opencode-thrum-pro 0.1.4 → 0.1.6

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 (69) hide show
  1. package/assets/commands/thrum-_compact-runtime-commands.md +61 -0
  2. package/assets/commands/thrum-_snapshot-protocol.md +17 -6
  3. package/assets/commands/thrum-_stamp-protocol.md +9 -2
  4. package/assets/commands/thrum-compact-extended.md +352 -0
  5. package/assets/commands/thrum-compact.md +300 -0
  6. package/assets/commands/thrum-inbox.md +1 -1
  7. package/assets/commands/thrum-restart-extended.md +84 -11
  8. package/assets/commands/thrum-restart.md +105 -13
  9. package/assets/commands/thrum-send.md +4 -1
  10. package/assets/commands/thrum-sleep-extended.md +67 -46
  11. package/assets/commands/thrum-sleep.md +67 -58
  12. package/assets/skills/adversarial-critique/SKILL.md +5 -8
  13. package/assets/skills/agent-messaging-protocol/SKILL.md +35 -0
  14. package/assets/skills/brainstorm-steward/SKILL.md +65 -11
  15. package/assets/skills/brainstormer-staying-current/SKILL.md +113 -0
  16. package/assets/skills/choosing-subagent-models/SKILL.md +14 -0
  17. package/assets/skills/conversation-only-context/SKILL.md +11 -11
  18. package/assets/skills/conversation-only-context/resources/driver-subagent-pattern.md +1 -1
  19. package/assets/skills/conversation-only-context/resources/remote-environment-scenarios.md +1 -1
  20. package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +98 -6
  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 +24 -11
  24. package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +62 -20
  25. package/assets/skills/coordinator-managing-state-and-lifecycle/SKILL.md +6 -6
  26. package/assets/skills/coordinator-merging-code/SKILL.md +25 -11
  27. package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +28 -7
  28. package/assets/skills/coordinator-plan-reconcile-gate/SKILL.md +3 -3
  29. package/assets/skills/coordinator-rolling-out-to-nodes/SKILL.md +92 -0
  30. package/assets/skills/coordinator-running-autonomous-feature-development/SKILL.md +3 -3
  31. package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +58 -71
  32. package/assets/skills/coordinator-running-review-cycles/SKILL.md +15 -4
  33. package/assets/skills/diagnosing-fleet-and-daemon/SKILL.md +0 -2
  34. package/assets/skills/efficient-multi-agent-research/SKILL.md +6 -7
  35. package/assets/skills/implementer-orchestrating-execution/SKILL.md +11 -14
  36. package/assets/skills/orchestrate/SKILL.md +47 -35
  37. package/assets/skills/persistent-watcher-archetype/SKILL.md +188 -37
  38. package/assets/skills/persistent-watcher-archetype/resources/capture_archive.py +618 -0
  39. package/assets/skills/persistent-watcher-archetype/resources/jev_watcher_filter.py +837 -0
  40. package/assets/skills/persistent-watcher-archetype/resources/roster-watch.sh +1140 -0
  41. package/assets/skills/persistent-watcher-archetype/resources/roster-watch_test.sh +291 -0
  42. package/assets/skills/persistent-watcher-archetype/resources/thrum-capture-fallback.sh +2 -2
  43. package/assets/skills/persistent-watcher-archetype/resources/thrum-watch-pane-capture.sh +20 -8
  44. package/assets/skills/prime-agent/SKILL.md +10 -0
  45. package/assets/skills/project-setup/SKILL.md +22 -16
  46. package/assets/skills/project-setup/resources/implementation-agent.md +56 -35
  47. package/assets/skills/researcher-investigating/SKILL.md +2 -5
  48. package/assets/skills/state-migration/SKILL.md +1 -1
  49. package/assets/skills/thrum/SKILL.md +14 -7
  50. package/assets/skills/thrum/resources/ANTI_PATTERNS.md +16 -18
  51. package/assets/skills/thrum/resources/CLI_REFERENCE.md +17 -11
  52. package/assets/skills/thrum/resources/LISTENER_PATTERN.md +9 -3
  53. package/assets/skills/thrum/resources/MESSAGING.md +18 -11
  54. package/assets/skills/thrum/resources/WORKTREES.md +1 -1
  55. package/assets/skills/thrum-memory/SKILL.md +1 -1
  56. package/assets/skills/trace-spec-to-plan/resources/sweep-agent-prompt.md +1 -1
  57. package/assets/skills/update-queue/SKILL.md +6 -8
  58. package/assets/skills/using-the-dashboard/SKILL.md +30 -0
  59. package/assets/skills/using-the-queue/SKILL.md +76 -5
  60. package/assets/skills/using-thrum-state/SKILL.md +84 -1
  61. package/assets/skills/verify-against-plan/SKILL.md +120 -5
  62. package/assets/skills/watcher-archetype/SKILL.md +18 -0
  63. package/assets/skills/writing-durable-markdown/SKILL.md +5 -0
  64. package/dist/installer.js +4 -4
  65. package/dist/permission-fixture.integration.test.js +4 -4
  66. package/package.json +1 -1
  67. package/assets/skills/coordinator-deploying-the-fleet/SKILL.md +0 -396
  68. package/dist/allowlist-sync.test.d.ts +0 -1
  69. package/dist/allowlist-sync.test.js +0 -44
