tickmarkr 2.5.3 → 2.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/adapters/registry.js +6 -1
  2. package/dist/adapters/types.d.ts +3 -0
  3. package/dist/cli/commands/approve.d.ts +1 -0
  4. package/dist/cli/commands/approve.js +54 -6
  5. package/dist/cli/commands/doctor.d.ts +4 -0
  6. package/dist/cli/commands/doctor.js +44 -29
  7. package/dist/cli/commands/fleet.js +195 -33
  8. package/dist/cli/commands/init.js +196 -6
  9. package/dist/cli/commands/plan.js +144 -3
  10. package/dist/cli/commands/resume.js +6 -2
  11. package/dist/cli/commands/run.js +21 -2
  12. package/dist/cli/commands/verify.js +1 -1
  13. package/dist/cli/help.d.ts +2 -0
  14. package/dist/cli/help.js +3 -1
  15. package/dist/compile/collateral.d.ts +2 -0
  16. package/dist/compile/collateral.js +50 -9
  17. package/dist/compile/ownership.d.ts +7 -0
  18. package/dist/compile/ownership.js +59 -22
  19. package/dist/config/config.d.ts +23 -8
  20. package/dist/config/config.js +42 -28
  21. package/dist/config/fleet-overlay.d.ts +3 -9
  22. package/dist/config/fleet-overlay.js +68 -11
  23. package/dist/config/fleet-why.d.ts +7 -0
  24. package/dist/config/fleet-why.js +5 -0
  25. package/dist/drivers/herdr.d.ts +5 -0
  26. package/dist/drivers/herdr.js +14 -3
  27. package/dist/drivers/index.d.ts +15 -1
  28. package/dist/drivers/index.js +38 -10
  29. package/dist/drivers/orca.d.ts +99 -10
  30. package/dist/drivers/orca.js +586 -97
  31. package/dist/drivers/types.d.ts +1 -0
  32. package/dist/gates/baseline.d.ts +3 -0
  33. package/dist/gates/baseline.js +2 -1
  34. package/dist/gates/cache.d.ts +100 -0
  35. package/dist/gates/cache.js +389 -0
  36. package/dist/gates/review.d.ts +35 -2
  37. package/dist/gates/review.js +64 -16
  38. package/dist/gates/run-gates.d.ts +5 -0
  39. package/dist/gates/run-gates.js +134 -18
  40. package/dist/gates/test-manifest.d.ts +99 -0
  41. package/dist/gates/test-manifest.js +389 -0
  42. package/dist/gates/test-reporter.d.ts +4 -0
  43. package/dist/gates/test-reporter.js +49 -0
  44. package/dist/route/preference.d.ts +22 -1
  45. package/dist/route/preference.js +123 -25
  46. package/dist/route/router.d.ts +13 -0
  47. package/dist/route/router.js +95 -17
  48. package/dist/run/daemon.d.ts +13 -0
  49. package/dist/run/daemon.js +398 -96
  50. package/dist/run/git.d.ts +35 -1
  51. package/dist/run/git.js +111 -10
  52. package/dist/run/journal.d.ts +14 -2
  53. package/dist/run/journal.js +78 -10
  54. package/dist/run/lease.d.ts +14 -0
  55. package/dist/run/lease.js +87 -0
  56. package/dist/run/merge.d.ts +2 -0
  57. package/dist/run/merge.js +91 -3
  58. package/dist/run/operator-state.d.ts +11 -0
  59. package/dist/run/operator-state.js +17 -3
  60. package/dist/tui/cockpit/board.d.ts +96 -0
  61. package/dist/tui/cockpit/board.js +346 -0
  62. package/dist/tui/cockpit/decision-actions.js +2 -0
  63. package/dist/tui/cockpit/layout.d.ts +5 -1
  64. package/dist/tui/cockpit/layout.js +8 -3
  65. package/dist/tui/cockpit/live-runtime.js +83 -31
  66. package/dist/tui/cockpit/run-view.d.ts +7 -5
  67. package/dist/tui/cockpit/run-view.js +12 -11
  68. package/dist/tui/ink/fleet-app.d.ts +41 -27
  69. package/dist/tui/ink/fleet-app.js +204 -31
  70. package/package.json +1 -1
  71. package/skills/tickmarkr-overseer/SKILL.md +180 -99
