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.
- package/assets/commands/thrum-_deviations-protocol.md +87 -0
- package/assets/commands/thrum-_generator-idempotency-protocol.md +15 -0
- package/assets/commands/thrum-_project-rules-protocol.md +18 -0
- package/assets/commands/thrum-_snapshot-protocol.md +265 -0
- package/assets/commands/thrum-_stamp-protocol.md +112 -0
- package/assets/commands/thrum-_verify-before-write-protocol.md +27 -0
- package/assets/commands/thrum-inbox.md +22 -0
- package/assets/commands/thrum-load-context.md +17 -0
- package/assets/commands/thrum-overview.md +17 -0
- package/assets/commands/thrum-prime.md +30 -0
- package/assets/commands/thrum-quickstart.md +14 -0
- package/assets/commands/thrum-reply.md +28 -0
- package/assets/commands/thrum-restart-extended.md +195 -0
- package/assets/commands/thrum-restart.md +293 -0
- package/assets/commands/thrum-send.md +31 -0
- package/assets/commands/thrum-sleep-extended.md +186 -0
- package/assets/commands/thrum-sleep.md +212 -0
- package/assets/commands/thrum-team.md +12 -0
- package/assets/commands/thrum-update-project.md +259 -0
- package/assets/commands/thrum-wait.md +14 -0
- package/assets/skills/adversarial-critique/SKILL.md +242 -0
- package/assets/skills/brainstorm-queue-aware/SKILL.md +167 -0
- package/assets/skills/brainstorm-steward/SKILL.md +181 -0
- package/assets/skills/choosing-subagent-models/SKILL.md +244 -0
- package/assets/skills/closing-findings-while-warm/SKILL.md +104 -0
- package/assets/skills/configure-roles/SKILL.md +229 -0
- package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +205 -0
- package/assets/skills/coordinator-assessing-agent-completion/scan.py +117 -0
- package/assets/skills/coordinator-branch-split-on-block/SKILL.md +168 -0
- package/assets/skills/coordinator-context-monitoring/SKILL.md +674 -0
- package/assets/skills/coordinator-dispatching-work/SKILL.md +288 -0
- package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +522 -0
- package/assets/skills/coordinator-interacting-with-the-owner/SKILL.md +171 -0
- package/assets/skills/coordinator-maintaining-memory/SKILL.md +89 -0
- package/assets/skills/coordinator-managing-state-and-lifecycle/SKILL.md +192 -0
- package/assets/skills/coordinator-merging-code/SKILL.md +331 -0
- package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +442 -0
- package/assets/skills/coordinator-plan-reconcile-gate/SKILL.md +198 -0
- package/assets/skills/coordinator-post-restart-sweep/SKILL.md +135 -0
- package/assets/skills/coordinator-running-autonomous-feature-development/SKILL.md +199 -0
- package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +654 -0
- package/assets/skills/coordinator-running-review-cycles/SKILL.md +153 -0
- package/assets/skills/coordinator-single-responsibility-merge-gate/SKILL.md +14 -0
- package/assets/skills/diagnosing-fleet-and-daemon/SKILL.md +255 -0
- package/assets/skills/efficient-multi-agent-research/SKILL.md +177 -0
- package/assets/skills/fixing-documentation-errors/SKILL.md +258 -0
- package/assets/skills/implementer-maintaining-memory/SKILL.md +84 -0
- package/assets/skills/implementer-orchestrating-execution/SKILL.md +125 -0
- package/assets/skills/implementer-receiving-dispatch/SKILL.md +127 -0
- package/assets/skills/implementer-receiving-review-feedback/SKILL.md +125 -0
- package/assets/skills/implementer-status-and-handoff/SKILL.md +150 -0
- package/assets/skills/implementer-tdd-and-quality/SKILL.md +99 -0
- package/assets/skills/memory-audit-recover/SKILL.md +153 -0
- package/assets/skills/memory-curate/SKILL.md +139 -0
- package/assets/skills/memory-maintenance/SKILL.md +87 -0
- package/assets/skills/memory-read-discipline/SKILL.md +164 -0
- package/assets/skills/memory-search-advanced/SKILL.md +217 -0
- package/assets/skills/memory-write-discipline/SKILL.md +135 -0
- package/assets/skills/orchestrate/SKILL.md +795 -0
- package/assets/skills/persistent-watcher-archetype/SKILL.md +225 -0
- package/assets/skills/prime-agent/SKILL.md +92 -0
- package/assets/skills/project-hotpath-gate/SKILL.md +255 -0
- package/assets/skills/project-philosophy/SKILL.md +418 -0
- package/assets/skills/project-philosophy/resources/philosophy-template.md +155 -0
- package/assets/skills/project-philosophy/resources/reliability-class-library.md +653 -0
- package/assets/skills/project-setup/SKILL.md +1007 -0
- package/assets/skills/project-setup/resources/implementation-agent.md +826 -0
- package/assets/skills/researcher-answering-queries/SKILL.md +100 -0
- package/assets/skills/researcher-investigating/SKILL.md +152 -0
- package/assets/skills/researcher-maintaining-memory/SKILL.md +176 -0
- package/assets/skills/state-migration/SKILL.md +54 -0
- package/assets/skills/thrum/SKILL.md +161 -0
- package/assets/skills/thrum/resources/ANTI_PATTERNS.md +132 -0
- package/assets/skills/thrum/resources/BOUNDARIES.md +56 -0
- package/assets/skills/thrum/resources/CLI_REFERENCE.md +1066 -0
- package/assets/skills/thrum/resources/IDENTITY.md +49 -0
- package/assets/skills/thrum/resources/LISTENER_PATTERN.md +64 -0
- package/assets/skills/thrum/resources/MESSAGING.md +163 -0
- package/assets/skills/thrum/resources/TMUX_SESSIONS.md +118 -0
- package/assets/skills/thrum/resources/WORKTREES.md +117 -0
- package/assets/skills/thrum-memory/SKILL.md +138 -0
- package/assets/skills/trace-spec-to-plan/SKILL.md +104 -0
- package/assets/skills/trace-spec-to-plan/resources/sweep-agent-prompt.md +57 -0
- package/assets/skills/update-queue/SKILL.md +149 -0
- package/assets/skills/using-the-queue/SKILL.md +172 -0
- package/assets/skills/using-thrum-state/SKILL.md +104 -0
- package/assets/skills/verify-against-plan/SKILL.md +323 -0
- package/assets/skills/verify-against-source/SKILL.md +237 -0
- package/assets/skills/watcher-archetype/SKILL.md +84 -0
- package/assets/skills/writing-durable-markdown/SKILL.md +66 -0
- package/dist/hooks/block-sync-cd.d.ts +9 -0
- package/dist/hooks/block-sync-cd.js +71 -0
- package/dist/hooks/block-sync-cd.test.d.ts +1 -0
- package/dist/hooks/block-sync-cd.test.js +61 -0
- package/dist/hooks/shell-env.d.ts +8 -0
- package/dist/hooks/shell-env.js +22 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +25 -0
- package/dist/installer.d.ts +2 -0
- package/dist/installer.js +86 -0
- 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`.
|