opencode-thrum-pro 0.1.6 → 0.1.8

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 (74) hide show
  1. package/assets/commands/thrum-compact-extended.md +36 -21
  2. package/assets/commands/thrum-compact.md +19 -18
  3. package/assets/commands/thrum-restart-extended.md +1 -5
  4. package/assets/commands/thrum-restart.md +2 -2
  5. package/assets/commands/thrum-sleep-extended.md +1 -5
  6. package/assets/commands/thrum-sleep.md +1 -5
  7. package/assets/commands/thrum-update-project.md +1 -1
  8. package/assets/skills/brainstorm-queue-aware/SKILL.md +1 -1
  9. package/assets/skills/brainstorm-steward/SKILL.md +3 -3
  10. package/assets/skills/choosing-subagent-models/SKILL.md +183 -74
  11. package/assets/skills/closing-findings-while-warm/SKILL.md +1 -2
  12. package/assets/skills/configure-roles/SKILL.md +2 -2
  13. package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +11 -10
  14. package/assets/skills/coordinator-branch-split-on-block/SKILL.md +1 -2
  15. package/assets/skills/coordinator-context-monitoring/SKILL.md +11 -12
  16. package/assets/skills/coordinator-deploying-a-node/SKILL.md +3 -1
  17. package/assets/skills/coordinator-dispatching-work/SKILL.md +5 -4
  18. package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +9 -7
  19. package/assets/skills/coordinator-interacting-with-the-owner/SKILL.md +1 -2
  20. package/assets/skills/coordinator-maintaining-memory/SKILL.md +1 -1
  21. package/assets/skills/coordinator-managing-state-and-lifecycle/SKILL.md +10 -3
  22. package/assets/skills/coordinator-merging-code/SKILL.md +21 -14
  23. package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +4 -5
  24. package/assets/skills/coordinator-plan-reconcile-gate/SKILL.md +1 -2
  25. package/assets/skills/coordinator-rolling-out-to-nodes/SKILL.md +1 -0
  26. package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +4 -5
  27. package/assets/skills/coordinator-running-review-cycles/SKILL.md +1 -2
  28. package/assets/{commands/thrum-_deviations-protocol.md → skills/deviations-protocol/SKILL.md} +6 -12
  29. package/assets/skills/efficient-multi-agent-research/SKILL.md +2 -2
  30. package/assets/skills/generator-idempotency-protocol/SKILL.md +9 -0
  31. package/assets/skills/implementer-maintaining-memory/SKILL.md +3 -4
  32. package/assets/skills/implementer-orchestrating-execution/SKILL.md +1 -2
  33. package/assets/skills/implementer-receiving-dispatch/SKILL.md +15 -17
  34. package/assets/skills/implementer-receiving-review-feedback/SKILL.md +3 -4
  35. package/assets/skills/implementer-status-and-handoff/SKILL.md +1 -14
  36. package/assets/skills/implementer-tdd-and-quality/SKILL.md +2 -2
  37. package/assets/skills/memory-audit-recover/SKILL.md +7 -5
  38. package/assets/skills/memory-curate/SKILL.md +3 -3
  39. package/assets/skills/memory-maintenance/SKILL.md +2 -0
  40. package/assets/skills/memory-write-discipline/SKILL.md +1 -1
  41. package/assets/skills/orchestrate/SKILL.md +34 -5
  42. package/assets/skills/persistent-watcher-archetype/SKILL.md +2 -2
  43. package/assets/skills/persistent-watcher-archetype/resources/jev_watcher_filter.py +5 -5
  44. package/assets/skills/persistent-watcher-archetype/resources/roster-watch.sh +5 -5
  45. package/assets/skills/persistent-watcher-archetype/resources/roster-watch_test.sh +2 -2
  46. package/assets/skills/persistent-watcher-archetype/resources/thrum-capture-fallback.sh +1 -1
  47. package/assets/skills/persistent-watcher-archetype/resources/thrum-watch-pane-capture.sh +3 -3
  48. package/assets/skills/prime-agent/SKILL.md +1 -1
  49. package/assets/skills/project-hotpath-gate/SKILL.md +1 -2
  50. package/assets/skills/project-philosophy/SKILL.md +2 -3
  51. package/assets/skills/project-rules-protocol/SKILL.md +12 -0
  52. package/assets/skills/project-setup/SKILL.md +9 -10
  53. package/assets/skills/project-setup/resources/implementation-agent.md +1 -2
  54. package/assets/skills/researcher-answering-queries/SKILL.md +1 -2
  55. package/assets/skills/researcher-investigating/SKILL.md +6 -8
  56. package/assets/skills/researcher-maintaining-memory/SKILL.md +3 -1
  57. package/assets/{commands/thrum-_snapshot-protocol.md → skills/snapshot-protocol/SKILL.md} +10 -15
  58. package/assets/{commands/thrum-_stamp-protocol.md → skills/stamp-protocol/SKILL.md} +5 -6
  59. package/assets/skills/thrum/SKILL.md +9 -4
  60. package/assets/skills/thrum/resources/CLI_REFERENCE.md +32 -27
  61. package/assets/skills/thrum-memory/SKILL.md +1 -1
  62. package/assets/skills/using-monitors/SKILL.md +198 -0
  63. package/assets/skills/using-the-queue/SKILL.md +2 -3
  64. package/assets/skills/using-thrum-state/SKILL.md +3 -3
  65. package/assets/skills/verify-against-plan/SKILL.md +2 -2
  66. package/dist/hooks/block-sync-cd.js +1 -1
  67. package/dist/hooks/block-sync-cd.test.js +1 -1
  68. package/dist/installer-assets.test.d.ts +1 -0
  69. package/dist/installer-assets.test.js +41 -0
  70. package/package.json +1 -1
  71. package/assets/commands/thrum-_compact-runtime-commands.md +0 -61
  72. package/assets/commands/thrum-_generator-idempotency-protocol.md +0 -15
  73. package/assets/commands/thrum-_project-rules-protocol.md +0 -18
  74. package/assets/commands/thrum-_verify-before-write-protocol.md +0 -27
