/** * Which published generations a LIVE run may still be reading (design v3 DECISION 1: "old * generations are reaped only after no live session references them"). * * The engine resolves `WICKED_SKILLS_SNAPSHOT` at every worker spawn and reports the generation it * ADMITTED as a `skillsSnapshotHanded` CoreEvent ({session, gen, …}) — the authoritative record of * which generation each session's spawn was actually handed. Crew keeps TWO kinds of pin: * * session pins a session is tracked from its first event; a `skillsSnapshotHanded` pins the * EXACT generation the engine reports (its `gen` field), never "whatever `current` * happens to be when crew observes some later event" (codex round 3); every * generation published WHILE the session is live is pinned to it too — its next * unit spawn reads (and will report) the new `current`; the terminal frame * (`sessionCompleted` / `sessionFailed` / `runCancelled` — the same triple * api/seat-health.ts drops assignments on) releases every pin the session held. * * launch pins EXPLICIT ACCOUNTING for the gap between a launch and the engine's report. When * the daemon hands a launch to the engine (`CoreAdapter.onLaunch`: launchRun, * resumeRun, confirmGate, launchCampaign, resumeCampaign — every path a spawn can * come from; the campaign's own DAG-node runs are pinned as the engine announces * them, `campaignNodeStarted`, under the campaign's umbrella pin), crew opens a pin * for that launch holding the generation the env exports RIGHT NOW, and every * generation published after that is added to it (the spawn may read any of them). * A launch pin is ACCOUNTED FOR when the engine reports a handoff for that session * (`skillsSnapshotHanded`): every generation it holds FOLDS INTO the session pin, * which the terminal frame releases — nothing the launch could have read is let go * early, because the report speaks for ONE spawn, not the run: a launcher-only seat * (wicked-core #499: codex/agy work units, chat seats) never reports at all, and a * unit of the same run may still be reading the launch-time generation (crew#577). * A launch pin is RELEASED only when the run/campaign reaches a terminal state, or * when the engine REJECTED the launch (nothing will ever read it). It never expires * by publish count or age (codex round 4: a bounded window let a run's generation be * reaped while its handoff report was still outstanding — publish count bounds * nothing about handoff delay). Reaping skips any generation with an open launch pin. * * The ledger is in-memory: the engine is in-process, so a daemon restart ends every worker it * spawned, and a resumed run's launch (`resumeRun`) opens a fresh launch pin. */ import type { CoreEvent } from '../core/types.js'; export type LiveGenerationObservation = 'pinned' | 'released' | 'ignored'; /** What the daemon hands the engine: a run (launch / resume / gate answer) or a campaign. */ export type LaunchKind = 'run' | 'campaign'; export declare class LiveGenerations { /** Session pins: session id → the generations the engine reported + every one published since. */ private readonly sessions; /** Launch pins: `run:` / `campaign:` → the generations the launch may read, until it is accounted for. */ private readonly launchPins; /** The generation the env exports right now (`exported`), or `null` when none is (fallback / unpublished). */ private exportedGen; private static key; /** * Fold one CoreEvent: track a live session, pin the EXACT generation the engine reports on a * `skillsSnapshotHanded` (folding that session's launch pin into the session pin — the engine has * accounted for the launch; nothing it held is released before the terminal frame, crew#577), * release on a terminal frame; pin a campaign's node run as the engine announces it and * release the campaign's pin on its terminal frame. A non-`skillsSnapshotHanded` session event * only tracks the session — it never pins "current at event time" (the bug codex round 3 * replaced): the generation a spawn actually used comes from the engine's own report, and the * pre-report window is covered by the launch pin. */ observe(event: CoreEvent): LiveGenerationObservation; /** * The env now exports generation `gen` to new launches (`WICKED_SKILLS_SNAPSHOT`; * runtime.afterPublish), or nothing (`null`). A launch pin opened after this starts from it. */ exported(gen: number | null): void; /** * The daemon is handing a launch to the engine (before the engine call, so no spawn can read the * env ahead of the pin): open its launch pin at the generation the env exports right now. The pin * accumulates every later publish (`published`); the engine's report for that session folds it into * the session pin, and only the run's / campaign's terminal frame or `launchRejected` releases it. */ launched(kind: LaunchKind, id: string): void; /** The engine REFUSED the launch (the call rejected): nothing will read it — release its pin. */ launchRejected(kind: LaunchKind, id: string): void; /** A generation was just published: every live session and every open launch may read it at its next spawn. */ published(gen: number): void; /** The union of every live session's pins and every open launch pin — what the reaper must keep. */ pinned(): ReadonlySet; /** Live sessions being tracked (diagnostics + tests). */ liveSessions(): string[]; /** Launches handed to the engine and not yet accounted for (`run:` / `campaign:`; diagnostics + tests). */ openLaunches(): string[]; } //# sourceMappingURL=live-generations.d.ts.map