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
@@ -35,9 +35,13 @@ When filling this template to create an implementation prompt:
35
35
  - `{{WORKTREE_PATH}}` — Absolute path to the working worktree
36
36
  - `{{BRANCH_NAME}}` — Git branch for this work (e.g., `feature/auth`)
37
37
  - `{{BASE_BRANCH}}` — The branch this work merges into. **Resolve it from the
38
- project's actual merge target** (`jq -r '.orchestration.merge_target'
39
- .thrum/config.json`); do not assume `main` and do not carry a branch name
40
- from another document
38
+ project's actual merge target**
39
+ (`CONFIG=.thrum/config.json;
40
+ [ -f .thrum/redirect ] && CONFIG="$(cat .thrum/redirect)/config.json";
41
+ jq -r '.orchestration.merge_target' "$CONFIG"`
42
+ — a worktree's `.thrum/` holds only a `redirect` file, not its own
43
+ `config.json`); do not assume `main` and do not carry a branch name from
44
+ another document
41
45
  - `{{DESIGN_DOC}}` — **Absolute path** to the design spec (if applicable)
42
46
  - `{{REFERENCE_CODE}}` — Paths to reference implementations (if any)
43
47
  - `{{QUALITY_COMMANDS}}` — Commands for test/lint, **scoped to packages this
@@ -88,12 +92,12 @@ Otherwise, orchestrate via the agent table below.
88
92
 
89
93
  | Dispatch | Agent type | Model | Background? |
90
94
  | ------------------------------ | ------------------------------ | --------------------------------------- | ----------- |
91
- | Research / explore a code area | `Explore` or `general-purpose` | `sonnet` | yes |
92
- | Implement a task | `general-purpose` | `sonnet` (low effort if purely mechanical) | no |
93
- | Verify a task against the plan | `general-purpose` | `sonnet` | no |
94
- | Run tests / lint | `general-purpose` | `sonnet` (low effort) | yes |
95
+ | Research / explore a code area | `Explore` or `general-purpose` | per `choosing-subagent-models` | yes |
96
+ | Implement a task | `general-purpose` | per `choosing-subagent-models` (low effort if purely mechanical) | no |
97
+ | Verify a task against the plan | `general-purpose` | per `choosing-subagent-models` | no |
98
+ | Run tests / lint | `general-purpose` | per `choosing-subagent-models` (low effort) | yes |
95
99
 
96
- Always pass `model:` explicitly — never let a sub-agent inherit your (Opus)
100
+ Always pass `model:` explicitly — never let a sub-agent inherit your own
97
101
  model. Label every dispatch's `description` with `research:` / `implement:` /
98
102
  `verify:` (the evaluation harness classifies delegation shape from these
99
103
  labels).
@@ -115,7 +119,7 @@ labels).
115
119
 
116
120
  ### Verifier dispatch (per task)
117
121
 
118
- After an implementation dispatch returns, spawn a `sonnet` verifier against the
122
+ After an implementation dispatch returns, spawn a verifier sub-agent (model per `choosing-subagent-models`) against the
119
123
  plan the implementing sub-agent was given — confirm the diff meets the
120
124
  acceptance criteria. This is the in-loop check; the full code review still
121
125
  happens at Phase 3: Self-Review Gate.
@@ -131,7 +135,7 @@ section.
131
135
  cd {{WORKTREE_PATH}}
132
136
  thrum quickstart --name {{AGENT_NAME}} --role implementer --module {{BRANCH_NAME}} --intent "Implementing {{EPIC_ID}}"
133
137
  thrum inbox --unread
134
- # Tip: thrum inbox --unread peeks without marking read; thrum message read --all to mark all read
138
+ # Tip: thrum inbox --unread peeks without marking read; thrum message read --all --force to mark all unread (run `--all` alone first — dry run)
135
139
  # Tip: default page is 10 newest-first — stale unread sorts LAST; use `thrum message search "<term>"` to find it
136
140
  thrum send --to @{{SUPERVISOR_NAME}} --stdin <<'EOF'
137
141
  Starting work on {{EPIC_ID}}
@@ -177,11 +181,13 @@ EOF
177
181
  Whether starting fresh or resuming after context loss, always begin here. This
178
182
  phase is idempotent — running it multiple times is safe and expected.
179
183
 
180
- 🔴 **BEFORE ANYTHING ELSE — OBTAIN THE PLAN INTO YOUR WORKTREE AND CONFIRM YOU CAN OPEN IT.** Do NOT implement from plan detail relayed to you in messages or beads — relay is lossy and drifts as the plan is updated.
184
+ 🔴 **BEFORE ANYTHING ELSE — OBTAIN THE PLAN INTO YOUR WORKTREE AND CONFIRM YOU CAN OPEN IT.**
185
+ Do NOT implement from plan detail relayed to you in messages or beads — relay is lossy and drifts as the
186
+ plan is updated.
181
187
 
182
188
  ```bash
183
189
  cd {{WORKTREE_PATH}}