@@ -189,8 +189,10 @@ thrum worktree create <name>
189
189
  thrum tmux create <name> --cwd <worktree-path> \
190
190
  --name <agent_name> --role implementer --module <module> \
191
191
  --mode ephemeral --identity ephemeral \
192
- --model <from runtime.role_models, per choosing-subagent-models>
193
- thrum tmux launch <name> --runtime <runtime> --model <from runtime.role_models, per choosing-subagent-models>
192
+ --model <from runtime.role_models, per choosing-subagent-models> \
193
+ --effort <from runtime.role_models, per choosing-subagent-models>
194
+ thrum tmux launch <name> --runtime <runtime> --model <from runtime.role_models, per choosing-subagent-models> \
195
+ --effort <from runtime.role_models, per choosing-subagent-models>
194
196
  ```
195
197
 
196
198
  > **Implementer lifecycle:** All implementers are ephemeral+stateless (no agent
@@ -233,7 +235,7 @@ That prints the runtime's own footer line, e.g. `Model: <resolved model>`. **Rea
233
235
  intended tier from `.thrum/config.json` → `runtime.role_models`, not from memory.**
234
236
  If the footer shows a different tier (see the BLOCKED note under Step 2 — the model ban
235
237
  list lives in `choosing-subagent-models`), the pin failed silently — re-pin with
236
- `thrum tmux create ... --model <from runtime.role_models, per choosing-subagent-models>` (or
238
+ `thrum tmux create ... --model <from runtime.role_models, per choosing-subagent-models> --effort <from runtime.role_models, per choosing-subagent-models>` (or
237
239
  `thrum agent runtime-config set <agent_name> --model <from runtime.role_models, per choosing-subagent-models>`) and relaunch BEFORE
238
240
  assigning work. **Do not dispatch an unpinned implementer** — the daemon's
239
241
  role-default backstop (`jq -r '.runtime.role_models' .thrum/config.json`) is a
@@ -504,7 +506,7 @@ done
504
506
 
505
507
  **C. If conflicts arise:**
506
508
  Reading the conflicted files directly is permitted (merge-conflict carve-out
507
- in Scope Boundaries). Analyze the conflict using your plan/intent context to
509
+ in the Scope section of your preamble). Analyze the conflict using your plan/intent context to
508
510
  determine the correct resolution. Then spawn a targeted edit sub-agent:
509
511
 
510
512
  ```text
@@ -651,7 +653,7 @@ thrum worktree teardown <name>
651
653
  ```
652
654
 
653
655
  > After set-phase=retired, `thrum team` and the active UI views no longer show
654
- > this agent (sidebar, pickers, badge, kbd-nav). It remains in the Retired tab.
656
+ > this agent (sidebar, pickers, badge, kbd-nav). It remains in the Retired tab (teardown retires, it does not delete the row).
655
657
  > Its messages + runtime transcript persist for audit. `thrum agent delete` is
656
658
  > operator-only (gated to the coordinator) and is NOT an orchestrator tool —
657
659
  > `set-phase retired` is the orchestrator's retirement command for both normal
@@ -805,3 +807,30 @@ EOF
805
807
  ```
