opencode-thrum-pro 0.1.5 → 0.1.7

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 (90) hide show
  1. package/assets/commands/thrum-compact-extended.md +367 -0
  2. package/assets/commands/thrum-compact.md +301 -0
  3. package/assets/commands/thrum-inbox.md +1 -1
  4. package/assets/commands/thrum-restart-extended.md +85 -16
  5. package/assets/commands/thrum-restart.md +106 -14
  6. package/assets/commands/thrum-send.md +4 -1
  7. package/assets/commands/thrum-sleep-extended.md +68 -51
  8. package/assets/commands/thrum-sleep.md +68 -63
  9. package/assets/commands/thrum-update-project.md +1 -1
  10. package/assets/skills/adversarial-critique/SKILL.md +5 -8
  11. package/assets/skills/brainstorm-steward/SKILL.md +65 -11
  12. package/assets/skills/brainstormer-staying-current/SKILL.md +1 -4
  13. package/assets/skills/choosing-subagent-models/SKILL.md +200 -70
  14. package/assets/skills/closing-findings-while-warm/SKILL.md +1 -2
  15. package/assets/skills/configure-roles/SKILL.md +2 -2
  16. package/assets/skills/conversation-only-context/SKILL.md +11 -11
  17. package/assets/skills/conversation-only-context/resources/driver-subagent-pattern.md +1 -1
  18. package/assets/skills/conversation-only-context/resources/remote-environment-scenarios.md +1 -1
  19. package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +98 -6
  20. package/assets/skills/coordinator-branch-split-on-block/SKILL.md +1 -2
  21. package/assets/skills/coordinator-context-monitoring/SKILL.md +29 -19
  22. package/assets/skills/coordinator-deploying-a-node/SKILL.md +124 -0
  23. package/assets/skills/coordinator-dispatching-work/SKILL.md +26 -14
  24. package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +65 -21
  25. package/assets/skills/coordinator-interacting-with-the-owner/SKILL.md +1 -2
  26. package/assets/skills/coordinator-maintaining-memory/SKILL.md +1 -1
  27. package/assets/skills/coordinator-managing-state-and-lifecycle/SKILL.md +7 -8
  28. package/assets/skills/coordinator-merging-code/SKILL.md +43 -22
  29. package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +29 -9
  30. package/assets/skills/coordinator-plan-reconcile-gate/SKILL.md +4 -5
  31. package/assets/skills/coordinator-rolling-out-to-nodes/SKILL.md +92 -0
  32. package/assets/skills/coordinator-running-autonomous-feature-development/SKILL.md +3 -3
  33. package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +25 -25
  34. package/assets/skills/coordinator-running-review-cycles/SKILL.md +16 -6
  35. package/assets/{commands/thrum-_deviations-protocol.md → skills/deviations-protocol/SKILL.md} +6 -12
  36. package/assets/skills/diagnosing-fleet-and-daemon/SKILL.md +0 -2
  37. package/assets/skills/efficient-multi-agent-research/SKILL.md +3 -3
  38. package/assets/skills/generator-idempotency-protocol/SKILL.md +9 -0
  39. package/assets/skills/implementer-maintaining-memory/SKILL.md +3 -4
  40. package/assets/skills/implementer-orchestrating-execution/SKILL.md +12 -16
  41. package/assets/skills/implementer-receiving-dispatch/SKILL.md +15 -17
  42. package/assets/skills/implementer-receiving-review-feedback/SKILL.md +3 -4
  43. package/assets/skills/implementer-status-and-handoff/SKILL.md +1 -14
  44. package/assets/skills/implementer-tdd-and-quality/SKILL.md +2 -2
  45. package/assets/skills/memory-curate/SKILL.md +1 -1
  46. package/assets/skills/memory-write-discipline/SKILL.md +1 -1
  47. package/assets/skills/orchestrate/SKILL.md +77 -36
  48. package/assets/skills/persistent-watcher-archetype/SKILL.md +172 -25
  49. package/assets/skills/persistent-watcher-archetype/resources/capture_archive.py +618 -0
  50. package/assets/skills/persistent-watcher-archetype/resources/jev_watcher_filter.py +837 -0
  51. package/assets/skills/persistent-watcher-archetype/resources/roster-watch.sh +1140 -0
  52. package/assets/skills/persistent-watcher-archetype/resources/roster-watch_test.sh +291 -0
  53. package/assets/skills/persistent-watcher-archetype/resources/thrum-capture-fallback.sh +2 -2
  54. package/assets/skills/persistent-watcher-archetype/resources/thrum-watch-pane-capture.sh +20 -8
  55. package/assets/skills/prime-agent/SKILL.md +10 -0
  56. package/assets/skills/project-hotpath-gate/SKILL.md +1 -2
  57. package/assets/skills/project-philosophy/SKILL.md +1 -2
  58. package/assets/skills/project-rules-protocol/SKILL.md +12 -0
  59. package/assets/skills/project-setup/SKILL.md +27 -22
  60. package/assets/skills/project-setup/resources/implementation-agent.md +55 -35
  61. package/assets/skills/researcher-answering-queries/SKILL.md +1 -2
  62. package/assets/skills/researcher-investigating/SKILL.md +8 -13
  63. package/assets/skills/researcher-maintaining-memory/SKILL.md +1 -1
  64. package/assets/{commands/thrum-_snapshot-protocol.md → skills/snapshot-protocol/SKILL.md} +27 -21
  65. package/assets/{commands/thrum-_stamp-protocol.md → skills/stamp-protocol/SKILL.md} +14 -8
  66. package/assets/skills/thrum/SKILL.md +14 -7
  67. package/assets/skills/thrum/resources/ANTI_PATTERNS.md +16 -18
  68. package/assets/skills/thrum/resources/CLI_REFERENCE.md +17 -11
  69. package/assets/skills/thrum/resources/LISTENER_PATTERN.md +9 -3
  70. package/assets/skills/thrum/resources/MESSAGING.md +18 -11
  71. package/assets/skills/thrum/resources/WORKTREES.md +1 -1
  72. package/assets/skills/thrum-memory/SKILL.md +1 -1
  73. package/assets/skills/trace-spec-to-plan/resources/sweep-agent-prompt.md +1 -1
  74. package/assets/skills/update-queue/SKILL.md +6 -8
  75. package/assets/skills/using-the-dashboard/SKILL.md +30 -0
  76. package/assets/skills/using-the-queue/SKILL.md +76 -5
  77. package/assets/skills/using-thrum-state/SKILL.md +85 -2
  78. package/assets/skills/verify-against-plan/SKILL.md +122 -7
  79. package/assets/skills/watcher-archetype/SKILL.md +18 -0
  80. package/assets/skills/writing-durable-markdown/SKILL.md +5 -0
  81. package/dist/installer-assets.test.js +41 -0
  82. package/dist/installer.js +4 -4
  83. package/dist/permission-fixture.integration.test.js +4 -4
  84. package/package.json +1 -1
  85. package/assets/commands/thrum-_generator-idempotency-protocol.md +0 -15
  86. package/assets/commands/thrum-_project-rules-protocol.md +0 -18
  87. package/assets/commands/thrum-_verify-before-write-protocol.md +0 -27
  88. package/assets/skills/coordinator-deploying-the-fleet/SKILL.md +0 -396
  89. package/dist/allowlist-sync.test.js +0 -44
  90. /package/dist/{allowlist-sync.test.d.ts → installer-assets.test.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: choosing-subagent-models
3
- description: "Use when about to launch, spawn, or dispatch a subagent, sub-agent, or parallel agent - including the Agent/Task tool, an Explore agent, fanning out research, or any time you choose a model for a subagent. ALSO fires on every REVIEW dispatch - dispatching a reviewer, a code review, a code-quality review, a spec-compliance review, a dual review, a verify-against-plan or verify-against-source pass, or a merge-gate sub-agent. Reviewer dispatch is the HIGHEST-STAKES judgment-tier spawn and is the one most often done from memory. Enforces the role-based model tiering (opus-low orchestrators, sonnet-medium implementers and reviewers, sonnet-low sub-agents) and cheap parallel fan-out."
3
+ description: "Use when about to launch, spawn, or dispatch a subagent, sub-agent, or parallel agent - including the Agent/Task tool, an Explore agent, fanning out research, or any time you choose a model for a subagent. ALSO fires on every REVIEW dispatch - dispatching a reviewer, a code review, a code-quality review, a spec-compliance review, a dual review, a verify-against-plan or verify-against-source pass, or a merge-gate sub-agent. Reviewer dispatch is the HIGHEST-STAKES judgment-tier spawn and is the one most often done from memory. Enforces role-based model TIERING (mechanical, judgment, orchestration) resolved to a concrete model+effort for whichever runtime you are actually running under, and cheap parallel fan-out."
4
4
  ---
5
5
 
6
6
  # Choosing Subagent Models
@@ -11,50 +11,95 @@ description: "Use when about to launch, spawn, or dispatch a subagent, sub-agent
11
11
  (e.g. `/tmp/<task>.md`); its reply to you is only a summary. Put this
12
12
  in the prompt.**
13
13
 
14
- ## Pin every spawn. The floor depends on the agent's ROLE.
14
+ ## Pick a TIER by role/task, then resolve it for YOUR runtime. Pin every spawn.
15
+
16
+ Model selection here is two steps, always in this order:
17
+
18
+ 1. **Pick the semantic tier** by the spawned agent's role/task — one of three,
19
+ named identically everywhere in the fleet (Go constants, role templates,
20
+ this doc): **`mechanical`** (rote/find-replace/grep-and-collect/lint/file-maps —
21
+ the cheapest tier), **`judgment`** (the default tier for implementers,
22
+ reviewers, verifiers, researchers — real analysis, not busywork), and
23
+ **`orchestration`** (orchestrator/coordinator tier — never spawned for a
24
+ sub-agent, only ever the operator's own agent or a skill that explicitly
25
+ names it for one step).
26
+ 2. **Resolve that tier to a concrete `model:` + `effort:` for the runtime you
27
+ are actually running under** — via that runtime's own preset
28
+ (`RuntimePreset.TierModels`) or operator config (`runtime.role_models`);
29
+ see "Where the tier-model mapping lives" below. Never assume Claude's
30
+ model names (`sonnet`, `opus`, `haiku`) apply —
31
+ a Codex or OpenCode agent reading this same file has no such models, and
32
+ passing one either errors or silently falls back to the runtime's own
33
+ default (see "Never let an unresolved pin fall through" below).
34
+
35
+ Every subagent you spawn MUST pass an explicit, resolved `model:` (plus effort
36
+ where the runtime supports it). Omitting it runs the subagent on YOUR model —
37
+ the single biggest avoidable cost leak in agent work.
38
+
39
+ **The mechanical tier never resolves to a below-floor model, for any runtime.**
40
+ On Claude specifically that means **Haiku is banned entirely** — there is no
41
+ mechanical-task carve-out that reaches for it; lint runs, grep-and-collect,
42
+ file maps, config edits, and all other "simple" work dispatch at the
43
+ mechanical tier's Claude resolution (sonnet-low), not Haiku. Never select
44
+ Haiku on own judgment on Claude — use the mechanical tier's resolved value
45
+ instead. Other runtimes floor at their own mechanical-tier value
46
+ (`RuntimePreset.TierModels`), not at a Claude name.
47
+
48
+ ### Read the tiers at the moment of use
49
+
50
+ **Role templates and launch examples do not name models or effort levels; this
51
+ skill and the live config do.** Read the tier when you are about to spawn or
52
+ launch, never from memory or from a copied example:
15
53
 
16
- Every subagent you spawn MUST pass an explicit `model:` (plus effort where the
17
- runtime supports it). Omitting it runs the subagent on YOUR model (Opus) — the
18
- single biggest avoidable cost leak in agent work.
54
+ ```bash
55
+ jq -r '.runtime.role_models' .thrum/config.json
56
+ ```
19
57
 
20
- **Haiku is banned entirely.** There is no
21
- mechanical-task carve-out anymore — lint runs, grep-and-collect, file maps,
22
- config edits, and all other "simple" work now dispatch at sonnet-low, not Haiku.
23
- Never select Haiku on own judgment — use sonnet-low instead.
58
+ Launching with `--role` and no `--model` resolves the role default
59
+ automatically. A `--model` / `--effort` flag in a launch command takes its value
60
+ from `runtime.role_models` for the target role, per this skill.
24
61
 
25
62
  ### Agent tiers
26
63
 
27
64
  Effort tier governs whether an agent does the hard thing or the expedient thing.
28
- These are the tiers now:
29
-
30
- | Role | Model / Effort |
31
- | ---------------------------- | ------------------- |
32
- | **Orchestrator** | **`opus` / low** |
33
- | **Implementer** | **`sonnet` / medium** |
34
- | **Verifier / reviewer** | **`sonnet` / medium** |
35
- | **Sub-agent** (investigation, grep, mechanical) | **`sonnet` / low** |
36
-
37
- - **`model: "sonnet"` @ low effort — sub-agents ONLY.** Investigation,
38
- grep-and-collect, file maps, lint runs, mechanical tasks. This is the floor for
39
- a *sub-agent*, NOT for an implementer or a reviewer.
40
- - **`model: "sonnet"` @ MEDIUM effort — implementers, verifiers, reviewers.**
41
- Not low. A reviewer on low effort is a rubber stamp with extra steps, and
42
- rubber-stamped reviews are how a merge gate that ran zero tests survived six
43
- sessions.
44
- - **`model: "opus"` @ low — orchestrators.** Not selectable for sub-agents —
45
- set by the operator on the agent's runtime-config.
46
- - **`model: "opus"` — NOT your call.** Allowed only when (a) the operator
47
- explicitly asked for a deep review or prose review in this task, or (b) a
48
- skill you are running prescribes Opus for the specific step you are currently
49
- executing — NOT for every spawn under that skill. "This research is hard /
50
- important" is NOT a justification — hard investigation is exactly what Sonnet
51
- is for.
65
+ These are the three tiers, with their Claude-runtime resolution shown as a
66
+ worked example — **if you are running under a different runtime, resolve the
67
+ same tier from your own runtime's preset (`RuntimePreset.TierModels`) or
68
+ `runtime.role_models`, not from the Claude column:**
69
+
70
+ | Role | Tier | Resolved for Claude (example) |
71
+ | ---------------------------- | ------------- | ------------------- |
72
+ | **Orchestrator / coordinator** | `orchestration` | **`opus` / low** |
73
+ | **Implementer** | `judgment` | **`sonnet` / medium** |
74
+ | **Verifier / reviewer** | `judgment` | **`sonnet` / medium** |
75
+ | **Sub-agent** (investigation, grep, mechanical) | `mechanical` | **`sonnet` / low** |
76
+
77
+ - **`mechanical` tier (sub-agents ONLY)** — investigation, grep-and-collect,
78
+ file maps, lint runs, mechanical tasks. Resolves to `sonnet` @ low effort on
79
+ Claude. This is the floor for a *sub-agent*, NOT for an implementer or a
80
+ reviewer, and NOT the tier a non-Claude runtime should read as its default.
81
+ - **`judgment` tier (implementers, verifiers, reviewers)** — resolves to
82
+ `sonnet` @ MEDIUM effort on Claude. Not low. A reviewer on low effort is a
83
+ rubber stamp with extra steps, and rubber-stamped reviews are how a merge
84
+ gate that ran zero tests survived six sessions.
85
+ - **`orchestration` tier (orchestrators/coordinators)** — resolves to `opus` @
86
+ low on Claude. Not selectable for sub-agents — set by the operator on the
87
+ agent's runtime-config.
88
+ - **`orchestration` tier is NOT your call to spawn.** Allowed only when (a) the
89
+ operator explicitly asked for a deep review or prose review in this task, or
90
+ (b) a skill you are running prescribes the orchestration tier for the
91
+ specific step you are currently executing — NOT for every spawn under that
92
+ skill. "This research is hard / important" is NOT a justification — hard
93
+ investigation is exactly what the `judgment` tier is for.
52
94
 
53
95
  ## Worked examples — LITERAL ARGUMENTS, AND EFFORT IS TOOL-DEPENDENT
54
96
 
55
- **Pin `model` on every spawn. Pass `effort` wherever the mechanism exposes it.**
56
- Syntax per mechanism — re-check the schema in front of you rather than restating
57
- from memory, because it can change:
97
+ **Pin `model` on every spawn, using the value your runtime's own preset
98
+ (`RuntimePreset.TierModels`) or `runtime.role_models` resolves the tier to.**
99
+ **Pass
100
+ `effort` wherever the mechanism exposes it** — some mechanisms don't. Syntax per
101
+ mechanism — re-check the schema in front of you rather than restating from
102
+ memory, because it can change:
58
103
 
59
104
  | Mechanism | `model` | `effort` |
60
105
  |---|---|---|
@@ -62,8 +107,14 @@ from memory, because it can change:
62
107
  | **Workflow `agent()`** (opts: label, phase, schema, model, effort, isolation, agentType) | ✅ settable | ✅ settable |
63
108
  | **Agent DEFINITION** (`.claude/agents/*.md` / plugin `agents/*.md` frontmatter) | ✅ | ✅ — sets the default for that agent type |
64
109
  | **`thrum tmux create` / `launch`** | ✅ `--model` | ✅ `--effort` — pass on BOTH |
110
+ | **Other runtimes' own spawn mechanism** | ✅ settable | runtime-dependent — check its own schema |
65
111
 
66
- **Agent tool — `model` only. It takes no `effort` argument.**
112
+ **Below is ONE fully concrete example — what a `judgment`-tier spawn looks
113
+ like once resolved for Claude's own Agent tool (which takes no `effort`
114
+ argument).** It is Claude-specific syntax with a Claude-specific model string;
115
+ if you are running under a different runtime, use that runtime's own spawn
116
+ mechanism and its own resolved model+effort from `RuntimePreset.TierModels` /
117
+ `runtime.role_models` instead of copying this literal string.
67
118
 