184
- git pull # pull the committed plan into this worktree
190
+ git pull --no-rebase # pull the committed plan into this worktree (merge; a bare pull aborts on divergence)
185
191
  head -1 {{PLAN_FILE}} # confirm the plan file actually opens here
186
192
  ```
187
193
 
@@ -216,7 +222,7 @@ git status
216
222
  git --no-pager log --oneline -10
217
223
 
218
224
  # Pull latest changes (if remote tracking is set up) — merge, never rebase
219
- git pull
225
+ git pull --no-rebase
220
226
  ```
221
227
 
222
228
  ### Step 3: Explore Existing Code
@@ -432,35 +438,40 @@ bd list --type=epic | grep -i refactor
432
438
 
433
439
  If no refactoring epic exists, create one:
434
440
 
435
- `--description` is multi-line prose — never double-quoted inline. On
436
- `scripts/bd-shared`, `--stdin`/`--body-file` are refused (remote-path
437
- resolution + silent-empty-body hazards), so write it to a scratch file and
438
- pass `-d "$(cat <file>)"`; see your role preamble's 🔴 PROSE INTO A COMMAND
439
- rule.
441
+ `--description` is multi-line prose — never double-quoted inline. Write it to a
442
+ scratch file and pass `--body-file <file>`; see the heredoc-or-file rule in your role preamble. `scripts/bd-shared` delivers `--body-file` (and `--stdin`)
443
+ content: it reads the file on YOUR box and pipes those bytes to bd, and an empty
444
+ or blank body is refused loudly. Only `-f`/`--file` and `--graph` (bulk-plan
445
+ files) are refused there. Scratch files go in `/private/tmp` on macOS, where
446
+ `/tmp` is a symlink (check `[ -L /tmp ]`), and in `/tmp` elsewhere.
440
447
 
441
448
  ```bash
442
- cat > /tmp/refactor-epic-desc.md <<'EOF'
449
+ # Scratch dir: /private/tmp on macOS (where /tmp is a symlink), /tmp elsewhere.
450
+ SCRATCH=$([ -L /tmp ] && echo /private/tmp || echo /tmp)
451
+ cat > "$SCRATCH/refactor-epic-desc.md" <<'EOF'
443
452
  Persistent backlog for refactoring, DRY improvements, and code organization
444
453
  opportunities discovered during feature work. Tasks are added by
445
454
  implementation agents as they encounter opportunities. Reviewed and
446
455
  prioritized by the coordinator periodically.
447
456
  EOF
448
- bd create --title="Refactoring & DRY Opportunities" --type=epic --priority=3 -d "$(cat /tmp/refactor-epic-desc.md)"
457
+ bd create --title="Refactoring & DRY Opportunities" --type=epic --priority=3 --body-file "$SCRATCH/refactor-epic-desc.md"
449
458
  ```
450
459
 
451
460
  #### 2. Log the Opportunity
452
461
 
453
- Same `--description` handling as §1 above (scratch file + `-d "$(cat <file>)"`).
462
+ Same `--description` handling as §1 above (scratch file + `--body-file`).
454
463
 
455
464
  ```bash
456
- cat > /tmp/refactor-task-desc.md <<'EOF'
465
+ # Scratch dir: /private/tmp on macOS (where /tmp is a symlink), /tmp elsewhere.
466
+ SCRATCH=$([ -L /tmp ] && echo /private/tmp || echo /tmp)
467
+ cat > "$SCRATCH/refactor-task-desc.md" <<'EOF'
457
468
  **Discovered during:** {{EPIC_ID}}
458
469
  **Files:** <file paths>
459
470
  **Opportunity:** <what could be improved — duplicated code, hardcoded values, missed abstraction>
460
471
  **Suggested approach:** <how to fix it>
461
472
  **Effort estimate:** small/medium/large
462
473
  EOF
463
- bd create --title="Refactor: <short description>" --type=task --parent=<refactoring-epic-id> --priority=3 -d "$(cat /tmp/refactor-task-desc.md)"
474
+ bd create --title="Refactor: <short description>" --type=task --parent=<refactoring-epic-id> --priority=3 --body-file "$SCRATCH/refactor-task-desc.md"
464
475
  ```
465
476
 
466
477
  #### 3. Continue With Your Assigned Work
@@ -494,11 +505,13 @@ If a task is blocked:
494
505
 
