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
@@ -26,40 +26,51 @@ What's forbidden is a script that bypasses this skill and fires
26
26
  `thrum tmux restart --force` unconditionally (that violates
27
27
  `feedback_restart_discipline` — burn the runway, don't restart on schedule).
28
28
 
29
- ## Coordinator self-restart — ALWAYS `/thrum:restart-extended`
29
+ ## Coordinator self-restart — ALWAYS the EXTENDED form, compact-extended FIRST
30
30
 
31
31
  This skill's tier ladder (Steps 3–5) governs how the coordinator restarts
32
32
  **other** agents. When the **coordinator restarts ITSELF**, a different rule
33
- applies and it is absolute:
33
+ applies and it is absolute — but D5 (owner-ruled)
34
+ REVERSES which command that is:
34
35
 
35
- > **The coordinator ALWAYS self-restarts via `/thrum:restart-extended`, NEVER
36
- > `/thrum:restart`.**
36
+ > **The coordinator ALWAYS uses the EXTENDED snapshot grade for itself — never
37
+ > the standard/compact form. Which command carries that grade is
38
+ > runtime-directed: `/thrum:compact-extended` on any runtime with a verified
39
+ > compact-equivalent skill (D6, the default), `/thrum:restart-extended` ONLY
40
+ > as the fallback on a runtime without one (today: muse, copilot).**
41
+
42
+ This is a REVERSAL of the prior absolute rule ("ALWAYS restart-extended, NEVER
43
+ compact") — that rule is retired, not merely relaxed. Do not restore it.
37
44
 
38
45
  Rationale: the coordinator is the nerve center. Its handoff must carry the full
39
46
  16-section snapshot (wire contracts, capability matrix, cycle history, open
40
47
  L-questions, anticipated Q&A, design rationale) so the next session resumes
41
- steady-state coordination without re-deriving fleet state. The standard
42
- `/thrum:restart` compact format drops that load-bearing context and strands the
43
- next session. This holds regardless of which tier the coordinator's own context
44
- sits in — there is no ctx-band at which the coordinator downgrades to the
45
- compact restart.
48
+ steady-state coordination without re-deriving fleet state — that requirement
49
+ is UNCHANGED and is what "EXTENDED" governs; only the compact-vs-restart choice
50
+ changed. Compacting (rather than restarting) additionally keeps the SAME
51
+ process/session alive — sub-agents, background loops, and cron schedules the
52
+ coordinator owns survive the compaction, where a restart would drop them.
53
+ There is no ctx-band at which the coordinator downgrades to the standard/
54
+ compact-grade snapshot — the tier ladder below governs OTHER agents, not this.
46
55
 
47
- Practical trigger points for coordinator self-restart:
56
+ Practical trigger points for coordinator self-restart/compact:
48
57
 
49
58
  - A warn-tier context nudge fires on the coordinator's own pane (e.g. 70%+).
50
59
  - The coordinator hits a clean checkpoint and elects a fresh session.
51
60
  - Rate-limit / stuck-state recovery on the coordinator itself.
52
61
 
53
- In every one of these, run `/thrum:restart-extended`. (Captured as role-rule
54
- `coord-always-restart-extended` /
55
- `Coordinator ALWAYS uses /thrum:restart-extended`; this skill is the
56
- always-loaded home so the rule survives even when memory isn't consulted.)
62
+ In every one of these: run `/thrum:compact-extended` if the coordinator's
63
+ runtime has a compact equivalent (the default); `/thrum:restart-extended` only
64
+ if it does not. (The role-rule `coord-always-restart-extended` — `Coordinator
65
+ ALWAYS uses /thrum:restart-extended` — is RETIRED as of D5; see
66
+ `thrum memory` for its retirement record. This skill is the always-loaded home
67
+ so the CURRENT rule survives even when memory isn't consulted.)
57
68
 
58
69
  Note the distinction from Steps 3–5 below: those steps drive `/thrum:restart`
59
70
  (Step 4) and `/thrum:restart-extended` (Step 5) into
60
71
  **implementer/brainstormer** panes per their ctx tier — that tiering is correct
61
72
  for worker agents. The carve-out here is ONLY about the coordinator's own
62
- restart, which is unconditionally the extended form.
73
+ restart/compact, which is unconditionally the extended grade, compact-first.
63
74
 
64
75
  ## How the scheduled sweep works (v0.10.6+ — thrum monitor)
65
76
 
@@ -274,10 +285,7 @@ brick.
274
285
 
275
286
  ## Subagent model selection
276
287
 
277
- > **Model tiers:** pass an explicit `model:` on every dispatch — `sonnet`
278
- > (low effort) mechanical, `sonnet` (medium effort) judgment, Opus only on
279
- > operator-ask or a skill step that names it. See the
280
- > `choosing-subagent-models` skill for the full policy.
288
+ > **Model tiers:** pass an explicit `model:` on every dispatch; choose model and effort per the `choosing-subagent-models` skill (read `runtime.role_models` at the moment of use). Never let a sub-agent inherit your own model.
281
289
 
282
290
  ## Step 1 — Run the sweep
283
291
 
@@ -464,6 +472,8 @@ by typing the restart command directly into their input field:
464
472
  thrum tmux send <tmux_session_name> '/thrum:restart'
465
473
  ```
466
474
 
475
+ If it exits 3 (Enter WITHHELD, text already typed) or 4 (verdict unknown), do NOT retype it: `thrum tmux capture` the pane and submit with `thrum tmux send <tmux_session_name> --keys Enter` only if no dialog is showing.
476
+
467
477
  (Find the tmux session name in sweep output — it's typically the worktree
468
478
  basename, e.g. `myepic-impl`, NOT the agent_id.)
469
479
 
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: coordinator-deploying-a-node
3
+ description: "Use when deploying a build to a single node, migrating or not — deploying a build, schema-migrating deploy, pro-bundle install plus service restart on a node, roll out a build to a node, ship to a node, single-node canary. Loads the deploy runbook — verifying the artifact actually CONTAINS the fix, install-before-restart ordering, verify-by-effect, and preventing store corruption on migration."
4
+ ---
5
+
6
+ # Coordinator: Deploying a Build to a Single Node — migrating or not
7
+
8
+ > This runbook covers EVERY deploy to a single node, migrating or not. Most sections apply to every deploy; only migration-weight and store-corruption specifics are bump-only.
9
+
10
+ ## 0. Pull-current first (ff-only)
11
+
12
+ The absolute first action before anything else: fetch the control-plane repository and fast-forward to the orchestrator's pin.
13
+
14
+ - Read the project's deployment adapter inside `.thrum/config.json` (`fleet.deployment`; reference at the deployment-adapter reference) to obtain `preflight.pull_command` and `preflight.pin_command`.
15
+ - Run `preflight.pull_command` (must be ff-only; if not fast-forwardable, STOP and surface — never blind-merge in the shared tree).
16
+ - Verify the delivered artifact actually CONTAINS the fix at the pinned SHA (adapter `artifact.commit_file` sidecar).
17
+
18
+ This ensures the node's coordinator reasons from a checkout that is actually current before evaluating backup, install, or migration.
19
+
20
+ > Example — Thrum project: pull via `git fetch origin && git merge --ff-only origin/<branch>` before any backup or install.
21
+
22
+ ## 1. Who executes — resolve the node's local coordinator (via adapter identity)
23
+
24
+ The node's own coordinator drives the deploy locally on its own host. Never drive a node's build/install/restart from another host.
25
+
26
+ - Resolve WHO via `topology.identity_resolution` (adapter `fleet.deployment.thrum.topology.identity_resolution` or `fleet.deployment.products.<id>.topology`) — a `daemon_id` join plus hostname and absence of `.thrum/redirect`, never by agent name or worktree name.
27
+ - When connected-repo daemons share a host, respect the adapter-defined restart order within that host.
28
+
29
+ If the target node has no working coordinator, state why explicitly before using any fallback.
30
+
31
+ ## 2. Back up before touching anything (via adapter backup command + sizing formula)
32
+
33
+ - Run the project's backup command (`fleet.deployment.thrum.backup.command` or `fleet.deployment.products.<id>.backup.command`) and verify per `backup.verify`.
34
+ - Size BEFORE you run it on a bloated node: apply the adapter's `backup.sizing_formula` (`free_at_completion = free_now - zip(stale current/) + size(stale current/) - size(live lane)`) — the stale `current/` is removed before the fresh export, so peak is not double-count. Retention runs last and does not bound the peak.
35
+ - On failure, roll back via `backup.restore_command`; never delete the store.
36
+
37
+ > Example — Thrum project: backup via `thrum backup`, sized per the formula above, verified with `sqlite3 ?mode=ro&immutable=1` read.
38
+
39
+ ## 3. Storage access — through the engine or control-plane CLI, never file-bypass
40
+
41
+ Access the state store only through the engine or the control-plane CLI in read-only mode. Never bypass the storage engine's file ownership.
42
+
43
+ - Via: `storage_access.via` (e.g., CLI or `?mode=ro`).
44
+ - Forbidden: `storage_access.forbidden` (e.g., hand-copy of live `-wal`/`-shm`, concurrent `.backup` on live store).
45
+ - A bare read-write open can fire a checkpoint that truncates the write log out from under live readers → sustained corruption. Always use `?mode=ro` where applicable.
46
+
47
+ If the project has no WAL/SHM, this section is N/A — skip and note.
48
+
49
+ ## 4. Never wrap service start/restart in a blind timeout
50
+
51
+ Run the project's service restart command (`fleet.deployment.thrum.service.restart_command` or product equivalent) without a blind timeout wrapper. A timeout that kills a migrating restart mid-migration manufactures a half-migrated store.
52
+
53
+ - Adapter flag `service.never_timeout` is true.
54
+ - Signal-window rules are adapter data: `migration.signal_rules` (`SIGQUIT` fatal-always, `SIGUSR1` fatal-before-socket). Respect them — do not send fatal signals in the forbidden window.
55
+
56
+ > Example — Thrum project: restart via `thrum daemon restart`, never wrapped in `timeout`; mac path via `scripts/mac-daemon-restart-via-cron.sh`.
57
+
58
+ ## 5. Install from the delivered artifact (never rebuild on the node)
59
+
60
+ Install from the identical bundle the orchestrator built, delivered to `artifact.distribution.drop_path`.
61
+
62
+ - Verify BEFORE unpack that the delivered bundle's version/checksum/commit sidecar equals the orchestrator's pin (adapter `artifact.checksum`, `artifact.version_file`, `artifact.commit_file`).
63
+ - Run `install.command` (from adapter). The node does not compile, sign, or rebuild — it installs.
64
+ - Collect BEFORE readings (current version, state counters, checkpoint counts, health probes) before the install.
65
+
66
+ > Example — Thrum project: install from the adapter's `artifact.distribution.drop_path` via the adapter's `install.command`.
67
+
68
+ ## 6. Measure from the running process, never the checkout
69
+
70
+ Read version/state from the running service, not from the filesystem checkout.
71
+
72
+ - Verify via `install.verify_by_effect` probes: version equals pin, NEW PID, service status reports pin, sidecar equals pin.
73
+ - Do not trust installer exit 0 alone.
74
+
75
+ ## 7. Migrate via service restart — verify by effect
76
+
77
+ Migration is performed by restarting the service after install; the service's own boot migration does the schema/data move.
78
+
79
+ - Calibrate weight via `migration.weight_calibration` (heavy bulk-export vs light add-column) — do not assume a fixed duration.
80
+ - Known signatures that require a cold-restart recovery: `migration.sigbus_signatures` (e.g., WAL-index recover signatures) and `migration.on_sigbus`.
81
+ - Observe that the restarted service reports the new version/state and that health probes have converged (adapter `health.probes`, `health.convergence_wait`).
82
+
83
+ ## 8. Verify post-migration (liveness, health probes, checkpoint counts, agent liveness)
84
+
85
+ Run adapter `health.probes` and compare BEFORE/AFTER:
86
+
87
+ - Service alive and reporting pin.
88
+ - State counters converged per `health.convergence_wait` (mechanism-derived, e.g., `3m`).
89
+ - Crash log empty, expected agents live.
90
+
91
+ For tandem daemons that share a host or depend on each other, verify the coordinated set per adapter.
92
+
93
+ ## 8a. Re-render configuration/templates if the build changes them
94
+
95
+ If the build carries template or role changes, re-render between install and restart:
96
+
97
+ - Commands: `templates.refresh_command` and `templates.deploy_command`.
98
+ - Order: `templates.order` (`refresh→deploy` between `install.sh` and daemon restart).
99
+ - Verify by effect (render output, then service restart).
100
+
101
+ > Example — Thrum project: `thrum roles refresh` then `thrum roles deploy` between install and restart.
102
+
103
+ ## 8b. Plugin/skill refresh if the deploy carries skill changes
104
+
105
+ If the bundle carries skill/plugin changes, refresh the plugin cache:
106
+
107
+ - Refresh driver: `plugin.refresh` (version bump required — cache keyed by version).
108
+ - Manifests: `plugin.manifests` (all skill-carrying manifests bumped in the same commit as the new skills).
109
+
110
+ Do not hand-edit generated marketplace manifests.
111
+
112
+ ## 8c. Reconcile registry/phase after restart
113
+
114
+ Re-verify the daemon registry and agent phases after restart (adapter `health.probes` includes phase reconciliation). Confirm the pinned version is durable across a clean cold-boot probe where applicable.
115
+
116
+ ## Red flags — STOP
117
+
118
+ - Pull not ff-only.
119
+ - Backup skipped or undersized.
120
+ - Storage accessed via forbidden path (`storage_access.forbidden`).
121
+ - Restart wrapped in a blind timeout or killed with `SIGQUIT`/`SIGUSR1` in a fatal window (`migration.signal_rules`).
122
+ - Install rebuilt locally instead of from the delivered artifact.
123
+ - Post-migration health not verified by observed effect.
124
+ - Template re-render skipped when the build changed templates (`templates.order` violated).
@@ -65,10 +65,7 @@ optimization.
65
65
 
66
66
  ## Subagent model selection
67
67
 
68
- > **Model tiers:** pass an explicit `model:` on every dispatch — `sonnet`
69
- > (low effort) mechanical, `sonnet` (medium effort) judgment, Opus only on
70
- > operator-ask or a skill step that names it. See the
71
- > `choosing-subagent-models` skill for the full policy.
68
+ > **Model tiers:** pass an explicit `model:` on every dispatch; choose model and effort per the `choosing-subagent-models` skill (read `runtime.role_models` at the moment of use). Never let a sub-agent inherit your own model.
72
69
 
73
70
  ## Check the target's queue before you dispatch (R3)
74
71
 
@@ -162,13 +159,30 @@ re-dispatch overhead.
162
159
  3. Acceptance criteria as bullets
163
160
  4. The worktree path the work happens in
164
161
  5. An explicit reminder to pass `model:` on any sub-agents the implementer
165
- spawns (sonnet-low for mechanical, sonnet-medium for judgment)
162
+ spawns (model and effort per `choosing-subagent-models`)
166
163
  6. Spec/plan paths to read before starting
167
164
  7. **Adjacent candidate beads** from the adjacency pass above, labeled as
168
165
  CANDIDATES with their validity explicitly unverified — plus the instruction to
169
166
  check them against the merged-forward tip and either fold them in or return
170
167
  them as completed
171
168
 
169
+ ## Anti-pattern-removal epics must ship a ratchet lens
170
+
171
+ **Why:** during a prior owner-bypass remediation, judgment
172
+ review alone let 11 new instances of the exact anti-pattern being removed
173
+ land through the merge gate mid-sprint, because no mechanical check enforced
174
+ a monotonic budget across diffs.
175
+
176
+ **How to apply:** When dispatching an epic whose purpose is removing an
177
+ existing anti-pattern (not just fixing one instance of it), the acceptance
178
+ criteria MUST include a mechanical ratchet lens (see
179
+ `coordinator-hotpath-merge-gate` § "Invariant-ratchet lenses") wired into
180
+ `.thrum/hotpath-gate.json` as `always_run` before the epic is considered
181
+ closeable — not as a follow-up. A judgment-only acceptance ("reviewer
182
+ confirms the count went down") is insufficient; the count must be enforced
183
+ by a standing mechanical budget the gate itself checks on every subsequent
184
+ merge.
185
+
172
186
  ## Execution invariants — carry these in every implementation dispatch
173
187
 
174
188
  **Why:** A plan is a snapshot; trunk moves and reality drifts from it. Sprints
@@ -208,17 +222,16 @@ with a different name — do not rename in place.
208
222
 
209
223
  ## Propagate model-selection discipline downward
210
224
 
211
- **Why:** Sub-agents inherit the parent model by default. A coordinator on Opus
212
- that spawns an unspecified sub-agent gets Opus-cost work for tasks that need
213
- sonnet-low. The same trap repeats inside an implementer's worktree: if the
225
+ **Why:** Sub-agents inherit the parent model by default. A coordinator whose own tier is
226
+ costly that spawns an unspecified sub-agent gets costly work for tasks that need
227
+ a cheap tier. The same trap repeats inside an implementer's worktree: if the
214
228
  implementer doesn't propagate the discipline, their own sub-agents silently
215
229
  inherit too. Cost compounds across a session.
216
230
 
217
231
  **How to apply:** Every dispatch prompt should include the model-selection rule
218
232
  explicitly: "When you spawn your own sub-agents, pass explicit `model:` —
219
- `sonnet` (low effort) for mechanical work (lint, tests, find/replace), `sonnet`
220
- (medium effort) for judgment work (review, complex implementation), `opus`
221
- only when justified. Default to sonnet over opus." Audit the dispatch prompt before sending.
233
+ choose model and effort per the `choosing-subagent-models` skill (read
234
+ `runtime.role_models` at the moment of use); never inherit your own model." Audit the dispatch prompt before sending.
222
235
 
223
236
  ## The impl-prompt review stamp satisfies pre-dispatch review
224
237
 
@@ -294,14 +307,13 @@ EOF
294
307
  ### Step 3: Your role during execution
295
308
 
296
309
  - You receive the orchestrator's merge report when all epics complete.
297
- - Run your merge-approval gate (see Merge Approval Gate in your preamble).
310
+ - Run your merge-approval gate (see the merge approval rules in your preamble).
298
311
  - Monitor the orchestrator's status updates; escalate to the operator only for
299
312
  genuine judgment calls (architectural pivot, scope change, budget concern).
300
313
 
301
314
  ## Project-specific rules (already loaded)
302
315
 
303
- Read the shared partial at the absolute path:
304
- `claude-plugin/commands/_project-rules-protocol.md`
316
+ Load the /thrum:project-rules-protocol skill and follow it.
305
317
 
306
318
  If you accumulate a new rule mid-session (the user corrects you), capture it via
307
319
  the `coordinator-maintaining-memory` skill — it references the
@@ -117,23 +117,37 @@ rediscovering these the hard way:
117
117
  carrying dupes instead of the real content.
118
118
  6. Run full-package `-race`, not targeted `-run` — a targeted race run misses
119
119
  cross-test races.
120
- 7. Build+test the MERGED-tree result as a SEPARATE condition — neither gate
120
+ 7. **`internal/daemon/rpc` must NEVER be run monolithically at gate time, in
121
+ either lane** — a bare package-level `go test [-race] ./internal/daemon/rpc`
122
+ starves and hits the configured `-timeout` wall in both the race and
123
+ non-race lane. The gate's OUTPUT must show the sharded runner actually
124
+ executed for RPC (`race-shard` / `package-shard --mode norace`, or
125
+ `scripts/test-run.sh race|norace ./internal/daemon/rpc`, or `make gate`
126
+ which shards both lanes automatically) — not just that some RPC test ran.
127
+ A bound-timeout with ZERO test failures is a FALSE RED, not a finding:
128
+ distinguish it from a genuine hang/deadlock via
129
+ `go run ./cmd/testgate classify-timeout --log <file> --shard-config <file>
130
+ --shard <name>` (fails closed — only BOUND-TIMEOUT exits 0; HANG and
131
+ UNCLASSIFIED both exit nonzero) before reporting it as a regression.
132
+ If a gate's own command line invokes the bare package path for RPC, that is a gate defect, not a passing lane.
133
+ A HANG or UNCLASSIFIED verdict from `classify-timeout` requires human review.
134
+ 8. Build+test the MERGED-tree result as a SEPARATE condition — neither gate
121
135
  currently runs a build of the actual post-merge tree; a clean pre-merge
122
136
  build/test does not prove the merged result compiles or passes.
123
- 8. Use `rm -r`, NEVER `rm -rf`; use plain `git worktree remove` to drop a worktree, never
124
- `--force` as the default (see item 12 below). A broad `ask` rule on `rm -rf *` outranks any narrow `/tmp` allow,
137
+ 9. Use `rm -r`, NEVER `rm -rf`; use plain `git worktree remove` to drop a worktree, never
138
+ `--force` as the default (see item 13 below). A broad `ask` rule on `rm -rf *` outranks any narrow `/tmp` allow,
125
139
  so `rm -rf` raises a human permission prompt EVERY time regardless of path —
126
140
  it stalls gate sub-agents mid-run waiting on a keystroke. `rm -r` runs free. Do NOT widen the ask rule
127
141
  to work around this; that entry is the only deletion protection on the box.
128
- 9. Check the discriminator before picking a scratch path, don't assume from
129
- the platform: `[ -L /tmp ]`. macOS (symlink) — create throwaway worktrees
130
- under `/private/tmp`; a worktree under `/tmp` false-FAILs worktree-ancestor
131
- tests via the symlink, producing a confident wrong gate result. Linux (real
132
- dir) — `/tmp` is correct; `/private/tmp` may not exist there and must not
133
- be created.
134
- 10. Your report reaches the coordinator ONLY as your final returned text.
142
+ 10. Check the discriminator before picking a scratch path, don't assume from
143
+ the platform: `[ -L /tmp ]`. macOS (symlink) — create throwaway worktrees
144
+ under `/private/tmp`; a worktree under `/tmp` false-FAILs worktree-ancestor
145
+ tests via the symlink, producing a confident wrong gate result. Linux (real
146
+ dir) — `/tmp` is correct; `/private/tmp` may not exist there and must not
147
+ be created.
148
+ 11. Your report reaches the coordinator ONLY as your final returned text.
135
149
  Side-channel output is discarded. Put the whole verdict in the return value.
136
- 11. **NEVER run `git stash`, `git checkout`, `git reset`, or any working-tree
150
+ 12. **NEVER run `git stash`, `git checkout`, `git reset`, or any working-tree
137
151
  mutation in the SHARED repo.** Do read-only inspection there (`git show
138
152
  <sha>:<path>`, `git log`, `git diff`) and do every build/test in a throwaway
139
153
  detached worktree. `git stash` is a SINGLE SHARED STACK across every
@@ -142,12 +156,12 @@ rediscovering these the hard way:
142
156
  hold uncommitted `State.md` they are actively re-authoring.
143
157
  If you believe you must mutate the shared tree, STOP and report instead —
144
158
  that is always a finding, never a step.
145
- 12. **TEAR DOWN YOUR THROWAWAY WORKTREE WHEN THE GATE ENDS — after two checks,
159
+ 13. **TEAR DOWN YOUR THROWAWAY WORKTREE WHEN THE GATE ENDS — after two checks,
146
160
  in this order.** A required final step, not cleanup etiquette. Each
147
161
  abandoned worktree pins its HEAD commit against `gc` and adds a
148
162
  `.git/worktrees` admin entry, so the object store grows monotonically.
149
163
  Before removing:
150
- (a) `git -C <wt> status --porcelain` — if NON-EMPTY, **STOP and report it
164
+ (a) `git -C <wt> status --porcelain --untracked-files=all --ignored -- .thrum` — if NON-EMPTY, **STOP and report it
151
165
  instead of removing.** Uncommitted work in a throwaway worktree exists
152
166
  NOWHERE else; this is the category that actually loses work.
153
167
  (b) `git branch -a --contains $(git -C <wt> rev-parse HEAD)` — if EMPTY,
@@ -155,7 +169,7 @@ rediscovering these the hard way:
155
169
  it. Usually fine (a gate merge is reproducible by redoing it) but say so
156
170
  in your report rather than doing it silently.
157
171
  Then `git worktree remove <wt>` — **plain, no `--force`.** Its rc=128 refusal backstops
158
- ONLY untracked/modified content (see rule 8 on `rm -r`) — it does NOT cover gitignored
172
+ ONLY untracked/modified content (see rule 9 on `rm -r`) — it does NOT cover gitignored
159
173
  content, which git removes silently with no refusal; a clean rc=0 is not proof nothing of
160
174
  value was in there (see coordinator-assessing-agent-completion's reap procedure). `--force`
161
175
  is a justified override only, never the default (see coordinator-merging-code §7a).
@@ -169,6 +183,21 @@ config entry (see `lens_scope_semantics` in the config), which still runs on
169
183
  every diff regardless of trigger directories. If the config has no
170
184
  `trigger_directories`, fail with guidance to run `project-hotpath-gate`.
171
185
 
186
+ ## Invariant-ratchet lenses
187
+
188
+ A lens may declare `mandatory_test_command` (see `census_classification_coverage`
189
+ and `write_owner_bypass_ratchet` in `.thrum/hotpath-gate.json`) instead of
190
+ (or alongside) a pattern-match `question`/`required_evidence` pair. When
191
+ present, PASS/FAIL is the command's own exit code — never a judgment call
192
+ from reading the diff. This is the shape for any invariant that already has
193
+ a mechanical detector: wire the detector as an `always_run` lens with a
194
+ monotonic budget (a count that may only decrease, or an explicit
195
+ waiver-tagged exception), so a diff cannot silently re-widen the invariant
196
+ in the same change that appears to narrow it. `write_owner_bypass_ratchet`
197
+ is the reference instance: it fails a merge that bumps a
198
+ ceiling/aggregate in the ledger file without a `RATCHET-WAIVER:` tag, even
199
+ when the ledger-equality test alone would pass.
200
+
172
201
  ## Delta re-gate continuity — walk the whole branch, read the whole function
173
202
 
174
203
  **Why:** A commit introducing a lock can be an ancestor of a delta-re-gate's
@@ -432,7 +461,7 @@ hoc test target nothing routes to. A merge that adds a `state.NewState(...)`
432
461
  call site in an `internal/daemon/rpc/*_test.go` file (test-fixture setup, not a
433
462
  handler) can leave it unclassified and desync the frozen census snapshot with
434
463
  no gate catching it — trunk went RED post-merge on 573mo v87 for exactly this
435
- reason (thrum-ykmly).
464
+ reason.
436
465
 
437
466
  **Relationship to Lenses 1–10:** every other lens in this file is an
438
467
  LLM-judgment pattern check — grep a pattern, read the surrounding code, apply
@@ -476,7 +505,7 @@ diff on `TestCensusRegeneration`'s brittleness with zero added
476
505
  defect-prevention (`ClassificationCoverage` alone already catches the defect
477
506
  this lens exists for). `TestCensusRegeneration`'s own staleness is tracked
478
507
  separately (nd2j1/P1 owns the classification data; the brittle count-snapshot
479
- assertion itself is tracked as **thrum-33zzh** — "make advisory or drop the
508
+ assertion itself is a distinct open question — "make advisory or drop the
480
509
  raw-count assertion"), not by this lens.
481
510
 
482
511
  **Severity:** Trigger fires and `mandatory_test_command` was not run before
@@ -520,10 +549,24 @@ otherwise leave them.
520
549
 
521
550
  ## If it fails
522
551
 
523
- Send it back as a normal review finding — same channel as dual-review output,
524
- folded into the same numbered list if dual review is still open, or as its own
525
- short reply if dual review already passed. Cite the offending function/file,
526
- which lens it failed, and the config value that triggered the finding.
552
+ For a genuine hot-path/perf defect, a production-behaviour change, or a design
553
+ judgment call: send it back as a normal review finding — same channel as
554
+ dual-review output, folded into the same numbered list if dual review is still
555
+ open, or as its own short reply if dual review already passed. Cite the
556
+ offending function/file, which lens it failed, and the config value that
557
+ triggered the finding.
558
+
559
+ For mechanical bookkeeping only (census/shard regen via the tool, line-number
560
+ or key refreshes, ledger totals/ceilings where the arithmetic is derivable, a
561
+ per-entry waiver or citation comment recording a classification already
562
+ established elsewhere (never a new safety judgment of your own), a nosec
563
+ baseline hash for an already-reviewed pattern, comment wording, stale test
564
+ expectations that merely follow a landed change): fix it yourself as a
565
+ `GATE-AUTHORED` commit on your
566
+ `gate/` branch, re-run ONLY the lens(es) the fix affects, and report
567
+ `CLEAN-WITH-GATE-FIXES` listing each fix instead of bouncing it to the owner.
568
+ When unsure which bucket a finding falls in, ask the coordinator with the exact
569
+ diff — don't bounce reflexively.
527
570
 
528
571
  ## Efficacy tracking (v1 acceptance requirement)
529
572
 
@@ -563,6 +606,7 @@ rows.
563
606
  | `FALSE_POSITIVE` | Gate flagged something correct — record which lens and why |
564
607
  | `SLIPPED` | A wedge occurred AFTER merge that the gate did not catch |
565
608
  | `SKIPPED_WITH_EVIDENCE` | Gate deliberately skipped (no trigger dirs), evidence cited |
609
+ | `CLEAN-WITH-GATE-FIXES` | Gate found only mechanical bookkeeping gaps, fixed them itself as a GATE-AUTHORED commit, re-ran only the affected checks, merge proceeded |
566
610
 
567
611
  **Retrospective reclassification:** When triaging a new wedge or incident, grep
568
612
  `dev-docs/hotpath-gate-efficacy.md` for the merged branch/date. If the gate
@@ -591,4 +635,4 @@ gaps and lens improvements for the next version.
591
635
  first gate run, appended after each run)
592
636
 
593
637
  <!-- THRUM-GATE: stage=skill next=review -->
594
- <!-- THRUM-REVIEW: stage=skill verdict=Ready:Yes cycle=2 date=2026-07-10 -->
638
+ <!-- THRUM-REVIEW: stage=skill verdict=Ready:Yes cycle=2 -->
@@ -162,8 +162,7 @@ bd update thrum-abc --notes "$notes"
162
162
 
163
163
  ## Project-specific rules (already loaded)
164
164
 
165
- Read the shared partial at the absolute path:
166
- `claude-plugin/commands/_project-rules-protocol.md`
165
+ Load the /thrum:project-rules-protocol skill and follow it.
167
166
 
168
167
  If you accumulate a new rule mid-session (the user corrects you), capture it
169
168
  via the `coordinator-maintaining-memory` skill — it references the
@@ -40,7 +40,7 @@ thrum memory create --kind agent_rule --scope role \
40
40
  ```
41
41
 
42
42
  `--short`/`--full` carry real prose — compose via heredoc or file, never
43
- double-quoted inline; see your role preamble's 🔴 PROSE INTO A COMMAND rule.
43
+ double-quoted inline; see the heredoc-or-file rule in your role preamble.
44
44
 
45
45
  Body shape uniform across all role-rule writes — see `memory-write-discipline`.
46
46
 
@@ -57,8 +57,11 @@ created from origin, unpushed commits can be lost or inaccessible.
57
57
 
58
58
  **How to apply:** Session close protocol — push the coordination branch every
59
59
  session end. **Read the branch name, never recall it:**
60
- `jq -r '.orchestration.merge_target' .thrum/config.json` (or your project's
61
- CLAUDE.md § Branching Strategy). Push every `feature/*` and `fix/*` branch too.
60
+ `CONFIG=.thrum/config.json; [ -f .thrum/redirect ] && CONFIG="$(cat .thrum/redirect)/config.json"; jq -r '.orchestration.merge_target' "$CONFIG"`
61
+ (a worktree's `.thrum/` holds only a `redirect` file pointing at the main
62
+ repo's `.thrum` dir, so reading `.thrum/config.json` directly there returns
63
+ empty) — or your project's CLAUDE.md § Branching Strategy. Push every
64
+ `feature/*` and `fix/*` branch too.
62
65
  A docs/site branch pushes only when the site is ready to deploy; `main` and
63
66
  `release/*` go through the release flow.
64
67
 
@@ -77,10 +80,7 @@ batch — the visual tree exposes inversion immediately. For bulk epic creation
77
80
  (many tasks at once), spawn parallel sub-agents to issue the `bd create` calls;
78
81
  bd is fully concurrent-safe.
79
82
 
80
- > **Model tiers:** pass an explicit `model:` on every dispatch — `sonnet`
81
- > (low effort) mechanical, `sonnet` (medium effort) judgment, Opus only on
82
- > operator-ask or a skill step that names it. See the
83
- > `choosing-subagent-models` skill for the full policy.
83
+ > **Model tiers:** pass an explicit `model:` on every dispatch; choose model and effort per the `choosing-subagent-models` skill (read `runtime.role_models` at the moment of use). Never let a sub-agent inherit your own model.
84
84
 
85
85
  ## Use `bd close --suggest-next` to surface unblocked work
86
86
 
@@ -184,8 +184,7 @@ orchestrators to for the implementers **they** launched.
184
184
 
185
185
  ## Project-specific rules (already loaded)
186
186
 
187
- Read the shared partial at the absolute path:
188
- `claude-plugin/commands/_project-rules-protocol.md`
187
+ Load the /thrum:project-rules-protocol skill and follow it.
189
188
 
190
189
  If you accumulate a new rule mid-session (the user corrects you), capture it via
191
190
  the `coordinator-maintaining-memory` skill — it references the