tickmarkr 2.2.1 → 2.4.0

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 (81) hide show
  1. package/README.md +10 -9
  2. package/dist/adapters/catalog-remote.d.ts +1 -4
  3. package/dist/adapters/catalog-remote.js +52 -42
  4. package/dist/adapters/catalog.js +5 -3
  5. package/dist/adapters/claude-code.d.ts +1 -1
  6. package/dist/adapters/claude-code.js +8 -5
  7. package/dist/adapters/model-lints.d.ts +9 -5
  8. package/dist/adapters/model-lints.js +56 -15
  9. package/dist/adapters/model-windows.js +11 -0
  10. package/dist/adapters/prompt.js +1 -0
  11. package/dist/adapters/qwen.d.ts +5 -0
  12. package/dist/adapters/qwen.js +153 -0
  13. package/dist/adapters/types.d.ts +21 -1
  14. package/dist/adapters/types.js +43 -2
  15. package/dist/cli/commands/approve.js +5 -4
  16. package/dist/cli/commands/beat.js +7 -4
  17. package/dist/cli/commands/compile.js +32 -6
  18. package/dist/cli/commands/doctor.d.ts +9 -4
  19. package/dist/cli/commands/doctor.js +87 -13
  20. package/dist/cli/commands/fleet.d.ts +4 -0
  21. package/dist/cli/commands/fleet.js +53 -14
  22. package/dist/cli/commands/init.js +36 -21
  23. package/dist/cli/commands/plan.js +45 -7
  24. package/dist/cli/commands/report.js +37 -1
  25. package/dist/cli/commands/status.d.ts +1 -0
  26. package/dist/cli/commands/status.js +45 -1
  27. package/dist/cli/commands/verify.d.ts +6 -0
  28. package/dist/cli/commands/verify.js +145 -25
  29. package/dist/cli/index.d.ts +1 -1
  30. package/dist/cli/index.js +2 -2
  31. package/dist/compile/collateral.d.ts +2 -9
  32. package/dist/compile/collateral.js +17 -18
  33. package/dist/compile/index.d.ts +4 -1
  34. package/dist/compile/index.js +41 -7
  35. package/dist/compile/native.d.ts +4 -2
  36. package/dist/compile/native.js +58 -9
  37. package/dist/compile/ownership.js +34 -9
  38. package/dist/config/config.d.ts +1 -0
  39. package/dist/config/config.js +52 -6
  40. package/dist/drivers/herdr.d.ts +1 -0
  41. package/dist/drivers/herdr.js +11 -1
  42. package/dist/drivers/index.d.ts +6 -0
  43. package/dist/drivers/index.js +19 -4
  44. package/dist/drivers/orca.d.ts +35 -1
  45. package/dist/drivers/orca.js +260 -20
  46. package/dist/drivers/subprocess.d.ts +3 -3
  47. package/dist/drivers/subprocess.js +16 -9
  48. package/dist/drivers/types.d.ts +12 -0
  49. package/dist/gates/baseline.d.ts +2 -0
  50. package/dist/gates/baseline.js +47 -11
  51. package/dist/gates/llm.d.ts +6 -0
  52. package/dist/gates/llm.js +25 -9
  53. package/dist/gates/review.d.ts +7 -3
  54. package/dist/gates/review.js +61 -22
  55. package/dist/gates/run-gates.d.ts +5 -2
  56. package/dist/gates/run-gates.js +50 -26
  57. package/dist/gates/verdict-cause.d.ts +6 -2
  58. package/dist/gates/verdict-cause.js +8 -4
  59. package/dist/route/preference.d.ts +4 -0
  60. package/dist/route/preference.js +40 -0
  61. package/dist/route/router.js +15 -2
  62. package/dist/run/consult.d.ts +1 -0
  63. package/dist/run/consult.js +39 -8
  64. package/dist/run/daemon.d.ts +16 -0
  65. package/dist/run/daemon.js +345 -74
  66. package/dist/run/git.d.ts +3 -0
  67. package/dist/run/git.js +40 -5
  68. package/dist/run/journal.d.ts +15 -2
  69. package/dist/run/journal.js +73 -12
  70. package/dist/run/supervision.d.ts +6 -0
  71. package/dist/run/supervision.js +29 -1
  72. package/dist/tui/ink/fleet-app.d.ts +4 -0
  73. package/dist/tui/ink/fleet-app.js +45 -16
  74. package/dist/tui/ink/init-app.js +4 -4
  75. package/package.json +59 -1
  76. package/skills/tickmarkr-overseer/SKILL.md +77 -18
  77. package/skills/tickmarkr-overseer/scripts/seat-send.sh +88 -18
  78. package/skills/tickmarkr-overseer/scripts/watch-artifacts.sh +36 -2
  79. package/skills/tickmarkr-overseer/scripts/watch-contamination.sh +36 -15
  80. package/skills/tickmarkr-overseer/scripts/watch-context.sh +33 -7
  81. package/skills/tickmarkr-overseer/scripts/watch-pending-input.sh +32 -8
