@os-eco/overstory-cli 0.6.4 → 0.6.6

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 (117) hide show
  1. package/README.md +61 -61
  2. package/agents/builder.md +16 -16
  3. package/agents/coordinator.md +57 -57
  4. package/agents/issue-reviews.md +71 -0
  5. package/agents/lead.md +43 -42
  6. package/agents/merger.md +15 -15
  7. package/agents/monitor.md +37 -37
  8. package/agents/pr-reviews.md +60 -0
  9. package/agents/prioritize.md +110 -0
  10. package/agents/release.md +56 -0
  11. package/agents/reviewer.md +15 -15
  12. package/agents/scout.md +18 -18
  13. package/agents/supervisor.md +78 -78
  14. package/package.json +1 -1
  15. package/src/agents/checkpoint.test.ts +2 -2
  16. package/src/agents/hooks-deployer.test.ts +59 -25
  17. package/src/agents/hooks-deployer.ts +24 -6
  18. package/src/agents/identity.test.ts +27 -27
  19. package/src/agents/identity.ts +10 -10
  20. package/src/agents/lifecycle.test.ts +6 -6
  21. package/src/agents/lifecycle.ts +2 -2
  22. package/src/agents/overlay.test.ts +14 -14
  23. package/src/agents/overlay.ts +14 -14
  24. package/src/commands/agents.test.ts +5 -5
  25. package/src/commands/agents.ts +10 -9
  26. package/src/commands/clean.test.ts +5 -5
  27. package/src/commands/clean.ts +5 -5
  28. package/src/commands/completions.test.ts +10 -10
  29. package/src/commands/completions.ts +26 -28
  30. package/src/commands/coordinator.test.ts +4 -4
  31. package/src/commands/coordinator.ts +13 -13
  32. package/src/commands/costs.test.ts +45 -45
  33. package/src/commands/costs.ts +1 -1
  34. package/src/commands/dashboard.ts +11 -11
  35. package/src/commands/doctor.ts +4 -4
  36. package/src/commands/errors.ts +1 -1
  37. package/src/commands/feed.ts +1 -1
  38. package/src/commands/group.ts +3 -3
  39. package/src/commands/hooks.test.ts +7 -7
  40. package/src/commands/hooks.ts +7 -7
  41. package/src/commands/init.test.ts +6 -2
  42. package/src/commands/init.ts +19 -19
  43. package/src/commands/inspect.test.ts +16 -16
  44. package/src/commands/inspect.ts +19 -19
  45. package/src/commands/log.test.ts +21 -21
  46. package/src/commands/log.ts +10 -10
  47. package/src/commands/logs.ts +1 -1
  48. package/src/commands/mail.test.ts +7 -7
  49. package/src/commands/mail.ts +28 -11
  50. package/src/commands/merge.test.ts +8 -8
  51. package/src/commands/merge.ts +15 -15
  52. package/src/commands/metrics.test.ts +7 -7
  53. package/src/commands/metrics.ts +3 -3
  54. package/src/commands/monitor.test.ts +5 -5
  55. package/src/commands/monitor.ts +5 -5
  56. package/src/commands/nudge.test.ts +1 -1
  57. package/src/commands/nudge.ts +1 -1
  58. package/src/commands/prime.test.ts +5 -5
  59. package/src/commands/prime.ts +8 -8
  60. package/src/commands/replay.ts +1 -1
  61. package/src/commands/run.test.ts +1 -1
  62. package/src/commands/run.ts +2 -2
  63. package/src/commands/sling.test.ts +89 -7
  64. package/src/commands/sling.ts +109 -18
  65. package/src/commands/spec.test.ts +2 -2
  66. package/src/commands/spec.ts +13 -14
  67. package/src/commands/status.test.ts +99 -3
  68. package/src/commands/status.ts +19 -20
  69. package/src/commands/stop.test.ts +1 -1
  70. package/src/commands/stop.ts +2 -2
  71. package/src/commands/supervisor.test.ts +10 -10
  72. package/src/commands/supervisor.ts +14 -14
  73. package/src/commands/trace.test.ts +7 -7
  74. package/src/commands/trace.ts +10 -10
  75. package/src/commands/watch.ts +5 -5
  76. package/src/commands/worktree.test.ts +208 -32
  77. package/src/commands/worktree.ts +56 -18
  78. package/src/doctor/consistency.test.ts +14 -14
  79. package/src/doctor/dependencies.test.ts +5 -5
  80. package/src/doctor/dependencies.ts +2 -2
  81. package/src/doctor/logs.ts +1 -1
  82. package/src/doctor/merge-queue.test.ts +4 -4
  83. package/src/doctor/structure.test.ts +1 -1
  84. package/src/doctor/structure.ts +1 -1
  85. package/src/doctor/version.test.ts +3 -3
  86. package/src/doctor/version.ts +1 -1
  87. package/src/e2e/init-sling-lifecycle.test.ts +8 -4
  88. package/src/errors.ts +1 -1
  89. package/src/index.ts +13 -11
  90. package/src/mail/broadcast.test.ts +1 -1
  91. package/src/mail/client.test.ts +7 -7
  92. package/src/mail/client.ts +2 -2
  93. package/src/mail/store.test.ts +3 -3
  94. package/src/merge/queue.test.ts +12 -12
  95. package/src/merge/queue.ts +2 -2
  96. package/src/merge/resolver.test.ts +159 -7
  97. package/src/merge/resolver.ts +46 -2
  98. package/src/metrics/store.test.ts +44 -44
  99. package/src/metrics/store.ts +2 -2
  100. package/src/metrics/summary.test.ts +35 -35
  101. package/src/mulch/client.test.ts +1 -1
  102. package/src/mulch/client.ts +1 -1
  103. package/src/sessions/compat.test.ts +3 -3
  104. package/src/sessions/compat.ts +1 -1
  105. package/src/sessions/store.test.ts +4 -4
  106. package/src/sessions/store.ts +2 -2
  107. package/src/types.ts +14 -14
  108. package/src/watchdog/daemon.test.ts +10 -10
  109. package/src/watchdog/daemon.ts +1 -1
  110. package/src/watchdog/health.test.ts +1 -1
  111. package/src/worktree/manager.test.ts +20 -20
  112. package/src/worktree/manager.ts +120 -4
  113. package/src/worktree/tmux.test.ts +8 -3
  114. package/src/worktree/tmux.ts +19 -18
  115. package/templates/CLAUDE.md.tmpl +27 -27
  116. package/templates/hooks.json.tmpl +15 -11
  117. package/templates/overlay.md.tmpl +7 -7