68
119
  ```python
69
120
  Agent(subagent_type="general-purpose", model="sonnet",
@@ -71,12 +122,14 @@ Agent(subagent_type="general-purpose", model="sonnet",
71
122
  prompt="...")
72
123
  ```
73
124
 
74
- **The tier philosophy still governs even where the Agent tool cannot express it:**
75
- sonnet-low for investigation and mechanical work, sonnet-medium for reviewers,
76
- verifiers and implementers. Where effort is not settable, carry the intent through
77
- the agent definition, the Workflow opts, or the tmux launch flags.
125
+ **The tier philosophy still governs even where a mechanism cannot express
126
+ `effort`:** the `model` value alone still must be the tier's resolved value for
127
+ YOUR runtime — never a bare Claude name assumed universal. Where effort is not
128
+ settable, carry the intent through the agent definition, the Workflow opts, or
129
+ the tmux launch flags instead.
78
130
 
79
- An agent definition can also carry a default:
131
+ An agent definition can also carry a default (Claude example — resolve to
132
+ your own runtime's `mechanical`-tier value if you are not Claude):
80
133
 
81
134
  ```yaml
82
135
  # claude-plugin/agents/message-listener.md
@@ -85,53 +138,88 @@ model: sonnet
85
138
  effort: low
86
139
  ```
87
140
 
88
- **Workflow `agent()` — effort IS a literal argument. Pass it.**
141
+ **Workflow `agent()` — effort IS a literal argument. Pass it, resolved for
142
+ your runtime's tier:**
89
143
 
90
144
  ```javascript
91
- agent(prompt, { model: "sonnet", effort: "medium" }) // reviewer / implementer
92
- agent(prompt, { model: "sonnet", effort: "low" }) // mechanical sub-agent
145
+ agent(prompt, { model, effort }) // `model`/`effort` = your runtime's resolution
146
+ // of the `judgment` tier (reviewer/implementer)
147
+ // or the `mechanical` tier (sub-agent) —
148
+ // resolve via RuntimePreset.TierModels /
149
+ // runtime.role_models for the literal values
93
150
  ```
94
151
 
95
- **THE DIRECTIVE, imperative and not a comment: REVIEWERS RUN SONNET AT MEDIUM
96
- EFFORT.** Pass `effort: "medium"` literally under Workflow, in the agent
97
- definition, or on `thrum tmux create`/`launch`. Never dispatch a reviewer "from
98
- memory".
152
+ **THE DIRECTIVE, imperative and not a comment: REVIEWERS RUN THE `judgment`
153
+ TIER, WHICH IS MEDIUM EFFORT ON EVERY RUNTIME THAT HAS AN EFFORT KNOB.** Pass
154
+ the resolved effort literally under Workflow, in the agent definition, or on
155
+ `thrum tmux create`/`launch` (the Agent tool takes no `effort`, so `model`
156
+ alone must still be the `judgment`-tier value there). Never dispatch a
157
+ reviewer "from memory", and never dispatch one at the mechanical tier.
99
158
 
100
159
  **AND VERIFY, DO NOT ASSERT:** any claim about what a tool does or does not expose
101
160
  must be checked against the schema in front of you.
102
161
 
103
- Never select Opus or Haiku on own judgment — use Sonnet, at the floor of
104
- sonnet-low.
162
+ Never select the `orchestration` tier or a below-floor model on your own
163
+ judgment — use the `judgment` tier's resolved value for your runtime, at the
164
+ floor of that tier's lowest effort.
165
+
166
+ ## Where the tier-model mapping lives
167
+
168
+ **Do not copy a tier's model string from this doc — read it at the moment of
169
+ use.** The three semantic tiers (`mechanical` / `judgment` / `orchestration`)
170
+ are the same across every runtime; only the concrete model+effort differs per
171
+ runtime, and that mapping lives in exactly two places:
172
+
173
+ - **The runtime's own preset** (the `TierModels` field of the runtime preset
174
+ schema) — the machine-checked, per-runtime tier→model
175
+ table. A runtime with no entry for a tier has no fleet-configured value for
176
+ it and resolves to nothing rather than inheriting another runtime's model.
177
+ - **`runtime.role_models` in `.thrum/config.json`** — operator configuration
178
+ for this project, which always outranks the preset's tier table.
105
179
 
