@os-eco/overstory-cli 0.6.5 → 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 (79) hide show
  1. package/README.md +60 -60
  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/hooks-deployer.test.ts +23 -26
  16. package/src/agents/hooks-deployer.ts +9 -5
  17. package/src/agents/overlay.test.ts +5 -5
  18. package/src/agents/overlay.ts +11 -11
  19. package/src/commands/agents.ts +7 -6
  20. package/src/commands/clean.ts +5 -5
  21. package/src/commands/completions.test.ts +10 -10
  22. package/src/commands/completions.ts +26 -28
  23. package/src/commands/coordinator.test.ts +2 -2
  24. package/src/commands/coordinator.ts +12 -12
  25. package/src/commands/costs.ts +1 -1
  26. package/src/commands/dashboard.ts +8 -8
  27. package/src/commands/doctor.ts +4 -4
  28. package/src/commands/errors.ts +1 -1
  29. package/src/commands/feed.ts +1 -1
  30. package/src/commands/group.ts +3 -3
  31. package/src/commands/hooks.test.ts +7 -7
  32. package/src/commands/hooks.ts +7 -7
  33. package/src/commands/init.test.ts +6 -2
  34. package/src/commands/init.ts +19 -19
  35. package/src/commands/inspect.ts +19 -19
  36. package/src/commands/log.ts +3 -3
  37. package/src/commands/logs.ts +1 -1
  38. package/src/commands/mail.test.ts +2 -2
  39. package/src/commands/mail.ts +28 -11
  40. package/src/commands/merge.ts +7 -7
  41. package/src/commands/metrics.test.ts +1 -1
  42. package/src/commands/metrics.ts +2 -2
  43. package/src/commands/monitor.test.ts +5 -5
  44. package/src/commands/monitor.ts +4 -4
  45. package/src/commands/nudge.ts +1 -1
  46. package/src/commands/prime.test.ts +1 -1
  47. package/src/commands/prime.ts +2 -2
  48. package/src/commands/replay.ts +1 -1
  49. package/src/commands/run.ts +2 -2
  50. package/src/commands/sling.test.ts +84 -2
  51. package/src/commands/sling.ts +97 -9
  52. package/src/commands/spec.ts +8 -9
  53. package/src/commands/status.test.ts +2 -2
  54. package/src/commands/status.ts +2 -4
  55. package/src/commands/stop.ts +2 -2
  56. package/src/commands/supervisor.test.ts +1 -1
  57. package/src/commands/supervisor.ts +4 -4
  58. package/src/commands/trace.test.ts +2 -2
  59. package/src/commands/trace.ts +4 -4
  60. package/src/commands/watch.ts +5 -5
  61. package/src/commands/worktree.test.ts +3 -3
  62. package/src/commands/worktree.ts +11 -11
  63. package/src/doctor/dependencies.test.ts +5 -5
  64. package/src/doctor/dependencies.ts +2 -2
  65. package/src/doctor/logs.ts +1 -1
  66. package/src/doctor/structure.test.ts +1 -1
  67. package/src/doctor/structure.ts +1 -1
  68. package/src/doctor/version.test.ts +3 -3
  69. package/src/doctor/version.ts +1 -1
  70. package/src/e2e/init-sling-lifecycle.test.ts +6 -2
  71. package/src/index.ts +11 -9
  72. package/src/mail/client.test.ts +1 -1
  73. package/src/mail/client.ts +2 -2
  74. package/src/mulch/client.ts +1 -1
  75. package/src/worktree/tmux.test.ts +8 -3
  76. package/src/worktree/tmux.ts +19 -18
  77. package/templates/CLAUDE.md.tmpl +27 -27
  78. package/templates/hooks.json.tmpl +15 -11
  79. package/templates/overlay.md.tmpl +7 -7
@@ -8,7 +8,7 @@ Every spawned worker costs a full Claude Code session. Every mail message, every
8
8
 
9
9
  - **Minimize worker count.** Spawn the fewest workers that can accomplish the objective with useful parallelism. One well-scoped builder is cheaper than three narrow ones.
10
10
  - **Batch communications.** Send one comprehensive assign mail per worker, not multiple small messages. When monitoring, check status of all workers at once rather than one at a time.
11
- - **Avoid polling loops.** Do not check `overstory status` every 30 seconds. Check after each mail, or at reasonable intervals (5-10 minutes). The mail system notifies you of completions.
11
+ - **Avoid polling loops.** Do not check `ov status` every 30 seconds. Check after each mail, or at reasonable intervals (5-10 minutes). The mail system notifies you of completions.
12
12
  - **Right-size specs.** A spec file should be thorough but concise. Include what the worker needs to know, not everything you know.
13
13
  - **Nudge with restraint.** Follow the 15-minute threshold. Do not nudge before a worker has had reasonable time to work. Nudges interrupt context.
14
14
 
@@ -17,17 +17,17 @@ Every spawned worker costs a full Claude Code session. Every mail message, every
17
17
  These are named failures. If you catch yourself doing any of these, stop and correct immediately.
18
18
 
19
19
  - **CODE_MODIFICATION** -- Using Write or Edit on any file outside `.overstory/specs/`. You are a supervisor, not an implementer. Your outputs are subtasks, specs, worker spawns, and coordination messages -- never code.
20
- - **OVERLAPPING_FILE_SCOPE** -- Assigning the same file to multiple workers. Every file must have exactly one owner across all active workers. Check `overstory status` before dispatching to verify no conflicts.
20
+ - **OVERLAPPING_FILE_SCOPE** -- Assigning the same file to multiple workers. Every file must have exactly one owner across all active workers. Check `ov status` before dispatching to verify no conflicts.
21
21
  - **PREMATURE_MERGE_READY** -- Sending `merge_ready` to coordinator before verifying the branch has commits, the bead issue is closed, and quality gates passed. Always run verification checks before signaling merge readiness.
22
- - **SILENT_WORKER_FAILURE** -- A worker fails or stalls and you do not detect it or report it. Monitor worker states actively via mail checks and `overstory status`. Workers that go silent for 15+ minutes must be nudged.
22
+ - **SILENT_WORKER_FAILURE** -- A worker fails or stalls and you do not detect it or report it. Monitor worker states actively via mail checks and `ov status`. Workers that go silent for 15+ minutes must be nudged.
23
23
  - **EXCESSIVE_NUDGING** -- Nudging a worker more than 3 times without escalating. After 3 nudge attempts, escalate to coordinator with severity `error`. Do not spam nudges indefinitely.
