/** * Directories a project keeps skills in, in probe order. * * Duplicated from `detectFormat`'s `isUnderSkillsDir` * (`packages/projections/src/detect-format.ts`) for the same reason as * `DEFAULT_RUNS_DIR` above — importing `@auden.to/projections` here would put * a package on the per-tool-call path for two string constants. * `hook-logger.test.ts` pins both against `detectFormat` so a root this probes * but discovery does not recognize (or vice versa) fails a test rather than * silently producing a skill path that matches no guide. * * `.claude/skills` first: it is where Claude Code itself resolves a `Skill` * call from, so when both roots hold a same-named skill it is the one that was * actually loaded. */ export declare const SKILL_ROOTS: readonly [".claude/skills", ".agents/skills"]; /** * Whether a tool call succeeded, as written into the run log. * * Declared here rather than imported from `@auden.to/protocol` for the same * reason as `ActionEntry` below; `hook-logger.test.ts` pins it against * `ActionOutcomeSchema`. */ export type ActionOutcome = { status: 'ok' | 'error'; errorClass?: string; exitCode?: number; }; /** * One logged agent action, as written to `~/.auden/runs/.jsonl`. * * Declared here rather than imported from `@auden.to/protocol` for the same * reason as `DEFAULT_RUNS_DIR` above — this module's import graph is the * per-tool-call latency budget. `hook-logger.test.ts` pins it against * `ActionEntrySchema` so the two cannot drift apart silently. */ export type ActionEntry = { /** Stable id + transcript correlation key; see `ActionEntrySchema`. */ id: string; timestamp: string; sessionId: string; toolName: string; filePath?: string; command?: string; /** Set only for a `Skill` call; see `ActionSkillLoadSchema`. */ skill?: { name: string; path?: string; }; /** This machine's transcript for the session; see `ActionEntrySchema.transcriptPath`. */ transcriptPath?: string; /** Checkout digest; see `ActionEntrySchema.repoId`. */ repoId?: string; /** Set only when the response shape was recognized; see `extractActionOutcome`. */ outcome?: ActionOutcome; }; /** * Read whether the tool call succeeded out of the hook event's `tool_response`. * * The hook has always parsed `tool_input` and thrown away the `tool_response` * sitting beside it, so a failed edit and a successful one reached the run * grader as the same line and the grader scored work that never happened * (docs/plans/action-evidence-sync-plan.md — the outcome-metadata slice). * * **Recognized shapes only; an unrecognized one yields `undefined`, not `ok`.** * There is no cross-tool response contract to lean on — Claude Code's `Bash`, * `Edit` and `Read` each answer with a different object, an MCP tool answers * with its own, and Codex's `post_tool_use` differs again — so this probes for * fields whose *name* carries the fact and declines to guess otherwise. That is * `buildActionEntry`'s existing degrade-to-`unknown` discipline applied to a * field where guessing is worse than silence: the grader weighs what it is * told, and "this action succeeded" asserted from an unread shape would be a * fabricated fact about the user's session. * * Error signals beat success signals rather than last-write-wins, so a response * carrying both (`{ exit_code: 0, is_error: true }`) records the failure. * * Deliberately **not** captured: the error *message*, stderr, or command * output. Those are content — free text that can quote file contents or * third-party data, which `sanitizeCommand` does not redact because it targets * shell syntax — and they stay behind `content-sync-privacy` with narration. * A status, a machine-shaped class and an exit code are metadata, which is why * this slice is unblocked while the rest of Phase 2 is not. */ export declare function extractActionOutcome(response: unknown): ActionOutcome | undefined; /** * Read whether the tool call succeeded out of a `PostToolUseFailure` event. * * This event carries no `tool_response` — captured live from a Claude Code * session (`hook-failure-event-registration`), its payload is `{ tool_name, * tool_input, error, is_interrupt, duration_ms, ... }` for a shell exit, an * `ls` on a missing path, and an MCP tool's own error alike, so one probe * covers every tool kind. The event's own name already settles `status` — * nothing here is inferred, unlike `extractActionOutcome`'s reading of an * ambiguous response shape. `is_interrupt` maps to the same `errorClass: * 'interrupted'` that function derives from a response's own `interrupted` * flag, so both paths describe an interrupted call the same way downstream. * * `error` (the failure message) is deliberately not captured, for the same * reason `extractActionOutcome` never turns a message into an `errorClass`: it * is free text that can quote file contents or third-party data, and stays * behind `content-sync-privacy` with narration. */ export declare function extractFailureOutcome(event: Record): ActionOutcome; /** * Build a log entry from a hook event payload. * * Reads `session_id`, `tool_name` and `tool_input` — the three fields every * Claude-style hook protocol agrees on, which is what lets one binary serve * Claude Code's PostToolUse and Codex's post_tool_use without an adapter — plus * `cwd`, used only to qualify a skill load and falling back to `process.cwd()` * for a protocol that omits it, and the call's outcome. A `PostToolUseFailure` * event (`hook_event_name`) carries no `tool_response` — its failure is read * from `error`/`is_interrupt` instead (`extractFailureOutcome`) — while every * other event's outcome comes from `tool_response`, and only when its shape is * recognized (`extractActionOutcome`). Unknown shapes degrade to `unknown` * rather than throwing: a hook that errors is a hook that interrupts the * agent. */ export declare function buildActionEntry(raw: string, timestamp: string, options?: { homedir?: string; }): ActionEntry | null; /** * Append an entry to its session's run log, creating the runs directory if * needed. Synchronous because the process exits immediately afterwards. */ export declare function appendActionEntry(entry: ActionEntry, runsDir?: string): void; //# sourceMappingURL=hook-logger.d.ts.map