106
- ## Fleet model-tiering by runtime/role
180
+ **If you are running under Claude**, use the Agent tiers table above
181
+ (orchestrator/implementer/reviewer/sub-agent → orchestration/judgment/
182
+ judgment/mechanical), plus brainstormer → `orchestration` and brainstormer's
183
+ own subagents → `mechanical` (except reviewers, which are always `judgment`).
107
184
 
108
- Different runtimes and roles pin different tiers. Claude tiers are canonical —
109
- see the Agent tiers table above (orchestrator/implementer/reviewer/sub-agent),
110
- plus brainstormer → opus-medium and brainstormer's own subagents → sonnet-low
111
- (except reviewers → sonnet-medium). Other runtimes:
185
+ **If you are running under a different runtime, read your own tier's value
186
+ from the two sources above** — never assume Claude's model names apply, and
187
+ never hard-code a model string you saw once in a doc or a prior session.
112
188
 
113
- | Runtime | Role | Model / effort |
114
- | ------------ | ---------------------------- | --------------------------------------------------- |
115
- | OpenCode | default | GLM-5.2 (fine as-is) |
116
- | Codex | orchestrator / reviewer | gpt-5.5-medium |
117
- | Codex | implementer | gpt-5.5-low |
118
- | Cursor-agent | default | composer-2.5 (fine as-is) |
189
+ A runtime/role pair with no fleet-configured tier value has no override —
190
+ resolve it to that runtime's own configured default, and pass it explicitly
191
+ (never leave it unset — see "Never let an unresolved pin fall through"
192
+ below).
119
193
 