806
808
 
807
809
  Do not proceed without approval when autonomy is `per_epic`.
810
+
811
+ ### Tier-swap: replace an underperforming implementer in the same worktree
812
+
813
+ Use when the first review shows multiple BLOCKING findings, systematic misunderstanding of the task, or an agent clearly going long. The swap reuses the SAME worktree: retire the underperforming agent and relaunch a fresh one under a NEW name in place. Never `thrum agent delete` (operator-only, gated to the coordinator; orchestrators are refused). The swapped-out agent is retired with `set-phase retired`; its registry row, messages and transcript are retained.
814
+
815
+ Step 1: kill the old agent's tmux session first, so its pid is dead. A live-pid identity file is preserved and not quarantined; a dead pid lets the new create quarantine it.
816
+ thrum tmux kill <same_worktree_name>
817
+ Step 2: retire the old agent. It keeps the registry row (Retired tab). `set-phase` is not operator-gated. Retiring does not free the identity; Step 4's create does.
818
+ thrum agent set-phase retired --agent <underperforming_agent_name>
819
+ Step 3: verify the worktree is intact (WIP code preserved).
820
+ ls <worktree-path>
821
+ Step 4: launch a fresh ephemeral identity under a NEW name in the SAME worktree, pinned on both create and launch from `runtime.role_models` (per `choosing-subagent-models`). `--intent` carries the orient-from-WIP one-liner.
822
+ thrum tmux create <same_worktree_name> --cwd <worktree-path> --name <new_agent_name> --role implementer --module <module> --mode ephemeral --identity ephemeral --model <per runtime.role_models> --effort <per runtime.role_models> --intent "tier-swap: orient in the worktree (WIP + first-review findings) and continue"
823
+ thrum tmux launch <same_worktree_name> --runtime claude --model <per runtime.role_models> --effort <per runtime.role_models>
824
+ Step 5: deliver the WIP pointer and first-review findings (a cold handoff: the code plus the findings).
825
+ thrum send --to @<new_agent_name> --stdin <<'EOF'
826
+ Tier-swap pickup: <WIP summary + first-review findings>
827
+ EOF
828
+
829
+ The pickup prompt (Step 5) must include:
830
+ You are picking up in-progress work from a prior agent that was replaced.
831
+ Context:
832
+ - Worktree: <path> — contains partial implementation, review it with git diff
833
+ - Task: <epic-id> / <task description>
834
+ - First-review findings from the prior pass:
835
+ <paste the consolidated finding list here>
836
+ - Your goal: address all BLOCKING findings + complete the remaining task scope.
@@ -131,7 +131,7 @@ The procedure, every time, no shortcuts:
131
131
  another peer's panes read-only regardless of capability.
132
132
 
133
133
  **Worked example** — the standard two-variant Claude Code tool-confirmation
134
- modal (`internal/daemon/permission/patterns.go`, pattern `tool_confirmation`,
134
+ modal (the daemon's permission patterns, pattern `tool_confirmation`,
135
135
  dialect `claude-tui`), captured verbatim:
136
136
 
137
137
  ```
@@ -149,7 +149,7 @@ dialect `claude-tui`), captured verbatim:
149
149
  allow-rule beyond this one command; the modal judgment rubric above is a
150
150
  per-command judgment, not a license to mint blanket permissions. This is
151
151
  pinned by `ApproveKey: "1", // Yes (once) — NEVER "2"` in
152
- `internal/daemon/permission/patterns.go` and tested by
152
+ the daemon's permission patterns and tested by
153
153
  `TestApproveKeyNeverForeverAllow`.
154
154
 
155
155
  ## Your own restart (auto-restart-at-ctx-threshold)
@@ -45,8 +45,8 @@ NOTIFY_CLASSES = VALID_CLASSES - {"ordinary"}
45
45
  REDACTION_TOKEN = "[REDACTED_SECRET]"
46
46
  LOCAL_PATH_REDACTION_TOKEN = "[REDACTED_LOCAL_PATH]"
47
47
  SECRET_PATTERNS: tuple[tuple[str, re.Pattern[str]], ...] = (
48
- ("private_key_block", re.compile(r"-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----.*?-----END [A-Z0-9 ]*PRIVATE KEY-----", re.S)),
49
- ("env_secret_assignment", re.compile(r"(?im)^\s*(?:export\s+)?[A-Z0-9_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|AUTH[_-]?KEY)[A-Z0-9_]*\s*=\s*([^\s#]+)")),
48
+ ("private_key_block", re.compile(r"-----BEGIN [0-9A-Z ]*PRIVATE KEY-----.*?-----END [0-9A-Z ]*PRIVATE KEY-----", re.S)),
49
+ ("env_secret_assignment", re.compile(r"(?im)^\s*(?:export\s+)?[0-9A-Z_]*(?:API[_-]?KEY|TOKEN|SECRET|PASSWORD|PRIVATE[_-]?KEY|AUTH[_-]?KEY)[0-9A-Z_]*\s*=\s*([^\s#]+)")),
50
50
  ("bearer_token", re.compile(r"(?i)\bBearer\s+[A-Za-z0-9._~+/=-]{16,}")),
51
51
  ("openai_key", re.compile(r"\bsk-[A-Za-z0-9_-]{20,}\b")),
52
52
  ("thrum_key", re.compile(r"\btskey-[A-Za-z0-9_-]{16,}\b")),
@@ -318,7 +318,7 @@ def prompt_payload(state: dict[str, Any], provider: str = TYPESAFE_PROVIDER) ->
318
318
  },
319
319
  }