495
506
  ```bash
496
507
  # Ask the blocking agent for help
497
- # NOTE: --mention @implementer (with no --to) delivers ONLY to agent(s) matching
498
- # that role/name — it does not go to the supervisor and does not broadcast. A
499
- # message with ZERO addressing (no --to, no mentions) routes to the local
500
- # coordinator instead. Broadcast to everyone requires an explicit
501
- # --to everyone / --mention @everyone.
508
+ # NOTE: --mention @implementer (with no --to) only delivers if "implementer"
509
+ # is itself a registered agent ID — mentions resolve exact agent IDs only, no
510
+ # role fan-out (P0 ruling: removed by design, do not
511
+ # restore). A message with ZERO addressing (no --to, no mentions) routes to
512
+ # the local coordinator instead. There is no broadcast-to-everyone mechanism —
513
+ # --broadcast and @everyone were removed by design; name every recipient
514
+ # explicitly (--to is repeatable for multiple recipients).
502
515
  thrum send --mention @implementer --stdin <<'EOF'
503
516
  BLOCKED: {{TASK_ID}} — waiting for {{BLOCKER_ID}}. Can you prioritize?
504
517
  EOF
@@ -603,18 +616,25 @@ Fix any failures before proceeding. Do not submit broken code for review.
603
616
 
604
617
  ### Step 2: Spec Compliance Review (Stage 1)
605
618
 
606
- Verify the implementation covers everything specified in the plan, design doc,
607
- and each task's acceptance criteria. No code-style judgments at this stage —
608
- only "does the code do what was asked?"
619
+ Verify the implementation covers everything specified in the plan and, when the
620
+ epic has a design doc, in the design doc. Also cross-check each task's
621
+ acceptance criteria against the code: run
622
+ `bd show <task_id>` for every task in the epic and confirm each acceptance
623
+ criterion is met. No code-style judgments at this stage — only "does the code do
624
+ what was asked?"
609
625
 
610
626
  Invoke `verify-against-plan` with these inputs:
611
627
 
612
628
  ```text
613
- /verify-against-plan plan={{PLAN_FILE}} branch={{BRANCH_NAME}}
629
+ /verify-against-plan plan={{PLAN_FILE}} design={{DESIGN_DOC}} branch={{BRANCH_NAME}}
614
630
  ```
615
631
 
632
+ Drop the `design=` input only when this epic has no design doc (`{{DESIGN_DOC}}`
633
+ was left unset). With it, requirements that only the design states are checked
634
+ too, not just the plan's tasks.
635
+
616
636
  The skill produces structured `BLOCKING` / `IMPORTANT` / `MINOR` findings with
617
- plan-reference + file:line evidence.
637
+ plan-reference (or design-reference) + file:line evidence.
618
638
 
619
639
  **When findings come back:**
620
640
 
@@ -643,7 +663,7 @@ results before proceeding). The reviewer is a separate agent — you cannot
643
663
  influence its findings.
644
664
 
645
665
  ```text