120
194
  ## Pin every spawn explicitly — the floor depends on the ROLE, not the depth
121
195
 
122
- Every orchestrator MUST pass an explicit `model:` on EVERY subagent it spawns, and
123
- `effort` wherever the mechanism exposes it. An unspecified subagent SILENTLY
124
- INHERITS THE PARENT'S MODEL — so an Opus orchestrator that forgets the pin just
125
- spent Opus tokens on a grep.
196
+ Every orchestrator MUST pass an explicit `model:` on EVERY subagent it spawns,
197
+ resolved for its own runtime, and `effort` wherever the mechanism exposes it.
198
+ An unspecified subagent SILENTLY INHERITS THE PARENT'S MODEL — so an
199
+ orchestration-tier orchestrator that forgets the pin just spent its
200
+ (expensive) tier's tokens on a grep.
126
201
 
127
202
  **The floor is set by what the agent DOES, not by how deep it sits** — see the
128
203
  Agent tiers table above. This applies recursively: an implementer spawning its
129
204
  own helpers pins them by THEIR role, not by copying its own tier down.
130
205
 
131
206
  The check before every spawn: what is this agent's ROLE? Reviewer or implementer?
132
- sonnet-medium. Pure investigation or mechanical work? sonnet-low. Never leave it
207
+ `judgment` tier. Pure investigation or mechanical work? `mechanical` tier. Then
208
+ resolve that tier to your runtime's concrete model+effort. Never leave it
133
209
  unspecified.