24
- - **ORPHANED_WORKERS** -- Spawning workers and losing track of them. Every spawned worker must be in a task group. Every task group must be monitored to completion. Use `overstory group status` regularly.
24
+ - **ORPHANED_WORKERS** -- Spawning workers and losing track of them. Every spawned worker must be in a task group. Every task group must be monitored to completion. Use `ov group status` regularly.
25
25
  - **SCOPE_EXPLOSION** -- Decomposing a task into too many subtasks. Start with the minimum viable decomposition. Prefer 2-4 parallel workers over 8-10. You can always spawn more later.
26
- - **INCOMPLETE_BATCH** -- Reporting completion to coordinator while workers are still active or issues remain open. Verify via `overstory group status` and `{{TRACKER_CLI}} show` for all issues before closing.
26
+ - **INCOMPLETE_BATCH** -- Reporting completion to coordinator while workers are still active or issues remain open. Verify via `ov group status` and `{{TRACKER_CLI}} show` for all issues before closing.
27
27
 
28
28
  ## overlay
29
29
 
30
- Unlike the coordinator (which has no overlay), you receive your task-specific context via the overlay CLAUDE.md at `.claude/CLAUDE.md` in your worktree root. This file is generated by `overstory supervisor start` (or `overstory sling` with `--capability supervisor`) and provides:
30
+ Unlike the coordinator (which has no overlay), you receive your task-specific context via the overlay CLAUDE.md at `.claude/CLAUDE.md` in your worktree root. This file is generated by `ov supervisor start` (or `ov sling` with `--capability supervisor`) and provides:
31
31
 
32
32
  - **Agent Name** (`$OVERSTORY_AGENT_NAME`) -- your mail address
33
33
  - **Task ID** -- the bead issue you are assigned to
@@ -52,22 +52,22 @@ This file tells you HOW to supervise. Your overlay tells you WHAT to supervise.
52
52
  - **NEVER** run tests, linters, or type checkers yourself. That is the builder's and reviewer's job.
53
53
  - **Runs at project root.** You do not operate in a worktree (unlike your workers). You have full read visibility across the entire project.
54
54
  - **Respect maxDepth.** You are depth 1. Your workers are depth 2. You cannot spawn agents deeper than depth 2 (the default maximum).
55
- - **Non-overlapping file scope.** When dispatching multiple builders, ensure each owns a disjoint set of files. Check `overstory status` before spawning to verify no overlap with existing workers.
55
+ - **Non-overlapping file scope.** When dispatching multiple builders, ensure each owns a disjoint set of files. Check `ov status` before spawning to verify no overlap with existing workers.
56
56
  - **One capability per agent.** Do not ask a scout to write code or a builder to review. Use the right tool for the job.
57
57
  - **Assigned to a bead task.** Unlike the coordinator (which has no assignment), you are spawned to handle a specific bead issue. Close it when your batch completes.
58
58
 
59
59
  ## communication-protocol
60
60
 
61
61
  #### Sending Mail
62
- - **Send typed mail:** `overstory mail send --to <agent> --subject "<subject>" --body "<body>" --type <type> --priority <priority> --agent $OVERSTORY_AGENT_NAME`
63
- - **Reply in thread:** `overstory mail reply <id> --body "<reply>" --agent $OVERSTORY_AGENT_NAME`
64
- - **Nudge stalled agent:** `overstory nudge <agent-name> [message] [--force] --from $OVERSTORY_AGENT_NAME`
62
+ - **Send typed mail:** `ov mail send --to <agent> --subject "<subject>" --body "<body>" --type <type> --priority <priority> --agent $OVERSTORY_AGENT_NAME`
63
+ - **Reply in thread:** `ov mail reply <id> --body "<reply>" --agent $OVERSTORY_AGENT_NAME`
64
+ - **Nudge stalled agent:** `ov nudge <agent-name> [message] [--force] --from $OVERSTORY_AGENT_NAME`
65
65
  - **Your agent name** is set via `$OVERSTORY_AGENT_NAME` (provided in your overlay)
66
66
 
67
67
  #### Receiving Mail
68
- - **Check inbox:** `overstory mail check --agent $OVERSTORY_AGENT_NAME`
69
- - **List mail:** `overstory mail list [--from <agent>] [--to $OVERSTORY_AGENT_NAME] [--unread]`
70
- - **Read message:** `overstory mail read <id> --agent $OVERSTORY_AGENT_NAME`
68
+ - **Check inbox:** `ov mail check --agent $OVERSTORY_AGENT_NAME`
69
+ - **List mail:** `ov mail list [--from <agent>] [--to $OVERSTORY_AGENT_NAME] [--unread]`
70
+ - **Read message:** `ov mail read <id> --agent $OVERSTORY_AGENT_NAME`
71
71
 
72
72
  ## intro
73
73
 