@@ -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,41 @@ 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 your role preamble's 🔴 PROSE
443
+ INTO A COMMAND rule. `scripts/bd-shared` delivers `--body-file` (and `--stdin`)
444
+ content: it reads the file on YOUR box and pipes those bytes to bd, and an empty
445
+ or blank body is refused loudly. Only `-f`/`--file` and `--graph` (bulk-plan
446
+ files) are refused there. Scratch files go in `/private/tmp` on macOS, where
447
+ `/tmp` is a symlink (check `[ -L /tmp ]`), and in `/tmp` elsewhere.
440
448
 
441
449
  ```bash
442
- cat > /tmp/refactor-epic-desc.md <<'EOF'
450
+ # Scratch dir: /private/tmp on macOS (where /tmp is a symlink), /tmp elsewhere.
451
+ SCRATCH=$([ -L /tmp ] && echo /private/tmp || echo /tmp)
452
+ cat > "$SCRATCH/refactor-epic-desc.md" <<'EOF'
443
453
  Persistent backlog for refactoring, DRY improvements, and code organization
444
454
  opportunities discovered during feature work. Tasks are added by
445
455
  implementation agents as they encounter opportunities. Reviewed and
446
456
  prioritized by the coordinator periodically.
447
457
  EOF
448
- bd create --title="Refactoring & DRY Opportunities" --type=epic --priority=3 -d "$(cat /tmp/refactor-epic-desc.md)"
458
+ bd create --title="Refactoring & DRY Opportunities" --type=epic --priority=3 --body-file "$SCRATCH/refactor-epic-desc.md"
449
459
  ```
450
460
 
451
461
  #### 2. Log the Opportunity
452
462
 
453
- Same `--description` handling as §1 above (scratch file + `-d "$(cat <file>)"`).
463
+ Same `--description` handling as §1 above (scratch file + `--body-file`).
454
464
 
455
465
  ```bash
456
- cat > /tmp/refactor-task-desc.md <<'EOF'
466
+ # Scratch dir: /private/tmp on macOS (where /tmp is a symlink), /tmp elsewhere.
467
+ SCRATCH=$([ -L /tmp ] && echo /private/tmp || echo /tmp)
468
+ cat > "$SCRATCH/refactor-task-desc.md" <<'EOF'
457
469
  **Discovered during:** {{EPIC_ID}}
458
470
  **Files:** <file paths>
459
471
  **Opportunity:** <what could be improved — duplicated code, hardcoded values, missed abstraction>
460
472
  **Suggested approach:** <how to fix it>
461
473
  **Effort estimate:** small/medium/large
462
474
  EOF
463
- bd create --title="Refactor: <short description>" --type=task --parent=<refactoring-epic-id> --priority=3 -d "$(cat /tmp/refactor-task-desc.md)"
475
+ bd create --title="Refactor: <short description>" --type=task --parent=<refactoring-epic-id> --priority=3 --body-file "$SCRATCH/refactor-task-desc.md"
464
476
  ```
465
477
 
466
478
  #### 3. Continue With Your Assigned Work
@@ -494,11 +506,13 @@ If a task is blocked:
494
506
 
