@os-eco/overstory-cli 0.7.0 → 0.7.2

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 (60) hide show
  1. package/README.md +6 -5
  2. package/agents/builder.md +1 -1
  3. package/agents/coordinator.md +12 -11
  4. package/agents/lead.md +6 -6
  5. package/agents/monitor.md +4 -4
  6. package/agents/reviewer.md +1 -1
  7. package/agents/scout.md +5 -5
  8. package/agents/supervisor.md +36 -32
  9. package/package.json +1 -1
  10. package/src/agents/guard-rules.ts +97 -0
  11. package/src/agents/hooks-deployer.ts +7 -90
  12. package/src/agents/overlay.test.ts +7 -7
  13. package/src/agents/overlay.ts +5 -5
  14. package/src/commands/agents.test.ts +5 -0
  15. package/src/commands/clean.test.ts +3 -0
  16. package/src/commands/completions.ts +1 -1
  17. package/src/commands/coordinator.test.ts +1 -0
  18. package/src/commands/coordinator.ts +15 -11
  19. package/src/commands/costs.test.ts +5 -0
  20. package/src/commands/init.test.ts +1 -2
  21. package/src/commands/init.ts +1 -8
  22. package/src/commands/inspect.test.ts +14 -0
  23. package/src/commands/log.test.ts +14 -0
  24. package/src/commands/log.ts +39 -0
  25. package/src/commands/mail.test.ts +5 -0
  26. package/src/commands/monitor.ts +15 -11
  27. package/src/commands/nudge.test.ts +1 -0
  28. package/src/commands/prime.test.ts +2 -0
  29. package/src/commands/prime.ts +6 -2
  30. package/src/commands/run.test.ts +1 -0
  31. package/src/commands/sling.test.ts +15 -1
  32. package/src/commands/sling.ts +44 -21
  33. package/src/commands/status.test.ts +1 -0
  34. package/src/commands/stop.test.ts +1 -0
  35. package/src/commands/supervisor.ts +19 -12
  36. package/src/commands/trace.test.ts +1 -0
  37. package/src/commands/worktree.test.ts +9 -0
  38. package/src/config.ts +29 -0
  39. package/src/doctor/consistency.test.ts +14 -0
  40. package/src/e2e/init-sling-lifecycle.test.ts +3 -5
  41. package/src/index.ts +1 -1
  42. package/src/mail/broadcast.test.ts +1 -0
  43. package/src/merge/resolver.ts +23 -4
  44. package/src/runtimes/claude.test.ts +1 -1
  45. package/src/runtimes/pi-guards.test.ts +433 -0
  46. package/src/runtimes/pi-guards.ts +349 -0
  47. package/src/runtimes/pi.test.ts +620 -0
  48. package/src/runtimes/pi.ts +244 -0
  49. package/src/runtimes/registry.test.ts +33 -0
  50. package/src/runtimes/registry.ts +15 -2
  51. package/src/runtimes/types.ts +63 -0
  52. package/src/schema-consistency.test.ts +1 -0
  53. package/src/sessions/compat.ts +1 -0
  54. package/src/sessions/store.test.ts +31 -0
  55. package/src/sessions/store.ts +37 -4
  56. package/src/types.ts +17 -0
  57. package/src/watchdog/daemon.test.ts +7 -4
  58. package/src/watchdog/daemon.ts +1 -1
  59. package/src/watchdog/health.test.ts +1 -0
  60. package/src/watchdog/triage.ts +14 -4
@@ -3,6 +3,13 @@ import { dirname, join } from "node:path";
3
3
  import { DEFAULT_QUALITY_GATES } from "../config.ts";
4
4
  import { AgentError } from "../errors.ts";
5
5
  import type { QualityGate } from "../types.ts";
6
+ import {
7
+ DANGEROUS_BASH_PATTERNS,
8
+ INTERACTIVE_TOOLS,
9
+ NATIVE_TEAM_TOOLS,
10
+ SAFE_BASH_PREFIXES,
11
+ WRITE_TOOLS,
12
+ } from "./guard-rules.ts";
6
13
 
7
14
  /**
8
15
  * Capabilities that must never modify project files.
@@ -31,96 +38,6 @@ const COORDINATION_CAPABILITIES = new Set(["coordinator", "supervisor", "monitor
31
38
  */