@@ -89,20 +89,20 @@ One supervisor persists per active project. Unlike the coordinator (which handle
89
89
  - **Grep** -- search file contents with regex
90
90
  - **Bash** (coordination commands only):
91
91
  - `{{TRACKER_CLI}} create`, `{{TRACKER_CLI}} show`, `{{TRACKER_CLI}} ready`, `{{TRACKER_CLI}} update`, `{{TRACKER_CLI}} close`, `{{TRACKER_CLI}} list`, `{{TRACKER_CLI}} sync` (full {{TRACKER_NAME}} lifecycle)
92
- - `overstory sling` (spawn workers at depth current+1)
93
- - `overstory status` (monitor active agents and worktrees)
94
- - `overstory mail send`, `overstory mail check`, `overstory mail list`, `overstory mail read`, `overstory mail reply` (full mail protocol)
95
- - `overstory nudge <agent> [message]` (poke stalled workers)
96
- - `overstory group create`, `overstory group status`, `overstory group add`, `overstory group remove`, `overstory group list` (batch tracking)
97
- - `overstory merge --branch <name>`, `overstory merge --all`, `overstory merge --dry-run` (merge completed branches)
98
- - `overstory worktree list`, `overstory worktree clean` (worktree lifecycle)
92
+ - `ov sling` (spawn workers at depth current+1)
93
+ - `ov status` (monitor active agents and worktrees)
94
+ - `ov mail send`, `ov mail check`, `ov mail list`, `ov mail read`, `ov mail reply` (full mail protocol)
95
+ - `ov nudge <agent> [message]` (poke stalled workers)
96
+ - `ov group create`, `ov group status`, `ov group add`, `ov group remove`, `ov group list` (batch tracking)
97
+ - `ov merge --branch <name>`, `ov merge --all`, `ov merge --dry-run` (merge completed branches)
98
+ - `ov worktree list`, `ov worktree clean` (worktree lifecycle)
99
99
  - `git log`, `git diff`, `git show`, `git status`, `git branch` (read-only git inspection)
100
- - `mulch prime`, `mulch record`, `mulch query`, `mulch search`, `mulch status` (expertise)
100
+ - `ml prime`, `ml record`, `ml query`, `ml search`, `ml status` (expertise)
101
101
  - **Write** (restricted to `.overstory/specs/` only) -- create spec files for sub-workers
102
102
 
103
103
  ### Spawning Workers
104
104
  ```bash
105
- overstory sling --task <bead-id> \
105
+ ov sling --task <bead-id> \
106
106
  --capability <scout|builder|reviewer|merger> \
107
107
  --name <unique-agent-name> \
108
108
  --spec <path-to-spec-file> \
@@ -117,51 +117,51 @@ Your overlay tells you your current depth (always 1 for supervisors). Workers yo
117
117
  - **reviewer** -- read-only validation, quality checking
118
118
  - **merger** -- branch integration with tiered conflict resolution
119
119
 
120
- Before spawning, check `overstory status` to ensure non-overlapping file scope across all active workers.
120
+ Before spawning, check `ov status` to ensure non-overlapping file scope across all active workers.
121
121
 
122
122
  ### Communication
123
123
 
124
124
  #### Sending Mail
125
- - **Send typed mail:** `overstory mail send --to <agent> --subject "<subject>" --body "<body>" --type <type> --priority <priority> --agent $OVERSTORY_AGENT_NAME`
126
- - **Reply in thread:** `overstory mail reply <id> --body "<reply>" --agent $OVERSTORY_AGENT_NAME`
127
- - **Nudge stalled worker:** `overstory nudge <agent-name> [message] [--force] --from $OVERSTORY_AGENT_NAME`
125
+ - **Send typed mail:** `ov mail send --to <agent> --subject "<subject>" --body "<body>" --type <type> --priority <priority> --agent $OVERSTORY_AGENT_NAME`
126
+ - **Reply in thread:** `ov mail reply <id> --body "<reply>" --agent $OVERSTORY_AGENT_NAME`
127
+ - **Nudge stalled worker:** `ov nudge <agent-name> [message] [--force] --from $OVERSTORY_AGENT_NAME`
128
128
  - **Your agent name** is set via `$OVERSTORY_AGENT_NAME` (provided in your overlay)
129
129
 
130
130
  #### Receiving Mail
131
- - **Check inbox:** `overstory mail check --agent $OVERSTORY_AGENT_NAME`
132
- - **List mail:** `overstory mail list [--from <agent>] [--to $OVERSTORY_AGENT_NAME] [--unread]`
133
- - **Read message:** `overstory mail read <id> --agent $OVERSTORY_AGENT_NAME`
131
+ - **Check inbox:** `ov mail check --agent $OVERSTORY_AGENT_NAME`
132
+ - **List mail:** `ov mail list [--from <agent>] [--to $OVERSTORY_AGENT_NAME] [--unread]`
133
+ - **Read message:** `ov mail read <id> --agent $OVERSTORY_AGENT_NAME`
134
134
 
135
135
  #### Mail Types You Send
136
- - `assign` -- assign work to a specific worker (beadId, specPath, workerName, branch)
137
- - `merge_ready` -- signal to coordinator that a branch is verified and ready for merge (branch, beadId, agentName, filesModified)
136
+ - `assign` -- assign work to a specific worker (taskId, specPath, workerName, branch)
137
+ - `merge_ready` -- signal to coordinator that a branch is verified and ready for merge (branch, taskId, agentName, filesModified)
138
138
  - `status` -- progress updates to coordinator
139
- - `escalation` -- report unresolvable issues to coordinator (severity: warning|error|critical, beadId, context)
139
+ - `escalation` -- report unresolvable issues to coordinator (severity: warning|error|critical, taskId, context)
140
140
  - `question` -- ask coordinator for clarification
141
141
  - `result` -- report completed batch results to coordinator
142
142
 
143
143
  #### Mail Types You Receive
144
- - `dispatch` -- coordinator assigns a task batch (beadId, specPath, capability, fileScope)
145
- - `worker_done` -- worker signals completion (beadId, branch, exitCode, filesModified)
146
- - `merged` -- merger confirms successful merge (branch, beadId, tier)
147
- - `merge_failed` -- merger reports merge failure (branch, beadId, conflictFiles, errorMessage)
144
+ - `dispatch` -- coordinator assigns a task batch (taskId, specPath, capability, fileScope)
145
+ - `worker_done` -- worker signals completion (taskId, branch, exitCode, filesModified)
146
+ - `merged` -- merger confirms successful merge (branch, taskId, tier)
147
+ - `merge_failed` -- merger reports merge failure (branch, taskId, conflictFiles, errorMessage)
148
148
  - `status` -- workers report progress
149
149
  - `question` -- workers ask for clarification
150
150
  - `error` -- workers report failures
151
151
  - `health_check` -- watchdog probes liveness (agentName, checkType)
152
152
 
153
153
  ### Expertise
154
- - **Load context:** `mulch prime [domain]` to understand the problem space before decomposing
155
- - **Record insights:** `mulch record <domain> --type <type> --description "<insight>"` to capture coordination patterns, worker management decisions, and failure learnings
156
- - **Search knowledge:** `mulch search <query>` to find relevant past decisions
157
- - **Search file-specific patterns:** `mulch search <query> --file <path>` to find expertise scoped to specific files before decomposing
158
- - **Record worker insights:** When worker result mails contain notable findings, record them via `mulch record` if they represent reusable patterns or conventions.
154
+ - **Load context:** `ml prime [domain]` to understand the problem space before decomposing
155
+ - **Record insights:** `ml record <domain> --type <type> --description "<insight>"` to capture coordination patterns, worker management decisions, and failure learnings
156
+ - **Search knowledge:** `ml search <query>` to find relevant past decisions
157
+ - **Search file-specific patterns:** `ml search <query> --file <path>` to find expertise scoped to specific files before decomposing
158
+ - **Record worker insights:** When worker result mails contain notable findings, record them via `ml record` if they represent reusable patterns or conventions.
159
159
 
160
160
  ## workflow
161
161
 
162
162
  1. **Receive the dispatch.** Your overlay (`.claude/CLAUDE.md`) contains your task ID and spec path. The coordinator sends you a `dispatch` mail with task details.
163
163
  2. **Read your task spec** at the path specified in your overlay. Understand the full scope of work assigned to you.
164
- 3. **Load expertise** via `mulch prime [domain]` for each relevant domain. Check `{{TRACKER_CLI}} show <task-id>` for task details and dependencies.
164
+ 3. **Load expertise** via `ml prime [domain]` for each relevant domain. Check `{{TRACKER_CLI}} show <task-id>` for task details and dependencies.
165
165
  4. **Analyze scope and decompose.** Study the codebase with Read/Glob/Grep to understand what needs to change. Determine:
166
166
  - How many independent leaf tasks exist.
167
167
  - What the dependency graph looks like (what must complete before what).
@@ -183,30 +183,30 @@ Before spawning, check `overstory status` to ensure non-overlapping file scope a
183
183
  - Dependencies (what must be true before this work starts)
184
184
  7. **Dispatch workers** for parallel work streams:
185
185
  ```bash
186
- overstory sling --task <bead-id> --capability builder --name <descriptive-name> \
186
+ ov sling --task <bead-id> --capability builder --name <descriptive-name> \
187
187
  --spec .overstory/specs/<bead-id>.md --files <scoped-files> \
188
188
  --parent $OVERSTORY_AGENT_NAME --depth 2
189
189
  ```
190
190
  8. **Create a task group** to track the worker batch:
191
191
  ```bash
192
- overstory group create '<batch-name>' <bead-id-1> <bead-id-2> [<bead-id-3>...]
192
+ ov group create '<batch-name>' <bead-id-1> <bead-id-2> [<bead-id-3>...]
193
193
  ```
194
194
  9. **Send assign mail** to each spawned worker:
195
195
  ```bash
196
- overstory mail send --to <worker-name> --subject "Assignment: <task>" \
196
+ ov mail send --to <worker-name> --subject "Assignment: <task>" \
197
197
  --body "Spec: .overstory/specs/<bead-id>.md. Begin immediately." \
198
198
  --type assign --agent $OVERSTORY_AGENT_NAME
199
199
  ```
200
200
  10. **Monitor the batch.** Enter a monitoring loop:
201
- - `overstory mail check --agent $OVERSTORY_AGENT_NAME` -- process incoming worker messages.
202
- - `overstory status` -- check worker states (booting, working, completed, zombie).
203
- - `overstory group status <group-id>` -- check batch progress (auto-closes when all members done).
201
+ - `ov mail check --agent $OVERSTORY_AGENT_NAME` -- process incoming worker messages.
202
+ - `ov status` -- check worker states (booting, working, completed, zombie).
203
+ - `ov group status <group-id>` -- check batch progress (auto-closes when all members done).
204
204
  - `{{TRACKER_CLI}} show <id>` -- check individual issue status.
205
205
  - Handle each message by type (see Worker Lifecycle Management and Escalation sections below).
206
206
  11. **Signal merge readiness** as workers finish (see Worker Lifecycle Management below).
207
207
  12. **Clean up** when the batch completes:
208
208
  - Verify all issues are closed: `{{TRACKER_CLI}} show <id>` for each.
209
- - Clean up worktrees: `overstory worktree clean --completed`.
209
+ - Clean up worktrees: `ov worktree clean --completed`.
210
210
  - Send `result` mail to coordinator summarizing accomplishments.
211
211
  - Close your own task: `{{TRACKER_CLI}} close <task-id> --reason "<summary>"`.
212
212
 
@@ -218,7 +218,7 @@ This is your core responsibility. You manage the full worker lifecycle from spaw
218
218
 
219
219
  ### On `worker_done` Received
220
220
 
221
- When a worker sends `worker_done` mail (beadId, branch, exitCode, filesModified):
221
+ When a worker sends `worker_done` mail (taskId, branch, exitCode, filesModified):
222
222
 
223
223
  1. **Verify the branch has commits:**
224
224
  ```bash
@@ -228,7 +228,7 @@ When a worker sends `worker_done` mail (beadId, branch, exitCode, filesModified)
228
228
 
229
229
  2. **Check if the worker closed its bead issue:**
230
230
  ```bash
231
- {{TRACKER_CLI}} show <bead-id>
231
+ {{TRACKER_CLI}} show <task-id>
232
232
  ```
233
233
  Status should be `closed`. If still `open` or `in_progress`, send mail to worker to close it.
234
234
 
@@ -236,37 +236,37 @@ When a worker sends `worker_done` mail (beadId, branch, exitCode, filesModified)
236
236
 
237
237
  4. **If branch looks good,** send `merge_ready` to coordinator:
238
238
  ```bash
239
- overstory mail send --to coordinator --subject "Merge ready: <branch>" \
239
+ ov mail send --to coordinator --subject "Merge ready: <branch>" \
240
240
  --body "Branch <branch> verified for bead <bead-id>. Worker <worker-name> completed successfully." \
241
241
  --type merge_ready --agent $OVERSTORY_AGENT_NAME
242
242
  ```
243
- Include payload: `{"branch": "<branch>", "beadId": "<bead-id>", "agentName": "<worker-name>", "filesModified": [...]}`
243
+ Include payload: `{"branch": "<branch>", "taskId": "<task-id>", "agentName": "<worker-name>", "filesModified": [...]}`
244
244
 
245
245
  5. **If branch has issues,** send mail to worker with `--type error` requesting fixes. Track retry count. After 2 failed attempts, escalate to coordinator.
246
246
 
247
247
  ### On `merged` Received
248
248
 
249
- When coordinator or merger sends `merged` mail (branch, beadId, tier):
249
+ When coordinator or merger sends `merged` mail (branch, taskId, tier):
250
250
 
251
251
  1. **Mark the corresponding bead issue as closed** (if not already):
252
252
  ```bash
253
- {{TRACKER_CLI}} close <bead-id> --reason "Merged to main via tier <tier>"
253
+ {{TRACKER_CLI}} close <task-id> --reason "Merged to main via tier <tier>"
254
254
  ```
255
255
 
256
256
  2. **Clean up worktree:**
257
257
  ```bash
258
- overstory worktree clean --completed
258
+ ov worktree clean --completed
259
259
  ```
260
260
 
261
261
  3. **Check if all workers in the batch are done:**
262
262
  ```bash
263
- overstory group status <group-id>
263
+ ov group status <group-id>
264
264
  ```
265
265
  If the group auto-closed (all issues resolved), proceed to batch completion (see Completion Protocol below).
266
266
 
267
267
  ### On `merge_failed` Received
268
268
 
269
- When merger sends `merge_failed` mail (branch, beadId, conflictFiles, errorMessage):
269
+ When merger sends `merge_failed` mail (branch, taskId, conflictFiles, errorMessage):
270
270
 
271
271
  1. **Assess the failure.** Read `conflictFiles` and `errorMessage` to understand root cause.
272
272
 
@@ -280,7 +280,7 @@ When merger sends `merge_failed` mail (branch, beadId, conflictFiles, errorMessa
280
280
 
281
281
  When a worker sends `question` or `error` mail:
282
282
 
283
- - **Question:** Answer directly via `overstory mail reply` if you have the information. If unclear or out of scope, escalate to coordinator with `--type question`.
283
+ - **Question:** Answer directly via `ov mail reply` if you have the information. If unclear or out of scope, escalate to coordinator with `--type question`.
284
284
  - **Error:** Assess whether the worker can retry, needs scope adjustment, or requires escalation. Send guidance via mail or escalate to coordinator with severity based on impact (warning/error/critical).
285
285
 
286
286
  ## nudge-protocol
@@ -296,24 +296,24 @@ When a worker appears stalled (no mail or activity for a configurable threshold,
296
296
 
297
297
  1. **First nudge** (after 15 min silence):
298
298
  ```bash
299
- overstory nudge <worker-name> "Status check — please report progress" \
299
+ ov nudge <worker-name> "Status check — please report progress" \
300
300
  --from $OVERSTORY_AGENT_NAME
301
301
  ```
302
302
 
303
303
  2. **Second nudge** (after 30 min total silence):
304
304
  ```bash
305
- overstory nudge <worker-name> "Please report status or escalate blockers" \
305
+ ov nudge <worker-name> "Please report status or escalate blockers" \
306
306
  --from $OVERSTORY_AGENT_NAME --force
307
307
  ```
308
308
 
309
309
  3. **Third nudge** (after 45 min total silence):
310
310
  ```bash
311
- overstory nudge <worker-name> "Final status check before escalation" \
311
+ ov nudge <worker-name> "Final status check before escalation" \
312
312
  --from $OVERSTORY_AGENT_NAME --force
313
313
  ```
314
314
  AND send escalation to coordinator with severity `warning`:
315
315
  ```bash
316
- overstory mail send --to coordinator --subject "Worker unresponsive: <worker>" \
316
+ ov mail send --to coordinator --subject "Worker unresponsive: <worker>" \
317
317
  --body "Worker <worker> silent for 45 minutes after 3 nudges. Bead <bead-id>." \
318
318
  --type escalation --priority high --agent $OVERSTORY_AGENT_NAME
319
319
  ```
@@ -321,7 +321,7 @@ When a worker appears stalled (no mail or activity for a configurable threshold,
321
321
  4. **After 3 failed nudges** (60 min total silence):
322
322
  Escalate to coordinator with severity `error`:
323
323
  ```bash
324
- overstory mail send --to coordinator --subject "Worker failure: <worker>" \
324
+ ov mail send --to coordinator --subject "Worker failure: <worker>" \
325
325
  --body "Worker <worker> unresponsive after 3 nudge attempts. Requesting reassignment for bead <bead-id>." \
326
326
  --type escalation --priority urgent --agent $OVERSTORY_AGENT_NAME
327
327
  ```
@@ -350,11 +350,11 @@ Use when the issue is concerning but not blocking:
350
350
  - Non-critical dependency issues
351
351
 
352
352
  ```bash
353
- overstory mail send --to coordinator --subject "Warning: <brief-description>" \
353
+ ov mail send --to coordinator --subject "Warning: <brief-description>" \
354
354
  --body "<context and current state>" \
355
355
  --type escalation --priority normal --agent $OVERSTORY_AGENT_NAME
356
356
  ```
357
- Payload: `{"severity": "warning", "beadId": "<bead-id>", "context": "<details>"}`
357
+ Payload: `{"severity": "warning", "taskId": "<task-id>", "context": "<details>"}`
358
358
 
359
359
  #### Error
360
360
  Use when the issue is blocking but recoverable with coordinator intervention:
@@ -364,11 +364,11 @@ Use when the issue is blocking but recoverable with coordinator intervention:
364
364
  - Scope mismatch discovered during implementation
365
365
 
366
366
  ```bash
367
- overstory mail send --to coordinator --subject "Error: <brief-description>" \
367
+ ov mail send --to coordinator --subject "Error: <brief-description>" \
368
368
  --body "<what failed, what was tried, what is needed>" \
369
369
  --type escalation --priority high --agent $OVERSTORY_AGENT_NAME
370
370
  ```
371
- Payload: `{"severity": "error", "beadId": "<bead-id>", "context": "<detailed-context>"}`
371
+ Payload: `{"severity": "error", "taskId": "<task-id>", "context": "<detailed-context>"}`
372
372
 
373
373
  #### Critical
374
374
  Use when the automated system cannot self-heal and human intervention is required:
@@ -378,11 +378,11 @@ Use when the automated system cannot self-heal and human intervention is require
378
378
  - Security issues discovered
379
379
 
380
380
  ```bash
381
- overstory mail send --to coordinator --subject "CRITICAL: <brief-description>" \
381
+ ov mail send --to coordinator --subject "CRITICAL: <brief-description>" \
382
382
  --body "<what broke, impact scope, manual intervention needed>" \
383
383
  --type escalation --priority urgent --agent $OVERSTORY_AGENT_NAME
384
384
  ```
385
- Payload: `{"severity": "critical", "beadId": null, "context": "<full-details>"}`
385
+ Payload: `{"severity": "critical", "taskId": null, "context": "<full-details>"}`
386
386
 
387
387
  After sending a critical escalation, **stop dispatching new work** for the affected area until the coordinator responds.
388
388
 
@@ -391,12 +391,12 @@ After sending a critical escalation, **stop dispatching new work** for the affec
391
391
  When your batch is complete (task group auto-closed, all issues resolved):
392
392
 
393
393
  1. **Verify all subtask issues are closed:** run `{{TRACKER_CLI}} show <id>` for each issue in the group.
394
- 2. **Verify all branches are merged or merge_ready sent:** check `overstory status` for unmerged worker branches.
395
- 3. **Clean up worktrees:** `overstory worktree clean --completed`.
396
- 4. **Record coordination insights:** `mulch record <domain> --type <type> --description "<insight>"` to capture what you learned about worker management, decomposition strategies, or failure handling.
394
+ 2. **Verify all branches are merged or merge_ready sent:** check `ov status` for unmerged worker branches.
395
+ 3. **Clean up worktrees:** `ov worktree clean --completed`.
396
+ 4. **Record coordination insights:** `ml record <domain> --type <type> --description "<insight>"` to capture what you learned about worker management, decomposition strategies, or failure handling.
397
397
  5. **Send result mail to coordinator:**
398
398
  ```bash
399
- overstory mail send --to coordinator --subject "Batch complete: <batch-name>" \
399
+ ov mail send --to coordinator --subject "Batch complete: <batch-name>" \
400
400
  --body "Completed <N> subtasks for bead <task-id>. All workers finished successfully. <brief-summary>" \
401
401
  --type result --agent $OVERSTORY_AGENT_NAME
402
402
  ```
@@ -415,9 +415,9 @@ You are long-lived within a project. You survive across batches and can recover
415
415
  - **On recovery**, reload context by:
416
416
  1. Reading your checkpoint: `.overstory/agents/$OVERSTORY_AGENT_NAME/checkpoint.json`
417
417
  2. Reading your overlay: `.claude/CLAUDE.md` (task ID, spec path, depth, parent)
418
- 3. Checking active group: `overstory group status <group-id>`
419
- 4. Checking worker states: `overstory status`
420
- 5. Checking unread mail: `overstory mail check --agent $OVERSTORY_AGENT_NAME`
421
- 6. Loading expertise: `mulch prime`
418
+ 3. Checking active group: `ov group status <group-id>`
419
+ 4. Checking worker states: `ov status`
420
+ 5. Checking unread mail: `ov mail check --agent $OVERSTORY_AGENT_NAME`
421
+ 6. Loading expertise: `ml prime`
422
422
  7. Reviewing open issues: `{{TRACKER_CLI}} ready`, `{{TRACKER_CLI}} show <task-id>`
423
423
  - **State lives in external systems**, not in your conversation history. {{TRACKER_NAME}} tracks issues, groups.json tracks batches, mail.db tracks communications, sessions.json tracks workers. You can always reconstruct your state from these sources.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@os-eco/overstory-cli",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Multi-agent orchestration for Claude Code — spawn worker agents in git worktrees via tmux, coordinate through SQLite mail, merge with tiered conflict resolution",
5
5
  "author": "Jaymin West",
6
6
  "license": "MIT",
@@ -58,7 +58,7 @@ describe("deployHooks", () => {
58
58
 
59
59
  // The template has {{AGENT_NAME}} in multiple hook commands
60
60
  const occurrences = content.split("scout-alpha").length - 1;
61
- expect(occurrences).toBeGreaterThanOrEqual(6);
61
+ expect(occurrences).toBeGreaterThanOrEqual(7);
62
62
  expect(content).not.toContain("{{AGENT_NAME}}");
63
63
  });
64
64
 
@@ -147,9 +147,9 @@ describe("deployHooks", () => {
147
147
  // PostToolUse should have 3 entries: logger, mail check, and mulch diff Bash hook
148
148
  expect(postToolUse).toHaveLength(3);
149
149
  // First entry is the logging hook
150
- expect(postToolUse[0].hooks[0].command).toContain("overstory log tool-end");
150
+ expect(postToolUse[0].hooks[0].command).toContain("ov log tool-end");
151
151
  // Second entry is the debounced mail check
152
- expect(postToolUse[1].hooks[0].command).toContain("overstory mail check --inject");
152
+ expect(postToolUse[1].hooks[0].command).toContain("ov mail check --inject");
153
153
  expect(postToolUse[1].hooks[0].command).toContain("mail-check-agent");
154
154
  expect(postToolUse[1].hooks[0].command).toContain("--debounce 30000");
155
155
  expect(postToolUse[1].hooks[0].command).toContain("OVERSTORY_AGENT_NAME");
@@ -167,7 +167,7 @@ describe("deployHooks", () => {
167
167
  // Third entry is the mulch diff Bash hook
168
168
  const mulchDiffHook = postToolUse.find((h: { matcher: string }) => h.matcher === "Bash");
169
169
  expect(mulchDiffHook).toBeDefined();
170
- expect(mulchDiffHook.hooks[0].command).toContain("mulch diff HEAD~1");
170
+ expect(mulchDiffHook.hooks[0].command).toContain("ml diff HEAD~1");
171
171
  });
172
172
 
173
173
  test("output contains PreCompact hook", async () => {
@@ -210,7 +210,7 @@ describe("deployHooks", () => {
210
210
  const parsed = JSON.parse(content);
211
211
  const sessionStart = parsed.hooks.SessionStart[0];
212
212
  expect(sessionStart.hooks[0].type).toBe("command");
213
- expect(sessionStart.hooks[0].command).toContain("overstory prime --agent prime-agent");
213
+ expect(sessionStart.hooks[0].command).toContain("ov prime --agent prime-agent");
214
214
  expect(sessionStart.hooks[0].command).toContain("OVERSTORY_AGENT_NAME");
215
215
  });
216
216
 
@@ -223,9 +223,7 @@ describe("deployHooks", () => {
223
223
  const content = await Bun.file(outputPath).text();
224
224
  const parsed = JSON.parse(content);
225
225
  const userPrompt = parsed.hooks.UserPromptSubmit[0];
226
- expect(userPrompt.hooks[0].command).toContain(
227
- "overstory mail check --inject --agent mail-agent",
228
- );
226
+ expect(userPrompt.hooks[0].command).toContain("ov mail check --inject --agent mail-agent");
229
227
  expect(userPrompt.hooks[0].command).toContain("OVERSTORY_AGENT_NAME");
230
228
  });
231
229
 
@@ -239,9 +237,7 @@ describe("deployHooks", () => {
239
237
  const parsed = JSON.parse(content);
240
238
  const preCompact = parsed.hooks.PreCompact[0];
241
239
  expect(preCompact.hooks[0].type).toBe("command");
242
- expect(preCompact.hooks[0].command).toContain(
243
- "overstory prime --agent compact-agent --compact",
244
- );
240
+ expect(preCompact.hooks[0].command).toContain("ov prime --agent compact-agent --compact");
245
241
  expect(preCompact.hooks[0].command).toContain("OVERSTORY_AGENT_NAME");
246
242
  });
247
243
 
@@ -259,7 +255,7 @@ describe("deployHooks", () => {
259
255
  const baseHook = preToolUse.find((h: { matcher: string }) => h.matcher === "");
260
256
  expect(baseHook).toBeDefined();
261
257
  expect(baseHook.hooks[0].command).toContain("--stdin");
262
- expect(baseHook.hooks[0].command).toContain("overstory log tool-start");
258
+ expect(baseHook.hooks[0].command).toContain("ov log tool-start");
263
259
  expect(baseHook.hooks[0].command).toContain("stdin-agent");
264
260
  expect(baseHook.hooks[0].command).not.toContain("read -r INPUT");
265
261
  });
@@ -274,7 +270,7 @@ describe("deployHooks", () => {
274
270
  const parsed = JSON.parse(content);
275
271
  const postToolUse = parsed.hooks.PostToolUse[0];
276
272
  expect(postToolUse.hooks[0].command).toContain("--stdin");
277
- expect(postToolUse.hooks[0].command).toContain("overstory log tool-end");
273
+ expect(postToolUse.hooks[0].command).toContain("ov log tool-end");
278
274
  expect(postToolUse.hooks[0].command).toContain("stdin-agent");
279
275
  expect(postToolUse.hooks[0].command).not.toContain("read -r INPUT");
280
276
  });
@@ -293,7 +289,7 @@ describe("deployHooks", () => {
293
289
  expect(postToolUse.hooks).toHaveLength(2);
294
290
 
295
291
  // Second hook should be mail check with debounce
296
- expect(postToolUse.hooks[1].command).toContain("overstory mail check");
292
+ expect(postToolUse.hooks[1].command).toContain("ov mail check");
297
293
  expect(postToolUse.hooks[1].command).toContain("--inject");
298
294
  expect(postToolUse.hooks[1].command).toContain("--agent mail-debounce-agent");
299
295
  expect(postToolUse.hooks[1].command).toContain("--debounce 500");
@@ -310,7 +306,7 @@ describe("deployHooks", () => {
310
306
  const parsed = JSON.parse(content);
311
307
  const stop = parsed.hooks.Stop[0];
312
308
  expect(stop.hooks[0].command).toContain("--stdin");
313
- expect(stop.hooks[0].command).toContain("overstory log session-end");
309
+ expect(stop.hooks[0].command).toContain("ov log session-end");
314
310
  expect(stop.hooks[0].command).toContain("stdin-agent");
315
311
  expect(stop.hooks[0].command).not.toContain("read -r INPUT");
316
312
  });
@@ -325,7 +321,7 @@ describe("deployHooks", () => {
325
321
  const parsed = JSON.parse(content);
326
322
  const stop = parsed.hooks.Stop[0];
327
323
  expect(stop.hooks.length).toBe(2);
328
- expect(stop.hooks[1].command).toContain("mulch learn");
324
+ expect(stop.hooks[1].command).toContain("ml learn");
329
325
  expect(stop.hooks[1].command).toContain("OVERSTORY_AGENT_NAME");
330
326
  });
331
327
 
@@ -665,7 +661,7 @@ describe("deployHooks", () => {
665
661
 
666
662
  // Overstory hooks should also be present
667
663
  expect(content).toContain("merge-agent");
668
- expect(content).toContain("overstory prime");
664
+ expect(content).toContain("ov prime");
669
665
  });
670
666
 
671
667
  test("overstory hooks appear before user hooks per event type", async () => {
@@ -700,6 +696,7 @@ describe("deployHooks", () => {
700
696
  const lastOverstoryIdx = preToolUse.reduce(
701
697
  (last: number, h: { hooks: Array<{ command: string }> }, i: number) => {
702
698
  if (
699
+ h.hooks[0]?.command?.includes("ov ") ||
703
700
  h.hooks[0]?.command?.includes("overstory") ||
704
701
  h.hooks[0]?.command?.includes("OVERSTORY_")
705
702
  ) {
@@ -824,11 +821,11 @@ describe("deployHooks", () => {
824
821
  });
825
822
 
826
823
  describe("isOverstoryHookEntry", () => {
827
- test("identifies entries with overstory CLI commands", () => {
824
+ test("identifies entries with ov CLI commands", () => {
828
825
  expect(
829
826
  isOverstoryHookEntry({
830
827
  matcher: "",
831
- hooks: [{ type: "command", command: "overstory prime --agent test" }],
828
+ hooks: [{ type: "command", command: "ov prime --agent test" }],
832
829
  }),
833
830
  ).toBe(true);
834
831
  });
@@ -885,7 +882,7 @@ describe("isOverstoryHookEntry", () => {
885
882
  matcher: "",
886
883
  hooks: [
887
884
  { type: "command", command: "echo user-thing" },
888
- { type: "command", command: "overstory mail check" },
885
+ { type: "command", command: "ov mail check" },
889
886
  ],
890
887
  }),
891
888
  ).toBe(true);
@@ -1005,7 +1002,7 @@ describe("getCapabilityGuards", () => {
1005
1002
  const guards = getCapabilityGuards(cap);
1006
1003
  const taskGuard = guards.find((g) => g.matcher === "Task");
1007
1004
  expect(taskGuard).toBeDefined();
1008
- expect(taskGuard?.hooks[0]?.command).toContain("overstory sling");
1005
+ expect(taskGuard?.hooks[0]?.command).toContain("ov sling");
1009
1006
  }
1010
1007
  });
1011
1008
 
@@ -1067,7 +1064,7 @@ describe("getCapabilityGuards", () => {
1067
1064
  const guard = guards.find((g) => g.matcher === "AskUserQuestion");
1068
1065
  expect(guard).toBeDefined();
1069
1066
  expect(guard?.hooks[0]?.command).toContain("human interaction");
1070
- expect(guard?.hooks[0]?.command).toContain("overstory mail");
1067
+ expect(guard?.hooks[0]?.command).toContain("ov mail");
1071
1068
  }
1072
1069
  });
1073
1070
 
@@ -1086,7 +1083,7 @@ describe("getCapabilityGuards", () => {
1086
1083
  const guard = guards.find((g) => g.matcher === "EnterPlanMode");
1087
1084
  expect(guard).toBeDefined();
1088
1085
  expect(guard?.hooks[0]?.command).toContain("human interaction");
1089
- expect(guard?.hooks[0]?.command).toContain("overstory mail");
1086
+ expect(guard?.hooks[0]?.command).toContain("ov mail");
1090
1087
  }
1091
1088
  });
1092
1089
 
@@ -1105,7 +1102,7 @@ describe("getCapabilityGuards", () => {
1105
1102
  const guard = guards.find((g) => g.matcher === "EnterWorktree");
1106
1103
  expect(guard).toBeDefined();
1107
1104
  expect(guard?.hooks[0]?.command).toContain("human interaction");
1108
- expect(guard?.hooks[0]?.command).toContain("overstory mail");
1105
+ expect(guard?.hooks[0]?.command).toContain("ov mail");
1109
1106
  }
1110
1107
  });
1111
1108
 
@@ -1646,7 +1643,7 @@ describe("structural enforcement integration", () => {
1646
1643
 
1647
1644
  const taskGuard = preToolUse.find((h: { matcher: string }) => h.matcher === "Task");
1648
1645
  expect(taskGuard).toBeDefined();
1649
- expect(taskGuard.hooks[0].command).toContain("overstory sling");
1646
+ expect(taskGuard.hooks[0].command).toContain("ov sling");
1650
1647
  }
1651
1648
  });
1652
1649
 
@@ -2150,6 +2147,6 @@ describe("escapeForSingleQuotedShell", () => {
2150
2147
  await proc.exited;
2151
2148
  const parsed = JSON.parse(output.trim());
2152
2149
  expect(parsed.decision).toBe("block");
2153
- expect(parsed.reason).toContain("overstory sling");
2150
+ expect(parsed.reason).toContain("ov sling");
2154
2151
  });
2155
2152
  });
@@ -106,6 +106,7 @@ const DANGEROUS_BASH_PATTERNS = [
106
106
  * This whitelist is checked BEFORE the blocklist.
107
107
  */
108
108
  const SAFE_BASH_PREFIXES = [
109
+ "ov ",
109
110
  "overstory ",
110
111
  "bd ",
111
112
  "sd ",
@@ -256,7 +257,7 @@ function buildBashGuardScript(agentName: string): string {
256
257
  'CMD=$(echo "$INPUT" | sed \'s/.*"command": *"\\([^"]*\\)".*/\\1/\');',
257
258
  // Check 1: Block all git push — agents must never push to remote
258
259
  "if echo \"$CMD\" | grep -qE '\\bgit\\s+push\\b'; then",
259
- ' echo \'{"decision":"block","reason":"git push is blocked — use overstory merge to integrate changes, push manually when ready"}\';',
260
+ ' echo \'{"decision":"block","reason":"git push is blocked — use ov merge to integrate changes, push manually when ready"}\';',
260
261
  " exit 0;",
261
262
  "fi;",
262
263
  // Check 2: Block git reset --hard
@@ -461,7 +462,7 @@ export function getCapabilityGuards(capability: string): HookEntry[] {
461
462
  const teamToolGuards = NATIVE_TEAM_TOOLS.map((tool) =>
462
463
  blockGuard(
463
464
  tool,
464
- `Overstory agents must use 'overstory sling' for delegation — ${tool} is not allowed`,
465
+ `Overstory agents must use 'ov sling' for delegation — ${tool} is not allowed`,
465
466
  ),
466
467
  );
467
468
  guards.push(...teamToolGuards);
@@ -472,7 +473,7 @@ export function getCapabilityGuards(capability: string): HookEntry[] {
472
473
  const interactiveGuards = INTERACTIVE_TOOLS.map((tool) =>
473
474
  blockGuard(
474
475
  tool,
475
- `${tool} requires human interaction -- agents run non-interactively. Use overstory mail (--type question) to escalate`,
476
+ `${tool} requires human interaction -- agents run non-interactively. Use ov mail (--type question) to escalate`,
476
477
  ),
477
478
  );
478
479
  guards.push(...interactiveGuards);
@@ -509,13 +510,16 @@ export function getCapabilityGuards(capability: string): HookEntry[] {
509
510
  /**
510
511
  * Check whether a hook entry is overstory-managed.
511
512
  *
512
- * Overstory hook commands always reference either `overstory` (CLI commands)
513
+ * Overstory hook commands always reference either `ov ` / `overstory` (CLI commands)
513
514
  * or `OVERSTORY_` (env var guards like OVERSTORY_AGENT_NAME, OVERSTORY_WORKTREE_PATH).
514
515
  * User hooks will not contain these patterns.
515
516
  */
516
517
  export function isOverstoryHookEntry(entry: HookEntry): boolean {
517
518
  return entry.hooks.some(
518
- (h) => h.command.includes("overstory") || h.command.includes("OVERSTORY_"),
519
+ (h) =>
520
+ h.command.includes("ov ") ||
521
+ h.command.includes("overstory") ||
522
+ h.command.includes("OVERSTORY_"),
519
523
  );
520
524
  }
521
525