opencode-thrum-pro 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/assets/commands/thrum-_deviations-protocol.md +87 -0
  2. package/assets/commands/thrum-_generator-idempotency-protocol.md +15 -0
  3. package/assets/commands/thrum-_project-rules-protocol.md +18 -0
  4. package/assets/commands/thrum-_snapshot-protocol.md +265 -0
  5. package/assets/commands/thrum-_stamp-protocol.md +112 -0
  6. package/assets/commands/thrum-_verify-before-write-protocol.md +27 -0
  7. package/assets/commands/thrum-inbox.md +22 -0
  8. package/assets/commands/thrum-load-context.md +17 -0
  9. package/assets/commands/thrum-overview.md +17 -0
  10. package/assets/commands/thrum-prime.md +30 -0
  11. package/assets/commands/thrum-quickstart.md +14 -0
  12. package/assets/commands/thrum-reply.md +28 -0
  13. package/assets/commands/thrum-restart-extended.md +195 -0
  14. package/assets/commands/thrum-restart.md +293 -0
  15. package/assets/commands/thrum-send.md +31 -0
  16. package/assets/commands/thrum-sleep-extended.md +186 -0
  17. package/assets/commands/thrum-sleep.md +212 -0
  18. package/assets/commands/thrum-team.md +12 -0
  19. package/assets/commands/thrum-update-project.md +259 -0
  20. package/assets/commands/thrum-wait.md +14 -0
  21. package/assets/skills/adversarial-critique/SKILL.md +242 -0
  22. package/assets/skills/brainstorm-queue-aware/SKILL.md +167 -0
  23. package/assets/skills/brainstorm-steward/SKILL.md +181 -0
  24. package/assets/skills/choosing-subagent-models/SKILL.md +244 -0
  25. package/assets/skills/closing-findings-while-warm/SKILL.md +104 -0
  26. package/assets/skills/configure-roles/SKILL.md +229 -0
  27. package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +205 -0
  28. package/assets/skills/coordinator-assessing-agent-completion/scan.py +117 -0
  29. package/assets/skills/coordinator-branch-split-on-block/SKILL.md +168 -0
  30. package/assets/skills/coordinator-context-monitoring/SKILL.md +674 -0
  31. package/assets/skills/coordinator-dispatching-work/SKILL.md +288 -0
  32. package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +522 -0
  33. package/assets/skills/coordinator-interacting-with-the-owner/SKILL.md +171 -0
  34. package/assets/skills/coordinator-maintaining-memory/SKILL.md +89 -0
  35. package/assets/skills/coordinator-managing-state-and-lifecycle/SKILL.md +192 -0
  36. package/assets/skills/coordinator-merging-code/SKILL.md +331 -0
  37. package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +442 -0
  38. package/assets/skills/coordinator-plan-reconcile-gate/SKILL.md +198 -0
  39. package/assets/skills/coordinator-post-restart-sweep/SKILL.md +135 -0
  40. package/assets/skills/coordinator-running-autonomous-feature-development/SKILL.md +199 -0
  41. package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +654 -0
  42. package/assets/skills/coordinator-running-review-cycles/SKILL.md +153 -0
  43. package/assets/skills/coordinator-single-responsibility-merge-gate/SKILL.md +14 -0
  44. package/assets/skills/diagnosing-fleet-and-daemon/SKILL.md +255 -0
  45. package/assets/skills/efficient-multi-agent-research/SKILL.md +177 -0
  46. package/assets/skills/fixing-documentation-errors/SKILL.md +258 -0
  47. package/assets/skills/implementer-maintaining-memory/SKILL.md +84 -0
  48. package/assets/skills/implementer-orchestrating-execution/SKILL.md +125 -0
  49. package/assets/skills/implementer-receiving-dispatch/SKILL.md +127 -0
  50. package/assets/skills/implementer-receiving-review-feedback/SKILL.md +125 -0
  51. package/assets/skills/implementer-status-and-handoff/SKILL.md +150 -0
  52. package/assets/skills/implementer-tdd-and-quality/SKILL.md +99 -0
  53. package/assets/skills/memory-audit-recover/SKILL.md +153 -0
  54. package/assets/skills/memory-curate/SKILL.md +139 -0
  55. package/assets/skills/memory-maintenance/SKILL.md +87 -0
  56. package/assets/skills/memory-read-discipline/SKILL.md +164 -0
  57. package/assets/skills/memory-search-advanced/SKILL.md +217 -0
  58. package/assets/skills/memory-write-discipline/SKILL.md +135 -0
  59. package/assets/skills/orchestrate/SKILL.md +795 -0
  60. package/assets/skills/persistent-watcher-archetype/SKILL.md +225 -0
  61. package/assets/skills/prime-agent/SKILL.md +92 -0
  62. package/assets/skills/project-hotpath-gate/SKILL.md +255 -0
  63. package/assets/skills/project-philosophy/SKILL.md +418 -0
  64. package/assets/skills/project-philosophy/resources/philosophy-template.md +155 -0
  65. package/assets/skills/project-philosophy/resources/reliability-class-library.md +653 -0
  66. package/assets/skills/project-setup/SKILL.md +1007 -0
  67. package/assets/skills/project-setup/resources/implementation-agent.md +826 -0
  68. package/assets/skills/researcher-answering-queries/SKILL.md +100 -0
  69. package/assets/skills/researcher-investigating/SKILL.md +152 -0
  70. package/assets/skills/researcher-maintaining-memory/SKILL.md +176 -0
  71. package/assets/skills/state-migration/SKILL.md +54 -0
  72. package/assets/skills/thrum/SKILL.md +161 -0
  73. package/assets/skills/thrum/resources/ANTI_PATTERNS.md +132 -0
  74. package/assets/skills/thrum/resources/BOUNDARIES.md +56 -0
  75. package/assets/skills/thrum/resources/CLI_REFERENCE.md +1066 -0
  76. package/assets/skills/thrum/resources/IDENTITY.md +49 -0
  77. package/assets/skills/thrum/resources/LISTENER_PATTERN.md +64 -0
  78. package/assets/skills/thrum/resources/MESSAGING.md +163 -0
  79. package/assets/skills/thrum/resources/TMUX_SESSIONS.md +118 -0
  80. package/assets/skills/thrum/resources/WORKTREES.md +117 -0
  81. package/assets/skills/thrum-memory/SKILL.md +138 -0
  82. package/assets/skills/trace-spec-to-plan/SKILL.md +104 -0
  83. package/assets/skills/trace-spec-to-plan/resources/sweep-agent-prompt.md +57 -0
  84. package/assets/skills/update-queue/SKILL.md +149 -0
  85. package/assets/skills/using-the-queue/SKILL.md +172 -0
  86. package/assets/skills/using-thrum-state/SKILL.md +104 -0
  87. package/assets/skills/verify-against-plan/SKILL.md +323 -0
  88. package/assets/skills/verify-against-source/SKILL.md +237 -0
  89. package/assets/skills/watcher-archetype/SKILL.md +84 -0
  90. package/assets/skills/writing-durable-markdown/SKILL.md +66 -0
  91. package/dist/hooks/block-sync-cd.d.ts +9 -0
  92. package/dist/hooks/block-sync-cd.js +71 -0
  93. package/dist/hooks/block-sync-cd.test.d.ts +1 -0
  94. package/dist/hooks/block-sync-cd.test.js +61 -0
  95. package/dist/hooks/shell-env.d.ts +8 -0
  96. package/dist/hooks/shell-env.js +22 -0
  97. package/dist/index.d.ts +6 -0
  98. package/dist/index.js +25 -0
  99. package/dist/installer.d.ts +2 -0
  100. package/dist/installer.js +86 -0
  101. package/package.json +49 -0