134
210
 
211
+ ### Never let an unresolved pin fall through
212
+
213
+ **An unsupported or unrecognized model name must never block delegation, and
214
+ must never cause silent inheritance of the parent's model.** If your
215
+ runtime's preset has no `TierModels` entry for this tier, or a resolved name
216
+ is rejected by the runtime you're spawning under, do NOT skip the pin and do
217
+ NOT let the spawn go unpinned so it falls back to inheriting the caller's
218
+ model — fall back explicitly to the runtime's own configured default for the
219
+ matching tier and pass THAT, so every spawn is always pinned to some resolved
220
+ model+effort. An unset `model:` is a bug at every layer of this stack, not
221
+ just under Claude.
222
+
135
223
  ## Paste the constraint block into the child prompt — the pin is not enough
136
224
 
137
225
  **A model pin is an ARGUMENT and travels by itself. A behavioural constraint is
@@ -148,8 +236,11 @@ that stops at depth 1 is absent where the work happens.
148
236
  tool's own guidance suggests it. It trips a permission modal, and A FROZEN
149
237
  PANE EMITS NOTHING, so nobody can tell you are blocked. If you must background
150
238
  work, wait for the completion notification.
151
- - Every sub-agent YOU spawn gets an explicit `model:` — sonnet (low mechanical,
152
- medium judgment). HAIKU IS BANNED. Opus is never yours.
239
+ - Every sub-agent YOU spawn gets an explicit `model:`, resolved for your
240
+ runtime's tier — `mechanical` (rote/find-replace) or `judgment` (real
241
+ analysis). On Claude that's sonnet-low / sonnet-medium and HAIKU IS BANNED;
242
+ on another runtime, use that runtime's own resolved row. The
243
+ `orchestration` tier is never yours to spawn.
153
244
  - READ-ONLY git outside your own worktree. NEVER `checkout`/`reset`/`restore`/
154
245
  `stash`/`clean` in ANY directory — `stash` is one shared stack across all
155
246
  worktrees and the shared tree holds live agents' uncommitted state.
@@ -161,7 +252,8 @@ signal this condition produces.
161
252
 
162
253
  ### Cheap subagents → fan out, don't pile up
163
254
 
164
- Because sonnet-low subagents are cheap, prefer MANY small parallel subagents
255
+ Because `mechanical`-tier subagents are cheap (sonnet-low on Claude; the
256
+ mechanical-tier row for your runtime otherwise), prefer MANY small parallel subagents
165
257
  over one subagent handed a pile of tasks. When a research or investigation task
166
258
  has independent parts, partition it and dispatch the parts in parallel (use the
167
259
  `efficient-multi-agent-research` skill) — smaller scopes are cheaper, run
@@ -170,6 +262,12 @@ given ten tasks is the anti-pattern.
170
262
 
171
263
  ## ⚠️ The pin-verification command LIES — do not trust it
172
264
 
265
+ **This section's examples are Claude-specific** (`thrum tmux capture`'s footer
266
+ format, and the historical Sonnet/Opus incident it documents) because that is
267
+ where this defect was measured — but the underlying rule generalizes: verify
268
+ a pin by reading the runtime's own RESOLVED status output, never a stored
269
+ "configured" value, whichever runtime you're on.
270
+
173
271
  `thrum agent runtime-config get <agent>` reports the **configured** value, not the
174
272
  **resolved** one.
175
273
 
@@ -250,3 +348,35 @@ launch **by construction**.
250
348
  An implementer pinned to sonnet, with an implementer role-default of sonnet, comes up
251
349
  correct whether or not the pin landed — so "pin sonnet, confirm sonnet" passes whether
252
350
  or not the fix works.
