/** * Where autopilot keeps its state, and the lock that keeps two passes from * overlapping (autopilot-driver/AC-19, autopilot-on-demand). * * Everything lives under `/aidlc/autopilot/`, beside the claims * and the registry: shared by every worktree, inside no working tree, so nothing * here can be committed by accident. * * @module */ import type { CodexProgress, SessionEnd } from './result.js'; import type { PausePhase, StopAt, Stops } from './stops.js'; import type { Harness } from './typed.js'; /** A lock older than this belongs to a pass that died. */ export declare const STALE_LOCK_MS: number; export interface AutopilotPaths { dir: string; state: string; config: string; stop: string; lock: string; logs: string; run: string; /** The pids `aidlc autopilot pause` froze; present only while paused. */ paused: string; } /** * `awaiting-review` and `awaiting-merge` wait for a person; `approved` is the pass * after an approval, which decides what comes next (autopilot-stop-controls/AC-13, * AC-18, AC-19). */ export type ItemStep = 'building' | 'pr-open' | 'queued' | 'awaiting-review' | 'approved' | 'awaiting-merge' | 'error'; export type ResumeStep = Exclude; /** * The checks on an item's pull request, as the driver last read them (autopilot-live-progress/AC-13). * `untested`: they failed without running a test, and wait on a runner * (ci-infra-failure-reads-as-code-failure/AC-6). */ export type CiState = 'waiting' | 'pending' | 'passed' | 'failed' | 'untested'; /** * A launch that asked for a typed result, recorded on the item so that a pass in any * process reads that launch's result — not only the one that spawned it * (autopilot-reads-agent-result/AC-32). */ export interface TypedLaunch { harness: Harness; /** When it was launched. */ at: string; /** The cap its budget was worked out from; absent when none was set (AC-7, AC-17). */ cap_usd?: number; /** The token cap in force at launch; absent when the cap was in dollars or unset (cost-in-tokens/AC-14). */ cap_tokens?: number; /** Where this launch's output starts in `logs/.log`. */ log_offset: number; /** Codex: the `-o` file, emptied before the launch so an earlier result cannot be read as this one's (AC-6). */ outcome_file?: string; /** Codex: the next byte of the log no pass has folded yet, and what was folded. */ read_offset?: number; progress?: CodexProgress; /** Codex: the model once read, and when to look for the thread's rollout — its first launch. */ model?: string; rollout_at?: string; /** Codex: rollout lookups so far; three, then the launch is unpriced (design D10). */ model_lookups?: number; /** The session id this launch resumed (AC-27). */ resumes?: string; /** Absent: not read yet. null: read, and nothing readable (AC-15). */ end?: SessionEnd | null; } /** * A session waiting to be resumed (autopilot-reads-agent-result/AC-23, AC-24, AC-26). An * `ended-early` session ended before the release boundary with no stop autopilot honours * (unattended-agent-ends-turn-to-wait/AC-3). */ export interface ResumeWait { kind: 'session-limit' | 'connection' | 'ended-early'; /** For a dropped connection or an early ending, the pass that decided it: the resume is the next pass. */ until: string; /** Checked against UUID_RE again where it is used: this file can be edited by hand. */ session: string; } export interface AutopilotItem { name: string; file: string; worktree: string; branch: string; step: ItemStep; ci_failures: number; pr: number | null; pid: number | null; /** When `pid` was spawned. `pause` matches it against the process's start, since pids are reused. */ pid_started_at?: string; /** `pid`'s identity read at spawn, on a clock that survives sleep and clock steps (see autopilot/pause.ts). */ pid_key?: number; pid_boot?: string | null; pid_ns?: string | null; started_at?: string; error?: string; /** Agent relaunches spent resolving conflicts with main (autopilot-merge-lane-stalls-on-conflicts/AC-11). */ conflict_fixes?: number; /** * The step `aidlc autopilot run` returns an errored item to. Absent means the * failure is not resumable: it came at or after the merge (AC-14, AC-16). */ resume_step?: ResumeStep; /** * The stops in force when the item started. Absent means it started before stops * existed, and it keeps the behaviour it started with (autopilot-stop-controls/AC-6). */ stops?: Stops; /** Paused phases a person has approved. */ approved?: PausePhase[]; /** * The approvals given through `aidlc autopilot answer` in the watching session, with who * gave each and when; an approval at a terminal leaves no entry here. */ approved_via_watcher?: { phase: PausePhase; by: string; at: string; }[]; /** * Paused phases passed with no person, because each left nothing open. Kept apart from * `approved`, which only a person writes (pause-only-on-open-decisions/AC-10). */ skipped_pauses?: PausePhase[]; /** The phase an `awaiting-review` or `approved` item stopped after. */ review?: PausePhase; /** * The step the item was in when last seen to change, and when. Absent on an item that * has not moved since this was recorded, so the view never counts from an upgrade * (autopilot-live-progress/AC-11). */ step_since?: { step: ItemStep; at: string; }; /** The last thing the driver said about the item, first said at `at` (autopilot-live-progress/AC-12). */ last_event?: { at: string; text: string; }; ci?: CiState; bump?: string; version?: string; /** The last launch, while its result can still decide. Absent: handled as before (AC-31). */ launch?: TypedLaunch; /** What the item's typed sessions cost, in micro-USD; absent is 0 (AC-19). */ spent_micro_usd?: number; /** Each session's last recorded cost, so a resumed session adds only its increase (AC-19). */ session_costs?: Record; /** Tokens the item's typed sessions used; absent is 0 (cost-in-tokens/AC-18). */ spent_tokens?: number; /** Each session's last recorded tokens, so a resumed session adds only its increase (cost-in-tokens/AC-18). */ session_tokens?: Record; resume_wait?: ResumeWait; /** Said once for the item that its Codex usage cannot be priced (AC-21). */ unpriced_noted?: boolean; } export interface AutopilotState { items: AutopilotItem[]; queue: string[]; backoff_until: string | null; backoff_ms: number; last_tick: string | null; } export interface AutopilotConfig { /** argv; the literal element `{prompt}` is replaced by the prompt. No default. */ agent_command?: string[]; agent_platform?: string; max_parallel?: number; cost_cap_usd?: number | null; /** Whole tokens per item; null = no cap. Wins over `cost_cap_usd` in the same config (cost-in-tokens/AC-12). */ cost_cap_tokens?: number | null; template?: string; /** argv run after merge and pull, from the primary checkout. Absent = merge only. */ release_command?: string[] | null; /** The last step autopilot takes. Absent = `release`, as before (autopilot-stop-controls/AC-3). */ stop_at?: StopAt; /** Phases to pause after for review. Absent = none, as before. */ pause_after?: PausePhase[]; /** Desktop notifications from a background run. Absent = on (autopilot-live-progress/AC-23). */ notify?: boolean; } /** One background run (autopilot-on-demand/AC-1..AC-4). */ export interface RunRecord { pid: number; started_at: string; /** null = `--all`. */ limit: number | null; /** Names of the items this run started, in order. */ started: string[]; /** Names of those items that have left the driver (released or held). */ finished: string[]; log: string; /** The driver's own identity, as `pid_key`/`pid_boot`/`pid_ns` on an item. */ pid_key?: number; pid_boot?: string | null; pid_ns?: string | null; } export declare function autopilotDir(cwd: string): string | null; export declare function autopilotPaths(dir: string): AutopilotPaths; export declare function emptyState(): AutopilotState; export declare function loadState(p: AutopilotPaths): AutopilotState; export declare function saveState(p: AutopilotPaths, state: AutopilotState): void; /** * The machine config, with a retired preset command read as its replacement. Every * reader comes through here, so the driver, setup and init see the same command; the * file itself changes only when one of those next saves it (codex-preset-removed-flag/AC-4, AC-13). */ export declare function loadConfig(p: AutopilotPaths): AutopilotConfig | null; export declare function saveConfig(p: AutopilotPaths, config: AutopilotConfig): void; export declare function loadRun(p: AutopilotPaths): RunRecord | null; export declare function saveRun(p: AutopilotPaths, run: RunRecord): void; export declare function clearRun(p: AutopilotPaths): void; /** * Run `fn` holding the lock, or return `{ locked: true }` without running it. * `mkdir` is the exclusive create: it fails when the directory exists. */ export declare function withLock(p: AutopilotPaths, now: () => number, fn: () => T): { locked: true; } | { locked: false; value: T; }; //# sourceMappingURL=state.d.ts.map