320
320
  if provider == OPENROUTER_PROVIDER:
321
- payload["user"] = "thrum-roster-watch-filter"
321
+ payload["user"] = "roster-watch-filter"
322
322
  return payload
323
323
 
324
324
 
@@ -462,8 +462,8 @@ def classify_remote(state: dict[str, Any], provider: str, api_key: str, timeout:
462
462
  }
463
463
  if provider == OPENROUTER_PROVIDER:
464
464
  headers.update({
465
- "HTTP-Referer": "https://github.com/falconleon/thrum",
466
- "X-Title": "thrum-roster-watch-filter",
465
+ "HTTP-Referer": "https://github.com/leonletto/thrum-pro.git",
466
+ "X-Title": "roster-watch-filter",
467
467
  })
468
468
  last_error = None
469
469
  last_category = None
@@ -32,7 +32,7 @@
32
32
  # GHOST-TIP DETECTION: Claude Code's TUI renders an unaccepted inline
33
33
  # autocomplete suggestion in the input box using the literal SGR
34
34
  # "dim/faint" escape code (ESC[2m ... ESC[0m) — confirmed by direct byte
35
- # inspection (2026-08-17, a reconciler agent's "Stop the sweep loop
35
+ # inspection (a reconciler agent's "Stop the sweep loop
36
36
  # for now" tip). Real typed/submitted text never carries that code. `thrum
37
37
  # tmux capture` returns plain text with all styling stripped, so a script
38
38
  # parsing ONLY that output cannot tell a live ghost-tip apart from real
@@ -50,7 +50,7 @@
50
50
  #
51
51
  # REDIRECT FIX (the actual bug this reconciliation targets):
52
52
  # `watch_params.json` lives under the SHARED, redirect-resolved `agents/`
53
- # tree (`internal/paths/paths.go` AgentDir: "the agents/ tree is shared,
53
+ # tree (the AgentDir path helper: "the agents/ tree is shared,
54
54
  # not per-worktree"), not under this script's own worktree. Both source
55
55
  # scripts read it as if it were always reachable via a hardcoded/relative
56
56
  # main-repo path (`cd /Users/you/dev/thrum` +
@@ -60,7 +60,7 @@
60
60
  # feature worktree. `resolve_watch_params()` below replaces that implicit
61
61
  # assumption with the same explicit `.thrum/redirect`-following idiom
62
62
  # already used by `scripts/heartbeat-lib.sh:225-232` and
63
- # `scripts/thrum-check-inbox.sh:25-41`.
63
+ # the check-inbox hook script.
64
64
  #
65
65
  # PORTABILITY FIX: both source scripts also hardcoded a single operator's
66
66
  # absolute paths (`cd /Users/you/dev/thrum`,
@@ -105,7 +105,7 @@ set -uo pipefail
105
105
  # ---------------------------------------------------------------------------
106
106
  # Args: worktree_root. Prints the redirect-resolved absolute .thrum/ dir.
107
107
  # Matches the idiom already used by scripts/heartbeat-lib.sh's
108
- # hb_sessions_dir() and scripts/thrum-check-inbox.sh's SPOOL_THRUM
108
+ # hb_sessions_dir() and the check-inbox hook script's SPOOL_THRUM
109
109
  # resolution: no redirect file present (main repo) -> use the local .thrum/