495
507
  ```bash
496
508
  # 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.
509
+ # NOTE: --mention @implementer (with no --to) only delivers if "implementer"
510
+ # is itself a registered agent ID — mentions resolve exact agent IDs only, no
511
+ # role fan-out (P0 ruling: removed by design, do not
512
+ # restore). A message with ZERO addressing (no --to, no mentions) routes to
513
+ # the local coordinator instead. There is no broadcast-to-everyone mechanism —
514
+ # --broadcast and @everyone were removed by design; name every recipient
515
+ # explicitly (--to is repeatable for multiple recipients).
502
516
  thrum send --mention @implementer --stdin <<'EOF'
503
517
  BLOCKED: {{TASK_ID}} — waiting for {{BLOCKER_ID}}. Can you prioritize?
504
518
  EOF
@@ -603,18 +617,25 @@ Fix any failures before proceeding. Do not submit broken code for review.
603
617
 
604
618
  ### Step 2: Spec Compliance Review (Stage 1)
605
619
 
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?"
620
+ Verify the implementation covers everything specified in the plan and, when the
621
+ epic has a design doc, in the design doc. Also cross-check each task's
622
+ acceptance criteria against the code: run
623
+ `bd show <task_id>` for every task in the epic and confirm each acceptance
624
+ criterion is met. No code-style judgments at this stage — only "does the code do
625
+ what was asked?"
609
626
 
610
627
  Invoke `verify-against-plan` with these inputs:
611
628
 
612
629
  ```text
613
- /verify-against-plan plan={{PLAN_FILE}} branch={{BRANCH_NAME}}
630
+ /verify-against-plan plan={{PLAN_FILE}} design={{DESIGN_DOC}} branch={{BRANCH_NAME}}
614
631
  ```
615
632
 
633
+ Drop the `design=` input only when this epic has no design doc (`{{DESIGN_DOC}}`
634
+ was left unset). With it, requirements that only the design states are checked
635
+ too, not just the plan's tasks.
636
+
616
637
  The skill produces structured `BLOCKING` / `IMPORTANT` / `MINOR` findings with
617
- plan-reference + file:line evidence.
638
+ plan-reference (or design-reference) + file:line evidence.
618
639
 
619
640
  **When findings come back:**
620
641
 
@@ -643,7 +664,7 @@ results before proceeding). The reviewer is a separate agent — you cannot
643
664
  influence its findings.
644
665
 
645
666
  ```text