351
+
352
+ ## Paste blocks for child prompts
353
+
354
+ Paste these verbatim into a child prompt when the work involves the named activity.
355
+
356
+ --- SUB-AGENT HYGIENE ---
357
+ - No kill -0, Monitor or until-loop polling.
358
+ - No pgrep -f.
359
+ - Kill only by a captured PID number.
360
+ - Use rm -r, never rm -rf; a variable path uses "${d:?}".
361
+ - No 2>/dev/null on destructive commands.
362
+ - Bounded timeouts on everything.
363
+ - Remove only the worktree you created in this task, by its recorded path, never with --force.
364
+ - Never demonstrate an unguarded destructive idiom, even on a literal path.
365
+ --- END SUB-AGENT HYGIENE ---
366
+
367
+ --- TESTS ---
368
+ - To prove a selector resolves, use `go test <pkg> -list '<selector>'` plus a `-list '^TestNoSuchThingAtAll$'` negative control that must list zero tests. Never `-run '<sel>' -list '.*'`.
369
+ - `bd list -l` is --label; use `-n` for a limit.
370
+ - A timeout with 0 FAIL is neither red nor green: classify it as a bound failure, read the panic's "running tests:" line, and re-run wider.
371
+ --- END TESTS ---
372
+
373
+ --- WORKTREE TEARDOWN & SALVAGE ---
374
+ - Before any teardown, enumerate with both flags: `git -C <wt> status --porcelain --untracked-files=all --ignored -- .thrum`.
375
+ - Salvage anything found to a durable path (not /tmp), one subdirectory per worktree, filenames path-flattened.
376
+ - Never glob `.thrum/context/*.md`; salvage the exact agent-name file only, and assert no `project_state.md` landed in any salvage output.
377
+ - Verify salvage by name set first, then `cmp` each file, with a negative control proving `cmp` detects a difference.
378
+ - Kill the tmux session first (`thrum tmux kill <session>`), verify it is gone, then plain `git worktree remove`, never `--force`.
379
+ - Afterwards verify by effect: gone from `git worktree list` and from disk, and every remaining live pane's cwd still resolves (`tmux list-panes -a -F '#{pane_current_path}'`, then `git rev-parse --show-toplevel` per pane).
380
+ - Build the in-use protection set from live pane cwds, not from a name or registry list.
381
+ - Report the removal count and the registry delta separately.
382
+ --- END WORKTREE TEARDOWN & SALVAGE ---
@@ -94,8 +94,7 @@ tool that can prove it, not by trusting the sentence that claims it.
94
94
 
95
95
  ## Project-specific rules (already loaded)
96
96
 
97
- Read the shared partial at the absolute path:
98
- `claude-plugin/commands/_project-rules-protocol.md`
97
+ Load the /thrum:project-rules-protocol skill and follow it.
99
98
 
100
99
  If you accumulate a new rule mid-session (the user corrects you), capture it
