export type HookOutcome = 'wrote' | 'skipped' | 'notified' | 'error'; export type HookHost = 'claude-code' | 'codex' | 'unknown'; export interface HookOutcomeRecord { hook: string; at: string; host: HookHost; outcome: HookOutcome; reason?: string; entity?: string; run?: string; } export interface HookOutcomeFile { hooks: Record; } export declare const HOOK_OUTCOMES_FILENAME = "hook-outcomes.jsonl"; export declare const HOOK_OUTCOMES_PER_HOOK = 20; export declare const HOOK_OUTCOMES_NOT_TRIGGERED_PER_HOOK = 5; export declare function isTriggeredRecord(record: Pick): boolean; export declare const HOOK_OUTCOMES_ROTATE_BYTES: number; export declare function serializeHookOutcome(record: HookOutcomeRecord): string; export declare function trimHookOutcomeLines(raw: string, max?: number, maxBytes?: number): string; export declare const SILENT_HOOK_MIN_RUNS = 5; export declare const CAPTURE_HOOKS: readonly ["post-commit", "session-summary", "pre-compact", "pre-edit-recall", "user-prompt-intent", "decision-nudge", "guard-check", "session-start", "note-ingest", "remember-nudge", "handoff-capture", "stop-message-gate"]; export declare const FAIL_ELIGIBLE_HOOKS: readonly ["session-summary"]; export declare const SILENT_ELIGIBLE_HOOKS: readonly ["post-commit", "session-summary", "pre-compact", "handoff-capture"]; export declare const SKIP_REASONS: { readonly notBash: "not a Bash tool call"; readonly notGitCommit: "not a git commit command"; readonly commitLineMissing: "a git commit ran but printed no commit line"; readonly commitHeadBaseline: "recorded the repository HEAD baseline; no history was backfilled"; readonly commitHeadUnchanged: "a commit-like command completed but repository HEAD did not change"; readonly commitHeadUnresolvable: "a commit-like command ran but repository HEAD could not be resolved"; readonly alreadyCaptured: "this session was already captured"; readonly payloadTooLarge: "payload exceeded the stdin byte cap"; readonly toolNameAbsent: "tool_name absent in payload"; readonly notDecisionTool: "not a decision-shaped tool call"; readonly noSessionId: "no usable session_id in the payload"; readonly alreadyNudged: "already nudged for this tool in this session"; readonly noBashCommand: "no Bash command in the payload"; readonly noDatabaseForGuards: "no database yet — nothing to guard against"; readonly noGuardMatched: "no active guard matched this command"; readonly autoCaptureOff: "auto-capture is turned off"; readonly commitCwdAbsent: "data.cwd absent — cannot resolve project or repo"; readonly hashNotACommit: "the hash is not a commit in this repository"; readonly noSessionOrTranscript: "neither session_id nor transcript_path in the payload"; readonly emptyStdin: "empty stdin"; readonly cwdAbsent: "cwd absent in payload — cannot resolve project"; readonly projectLineNoCwd: "no usable session cwd — the project line was not shown"; readonly notAgenticLoop: "not an agentic loop"; readonly transcriptPathAbsent: "transcript_path absent"; readonly transcriptGone: "the transcript file named by the payload is gone"; readonly tooLittleActivity: "too little activity in the session to be worth saving"; readonly noRuleMatched: "no rule matched (no edited file and fewer than 20 tool calls)"; readonly allMatchedEntitiesArchived: "every rule that matched targeted an entity the user forget-archived"; readonly toolInputAbsent: "tool_input absent in payload"; readonly noFilePath: "no file_path in the tool input"; readonly noDatabaseForRecall: "no database yet — nothing to recall"; readonly nothingToRecall: "no guard matched and nothing to recall for this file"; readonly recallThrottled: "no guard matched and recall for this file is throttled: this session already looked at it"; readonly candidateWindowTruncated: "more candidates may exist than the search window examined"; readonly noPromptIntent: "the prompt carried no remember intent and no update decision"; readonly noMemoryDir: "no Claude Code memory directory for this project"; readonly noNoteChanged: "no note file changed since the last ingestion"; readonly noteIngesterNotBuilt: "the note ingester is not built (dist/core/note-ingest.js is missing)"; readonly noteNothingNew: "note files were read and nothing new needed storing"; readonly noteFilesRefused: "note files were refused and nothing was stored"; readonly noTranscript: "no transcript to read"; readonly trivialTurn: "trivial turn — too few tool calls since the last Stop"; readonly noDecisionMove: "no decision-shaped move since the last Stop"; readonly memoryWritten: "a memory was written since the last Stop"; readonly noteFileChanged: "a note file changed since the last Stop"; readonly noAssistantText: "the Stop payload and the transcript held no assistant message"; readonly handoffTooShort: "the last assistant message was too short to be a handoff — the previous one is kept"; readonly handoffArchived: "the handoff memory was archived by forget — left alone"; readonly notClaudeCodeHost: "this Stop is not running under Claude Code"; readonly noRecipientForGate: "no recipient could be resolved for this session"; readonly noDatabaseForMessageGate: "no database yet — nothing to check for waiting messages"; readonly nothingWaitingForGate: "no messages are waiting for the resolved recipient"; readonly alreadyBlockedForGate: "every waiting message id was already blocked for in this session"; readonly sessionLauncherNotFound: "session_launcher_not_found: no claude process found above this hook (no ps, or not under Claude Code)"; readonly sessionLauncherSubagent: "session_launcher_subagent: a subagent SessionStart does not change its session mapping"; readonly sessionLauncherNoDatabase: "session_launcher_no_database: no database file yet — this session is not recorded for its claude process"; readonly clearAliasNoPrevious: "clear_alias_no_previous: no earlier session recorded for this claude process"; readonly clearAliasPidReused: "clear_alias_pid_reused: the recorded process had the same pid but a different start time"; readonly clearAliasAlreadyLinked: "clear_alias_already_linked: one of these session ids is already aliased"; readonly clearAliasNoTable: "clear_alias_no_table: the database has no alias tables yet (not migrated)"; readonly clearAliasInvalidInput: "clear_alias_invalid_input: no usable session_id in the SessionStart payload"; }; export declare const UNRECOGNISED_REASON = "unrecognised reason"; export declare function renderableSkipReason(reason: string | undefined): string; export declare function isGitCommitCommand(command: string): boolean; export declare const NOT_TRIGGERED_SKIP_REASONS: Readonly>; export declare const UNCLASSIFIED_SKIP_HOOKS: readonly ["pre-compact", "pre-edit-recall", "user-prompt-intent", "decision-nudge", "guard-check", "session-start", "stop-message-gate"]; export declare const NEVER_RAN_GRACE_HOURS = 72; export declare function parseHookOutcomes(raw: string | null | undefined, limit?: number): HookOutcomeFile; export declare function parseHookOutcomeLine(line: string): HookOutcomeRecord | null; export declare const RECORD_TEXT_MAX = 200; export declare function sanitizeRecordText(text: string): string; export interface HookLivenessSummary { hook: string; runs: number; triggeredRuns: number; writes: number; skips: number; errors: number; lastRunAt: string | null; firstTriggeredAt: string | null; lastWriteAt: string | null; lastEntity: string | null; notifies: number; lastNotifiedAt: string | null; lastSkipReason: string | null; dominantSkipReason: string | null; dominantSkipCount: number; lastErrorAt: string | null; lastErrorReason: string | null; recentErrors: number; hosts: HookHost[]; silent: boolean; } export declare function summarizeHookOutcomes(file: HookOutcomeFile): HookLivenessSummary[]; export declare function renderableErrorReason(reason: string | undefined): string; export declare const RECENT_ERROR_RUNS = 5; export interface TypeTrend { type: string; last7: number; prev7: number; stopped: boolean; } export declare function summarizeTypeTrends(rows: Array<{ type: string; last7: number; prev7: number; }>): TypeTrend[]; export type CaptureLivenessStatus = 'PASS' | 'PASS_WITH_CONCERNS' | 'FAIL'; export interface CaptureLivenessInput { hooks: HookLivenessSummary[]; types: TypeTrend[]; neverRanHooks?: string[]; measuringHours?: number | null; } export interface CaptureLivenessVerdict { status: CaptureLivenessStatus; silentHook: HookLivenessSummary | null; erroringHook: HookLivenessSummary | null; stoppedTypes: TypeTrend[]; deadHooks: string[]; } export declare function captureLivenessVerdict(input: CaptureLivenessInput): CaptureLivenessVerdict; export declare function captureLivenessNotice(verdict: CaptureLivenessVerdict): string | null; export declare const GRACE_SESSIONS = 3; export declare const GRACE_HOURS = 24; export interface CaptureGraceState { version: string; firstSeenAt: string; sessions: number; } export declare function parseGraceState(raw: string | null | undefined): CaptureGraceState | null; export declare function advanceGraceState(previous: CaptureGraceState | null, version: string, nowMs: number): CaptureGraceState; export declare function graceInEffect(state: CaptureGraceState, nowMs: number): boolean; export declare function detectHookHost(payload: Record | null | undefined, env?: Record, options?: { pluginRootIsHookRoot?: boolean; }): HookHost; //# sourceMappingURL=capture-liveness.d.ts.map