646
- Agent(subagent_type="feature-dev:code-reviewer", model="sonnet",
667
+ Agent(subagent_type="feature-dev:code-reviewer", model="<per choosing-subagent-models>",
647
668
  prompt="Review code quality of the implementation on branch {{BRANCH_NAME}}
648
669
  in {{WORKTREE_PATH}}. Focus only on quality of the code that was written —
649
670
  spec compliance is covered separately by verify-against-plan.
@@ -814,7 +835,7 @@ the minimal sequence:
814
835
  cd {{WORKTREE_PATH}}
815
836
  thrum quickstart --name {{AGENT_NAME}} --role implementer --module {{BRANCH_NAME}} --intent "Resuming {{EPIC_ID}}"
816
837
  thrum inbox --unread
817
- # Tip: thrum inbox --unread peeks without marking read; thrum message read --all to mark all read
838
+ # Tip: thrum inbox --unread peeks without marking read; thrum message read --all --force to mark all unread (run `--all` alone first — dry run)
818
839
  # Tip: default page is 10 newest-first — stale unread sorts LAST; use `thrum message search "<term>"` to find it
819
840
 
820
841
  # 2. Orient from beads and git
@@ -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
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: state-migration
3
- description: "Use when your agent-local thrum state is empty AND you have an existing State.md file in your agent directory - this is a ONE-TIME conditional onboarding that fires only on that exact combination. Do NOT use if thrum state already has entries (nothing to migrate) or if you have no State.md (brand-new agent, nothing to migrate). Triggers on: first session after the thrum state redesign lands, `thrum state list` returning empty while State.md exists on disk, being asked to migrate your personal state."
3
+ description: "Use when your agent-local thrum state is empty AND you have an existing State.md file in your agent directory - this is a ONE-TIME conditional onboarding that fires only on that exact combination. Do NOT use if thrum state already has entries (nothing to migrate) or if you have no State.md (brand-new agent, nothing to migrate). Triggers on - first session after the thrum state redesign lands, `thrum state list` returning empty while State.md exists on disk, being asked to migrate your personal state."
4
4
  ---
5
5
 
6
6
  # Migrating personal State.md into `thrum state`
@@ -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
@@ -9,8 +9,11 @@
9
9
  3. **Receive** — `thrum inbox` or `thrum wait` (blocking)
10
10
  4. **Verify sent state** — `thrum sent` or `thrum message get <msg-id>`
11
11
  5. **Read** — Auto-marked read when displayed via `thrum inbox`; use
12
- `thrum inbox --unread` to peek without marking. Explicit:
13
- `thrum message read --all`
12
+ `thrum inbox --unread` to peek without marking. Explicit: `thrum message
13
+ read <id> [<id>...]`, or `thrum message read --all` (DRY RUN — lists
14
+ candidates, marks nothing) then `--apply` (marks the shown/seen ones) or
15
+ `--force` (marks ALL unread, seen or not; needs a fresh `--all` dry run
16
+ first).
14
17
  6. **Search — do not page through the inbox to find old messages.** The
15
18
  default page is 10, newest-first, so stale unread sorts LAST exactly when
16
19
  it has waited longest. Use `thrum message search "<term>"` (full-text,
@@ -22,15 +25,19 @@
22
25
 
23
26
  ## Addressing
24
27
 
25
- | Target | Routing | When to use |
26
- | ------------------- | ------------------------------------------------------------- | ------------------------------------ |
27
- | `--to @lead_agent` | **Direct** — routes to the named agent | Default for all task messages |
28
- | `--to @coordinator` | **Role fanout** — ALL agents with that role (warning emitted) | Only when you want every coordinator |
29
- | `--to @everyone` | **Broadcast** — all registered agents | Critical alerts |
30
-
31
- **Critical:** `@coordinator` is a role, not an agent name. Sending
32
- `--to @coordinator` fans out to every agent registered with that role. Use
33
- `thrum team` to find agent names, then send `--to @<name>` for direct messages.
28
+ | Target | Routing | When to use |
29
+ | ------------------------------ | ------------------------------------------------- | -------------------------------- |
30
+ | `--to @lead_agent` | **Direct** — routes to the named agent | Default for all task messages |
31
+ | `--to @agent_a --to @agent_b` | **Explicit multi-recipient** — repeatable `--to` | Several specific named agents |
32
+
33
+ **(P0 ruling):** one-to-many fan-out — `--broadcast`,
34
+ `@everyone`, and role-based mentions/groups (e.g. `--to @coordinator` fanning
35
+ out to every agent with that role) — was removed by design across the whole
36
+ product. Do not restore it. `--to` and `--mention` only resolve exact agent
37
+ IDs now; a bare role name that is not also an agent ID matches nobody. Use
38
+ `thrum team` to find agent names, then send `--to @<name>` for direct
39
+ messages, or address a scoped agent-type group for a fixed, explicit set of
40
+ recipients.
34
41
 
35
42
  - **Reply:** `thrum reply <msg-id>` — same audience as original; takes **no
36
43
  `--to`** (recipient derived from the message)
@@ -86,7 +86,7 @@ thrum sent # Verifies what this worktree sent and who read it
86
86
  thrum reply <msg-id> --stdin <<'EOF'
87
87
  Integration tests passing, ready to merge
88
88
  EOF
89
- thrum message read --all # Mark all messages as read
89
+ thrum message read --all --force # Mark ALL unread as read (run `read --all` alone first — dry run)
90
90
  ```
91
91
 
92
92
  ## File Coordination
@@ -59,7 +59,7 @@ thrum memory search --tag substrate --kind arch_decision
59
59
  Show a single memory by ID:
60
60
 
61
61
  ```bash
62
- thrum memory show thrum-mem-01HQXZP3V8K2N7M0YJWQ8R5T6F
62
+ thrum memory show thrum-mem-01EXAMPLE00000000000000000
63
63
  ```
64
64
 
65
65
  Edit a single field (other zoom levels stay intact; only changed-zoom embeddings
@@ -1,7 +1,7 @@
1
1
  # Sweep agent — shared instructions
2
2
 
3
3
  > Dispatcher: write this file once, then give each agent ONLY its item list and its report path. Keeps dispatches short and identical.
4
- > **Model:** sonnet · **Effort:** medium. The verdict call needs judgement; the searching does not.
4
+ > **Model and effort:** per `choosing-subagent-models`. The verdict call needs judgement; the searching does not.
5
5
 
6
6
  ---
7
7
 
@@ -20,15 +20,13 @@ never a write to their queue (see the `using-the-queue` skill).
20
20
 
21
21
  ```bash
22
22
  thrum queue list
23
- thrum queue list | awk -F'\t' 'NF>1{print $2}' | sort | uniq -c # status counts
23
+ thrum queue list --json | jq -r '.bundles[].status' | sort | uniq -c # status counts
24
24
  ```
25
25
 
26
26
  Read the whole list yourself. The status counts are the before-number to
27
- reconcile against and report the delta from. `-F'\t'` is load-bearing: bundle
28
- rows are tab-delimited, but `queue list` also prints a space-delimited footer
29
- (`Oldest bundle updated …`) to stdout — under default whitespace splitting that
30
- footer's second word lands in the status tally and corrupts the denominator.
31
- The tab delimiter drops it (footer has no tab ⇒ NF=1).
27
+ reconcile against and report the delta from. Use `--json` for the tally, not
28
+ the text table: the JSON machine surface (`{"bundles": [...]}`) is a stable
29
+ contract, while the text table's column layout and footer line are not.
32
30
 
33
31
  Two staleness classes to expect:
34
32
 
@@ -112,7 +110,7 @@ Give each sub-agent:
112
110
  `merge-base`, `status` ONLY — never `checkout`/`reset`/`restore`/`stash`/
113
111
  `clean`/`rebase`/`commit`/`push`, in any directory; never enter another
114
112
  worktree.
115
- - pinned `model:` (sonnet; intended tier is low for mechanical lookups — the
113
+ - pinned `model:` (per `choosing-subagent-models`; a cheap tier for mechanical lookups — the
116
114
  Agent tool takes no `effort`, so carry the tier via the agent definition or
117
115
  the tmux launch flags).
118
116
 
@@ -135,7 +133,7 @@ on a guess.
135
133
  Re-run the status counts and report the delta:
136
134
 
137
135
  ```bash
138
- thrum queue list | awk -F'\t' 'NF>1{print $2}' | sort | uniq -c
136
+ thrum queue list --json | jq -r '.bundles[].status' | sort | uniq -c
139
137
  ```
140
138
 
141
139
  One line: dropped N, added M, reclassified K; note anything left deliberately
@@ -126,6 +126,36 @@ resubmit — do not recompute the whole board inside one invocation.
126
126
  - HTML files: no script/style/iframe/event-handlers — the render side strips
127
127
  them, but author clean anyway.
128
128
 
129
+ ## Widget schema
130
+
131
+ ```json
132
+ {"title": "<board title>", "widgets": [
133
+ {"id": "hdr", "type": "stat-row", "stats": [{"label": "<label>", "value": "<value>"}]},
134
+ {"id": "rows", "type": "list", "title": "<list title>", "rows": [{"id": "r0", "text": "<one-line markdown>"}]},
135
+ {"id": "note", "type": "card", "title": "<card title>", "body": "<markdown>"},
136
+ {"id": "grp", "type": "section", "label": "<section label>"}
137
+ ]}
138
+ ```
139
+
140
+ - `stat-row` takes `stats`, `list` takes `rows` (each row has its own `id`), `card` takes
141
+ `title` + `body`, `section` takes `label`. Widget `id`s are the upsert key — keep them stable.
142
+ - Write the document to a file; `thrum dashboard set --doc-file <f>`. Pass `--replace` when one
143
+ generator owns the whole board.
144
+ - Regenerate the board from a script that prints one summary line, run from the agent's own
145
+ session. A daemon-spawned monitor process is an unauthenticated caller (identity is
146
+ kernel-verified per process) and cannot write the board, whatever environment it carries, so
147
+ schedule the monitor as a reminder (`--schedule`, `--match`, `--notify-on-success`) and run
148
+ the generator when the reminder arrives. The cron schedule is evaluated in the daemon's local
149
+ time zone, not UTC.
150
+
151
+ ## The board is for the human reader, not an audit trail
152
+
153
+ - Show what the reader needs to decide or know; filter out coordinator mechanics.
154
+ - A "landed since deploy" list shows feature/fix branch landings only — no trunk-sync merges,
155
+ pull merges, or artifact commits.
156
+ - An "orchestrators" view shows each orchestrator's open work, not liveness.
157
+ - When the owner asks for a change, change the generator, not the snapshot.
158
+
129
159
  ## When to reach for the dashboard (vs a nudge vs a message)
130
160
 
131
161
  - **Dashboard:** state the human will consume VISUALLY and possibly answer