110
110
  # as-is; redirect file present (feature worktree) -> follow it to the main
111
111
  # repo's .thrum/.
@@ -648,7 +648,7 @@ except: print(0)
648
648
  # entry resolves to a real agent_id via `thrum team --offline --json`, and
649
649
  # log ROSTER-CHECK OK/FAIL. Cheap and valuable regardless of execution
650
650
  # model (catches the exact "bare `<box>`-as-hostname" class of stale-
651
- # roster-entry bug watcher-primary hit 2026-07-24..2026-09-06). Runs AFTER
651
+ # roster-entry bug watcher-primary hit). Runs AFTER
652
652
  # the dynamic roster is loaded from watch_params.json, not against a
653
653
  # hardcoded array.
654
654
  # ---------------------------------------------------------------------------
@@ -69,8 +69,8 @@ AGENT="watcher_primary"
69
69
  # Scenario 1 (MANDATORY, cmain-required regression guard): a worktree that
70
70
  # redirects to a main-repo tree. The "roster-editing agent's Edit-tool write"
71
71
  # lands in the REDIRECT TARGET (main-repo) copy -- that's the physically
72
- # correct, shared, redirect-resolved location per internal/paths/paths.go
73
- # AgentDir ("the agents/ tree is shared, not per-worktree"), and it's what
72
+ # correct, shared, redirect-resolved location per the AgentDir path helper
73
+ # ("the agents/ tree is shared, not per-worktree"), and it's what
74
74
  # resolve_watch_params must read. A worktree-LOCAL copy at the naive,
75
75
  # unresolved path is a decoy: it's what a broken script (SCRIPT_DIR-relative,
76
76
  # no redirect-follow) would read instead, and it must be ignored.
@@ -94,7 +94,7 @@ run_ssh() {
94
94
  }
95
95
 
96
96
  # ssh-add retry: if the SSH hop itself fails at the connection layer (not a
97
- # thrum-level error), the caller's identities may need re-adding to the
97
+ # CLI-level error), the caller's identities may need re-adding to the
98
98
  # keychain-backed ssh-agent. No default keys ship here -- this is a
99
99
  # generic plugin script, and baking in one operator's specific key
100
100
  # filenames would be wrong for every other fleet/operator that copies it.
@@ -74,7 +74,7 @@ AGENT_NAME="$(basename -- "${SCRIPT_DIR}")"
74
74
  REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../../.." >/dev/null 2>&1 && pwd)"
75
75
  # Resolve watch_params.json through .thrum/redirect. The
76
76
  # agents/ tree is the SHARED, redirect-resolved (main-repo) tree, not
77
- # per-worktree (see internal/paths/paths.go AgentDir) -- reading it
77
+ # per-worktree (see the AgentDir path helper) -- reading it
78
78
  # straight off SCRIPT_DIR (this copy's own worktree-local location) reads
79
79
  # the wrong, stale file whenever this script is deployed into a feature
80
80
  # worktree that redirects: a roster-editing agent's Edit-tool write lands
@@ -185,7 +185,7 @@ log "roster: ${ROSTER[*]}"
185
185
  #
186
186
  # NOTE ON THE TWO-STEP TOPOLOGY LOOKUP: `thrum state list --kind topology
187
187
  # --json`'s CLI output does NOT include each entry's `.value` (verified
188
- # against cmd/thrum/state.go's stateListEntry struct, which has no Value
188
+ # against the CLI's stateListEntry struct, which has no Value
189
189
  # field, and confirmed live -- `state list --json` returns only
190
190
  # kind/scope/method/as_of/established_by). Only `state get`/`state show`
191
191
  # emit the full entry including `.value`. So topology resolution is
@@ -338,7 +338,7 @@ for agent in "${ROSTER[@]}"; do
338
338
  STATUS="clean"
339
339
  MATCH_NAME=""
340
340
 
341
- # thrum detect exit-code contract (cmd/thrum/detect.go):
341
+ # thrum detect exit-code contract:
342
342
  # exit 0 + matched entry name on stdout -> match
343
343
  # exit 1, silent -> no match
344
344
  # `if VAR=$(...); then` is exempt from `set -e` semantics for this
@@ -88,7 +88,7 @@ context on a healthy daemon — no turn spent reading a file or running a skill.
88
88
  This skill is the correct choice here only as a **fallback**, when that
89
89
  auto-injection didn't fire or failed (e.g. the hook's "auto-injection failed"
