export type Outcome = 'accept' | 'correct' | 'error' | 'unknown'; export type Attribution = 'explicit' | 'window' | 'session_end' | 'default'; /** * One inject → outcome event. Written append-only to * ~/.forgen/state/outcomes/{session_id}.jsonl. The pending state (inject * happened, outcome not yet decided) is stored separately in * ~/.forgen/state/outcome-pending-{session_id}.json. */ export interface OutcomeEvent { ts: number; session_id: string; solution: string; match_score: number; injected_chars: number; outcome: Outcome; outcome_lag_ms: number; attribution: Attribution; } /** * Record that solutions were injected. Called from solution-injector right * after `approveWithContext` is emitted. Fails silently — outcome tracking * must never block the user's workflow. */ export declare function appendPending(sessionId: string, injections: Array<{ solution: string; match_score: number; injected_chars: number; }>): void; /** * Flush pending injections as `accept` events. Called when a new user * prompt arrives without any intervening correction/error, signaling that * the previous injections were silently accepted. "Silence = consent." * * If `excludeSolutions` is provided, those solutions are NOT flushed (e.g. * because an earlier step already attributed them as `correct` or `error`). */ export declare function flushAccept(sessionId: string, excludeSolutions?: Set): number; /** * Attribute a correction to the most recent pending injection(s). Called * from the correction-record MCP tool. Removes attributed entries from * pending so subsequent `flushAccept` does not double-count them. * * Strategy: all currently-pending solutions in this session are marked as * `correct`. This is conservative (the correction may target only one of * them), but without semantic attribution we err on the side of the user's * feedback signal being louder than acceptance. */ export declare function attributeCorrection(sessionId: string): string[]; /** * Attribute a tool error to pending solutions in this session. Called from * post-tool-failure hook. Unlike corrections, errors do not clear pending * — an error is a weaker signal and the next user prompt can still produce * a correct/accept decision. * * Only the top-K most-relevant, recent, above-threshold pending solutions * are attributed (see gates above). Below-threshold or stale pending * entries are left untouched — they will resolve via accept/unknown later. * * To avoid flooding the log with duplicate errors for the same pending * batch, we cap at one `error` event per (session, solution) pair per * pending-cycle by tracking a `error_flagged` set in the pending state. */ export declare function attributeError(sessionId: string): string[]; /** * At session end, any still-pending entries are logged as `unknown` (we * can't tell if the user was happy or just stopped). Pending file is * removed. */ export declare function finalizeSession(sessionId: string): number; /** * Read all outcome events across all sessions. Used by fitness * calculation. Returns events sorted by timestamp ascending. */ export declare function readAllOutcomes(): OutcomeEvent[];