646
- Agent(subagent_type="feature-dev:code-reviewer", model="sonnet",
666
+ Agent(subagent_type="feature-dev:code-reviewer", model="<per choosing-subagent-models>",
647
667
  prompt="Review code quality of the implementation on branch {{BRANCH_NAME}}
648
668
  in {{WORKTREE_PATH}}. Focus only on quality of the code that was written —
649
669
  spec compliance is covered separately by verify-against-plan.
@@ -814,7 +834,7 @@ the minimal sequence:
814
834
  cd {{WORKTREE_PATH}}
815
835
  thrum quickstart --name {{AGENT_NAME}} --role implementer --module {{BRANCH_NAME}} --intent "Resuming {{EPIC_ID}}"
816
836
  thrum inbox --unread
817
- # Tip: thrum inbox --unread peeks without marking read; thrum message read --all to mark all read
837
+ # Tip: thrum inbox --unread peeks without marking read; thrum message read --all --force to mark all unread (run `--all` alone first — dry run)
818
838
  # Tip: default page is 10 newest-first — stale unread sorts LAST; use `thrum message search "<term>"` to find it
819
839
 
820
840
  # 2. Orient from beads and git
@@ -75,8 +75,7 @@ where inlining is genuinely cheaper than the round-trip.
75
75
 
76
76
  ## Project-specific rules (already loaded)
77
77
 
78
- Read the shared partial at the absolute path:
79
- `claude-plugin/commands/_project-rules-protocol.md`
78
+ Load the /thrum:project-rules-protocol skill and follow it.
80
79
 
81
80
  If you accumulate a new rule mid-session (the user corrects you), capture it via
82
81
  the `researcher-maintaining-memory` skill — it references the
@@ -24,16 +24,13 @@ specific symbol, or a specific question. Get a focused report back. For research
24
24
  across N > 6 items, invoke `efficient-multi-agent-research` instead of bespoke
25
25
  dispatch — it handles partition + parallelization + consolidation.
26
26
 
27
- > **Model tiers:** pass an explicit `model:` on every dispatch — `sonnet`
28
- > (low effort) mechanical, `sonnet` (medium effort) judgment, Opus only on
29
- > operator-ask or a skill step that names it. See the
30
- > `choosing-subagent-models` skill for the full policy.
27
+ > **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.
31
28
 
32
29
  ### Prefer `efficient-multi-agent-research` for multi-part research
33
30
 
34
31
  When a research or investigation task has independent parts, reach for the
35
32
  `efficient-multi-agent-research` skill FIRST — it partitions the work across
36
- many cheap parallel subagents (sonnet-low gatherers, sonnet-medium synthesizers) instead of
33
+ many cheap parallel subagents (cheap gatherers, judgment-tier synthesizers) instead of
37
34
  one expensive serial subagent. It is the preferred research path: cheaper,
38
35
  faster, and it keeps each subagent's context tight.
39
36
 
@@ -77,8 +74,8 @@ sessions and re-readable by other agents.
77
74
 
78
75
  **How to apply:** After reporting to the requester, write the finding as a
79
76
  `research_note` memory with cited file:line refs and a verification footer. Tag
80
- with a `research-<slug>` handle so other agents can find it later via
81
- `thrum memory search --tag research-<slug>`:
77
+ it with `--tag <slug>` so other agents can find it later via
78
+ `thrum memory search --tag <slug>`:
82
79
 
83
80
  ```bash
84
81
  cat > /tmp/research-note-body.md <<EOF
@@ -88,19 +85,18 @@ Verified: $(date +%Y-%m-%d) @ $(git rev-parse HEAD)
88
85
  EOF
89
86
  thrum memory create --kind research_note --scope role \
90
87
  --title "<finding prose, ~80 char soft limit>" \
91
- --tag research-<slug> \
88
+ --tag <slug> \
92
89
  --oneline "<one-line summary>" \
93
90
  --full "@/tmp/research-note-body.md"
94
91
  ```
95
92
 
96
93
  `--full` here is multi-line prose — compose via heredoc or a captured
97
- variable, never double-quoted inline like this; see your role preamble's 🔴
98
- PROSE INTO A COMMAND rule.
94
+ variable, never double-quoted inline like this; see the heredoc-or-file rule in your role preamble.
99
95
 
100
96
  Then add one line to `.thrum/context/research.md` under Tracked Topics (note: `thrum queue` now supersedes free-text Open Questions tracking):
101
97
 
102
98
  ```markdown
103
- - `research-<slug>` — <one-line description, ≤ 80 chars>
99
+ - `<slug>` — <one-line description, ≤ 80 chars>
104
100
  ```
105
101
 
106
102
  The full index format and staleness-check protocol live in
@@ -124,8 +120,7 @@ gaps — you surface them, the implementer ships them.
124
120
 
125
121
  ## Project-specific rules (already loaded)
126
122
 
127
- Read the shared partial at the absolute path:
128
- `claude-plugin/commands/_project-rules-protocol.md`
123
+ Load the /thrum:project-rules-protocol skill and follow it.
129
124
 
130
125
  If you accumulate a new rule mid-session (the user corrects you), capture it via
131
126
  the `researcher-maintaining-memory` skill — it references the
@@ -158,7 +158,7 @@ thrum memory create --kind agent_rule --scope role \
158
158
  ```
159
159
 
160
160
  `--short`/`--full` carry real prose — compose via heredoc or file, never
161
- double-quoted inline; see your role preamble's 🔴 PROSE INTO A COMMAND rule.
161
+ double-quoted inline; see the heredoc-or-file rule in your role preamble.
162
162
 
163
163
  This is the SAME pattern as coordinator/implementer role-rule writes — see
164
164
  `memory-write-discipline` for the canonical shape.
@@ -1,32 +1,32 @@
1
1
  ---
2
- description:
3
- Shared snapshot-composition protocol consumed by the snapshot-save commands.
4
- Not user-invocable directly.
2
+ name: snapshot-protocol
3
+ description: "Use when composing a restart snapshot or continuation - snapshot structure, worktree resolution, write rules."
5
4
  ---
6
5
 
7
- # Snapshot Composition Protocol (shared partial)
8
6
 
9
- Consumers: run `grep -rl _snapshot-protocol claude-plugin/commands/` for the
10
- current set — do NOT hardcode it here. A list of consumers inside the consumed
11
- file is a second copy of a git-answerable fact and rots the moment a command is
12
- added or dropped. Note: plain `/thrum:restart` does NOT consume this partial; it
13
- carries its own inline snapshot template.
7
+ # Snapshot Composition Protocol
8
+ Note: plain `/thrum:restart` carries its own inline snapshot template rather
9
+ than consuming this skill.
14
10
 
15
- This is the canonical source-of-truth for snapshot composition discipline. The
16
- sibling commands that consume this partial compose: read this partial →
17
- variant-specific terminal action. Do NOT invoke this file directly; it has no
11
+ This is the canonical source-of-truth for snapshot composition discipline.
12
+ Invoke this skill to compose a snapshot, then take the variant-specific
18
13
  terminal action.
19
14
 
20
15
  ## Step 1 — Resolve identity and your worktree
21
16
 
22
17
  ```bash
23
18
  # $REPO must be YOUR worktree — the directory `thrum prime` reads the restart
24
- # snapshot back from. Resolve it from the daemon's authoritative identity, NOT
25
- # `git rev-parse` (which keys off the current shell CWD and would write to the
26
- # wrong .thrum/restart/ if a bash step left your worktree). Fall back to git
27
- # only if whoami can't answer.
28
- REPO=$(thrum whoami --field worktree 2>/dev/null)
29
- [ -n "$REPO" ] || REPO=$(git rev-parse --show-toplevel) || { echo "ERROR: cannot resolve your worktree"; exit 1; }
19
+ # snapshot back from. Resolve it ONLY via the daemon's authoritative,
20
+ # peercred-resolved identity (`thrum agent worktree --authoritative`) — NEVER
21
+ # via `thrum whoami --field worktree` (cwd-resolved) or `git rev-parse
22
+ # --show-toplevel` (also cwd-resolved). A cwd-derived pattern
23
+ # could silently resolve to a DIFFERENT agent's worktree, or the main repo,
24
+ # saving this snapshot where nothing ever reads it back. There is NO git
25
+ # fallback — if the daemon can't answer, refuse and stop rather than guess.
26
+ REPO=$(
27
+ thrum agent worktree --authoritative 2>/dev/null
28
+ ) || { echo "ERROR: cannot authoritatively resolve your worktree via the daemon. Refusing to fall back to cwd/git-toplevel — that would risk silently saving this snapshot to the wrong repo. Check daemon connectivity and retry."; exit 1; }
29
+ [ -n "$REPO" ] || { echo "ERROR: thrum agent worktree --authoritative returned empty"; exit 1; }
30
30
  AGENT=$(thrum whoami --field agent_id) || { echo "ERROR: agent not registered"; exit 1; }
31
31
  [ -n "$AGENT" ] || { echo "ERROR: empty agent_id"; exit 1; }
32
32
  mkdir -p "${REPO}/.thrum/restart"
@@ -66,14 +66,14 @@ shapes everything else you write below it.
66
66
 
67
67
  **Stamp your snapshot with the base it was authored against.**
68
68
  Derive and emit the **Authored-against** stamp per
69
- `claude-plugin/commands/_stamp-protocol.md` and place it at the very top of your
69
+ the /thrum:stamp-protocol skill and place it at the very top of your
70
70
  §1 section (that protocol computes the SHA and merge_target for you — never
71
71
  hand-type them). This is what lets `thrum prime` diff your snapshot at the next
72
72
  wake and flag which cited files have MOVED; an unstamped snapshot reads as
73
73
  "current", indistinguishable from one that never drifted.
74
74
 
75
75
  Any commit your snapshot names as its own stamped SHA must also be readable
76
- under `_stamp-protocol.md`'s "Read-time provenance re-derivation" section
76
+ under `stamp-protocol.md`'s "Read-time provenance re-derivation" section
77
77
  (SHA-resolves, then merge-status) — link to that section rather than restating
78
78
  its checks here.
79
79
 
@@ -109,7 +109,7 @@ session's conversation context. Refer to the previous session in third person.
109
109
 
110
110
  ### Choose your structure
111
111
 
112
- The variant skill that invoked this partial tells you which structure to use:
112
+ The variant skill that invoked this skill tells you which structure to use:
113
113
 
114
114
  - **`/thrum:sleep`** → use the STANDARD 11-section structure below.
115
115
  - **`/thrum:restart-extended` and `/thrum:sleep-extended`** → use the EXTENDED
@@ -261,5 +261,11 @@ ${REPO}/.thrum/restart/${AGENT}.md
261
261
  comes from `thrum tmux restart` or `thrum tmux create`). No bash heredoc or
262
262
  `cat <<EOF` redirection is needed — write the file directly.
263
263
 
264
+ Variants that have a verify step (`/thrum:compact`, `/thrum:compact-extended`,
265
+ `/thrum:restart`, `/thrum:restart-extended`) mint a `SNAPSHOT_PATH` and
266
+ `SNAPSHOT_NONCE` in their own Step 3 PREP block: write to exactly that path, end
267
+ the file with `<!-- snapshot-nonce: <nonce> -->`, and record both for the verify
268
+ block. The sleep variants have no verify block and need no nonce.
269
+
264
270
  After writing, return control to your variant skill (`/thrum:restart-extended`,
265
271
  `/thrum:sleep`, or `/thrum:sleep-extended`) for the terminal action.
@@ -1,15 +1,14 @@
1
1
  ---
2
- description:
3
- Shared Authored-against stamp protocol — canonical format, derivation
4
- commands, and never-type rule. Not user-invocable directly.
2
+ name: stamp-protocol
3
+ description: "Use when stamping a plan, prompt, or snapshot - Authored-against format, derivation commands, never-type rule."
5
4
  ---
6
5
 
7
- # Authored-against Stamp Protocol (shared partial)
8
6
 
7
+ # Authored-Against Stamp Protocol
9
8
  This is the canonical source-of-truth for the Authored-against stamp: its format,
10
9
  derivation commands, and the never-type rule. Consuming files point here instead of
11
- restating the recipe. Do NOT invoke this file directly; it has no terminal action.
12
- (To find what currently points here: `grep -rn "_stamp-protocol.md" claude-plugin/`
10
+ restating the recipe. Do not run this as a command; it has no terminal action — other skills and commands load it by name.
11
+ (To find what currently points here: `grep -rn "thrum:stamp-protocol" claude-plugin/commands/ claude-plugin/skills/`
13
12
  — a hand-listed consumer roster in this file would rot the moment a new emitter or
14
13
  reader is added, so none is kept here.)
15
14
 
@@ -46,8 +45,15 @@ diffs if the remote-tracking ref might be stale.
46
45
  # SHA of the current HEAD
47
46
  git rev-parse HEAD
48
47
 
49
- # Configured merge target
50
- jq -r '.orchestration.merge_target' .thrum/config.json
48
+ # Configured merge target -- resolve through .thrum/redirect when present.
49
+ # A worktree's .thrum/ holds only a `redirect` file (a single line: the
50
+ # absolute path to the MAIN REPO'S .thrum directory itself), not its own
51
+ # config.json -- reading .thrum/config.json directly from a worktree
52
+ # silently returns empty. Root repos have no redirect file, so CONFIG falls
53
+ # through to the direct path.
54
+ CONFIG=".thrum/config.json"
55
+ [ -f .thrum/redirect ] && CONFIG="$(cat .thrum/redirect)/config.json"
56
+ jq -r '.orchestration.merge_target' "$CONFIG"
51
57
  ```
52
58
 
53
59
  The author must never type or remember either value by hand — both come from the
@@ -8,8 +8,9 @@ license: "Apache-2.0"
8
8
 
9
9
  # Thrum - Git-Backed Multi-Agent Coordination (Messaging, Groups, Shared Context)
10
10
 
11
- Run `thrum prime` for full session context (auto-injected by hooks on
12
- SessionStart and PreCompact).
11
+ Run `thrum prime` for full session context (auto-injected by the SessionStart
12
+ hook; also fires on post-compact resume). PreCompact is not registered — use
13
+ `/thrum:compact` to save a snapshot before deliberately compacting.
13
14
 
14
15
  ## Quick Command Reference
15
16
 
@@ -17,19 +18,23 @@ SessionStart and PreCompact).
17
18
 
18
19
  ```bash
19
20
  thrum send --to @name --body-file msg.md # Direct message (body from file)
20
- thrum send --broadcast --body-file msg.md # Team-wide fanout
21
- thrum send --to @everyone --body-file msg.md # Broadcast (legacy keyword; --broadcast preferred)
21
+ thrum send --to @name1 --to @name2 --body-file msg.md # Multiple explicit recipients (repeatable --to)
22
22
  thrum reply <msg-id> --body-file reply.md # Reply (same audience; NO --to — recipient comes from the message)
23
23
  thrum inbox List messages (auto-marks displayed as read)
24
24
  thrum inbox --unread Unread only (does not mark as read)
25
25
  thrum message search "<term>" Full-text search — use instead of paging; stale unread sorts last
26
26
  thrum sent List messages you sent
27
27
  thrum sent --unread Sent messages with unread recipients
28
- thrum message read --all Mark all messages as read
28
+ thrum message read --all --force Mark ALL unread as read (run `read --all` alone first — dry run)
29
29
  thrum wait Block until message arrives (30s timeout)
30
30
  thrum wait --timeout 120s Custom timeout (duration)
31
31
  ```
32
32
 
33
+ One-to-many fan-out (`--broadcast`, `@everyone`, role-based mentions/groups)
34
+ was removed by design (P0 ruling); do not restore it. Name
35
+ every recipient explicitly with repeatable `--to @name`, or address a scoped
36
+ agent-type group.
37
+
33
38
  ### Agents
34
39
 
35
40
  ```bash
@@ -140,8 +145,10 @@ processing. See [LISTENER_PATTERN.md](resources/LISTENER_PATTERN.md).
140
145
  ### Context Management
141
146
 
142
147
  - `thrum prime` gathers identity, team, inbox, git context, sync health
143
- - SessionStart hook auto-runs `thrum prime` on session start
144
- - PreCompact hook saves state to thrum context + `/tmp` backup before compaction
148
+ - SessionStart hook auto-runs `thrum prime` on session start (including
149
+ post-compact resume)
150
+ - PreCompact is NOT registered — run `/thrum:compact` to save a restart
151
+ snapshot deliberately before compacting
145
152
  - **After compaction:** run `/thrum:load-context` to restore your work context
146
153
  - Agent identity persists in `.thrum/identities/`
147
154
 
@@ -26,9 +26,9 @@ Task(subagent_type="message-listener", run_in_background=true, prompt="...")
26
26
 
27
27
  ## 4. Sending Without an Explicit Recipient Flag
28
28
 
29
- `thrum send 'msg'` with no `--to` or `--broadcast` is a hard error. The
30
- previous default — silent broadcast to every team agent — was a real footgun,
31
- so the CLI now requires the recipient to be explicit:
29
+ `thrum send 'msg'` with no `--to` is a hard error. The previous default —
30
+ silent broadcast to every team agent — was a real footgun, so the CLI now
31
+ requires the recipient to be explicit:
32
32
 
33
33
  ```bash
34
34
  # Wrong — hard-errors with a "missing recipient" prompt
@@ -39,19 +39,15 @@ thrum send --to @your_coordinator --stdin <<'EOF'
39
39
  msg
40
40
  EOF
41
41
 
42
- # Right — explicit team-wide fanout
43
- thrum send --broadcast --stdin <<'EOF'
44
- msg
45
- EOF
46
-
47
- # Right — legacy keyword form (still works; --broadcast preferred)
48
- thrum send --to @everyone --stdin <<'EOF'
42
+ # Right — repeatable --to for multiple explicit recipients
43
+ thrum send --to @alice --to @bob --stdin <<'EOF'
49
44
  msg
50
45
  EOF
51
46
  ```
52
47
 
53
- `--to` and `--broadcast` are mutually exclusive. `@everyone` continues to be
54
- auto-created and handles membership dynamically.
48
+ (P0 ruling): `--broadcast` and `@everyone` were removed by
49
+ design; do not restore them. There is no team-wide fanout — name every
50
+ recipient explicitly, or address a scoped agent-type group.
55
51
 
56
52
  ## 5. Skipping Registration
57
53
 
@@ -102,14 +98,16 @@ finishing the main task.
102
98
  Include Beads IDs, file paths, commit hashes — anything that helps the recipient
103
99
  act on the message.
104
100
 
105
- ## 12. Using @role to Address One Agent
101
+ ## 12. Assuming @role Fans Out to a Role's Agents
106
102
 
107
- **Wrong:** `thrum send --to @implementer --body-file msg.md` — fans out to all
108
- implementers. **Right:** `thrum send --to @alice --body-file msg.md` — use the
109
- agent's name.
103
+ **Wrong:** assuming `thrum send --to @implementer --body-file msg.md` reaches
104
+ every implementer. **Right:** `thrum send --to @alice --body-file msg.md` —
105
+ use the agent's name.
110
106
 
111
- `@role` sends to **all agents** with that role (via the auto-created role group)
112
- and emits a warning. Use `@name` for direct messages. Check names with
107
+ (P0 ruling): role-based mention/group fan-out was removed by
108
+ design; do not restore it. `--to` and `--mention` only resolve exact agent
109
+ IDs — `@implementer` matches nobody unless an agent is literally named
110
+ `implementer`. Use `@name` for direct messages. Check names with
113
111
  `thrum team`.
114
112
 
115
113
  ## 13. Sending to Unknown Recipients
@@ -60,20 +60,23 @@ Full reference: [docs/cli-hints.md](https://thrum.team/docs/cli-hints.html)
60
60
 
61
61
  ```bash
62
62
  thrum send --to @name --body-file ./body.md # Direct message (canonical form)
63
- thrum send --broadcast --body-file ./body.md # Explicit team-wide fanout (preferred)
64
- thrum send --to @everyone --body-file ./body.md # Broadcast (legacy keyword form)
63
+ thrum send --to @name1 --to @name2 --body-file ./body.md # Multiple explicit recipients (repeatable --to)
65
64
  thrum send --to @name --scope type:value --scope type:value2 --body-file ./body.md
66
65
  thrum send --to @name --ref type:value --body-file ./body.md
67
- thrum send --to @name --mention @role --body-file ./body.md
66
+ thrum send --to @name --mention @other_agent --body-file ./body.md
68
67
  thrum send --to @name --format plain --body-file ./body.md
69
68
  thrum send --to @name --structured '{"key":"value"}' --body-file ./body.md
70
69
  thrum send --to @name --body-file ./body.md # Shell-safe body (file)
71
70
  generator | thrum send --to @name - # '-' is a --stdin alias
72
71
  ```
73
72
 
74
- A recipient flag is REQUIRED — `thrum send 'msg'` with no `--to` or
75
- `--broadcast` is a hard error. `--to` and `--broadcast` are
76
- mutually exclusive.
73
+ A recipient flag is REQUIRED — `thrum send 'msg'` with no `--to` is a hard
74
+ error.
75
+
76
+ (P0 ruling): `--broadcast` and `@everyone` were removed by
77
+ design across the whole product; do not restore them. There is no one-to-many
78
+ fan-out — name every recipient explicitly with repeatable `--to`, or address a
79
+ scoped agent-type group.
77
80
 
78
81
  Shell-safe bodies: backticks, `$(...)`, `$VAR`, and quotes in a
79
82
  double-quoted message are interpreted by the shell BEFORE thrum runs, silently
@@ -85,9 +88,8 @@ trailing newline is stripped from stdin/file bodies.
85
88
  Flags:
86
89
 
87
90
  ```text
88
- --to string Recipient — @agent_name or @everyone for broadcast (mutex with --broadcast)
89
- --broadcast Fan out to the entire team (mutex with --to)
90
- --mention strings Mention a role (repeatable, format: @role)
91
+ --to strings Recipient — @agent_name, explicit only (repeatable; no @everyone/@role fan-out)
92
+ --mention strings Mention an explicit agent (repeatable, format: @agent_name)
91
93
  --ref strings Add reference (repeatable, format: type:value)
92
94
  --scope strings Add scope (repeatable, format: type:value)
93
95
  --format string Message format: markdown, plain, json (default "markdown")
@@ -198,7 +200,9 @@ thrum message edit <msg-id> --body-file ./new-body.md # Full replacement (autho
198
200
  thrum message edit <msg-id> --body-file ./new.md # Full replacement from file
199
201
  thrum message delete <msg-id> --force # Delete (--force required)
200
202
  thrum message read <msg-id> [<msg-id>...] # Mark as read
201
- thrum message read --all # Mark all as read
203
+ thrum message read --all # DRY RUN: list what --apply/--force would mark, marks nothing
204
+ thrum message read --all --apply # Mark the shown (already-seen) candidates
205
+ thrum message read --all --force # Mark ALL unread, seen or not (needs a fresh `--all` dry run first)
202
206
  thrum message search "<term>" # Full-text search across all messages (see § inbox above)
203
207
  thrum message reindex # Rebuild the FTS index if search looks wrong
204
208
  ```
@@ -214,7 +218,9 @@ Subcommand flags:
214
218
  --force Confirm deletion (required)
215
219
 
216
220
  # message read
217
- --all Mark all unread messages as read
221
+ --all List seen+unread candidates (dry run); combine with --apply or --force to mark
222
+ --apply With --all: mark the shown (already-seen) candidates
223
+ --force With --all: mark ALL unread, seen or not (needs a fresh --all dry run first)
218
224
  ```
219
225
 
220
226
  ---
@@ -4,6 +4,12 @@
4
4
  > at zero token cost with no background listener needed. See
5
5
  > [TMUX_SESSIONS.md](TMUX_SESSIONS.md). Use the listener pattern below when tmux
6
6
  > is not available or not practical for your setup.
7
+ >
8
+ > **Deprecated for newly initialized agents:** the hook injection and
9
+ > scheduled backstop that `thrum init` installs deliver message nudges without a
10
+ > listener. The pattern below still works and is supported, but it holds tokens in
11
+ > the agent's context for the entire session. Cross-runtime agents (codex, cursor,
12
+ > etc.) without hook support still use it.
7
13
 
8
14
  The message-listener is a background sub-agent that blocks on `thrum wait` and
9
15
  returns when messages arrive. A PID file (`.thrum/var/<agent_id>-listener.pid`)
@@ -14,7 +20,7 @@ prevents duplicate listeners — spawning when one is already running is safe.
14
20
  ```text
15
21
  Task(
16
22
  subagent_type="message-listener",
17
- model="sonnet", # low effort
23
+ model="<per choosing-subagent-models>", # cheapest tier
18
24
  prompt="Listen for Thrum messages.\nSTEP_1: /path/to/repo/scripts/thrum-startup.sh --listener-heartbeat\nSTEP_2: thrum wait --timeout 8m --after -15s --agent-name <agent_id>"
19
25
  )
20
26
  ```
@@ -49,7 +55,7 @@ Automatically respawn the listener if it dies or is lost after compaction.
49
55
  ```text
50
56
  CronCreate(
51
57
  cron="*/30 * * * *",
52
- prompt="Check the listener PID file at .thrum/var/<agent_id>-listener.pid.\nIf the file does not exist, or if kill -0 <pid> fails (process not running),\nspawn a new listener:\n\nAgent(subagent_type=\"message-listener\", model=\"sonnet\", prompt=\"Listen for Thrum messages.\\nSTEP_1: /path/to/repo/scripts/thrum-startup.sh --listener-heartbeat\\nSTEP_2: thrum wait --timeout 8m --after -15s --agent-name <agent_id>\")"
58
+ prompt="Check the listener PID file at .thrum/var/<agent_id>-listener.pid.\nIf the file does not exist, or if kill -0 <pid> fails (process not running),\nspawn a new listener:\n\nAgent(subagent_type=\"message-listener\", model=\"<per choosing-subagent-models>\", prompt=\"Listen for Thrum messages.\\nSTEP_1: /path/to/repo/scripts/thrum-startup.sh --listener-heartbeat\\nSTEP_2: thrum wait --timeout 8m --after -15s --agent-name <agent_id>\")"
53
59
  )
54
60
  ```
55
61
 
@@ -60,5 +66,5 @@ Spawn the initial listener on session start, then create the cron watchdog.
60
66
  - **Spawn freely** — PID file prevents duplicates
61
67
  - **Return immediately** when messages arrive (don't wait for more)
62
68
  - **Read-only** — the listener never sends messages
63
- - **Cost-efficient** — runs on sonnet-low, blocks instead of polling
69
+ - **Cost-efficient** — runs on a cheap tier, blocks instead of polling
64
70
  - Listener uses CLI only (`Bash` tool), not MCP tools