90
90
  notice, daemon unreachable). In that fallback case: read the snapshot first,
91
- then run this skill. See `claude-plugin/commands/compact.md`'s "How resume
91
+ then run this skill. See `/thrum:compact`'s "How resume
92
92
  works" section.
93
93
 
94
94
  ## After Step 2
@@ -23,8 +23,7 @@ later ones.
23
23
  3. **Re-run-evolved** (config present, project has drifted) — compute a
24
24
  sectional diff, present for approval, write only on confirmation.
25
25
 
26
- Read the shared partial at the absolute path:
27
- `claude-plugin/commands/_generator-idempotency-protocol.md`
26
+ Load the /thrum:generator-idempotency-protocol skill and follow it.
28
27
 
29
28
  > **Note: human-in-the-loop required.** This skill uses interactive prompts for
30
29
  > first-run incident-prose seeding and re-run-evolved diff approval. It cannot
@@ -29,8 +29,7 @@ later ones.
29
29
  3. **Re-run-evolved** (doc present, project has drifted) — compute a sectional
30
30
  diff, present via `AskUserQuestion`, write only on confirmation.
31
31
 
32
- Read the shared partial at the absolute path:
33
- `claude-plugin/commands/_generator-idempotency-protocol.md`
32
+ Load the /thrum:generator-idempotency-protocol skill and follow it.
34
33
 
35
34
  > **Note: human-in-the-loop required.** This skill uses `AskUserQuestion` for
36
35
  > first-run project-specific prompts, re-run-evolved diff approval, and
@@ -232,7 +231,7 @@ undetected or unprovided. Fill in:
232
231
 
233
232
  ### Step 6a: MANDATORY — wire the project's security/threat model into the Decision Framework
234
233
 