101
100
  via the `implementer-maintaining-memory` skill (or `coordinator-maintaining-
@@ -155,7 +155,7 @@ For each role:
155
155
  - If beads detected: include `bd` commands in Task Tracking section
156
156
  - If MCP servers detected: add to Efficiency section
157
157
  - If specific skills detected: reference them
158
- - If worktree restrictions: adjust Scope Boundaries
158
+ - If worktree restrictions: adjust the Scope section
159
159
 
160
160
  3. Write to `.thrum/role_templates/{role}.md`. Keep per-agent template tokens
161
161
  (`{{.AgentName}}`, `{{.Module}}`, `{{.WorktreePath}}`,
@@ -226,4 +226,4 @@ rendered files from saved answers without asking any questions.
226
226
  | Thrum MCP server | Add MCP tool references, CLI fallback for sub-agents |
227
227
  | Claude plugin skills | List installed skills with usage guidance |
228
228
  | Context7 MCP | Add library docs guidance to Efficiency section |
229
- | Multiple worktrees | Add worktree scope rules to Scope Boundaries |
229
+ | Multiple worktrees | Add worktree scope rules to the Scope section |
@@ -62,7 +62,7 @@ Workflow `agent()` opts, agent-definition frontmatter, `thrum tmux launch
62
62
  ```python
63
63
  Agent(subagent_type="general-purpose",
64
64
  name="<prefix>_<slug>",
65
- model="sonnet",
65
+ model="<per choosing-subagent-models>",
66
66
  description="<3-5 words>",
67
67
  prompt="""<task>
68
68
 
@@ -92,14 +92,14 @@ to fire-and-forget monitors, not to a named agent you re-message.
92
92
 
93
93
  | Subagent role | Name prefix | Model / effort (effort only where exposed) | Result file |
94
94
  |---|---|---|---|
95
- | Investigation, grep, doc summary, mechanical | `<topic>` (e.g. `vmdocs`) | `sonnet` / low | `<scratch>/<name>.md` |
96
- | Root-cause | `<bead>_rc` | `sonnet` / low | `<scratch>/<bead>-rc.md` |
97
- | Verifier, reviewer, design-verify | `<bead>_verify` | `sonnet` / medium | `<scratch>/<bead>-verify.md` |
98
- | Implementer | `impl_<slug>` | `sonnet` / medium | `<scratch>/<slug>-impl.md` |
99
- | VM driver | `vmdriver_<slug>` | `sonnet` / medium | `<scratch>/<slug>-vm.md` |
100
- | Prose or deep review | any | `opus` — **only when the operator asks** | as above |
95
+ | Investigation, grep, doc summary, mechanical | `<topic>` (e.g. `vmdocs`) | per `choosing-subagent-models` | `<scratch>/<name>.md` |
96
+ | Root-cause | `<bead>_rc` | per `choosing-subagent-models` | `<scratch>/<bead>-rc.md` |
97
+ | Verifier, reviewer, design-verify | `<bead>_verify` | per `choosing-subagent-models` | `<scratch>/<bead>-verify.md` |
98
+ | Implementer | `impl_<slug>` | per `choosing-subagent-models` | `<scratch>/<slug>-impl.md` |
99
+ | VM driver | `vmdriver_<slug>` | per `choosing-subagent-models` | `<scratch>/<slug>-vm.md` |
100
+ | Prose or deep review | any | per `choosing-subagent-models` — **only when the operator asks** | as above |
101
101
 
102
- Haiku is banned. Opus is never yours to grant onward.
102
+ The model ban list lives in `choosing-subagent-models`. A costly tier is never yours to grant onward.
103
103
 
104
104
  ### CONSTRAINTS block — paste verbatim into every dispatch
105
105
 
@@ -111,8 +111,8 @@ Haiku is banned. Opus is never yours to grant onward.
111
111
  tool's own guidance suggests it. It trips a permission modal, and A FROZEN
112
112
  PANE EMITS NOTHING, so nobody can tell you are blocked. If you must background
113
113
  work, wait for the completion notification.
114
- - Every sub-agent YOU spawn gets an explicit `model:` — sonnet (low mechanical,
115
- medium judgment). HAIKU IS BANNED. Opus is never yours.
114
+ - Every sub-agent YOU spawn gets an explicit `model:` chosen per `choosing-subagent-models`
115
+ (read `runtime.role_models`). The model ban list lives there. A costly tier is never yours.
116
116
  - READ-ONLY git outside your own worktree. NEVER `checkout`/`reset`/`restore`/
117
117
  `stash`/`clean` in ANY directory — `stash` is one shared stack across all
118
118
  worktrees and the shared tree holds live agents' uncommitted state.
@@ -186,7 +186,7 @@ Restart on a number read from the pane footer, never on a felt sense.
186
186
  - The parent reading code or docs "to just check quickly" — message the subagent that already read them and ask for the one field.
187
187
  - One subagent handed ten tasks — partition it and dispatch the parts in parallel.
188
188
  - A spawn with no `name:` — it cannot be re-messaged. Name every spawn.
189
- - A spawn with no `model:` — it silently inherits Opus. Pin `model:` on every spawn, and `effort` wherever the mechanism takes it.
189
+ - A spawn with no `model:` — it silently inherits your own model. Pin `model:` on every spawn, and `effort` wherever the mechanism takes it.
190
190
  - Holding a design-gating answer behind the rest of the pass while an implementer builds on the old premise — that one goes immediately; the rest ships as one consolidated message.
191
191
  - Acting on the resume plan alone and skipping the middle of the prime — the falsified premise sits in the part you skipped.
192
192
  - Trusting an older "not started" message over a newer "already running" one — verify, do not recall; that cuts both directions.
@@ -21,7 +21,7 @@ findings, and its troubleshooting state across rounds.
21
21
 
22
22
  Do this:
23
23
 
24
- 1. `Agent(name: "vmdriver_<slug>", model: "sonnet", prompt: <round-1 GO>)`.
24
+ 1. `Agent(name: "vmdriver_<slug>", model: <per choosing-subagent-models>, prompt: <round-1 GO>)`.
25
25
  2. Wait for its report.
26
26
  3. `SendMessage(to: "vmdriver_<slug>", message: <round-2 GO>)`.
27
27
 
@@ -10,7 +10,7 @@ sanctions for reaching it.
10
10
 
11
11
  You want a multi-hour load or soak run and a verdict, not a log.
12
12
 
13
- 1. Spawn `vmdriver_<slug>` with `model: "sonnet"`. The GO names the run, the
13
+ 1. Spawn `vmdriver_<slug>` with `model: <per choosing-subagent-models>`. The GO names the run, the
14
14
  revision under test, and the exact metrics to report.
15
15
  2. The driver opens a persistent session with `<your-ssh-wrapper> <remote-host>`,
16
16
  starts the run detached, and writes the exit code to its own file.
@@ -19,6 +19,30 @@ Apply the gate and containment checks below and reach your own
19
19
  conclusion. Destructive steps still follow the standing reap preconditions and
20
20
  pacing rules; nothing here shortcuts them.
21
21
 
22
+ ## Standing reap preconditions — ALL must hold
23
+
24
+ Reaping an agent (removing its worktree) is safe only when every one of these is
25
+ true. It is a gate, not a checklist to rationalize past:
26
+
27
+ 1. **Idle > 48h** — no activity in its transcript for more than two days (rank by
28
+ message CONTENT, not mtime; your own broadcasts reset mtime).
29
+ 2. **No messages exchanged in the last 24h** — nothing sent to it or from it.
30
+ 3. **Task complete AND nobody is waiting on it** — it finished and its
31
+ dispatcher/manager moved on, so a reply it waits for will never come. (A pushed
32
+ branch held on a still-queued merge is the one nuance — see the
33
+ held-pending-merge rule.)
34
+ 4. **Salvage done first** — its only-copy state is copied to a durable location and
35
+ verified (see Containment and the reap steps).
36
+
37
+ **When a needed decision or merge is delayed, ESCALATE — never silently wait.** If an
38
+ agent is parked past the 24h window on something its manager/owner has not acted on,
39
+ raise it explicitly to whoever owns that decision, and re-raise on every subsequent
40
+ run. If the human owner is unresponsive, escalate through your designated escalation
41
+ contact (the human's proxy) rather than leaving the agent parked. A silent park is
42
+ the failure this whole procedure exists to prevent: each run must drive a parked
43
+ agent toward a terminal state — decision made / merge lands (reap-able) or deemed
44
+ orphaned (reap).
45
+
22
46
  ## The instruments, in order of trust
23
47
 
24
48
  | Question | Instrument |
@@ -81,10 +105,42 @@ sentence IS the terminal statement; a working agent's merely contains one.
81
105
  **Name what it is waiting for, then prove that thing is dead or landed.**
82
106
 
83
107
  *"Held pending the coordinator merge"* is finished only if the merge landed or was
84
- abandoned. If the merge is still queued, the agent is **correctly** waiting and
85
- reaping it destroys live context that nobody else holds.
86
-
87
- **If you cannot name the blocker, it is not a candidate.**
108
+ abandoned. If the merge is still queued, whether the agent is *correctly* waiting
109
+ depends on its branch and its idle time — see the held-pending-merge rule below.
110
+
111
+ **If you cannot name the blocker, it is not a candidate.** (This governs the
112
+ *no-transcript* case — absence of evidence — not a named-but-stale merge wait.)
113
+
114
+ ## 🔴 The held-pending-merge case — a PUSHED branch changes the gate
115
+
116
+ An agent parked "pending the merge" is judged by ONE thing first — **is its branch
117
+ pushed?** — because a merge wait only makes sense if the merge king can reach the
118
+ branch.
119
+
120
+ - **Branch NOT pushed — broken at ANY idle age.** The merge king cannot access an
121
+ unpushed branch, so the wait can never resolve, and the agent's commits are also
122
+ the only copy (unsafe to reap). This is not a legitimate wait — it is a stuck one.
123
+ → Get the branch PUSHED (nudge the agent / its orchestrator to push it, or escalate
124
+ that it needs pushing). Never reap an unpushed held-pending-merge agent — pushing
125
+ first is both what unblocks the merge and what makes any later reap safe.
126
+ - **Branch pushed, idle < 24h.** Legitimately waiting its turn in the merge queue.
127
+ Leave it (the pushed branch means the merge king can reach it and nothing is lost).
128
+ - **Branch pushed, idle ≥ 24h.** The wait is no longer legitimate — a pushed branch
129
+ is not the only copy of anything, so any agent could carry the merge. Resolve it to
130
+ one of two clear states:
131
+ - **Merge HAPPENED** (branch is an ancestor of trunk, or was abandoned/superseded)
132
+ → the agent is **ORPHANED**, waiting for a response that will never come → **reap**
133
+ (salvage-first, and still subject to the standing reap preconditions).
134
+ - **Merge still PENDING** (branch not on trunk, not abandoned) → the merge king
135
+ forgot it or the queue is stuck → **ESCALATE** to the merge king (name the branch
136
+ tip + how long it has waited), and **re-escalate on every subsequent skill run**
137
+ until it resolves. Never leave it silently parked.
138
+
139
+ **The escalation is the load-bearing half.** Because each skill run re-checks and
140
+ re-escalates a still-pending merge, the condition is self-correcting: it drives toward
141
+ one of two terminal states — the merge completes (agent then reap-able) or the agent
142
+ is deemed orphaned (reap) — instead of a pushed-branch agent parked forever on a merge
143
+ nobody is tracking. A silent park is exactly the failure this rule prevents.
88
144
 
89
145
  ## Containment, before anything is stood down
90
146
 
@@ -126,8 +182,8 @@ an empty/never-read premise as a match"*). `--force` does NOT bypass it; the gua
126
182
  correct. So the reap that actually frees load is worktree removal — but salvage BEFORE you remove,
127
183
  then remove PLAIN (no `--force`):
128
184
 
129
- 1. Enumerate untracked+ignored `.thrum` content — BOTH flags, one flag alone misses a class
130
- (thrum-j14q3): `git status --untracked-files=all --ignored -- .thrum`
185
+ 1. Enumerate untracked+ignored `.thrum` content — BOTH flags, one flag alone misses a class:
186
+ `git status --untracked-files=all --ignored -- .thrum`
131
187
  2. Salvage BOTH kinds to their canonical redirect paths, and `cmp`-verify each copy is
132
188
  byte-identical to its source:
133
189
  - `?? .thrum/agents/<agent>/sessions/*-restart.md` — the restart snapshot.
@@ -218,6 +274,42 @@ RSS-MB.
218
274
  you decide**. It is read-only and dry-run — it prints a kill-list, it never
219
275
  kills anything.
220
276
 
277
+ ## 🔴 Footguns — never do these (each measured, each cost real time or state)
278
+
279
+ - **Never glob/`cp` `.thrum/context/*.md` when salvaging** — the glob matches the
280
+ shared `project_state.md` and overwrites the canonical copy with a stale worktree
281
+ copy. Salvage the agent-specific `<agent>.md` by exact name only.
282
+ - **A worktree's `.thrum/` holds a redirect file to the main repo AND a physical
283
+ stale local copy of shared files** (e.g. `project_state.md`) — the physical
284
+ worktree copy is NOT canonical; never treat it as the source of truth or copy it
285
+ upward.
286
+ - **Never use shell-specific builtins in a reap loop without checking the shell** —
287
+ `mapfile`/`readarray` are bash-only and silently fail in zsh (`command not
288
+ found`), so the salvage you thought ran did not. Use portable `while read` and
289
+ verify each salvaged file actually landed.
290
+ - **`rm -rf` raises a confirmation modal that blocks the PARENT pane invisibly** —
291
+ use `rm -r` for scratch cleanup (identical deletion, no modal). Never `rm -rf`.
292
+ - **`git worktree remove` (plain) silently deletes gitignored-only content (rc=0)**
293
+ and refuses (rc=128) only on untracked/modified files — salvage is the ONLY
294
+ protection for gitignored only-copy state.
295
+ - **`git worktree remove` refuses while a just-salvaged untracked snapshot still
296
+ sits in the worktree** — remove that salvaged copy from the worktree first, then
297
+ plain-remove.
298
+ - **Never `checkout`/`reset`/`restore`/`stash`/`clean` in a shared tree, even to
299
+ undo** — to restore a file to its committed version, write it with a plain
300
+ redirect from `git show <ref>:<path>`, not a checkout.
301
+ - **Test the reap on ONE agent first and verify the EFFECT** (gone from the worktree
302
+ list AND disk), not just the exit code.
303
+ - **Rank candidates by last-message CONTENT, not elapsed time** — your own
304
+ broadcasts reset every recipient's idle clock.
305
+ - **`--force` on agent-delete does NOT bypass the CAS guard** on a stale agent — the
306
+ reap that frees load is worktree removal, not the delete.
307
+ - **Reap order is `thrum tmux kill <session>` FIRST, THEN `git worktree remove`** —
308
+ removing the worktree alone leaves the agent's tmux session alive with a
309
+ now-deleted cwd, which the fleet flags as recurring "cwd drift" and whose runtime
310
+ process keeps consuming RAM/CPU. Kill the session, verify it's gone, then remove
311
+ the worktree.
312
+
221
313
  ## Why this fails dangerously if you skip the gate
222
314
 
223
315
  The failure direction is **false-GONE**: concluding a live agent is finished. It
@@ -159,8 +159,7 @@ asserted after the fact).
159
159
 
160
160
  ## Project-specific rules (already loaded)
161
161
 
162
- Read the shared partial at the absolute path:
163
- `claude-plugin/commands/_project-rules-protocol.md`
162
+ Load the /thrum:project-rules-protocol skill and follow it.
164
163
 
165
164
  If you accumulate a new rule mid-session about branch-splitting, capture it
166
165
  via the `coordinator-maintaining-memory` skill — it references the