/** * Turn origin — records turns the harness did not start, and agent actions * taken outside any trace. * * Why (2026-10-03): text that predicted the owner's next message was * submitted in an agent's input without any harness delivery. The agent * treated it as the owner's approval and posted on LinkedIn as the owner. * That turn, and the browser actions it took, appeared in no trace. * * Two things are recorded: * * - `turn.unsolicited`: Claude Code's UserPromptSubmit hook fired, but the * harness typed nothing into the session since the last submitted prompt. * The text came from somewhere else (a pre-filled line, a prompt * suggestion, someone typing in the terminal). * - Agent browser actions (`skill.call` / `guard.block`) with what was done * and where — never typed text, only its length. * * Both go to the session's current trace, else its last known trace, else a * new `unsolicited` trace, so they are never untraced. * * @module services/trace/turn-origin */ import type { TraceOutcome } from './trace.types.js'; /** * A harness write older than this no longer vouches for a submit: a paste * whose Enter was lost and never taken must not mask a later prompt typed * by someone else. */ export declare const PENDING_WRITE_TTL_MS: number; /** * The harness is about to submit text into a session's input (called by the * guarded writer before it presses Enter). * * @param session - Agent session */ export declare function noteHarnessWrite(session: string, now?: number): void; /** * A prompt was submitted in the session (Claude Code UserPromptSubmit hook). * When the harness typed nothing since the last submitted prompt, the turn * was not started by a harness delivery: record `turn.unsolicited`. * * One submit consumes ONE pending write, oldest first. It used to consume * every pending write: Claude Code queues each harness paste that lands * mid-turn as its own prompt and submits them one by one when the turn ends, * so the second and later ones were flagged unsolicited (21 times on * 2026-10-22, Pia alone 12; crewly#1431). Writes expire after * {@link PENDING_WRITE_TTL_MS} so a lost paste never vouches for a prompt * typed much later by someone else. * * @param session - Agent session * @param now - Clock (tests) * @returns True when the turn was unsolicited (and recorded) */ export declare function notePromptSubmitted(session: string, now?: number): boolean; /** An agent browser action, as recorded in a trace. */ export interface BrowserActionTrace { /** Agent session */ session: string; /** Browser tool */ tool: string; /** Tool params (only names and lengths are recorded, never typed text) */ params?: Record; /** Page URL, when known */ url?: string; /** What happened: ok, failed, or blocked (held / refused) */ outcome: TraceOutcome; /** Why it was held or refused */ reason?: string; } /** * Record an agent browser action in the session's trace — always, starting * an `unsolicited` trace when the session has none. * * @param input - The action */ export declare function traceBrowserAction(input: BrowserActionTrace): void; /** * Forget all state (tests). */ export declare function resetTurnOriginForTesting(): void; //# sourceMappingURL=turn-origin.d.ts.map