@@ -22,14 +22,31 @@ function testSources(repoRoot) {
22
22
  return [];
23
23
  }
24
24
  }
25
- function namedSources(test, tasks) {
25
+ function sourceFiles(repoRoot) {
26
+ const root = join(repoRoot, "src");
27
+ try {
28
+ return readdirSync(root, { recursive: true, encoding: "utf8" })
29
+ .filter((path) => /\.(?:[cm]?[jt]sx?)$/.test(path))
30
+ .map((path) => `src/${normalize(path)}`)
31
+ .sort();
32
+ }
33
+ catch {
34
+ return [];
35
+ }
36
+ }
37
+ // OBS-898: `allSources` is indexed once per ownership pass by the caller, never per test source.
38
+ function namedSources(test, tasks, allSources) {
26
39
  const stem = basename(test).replace(/\.test\.ts$/, "");
27
40
  const matches = new Map();
28
41
  for (const task of tasks) {
29
- for (const entry of task.files.map(normalize).filter((path) => path.startsWith("src/") && !/[*?{[]/.test(path))) {
30
- const source = basename(entry, extname(entry));
31
- if (stem === source || stem.startsWith(`${source}-`)) {
32
- matches.set(`${task.id}:${entry}`, { taskId: task.id, source: entry });
42
+ for (const entry of task.files.map(normalize).filter((path) => path.startsWith("src/"))) {
43
+ const fromGlob = /[*?{[]/.test(entry);
44
+ const entries = fromGlob ? allSources.filter(filesGlob(entry)) : [entry];
45
+ for (const sourcePath of entries) {
46
+ const source = basename(sourcePath, extname(sourcePath));
47
+ if (stem === source || stem.startsWith(`${source}-`)) {
48
+ matches.set(`${task.id}:${sourcePath}`, { taskId: task.id, source: sourcePath, fromGlob });
49
+ }
33
50
  }
34
51
  }
35
52
  }
@@ -148,19 +165,27 @@ export function ownershipFindings(tasks, repoRoot) {
148
165
  predictedBy.set(hit, ids);
149
166
  }
150
167
  }
168
+ const globOwnedTests = new Map();
169
+ const allSources = sourceFiles(repoRoot);
151
170
  for (const source of sources) {
152
171
  const ids = predictedBy.get(source.path) ?? new Set();
153
- for (const { taskId } of namedSources(source.path, tasks))
154
- ids.add(taskId);
172
+ for (const named of namedSources(source.path, tasks, allSources)) {
173
+ ids.add(named.taskId);
174
+ if (named.fromGlob) {
175
+ const owners = globOwnedTests.get(source.path) ?? new Set();
176
+ owners.add(named.taskId);
177
+ globOwnedTests.set(source.path, owners);
178
+ }
179
+ }
155
180
  if (ids.size > 0)
156
181
  predictedBy.set(source.path, ids);
157
182
  }
158
183
  const findings = [];
159
184
  for (const [test, taskIds] of predictedBy) {
160
- if (owners(test).length === 0) {
185
+ if (owners(test).length === 0 && !(globOwnedTests.get(test)?.size)) {
161
186
  const ids = [...taskIds].sort();
162
187
  const source = sourceByPath.get(test);
163
- const evidence = corroboration(source, namedSources(test, tasks));
188
+ const evidence = corroboration(source, namedSources(test, tasks, allSources));
164
189
  findings.push({
165
190
  code: "unowned-test",
166
191
  test,
@@ -266,6 +266,7 @@ export declare const TickmarkrConfigSchema: z.ZodObject<{
266
266
  }, z.core.$strip>;
267
267
  review: z.ZodObject<{
268
268
  complexityThreshold: z.ZodNumber;
269
+ timeoutMs: z.ZodNumber;
269
270
  required: z.ZodBoolean;
270
271
  prefer: z.ZodOptional<z.ZodArray<z.ZodString>>;
271
272
  policy: z.ZodOptional<z.ZodEnum<{
@@ -355,6 +355,7 @@ export const TickmarkrConfigSchema = z.object({
355
355
  // because routing hints and the setup cockpit still read it as a complexity landmark; NOTHING in
356
356
  // src/gates/review.ts reads it any more, and a value here can no longer disable a review.
357
357
  complexityThreshold: z.number(),
358
+ timeoutMs: z.number().int().positive(),
358
359
  required: z.boolean(),
359
360
  prefer: z.array(z.string()).optional(),
360
361
  // R3: the operator's participation floor. "full" forces a cross-vendor review on every task;
@@ -484,8 +485,15 @@ export const DEFAULT_CONFIG = {
484
485
  // 2026-07-16 (cursor-agent 2026.07.09); gives cursor a cheap-tier channel so low-complexity shapes
485
486
  // stop burning its mid. Operator-approved 2026-07-16.
486
487
  "composer-2.5-fast": "cheap",
488
+ // OBS-871: LiveBench 2026_06_25, fetched 2026-09-03; released 2026-09-01.
489
+ "claude-fable-5-1": "frontier",
490
+ // OBS-871: LiveBench 2026_06_25, fetched 2026-09-03; released 2026-09-02.
491
+ "gemini-3.8-flash": "mid",
492
+ },
493
+ windows: {
494
+ "composer-2.5": 200_000, "composer-2.5-fast": 200_000,
495
+ "claude-fable-5-1": 1_000_000, "gemini-3.8-flash": 1_000_000,
487
496
  },
488
- windows: { "composer-2.5": 200_000, "composer-2.5-fast": 200_000 },
489
497
  },
490
498
  // GLM-5.2 → mid per benchmark policy (2026-07): SWE-bench Pro 62.1 (> GPT-5.5 58.6), FrontierSWE 74.4 ≈ Opus 4.8;
491
499
  // no independent Terminal-Bench score → conservative mid, overlays may raise.
@@ -507,8 +515,46 @@ export const DEFAULT_CONFIG = {
507
515
  // cross-harness) is pre-existing, FLEET-05 owns it.
508
516
  pi: {
509
517
  vendor: "zhipu", channel: "sub",
510
- models: { "zai/glm-5.2": "mid" },
511
- windows: { "zai/glm-5.2": 1_000_000 },
518
+ models: {
519
+ "zai/glm-5.2": "mid",
520
+ // OBS-871: LiveBench 2026_06_25, fetched 2026-09-03; GLM-5.3 released 2026-08-18.
521
+ "zai/glm-5.3": "frontier",
522
+ // OBS-871: same LiveBench source and 2026-09-03 fetch; speed variant remains mid.
523
+ "zai/glm-5.3-flash": "mid",
524
+ },
525
+ windows: { "zai/glm-5.2": 1_000_000, "zai/glm-5.3": 1_000_000, "zai/glm-5.3-flash": 200_000 },
526
+ },
527
+ // OBS-871: gateway ids and bands from LiveBench 2026_06_25, fetched 2026-09-03.
528
+ omp: {
529
+ vendor: "mixed", channel: "sub",
530
+ models: {
531
+ "google/gemini-3.8-flash": "mid",
532
+ "zai/glm-5.3": "frontier",
533
+ "alibaba/qwen3.8-max": "frontier",
534
+ },
535
+ modelOverrides: {
536
+ "google/gemini-3.8-flash": { vendor: "google" },
537
+ "zai/glm-5.3": { vendor: "zhipu" },
538
+ "alibaba/qwen3.8-max": { vendor: "alibaba" },
539
+ },
540
+ windows: {
541
+ "google/gemini-3.8-flash": 1_000_000,
542
+ "zai/glm-5.3": 1_000_000,
543
+ "alibaba/qwen3.8-max": 1_000_000,
544
+ },
545
+ },
546
+ // OBS-871: Qwen 3.8 Max scored 64.6 in LiveBench 2026_06_25, fetched 2026-09-03.
547
+ qwen: {
548
+ vendor: "alibaba", channel: "sub",
549
+ models: { "qwen3.8-max": "frontier" },
550
+ windows: { "qwen3.8-max": 1_000_000 },
551
+ },
552
+ // OBS-871: prime-agent listed this prime-inference route on 2026-09-03; GLM-5.2 remains mid.
553
+ "prime-agent": {
554
+ vendor: "mixed", channel: "sub",
555
+ models: { "prime-inference/z-ai/glm-5.2": "mid" },
556
+ modelOverrides: { "prime-inference/z-ai/glm-5.2": { vendor: "zhipu" } },
557
+ windows: { "prime-inference/z-ai/glm-5.2": 1_000_000 },
512
558
  },
513
559
  // Native grok CLI (Phase 40). grok-4.5 → mid: same benchmark provenance as the retired cursor-agent
514
560
  // grok-4.5-xhigh seed above (AA 54, TB2.1 83.3%, SWE-b Pro 64.7% — researched 2026-07-10).
@@ -543,7 +589,7 @@ export const DEFAULT_CONFIG = {
543
589
  judge: { adapter: "claude-code", model: "fable" },
544
590
  // R3: no `policy` floor — the neutral floor leaves the compiler's per-task assignment standing, so
545
591
  // the path-keyed rule is reachable out of the box rather than raised to full by construction.
546
- review: { complexityThreshold: 7, required: true, criticalPaths: [...DEFAULT_REVIEW_CRITICAL_PATHS] },
592
+ review: { complexityThreshold: 7, timeoutMs: 900_000, required: true, criticalPaths: [...DEFAULT_REVIEW_CRITICAL_PATHS] },
547
593
  consult: { adapter: "claude-code", model: "fable", stallMinutes: 15 },
548
594
  // v1.4: gate LLM calls (judge/review/consult) run headless by default; pane opts back into visible agents.
549
595
  // v1.2: workers are the real agent TUI in the pane; "print" restores the -p-rendered-in-pane path.
@@ -713,7 +759,7 @@ export function overlayBytesLoadError(repoRoot, bytes, opts = {}) {
713
759
  export function configTemplate(overlay) {
714
760
  const base = `# tickmarkr config overlay — merges over built-in defaults (repo beats global beats defaults)
715
761
  # concurrency: 3
716
- # driver: auto # auto | herdr | subprocess | orca
762
+ # driver: auto # auto: herdr when HERDR_ENV=1, then orca when TERM_PROGRAM=Orca + ORCA_TERMINAL_HANDLE, else subprocess; name orca explicitly outside an Orca terminal
717
763
  # taskTimeoutMinutes: 30
718
764
  # contextWarnTokens: 170000 # v1.23: journal+notify once per attempt when live worker context crosses this (status shows the sample)
719
765
  # setup: npm ci --prefer-offline # run in each fresh task worktree before dispatch
@@ -765,7 +811,7 @@ export function configTemplate(overlay) {
765
811
  # test: npm test
766
812
  # byShape:
767
813
  # docs: { acceptance: false, review: false } # baseline, evidence, and scope are mandatory
768
- # review: { complexityThreshold: 7, required: true, prefer: [codex:gpt-5.6-sol, kimi] }
814
+ # review: { complexityThreshold: 7, timeoutMs: 900000, required: true, prefer: [codex:gpt-5.6-sol, kimi] }
769
815
  # # prefer: ordered reviewer seat preference (adapter | adapter:model); ranks
770
816
  # # diversity-eligible channels only — never admits a same-vendor/same-model reviewer
771
817
  # consult: { adapter: claude-code, model: fable, stallMinutes: 15, prefer: [codex:gpt-5.6-sol, kimi:kimi-code/k3] }
@@ -56,6 +56,7 @@ export declare class HerdrDriver implements ExecutorDriver {
56
56
  private journal?;
57
57
  id: string;
58
58
  interactive: boolean;
59
+ readSource: string;
59
60
  private groups;
60
61
  private groupSerial;
61
62
  private deliverySerial;
@@ -142,6 +142,7 @@ export class HerdrDriver {
142
142
  journal;
143
143
  id = "herdr";
144
144
  interactive = true;
145
+ readSource = "recent-unwrapped";
145
146
  groups = new Map();
146
147
  // grouped slot()/close() mutate shared group state across awaits — serialize them so two
147
148
  // concurrent first members can never both create the group tab (mergeSerial idiom, daemon.ts)
@@ -1339,7 +1340,16 @@ export class HerdrDriver {
1339
1340
  if (alive.has(tab))
1340
1341
  continue;
1341
1342
  const closed = await this.herdr(`tab close ${shq(tab)}`);
1342
- if (closed.code !== 0) {
1343
+ if (closed.code !== 0 && /tab_not_found/i.test(`${closed.stderr}\n${closed.stdout}`)) {
1344
+ this.journalReconcile(journalHandle, "tab-reconcile-close-skipped", undefined, {
1345
+ tabId: tab,
1346
+ runId,
1347
+ sweeperRunId: runId,
1348
+ exitCode: 0,
1349
+ reason: "tab_not_found",
1350
+ });
1351
+ }
1352
+ else if (closed.code !== 0) {
1343
1353
  this.journalReconcile(journalHandle, "tab-reconcile-close-failed", undefined, {
1344
1354
  tabId: tab,
1345
1355
  runId,
@@ -2,6 +2,12 @@ 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
+ /**
6
+ * Orca authors both markers on every terminal it creates. Requiring the pair avoids treating an
7
+ * unrelated TERM_PROGRAM value or a copied terminal handle as host identity. This is deliberately
8
+ * environment-only: selection must not execute a binary or contact the Orca runtime.
9
+ */
10
+ export declare function orcaHostDetected(env?: NodeJS.ProcessEnv): boolean;
5
11
  /** Validate argv at the CLI boundary rather than casting an arbitrary string into a driver choice. */
6
12
  export declare function parseDriverOverride(override?: string): DriverChoice | undefined;
7
13
  export declare function driverEvidence(cfg: TickmarkrConfig, driver: ExecutorDriver, override?: string): string;
@@ -3,6 +3,14 @@ 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
+ /**
7
+ * Orca authors both markers on every terminal it creates. Requiring the pair avoids treating an
8
+ * unrelated TERM_PROGRAM value or a copied terminal handle as host identity. This is deliberately
9
+ * environment-only: selection must not execute a binary or contact the Orca runtime.
10
+ */
11
+ export function orcaHostDetected(env = process.env) {
12
+ return env.TERM_PROGRAM === "Orca" && env.ORCA_TERMINAL_HANDLE !== undefined;
13
+ }
6
14
  /** Validate argv at the CLI boundary rather than casting an arbitrary string into a driver choice. */
7
15
  export function parseDriverOverride(override) {
8
16
  if (override === undefined)
@@ -20,8 +28,13 @@ export function driverEvidence(cfg, driver, override) {
20
28
  if (want !== "auto")
21
29
  return `${driver.id} (config)`;
22
30
  const herdrAvailable = process.env.HERDR_ENV === "1";
23
- if (driver.id === (herdrAvailable ? "herdr" : "subprocess")) {
24
- return `auto → ${driver.id} (${herdrAvailable ? "HERDR_ENV=1" : "HERDR_ENV unset"})`;
31
+ if (herdrAvailable && driver.id === "herdr")
32
+ return "auto → herdr (HERDR_ENV=1)";
33
+ if (!herdrAvailable && orcaHostDetected() && driver.id === "orca") {
34
+ return "auto → orca (TERM_PROGRAM+ORCA_TERMINAL_HANDLE)";
35
+ }
36
+ if (!herdrAvailable && !orcaHostDetected() && driver.id === "subprocess") {
37
+ return "auto → subprocess (HERDR_ENV unset)";
25
38
  }
26
39
  return `auto → ${driver.id} (runtime)`;
27
40
  }
@@ -34,9 +47,11 @@ export function pickDriver(cfg, override) {
34
47
  const driver = want === "herdr" ? new HerdrDriver("herdr", cfg.visibility.workersPerTab)
35
48
  : want === "subprocess" ? new SubprocessDriver()
36
49
  // Orca is an operator-selected execution surface. Its runtime failure stays on Orca; selection
37
- // must never substitute a hidden subprocess worker after this explicit choice.
50
+ // must never substitute a hidden subprocess worker after an explicit or detected choice.
38
51
  : want === "orca" ? new OrcaDriver()
39
- : HerdrDriver.available() ? new HerdrDriver("herdr", cfg.visibility.workersPerTab) : new SubprocessDriver();
52
+ : HerdrDriver.available() ? new HerdrDriver("herdr", cfg.visibility.workersPerTab)
53
+ : orcaHostDetected() ? new OrcaDriver()
54
+ : new SubprocessDriver();
40
55
  if (selectedOverride !== undefined)
41
56
  overrideByDriver.set(driver, selectedOverride);
42
57
  return driver;
@@ -1,7 +1,8 @@
1
1
  import { type ShResult } from "../run/git.js";
2
+ import { type JournalEvent } from "../run/journal.js";
2
3
  import { type ExecutorDriver, type NotifyOpts, type Slot, type SlotOpts } from "./types.js";
3
4
  /** The response families the ONE shared envelope parser serves. There is no second JSON seam. */
4
- export declare const ORCA_RESPONSE_FAMILIES: readonly ["status", "create", "list", "read", "send", "wait", "show", "close"];
5
+ export declare const ORCA_RESPONSE_FAMILIES: readonly ["status", "create", "list", "read", "send", "wait", "show", "close", "worktree-current", "worktree-set", "hooks-status"];
5
6
  export type OrcaFamily = (typeof ORCA_RESPONSE_FAMILIES)[number];
6
7
  export declare const ORCA_FIXTURE_VERSION = "1.4.195";
7
8
  export declare const ORCA_CLI_COMMAND_ENV = "ORCA_CLI_COMMAND";
@@ -13,6 +14,7 @@ export declare const NOT_WRITABLE_CODE = "terminal_not_writable";
13
14
  /** The ONLY terminal status that licenses reading a terminal's bytes or its agent state. */
14
15
  export declare const RUNNING_STATUS = "running";
15
16
  export declare const STATUS_GOVERNED_METHODS: readonly ["read", "waitOutput", "status", "waitAgentStatus"];
17
+ export declare const WORKTREE_ADOPTION_TIMEOUT_MS = 60000;
16
18
  export interface OrcaExec {
17
19
  (args: string[], cwd: string, timeoutMs?: number): Promise<ShResult>;
18
20
  }
@@ -113,6 +115,11 @@ export declare class OrcaDriver implements ExecutorDriver {
113
115
  private pageLines;
114
116
  private pollMs;
115
117
  private probeStalenessMs;
118
+ private journalRoots;
119
+ private narrate?;
120
+ private hookCoverage?;
121
+ private taskWorktrees;
122
+ private pendingProjects;
116
123
  constructor(opts?: OrcaDriverOpts);
117
124
  private call;
118
125
  /** The live runtime's identity, or an explicit failure. A missing or unreachable runtime is a
@@ -126,8 +133,23 @@ export declare class OrcaDriver implements ExecutorDriver {
126
133
  private state;
127
134
  private latched;
128
135
  private assertAvailable;
136
+ describe(slot: Slot): {
137
+ surface?: string;
138
+ hostPlatform?: string;
139
+ };
129
140
  run(slot: Slot, cmd: string): Promise<void>;
141
+ private sendText;
142
+ private sendReceipt;
130
143
  private create;
144
+ /**
145
+ * A freshly-created git checkout does not become a valid Orca selector atomically. Ask
146
+ * `worktree current` FROM that checkout until Orca itself resolves the exact filesystem identity;
147
+ * an enclosing checkout is still not adoption. Only selector_not_found is a retryable refusal —
148
+ * malformed envelopes and every other refusal remain explicit driver failures.
149
+ */
150
+ private awaitWorktreeAdoption;
151
+ /** Same repo/run/narration path Herdr uses for its driver-owned dispatch-retry row. */
152
+ private appendAdoptionWait;
131
153
  /**
132
154
  * Every terminal-addressed call — read AND write — goes through here, and the runtime identity is
133
155
  * established BEFORE the runtime-scoped handle goes on the wire. Discarding a lookalike's answer
@@ -149,6 +171,8 @@ export declare class OrcaDriver implements ExecutorDriver {
149
171
  private liveShowTerm;
150
172
  private tailText;
151
173
  private readPage;
174
+ /** A rendered-frame liveness read. `--screen` and `--cursor` are mutually exclusive in Orca. */
175
+ private readScreen;
152
176
  /** A single UNPAGED tail read — exactly what the caller asked for and nothing more. Markers split
153
177
  * across cursor pages are not reassembled here; that is waitOutput's job. */
154
178
  read(slot: Slot, lines: number): Promise<string>;
@@ -163,12 +187,22 @@ export declare class OrcaDriver implements ExecutorDriver {
163
187
  regex?: boolean;
164
188
  }): Promise<boolean>;
165
189
  status(slot: Slot): Promise<string>;
190
+ private hookAgent;
191
+ /** true = hooked, false = definitively unhooked, undefined = agent absent from Orca's table. */
192
+ private agentHookAvailable;
193
+ private loadHookCoverage;
166
194
  /** One `terminal wait` through the full identity machinery. The recorded 1.4.186 elapsed answer
167
195
  * is rc 1 + ok:true + {handle, condition, satisfied:false, status:"running"}; it is "not yet"
168
196
  * only after this method validates all four fields. Any malformed/refused wait remains explicit. */
169
197
  private waitCondition;
170
198
  waitAgentStatus(slot: Slot, status: string, timeoutMs: number): Promise<boolean>;
199
+ sendKey(slot: Slot, key: string): Promise<void>;
200
+ nudge(slot: Slot, message: string): Promise<boolean>;
201
+ narrator(cwd: string, command: string, runId?: string): Promise<Slot>;
202
+ project(taskId: string, state: "in-progress" | "in-review" | "completed"): Promise<void>;
203
+ private setWorkspaceStatus;
171
204
  notify(msg: string, opts?: NotifyOpts): Promise<void>;
205
+ narrateWith(narrate: (event: JournalEvent) => void): void;
172
206
  close(slot: Slot): Promise<void>;
173
207
  /**
174
208
  * The one destructive call in this driver, for a slot's own terminal AND for a reconcile candidate