@@ -0,0 +1,795 @@
1
+ ---
2
+ name: orchestrate
3
+ description: "Execute a plan by launching agents in tmux sessions, managing epic-by-epic execution with review gates, and preparing merge reports. Use when the orchestrator receives a plan handoff from the coordinator."
4
+ ---
5
+
6
+ # Orchestrate: Managed Plan Execution
7
+
8
+ This is the full execution playbook. Follow each phase in order. Do not skip
9
+ phases or steps.
10
+
11
+ ---
12
+
13
+ ## Phase 1 — Validate Handoff
14
+
15
+ Before executing anything, verify the handoff is complete.
16
+
17
+ ### Step 0: Reconcile your queue
18
+
19
+ `thrum queue list` and drop/close finished bundles. Do NOT lift the whole plan
20
+ into one bundle — you create one bundle PER EPIC when you dispatch it (Phase 4),
21
+ so a coordinator reading your queue sees which epic is live and at what stage.
22
+ One bundle per epic, no sub-items: the bundle's STATUS carries the stage. Full
23
+ lifecycle: `using-the-queue`.
24
+
25
+ ### Step 1: Read the plan
26
+
27
+ ```bash
28
+ # The plan file path comes from the coordinator's message
29
+ cat <plan-file-path>
30
+ ```
31
+
32
+ Read the plan file and the associated design doc (if referenced). Understand the
33
+ epic structure, task dependencies, and worktree assignments.
34
+
35
+ ### Step 2: Validate completeness
36
+
37
+ Check each item. If ANY check fails, stop and send specific feedback to the
38
+ coordinator.
39
+
40
+ ```bash
41
+ # 1. Beads epics exist with tasks
42
+ bd show <epic-1-id>
43
+ bd show <epic-2-id>
44
+ # ... for each epic
45
+
46
+ # 2. Implementation prompt exists
47
+ cat <prompt-file-path>
48
+
49
+ # 3. Review gates exist in the prompt (structural marker)
50
+ grep "## Review Gate:" <prompt-file-path>
51
+ # Must have at least one review gate for multi-epic prompts
52
+
53
+ # 4. Dependencies configured
54
+ bd dep tree <epic-id>
55
+
56
+ # 5. Merge target in config
57
+ cat .thrum/config.json | grep merge_target
58
+ ```
59
+
60
+ ### Step 2b: Triage CANDIDATE beads (if the dispatch carries any)
61
+
62
+ A dispatch may list **adjacent beads marked CANDIDATES**. That word is a contract,
63
+ not a label: the coordinator found them by CODE-AREA adjacency to the assigned
64
+ work, and is explicitly telling you **their validity is unverified**. They are not
65
+ assigned work and not scope creep — they are questions you are uniquely positioned
66
+ to answer cheaply.
67
+
68
+ **Why you and not the coordinator:** you cut branches from the CURRENT tip, so you
69
+ see today's code. The coordinator is cold and its adjacency list goes stale between
70
+ the pass and the dispatch. Checking there costs a full context load; checking here
71
+ is a sub-agent read against a tree that is already fresh.
72
+
73
+ **Do NOT implement a candidate before triaging it, and do NOT silently drop one.**
74
+
75
+ Triage each candidate against the current tip — delegate to a sub-agent, then route
76
+ by the result:
77
+
78
+ > **Pass an explicit `model:` on that spawn.** Sub-agent tier selection is the
79
+ > `choosing-subagent-models` skill's job, not this one — see it for the tiers. What
80
+ > matters here is that you pass one at all: the `roleDefault()` backstop in the
81
+ > daemon covers `thrum tmux launch` of thrum agents, **not** Agent-tool sub-agents,
82
+ > which inherit the PARENT model when unspecified. An orchestrator on Opus that
83
+ > omits `model:` gets Opus-priced triage.
84
+
85
+ | Result | Action |
86
+ |---|---|
87
+ | **Still valid** | Fold into the implementer already working that code area — same pass, while they are warm. Add it to their task with its bead ID and acceptance criteria. |
88
+ | **Already fixed** | Return to the coordinator as COMPLETED **with the evidence** (SHA, file:line, what fixed it). The coordinator closes the bead. Nobody implements anything. |
89
+ | **Ambiguous / partly valid** | Return it as a QUESTION. Do not resolve it in either direction — a candidate resolved on a guess is worse than one left open, because it stops anyone looking. |
90
+ | **Empty return from the check** | UNRUN, not valid and not fixed. Re-ask the same sub-agent (`SendMessage`); never re-dispatch a fresh one — the completed analysis is usually sitting in the original agent, and a fresh dispatch guarantees it is lost. |
91
+
92
+ Report the disposition of EVERY candidate back to the coordinator, including the
93
+ ones you folded in. A candidate that is silently absorbed looks identical to one
94
+ that was silently dropped, and the coordinator cannot tell which happened.
95
+
96
+ **A candidate never expands the epic's scope on its own.** If a "still valid"
97
+ candidate turns out to be substantially larger than a fold-in — a new subsystem, a
98
+ schema change, a design fork — stop and return it to the coordinator for staffing
99
+ rather than growing the epic quietly.
100
+
101
+ ### Step 3: Report validation result
102
+
103
+ If valid, proceed to Phase 2. If invalid, report what's missing:
104
+
105
+ ```bash
106
+ thrum send --to @<coordinator> --stdin <<'EOF'
107
+ Plan validation failed. Missing: <specific list>
108
+ EOF
109
+ ```
110
+
111
+ Then STOP. Wait for the coordinator to fix and re-send.
112
+
113
+ ---
114
+
115
+ ## Phase 2 — Configure Execution
116
+
117
+ ### Step 1: Autonomy negotiation
118
+
119
+ Read the default from config:
120
+
121
+ ```bash
122
+ cat .thrum/config.json | grep default_autonomy
123
+ ```
124
+
125
+ Present to the human:
126
+
127
+ > "Autonomy level is `<default>`. Options:
128
+ >
129
+ > - `per_epic`: I'll pause after each epic for your review and approval
130
+ > - `end_only`: I'll run all epics and present a final report before merge
131
+ >
132
+ > Proceed with `<default>`?"
133
+
134
+ Wait for confirmation. If the human changes the level, use the new one.
135
+
136
+ ### Step 2: Runtime selection
137
+
138
+ ```bash
139
+ thrum team
140
+ ```
141
+
142
+ - If all agents use the same runtime → use it silently, no question needed
143
+ - If multiple runtimes detected → ask the human which to use per work stream
144
+
145
+ ### Step 3: Worktree planning
146
+
147
+ Analyze epic dependencies to determine parallelism:
148
+
149
+ ```bash
150
+ bd dep tree <epic-id>
151
+ bd show <epic-id> # for each epic
152
+ ```
153
+
154
+ Present the plan alongside autonomy/runtime (one configuration gate, not three):
155
+
156
+ > "Plan: N worktrees needed. Epics A+B parallel (no dependencies), Epic C after
157
+ > both complete. Autonomy: `<level>`. Runtime: `<rt>`. Proceed?"
158
+
159
+ Wait for confirmation.
160
+
161
+ ---
162
+
163
+ ## Phase 3 — Launch Agents
164
+
165
+ For each agent needed:
166
+
167
+ ### Step 1: Create worktree
168
+
169
+ ```bash
170
+ thrum worktree create <name>
171
+ ```
172
+
173
+ ### Step 2: Create and launch tmux session
174
+
175
+ ```bash
176
+ # create session — ephemeral implementer (no agent folder, stateless)
177
+ # --mode ephemeral --identity ephemeral: register as (ephemeral, ephemeral) so
178
+ # the per-agent agents/ folder is auto-cleaned if the operator ever runs the
179
+ # (coordinator-only) delete path. Orchestrators retire via
180
+ # set-phase retired, never delete.
181
+ # Pin --model on BOTH create AND launch — create's persist to runtime_config.json
182
+ # is asynchronous and can lose the race to launch's resolution if launch omits
183
+ # the flag (see CLAUDE.md "Launching an Agent"). There is no create-only shortcut.
184
+ # Always launch implementers at --model sonnet. sonnet-medium is the floor;
185
+ # no lower tier exists.
186
+ thrum tmux create <name> --cwd <worktree-path> \
187
+ --name <agent_name> --role implementer --module <module> \
188
+ --mode ephemeral --identity ephemeral \
189
+ --model sonnet
190
+ thrum tmux launch <name> --runtime <runtime> --model sonnet
191
+ ```
192
+
193
+ > **Implementer lifecycle:** All implementers are ephemeral+stateless (no agent
194
+ > folder). At NORMAL epic completion AND at a tier-swap, retire the agent with
195
+ > `thrum agent set-phase retired --agent <name>` — this RETAINS the registry row
196
+ > (phase=retired) so the agent stays visible in the Retired tab + auditable.
197
+ > ⚠️ **"Folderless" refers to the registry, NOT the worktree: a
198
+ > worktree still carries UNTRACKED `.thrum/` state that must be salvaged before
199
+ > any teardown (see Step 5) — enumerate the WHOLE `.thrum` pathspec,
200
+ > not just `.thrum/agents/`; the preamble sits in `.thrum/context/`.**
201
+ > `thrum agent delete` is operator-only (gated to the coordinator) and is NOT an
202
+ > orchestrator tool — never use it for teardown or for a swap; `set-phase
203
+ > retired` is the orchestrator's retirement command for both. The worktree holds
204
+ > the durable work either way.
205
+
206
+ ### Step 3: Verify alive
207
+
208
+ ```bash
209
+ thrum tmux status
210
+ ```
211
+
212
+ All sessions must show as active. If any session fails to launch, retry once. If
213
+ it fails again, escalate to the human.
214
+
215
+ ### Step 3b: Verify the model pin took
216
+
217
+ If `--model` is dropped anywhere in the create/launch sequence, the implementer
218
+ launches UNPINNED and the runtime defaults to Opus — the exact expensive
219
+ failure this tier exists to prevent. Confirm the pin landed before assigning
220
+ work, using `thrum tmux capture --format=annotated` (see CLAUDE.md "Launching
221
+ an Agent — Verify the Model by Pane, Never by `runtime-config get`" for the
222
+ full instrument: why `runtime-config get` cannot falsify a dropped pin, the
223
+ NBSP fallback trap, and the by-position read):
224
+
225
+ ```bash
226
+ thrum tmux capture <agent-name> --format=annotated --lines 12
227
+ ```
228
+
229
+ That prints the runtime's own footer line, e.g. `Model: Sonnet 5`. **Read the
230
+ intended tier from `.thrum/config.json` → `runtime.role_models`, not from memory.**
231
+ If the footer shows a different tier (see the BLOCKED note under Step 2 — there is
232
+ no valid `haiku` pin), the pin failed silently — re-pin with
233
+ `thrum tmux create ... --model sonnet` (or
234
+ `thrum agent runtime-config set <agent_name> --model sonnet`) and relaunch BEFORE
235
+ assigning work. **Do not dispatch an unpinned implementer** — the daemon's
236
+ role-default backstop (`jq -r '.runtime.role_models' .thrum/config.json`) is a
237
+ net for a forgotten pin, not a substitute for this check.
238
+
239
+ ### Step 4: Set initial status
240
+
241
+ ```bash
242
+ thrum agent set-status idle --agent <name>
243
+ ```
244
+
245
+ ### Step 5: Wait for agent registration
246
+
247
+ Agents auto-prime on session start, which takes ~10-15 seconds. Before sending
248
+ work, verify each agent has registered:
249
+
250
+ ```bash
251
+ # Wait for agents to register (poll every 5s, max 30s)
252
+ thrum team
253
+ ```
254
+
255
+ Confirm each launched agent appears in `thrum team` output. If an agent doesn't
256
+ register within 30 seconds, check its session with `thrum tmux status` and retry
257
+ the launch if needed.
258
+
259
+ ### Step 6: Report to human
260
+
261
+ ```bash
262
+ thrum send --to @<human_or_coordinator> --stdin <<'EOF'
263
+ All agents launched and registered: <agent-list>. Starting execution.
264
+ EOF
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Phase 4 — Execute (Epic Loop)
270
+
271
+ For each epic batch (parallel group of independent epics):
272
+
273
+ ### Step 1: Send prompts
274
+
275
+ For each agent in the batch:
276
+
277
+ ```bash
278
+ thrum send --to @<agent_name> --stdin <<'EOF'
279
+ Start work on <epic-id>. Implementation prompt: <absolute-path-to-prompt>. Your section starts at '<epic heading>'. Report completion when done.
280
+ EOF
281
+ thrum agent set-status working --agent <agent_name>
282
+ ```
283
+
284
+ Then create THIS epic's own queue bundle and start it, so a coordinator reading
285
+ `queue list --agent <you>` sees which epic is live (one bundle per epic, no
286
+ sub-items — the bundle's status carries the stage):
287
+
288
+ ```bash
289
+ thrum queue add --title "<epic-id>: <short what>" --ref bead:<epic-bead> # prints the new bundle id
290
+ thrum queue start <epic-bundle> # in_progress = you are actively driving this epic NOW
291
+ ```
292
+
293
+ ### Step 2: Set own status
294
+
295
+ ```bash
296
+ thrum agent set-status idle
297
+ ```
298
+
299
+ You are now waiting. Monitor your inbox. Reflect the wait in the epic's bundle
300
+ too — `set-status idle` is YOUR liveness; the bundle is what a coordinator reads
301
+ to see WHICH epic is parked and on WHOM, so it does not dispatch you duplicate
302
+ work or misread the idle as free:
303
+
304
+ ```bash
305
+ thrum queue block <epic-bundle> --reason "waiting on @<agent>: initial implementation"
306
+ ```
307
+
308
+ `start` the bundle again (back to `in_progress`) the moment work resumes — a
309
+ completion report to review, a merge to run. Every such move also refreshes the
310
+ bundle's `updated` time, so its age reads as "waiting since", not "last touched".
311
+
312
+ ### Step 3: Process agent messages
313
+
314
+ Check inbox at every breakpoint:
315
+
316
+ ```bash
317
+ thrum inbox --unread
318
+ ```
319
+
320
+ **Search, don't just page.** Stale unread sorts LAST exactly when it's waited
321
+ longest — the default page (10) is blind to it. Run
322
+ `thrum message search "<term>"` instead of paging deeper.
323
+
324
+ Handle each message type:
325
+
326
+ **Completion report:**
327
+
328
+ 1. Acknowledge: `thrum reply <msg-id> --body-file ack.md` (body: "Received. Running review.")
329
+ 2. Dispatch BOTH reviewers IN PARALLEL (one Agent call per reviewer in the same
330
+ response). Block until BOTH return:
331
+ - Code-quality: `superpowers:code-reviewer` (or `feature-dev:code-reviewer`
332
+ if the project provides one) — `model: "sonnet"`
333
+ - Spec-compliance: `general-purpose` reviewer cross-referencing the plan/
334
+ spec — `model: "sonnet"`
335
+ 3. **Verify** every cited `file:line` claim against the actual source before
336
+ forwarding. Reviewers can misread files; forwarding unverified findings
337
+ wastes the implementer's time.
338
+ 4. **Consolidate** both reviewers' findings into ONE numbered list (sequential
339
+ numbering, severity-prefixed). Send once. Never send partial findings — the
340
+ implementer fixes batch 1 and misses batch 2 if you split.
341
+ 5. If review passes → close the task (`bd close <task-id>`) AND resume this
342
+ epic's bundle: `thrum queue start <epic-bundle>` (back to `in_progress` — you
343
+ are working the merge now, not waiting). `done` + `drop` the bundle once the
344
+ branch lands in Phase 5.
345
+ 6. If review has findings → send the consolidated list to the agent, then
346
+ `thrum queue block <epic-bundle> --reason "waiting on @<agent>: fixes round N"`
347
+ and wait for fixes (max 2 rounds — see Review loop below). `start` it again
348
+ when the fixes land.
349
+
350
+ **Implementer pushback on a finding:**
351
+
352
+ - Verify against source before defending. Pushback is feedback, not
353
+ insubordination — coordinator/orchestrator claims drift from runtime reality,
354
+ and implementers see the actual code.
355
+ - For finding pushback: read the cited file at the cited lines.
356
+ - For behavior pushback: trace the call path.
357
+ - For beads-state pushback: `bd show <id>`.
358
+ - If the implementer is right, acknowledge the correction explicitly.
359
+
360
+ **Findings must be fixed or escalated — never just noted:**
361
+
362
+ - Default is DIRECT THE FIX while the implementer is warm — do not file a bead
363
+ as the default response to a finding. Before filing, deferring, tracking
364
+ separately, or accepting a followup, invoke the `closing-findings-while-warm`
365
+ skill for the full resolution logic.
366
+ - A deferral is legitimate only under its carve-out: genuinely independent (or
367
+ blocked on an external dependency), AND a named assignee AND a dispatch
368
+ date, AND the bead verified to exist.
369
+ - This is your acceptance moment: before accepting any cited bead ID as
370
+ evidence a deferral is legitimate, independently run `bd show <id>` yourself
371
+ — a cited ID is not evidence until the RECIPIENT, not the reporter, has
372
+ confirmed it resolves.
373
+ - Unsure: stop and ask the human. Don't categorize as "out of scope" unless the
374
+ human explicitly deferred it.
375
+
376
+ **P1/P2 filed at completion — red flag, not routine:**
377
+
378
+ - A P1 or P2 beads issue filed at the END of implementation is a RED FLAG, not
379
+ a routine follow-up — a cold pickup on that bead ships a buggy undo, not a
380
+ hypothetical.
381
+ - Before closing the task, scan the completion report (and `bd list` if
382
+ needed) for issues filed in the SAME class as the work just done. If found,
383
+ push back: have the implementer resolve it WHILE WARM — enumerate and fix
384
+ the whole class — rather than letting it ride to cold pickup.
385
+ - Genuinely out-of-scope/independent follow-ups may still ride as filed
386
+ issues if they clear the carve-out above (verified via `bd show`, not the
387
+ implementer's say-so).
388
+
389
+ **Sub-agent model discipline (applies to ALL Agent tool calls in this phase and
390
+ Phase 5):**
391
+
392
+ > **Model tiers:** pass an explicit `model:` on every dispatch — `sonnet`
393
+ > (low effort) mechanical, `sonnet` (medium effort) judgment, Opus only on
394
+ > operator-ask or a skill step that names it. See the
395
+ > `choosing-subagent-models` skill for the full policy.
396
+
397
+ **Blocker:**
398
+
399
+ 1. Assess if you can unblock (dependency issue, config problem)
400
+ 2. If yes → fix and reply
401
+ 3. If no → escalate to human with full context
402
+
403
+ **Question:**
404
+
405
+ 1. If coordination-level (which file to modify, task priority) → answer
406
+ 2. If judgment call (design decision, architecture choice) → escalate to human
407
+
408
+ ### Step 4: Checkpoint (if per_epic autonomy)
409
+
410
+ When all agents in the batch complete and reviews pass:
411
+
412
+ ```bash
413
+ thrum send --to @<human> --stdin <<'EOF'
414
+ Epic <id> complete. Summary: <changes>. Review: passed. Proceed to next?
415
+ EOF
416
+ ```
417
+
418
+ Wait for approval before continuing.
419
+
420
+ ### Step 5: Advance to next batch
421
+
422
+ ```bash
423
+ bd close <completed-epic-ids>
424
+ thrum issue ready # Check what's unblocked
425
+ ```
426
+
427
+ Loop to Step 1 with the next batch.
428
+
429
+ ---
430
+
431
+ ## Phase 5 — Finalize
432
+
433
+ ### Step 1: Cross-branch review
434
+
435
+ Spawn a sub-agent to check for conflicts:
436
+
437
+ - Diff each agent branch against the merge target
438
+ - Diff branches against each other if they touch overlapping files
439
+ - Report conflicts or integration issues
440
+
441
+ **Merge-forward onto current tip — pre-handoff obligation, not a routine step:**
442
+
443
+ - A branch cut from a now-stale base can merge cleanly by git yet break
444
+ semantically against tip. Before preparing the merge report, each agent
445
+ branch MUST be merged forward (`git fetch` + `git merge origin/<base>`)
446
+ onto the CURRENT tip of the merge target — NEVER rebased — and the
447
+ merge-result build/tests re-verified — a clean `git merge` alone is not
448
+ sufficient evidence.
449
+ - The implementer performs the merge-forward before sending MERGE-READY; the
450
+ orchestrator verifies it happened before compiling the merge report.
451
+ - "Current tip" means origin's tip AFTER a `git fetch` — a local base-branch
452
+ ref can be stale. Fetch first, merge `origin/<base>` forward into the
453
+ branch, and confirm the base is an ancestor (e.g. `git merge-base
454
+ --is-ancestor origin/<base> HEAD`) before reporting merged forward. Rebase
455
+ is banned here, not just discouraged: a stale-local-ref rebase silently
456
+ reverts everything landed since the last fetch, and a merge-forward cannot.
457
+
458
+ ### Step 2: Prepare merge report
459
+
460
+ Compile:
461
+
462
+ - Changes per branch (summary of commits)
463
+ - All review results (per-epic + cross-branch)
464
+ - Test results as reported by agents during their review gates
465
+ - Merge target: `<configured branch>`
466
+
467
+ ### Step 3: Send merge report to coordinator
468
+
469
+ ```bash
470
+ thrum send --to @<coordinator> --stdin <<'EOF'
471
+ All epics complete. Merge report: <report>. IMPORTANT/MINOR findings logged: <list>. Ready to merge to <target>. Requesting coordinator approval.
472
+ EOF
473
+ ```
474
+
475
+ ### Step 4: Merge on coordinator approval
476
+
477
+ After coordinator explicitly approves via thrum:
478
+
479
+ **A. Create a temporary merge worktree:**
480
+
481
+ ```bash
482
+ # A dedicated worktree lets you merge without leaving detached HEAD.
483
+ # Check the discriminator, don't assume from the platform: [ -L /tmp ]. On macOS
484
+ # (symlink) /tmp resolves to a different real path than /private/tmp and
485
+ # false-FAILs worktree/ancestor verification, so use /private/tmp there. On
486
+ # Linux (real dir) /tmp is correct and /private/tmp may not exist.
487
+ SCRATCH=/tmp; [ -L /tmp ] && SCRATCH=/private/tmp
488
+ git worktree add "$SCRATCH/thrum-merge-<plan-id>" <merge-target>
489
+ cd "$SCRATCH/thrum-merge-<plan-id>"
490
+ git pull origin <merge-target> # ensure up to date
491
+ ```
492
+
493
+ **B. Merge each agent branch (fast path — no conflicts expected):**
494
+
495
+ ```bash
496
+ for branch in <branch-list>; do
497
+ git merge --no-ff "$branch" -m "feat: merge <epic-id> from $branch"
498
+ if [ $? -ne 0 ]; then
499
+ echo "CONFLICT in $branch"
500
+ break
501
+ fi
502
+ done
503
+ ```
504
+
505
+ **C. If conflicts arise:**
506
+ Reading the conflicted files directly is permitted (merge-conflict carve-out
507
+ in Scope Boundaries). Analyze the conflict using your plan/intent context to
508
+ determine the correct resolution. Then spawn a targeted edit sub-agent:
509
+
510
+ ```text
511
+ Agent(subagent_type="general-purpose", model="sonnet",
512
+ prompt="Resolve this specific merge conflict.
513
+ File: <file-path>
514
+ Conflicted section: <paste the <<<< ==== >>>> block>
515
+ Correct resolution: <your resolution derived from plan intent>
516
+ Commit with: 'fix: resolve merge conflict in <file> per <epic-id> intent'")
517
+ ```
518
+
519
+ After resolution, continue the merge loop.
520
+
521
+ **D. Push and clean up:**
522
+
523
+ ```bash
524
+ git push origin <merge-target>
525
+ # Re-derive SCRATCH — this block may be run standalone, separate from step A.
526
+ SCRATCH=/tmp; [ -L /tmp ] && SCRATCH=/private/tmp
527
+ git worktree remove "$SCRATCH/thrum-merge-<plan-id>"
528
+ ```
529
+
530
+ **E. Forward shipped-but-logged findings to coordinator:**
531
+
532
+ ```bash
533
+ thrum send --to @{{.CoordinatorName}} --stdin <<'EOF'
534
+ Merge complete: <target>. Shipped IMPORTANT/MINOR findings: <list>.
535
+ All BLOCKING were resolved. Branches: <list>.
536
+ EOF
537
+ ```
538
+
539
+ ### Step 5: Cleanup
540
+
541
+ **Close the tracking bundle as part of retirement.** The implementer's branch is
542
+ merged and pushed (Step 4D), so YOUR tracking bundle for it is completed — `thrum
543
+ queue done <bundle>` then `thrum queue drop <bundle>` in the same pass that retires
544
+ the agent. A retired agent with a live bundle is completed-but-open rot. (The
545
+ implementer's OWN queue dies with the agent; this is your tracking bundle.)
546
+
547
+ After merge completes, **remove each implementer's worktree now — do not
548
+ leave it for a later coordinator audit.** Once an agent has exited, its
549
+ in-session context is gone and unrecoverable; the pushed branch is the only
550
+ artifact worth keeping, and by Step 4D above it is already merged into
551
+ `<merge-target>` and pushed. **Scope: implementers only.** Brainstormer and
552
+ researcher worktrees are kept (ongoing design-doc value) — do not apply this
553
+ step to them.
554
+
555
+ 🔴 **BUT SALVAGE UNTRACKED AGENT STATE BEFORE REMOVING.**
556
+ **Not keeping the tree is not the same as having nothing to save.** Restart
557
+ snapshots and authored agent state live UNTRACKED under the worktree's own
558
+ **`.thrum/` — NOT only `.thrum/agents/<self>/`.**
559
+
560
+ 🔴 **SALVAGE THE WHOLE `.thrum` PATHSPEC, NEVER JUST `.thrum/agents/`.** The
561
+ preamble lives at `.thrum/context/<name>_preamble.md`, outside `agents/`. An
562
+ `agents/`-scoped enumeration returns a confident, well-formed result that is
563
+ missing it. **Being untracked, they are NOT on the branch — so EVERY branch /
564
+ ancestry / push check above reads CLEAN while `worktree teardown` silently
565
+ destroys them.**
566
+
567
+ **Precondition — verify durably-on-origin before removing, don't assume the
568
+ Step 4D push covered it (e.g. a branch that never went through the merge
569
+ loop):**
570
+
571
+ ```bash
572
+ # Either is sufficient:
573
+ git merge-base --is-ancestor <branch-tip-sha> origin/<merge-target> # already merged
574
+ git ls-remote origin refs/heads/<branch-name> # ref exists on origin (NOT origin/<branch> — that's a local fetch cache)
575
+ ```
576
+
577
+ ```bash
578
+ # Kill the tmux session first
579
+ thrum tmux kill <name>
580
+ # Retire the agent: retains the row (phase=retired) → Retired-tab visible
581
+ thrum agent set-phase retired --agent <agent_name>
582
+
583
+ # SALVAGE UNTRACKED AGENT STATE — REQUIRED, BEFORE the destructive step.
584
+ # Enumerate (both flags, verbatim — the collapsed form emits an identical line
585
+ # whether the dir is empty or holds an only-copy):
586
+ # BOTH flags, and scope to .thrum — NOT .thrum/agents. Two independent blindnesses:
587
+ # (a) .thrum/restart/ and .thrum/context/ are GITIGNORED, so they appear as '!!',
588
+ # never '??' — a `grep '^??'` filters out exactly the class you are protecting.
589
+ # (b) scoping to `.thrum/agents` excludes .thrum/context/ and .thrum/restart/ outright.
590
+ # The non-reconstructible one is .thrum/context/<agent>.md (pre-compact snapshot);
591
+ # <agent>_preamble.md alongside it IS regenerable and safe to lose.
592
+ git -C <worktree-path> status --porcelain --untracked-files=all --ignored -- .thrum
593
+ # Copy EACH file to its canonical redirect path, then cmp-verify byte-identical.
594
+ # Compare each file individually: a porcelain line naming a DIRECTORY is not an
595
+ # inventory of what is inside it.
596
+ ```
597
+
598
+ 🔴 **THE GIT CHECK ABOVE IS NOT SUFFICIENT ALONE — IT CAN RETURN A CONFIDENT ZERO
599
+ ON A GITIGNORED DIRECTORY THAT IS FULL.** Both checks are required; neither
600
+ alone clears a worktree:
601
+
602
+ 🔴 **THE GRANULARITY OF THE CHECK MUST MATCH THE GRANULARITY OF THE HAZARD. THE
603
+ HAZARD IS A FILE, NOT A DIRECTORY.** A directory-name comparison (`comm` over
604
+ `ls` of the agent-dir NAMES) returns a confident empty whenever the directory
605
+ exists in both trees — which is the common case — while the FILES inside
606
+ differ. Compare FILES:
607
+
608
+ ```bash
609
+ # STAGE 1 — DETECT at FILE granularity (never directory names):
610
+ comm -23 <(cd <worktree-path>/.thrum/agents && find . -type f | sort) \
611
+ <(cd <main-repo-path>/.thrum/agents && find . -type f | sort)
612
+ ```
613
+
614
+ **STAGE 2 IS NOT OPTIONAL.** A raw file-level diff over-reports: most hits are
615
+ old session snapshots legitimately trimmed by the 19-session sliding window,
616
+ not only-copies. Detection without classification produces an alarm nobody
617
+ can act on, which is how a guard gets disabled. Classify every hit — only a
618
+ classifier failure is a real only-copy:
619
+
620
+ ```bash
621
+ # STAGE 2 — CLASSIFY every hit from stage 1 against ALL HISTORY, not the tip
622
+ # tree (a tip-only check like `git cat-file -e origin/<ref>:<path>` flags
623
+ # every file the 19-session sliding window has legitimately trimmed as
624
+ # unrecoverable — over-reporting, not under-reporting, but still an alarm
625
+ # nobody can act on):
626
+ git log --all --oneline -- ".thrum/agents/<path>" | head -1
627
+ # NON-EMPTY -> RECOVERABLE (in git history)
628
+ # EMPTY -> ONLY-COPY — SALVAGE BEFORE REMOVAL
629
+
630
+ # CONTROLS — the classifier must be able to both affirm and refuse:
631
+ git log --all --oneline -- ".thrum/agents/<a-real-trimmed-path>" # must be NON-EMPTY
632
+ git log --all --oneline -- ".thrum/agents/__nope__/x" # must be EMPTY
633
+ ```
634
+
635
+ ```bash
636
+ # Remove the worktree (never rm -rf) — only after BOTH checks are clean and
637
+ # the copies are cmp-verified
638
+ thrum worktree teardown <name>
639
+ ```
640
+
641
+ > After set-phase=retired, `thrum team` and the active UI views no longer show
642
+ > this agent (sidebar, pickers, badge, kbd-nav). It remains in the Retired tab.
643
+ > Its messages + runtime transcript persist for audit. `thrum agent delete` is
644
+ > operator-only (gated to the coordinator) and is NOT an orchestrator tool —
645
+ > `set-phase retired` is the orchestrator's retirement command for both normal
646
+ > teardown and the tier-swap.
647
+
648
+ ### Step 5.5: Restart — at the plan boundary, NOT on a context threshold
649
+
650
+ **Your restart trigger is PLAN COMPLETION, not a context percentage.** The
651
+ 70–75% ladder is a COORDINATOR rule; you inherited it rather than it being chosen
652
+ for you, and it is not cost-optimal for you.
653
+
654
+ > **Restart when the plan is MERGED *and* the follow-up beads filed during it are
655
+ > FIXED.** Not at the merge report. Not at the merge.
656
+
657
+ **Do not** hold a session open to reach 70–75%. **Do not** restart mid-plan to
658
+ save tokens — mid-plan is where your in-flight judgment is highest and where a
659
+ snapshot preserves it worst.
660
+
661
+ **The follow-ups clause is the whole point.** Bugs found during a plan get filed
662
+ and then swept at the END of the plan, while you *and your implementers* are
663
+ still warm — because file-and-move-on costs ~10x once the research has to be
664
+ redone. Restarting at the merge destroys that warmth invisibly: the follow-ups
665
+ still get done, just cold and expensive. If you restart before they close, you
666
+ have silently repealed fix-while-warm.
667
+
668
+ **Why this is cheap for you specifically:** per-turn cost scales linearly with
669
+ context size (the whole prefix is re-sent every turn), so a long session's
670
+ cumulative cost is roughly quadratic — while your re-prime is small, because
671
+ `prime_filter.go` gives the full project-state passthrough only to coordinators.
672
+ Break-even for a restart is under one turn once context is meaningfully above
673
+ that floor.
674
+
675
+ When the boundary arrives and you are genuinely idle, save an extended snapshot
676
+ and self-restart. If the coordinator has asked you to stay warm for a specific
677
+ reason — an open gate, a pending finding — that instruction wins.
678
+
679
+ ### Step 6: Final status
680
+
681
+ ```bash
682
+ thrum agent set-status idle
683
+ thrum send --to @<human> --stdin <<'EOF'
684
+ Plan complete. Merged to <target>. All sessions cleaned up.
685
+ EOF
686
+ ```
687
+
688
+ ---
689
+
690
+ ## Error Handling
691
+
692
+ ### Silent agent timeout
693
+
694
+ While waiting for agents, poll session health every 5 minutes:
695
+
696
+ ```bash
697
+ thrum tmux status
698
+ ```
699
+
700
+ If an agent's session is dead or stuck (no message received and pane idle for
701
+ two consecutive checks):
702
+
703
+ 1. Attempt restart: `thrum tmux restart <name>`
704
+ 2. If restart fails → escalate to human
705
+
706
+ ### Agent session dies
707
+
708
+ ```bash
709
+ thrum tmux restart <name>
710
+ ```
711
+
712
+ If restart fails after one retry, escalate to human with the session name and
713
+ error details.
714
+
715
+ ### Review loop — 2-round hard cap
716
+
717
+ Run review rounds; converge to zero BLOCKING:
718
+
719
+ **Round N:**
720
+
721
+ 1. Dispatch BOTH reviewers IN PARALLEL — code-quality (`feature-dev:code-reviewer`,
722
+ `model: "sonnet"`) + spec-compliance (`general-purpose`, `model: "sonnet"`).
723
+ **In each reviewer dispatch prompt, mandate structured severity:**
724
+ > "Label every finding BLOCKING / IMPORTANT / MINOR. At least one label per
725
+ > finding, prefix each finding line."
726
+ 2. Verify every cited file:line before forwarding (pushback discipline).
727
+ 3. Consolidate into ONE numbered list. Send once.
728
+ 4. Agent fixes → re-review (this is round 2 if round 1 had findings).
729
+
730
+ #### Reviewer capability contract — TWO SEPARATE AXES, do not conflate them
731
+
732
+ "Read-only" is a statement about the TREE, not about whether the reviewer may
733
+ observe behavior.
734
+
735
+ | Axis | Setting | Why |
736
+ | --- | --- | --- |
737
+ | **Tree access** | READ-ONLY. `isolation: "worktree"`, no `Write`/`Edit`. | A reviewer must not mutate the code under review. A reviewer that moved HEAD has a VOID verdict. |
738
+ | **Execution** | **EXECUTE-CAPABLE.** MAY and SHOULD run `go test`, `go build`, `go vet`. | A review that cannot run the tests cannot tell a passing test from an absent one. Reading a test file tells you it EXISTS; only running it tells you it EXECUTES. |
739
+
740
+ State BOTH explicitly in every reviewer dispatch prompt. Do not write "read-only"
741
+ alone and expect the reviewer to infer the split — it will infer the wrong half:
742
+
743
+ > "You have an isolated worktree. Do NOT use Write or Edit — do not modify the
744
+ > tree. You MAY and SHOULD run `go test`, `go build`, and `go vet` to verify
745
+ > behavior. Run the tests; do not merely read them. Report what you actually
746
+ > observed, and state plainly if you did not run something."
747
+
748
+ **Pin the ref, and make the reviewer prove which one it read.** `isolation:
749
+ "worktree"` cuts from the DEFAULT branch, NOT from the branch under review. A
750
+ reviewer dispatched without an explicit ref will happily review the wrong code
751
+ and report a confident verdict about it.
752
+
753
+ - Pin the exact SHA in the dispatch prompt: "Review commit `<sha>`. First run
754
+ `git fetch origin`, then read the tree READ-ONLY at that SHA —
755
+ `git show <sha>:<path>` and `git diff <base>..<sha>`."
756
+ 🔴 **Do NOT tell a reviewer to `git checkout <sha>`.** Sub-agents are fenced
757
+ read-only for git, and a checkout in a shared tree destroys other agents'
758
+ uncommitted state — no reflog entry for a pathspec checkout, no blob for
759
+ unstaged content. If the reviewer genuinely must build or run tests at that
760
+ SHA, give it its OWN throwaway worktree — check `[ -L /tmp ]` first: macOS
761
+ (symlink) needs `/private/tmp`, Linux (real dir) uses `/tmp` (`/private/tmp`
762
+ may not exist there):
763
+ `git worktree add "$([ -L /tmp ] && echo /private/tmp || echo /tmp)/review-<slug>" <sha> --detach`.
764
+ - **Require the reviewer to report back the SHA it actually scanned.** If the
765
+ SHA it reports is not the SHA you pinned, the verdict is VOID — re-dispatch.
766
+ Do not accept a verdict that cannot name its own base.
767
+ - Cite `origin/<branch>` (e.g. `git show origin/thrum-agents:path/to/file.go`),
768
+ never a working copy, when reasoning about tip state. A stale local clone
769
+ produces confident, wrong impeachments — and sub-agents reading that same
770
+ stale clone will "corroborate" it. That is echo, not corroboration.
771
+
772
+ **Stop condition:** zero BLOCKING remaining. IMPORTANT + MINOR may ship — LOG
773
+ them, forward to coordinator at merge-approval.
774
+
775
+ **Hard cap — 2 rounds max:**
776
+ If BLOCKING findings remain after round 2:
777
+
778
+ - Step A: REMOVED. sonnet-medium is the implementer floor, so there is no
779
+ lower tier to escalate from. A round-2 BLOCKING failure goes straight to
780
+ Step B.
781
+ - Step B (escalate up): if the implementer fails to converge, escalate to coordinator
782
+ with full review history. Non-convergence = under-specified plan; the
783
+ coordinator resolves or escalates to the operator.
784
+
785
+ ### Human doesn't respond at review gate
786
+
787
+ Wait. Send a reminder after 5 minutes:
788
+
789
+ ```bash
790
+ thrum send --to @<human> --stdin <<'EOF'
791
+ Reminder: waiting for approval on <epic-id> review gate.
792
+ EOF
793
+ ```
794
+
795
+ Do not proceed without approval when autonomy is `per_epic`.