235
- If the project has a written threat model (search `docs/security_model/`,
234
+ If the project has a written threat model (search the project's security-model directory,
236
235
  `docs/security*.md`, `SECURITY.md`), the rendered philosophy MUST carry a
237
236
  Decision Framework row pointing at it — and that row MUST NOT be keyed on the
238
237
  word "attacker".
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: project-rules-protocol
3
+ description: "Use when loading project-specific rules - shared rule skill for role skills."
4
+ ---
5
+
6
+
7
+ # Project-Specific Rules Protocol
8
+ Project-local rules of kind `agent_rule` at `--scope role` were loaded at
9
+ session start by your preamble (see the memory rules in your role preamble).
10
+ If a project-local rule conflicts with a universal rule above, the
11
+ project-local rule wins; surface the conflict in your reply so the user can
12
+ decide whether to graduate or remove the override.
@@ -50,7 +50,7 @@ describes the artifact in front of you. Parse the binding keys from the
50
50
  **highest-cycle** (last-appended) `stage=plan` line — stamps are only ever
51
51
  appended, never reordered, so `tail -1` is the binding verdict; never `sort`
52
52
  (a `cycle=10` line must beat `cycle=9`, which a lexical sort inverts) — then
53
- re-derive the current values per `_stamp-protocol.md` § "Review-object
53
+ re-derive the current values per `stamp-protocol.md` § "Review-object
54
54
  binding" and compare:
55
55
 
56
56
  ```bash
@@ -95,7 +95,7 @@ Notes on the check:
95
95
  marker. Surface any `THRUM-DEFER` lines still present in the doc as part
96
96
  of the override audit.
97
97
  - **The Deviations block has no override.** Its absence always fails the
98
- gate — see `claude-plugin/commands/_deviations-protocol.md` ("empty must
98
+ gate — see the /thrum:deviations-protocol skill ("empty must
99
99
  be WRITTEN, not omitted").
100
100
  - **`verify=` has no silent-omission path.** A stamp missing `verify=`
101
101
  entirely FAILS this third check exactly like a missing stamp fails the
@@ -117,7 +117,7 @@ Notes on the check:
117
117
  silent-omission path** — a stamp missing `plan_obj`/`src_lock` entirely
118
118
  fails exactly like a missing `verify=` field (fourth check above). The
119
119
  remedy is the same shape as the `verify=` remedy: re-run the plan review so
120
- the stamp is emitted with live binding keys (`_stamp-protocol.md` § "Review-
120
+ the stamp is emitted with live binding keys (`stamp-protocol.md` § "Review-
121
121
  object binding"), or a coordinator adds an explicit `verdict=OVERRIDE`
122
122
  (with `reason=`) to the `stage=plan` line — the SAME auditable escape used
123
123
  for the first check, not a new mechanism. There is no `PREDATES` value for
@@ -260,8 +260,8 @@ components, data flow, and interfaces.
260
260
 
261
261
  ### 🔴 Phase 1a — MANDATORY security-frame check (do this BEFORE decomposing)
262
262
 
263
- **Read the project's threat model** (`docs/security_model/master.md` §1 and §1.2
264
- on thrum; otherwise `docs/security*.md` / `SECURITY.md`) **whenever the plan
263
+ **Read the project's threat model** (its security-model document, or
264
+ `docs/security*.md` / `SECURITY.md`) **whenever the plan
265
265
  contains ANY of the following — and note that NONE of them need name an
266
266
  attacker:**
267
267
 
@@ -476,8 +476,7 @@ template's "Logging Refactoring Opportunities" section.
476
476
  If not found, create one:
477
477
 
478
478
  `--description` is multi-line prose — never double-quoted inline. Use
479
- `--body-file` to pass the content from a file instead; see the role preamble's
480
- 🔴 PROSE INTO A COMMAND rule. `scripts/bd-shared` delivers `--body-file` (and
479
+ `--body-file` to pass the content from a file instead; see the heredoc-or-file rule in your role preamble. `scripts/bd-shared` delivers `--body-file` (and
481
480
  `--stdin`) content: it reads the file on your box and pipes those bytes to bd,
482
481
  and an empty or blank body is refused loudly; only `-f`/`--file` and `--graph`
483
482
  (bulk-plan files) are refused there. Scratch files go in `/private/tmp` on macOS,
@@ -870,11 +869,11 @@ architecture notes specific to this feature:
870
869
 
871
870
  > ⚠️ Verify base before acting: `git diff <sha>..origin/<merge_target> -- <files cited>` -- non-empty ⇒ cited code moved. (Resolve `<merge_target>` through its remote-tracking ref, never a bare local branch name — a local branch of the same name can be stale or absent.)
872
871
 
873
- <!-- Derive stamp per `claude-plugin/commands/_stamp-protocol.md`. -->
872
+ <!-- Derive stamp per the /thrum:stamp-protocol skill. -->
874
873
 
875
874
  ## Deviations from Source
876
875
 
877
- <!-- Derive per `claude-plugin/commands/_deviations-protocol.md` — diff
876
+ <!-- Derive per the /thrum:deviations-protocol skill — diff
878
877
  against the plan/spec, never recall from memory. Required even when
879
878
  empty. -->
880
879
 
@@ -959,7 +958,7 @@ prompt file:
959
958
  ```
960
959
 
961
960
  2. **After the post-setup prompt review terminates `Ready:Yes`**, compute
962
- `prompt_obj`/`plan_lock` per `_stamp-protocol.md` § "Review-object binding"
961
+ `prompt_obj`/`plan_lock` per `stamp-protocol.md` § "Review-object binding"
963
962
  (strip-then-hash the prompt against itself for `prompt_obj`; plain-hash the
964
963
  LOCKED plan for `plan_lock`), then append the verdict stamp:
965
964
 
@@ -439,8 +439,7 @@ bd list --type=epic | grep -i refactor
439
439
  If no refactoring epic exists, create one:
440
440
 
441
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`)
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`)
444
443
  content: it reads the file on YOUR box and pipes those bytes to bd, and an empty
445
444
  or blank body is refused loudly. Only `-f`/`--file` and `--graph` (bulk-plan
446
445
  files) are refused there. Scratch files go in `/private/tmp` on macOS, where
@@ -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
@@ -74,8 +74,8 @@ sessions and re-readable by other agents.
74
74
 
75
75
  **How to apply:** After reporting to the requester, write the finding as a
76
76
  `research_note` memory with cited file:line refs and a verification footer. Tag
77
- with a `research-<slug>` handle so other agents can find it later via
78
- `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>`:
79
79
 
80
80
  ```bash
81
81
  cat > /tmp/research-note-body.md <<EOF
@@ -85,19 +85,18 @@ Verified: $(date +%Y-%m-%d) @ $(git rev-parse HEAD)
85
85
  EOF
86
86
  thrum memory create --kind research_note --scope role \
87
87
  --title "<finding prose, ~80 char soft limit>" \
88
- --tag research-<slug> \
88
+ --tag <slug> \
89
89
  --oneline "<one-line summary>" \
90
90
  --full "@/tmp/research-note-body.md"
91
91
  ```
92
92
 
93
93
  `--full` here is multi-line prose — compose via heredoc or a captured
