/** * v3.1.2 Step 11 / final handoff — Size-fear ban. * * Refuses to emit a final handoff while a Job has remaining slices. * Closes the v3.1.0 incident pattern: LLM writes a fake-completion * message at high context-fill before Job mode kicks in. * * Decision tree: * - job-shape.json missing OR isJob === false → ALLOW (normal handoff) * - isJob === true, no state.json → JOB_NOT_INITIALIZED (LLM * skipped `peaks job init`) * - isJob === true, state.json, remaining > 0, * no --force-under-job → JOB_REMAINING_BLOCKED * - isJob === true, state.json, remaining > 0, * --force-under-job → ALLOW (override path) * - isJob === true, state.json, remaining === 0, * no session sediment, no --force-no-sediment → JOB_COMPLETED_NO_SEDIMENT * - isJob === true, state.json, remaining === 0, * session sediment OR --force-no-sediment → ALLOW (Job done) * * The sediment arm is the refusal point for Step 11: a completed Job whose * session put nothing into `.peaks/memory/` is refused, and an unanswerable * sediment question is refused too (fail closed). * * Karpathy §2 (Simplicity First): ~70 lines, no LLM call, no regex. * Pure read + arithmetic. The CLI wrapper in code-commands.ts * translates the verdict into exit code + JSON envelope. */ export declare const JOB_NOT_INITIALIZED: "JOB_NOT_INITIALIZED"; export declare const JOB_REMAINING_BLOCKED: "JOB_REMAINING_BLOCKED"; export declare const JOB_COMPLETED_NO_SEDIMENT: "JOB_COMPLETED_NO_SEDIMENT"; /** * What the memory index says about this session. * * `unknown` is a first-class answer, not an error code: it means the question * could not be put to peaks' own store at all, and the handoff refuses on it * rather than assuming the session sedimented nothing. */ export type SessionSedimentState = 'sedimented' | 'none' | 'unknown'; export type EmitHandoffVerdict = { readonly kind: 'allow-not-job'; } | { readonly kind: 'allow-done'; readonly remaining: number; } | { readonly kind: 'allow-force-override'; readonly remaining: number; } | { readonly kind: 'block-not-initialized'; readonly code: typeof JOB_NOT_INITIALIZED; readonly jobId: string; } | { readonly kind: 'block-remaining'; readonly code: typeof JOB_REMAINING_BLOCKED; readonly jobId: string; readonly remaining: number; } | { readonly kind: 'block-no-sediment'; readonly code: typeof JOB_COMPLETED_NO_SEDIMENT; readonly jobId: string; /** `none` = the index was read and holds no entry for this session. */ readonly sedimentState: Exclude; } | { readonly kind: 'allow-forced-no-sediment'; readonly remaining: number; /** The reason the user approved a no-sediment outcome. Never blank. */ readonly reason: string; readonly sedimentState: Exclude; }; export interface EvaluateEmitHandoffInput { readonly projectRoot: string; readonly sessionId: string; /** Suggested job id — read from job-shape.json when omitted. */ readonly jobId?: string; readonly forceUnderJob?: boolean; /** * The reason the user approved a no-sediment outcome. Present and non-blank * overrides the completed-Job no-sediment block; blank is treated as absent, * so an override nobody justified does not open the gate. */ readonly forceNoSedimentReason?: string; } export declare function evaluateEmitHandoff(input: EvaluateEmitHandoffInput): EmitHandoffVerdict;