@@ -6,7 +6,7 @@ import { declaredInputBoxForWorkerName, matchesEmptyInputBox, matchesInputBox, m
6
6
  import { consumePaneLaunchIntent, PANE_IDENTITY_ENV, paneIdentityLine } from "../brand.js";
7
7
  import { createWorktree, sh } from "../run/git.js";
8
8
  import { Journal } from "../run/journal.js";
9
- import { readSupervision, readWatchBoard, reserveWatchBoard, stopWatchBoard, WATCH_OWNER_ENV } from "../run/supervision.js";
9
+ import { readSupervision, readWatchBoard, requestWatchBoardStop, reserveWatchBoard, stopWatchBoard, WATCH_OWNER_ENV } from "../run/supervision.js";
10
10
  import { herdrSealShellPrefix } from "./subprocess.js";
11
11
  import { canonicalizeLegacyName, formatOwnedName, panesToClose, parseOwnedName } from "./types.js";
12
12
  // VIS-09 P43-03: adopted safety floor from 43-MEASUREMENT.md (narrowest safe 53 → floor 108).
@@ -1169,8 +1169,16 @@ export class HerdrDriver {
1169
1169
  throw new Error("herdr pane list returned no panes");
1170
1170
  return panes.filter(p => p.workspace_id === this.ws && p.label === name);
1171
1171
  }
1172
+ /** WB-1 (OBS-988): the daemon proved this run's own board lost. Forget the cached slot FIRST — even a
1173
+ * retire that fails must never let the narrator answer with the ghost again — then take the pane
1174
+ * back on ownership alone: the dead UI can never acknowledge, so the stop request is left for a
1175
+ * merely stuck one to find. Serialized with the narrator so no split races the close. */
1176
+ async retireLostWatch(slot) {
1177
+ this.watches.delete(slot.name);
1178
+ await this.serial(() => this.retireWatch(slot, true));
1179
+ }
1172
1180
  /** Name collisions never confer repository ownership. Unknown boards stay protected. */
1173
- async retireWatch(slot) {
1181
+ async retireWatch(slot, lost = false) {
1174
1182
  const runId = parseOwnedName(slot.name)?.runId;
1175
1183
  const owner = runId ? readWatchBoard(slot.cwd, runId) : undefined;
1176
1184
  const matches = await this.watchPanes(slot.name);
@@ -1181,7 +1189,10 @@ export class HerdrDriver {
1181
1189
  owner.pane !== slot.id || matches.length !== 1 || matches[0]?.pane_id !== owner.pane) {
1182
1190
  throw new Error(`watch ownership unknown or foreign for ${slot.name}; existing board protected`);
1183
1191
  }
1184
- await stopWatchBoard(owner, this.time);
1192
+ if (lost)
1193
+ requestWatchBoardStop(owner); // a lost owner never answers; only a live one still gets the ack window
1194
+ else
1195
+ await stopWatchBoard(owner, this.time);
1185
1196
  const verified = await this.watchPanes(slot.name);
1186
1197
  if (verified.length !== 1 || verified[0]?.pane_id !== owner.pane)
1187
1198
  throw new Error("watch target changed after acknowledgement; pane protected");
@@ -2,6 +2,20 @@ import type { TickmarkrConfig } from "../config/config.js";
2
2
  import type { ExecutorDriver } from "./types.js";
3
3
  export declare const DRIVER_CHOICES: readonly ["auto", "herdr", "subprocess", "orca"];
4
4
  export type DriverChoice = (typeof DRIVER_CHOICES)[number];
5
+ export type ClassifiedHost = "herdr" | "orca" | "none";
6
+ /**
7
+ * One host classifier beside the driver chooser reads the launching environment:
8
+ * herdr only when HERDR_ENV is exactly 1, orca only when both Orca markers are present,
9
+ * none otherwise. run and resume call it once at the refs-preflight point and thread the
10
+ * result into pickDriver; nothing downstream reads the markers again.
11
+ */
12
+ export declare function classifyHost(env?: NodeJS.ProcessEnv): ClassifiedHost;
13
+ /**
14
+ * A config driver of herdr or orca whose host is not the classified one is refused naming the
15
+ * detected host, the config line and the --driver remedy. Any explicit --driver value bypasses
16
+ * this; auto and subprocess are never refused.
17
+ */
18
+ export declare function preflightHostDriver(cfg: TickmarkrConfig, driverOverride: string | undefined, host: ClassifiedHost): void;
5
19
  /**
6
20
  * Orca authors both markers on every terminal it creates. Requiring the pair avoids treating an
7
21
  * unrelated TERM_PROGRAM value or a copied terminal handle as host identity. This is deliberately
@@ -11,4 +25,4 @@ export declare function orcaHostDetected(env?: NodeJS.ProcessEnv): boolean;
11
25
  /** Validate argv at the CLI boundary rather than casting an arbitrary string into a driver choice. */
12
26
  export declare function parseDriverOverride(override?: string): DriverChoice | undefined;
13
27
  export declare function driverEvidence(cfg: TickmarkrConfig, driver: ExecutorDriver, override?: string): string;
14
- export declare function pickDriver(cfg: TickmarkrConfig, override?: string): ExecutorDriver;
28
+ export declare function pickDriver(cfg: TickmarkrConfig, override?: string, host?: ClassifiedHost): ExecutorDriver;
@@ -3,13 +3,42 @@ import { OrcaDriver } from "./orca.js";
3
3
  import { SubprocessDriver } from "./subprocess.js";
4
4
  export const DRIVER_CHOICES = ["auto", "herdr", "subprocess", "orca"];
5
5
  const overrideByDriver = new WeakMap();
6
+ // The host snapshot the driver was selected under: driverEvidence reads this, never process.env,
7
+ // so preflight, selection and the journal row all describe the same instant.
8
+ const hostByDriver = new WeakMap();
9
+ /**
10
+ * One host classifier beside the driver chooser reads the launching environment:
11
+ * herdr only when HERDR_ENV is exactly 1, orca only when both Orca markers are present,
12
+ * none otherwise. run and resume call it once at the refs-preflight point and thread the
13
+ * result into pickDriver; nothing downstream reads the markers again.
14
+ */
15
+ export function classifyHost(env = process.env) {
16
+ if (env.HERDR_ENV === "1")
17
+ return "herdr";
18
+ if (env.TERM_PROGRAM === "Orca" && env.ORCA_TERMINAL_HANDLE !== undefined && env.ORCA_TERMINAL_HANDLE !== "")
19
+ return "orca";
20
+ return "none";
21
+ }
22
+ /**
23
+ * A config driver of herdr or orca whose host is not the classified one is refused naming the
24
+ * detected host, the config line and the --driver remedy. Any explicit --driver value bypasses
25
+ * this; auto and subprocess are never refused.
26
+ */
27
+ export function preflightHostDriver(cfg, driverOverride, host) {
28
+ if (driverOverride !== undefined)
29
+ return;
30
+ if ((cfg.driver === "herdr" || cfg.driver === "orca") && cfg.driver !== host) {
31
+ const remedy = host === "none" ? "subprocess" : host;
32
+ throw new Error(`refusing driver '${cfg.driver}' (config line 'driver: ${cfg.driver}'): detected host is ${host}; use --driver ${remedy} to override`);
33
+ }
34
+ }
6
35
  /**
7
36
  * Orca authors both markers on every terminal it creates. Requiring the pair avoids treating an
8
37
  * unrelated TERM_PROGRAM value or a copied terminal handle as host identity. This is deliberately
9
38
  * environment-only: selection must not execute a binary or contact the Orca runtime.
10
39
  */
11
40
  export function orcaHostDetected(env = process.env) {
12
- return env.TERM_PROGRAM === "Orca" && env.ORCA_TERMINAL_HANDLE !== undefined;
41
+ return classifyHost(env) === "orca";
13
42
  }
14
43
  /** Validate argv at the CLI boundary rather than casting an arbitrary string into a driver choice. */
15
44
  export function parseDriverOverride(override) {
@@ -27,18 +56,16 @@ export function driverEvidence(cfg, driver, override) {
27
56
  return `${driver.id} (--driver)`;
28
57
  if (want !== "auto")
29
58
  return `${driver.id} (config)`;
30
- const herdrAvailable = process.env.HERDR_ENV === "1";
31
- if (herdrAvailable && driver.id === "herdr")
59
+ const host = hostByDriver.get(driver);
60
+ if (host === "herdr" && driver.id === "herdr")
32
61
  return "auto → herdr (HERDR_ENV=1)";
33
- if (!herdrAvailable && orcaHostDetected() && driver.id === "orca") {
62
+ if (host === "orca" && driver.id === "orca")
34
63
  return "auto → orca (TERM_PROGRAM+ORCA_TERMINAL_HANDLE)";
35
- }
36
- if (!herdrAvailable && !orcaHostDetected() && driver.id === "subprocess") {
64
+ if (host === "none" && driver.id === "subprocess")
37
65
  return "auto → subprocess (HERDR_ENV unset)";
38
- }
39
66
  return `auto → ${driver.id} (runtime)`;
40
67
  }
41
- export function pickDriver(cfg, override) {
68
+ export function pickDriver(cfg, override, host = classifyHost()) {
42
69
  const selectedOverride = parseDriverOverride(override);
43
70
  const want = selectedOverride ?? cfg.driver;
44
71
  // VIS-09 item 2: plumb the per-tab cap into the HerdrDriver — the driver takes it as a constructor
@@ -49,10 +76,11 @@ export function pickDriver(cfg, override) {
49
76
  // Orca is an operator-selected execution surface. Its runtime failure stays on Orca; selection
50
77
  // must never substitute a hidden subprocess worker after an explicit or detected choice.
51
78
  : want === "orca" ? new OrcaDriver()
52
- : HerdrDriver.available() ? new HerdrDriver("herdr", cfg.visibility.workersPerTab)
53
- : orcaHostDetected() ? new OrcaDriver()
79
+ : host === "herdr" ? new HerdrDriver("herdr", cfg.visibility.workersPerTab)
80
+ : host === "orca" ? new OrcaDriver()
54
81
  : new SubprocessDriver();
55
82
  if (selectedOverride !== undefined)
56
83
  overrideByDriver.set(driver, selectedOverride);
84
+ hostByDriver.set(driver, host);
57
85
  return driver;
58
86
  }
@@ -1,8 +1,9 @@
1
1
  import { type ShResult } from "../run/git.js";
2
2
  import { type JournalEvent } from "../run/journal.js";
3
+ import { type WatchBoardOwner } from "../run/supervision.js";
3
4
  import { type ExecutorDriver, type FocusTarget, type FocusResult, type NotifyOpts, type Slot, type SlotOpts } from "./types.js";
4
5
  /** The response families the ONE shared envelope parser serves. There is no second JSON seam. */
5
- export declare const ORCA_RESPONSE_FAMILIES: readonly ["status", "create", "list", "read", "send", "wait", "show", "close", "worktree-current", "worktree-set", "hooks-status"];
6
+ export declare const ORCA_RESPONSE_FAMILIES: readonly ["status", "create", "list", "read", "send", "wait", "show", "close", "worktree-current", "worktree-set", "hooks-status", "split"];
6
7
  export type OrcaFamily = (typeof ORCA_RESPONSE_FAMILIES)[number];
7
8
  export declare const ORCA_FIXTURE_VERSION = "1.4.195";
8
9
  export declare const ORCA_CLI_COMMAND_ENV = "ORCA_CLI_COMMAND";
@@ -14,7 +15,6 @@ export declare const NOT_WRITABLE_CODE = "terminal_not_writable";
14
15
  /** The ONLY terminal status that licenses reading a terminal's bytes or its agent state. */
15
16
  export declare const RUNNING_STATUS = "running";
16
17
  export declare const STATUS_GOVERNED_METHODS: readonly ["read", "waitOutput", "status", "waitAgentStatus"];
17
- export declare const WORKTREE_ADOPTION_TIMEOUT_MS = 60000;
18
18
  /** A missing slot gets the same bounded chance to appear as a reaped shell gets to settle. */
19
19
  export declare const PENDING_PROJECT_GRACE_MS = 2000;
20
20
  export interface OrcaExec {
@@ -81,11 +81,62 @@ export declare function terminalWorktree(term: Record<string, unknown>): string
81
81
  * it keeps its resolved spelling: deterministic, and still comparable to another spelling of itself.
82
82
  */
83
83
  export declare function canonicalWorktreePath(path: string): string;
84
+ /** The proof line a worker terminal prints first: recovery and focus read it back (FX-N01). */
85
+ export declare const CHECKOUT_MARK = "TICKMARKR_CHECKOUT";
86
+ /** The exact bytes the create command prints as its first line. */
87
+ export declare function checkoutProofLine(checkout: string): string;
88
+ /** Every complete frame in a scrollback, decoded and canonicalized; whether an incomplete one was seen. */
89
+ export declare function checkoutFrames(text: string): {
90
+ complete: string[];
91
+ incomplete: boolean;
92
+ };
93
+ /** Does a scrollback prove exactly `checkout`: at least one complete frame equals it, no complete
94
+ * frame names anything else, and no frame is incomplete. Full-path equality after canonicalization —
95
+ * never a prefix, a substring, or a whitespace-terminated fragment. */
96
+ export declare function provesCheckout(text: string, checkout: string): boolean;
97
+ /**
98
+ * Everything a terminal on the tracked worktree runs before the payload: enter the checkout (a
99
+ * failed cd stops the whole line — nothing of the payload ever runs in the enclosing path), print
100
+ * the proof line, then hand the WHOLE payload to one `sh -c` so a background list, a `;` list or a
101
+ * subshell inside it all start in the checkout and its exit status is the payload's (FX-N02).
102
+ */
103
+ export declare function checkoutPrefix(checkout: string): string;
104
+ /** The command a terminal on the tracked worktree runs so that it executes INSIDE the checkout. */
105
+ export declare function inCheckout(checkout: string, cmd: string): string;
106
+ /** Every checkout the complete proof frames in a scrollback name, in order of appearance. */
107
+ export declare function checkoutsNamed(text: string): string[];
84
108
  /** Conservative agent-state mapping over orca's ACTUAL surfaces: `blocked` only when the show
85
109
  * record reports agentWait:true, `idle` only when the `terminal wait --for tui-idle` condition is
86
110
  * satisfied. The recorded 1.4.186 show response carries NO agent field at all — an absent signal
87
111
  * is "unknown", never a fabricated definite status. */
88
112
  export declare function mapAgentState(term: Record<string, unknown>, tuiIdle: boolean): string;
113
+ /**
114
+ * The Orca board owner record is the board's ONE lifecycle, and it lives on disk: every step below is
115
+ * decided from the file (plus Orca's own terminal table), so a fresh OrcaDriver — a restarted daemon —
116
+ * reaches the same answer as the instance that placed the board. No instance map or set carries it.
117
+ *
118
+ * reserved pane "", no claim narrator, create-only, before the split can read its token
119
+ * claimed pid + armId, pane "" observer (observeNamedRun), written exactly once
120
+ * bound claim + the receipt's handle and the split envelope's runtimeId
121
+ * retired bound + retired:true tombstone, CAS on the bound bytes; never answered again
122
+ *
123
+ * A retired record is replaced by a new reservation (CAS on the tombstone bytes) only once its pane
124
+ * is proven gone. Everything else — a reservation or claim with no bound pane, a failed cleanup, a
125
+ * record another driver holds with a live observer — refuses and keeps the record exactly as it is.
126
+ */
127
+ type BoardRecord = WatchBoardOwner & {
128
+ retired?: true;
129
+ runtimeId?: string;
130
+ };
131
+ /**
132
+ * Whole-record compare-and-swap. The canonical path stays readable until commit: a mkdir lock
133
+ * excludes other writers, then create-only `link`s the new inode (fails if anything exists) or
134
+ * `rename`s the new file over the live path (POSIX atomic replace — readers see old or new, never
135
+ * absence). A crash that leaves a `.tmp` or `.lock` does not drop the previous record.
136
+ * ponytail: observeNamedRun (supervision.ts) renames without CAS. It cannot interleave with a swap
137
+ * because the narrator writes nothing between reserve and claim, and no transition here swaps one.
138
+ */
139
+ export declare function casBoard(family: string, path: string, expected: string | undefined, next: BoardRecord): string;
89
140
  /**
90
141
  * The renderer hard-wraps long lines, paints margin chrome, and a cursor page boundary splits a
91
142
  * marker exactly like a wrap does. `parseWorkerResult` (src/adapters/prompt.ts) already de-wraps
@@ -105,6 +156,7 @@ export interface OrcaDriverOpts {
105
156
  pollMs?: number;
106
157
  /** Bounded, seam-adjustable staleness window for runtime probes before mutations. */
107
158
  probeStalenessMs?: number;
159
+ launchingHandle?: string;
108
160
  }
109
161
  export declare class OrcaDriver implements ExecutorDriver {
110
162
  id: string;
@@ -121,7 +173,12 @@ export declare class OrcaDriver implements ExecutorDriver {
121
173
  private narrate?;
122
174
  private hookCoverage?;
123
175
  private taskWorktrees;
176
+ private trackedByCheckout;
124
177
  private pendingProjects;
178
+ private env;
179
+ private launchingHandle?;
180
+ private serialQueue;
181
+ private serial;
125
182
  constructor(opts?: OrcaDriverOpts);
126
183
  private call;
127
184
  /** The live runtime's identity, or an explicit failure. A missing or unreachable runtime is a
@@ -144,14 +201,13 @@ export declare class OrcaDriver implements ExecutorDriver {
144
201
  private sendReceipt;
145
202
  private create;
146
203
  /**
147
- * A freshly-created git checkout does not become a valid Orca selector atomically. Ask
148
- * `worktree current` FROM that checkout until Orca itself resolves the exact filesystem identity;
149
- * an enclosing checkout is still not adoption. Only selector_not_found is a retryable refusal —
150
- * malformed envelopes and every other refusal remain explicit driver failures.
204
+ * OBS-1004: the tracked worktree that encloses a checkout, asked ONCE of `worktree current` from
205
+ * inside that checkout. Orca answers the exact path when it tracks the checkout itself, the
206
+ * enclosing tracked clone for a git worktree the daemon added beneath it (1.4.200, verified from
207
+ * `.tickmarkr/worktrees.noindex/<task>`), and selector_not_found when nothing it tracks encloses
208
+ * the cwd — which is a driver failure, not something to wait out: Orca has no adopt verb.
151
209
  */
152
- private awaitWorktreeAdoption;
153
- /** Same repo/run/narration path Herdr uses for its driver-owned dispatch-retry row. */
154
- private appendAdoptionWait;
210
+ private trackedWorktree;
155
211
  /**
156
212
  * Every terminal-addressed call — read AND write — goes through here, and the runtime identity is
157
213
  * established BEFORE the runtime-scoped handle goes on the wire. Discarding a lookalike's answer
@@ -161,6 +217,19 @@ export declare class OrcaDriver implements ExecutorDriver {
161
217
  * the handle exactly once, then re-issues the operation against the replacement.
162
218
  */
163
219
  private terminalOp;
220
+ /**
221
+ * FX-N01/N05/N06: under a shared enclosing worktree every task terminal lists with the same
222
+ * worktreePath, so the tracked path + owned title cannot tell two nested checkouts apart. The
223
+ * runtime's own proof is the terminal's earliest scrollback, where the create command printed a
224
+ * framed `TICKMARKR_CHECKOUT` line before its payload (checkoutProofLine). READ-only calls: the
225
+ * anchor (for `oldestCursor`), then pages from the oldest cursor until a frame is complete or the
226
+ * bound is hit. Every page is evidence only when the response's own identity is the candidate's:
227
+ * the terminal record must name `handle` and `_meta.runtimeId` must be `runtimeId` — the runtime
228
+ * that supplied the ownership listing — else another terminal's or another runtime's bytes were
229
+ * answered and nothing is proven. Proven means provesCheckout: exact canonical full-path equality
230
+ * of a complete frame, no other checkout named, no incomplete frame.
231
+ */
232
+ private checkoutProven;
164
233
  private recover;
165
234
  /** Validated READ terminal record, or an explicit unavailable failure. Called BEFORE any caller
166
235
  * looks at tail bytes — on every page, on every read-governed method. Read records are the one
@@ -200,7 +269,24 @@ export declare class OrcaDriver implements ExecutorDriver {
200
269
  waitAgentStatus(slot: Slot, status: string, timeoutMs: number): Promise<boolean>;
201
270
  sendKey(slot: Slot, key: string): Promise<void>;
202
271
  nudge(slot: Slot, message: string): Promise<boolean>;
203
- narrator(_cwd: string, _command: string, runId?: string): Promise<Slot>;
272
+ narrator(cwd: string, command: string, runId?: string): Promise<Slot>;
273
+ private boardPath;
274
+ /** A recorded pane (a receipt's handle bound to the split envelope's runtime, never a guess) is
275
+ * gone when that runtime no longer lists it, or when a handle-bound close receipt names it.
276
+ * A handle listed by a different runtime is a different pane — not closed, treated as gone. */
277
+ private closeRecordedPane;
278
+ /** bound → retired, decided from the record alone: it must be this driver's board for exactly this
279
+ * slot's pane. Already retired is returned as it is. */
280
+ private retireBoard;
281
+ /** bound → retired first: whatever fails below, no later call answers this board again. A live
282
+ * observer is asked to stop and its acknowledgement awaited on injected time before the
283
+ * handle-bound close (timeout keeps the tombstone and the pane); a dead one never acknowledges,
284
+ * so it is only asked. */
285
+ private retireAndClose;
286
+ /** WB-1 seam: the daemon reports this board lost. "Lost" can be a stale beat or missing presence
287
+ * under a still-live owner pid, so it is not proof of a dead observer — retirement keeps close's
288
+ * acknowledgement discipline (Leg-2 T9 P1). */
289
+ retireLostWatch(slot: Slot): Promise<void>;
204
290
  focus(target: FocusTarget): Promise<FocusResult>;
205
291
  project(taskId: string, state: "in-progress" | "in-review" | "completed"): Promise<void>;
206
292
  private setWorkspaceStatus;
@@ -243,5 +329,8 @@ export declare class OrcaDriver implements ExecutorDriver {
243
329
  reconcile(desired: Set<string>, runId: string, opts?: {
244
330
  spareLiveLlm?: boolean;
245
331
  }): Promise<void>;
332
+ private isRecordedWatchHandle;
333
+ private isRecordedWorkerHandle;
246
334
  worktree(repo: string, branch: string, baseRef: string): Promise<string>;
247
335
  }
336
+ export {};