@@ -33,7 +33,7 @@ afterEach(async () => {
33
33
  function makeSession(overrides: Partial<SessionMetrics> = {}): SessionMetrics {
34
34
  return {
35
35
  agentName: "test-agent",
36
- beadId: "test-task-123",
36
+ taskId: "test-task-123",
37
37
  capability: "builder",
38
38
  startedAt: new Date("2026-01-01T00:00:00Z").toISOString(),
39
39
  completedAt: new Date("2026-01-01T00:05:00Z").toISOString(),
@@ -66,9 +66,9 @@ describe("generateSummary", () => {
66
66
  });
67
67
 
68
68
  test("counts total and completed sessions correctly", () => {
69
- store.recordSession(makeSession({ beadId: "task-1", completedAt: "2026-01-01T00:05:00Z" }));
70
- store.recordSession(makeSession({ beadId: "task-2", completedAt: null }));
71
- store.recordSession(makeSession({ beadId: "task-3", completedAt: "2026-01-01T00:10:00Z" }));
69
+ store.recordSession(makeSession({ taskId: "task-1", completedAt: "2026-01-01T00:05:00Z" }));
70
+ store.recordSession(makeSession({ taskId: "task-2", completedAt: null }));
71
+ store.recordSession(makeSession({ taskId: "task-3", completedAt: "2026-01-01T00:10:00Z" }));
72
72
 
73
73
  const summary = generateSummary(store);
74
74
 
@@ -79,21 +79,21 @@ describe("generateSummary", () => {
79
79
  test("groups by capability with correct counts and avg durations", () => {
80
80
  store.recordSession(
81
81
  makeSession({
82
- beadId: "task-1",
82
+ taskId: "task-1",
83
83
  capability: "builder",
84
84
  durationMs: 100_000,
85
85
  }),
86
86
  );
87
87
  store.recordSession(
88
88
  makeSession({
89
- beadId: "task-2",
89
+ taskId: "task-2",
90
90
  capability: "builder",
91
91
  durationMs: 200_000,
92
92
  }),
93
93
  );
94
94
  store.recordSession(
95
95
  makeSession({
96
- beadId: "task-3",
96
+ taskId: "task-3",
97
97
  capability: "scout",
98
98
  durationMs: 50_000,
99
99
  }),
@@ -112,10 +112,10 @@ describe("generateSummary", () => {
112
112
  });
113
113
 
114
114
  test("respects the limit parameter for recentSessions", () => {
115
- store.recordSession(makeSession({ beadId: "task-1" }));
116
- store.recordSession(makeSession({ beadId: "task-2" }));
117
- store.recordSession(makeSession({ beadId: "task-3" }));
118
- store.recordSession(makeSession({ beadId: "task-4" }));
115
+ store.recordSession(makeSession({ taskId: "task-1" }));
116
+ store.recordSession(makeSession({ taskId: "task-2" }));
117
+ store.recordSession(makeSession({ taskId: "task-3" }));
118
+ store.recordSession(makeSession({ taskId: "task-4" }));
119
119
 
120
120
  const summary = generateSummary(store, 2);
121
121
 
@@ -124,9 +124,9 @@ describe("generateSummary", () => {
124
124
  });
125
125
 
126
126
  test("sessions without completedAt counted in total but not completed", () => {
127
- store.recordSession(makeSession({ beadId: "task-1", completedAt: null }));
128
- store.recordSession(makeSession({ beadId: "task-2", completedAt: null }));
129
- store.recordSession(makeSession({ beadId: "task-3", completedAt: "2026-01-01T00:05:00Z" }));
127
+ store.recordSession(makeSession({ taskId: "task-1", completedAt: null }));
128
+ store.recordSession(makeSession({ taskId: "task-2", completedAt: null }));
129
+ store.recordSession(makeSession({ taskId: "task-3", completedAt: "2026-01-01T00:05:00Z" }));
130
130
 
131
131
  const summary = generateSummary(store);
132
132
 
@@ -137,7 +137,7 @@ describe("generateSummary", () => {
137
137
  test("aggregates token totals across all sessions", () => {
138
138
  store.recordSession(
139
139
  makeSession({
140
- beadId: "task-1",
140
+ taskId: "task-1",
141
141
  inputTokens: 10_000,
142
142
  outputTokens: 2_000,
143
143
  cacheReadTokens: 50_000,
@@ -147,7 +147,7 @@ describe("generateSummary", () => {
147
147
  );
148
148
  store.recordSession(
149
149
  makeSession({
150
- beadId: "task-2",
150
+ taskId: "task-2",
151
151
  inputTokens: 20_000,
152
152
  outputTokens: 3_000,
153
153
  cacheReadTokens: 80_000,
@@ -166,7 +166,7 @@ describe("generateSummary", () => {
166
166
  });
167
167
 
168
168
  test("token totals are zero when no sessions have token data", () => {
169
- store.recordSession(makeSession({ beadId: "task-1" }));
169
+ store.recordSession(makeSession({ taskId: "task-1" }));
170
170
 
171
171
  const summary = generateSummary(store);
172
172
 
@@ -180,14 +180,14 @@ describe("generateSummary", () => {
180
180
  test("token totals skip null cost entries gracefully", () => {
181
181
  store.recordSession(
182
182
  makeSession({
183
- beadId: "task-1",
183
+ taskId: "task-1",
184
184
  inputTokens: 100,
185
185
  estimatedCostUsd: 0.5,
186
186
  }),
187
187
  );
188
188
  store.recordSession(
189
189
  makeSession({
190
- beadId: "task-2",
190
+ taskId: "task-2",
191
191
  inputTokens: 200,
192
192
  estimatedCostUsd: null, // no cost data
193
193
  }),
@@ -202,7 +202,7 @@ describe("generateSummary", () => {
202
202
  test("capability breakdown excludes incomplete sessions from avgDurationMs", () => {
203
203
  store.recordSession(
204
204
  makeSession({
205
- beadId: "task-1",
205
+ taskId: "task-1",
206
206
  capability: "builder",
207
207
  durationMs: 100_000,
208
208
  completedAt: null,
@@ -210,14 +210,14 @@ describe("generateSummary", () => {
210
210
  );
211
211
  store.recordSession(
212
212
  makeSession({
213
- beadId: "task-2",
213
+ taskId: "task-2",
214
214
  capability: "builder",
215
215
  durationMs: 200_000,
216
216
  }),
217
217
  );
218
218
  store.recordSession(
219
219
  makeSession({
220
- beadId: "task-3",
220
+ taskId: "task-3",
221
221
  capability: "builder",
222
222
  durationMs: 300_000,
223
223
  }),
@@ -242,8 +242,8 @@ describe("formatSummary", () => {
242
242
  });
243
243
 
244
244
  test("shows total/completed/average duration", () => {
245
- store.recordSession(makeSession({ beadId: "task-1", durationMs: 100_000 }));
246
- store.recordSession(makeSession({ beadId: "task-2", durationMs: 200_000 }));
245
+ store.recordSession(makeSession({ taskId: "task-1", durationMs: 100_000 }));
246
+ store.recordSession(makeSession({ taskId: "task-2", durationMs: 200_000 }));
247
247
 
248
248
  const summary = generateSummary(store);
249
249
  const formatted = formatSummary(summary);
@@ -254,8 +254,8 @@ describe("formatSummary", () => {
254
254
  });
255
255
 
256
256
  test("shows capability breakdown", () => {
257
- store.recordSession(makeSession({ beadId: "task-1", capability: "builder" }));
258
- store.recordSession(makeSession({ beadId: "task-2", capability: "scout" }));
257
+ store.recordSession(makeSession({ taskId: "task-1", capability: "builder" }));
258
+ store.recordSession(makeSession({ taskId: "task-2", capability: "scout" }));
259
259
 
260
260
  const summary = generateSummary(store);
261
261
  const formatted = formatSummary(summary);
@@ -268,14 +268,14 @@ describe("formatSummary", () => {
268
268
  test("shows recent sessions with status (done vs running)", () => {
269
269
  store.recordSession(
270
270
  makeSession({
271
- beadId: "task-1",
271
+ taskId: "task-1",
272
272
  agentName: "agent-done",
273
273
  completedAt: "2026-01-01T00:05:00Z",
274
274
  }),
275
275
  );
276
276
  store.recordSession(
277
277
  makeSession({
278
- beadId: "task-2",
278
+ taskId: "task-2",
279
279
  agentName: "agent-running",
280
280
  completedAt: null,
281
281
  }),
@@ -293,7 +293,7 @@ describe("formatSummary", () => {
293
293
  });
294
294
 
295
295
  test("formatDuration: <1000ms shows ms", () => {
296
- store.recordSession(makeSession({ beadId: "task-1", durationMs: 500 }));
296
+ store.recordSession(makeSession({ taskId: "task-1", durationMs: 500 }));
297
297
 
298
298
  const summary = generateSummary(store);
299
299
  const formatted = formatSummary(summary);
@@ -302,7 +302,7 @@ describe("formatSummary", () => {
302
302
  });
303
303
 
304
304
  test("formatDuration: <60000ms shows seconds", () => {
305
- store.recordSession(makeSession({ beadId: "task-1", durationMs: 5_500 }));
305
+ store.recordSession(makeSession({ taskId: "task-1", durationMs: 5_500 }));
306
306
 
307
307
  const summary = generateSummary(store);
308
308
  const formatted = formatSummary(summary);
@@ -311,7 +311,7 @@ describe("formatSummary", () => {
311
311
  });
312
312
 
313
313
  test("formatDuration: >=60000ms shows minutes+seconds", () => {
314
- store.recordSession(makeSession({ beadId: "task-1", durationMs: 125_000 }));
314
+ store.recordSession(makeSession({ taskId: "task-1", durationMs: 125_000 }));
315
315
 
316
316
  const summary = generateSummary(store);
317
317
  const formatted = formatSummary(summary);
@@ -322,7 +322,7 @@ describe("formatSummary", () => {
322
322
  test("shows token usage section when sessions have token data", () => {
323
323
  store.recordSession(
324
324
  makeSession({
325
- beadId: "task-1",
325
+ taskId: "task-1",
326
326
  inputTokens: 15_000,
327
327
  outputTokens: 3_000,
328
328
  cacheReadTokens: 100_000,
@@ -344,7 +344,7 @@ describe("formatSummary", () => {
344
344
  });
345
345
 
346
346
  test("hides token usage section when no token data exists", () => {
347
- store.recordSession(makeSession({ beadId: "task-1" }));
347
+ store.recordSession(makeSession({ taskId: "task-1" }));
348
348
 
349
349
  const summary = generateSummary(store);
350
350
  const formatted = formatSummary(summary);
@@ -355,7 +355,7 @@ describe("formatSummary", () => {
355
355
  test("shows per-session cost in recent sessions", () => {
356
356
  store.recordSession(
357
357
  makeSession({
358
- beadId: "task-1",
358
+ taskId: "task-1",
359
359
  agentName: "agent-costly",
360
360
  inputTokens: 10_000,
361
361
  outputTokens: 2_000,
@@ -373,7 +373,7 @@ describe("formatSummary", () => {
373
373
  test("formats large token counts with M suffix", () => {
374
374
  store.recordSession(
375
375
  makeSession({
376
- beadId: "task-1",
376
+ taskId: "task-1",
377
377
  inputTokens: 2_500_000,
378
378
  outputTokens: 500_000,
379
379
  cacheReadTokens: 0,
@@ -360,7 +360,7 @@ describe("createMulchClient", () => {
360
360
  await addProc.exited;
361
361
 
362
362
  const client = createMulchClient(tempDir);
363
- // The flag is passed correctly, but may fail if the bead ID is invalid
363
+ // The flag is passed correctly, but may fail if the task ID is invalid
364
364
  // or if other required fields are missing. This test documents that the
365
365
  // flag is properly passed to the CLI.
366
366
  try {
@@ -116,7 +116,7 @@ export function createMulchClient(cwd: string): MulchClient {
116
116
  args: string[],
117
117
  context: string,
118
118
  ): Promise<{ stdout: string; stderr: string }> {
119
- const { stdout, stderr, exitCode } = await runCommand(["mulch", ...args], cwd);
119
+ const { stdout, stderr, exitCode } = await runCommand(["ml", ...args], cwd);
120
120
  if (exitCode !== 0) {
121
121
  throw new AgentError(`mulch ${context} failed (exit ${exitCode}): ${stderr.trim()}`);
122
122
  }
@@ -39,7 +39,7 @@ function makeJsonSession(overrides: Record<string, unknown> = {}): Record<string
39
39
  capability: "builder",
40
40
  worktreePath: "/tmp/worktrees/test-agent",
41
41
  branchName: "overstory/test-agent/task-1",
42
- beadId: "task-1",
42
+ taskId: "task-1",
43
43
  tmuxSession: "overstory-test-agent",
44
44
  state: "working",
45
45
  pid: 12345,
@@ -198,7 +198,7 @@ describe("data integrity", () => {
198
198
  capability: "scout",
199
199
  worktreePath: "/tmp/worktrees/full-agent",
200
200
  branchName: "overstory/full-agent/task-42",
201
- beadId: "task-42",
201
+ taskId: "task-42",
202
202
  tmuxSession: "overstory-full-agent",
203
203
  state: "stalled",
204
204
  pid: 99999,
@@ -221,7 +221,7 @@ describe("data integrity", () => {
221
221
  expect(result?.capability).toBe("scout");
222
222
  expect(result?.worktreePath).toBe("/tmp/worktrees/full-agent");
223
223
  expect(result?.branchName).toBe("overstory/full-agent/task-42");
224
- expect(result?.beadId).toBe("task-42");
224
+ expect(result?.taskId).toBe("task-42");
225
225
  expect(result?.tmuxSession).toBe("overstory-full-agent");
226
226
  expect(result?.state).toBe("stalled");
227
227
  expect(result?.pid).toBe(99999);
@@ -25,7 +25,7 @@ function normalizeSession(raw: Record<string, unknown>): AgentSession {
25
25
  capability: raw.capability as string,
26
26
  worktreePath: raw.worktreePath as string,
27
27
  branchName: raw.branchName as string,
28
- beadId: raw.beadId as string,
28
+ taskId: raw.taskId as string,
29
29
  tmuxSession: raw.tmuxSession as string,
30
30
  state: raw.state as AgentSession["state"],
31
31
  pid: (raw.pid as number | null) ?? null,
@@ -35,7 +35,7 @@ function makeSession(overrides: Partial<AgentSession> = {}): AgentSession {
35
35
  capability: "builder",
36
36
  worktreePath: "/tmp/worktrees/test-agent",
37
37
  branchName: "overstory/test-agent/task-1",
38
- beadId: "task-1",
38
+ taskId: "task-1",
39
39
  tmuxSession: "overstory-test-agent",
40
40
  state: "booting",
41
41
  pid: 12345,
@@ -81,7 +81,7 @@ describe("upsert", () => {
81
81
  capability: "scout",
82
82
  worktreePath: "/tmp/worktrees/roundtrip",
83
83
  branchName: "overstory/roundtrip-agent/task-42",
84
- beadId: "task-42",
84
+ taskId: "task-42",
85
85
  tmuxSession: "overstory-roundtrip-agent",
86
86
  state: "working",
87
87
  pid: 99999,
@@ -547,11 +547,11 @@ describe("edge cases", () => {
547
547
  });
548
548
 
549
549
  test("empty string fields are stored correctly", () => {
550
- const session = makeSession({ beadId: "", capability: "builder" });
550
+ const session = makeSession({ taskId: "", capability: "builder" });
551
551
  store.upsert(session);
552
552
 
553
553
  const result = store.getByName("test-agent");
554
- expect(result?.beadId).toBe("");
554
+ expect(result?.taskId).toBe("");
555
555
  });
556
556
  });
557
557
 
@@ -113,7 +113,7 @@ function rowToSession(row: SessionRow): AgentSession {
113
113
  capability: row.capability,
114
114
  worktreePath: row.worktree_path,
115
115
  branchName: row.branch_name,
116
- beadId: row.task_id,
116
+ taskId: row.task_id,
117
117
  tmuxSession: row.tmux_session,
118
118
  state: row.state as AgentState,
119
119
  pid: row.pid,
@@ -276,7 +276,7 @@ export function createSessionStore(dbPath: string): SessionStore {
276
276
  $capability: session.capability,
277
277
  $worktree_path: session.worktreePath,
278
278
  $branch_name: session.branchName,
279
- $task_id: session.beadId,
279
+ $task_id: session.taskId,
280
280
  $tmux_session: session.tmuxSession,
281
281
  $state: session.state,
282
282
  $pid: session.pid,
package/src/types.ts CHANGED
@@ -129,7 +129,7 @@ export interface AgentSession {
129
129
  capability: string; // Which agent definition
130
130
  worktreePath: string;
131
131
  branchName: string;
132
- beadId: string; // Task being worked
132
+ taskId: string; // Task being worked
133
133
  tmuxSession: string; // Tmux session name
134
134
  state: AgentState;
135
135
  pid: number | null; // Claude Code PID
@@ -151,7 +151,7 @@ export interface AgentIdentity {
151
151
  sessionsCompleted: number;
152
152
  expertiseDomains: string[];
153
153
  recentTasks: Array<{
154
- beadId: string;
154
+ taskId: string;
155
155
  summary: string;
156
156
  completedAt: string;
157
157
  }>;
@@ -210,7 +210,7 @@ export interface MailMessage {
210
210
 
211
211
  /** Worker signals task completion to supervisor. */
212
212
  export interface WorkerDonePayload {
213
- beadId: string;
213
+ taskId: string;
214
214
  branch: string;
215
215
  exitCode: number;
216
216
  filesModified: string[];
@@ -219,7 +219,7 @@ export interface WorkerDonePayload {
219
219
  /** Supervisor signals branch is verified and ready for merge. */
220
220
  export interface MergeReadyPayload {
221
221
  branch: string;
222
- beadId: string;
222
+ taskId: string;
223
223
  agentName: string;
224
224
  filesModified: string[];
225
225
  }
@@ -227,14 +227,14 @@ export interface MergeReadyPayload {
227
227
  /** Merger signals branch was merged successfully. */
228
228
  export interface MergedPayload {
229
229
  branch: string;
230
- beadId: string;
230
+ taskId: string;
231
231
  tier: ResolutionTier;
232
232
  }
233
233
 
234
234
  /** Merger signals merge failed, needs rework. */
235
235
  export interface MergeFailedPayload {
236
236
  branch: string;
237
- beadId: string;
237
+ taskId: string;
238
238
  conflictFiles: string[];
239
239
  errorMessage: string;
240
240
  }
@@ -242,7 +242,7 @@ export interface MergeFailedPayload {
242
242
  /** Any agent escalates an issue to a higher-level decision-maker. */
243
243
  export interface EscalationPayload {
244
244
  severity: "warning" | "error" | "critical";
245
- beadId: string | null;
245
+ taskId: string | null;
246
246
  context: string;
247
247
  }
248
248
 
@@ -254,7 +254,7 @@ export interface HealthCheckPayload {
254
254
 
255
255
  /** Coordinator dispatches work to a supervisor. */
256
256
  export interface DispatchPayload {
257
- beadId: string;
257
+ taskId: string;
258
258
  specPath: string;
259
259
  capability: Capability;
260
260
  fileScope: string[];
@@ -262,7 +262,7 @@ export interface DispatchPayload {
262
262
 
263
263
  /** Supervisor assigns work to a specific worker. */
264
264
  export interface AssignPayload {
265
- beadId: string;
265
+ taskId: string;
266
266
  specPath: string;
267
267
  workerName: string;
268
268
  branch: string;
@@ -284,7 +284,7 @@ export interface MailPayloadMap {
284
284
 
285
285
  export interface OverlayConfig {
286
286
  agentName: string;
287
- beadId: string;
287
+ taskId: string;
288
288
  specPath: string | null;
289
289
  branchName: string;
290
290
  worktreePath: string;
@@ -312,7 +312,7 @@ export type ResolutionTier = "clean-merge" | "auto-resolve" | "ai-resolve" | "re
312
312
 
313
313
  export interface MergeEntry {
314
314
  branchName: string;
315
- beadId: string;
315
+ taskId: string;
316
316
  agentName: string;
317
317
  filesModified: string[];
318
318
  enqueuedAt: string;
@@ -376,7 +376,7 @@ export interface LogEvent {
376
376
 
377
377
  export interface SessionMetrics {
378
378
  agentName: string;
379
- beadId: string;
379
+ taskId: string;
380
380
  capability: string;
381
381
  startedAt: string;
382
382
  completedAt: string | null;
@@ -645,7 +645,7 @@ export interface MulchCompactResult {
645
645
  */
646
646
  export interface SessionCheckpoint {
647
647
  agentName: string;
648
- beadId: string;
648
+ taskId: string;
649
649
  sessionId: string; // The AgentSession.id that created this checkpoint
650
650
  timestamp: string; // ISO
651
651
  progressSummary: string; // Human-readable summary of work done so far
@@ -677,7 +677,7 @@ export interface AgentLayers {
677
677
  sandbox: {
678
678
  worktreePath: string;
679
679
  branchName: string;
680
- beadId: string;
680
+ taskId: string;
681
681
  };
682
682
  session: {
683
683
  id: string;
@@ -66,7 +66,7 @@ function makeSession(overrides: Partial<AgentSession> = {}): AgentSession {
66
66
  capability: "builder",
67
67
  worktreePath: "/tmp/test",
68
68
  branchName: "overstory/test-agent/test-task",
69
- beadId: "test-task",
69
+ taskId: "test-task",
70
70
  tmuxSession: "overstory-test-agent",
71
71
  state: "working",
72
72
  pid: process.pid, // Use our own PID so isProcessRunning returns true
@@ -798,7 +798,7 @@ describe("daemon tick", () => {
798
798
  agentName: "old-agent",
799
799
  worktreePath: "/tmp/test",
800
800
  branchName: "overstory/old-agent/task",
801
- beadId: "task",
801
+ taskId: "task",
802
802
  tmuxSession: "overstory-old-agent",
803
803
  state: "working",
804
804
  pid: process.pid,
@@ -1133,7 +1133,7 @@ describe("daemon mulch failure recording", () => {
1133
1133
  const session = makeSession({
1134
1134
  agentName: "dying-agent",
1135
1135
  capability: "builder",
1136
- beadId: "task-123",
1136
+ taskId: "task-123",
1137
1137
  tmuxSession: "overstory-dying-agent",
1138
1138
  state: "working",
1139
1139
  lastActivity: new Date().toISOString(),
@@ -1158,7 +1158,7 @@ describe("daemon mulch failure recording", () => {
1158
1158
  expect(failureMock.calls[0]?.tier).toBe(0);
1159
1159
  expect(failureMock.calls[0]?.session.agentName).toBe("dying-agent");
1160
1160
  expect(failureMock.calls[0]?.session.capability).toBe("builder");
1161
- expect(failureMock.calls[0]?.session.beadId).toBe("task-123");
1161
+ expect(failureMock.calls[0]?.session.taskId).toBe("task-123");
1162
1162
  // Reason should be either the reconciliationNote or default "Process terminated"
1163
1163
  expect(failureMock.calls[0]?.reason).toBeDefined();
1164
1164
  });
@@ -1169,7 +1169,7 @@ describe("daemon mulch failure recording", () => {
1169
1169
  const session = makeSession({
1170
1170
  agentName: "triaged-agent",
1171
1171
  capability: "scout",
1172
- beadId: "task-456",
1172
+ taskId: "task-456",
1173
1173
  tmuxSession: "overstory-triaged-agent",
1174
1174
  state: "stalled",
1175
1175
  lastActivity: staleActivity,
@@ -1198,7 +1198,7 @@ describe("daemon mulch failure recording", () => {
1198
1198
  expect(failureMock.calls[0]?.tier).toBe(1);
1199
1199
  expect(failureMock.calls[0]?.session.agentName).toBe("triaged-agent");
1200
1200
  expect(failureMock.calls[0]?.session.capability).toBe("scout");
1201
- expect(failureMock.calls[0]?.session.beadId).toBe("task-456");
1201
+ expect(failureMock.calls[0]?.session.taskId).toBe("task-456");
1202
1202
  expect(failureMock.calls[0]?.triageSuggestion).toBe("terminate");
1203
1203
  expect(failureMock.calls[0]?.reason).toContain("AI triage");
1204
1204
  });
@@ -1267,11 +1267,11 @@ describe("daemon mulch failure recording", () => {
1267
1267
  expect(failureMock.calls).toHaveLength(0);
1268
1268
  });
1269
1269
 
1270
- test("recordFailure includes evidenceBead when beadId is present", async () => {
1270
+ test("recordFailure includes evidenceBead when taskId is present", async () => {
1271
1271
  const session = makeSession({
1272
1272
  agentName: "beaded-agent",
1273
1273
  capability: "builder",
1274
- beadId: "task-789",
1274
+ taskId: "task-789",
1275
1275
  tmuxSession: "overstory-beaded-agent",
1276
1276
  state: "working",
1277
1277
  lastActivity: new Date().toISOString(),
@@ -1292,7 +1292,7 @@ describe("daemon mulch failure recording", () => {
1292
1292
  });
1293
1293
 
1294
1294
  expect(failureMock.calls).toHaveLength(1);
1295
- expect(failureMock.calls[0]?.session.beadId).toBe("task-789");
1295
+ expect(failureMock.calls[0]?.session.taskId).toBe("task-789");
1296
1296
  });
1297
1297
 
1298
1298
  test("Tier 0: recordFailure called at escalation level 3+ (progressive termination)", async () => {
@@ -1301,7 +1301,7 @@ describe("daemon mulch failure recording", () => {
1301
1301
  const session = makeSession({
1302
1302
  agentName: "doomed-agent",
1303
1303
  capability: "builder",
1304
- beadId: "task-999",
1304
+ taskId: "task-999",
1305
1305
  tmuxSession: "overstory-doomed-agent",
1306
1306
  state: "stalled",
1307
1307
  lastActivity: staleActivity,
@@ -73,7 +73,7 @@ async function recordFailure(
73
73
  type: "failure",
74
74
  description,
75
75
  tags: ["watchdog", "auto-recorded"],
76
- evidenceBead: session.beadId || undefined,
76
+ evidenceBead: session.taskId || undefined,
77
77
  });
78
78
  } catch {
79
79
  // Fire-and-forget: recording failures must not break the watchdog
@@ -36,7 +36,7 @@ function makeSession(overrides: Partial<AgentSession> = {}): AgentSession {
36
36
  capability: "builder",
37
37
  worktreePath: "/tmp/test",
38
38
  branchName: "overstory/test-agent/test-task",
39
- beadId: "test-task",
39
+ taskId: "test-task",
40
40
  tmuxSession: "overstory-test-agent",
41
41
  state: "booting",
42
42
  pid: ALIVE_PID,