/** * `openlore hook ` (change: add-agent-loop-hook-surfaces). * * One command per moment of the agent loop, wired by `openlore install` into the harness's hook * events, so the agent receives OpenLore's deterministic receipts without having to call a tool: * * | Moment | Claude Code event | Receipt | * |---------------|------------------------------|-------------------------------------------------------------| * | `before-edit` | `PreToolUse` (edit tools) | the target is a generated file: its source and command | * | `after-tools` | `PostToolUse` (edit tools) | the edit recorded for the session ledger; new ledger facts; | * | | | generated-file, phantom-reference and check-weakening facts | * | | | for the edited file | * | `before-stop` | `Stop` | the `verify_change` receipt for the session's diff, shown | * | | | to the user; the agent sees it only as a policy block | * | `after-compact` | `SessionStart` (`compact`) | the handoff briefing of the in-flight change | * | `before-subagent` | `PreToolUse` (`Agent|Task`) | nothing: queues the sub-agent's task | * | `subagent-start` | `SubagentStart` | the sub-agent's task-scoped briefing and the board's peers | * * Every hook reads the harness payload from stdin and prints at most one budgeted receipt as the * event's `additionalContext`; it prints nothing when it has nothing new. A fact already delivered * under the payload's `session_id` is not repeated. Hooks are advisory: they exit 0, and on a * timeout or an error they print nothing. Only a finding code the repository's `enforcement.policy` * makes blocking can block, and only at `before-stop`. A moment is turned off with * `hooks.: false` in `.openlore/config.json`. */ import { Command } from 'commander'; export declare const HOOK_MOMENTS: readonly ["before-edit", "after-tools", "before-stop", "after-compact", "before-subagent", "subagent-start"]; export type HookMoment = typeof HOOK_MOMENTS[number]; /** The harness event each moment is wired to (Claude Code). */ export declare const HOOK_EVENT: Record; /** One fact for the receipt. `key` identifies it for the per-session dedupe. */ export interface HookItem { key: string; severity: string; text: string; next?: string; } export interface HookPayload { sessionId?: string; cwd?: string; toolName?: string; /** Files the tool call writes, as given (absolute or relative). */ files: string[]; /** The shell command of a shell tool call, and its exit status when the payload carries one. */ command?: string; exit?: number; /** The shell call was interrupted before it finished. */ interrupted?: boolean; stopHookActive: boolean; /** An Agent/Task tool call: the sub-agent's task and type. */ agentPrompt?: string; subagentType?: string; /** A SubagentStart event: the starting sub-agent's type. */ agentType?: string; /** An edit tool call's pending change: Write's content, or Edit/MultiEdit's replacements. */ edit?: { content?: string; edits?: Array<{ oldString: string; newString: string; replaceAll: boolean; }>; }; } /** Read the fields OpenLore uses from a harness hook payload (Claude Code's shape). */ export declare function parseHookPayload(raw: string): HookPayload; /** The files a Codex `apply_patch` patch adds, updates, deletes, or moves to, in order, once each. */ export declare function patchFiles(patch: string): string[]; /** * The text a pending edit would produce from `current` (null: the file does not exist), or undefined * when it cannot be told exactly — an old string that is absent or (without replace-all) not unique, * as the edit tool itself would refuse it. */ export declare function applyPendingEdit(current: string | null, edit: NonNullable): string | undefined; /** * A payload path as a root-relative path with forward slashes, or `undefined` when it is outside * the repository. The file need not exist yet (a `Write` of a new file). */ export declare function repoPath(root: string, file: string): string | undefined; /** Keep the most severe items within the budget; the rest are counted. */ export declare function renderReceipt(moment: HookMoment, items: HookItem[], budgetChars?: number): string | null; export interface HookRunResult { stdout: string; exitCode: 0; } /** * Run one moment over a payload, then SCREEN the result. * * Never throws and always exits 0: a timeout or an error prints nothing. Exported for tests; the * CLI prints `stdout`. * * Screening happens here rather than in each moment, because every moment's payload is * repository-derived text going straight into model context and only `subagent-start` screened its * own. The class only removes characters inside the JSON's string literals, so the harness still * parses exactly one object. */ export declare function runHook(moment: HookMoment, raw: string, opts?: { cwd?: string; timeoutMs?: number; }): Promise; export declare const hookCommand: Command; //# sourceMappingURL=hook.d.ts.map