32
39
  const COORDINATION_SAFE_PREFIXES = ["git add", "git commit"];
33
40
 
34
- /**
35
- * Claude Code native team/task tools that bypass overstory orchestration.
36
- * All overstory agents must use `overstory sling` for delegation, not these.
37
- */
38
- const NATIVE_TEAM_TOOLS = [
39
- "Task",
40
- "TeamCreate",
41
- "TeamDelete",
42
- "SendMessage",
43
- "TaskCreate",
44
- "TaskUpdate",
45
- "TaskList",
46
- "TaskGet",
47
- "TaskOutput",
48
- "TaskStop",
49
- ];
50
-
51
- /**
52
- * Tools that require human interaction and block indefinitely in non-interactive
53
- * tmux sessions. Agents run non-interactively and must never call these tools.
54
- * Use overstory mail (--type question) to escalate to the orchestrator instead.
55
- */
56
- const INTERACTIVE_TOOLS = ["AskUserQuestion", "EnterPlanMode", "EnterWorktree"];
57
-
58
- /** Tools that non-implementation agents must not use. */
59
- const WRITE_TOOLS = ["Write", "Edit", "NotebookEdit"];
60
-
61
- /**
62
- * Bash commands that modify files and must be blocked for non-implementation agents.
63
- * Each pattern is a regex fragment used inside a grep -qE check.
64
- */
65
- const DANGEROUS_BASH_PATTERNS = [
66
- "sed\\s+-i",
67
- "sed\\s+--in-place",
68
- "echo\\s+.*>",
69
- "printf\\s+.*>",
70
- "cat\\s+.*>",
71
- "tee\\s",
72
- "\\bvim\\b",
73
- "\\bnano\\b",
74
- "\\bvi\\b",
75
- "\\bmv\\s",
76
- "\\bcp\\s",
77
- "\\brm\\s",
78
- "\\bmkdir\\s",
79
- "\\btouch\\s",
80
- "\\bchmod\\s",
81
- "\\bchown\\s",
82
- ">>",
83
- "\\bgit\\s+add\\b",
84
- "\\bgit\\s+commit\\b",
85
- "\\bgit\\s+merge\\b",
86
- "\\bgit\\s+push\\b",
87
- "\\bgit\\s+reset\\b",
88
- "\\bgit\\s+checkout\\b",
89
- "\\bgit\\s+rebase\\b",
90
- "\\bgit\\s+stash\\b",
91
- "\\bnpm\\s+install\\b",
92
- "\\bbun\\s+install\\b",
93
- "\\bbun\\s+add\\b",
94
- // Runtime eval flags — bypass shell pattern guards by executing JS/Python directly
95
- "\\bbun\\s+-e\\b",
96
- "\\bbun\\s+--eval\\b",
97
- "\\bnode\\s+-e\\b",
98
- "\\bnode\\s+--eval\\b",
99
- "\\bdeno\\s+eval\\b",
100
- "\\bpython3?\\s+-c\\b",
101
- "\\bperl\\s+-e\\b",
102
- "\\bruby\\s+-e\\b",
103
- ];
104
-
105
- /**
106
- * Bash commands that are always safe for non-implementation agents.
107
- * If a command starts with any of these prefixes, it bypasses the dangerous command check.
108
- * This whitelist is checked BEFORE the blocklist.
109
- */
110
- const SAFE_BASH_PREFIXES = [
111
- "ov ",
112
- "overstory ",
113
- "bd ",
114
- "sd ",
115
- "git status",
116
- "git log",
117
- "git diff",
118
- "git show",
119
- "git blame",
120
- "git branch",
121
- "mulch ",
122
- ];
123
-
124
41
  /**
125
42
  * Extract command prefixes from quality gate configurations.
126
43
  *
@@ -265,7 +265,7 @@ describe("generateOverlay", () => {
265
265
  expect(output).not.toContain("bun run lint");
266
266
  });
267
267
 
268
- test("scout completion section includes bd close and mail send", async () => {
268
+ test("scout completion section includes sd close and mail send", async () => {
269
269
  const config = makeConfig({
270
270
  capability: "scout",
271
271
  agentName: "recon-1",
@@ -274,7 +274,7 @@ describe("generateOverlay", () => {
274
274
  });
275
275
  const output = await generateOverlay(config);
276
276
 
277
- expect(output).toContain("bd close overstory-task1");
277
+ expect(output).toContain("sd close overstory-task1");
278
278
  expect(output).toContain("ov mail send --to lead-alpha");
279
279
  });
280
280
 
@@ -426,14 +426,14 @@ describe("generateOverlay", () => {
426
426
  expect(output).not.toContain("Quality Gates");
427
427
  });
428
428
 
429
- test("default trackerCli renders as bd in quality gates", async () => {
429
+ test("default trackerCli renders as sd in quality gates", async () => {
430
430
  const config = makeConfig({ capability: "builder", taskId: "overstory-task1" });
431
431
  const output = await generateOverlay(config);
432
432
 
433
- expect(output).toContain("bd close overstory-task1");
433
+ expect(output).toContain("sd close overstory-task1");
434
434
  });
435
435
 
436
- test("custom trackerCli replaces bd in quality gates", async () => {
436
+ test("custom trackerCli replaces sd in quality gates", async () => {
437
437
  const config = makeConfig({
438
438
  capability: "builder",
439
439
  trackerCli: "sd",
@@ -489,11 +489,11 @@ describe("generateOverlay", () => {
489
489
  expect(output).not.toContain("{{TRACKER_NAME}}");
490
490
  });
491
491
 
492
- test("defaults backward-compatible: no trackerCli/trackerName produces bd/beads", async () => {
492
+ test("defaults: no trackerCli/trackerName produces sd/seeds", async () => {
493
493
  const config = makeConfig({ capability: "builder", taskId: "overstory-back" });
494
494
  const output = await generateOverlay(config);
495
495
 
496
- expect(output).toContain("bd close overstory-back");
496
+ expect(output).toContain("sd close overstory-back");
497
497
  });
498
498
 
499
499
  test("dispatch overrides: skipReview injects SKIP REVIEW directive for leads", async () => {
@@ -182,7 +182,7 @@ function formatQualityGates(config: OverlayConfig): string {
182
182
  "Before reporting completion:",
183
183
  "",
184
184
  `1. **Record mulch learnings:** \`ml record <domain> --type <convention|pattern|reference> --description "..."\` — capture reusable knowledge from your work`,
185
- `2. **Close issue:** \`${config.trackerCli ?? "bd"} close ${config.taskId} --reason "summary of findings"\``,
185
+ `2. **Close issue:** \`${config.trackerCli ?? "sd"} close ${config.taskId} --reason "summary of findings"\``,
186
186
  `3. **Send results:** \`ov mail send --to ${config.parentAgent ?? "coordinator"} --subject "done" --body "Summary" --type result --agent ${config.agentName}\``,
187
187
  "",
188
188
  "You are a read-only agent. Do NOT commit, modify files, or run quality gates.",
@@ -207,7 +207,7 @@ function formatQualityGates(config: OverlayConfig): string {
207
207
  `${gateLines.length + 1}. **Commit:** all changes committed to your branch (${config.branchName})`,
208
208
  `${gateLines.length + 2}. **Record mulch learnings:** \`ml record <domain> --type <convention|pattern|failure|decision> --description "..." --outcome-status success --outcome-agent ${config.agentName}\` — capture insights from your work`,
209
209
  `${gateLines.length + 3}. **Signal completion:** send \`worker_done\` mail to ${config.parentAgent ?? "coordinator"}: \`ov mail send --to ${config.parentAgent ?? "coordinator"} --subject "Worker done: ${config.taskId}" --body "Quality gates passed." --type worker_done --agent ${config.agentName}\``,
210
- `${gateLines.length + 4}. **Close issue:** \`${config.trackerCli ?? "bd"} close ${config.taskId} --reason "summary of changes"\``,
210
+ `${gateLines.length + 4}. **Close issue:** \`${config.trackerCli ?? "sd"} close ${config.taskId} --reason "summary of changes"\``,
211
211
  "",
212
212
  "Do NOT push to the canonical branch. Your work will be merged by the",
213
213
  "coordinator via `ov merge`.",
@@ -225,7 +225,7 @@ function formatConstraints(config: OverlayConfig): string {
225
225
  "",
226
226
  "- You are **read-only**: do NOT modify, create, or delete any files",
227
227
  "- Do NOT commit, push, or make any git state changes",
228
- `- Report completion via \`${config.trackerCli ?? "bd"} close\` AND \`ov mail send --type result\``,
228
+ `- Report completion via \`${config.trackerCli ?? "sd"} close\` AND \`ov mail send --type result\``,
229
229
  "- If you encounter a blocking issue, send mail with `--priority urgent --type error`",
230
230
  ].join("\n");
231
231
  }
@@ -238,7 +238,7 @@ function formatConstraints(config: OverlayConfig): string {
238
238
  "- Only modify files in your File Scope",
239
239
  `- Commit only to your branch: ${config.branchName}`,
240
240
  "- Never push to the canonical branch",
241
- `- Report completion via \`${config.trackerCli ?? "bd"} close\` AND \`ov mail send --type result\``,
241
+ `- Report completion via \`${config.trackerCli ?? "sd"} close\` AND \`ov mail send --type result\``,
242
242
  "- If you encounter a blocking issue, send mail with `--priority urgent --type error`",
243
243
  ].join("\n");
244
244
  }
@@ -318,7 +318,7 @@ export async function generateOverlay(config: OverlayConfig): Promise<string> {
318
318
  "{{QUALITY_GATE_STEPS}}": formatQualityGatesSteps(config.qualityGates),
319
319
  "{{QUALITY_GATE_BASH}}": formatQualityGatesBash(config.qualityGates),
320
320
  "{{QUALITY_GATE_CAPABILITIES}}": formatQualityGatesCapabilities(config.qualityGates),
321
- "{{TRACKER_CLI}}": config.trackerCli ?? "bd",
321
+ "{{TRACKER_CLI}}": config.trackerCli ?? "sd",
322
322
  "{{TRACKER_NAME}}": config.trackerName ?? "seeds",
323
323
  };
324
324
 
@@ -108,6 +108,7 @@ describe("discoverAgents", () => {
108
108
  lastActivity: "2024-01-01T00:01:00Z",
109
109
  escalationLevel: 0,
110
110
  stalledSince: null,
111
+ transcriptPath: null,
111
112
  };
112
113
 
113
114
  store.upsert(session);
@@ -140,6 +141,7 @@ describe("discoverAgents", () => {
140
141
  lastActivity: "2024-01-01T00:01:00Z",
141
142
  escalationLevel: 0,
142
143
  stalledSince: null,
144
+ transcriptPath: null,
143
145
  };
144
146
 
145
147
  const scout: AgentSession = {
@@ -159,6 +161,7 @@ describe("discoverAgents", () => {
159
161
  lastActivity: "2024-01-01T00:01:00Z",
160
162
  escalationLevel: 0,
161
163
  stalledSince: null,
164
+ transcriptPath: null,
162
165
  };
163
166
 
164
167
  store.upsert(builder);
@@ -191,6 +194,7 @@ describe("discoverAgents", () => {
191
194
  lastActivity: "2024-01-01T00:01:00Z",
192
195
  escalationLevel: 0,
193
196
  stalledSince: null,
197
+ transcriptPath: null,
194
198
  };
195
199
 
196
200
  const completed: AgentSession = {
@@ -210,6 +214,7 @@ describe("discoverAgents", () => {
210
214
  lastActivity: "2024-01-01T00:02:00Z",
211
215
  escalationLevel: 0,
212
216
  stalledSince: null,
217
+ transcriptPath: null,
213
218
  };
214
219
 
215
220
  store.upsert(working);
@@ -159,6 +159,7 @@ describe("--all", () => {
159
159
  lastActivity: new Date().toISOString(),
160
160
  escalationLevel: 0,
161
161
  stalledSince: null,
162
+ transcriptPath: null,
162
163
  });
163
164
  store.close();
164
165
 
@@ -303,6 +304,7 @@ describe("individual flags", () => {
303
304
  lastActivity: new Date().toISOString(),
304
305
  escalationLevel: 0,
305
306
  stalledSince: null,
307
+ transcriptPath: null,
306
308
  });
307
309
  store.close();
308
310
 
@@ -424,6 +426,7 @@ describe("synthetic session-end events", () => {
424
426
  lastActivity: new Date().toISOString(),
425
427
  escalationLevel: 0,
426
428
  stalledSince: null,
429
+ transcriptPath: null,
427
430
  ...overrides,
428
431
  };
429
432
  }
@@ -356,7 +356,7 @@ export const COMMANDS: readonly CommandDef[] = [
356
356
  },
357
357
  {
358
358
  name: "supervisor",
359
- desc: "Per-project supervisor agent",
359
+ desc: "[DEPRECATED] Per-project supervisor agent",
360
360
  flags: [
361
361
  { name: "--json", desc: "JSON output" },
362
362
  { name: "--help", desc: "Show help" },
@@ -297,6 +297,7 @@ function makeCoordinatorSession(overrides: Partial<AgentSession> = {}): AgentSes
297
297
  lastActivity: new Date().toISOString(),
298
298
  escalationLevel: 0,
299
299
  stalledSince: null,
300
+ transcriptPath: null,
300
301
  ...overrides,
301
302
  };
302
303
  }
@@ -15,7 +15,6 @@
15
15
  import { mkdir, unlink } from "node:fs/promises";
16
16
  import { join } from "node:path";
17
17
  import { Command } from "commander";
18
- import { deployHooks } from "../agents/hooks-deployer.ts";
19
18
  import { createIdentity, loadIdentity } from "../agents/identity.ts";
20
19
  import { createManifestLoader, resolveModel } from "../agents/manifest.ts";
21
20
  import { loadConfig } from "../config.ts";
@@ -320,13 +319,26 @@ async function startCoordinator(
320
319
  store.updateState(COORDINATOR_NAME, "completed");
321
320
  }
322
321
 
322
+ // Resolve model and runtime early (needed for deployConfig and spawn)
323
+ const manifestLoader = createManifestLoader(
324
+ join(projectRoot, config.agents.manifestPath),
325
+ join(projectRoot, config.agents.baseDir),
326
+ );
327
+ const manifest = await manifestLoader.load();
328
+ const resolvedModel = resolveModel(config, manifest, "coordinator", "opus");
329
+ const runtime = getRuntime(undefined, config);
330
+
323
331
  // Deploy hooks to the project root so the coordinator gets event logging,
324
332
  // mail check --inject, and activity tracking via the standard hook pipeline.
325
333
  // The ENV_GUARD prefix on all hooks (both template and generated guards)
326
334
  // ensures they only activate when OVERSTORY_AGENT_NAME is set (i.e. for
327
335
  // the coordinator's tmux session), so the user's own Claude Code session
328
336
  // at the project root is unaffected.
329
- await deployHooks(projectRoot, COORDINATOR_NAME, "coordinator");
337
+ await runtime.deployConfig(projectRoot, undefined, {
338
+ agentName: COORDINATOR_NAME,
339
+ capability: "coordinator",
340
+ worktreePath: projectRoot,
341
+ });
330
342
 
331
343
  // Create coordinator identity if first run
332
344
  const identityBaseDir = join(projectRoot, ".overstory", "agents");
@@ -343,15 +355,6 @@ async function startCoordinator(
343
355
  });
344
356
  }
345
357
 
346
- // Resolve model from config > manifest > fallback
347
- const manifestLoader = createManifestLoader(
348
- join(projectRoot, config.agents.manifestPath),
349
- join(projectRoot, config.agents.baseDir),
350
- );
351
- const manifest = await manifestLoader.load();
352
- const resolvedModel = resolveModel(config, manifest, "coordinator", "opus");
353
- const runtime = getRuntime(undefined, config);
354
-
355
358
  // Preflight: verify tmux is installed before attempting to spawn.
356
359
  // Without this check, a missing tmux leads to cryptic errors later.
357
360
  await tmux.ensureTmuxAvailable();
@@ -402,6 +405,7 @@ async function startCoordinator(
402
405
  lastActivity: new Date().toISOString(),
403
406
  escalationLevel: 0,
404
407
  stalledSince: null,
408
+ transcriptPath: null,
405
409
  };
406
410
 
407
411
  store.upsert(session);
@@ -780,6 +780,7 @@ describe("costsCommand", () => {
780
780
  lastActivity: new Date().toISOString(),
781
781
  escalationLevel: 0,
782
782
  stalledSince: null,
783
+ transcriptPath: null,
783
784
  });
784
785
  sessionStore.close();
785
786
 
@@ -836,6 +837,7 @@ describe("costsCommand", () => {
836
837
  lastActivity: new Date().toISOString(),
837
838
  escalationLevel: 0,
838
839
  stalledSince: null,
840
+ transcriptPath: null,
839
841
  });
840
842
  sessionStore.close();
841
843
 
@@ -900,6 +902,7 @@ describe("costsCommand", () => {
900
902
  lastActivity: new Date().toISOString(),
901
903
  escalationLevel: 0,
902
904
  stalledSince: null,
905
+ transcriptPath: null,
903
906
  });
904
907
  sessionStore.upsert({
905
908
  id: "sess-002",
@@ -918,6 +921,7 @@ describe("costsCommand", () => {
918
921
  lastActivity: new Date().toISOString(),
919
922
  escalationLevel: 0,
920
923
  stalledSince: null,
924
+ transcriptPath: null,
921
925
  });
922
926
  sessionStore.close();
923
927
 
@@ -977,6 +981,7 @@ describe("costsCommand", () => {
977
981
  lastActivity: new Date().toISOString(),
978
982
  escalationLevel: 0,
979
983
  stalledSince: null,
984
+ transcriptPath: null,
980
985
  });
981
986
  sessionStore.close();
982
987
 
@@ -17,7 +17,6 @@ const AGENT_DEF_FILES = [
17
17
  "reviewer.md",
18
18
  "lead.md",
19
19
  "merger.md",
20
- "supervisor.md",
21
20
  "coordinator.md",
22
21
  "monitor.md",
23
22
  ];
@@ -46,7 +45,7 @@ describe("initCommand: agent-defs deployment", () => {
46
45
  await cleanupTempDir(tempDir);
47
46
  });
48
47
 
49
- test("creates .overstory/agent-defs/ with all 8 agent definition files", async () => {
48
+ test("creates .overstory/agent-defs/ with all 7 agent definition files (supervisor deprecated)", async () => {
50
49
  await initCommand({});
51
50
 
52
51
  const agentDefsDir = join(tempDir, ".overstory", "agent-defs");
@@ -241,14 +241,6 @@ function buildAgentManifest(): AgentManifest {
241
241
  canSpawn: true,
242
242
  constraints: ["read-only", "no-worktree"],
243
243
  },
244
- supervisor: {
245
- file: "supervisor.md",
246
- model: "opus",
247
- tools: ["Read", "Write", "Edit", "Glob", "Grep", "Bash", "Task"],
248
- capabilities: ["coordinate", "supervise"],
249
- canSpawn: true,
250
- constraints: [],
251
- },
252
244
  monitor: {
253
245
  file: "monitor.md",
254
246
  model: "sonnet",
@@ -595,6 +587,7 @@ export async function initCommand(opts: InitOptions): Promise<void> {
595
587
  const agentDefFiles = await readdir(overstoryAgentsDir);
596
588
  for (const fileName of agentDefFiles) {
597
589
  if (!fileName.endsWith(".md")) continue;
590
+ if (fileName === "supervisor.md") continue; // Deprecated: not deployed to new projects
598
591
  const source = Bun.file(join(overstoryAgentsDir, fileName));
599
592
  const content = await source.text();
600
593
  await Bun.write(join(agentDefsTarget, fileName), content);
@@ -153,6 +153,7 @@ describe("inspectCommand", () => {
153
153
  lastActivity: new Date().toISOString(),
154
154
  escalationLevel: 0,
155
155
  stalledSince: null,
156
+ transcriptPath: null,
156
157
  });
157
158
  store.close();
158
159
 
@@ -185,6 +186,7 @@ describe("inspectCommand", () => {
185
186
  lastActivity: new Date().toISOString(),
186
187
  escalationLevel: 0,
187
188
  stalledSince: null,
189
+ transcriptPath: null,
188
190
  });
189
191
  store.close();
190
192
 
@@ -221,6 +223,7 @@ describe("inspectCommand", () => {
221
223
  lastActivity: new Date(Date.now() - 5_000).toISOString(),
222
224
  escalationLevel: 0,
223
225
  stalledSince: null,
226
+ transcriptPath: null,
224
227
  });
225
228
  store.close();
226
229
 
@@ -257,6 +260,7 @@ describe("inspectCommand", () => {
257
260
  lastActivity: new Date().toISOString(),
258
261
  escalationLevel: 0,
259
262
  stalledSince: null,
263
+ transcriptPath: null,
260
264
  });
261
265
  store.close();
262
266
 
@@ -296,6 +300,7 @@ describe("inspectCommand", () => {
296
300
  lastActivity: new Date().toISOString(),
297
301
  escalationLevel: 0,
298
302
  stalledSince: null,
303
+ transcriptPath: null,
299
304
  });
300
305
  store.close();
301
306
 
@@ -331,6 +336,7 @@ describe("inspectCommand", () => {
331
336
  lastActivity: new Date().toISOString(),
332
337
  escalationLevel: 0,
333
338
  stalledSince: null,
339
+ transcriptPath: null,
334
340
  });
335
341
  store.close();
336
342
 
@@ -366,6 +372,7 @@ describe("inspectCommand", () => {
366
372
  lastActivity: new Date().toISOString(),
367
373
  escalationLevel: 0,
368
374
  stalledSince: null,
375
+ transcriptPath: null,
369
376
  });
370
377
  store.close();
371
378
 
@@ -410,6 +417,7 @@ describe("inspectCommand", () => {
410
417
  lastActivity: new Date().toISOString(),
411
418
  escalationLevel: 0,
412
419
  stalledSince: null,
420
+ transcriptPath: null,
413
421
  });
414
422
  store.close();
415
423
 
@@ -453,6 +461,7 @@ describe("inspectCommand", () => {
453
461
  lastActivity: new Date().toISOString(),
454
462
  escalationLevel: 0,
455
463
  stalledSince: null,
464
+ transcriptPath: null,
456
465
  });
457
466
  store.close();
458
467
 
@@ -502,6 +511,7 @@ describe("inspectCommand", () => {
502
511
  lastActivity: new Date().toISOString(),
503
512
  escalationLevel: 0,
504
513
  stalledSince: null,
514
+ transcriptPath: null,
505
515
  });
506
516
  store.close();
507
517
 
@@ -539,6 +549,7 @@ describe("inspectCommand", () => {
539
549
  lastActivity: new Date().toISOString(),
540
550
  escalationLevel: 0,
541
551
  stalledSince: null,
552
+ transcriptPath: null,
542
553
  });
543
554
  store.close();
544
555
 
@@ -577,6 +588,7 @@ describe("inspectCommand", () => {
577
588
  lastActivity: new Date().toISOString(),
578
589
  escalationLevel: 0,
579
590
  stalledSince: null,
591
+ transcriptPath: null,
580
592
  });
581
593
  store.close();
582
594
 
@@ -614,6 +626,7 @@ describe("inspectCommand", () => {
614
626
  lastActivity: new Date().toISOString(),
615
627
  escalationLevel: 0,
616
628
  stalledSince: null,
629
+ transcriptPath: null,
617
630
  });
618
631
  store.close();
619
632
 
@@ -652,6 +665,7 @@ describe("inspectCommand", () => {
652
665
  lastActivity: new Date().toISOString(),
653
666
  escalationLevel: 0,
654
667
  stalledSince: null,
668
+ transcriptPath: null,
655
669
  });
656
670
  store.close();
657
671
 
@@ -229,6 +229,7 @@ describe("logCommand", () => {
229
229
  lastActivity: new Date().toISOString(),
230
230
  escalationLevel: 0,
231
231
  stalledSince: null,
232
+ transcriptPath: null,
232
233
  };
233
234
  const store = createSessionStore(dbPath);
234
235
  store.upsert(session);
@@ -284,6 +285,7 @@ describe("logCommand", () => {
284
285
  lastActivity: new Date().toISOString(),
285
286
  escalationLevel: 0,
286
287
  stalledSince: null,
288
+ transcriptPath: null,
287
289
  };
288
290
  const sessStore = createSessionStore(sessionsDbPath);
289
291
  sessStore.upsert(session);
@@ -324,6 +326,7 @@ describe("logCommand", () => {
324
326
  lastActivity: new Date(Date.now() - 60_000).toISOString(),
325
327
  escalationLevel: 0,
326
328
  stalledSince: null,
329
+ transcriptPath: null,
327
330
  };
328
331
  const store = createSessionStore(dbPath);
329
332
  store.upsert(session);
@@ -363,6 +366,7 @@ describe("logCommand", () => {
363
366
  lastActivity: new Date(Date.now() - 60_000).toISOString(),
364
367
  escalationLevel: 0,
365
368
  stalledSince: null,
369
+ transcriptPath: null,
366
370
  };
367
371
  const store = createSessionStore(dbPath);
368
372
  store.upsert(session);
@@ -400,6 +404,7 @@ describe("logCommand", () => {
400
404
  lastActivity: new Date().toISOString(),
401
405
  escalationLevel: 0,
402
406
  stalledSince: null,
407
+ transcriptPath: null,
403
408
  });
404
409
  sessionStoreLocal.close();
405
410
 
@@ -457,6 +462,7 @@ describe("logCommand", () => {
457
462
  lastActivity: new Date().toISOString(),
458
463
  escalationLevel: 0,
459
464
  stalledSince: null,
465
+ transcriptPath: null,
460
466
  });
461
467
  sessionStoreLocal.close();
462
468
 
@@ -487,6 +493,7 @@ describe("logCommand", () => {
487
493
  lastActivity: new Date().toISOString(),
488
494
  escalationLevel: 0,
489
495
  stalledSince: null,
496
+ transcriptPath: null,
490
497
  });
491
498
  sessionStoreLocal.close();
492
499
 
@@ -541,6 +548,7 @@ describe("logCommand", () => {
541
548
  lastActivity: new Date().toISOString(),
542
549
  escalationLevel: 0,
543
550
  stalledSince: null,
551
+ transcriptPath: null,
544
552
  });
545
553
  sessionStoreLocal.close();
546
554
 
@@ -594,6 +602,7 @@ describe("logCommand", () => {
594
602
  lastActivity: new Date().toISOString(),
595
603
  escalationLevel: 0,
596
604
  stalledSince: null,
605
+ transcriptPath: null,
597
606
  };
598
607
  const store = createSessionStore(dbPath);
599
608
  store.upsert(session);
@@ -634,6 +643,7 @@ describe("logCommand", () => {
634
643
  lastActivity: new Date().toISOString(),
635
644
  escalationLevel: 0,
636
645
  stalledSince: null,
646
+ transcriptPath: null,
637
647
  };
638
648
  const store = createSessionStore(dbPath);
639
649
  store.upsert(session);
@@ -676,6 +686,7 @@ describe("logCommand", () => {
676
686
  lastActivity: oldTimestamp,
677
687
  escalationLevel: 0,
678
688
  stalledSince: null,
689
+ transcriptPath: null,
679
690
  };
680
691
  const store = createSessionStore(dbPath);
681
692
  store.upsert(session);
@@ -715,6 +726,7 @@ describe("logCommand", () => {
715
726
  lastActivity: new Date().toISOString(),
716
727
  escalationLevel: 0,
717
728
  stalledSince: null,
729
+ transcriptPath: null,
718
730
  };
719
731
  const store = createSessionStore(dbPath);
720
732
  store.upsert(session);
@@ -800,6 +812,7 @@ describe("logCommand", () => {
800
812
  lastActivity: new Date().toISOString(),
801
813
  escalationLevel: 0,
802
814
  stalledSince: null,
815
+ transcriptPath: null,
803
816
  };
804
817
  const store = createSessionStore(dbPath);
805
818
  store.upsert(session);
@@ -839,6 +852,7 @@ describe("logCommand", () => {
839
852
  lastActivity: new Date().toISOString(),
840
853
  escalationLevel: 0,
841
854
  stalledSince: null,
855
+ transcriptPath: null,
842
856
  };
843
857
  const store = createSessionStore(dbPath);
844
858
  store.upsert(session);