94
- variable, never double-quoted inline like this; see your role preamble's 🔴
95
- PROSE INTO A COMMAND rule.
94
+ variable, never double-quoted inline like this; see the heredoc-or-file rule in your role preamble.
96
95
 
97
96
  Then add one line to `.thrum/context/research.md` under Tracked Topics (note: `thrum queue` now supersedes free-text Open Questions tracking):
98
97
 
99
98
  ```markdown
100
- - `research-<slug>` — <one-line description, ≤ 80 chars>
99
+ - `<slug>` — <one-line description, ≤ 80 chars>
101
100
  ```
102
101
 
103
102
  The full index format and staleness-check protocol live in
@@ -121,8 +120,7 @@ gaps — you surface them, the implementer ships them.
121
120
 
122
121
  ## Project-specific rules (already loaded)
123
122
 
124
- Read the shared partial at the absolute path:
125
- `claude-plugin/commands/_project-rules-protocol.md`
123
+ Load the /thrum:project-rules-protocol skill and follow it.
126
124
 
127
125
  If you accumulate a new rule mid-session (the user corrects you), capture it via
128
126
  the `researcher-maintaining-memory` skill — it references the
@@ -94,6 +94,8 @@ EOF
94
94
  thrum memory edit <id> --full "@/tmp/memory-verify-body.md"
95
95
  ```
96
96
 
97
+ Re-verifying with `memory edit` needs a license.
98
+
97
99
  ## Staleness check via git diff
98
100
 
99
101
  For research notes that cite specific files, structural staleness review filters
@@ -158,7 +160,7 @@ thrum memory create --kind agent_rule --scope role \
158
160
  ```
159
161
 
160
162
  `--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.
163
+ double-quoted inline; see the heredoc-or-file rule in your role preamble.
162
164
 
163
165
  This is the SAME pattern as coordinator/implementer role-rule writes — see
164
166
  `memory-write-discipline` for the canonical shape.
@@ -1,20 +1,15 @@
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
@@ -71,14 +66,14 @@ shapes everything else you write below it.
71
66
 
72
67
  **Stamp your snapshot with the base it was authored against.**
73
68
  Derive and emit the **Authored-against** stamp per
74
- `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
75
70
  §1 section (that protocol computes the SHA and merge_target for you — never
76
71
  hand-type them). This is what lets `thrum prime` diff your snapshot at the next
77
72
  wake and flag which cited files have MOVED; an unstamped snapshot reads as
78
73
  "current", indistinguishable from one that never drifted.
79
74
 
80
75
  Any commit your snapshot names as its own stamped SHA must also be readable
81
- under `_stamp-protocol.md`'s "Read-time provenance re-derivation" section
76
+ under `stamp-protocol.md`'s "Read-time provenance re-derivation" section
82
77
  (SHA-resolves, then merge-status) — link to that section rather than restating
83
78
  its checks here.
84
79
 
@@ -114,7 +109,7 @@ session's conversation context. Refer to the previous session in third person.
114
109
 
115
110
  ### Choose your structure
116
111
 
117
- 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:
118
113
 
119
114
  - **`/thrum:sleep`** → use the STANDARD 11-section structure below.
120
115
  - **`/thrum:restart-extended` and `/thrum:sleep-extended`** → use the EXTENDED
@@ -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
 
@@ -86,14 +86,19 @@ thrum tmux launch <session> [--runtime <r>] Start runtime in session (REQUIRED
86
86
  ### Monitor Jobs
87
87
 
88
88
  ```bash
89
- thrum monitor add <name> --cmd "..." --on-match "msg" Add a monitored process
90
- thrum monitor list List all monitor jobs
91
- thrum monitor show <name> Show job details and recent matches
89
+ thrum monitor start --name <n> --match <re> --to @agent [--schedule "<cron>"] [--notify-on-success] -- <cmd> [args...]
90
+ thrum monitor list [--all] List monitor jobs (running; --all adds stopped)
91
+ thrum monitor show <name> Show job details
92
+ thrum monitor logs <name> Recent matched lines
93
+ thrum monitor update <name> Change match, schedule, target or debounce in place
92
94
  thrum monitor stop <name> Stop a monitor job
93
- thrum monitor logs <name> Tail job output
95
+ thrum monitor delete <name> Remove a job and free its name
94
96
  thrum monitor restart <name> Restart a stopped job
95
97
  ```
96
98
 
99
+ Reminders, periodic script checks and delivery verification: see the
100
+ `using-monitors` skill.
101
+
97
102
  ### Daemon & Sync
98
103
 
99
104
  ```bash