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.
- package/assets/commands/thrum-compact-extended.md +36 -21
- package/assets/commands/thrum-compact.md +19 -18
- package/assets/commands/thrum-restart-extended.md +1 -5
- package/assets/commands/thrum-restart.md +2 -2
- package/assets/commands/thrum-sleep-extended.md +1 -5
- package/assets/commands/thrum-sleep.md +1 -5
- package/assets/commands/thrum-update-project.md +1 -1
- package/assets/skills/brainstorm-queue-aware/SKILL.md +1 -1
- package/assets/skills/brainstorm-steward/SKILL.md +3 -3
- package/assets/skills/choosing-subagent-models/SKILL.md +183 -74
- package/assets/skills/closing-findings-while-warm/SKILL.md +1 -2
- package/assets/skills/configure-roles/SKILL.md +2 -2
- package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +11 -10
- package/assets/skills/coordinator-branch-split-on-block/SKILL.md +1 -2
- package/assets/skills/coordinator-context-monitoring/SKILL.md +11 -12
- package/assets/skills/coordinator-deploying-a-node/SKILL.md +3 -1
- package/assets/skills/coordinator-dispatching-work/SKILL.md +5 -4
- package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +9 -7
- package/assets/skills/coordinator-interacting-with-the-owner/SKILL.md +1 -2
- package/assets/skills/coordinator-maintaining-memory/SKILL.md +1 -1
- package/assets/skills/coordinator-managing-state-and-lifecycle/SKILL.md +10 -3
- package/assets/skills/coordinator-merging-code/SKILL.md +21 -14
- package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +4 -5
- package/assets/skills/coordinator-plan-reconcile-gate/SKILL.md +1 -2
- package/assets/skills/coordinator-rolling-out-to-nodes/SKILL.md +1 -0
- package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +4 -5
- package/assets/skills/coordinator-running-review-cycles/SKILL.md +1 -2
- package/assets/{commands/thrum-_deviations-protocol.md → skills/deviations-protocol/SKILL.md} +6 -12
- package/assets/skills/efficient-multi-agent-research/SKILL.md +2 -2
- package/assets/skills/generator-idempotency-protocol/SKILL.md +9 -0
- package/assets/skills/implementer-maintaining-memory/SKILL.md +3 -4
- package/assets/skills/implementer-orchestrating-execution/SKILL.md +1 -2
- package/assets/skills/implementer-receiving-dispatch/SKILL.md +15 -17
- package/assets/skills/implementer-receiving-review-feedback/SKILL.md +3 -4
- package/assets/skills/implementer-status-and-handoff/SKILL.md +1 -14
- package/assets/skills/implementer-tdd-and-quality/SKILL.md +2 -2
- package/assets/skills/memory-audit-recover/SKILL.md +7 -5
- package/assets/skills/memory-curate/SKILL.md +3 -3
- package/assets/skills/memory-maintenance/SKILL.md +2 -0
- package/assets/skills/memory-write-discipline/SKILL.md +1 -1
- package/assets/skills/orchestrate/SKILL.md +34 -5
- package/assets/skills/persistent-watcher-archetype/SKILL.md +2 -2
- package/assets/skills/persistent-watcher-archetype/resources/jev_watcher_filter.py +5 -5
- package/assets/skills/persistent-watcher-archetype/resources/roster-watch.sh +5 -5
- package/assets/skills/persistent-watcher-archetype/resources/roster-watch_test.sh +2 -2
- package/assets/skills/persistent-watcher-archetype/resources/thrum-capture-fallback.sh +1 -1
- package/assets/skills/persistent-watcher-archetype/resources/thrum-watch-pane-capture.sh +3 -3
- package/assets/skills/prime-agent/SKILL.md +1 -1
- package/assets/skills/project-hotpath-gate/SKILL.md +1 -2
- package/assets/skills/project-philosophy/SKILL.md +2 -3
- package/assets/skills/project-rules-protocol/SKILL.md +12 -0
- package/assets/skills/project-setup/SKILL.md +9 -10
- package/assets/skills/project-setup/resources/implementation-agent.md +1 -2
- package/assets/skills/researcher-answering-queries/SKILL.md +1 -2
- package/assets/skills/researcher-investigating/SKILL.md +6 -8
- package/assets/skills/researcher-maintaining-memory/SKILL.md +3 -1
- package/assets/{commands/thrum-_snapshot-protocol.md → skills/snapshot-protocol/SKILL.md} +10 -15
- package/assets/{commands/thrum-_stamp-protocol.md → skills/stamp-protocol/SKILL.md} +5 -6
- package/assets/skills/thrum/SKILL.md +9 -4
- package/assets/skills/thrum/resources/CLI_REFERENCE.md +32 -27
- package/assets/skills/thrum-memory/SKILL.md +1 -1
- package/assets/skills/using-monitors/SKILL.md +198 -0
- package/assets/skills/using-the-queue/SKILL.md +2 -3
- package/assets/skills/using-thrum-state/SKILL.md +3 -3
- package/assets/skills/verify-against-plan/SKILL.md +2 -2
- package/dist/hooks/block-sync-cd.js +1 -1
- package/dist/hooks/block-sync-cd.test.js +1 -1
- package/dist/installer-assets.test.d.ts +1 -0
- package/dist/installer-assets.test.js +41 -0
- package/package.json +1 -1
- package/assets/commands/thrum-_compact-runtime-commands.md +0 -61
- package/assets/commands/thrum-_generator-idempotency-protocol.md +0 -15
- package/assets/commands/thrum-_project-rules-protocol.md +0 -18
- package/assets/commands/thrum-_verify-before-write-protocol.md +0 -27
|
@@ -255,7 +255,7 @@ Flags:
|
|
|
255
255
|
--runtime string Runtime preset: claude, codex, cursor, gemini, opencode, auggie, cli-only
|
|
256
256
|
--preamble-file string Custom preamble file to compose with default preamble
|
|
257
257
|
--no-init Skip runtime config generation, just register agent
|
|
258
|
-
--force
|
|
258
|
+
--force Force runtime config reinitialization; project instruction files are preserved
|
|
259
259
|
--dry-run Preview changes without writing files or registering
|
|
260
260
|
--no-agent-pid Persist agent_pid=0 instead of detecting the runtime ancestor; defers PID claim to first /thrum:prime (used for inline tmux quickstart)
|
|
261
261
|
```
|
|
@@ -379,6 +379,10 @@ thrum agent delete <name>
|
|
|
379
379
|
thrum agent delete coordinator_1B9K --force
|
|
380
380
|
```
|
|
381
381
|
|
|
382
|
+
Refuses an agent whose linked worktree still exists (run `worktree teardown`
|
|
383
|
+
first), a live pid/tmux process, and coordinators. Order: teardown (with
|
|
384
|
+
salvage), then delete.
|
|
385
|
+
|
|
382
386
|
Flags:
|
|
383
387
|
|
|
384
388
|
```text
|
|
@@ -858,7 +862,7 @@ thrum tmux cancel <command-id> # Cancel a queued or active comma
|
|
|
858
862
|
--intent string Initial work intent description
|
|
859
863
|
--runtime string Runtime preset: claude, codex, cursor, gemini, opencode, auggie
|
|
860
864
|
--no-agent Skip agent registration (create session only)
|
|
861
|
-
--force
|
|
865
|
+
--force Re-register even if agent exists; kill and recreate an existing session
|
|
862
866
|
```
|
|
863
867
|
|
|
864
868
|
Without `--no-agent`, the command errors if `--name`, `--role`, and `--module`
|
|
@@ -900,7 +904,7 @@ thrum worktree create <name> --detach # Detached HEAD worktree
|
|
|
900
904
|
thrum worktree create <name> \
|
|
901
905
|
--name <agent> --role <role> --module <mod> # Create worktree + register agent
|
|
902
906
|
thrum worktree setup <name> # Alias for worktree create
|
|
903
|
-
thrum worktree teardown <name> #
|
|
907
|
+
thrum worktree teardown <name> # Retire agent + remove worktree, keep branch (does NOT delete the agent; reap with `thrum agent delete` after)
|
|
904
908
|
thrum worktree teardown <name> --delete-branch # Also delete the worktree's branch
|
|
905
909
|
thrum worktree list # List worktrees with agent info
|
|
906
910
|
```
|
|
@@ -939,51 +943,52 @@ later.
|
|
|
939
943
|
|
|
940
944
|
## Monitor Jobs
|
|
941
945
|
|
|
942
|
-
Run a
|
|
943
|
-
|
|
944
|
-
|
|
946
|
+
Run a command, filter its output through a regex, and deliver matching lines as
|
|
947
|
+
Thrum messages. Without `--schedule` the command runs continuously and restarts
|
|
948
|
+
with backoff; with `--schedule` it runs once per cron tick. Jobs persist across
|
|
949
|
+
daemon restarts. Max 100 concurrent. The command must follow `--`.
|
|
945
950
|
|
|
946
951
|
```bash
|
|
947
952
|
thrum monitor start --name <n> --match <re> --to @agent -- <cmd> [args...]
|
|
948
953
|
thrum monitor start --name <n> --match <re> --to @agent \
|
|
949
|
-
--debounce 120s --env KEY=VALUE -- <cmd>
|
|
954
|
+
--schedule "*/5 * * * *" --notify-on-success --debounce 120s --env KEY=VALUE -- <cmd>
|
|
950
955
|
thrum monitor list # Running jobs only
|
|
951
956
|
thrum monitor list --all # Include stopped/dead (<1 week)
|
|
952
957
|
thrum monitor show <id|name> # Full detail (env values redacted)
|
|
953
|
-
thrum monitor
|
|
954
|
-
thrum monitor
|
|
955
|
-
thrum monitor
|
|
958
|
+
thrum monitor logs <id|name> -n 50 # Last 50 matched lines (default 20)
|
|
959
|
+
thrum monitor update <id|name> --match <re> # Change match/schedule/target/debounce in place
|
|
960
|
+
thrum monitor stop <id|name> # SIGTERM, 5s, SIGKILL
|
|
956
961
|
thrum monitor restart <id|name> # Restart dead/stopped monitor
|
|
962
|
+
thrum monitor delete <id|name> # Remove the record and free the name
|
|
963
|
+
thrum monitor adopt <id|name> # Claim a monitor for this daemon
|
|
957
964
|
```
|
|
958
965
|
|
|
959
|
-
|
|
966
|
+
`monitor add` is an alias for `monitor start`.
|
|
960
967
|
|
|
961
968
|
`monitor start` flags:
|
|
962
969
|
|
|
963
970
|
```text
|
|
964
971
|
--name string Unique monitor name (required)
|
|
965
|
-
--match string Regex pattern
|
|
972
|
+
--match string Regex pattern - matching lines trigger a message (required)
|
|
966
973
|
--to string Target agent or group, e.g. @coordinator (required)
|
|
967
|
-
--
|
|
968
|
-
--
|
|
974
|
+
--schedule string 5-field cron expression; runs the command once per tick
|
|
975
|
+
--notify-on-success Deliver a generic [OK] message for a successful run in which no line matched
|
|
976
|
+
--debounce duration Leading-edge debounce window, minimum 30s (default 1m)
|
|
977
|
+
--env stringArray Environment variable in KEY=VALUE form (repeatable)
|
|
969
978
|
--cwd string Working directory for the command (default: current dir)
|
|
970
979
|
```
|
|
971
980
|
|
|
972
|
-
`monitor
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
```
|
|
981
|
+
`monitor update` flags: `--match`, `--to`, `--schedule`, `--debounce`.
|
|
982
|
+
`--schedule` changes the cron of a scheduled monitor at any time; setting or
|
|
983
|
+
removing a schedule switches the mode, which is refused while the monitor is
|
|
984
|
+
running and allowed while it is stopped.
|
|
977
985
|
|
|
978
|
-
`monitor logs`
|
|
979
|
-
|
|
980
|
-
```text
|
|
981
|
-
-n, --limit int Max number of matches to return (default 20)
|
|
982
|
-
```
|
|
986
|
+
`monitor logs` flag: `-n, --limit int` (default 20).
|
|
983
987
|
|
|
984
|
-
Key constraints: local Unix socket only,
|
|
985
|
-
|
|
986
|
-
|
|
988
|
+
Key constraints: local Unix socket only, lines over 2KB are truncated with a
|
|
989
|
+
marker, one matching line is delivered per debounce window, and a message is
|
|
990
|
+
sent when the child exits non-zero. See the `using-monitors` skill for
|
|
991
|
+
reminders, script checks and delivery rules.
|
|
987
992
|
|
|
988
993
|
---
|
|
989
994
|
|
|
@@ -70,7 +70,7 @@ thrum memory edit <id> --short @newshort.md
|
|
|
70
70
|
thrum memory edit <id> --add-tag v0.11 --rm-tag draft
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
Link an edge
|
|
73
|
+
Link an edge. `memory create`, `edit` and `link` need a license (memory.substrate); reads, `delete`, `purge` and `unlink` do not.
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
76
|
thrum memory link <new-id> supersedes <old-id>
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: using-monitors
|
|
3
|
+
description: "Use when scheduling a reminder, watching a log, or running a periodic check that must reach an agent - thrum monitor start, cron --schedule, --match, --notify-on-success, --debounce, recurring nudge, script check with exit codes, why a monitor message did not arrive, how to verify a monitor delivered."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Thrum Monitors - Reminders And Script Checks
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
A monitor runs a command, keeps the output lines that match a regex, and
|
|
11
|
+
delivers them as Thrum messages to a target: a continuous monitor sends each
|
|
12
|
+
kept line, a scheduled monitor sends all the lines of a run in one message. With
|
|
13
|
+
`--schedule` it runs the command once per cron tick; without it the command runs continuously
|
|
14
|
+
and restarts with backoff when it exits. Monitors persist across daemon
|
|
15
|
+
restarts and run only on the daemon that owns them.
|
|
16
|
+
|
|
17
|
+
Every flag below appears in `thrum monitor start --help`. Re-read the help
|
|
18
|
+
before relying on a flag not listed here.
|
|
19
|
+
|
|
20
|
+
## Command Surface
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
thrum monitor start --name <n> --match <re> --to @agent [--schedule "<cron>"] \
|
|
24
|
+
[--notify-on-success] [--debounce 60s] [--env K=V] [--cwd <dir>] -- <cmd> [args...]
|
|
25
|
+
thrum monitor list [--all]
|
|
26
|
+
thrum monitor show <name|id>
|
|
27
|
+
thrum monitor logs <name|id> [-n 50]
|
|
28
|
+
thrum monitor update <name|id> [--match <re>] [--to <t>] [--debounce <d>] [--schedule "<cron>"]
|
|
29
|
+
thrum monitor stop <name|id>
|
|
30
|
+
thrum monitor restart <name|id>
|
|
31
|
+
thrum monitor delete <name|id>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- `--name`, `--match` and `--to` are required; the command follows `--`.
|
|
35
|
+
- `--schedule` takes a 5-field cron expression. `update --schedule` changes the
|
|
36
|
+
cron of a scheduled monitor at any time. Setting a first schedule or removing
|
|
37
|
+
it (`--schedule ""`) switches the mode, which is refused while the monitor is
|
|
38
|
+
running and allowed while it is stopped.
|
|
39
|
+
- `--debounce` is leading-edge with a 30s minimum (default 1m).
|
|
40
|
+
- `stop` leaves a stopped record that still holds the name; `delete` frees the
|
|
41
|
+
name. Use a unique name per monitor.
|
|
42
|
+
|
|
43
|
+
## What Is Delivered
|
|
44
|
+
|
|
45
|
+
Each output line is tested against `--match` on its own. A line is truncated at
|
|
46
|
+
2048 bytes with a marker appended.
|
|
47
|
+
|
|
48
|
+
A scheduled (`--schedule`) job is a one-shot run, so its exit code is
|
|
49
|
+
authoritative. It delivers ONE message at exit that carries every matched line,
|
|
50
|
+
in order. A continuous job has no exit code per line, so it classifies and
|
|
51
|
+
delivers and classifies each matched line on its own, by its words.
|
|
52
|
+
|
|
53
|
+
| Scheduled job | Delivered as |
|
|
54
|
+
| --------------------------------------------------------------- | --------------------------------------------- |
|
|
55
|
+
| Non-zero exit, or the command failed to start | `[FAIL] <name>: exit code N` with the output tail, then the matched lines |
|
|
56
|
+
| Exit 0, a matched line starts `ERROR:`, `FATAL:` or `FAIL:` | `[FAIL] <name>: matched error pattern` + all matched lines |
|
|
57
|
+
| Exit 0, highest prefix is `WARN:`, `WARNING:` or `ALERT:` | `[WARN] <name>: matched WARNING` + all matched lines |
|
|
58
|
+
| Exit 0, lines matched, no such prefix | All matched lines, in order, verbatim |
|
|
59
|
+
| Exit 0, nothing matched, `--notify-on-success` | `[OK] <name>: succeeded` |
|
|
60
|
+
| Exit 0, nothing matched | Nothing (logged only) |
|
|
61
|
+
|
|
62
|
+
Cadence: the first non-zero scheduled run sends its `[FAIL]` notice; repeats of
|
|
63
|
+
that failure are not sent again until the outcome changes or the re-escalation
|
|
64
|
+
interval (30 minutes) passes. An exit-0 run that matched lines sends its message
|
|
65
|
+
on every run.
|
|
66
|
+
|
|
67
|
+
On a scheduled job only these prefixes, at the very start of a line, label the
|
|
68
|
+
output, with the colon directly after the word: `ERROR:`, `FATAL:` and `FAIL:`
|
|
69
|
+
fail it; `WARN:`, `WARNING:` and `ALERT:` warn. Any other prefix, including
|
|
70
|
+
`ALERT-<NAME>:`, `ERROR :`, `INFO:`, `OK:`, `NOT_OK:` and lowercase forms, is
|
|
71
|
+
neutral. They are read before any wording in the body, and
|
|
72
|
+
the highest one decides the label. Words such as `done`, `ok`, `complete`, `failures` or `error` neither
|
|
73
|
+
drop nor relabel a line, and `WARN: batch not complete` stays a warning.
|
|
74
|
+
`--notify-on-success` adds the generic `[OK]` only for a run in which nothing
|
|
75
|
+
matched; an empty matched line counts as a match and is announced as
|
|
76
|
+
`[matched N empty line(s)]`.
|
|
77
|
+
|
|
78
|
+
The whole message, including its label and framing, never exceeds the daemon's
|
|
79
|
+
configured message-body limit. Matched lines are sent whole while they fit both
|
|
80
|
+
budgets: the in-memory retention budget (each line costs its bytes plus a small
|
|
81
|
+
fixed overhead, so a line close to the limit, or many short lines, can be cut
|
|
82
|
+
or omitted earlier than their plain total would suggest) and the final rendered
|
|
83
|
+
message including its label. Lines that do not fit are replaced by `[N more
|
|
84
|
+
matched lines omitted]`, and a first line that does not fit is cut and
|
|
85
|
+
marked. The limit is never below 1024 bytes (the configuration floor), enough for
|
|
86
|
+
the framing and an omission marker with ordinary job names; when variable
|
|
87
|
+
framing such as a very long job name does not fit, the monitor sends a bounded
|
|
88
|
+
summary that starts with `+N omitted` instead of the lines. A run keeps only a bounded prefix of its lines in memory (at most
|
|
89
|
+
the delivery limit, or 1 MiB when the limit is disabled, counting a small fixed
|
|
90
|
+
overhead per line) but
|
|
91
|
+
counts every match, so the omitted count is exact and an `ERROR:`/`WARN:` line
|
|
92
|
+
past the retained prefix still sets the label.
|
|
93
|
+
|
|
94
|
+
| Continuous job (no `--schedule`) | Delivered as |
|
|
95
|
+
| --------------------------------------------------------------- | --------------------------------------------- |
|
|
96
|
+
| Contains `error`, `fatal`, `fail`, `permission denied` | `[FAIL] <name>: matched error pattern` + line |
|
|
97
|
+
| Contains `warn` or `warning` | `[WARN] <name>: matched WARNING` + line |
|
|
98
|
+
| Contains a whole word `success`, `succeeded`, `complete`, `completed`, `done`, `ok` | Not delivered (logged only) |
|
|
99
|
+
| Any other matched line | The line, verbatim |
|
|
100
|
+
|
|
101
|
+
A continuous job checks a line for a negated completion word (`not complete`)
|
|
102
|
+
first, then for a level prefix (`ERROR:`, `WARN:`, `INFO:`, optionally after a
|
|
103
|
+
timestamp), then for the words above. Tokens such as `fail=0` are not failures;
|
|
104
|
+
the phrase `0 errors` still contains `error`.
|
|
105
|
+
|
|
106
|
+
Delivery limits:
|
|
107
|
+
|
|
108
|
+
- A continuous job delivers the first matching line in each debounce window at
|
|
109
|
+
once and holds later ones for a trailing summary. A scheduled job has no
|
|
110
|
+
debounce; its lines are aggregated as above.
|
|
111
|
+
- The `[FAIL]` body for a non-zero exit carries only the last 500 bytes of
|
|
112
|
+
output, so the message that matters goes last.
|
|
113
|
+
|
|
114
|
+
## Prompt-Only Reminder
|
|
115
|
+
|
|
116
|
+
A reminder is a monitor whose command only prints a fixed line. Give the line a
|
|
117
|
+
stable prefix and match exactly that prefix.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
thrum monitor start --name standup-nudge --to @me \
|
|
121
|
+
--match '^REMINDER-STANDUP:' --schedule "0 9 * * 1-5" -- \
|
|
122
|
+
echo "REMINDER-STANDUP: post the status update, then reply to the open review"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- Schedule the reminder; words in its text, including "failures", "error" and
|
|
126
|
+
"done", then neither relabel nor drop it, and the exit code decides success.
|
|
127
|
+
- Make the body an instruction with the next concrete step; a bare "reminder"
|
|
128
|
+
carries no action.
|
|
129
|
+
- Add `--notify-on-success` only when a delivered line must be guaranteed for a
|
|
130
|
+
run that matched nothing.
|
|
131
|
+
- A delivered reminder shows the schedule fired. It does not show that the work
|
|
132
|
+
moved. Check the work itself (commits, queue, state) before treating the
|
|
133
|
+
reminder as progress.
|
|
134
|
+
|
|
135
|
+
## Script Check
|
|
136
|
+
|
|
137
|
+
A script check runs a bounded, synchronous probe and reports through its exit
|
|
138
|
+
code and one structured line.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
thrum monitor start --name disk-check --to @me \
|
|
142
|
+
--match '^CHECK-DISK:' --schedule "*/15 * * * *" -- \
|
|
143
|
+
bash -c 'u=$(df --output=pcent / | tail -1 | tr -dc 0-9)
|
|
144
|
+
[ "$u" -lt 90 ] && exit 0
|
|
145
|
+
echo "CHECK-DISK: root volume at ${u} percent used, free space then rerun df -h /"
|
|
146
|
+
exit 3'
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Rules:
|
|
150
|
+
|
|
151
|
+
1. Bound every probe with `timeout <secs>`; a hung probe holds the tick.
|
|
152
|
+
2. Exit 0 for healthy and print nothing matching, which keeps the run quiet.
|
|
153
|
+
3. Exit non-zero for a failure; the daemon sends the `[FAIL]` notice with the
|
|
154
|
+
exit code and output tail.
|
|
155
|
+
4. Print a matching line that names the subject, the observed value and the
|
|
156
|
+
next action. A generic `OK` or `done` line carries no information.
|
|
157
|
+
5. Use a distinct stable prefix per outcome (`CHECK-DISK:` for a finding,
|
|
158
|
+
`REMINDER-DISK:` for a nudge) so `--match` selects what must reach the
|
|
159
|
+
target.
|
|
160
|
+
|
|
161
|
+
| Outcome | Script does | Target receives |
|
|
162
|
+
| -------- | ---------------------------------------- | ---------------------------------- |
|
|
163
|
+
| Quiet | Exit 0, no matching line | Nothing |
|
|
164
|
+
| Failure | Non-zero exit, finding line last | One `[FAIL] <name>: exit code N` message with the tail and the finding line |
|
|
165
|
+
| Finding | Exit 0, matching line(s) | The line(s), verbatim (labeled only by an `ERROR:`/`FATAL:`/`FAIL:` or `WARN:`/`WARNING:`/`ALERT:` prefix) |
|
|
166
|
+
| Reminder | Exit 0, one stable-prefix instruction | The line, verbatim |
|
|
167
|
+
|
|
168
|
+
A `--match` that never matches the script's real output delivers nothing and
|
|
169
|
+
raises no error. Test the regex against the exact output before starting.
|
|
170
|
+
|
|
171
|
+
## Verify By Delivery
|
|
172
|
+
|
|
173
|
+
Start the monitor with a unique name, `--to` the verifying agent, and a
|
|
174
|
+
one-minute schedule, then read the delivered message back in full.
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
thrum monitor start --name verify-<unique> --to @me --match '^VERIFY-<unique>:' \
|
|
178
|
+
--schedule "* * * * *" -- echo "VERIFY-<unique>: delivery body check"
|
|
179
|
+
thrum inbox --unread
|
|
180
|
+
thrum message get <message-id> # the complete delivered body
|
|
181
|
+
thrum monitor logs verify-<unique> # the matches the daemon recorded
|
|
182
|
+
thrum monitor delete verify-<unique>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Confirm the body carries the prefix, the wording and no unexpected `[FAIL]`
|
|
186
|
+
or `[WARN]` label. Delete the monitor when done; never alter a monitor another
|
|
187
|
+
agent owns.
|
|
188
|
+
|
|
189
|
+
## Troubleshooting
|
|
190
|
+
|
|
191
|
+
- Nothing arrived: `thrum monitor show` for state and last exit, `thrum
|
|
192
|
+
monitor logs` for recorded matches. No recorded match means the regex did not
|
|
193
|
+
match, or (continuous job) the line was completion-classified and suppressed;
|
|
194
|
+
run the command by hand and compare its output with the regex.
|
|
195
|
+
- Message labeled `[FAIL]` unexpectedly: the job exited non-zero, the line starts
|
|
196
|
+
with `ERROR:`/`FATAL:`/`FAIL:`, or (continuous job) the line contains a fail or
|
|
197
|
+
error substring.
|
|
198
|
+
- Name already in use: a stopped record holds it. `thrum monitor delete` it.
|
|
@@ -191,7 +191,7 @@ so this wrapper is defense-in-depth, not load-bearing on its own.
|
|
|
191
191
|
non-peercred transport (browser/WS, unit tests) - but that is a general,
|
|
192
192
|
already-documented property of the RPC layer (identity trust depends on
|
|
193
193
|
transport), not something unique to `state.set`, and it is explicitly out
|
|
194
|
-
of scope per
|
|
194
|
+
of scope per the project's security model: "Thrum does not attempt
|
|
195
195
|
to prevent agent identity forgery" is an owner ruling, stated as
|
|
196
196
|
[INTENDED] and permanent, not tracked as debt.
|
|
197
197
|
|
|
@@ -204,8 +204,7 @@ shapes, chosen by domain, not an oversight.
|
|
|
204
204
|
|
|
205
205
|
Non-goal: fail-closed reject-symmetry for `state.set` (mirroring queue's
|
|
206
206
|
`RejectIdentityKeysHandler`) is a possible future non-security hardening
|
|
207
|
-
preference, not built here - out of scope per
|
|
208
|
-
§1.5.
|
|
207
|
+
preference, not built here - out of scope per the project's security model.
|
|
209
208
|
|
|
210
209
|
## Common Mistakes
|
|
211
210
|
|
|
@@ -42,8 +42,8 @@ time** — writing a fleet row without a fresh by-effect check, even to
|
|
|
42
42
|
## Reconcile, don't just read
|
|
43
43
|
|
|
44
44
|
- **Agent-local** (all roles): check at session start
|
|
45
|
-
(`thrum state list`), update as you go.
|
|
46
|
-
|
|
45
|
+
(`thrum state list`), update as you go. Prime injects only a capped digest
|
|
46
|
+
of agent-local state; `thrum state list` shows all.
|
|
47
47
|
- **Fleet** (coordinators write; everyone reads): before citing a fleet
|
|
48
48
|
fact in a decision, check `as_of`/`method`. Past the kind's threshold
|
|
49
49
|
(`thrum state describe <kind>`)? Re-verify by effect before acting, or
|
|
@@ -73,7 +73,7 @@ yourself.
|
|
|
73
73
|
|
|
74
74
|
## Field Mutability Matrix
|
|
75
75
|
|
|
76
|
-
`Entry`
|
|
76
|
+
The state `Entry` type has five mutability classes, not one
|
|
77
77
|
uniform "immutable field" guard:
|
|
78
78
|
|
|
79
79
|
- **immutable-identity** — part of the `(Kind, Scope)` addressing key, or
|
|
@@ -104,7 +104,7 @@ clear error — do not proceed with partial inputs.
|
|
|
104
104
|
Regex: `^\*\*Authored-against:\*\* \`([0-9a-f]+)\` target: \`([^\`]+)\``
|
|
105
105
|
(sha → capture group 1, merge_target → capture group 2)
|
|
106
106
|
|
|
107
|
-
(Canonical stamp definition:
|
|
107
|
+
(Canonical stamp definition: the /thrum:stamp-protocol skill. The
|
|
108
108
|
stamp follows the same literal `grep -F` / fixed-field-order / case-sensitive /
|
|
109
109
|
ASCII-only convention as the `THRUM-REVIEW` marker — see
|
|
110
110
|
`coordinator-running-brainstorm-cycles` skill § "Footer → commit → stamp".)
|
|
@@ -158,7 +158,7 @@ clear error — do not proceed with partial inputs.
|
|
|
158
158
|
present" outcome above, since this check only needs the stamp's
|
|
159
159
|
`<sha>`/`<merge_target>`, not the plan's cited-files list. Run the
|
|
160
160
|
ordered, short-circuiting two-check sequence defined canonically in
|
|
161
|
-
`
|
|
161
|
+
`stamp-protocol.md` § "Read-time provenance re-derivation" (SHA-resolves
|
|
162
162
|
first, then merge-status) against the stamp's `<sha>`/`<merge_target>` —
|
|
163
163
|
the exact commands live there as the single source of truth; this section
|
|
164
164
|
states outcomes and severity only:
|
|
@@ -29,7 +29,7 @@ const SYNC = String.raw `\.git/thrum-sync/a-sync`;
|
|
|
29
29
|
// Command-position anchor: line start or immediately after a shell separator
|
|
30
30
|
// (;, &&, ||), then optional whitespace. This matches `cd`/`git` only when they
|
|
31
31
|
// are the actual command — NOT when those words appear inside a quoted argument
|
|
32
|
-
// preceded by a bare space (the
|
|
32
|
+
// preceded by a bare space (the quoted-argument false-positive: `bd remember "... cd
|
|
33
33
|
// .git/thrum-sync/a-sync ..."` must NOT be denied). Match op-shape, not the mere
|
|
34
34
|
// presence of the path string.
|
|
35
35
|
const CMDPOS = String.raw `(^|;|&&|\|\|)\s*`;
|
|
@@ -31,7 +31,7 @@ const ALLOW = [
|
|
|
31
31
|
["git -C a-sync push", `git -C ${ASYNC} push`],
|
|
32
32
|
["git -C a-sync log (not branch-changing)", `git -C ${ASYNC} log --oneline`],
|
|
33
33
|
["ls the path", `ls ${ASYNC}/`],
|
|
34
|
-
//
|
|
34
|
+
// quoted-argument false-positive guard: cd inside a quoted argument (bare space before it),
|
|
35
35
|
// not at command position -> must be ALLOWED.
|
|
36
36
|
["quoted cd inside bd remember", `bd remember "note: do not cd ${ASYNC} directly"`],
|
|
37
37
|
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Tests for installAssets skills/commands staging (o4jgf MINOR 13):
|
|
2
|
+
// expected content lands on first install, and the version gate makes a
|
|
3
|
+
// second install a no-op. Offline/deterministic: temp XDG_CONFIG_HOME,
|
|
4
|
+
// stub ctx, real asset tree, never the real $HOME or network.
|
|
5
|
+
//
|
|
6
|
+
// Run: npm test (builds, then `node --test dist`)
|
|
7
|
+
import { test } from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import os from "os";
|
|
11
|
+
import path from "path";
|
|
12
|
+
import { getConfigDir, installAssets } from "./installer.js";
|
|
13
|
+
function stubCtx() {
|
|
14
|
+
return { client: { app: { log: async () => { } } } };
|
|
15
|
+
}
|
|
16
|
+
test("installAssets stages skills and commands; version gate skips reinstall", async () => {
|
|
17
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "thrum-oc-install-"));
|
|
18
|
+
const prevXdg = process.env.XDG_CONFIG_HOME;
|
|
19
|
+
process.env.XDG_CONFIG_HOME = tmp;
|
|
20
|
+
try {
|
|
21
|
+
await installAssets(stubCtx());
|
|
22
|
+
const cfg = path.join(tmp, "opencode");
|
|
23
|
+
assert.equal(getConfigDir(), cfg);
|
|
24
|
+
// protocol skills ride the wholesale skills copy (o4jgf item 5)
|
|
25
|
+
const skillFile = path.join(cfg, "skills", "snapshot-protocol", "SKILL.md");
|
|
26
|
+
assert.ok(fs.existsSync(skillFile));
|
|
27
|
+
assert.ok(fs.existsSync(path.join(cfg, "commands", "thrum-sleep.md")));
|
|
28
|
+
const mtimeBefore = fs.statSync(skillFile).mtimeMs;
|
|
29
|
+
await installAssets(stubCtx());
|
|
30
|
+
assert.equal(fs.statSync(skillFile).mtimeMs, mtimeBefore);
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
if (prevXdg === undefined) {
|
|
34
|
+
delete process.env.XDG_CONFIG_HOME;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
process.env.XDG_CONFIG_HOME = prevXdg;
|
|
38
|
+
}
|
|
39
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
40
|
+
}
|
|
41
|
+
});
|
package/package.json
CHANGED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description:
|
|
3
|
-
Per-runtime compact-equivalent command table consumed by compact.md,
|
|
4
|
-
compact-extended.md, and scripts/sync-skills.sh. Not user-invocable
|
|
5
|
-
directly.
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Per-Runtime Compact Command Table (shared partial)
|
|
9
|
-
|
|
10
|
-
Consumers: `claude-plugin/commands/compact.md`, `compact-extended.md`
|
|
11
|
-
(reference this table for the command each runtime's synced copy sends), and
|
|
12
|
-
`scripts/sync-skills.sh`'s `compact_command_for_runtime()` (the executable
|
|
13
|
-
mirror of this table — keep the two in lockstep; a row added/changed here
|
|
14
|
-
without a matching case in that function is a defect at review, not a style
|
|
15
|
-
nit).
|
|
16
|
-
|
|
17
|
-
This is the canonical, cited source of truth for what "the compact command"
|
|
18
|
-
means on each runtime thrum drives. Do NOT invent a command for a runtime not
|
|
19
|
-
listed here or not sourced — an unverified guess sent to a runtime's pane is
|
|
20
|
-
worse than no compaction at all (it either no-ops or does something
|
|
21
|
-
unintended). A runtime found to have no equivalent is recorded as such, not
|
|
22
|
-
silently omitted.
|
|
23
|
-
|
|
24
|
-
| Runtime | Compact command | Source | Confidence |
|
|
25
|
-
| ------------ | -------------------------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------ |
|
|
26
|
-
| `claude` | `/compact` | Claude Code built-in slash command (already established in this project). | Verified — first-party. |
|
|
27
|
-
| `codex` | `/compact` | OpenAI Codex CLI context-compaction architecture (server-side `POST /v1/responses/compact`, manual trigger `/compact`). | Verified — corroborated by two independent technical write-ups; not fetched from `codex --help` directly. |
|
|
28
|
-
| `opencode` | `/compact` (alias `/summarize`) | opencode.ai official docs, keybinds reference — `session_compact` action, default slash command `/compact`. | Verified from official docs. **Caveat:** a differently-named community fork lacks this command — confirm against the specific `opencode` binary before relying on it blindly. |
|
|
29
|
-
| `cursor` | `/summarize` (alias `/compress`) | cursor.com CLI reference, slash-commands page. | Verified from official docs. **Differs from Claude's `/compact`** — this is the one runtime where the sent text must actually change. `/clear` (aliases `/new`, `/new-chat`) is a separate full-reset command, not compaction — do not confuse the two. |
|
|
30
|
-
| `copilot` | `/compact` | docs.github.com, "Managing context in GitHub Copilot CLI". | Verified from official docs. **Not currently shippable**: `copilot-plugin/` has no skills/commands-loading mechanism at all (pre-existing, documented in `scripts/sync-skills.sh`'s header) — this row exists for completeness/future readiness, not because the skill ships there today. Coverage tracked as a build-vs-accept scope call, owner-owned. |
|
|
31
|
-
| `muse` | **NONE FOUND** | musecodes.io official docs — documented commands are `/plan`, `/grill`, `/goal`, `/workflows`, `/model`, `/effort`, `Esc Esc` (rewind), `muse replay`. No manual compact/summarize trigger is documented; marketing copy describing context "compaction" refers to an automatic/internal mechanism only, not a user-invocable command. | Verified absence, not an inferred gap. Per E9 (owner-ruled), muse falls to the `restart-extended` exception — it does not receive compact.md/compact-extended.md. |
|
|
32
|
-
| `gemini` | **UNVERIFIED** | Not researched — no plugin tree exists for this runtime, and it was never included in this table's original research pass. | **Not a confirmed negative.** Go-side `internal/runtime.RuntimePreset` exists for this runtime with `CompactCommand` deliberately left empty (falls back to `/thrum:restart-extended`, never invented). This research is not yet done — do not research here; treat future work on this row as owned elsewhere. |
|
|
33
|
-
| `kiro-cli` | **UNVERIFIED** | Same as `gemini` — not researched, no plugin tree. | Same as `gemini` — empty `CompactCommand`, safe fallback, research pending. |
|
|
34
|
-
| `amp` | **UNVERIFIED** | Same as `gemini` — not researched, no plugin tree. | Same as `gemini` — empty `CompactCommand`, safe fallback, research pending. |
|
|
35
|
-
| `shell` | **UNVERIFIED** | Same as `gemini` — not researched, no plugin tree. | Same as `gemini` — empty `CompactCommand`, safe fallback, research pending. |
|
|
36
|
-
|
|
37
|
-
## Notes
|
|
38
|
-
|
|
39
|
-
- `codex` and `opencode` resolve to the same literal string Claude uses
|
|
40
|
-
(`/compact`), so their synced copies are a functional no-op substitution —
|
|
41
|
-
still routed through the same mechanism for consistency and so a future
|
|
42
|
-
table change (e.g. if `opencode`'s fork situation resolves differently)
|
|
43
|
-
propagates without a second code path.
|
|
44
|
-
- `cursor` is the one runtime whose synced copy's sent command differs from
|
|
45
|
-
Claude's and must be verified after every sync run (`grep` step in
|
|
46
|
-
`scripts/sync-skills.sh`'s `compact_command_for_runtime` block).
|
|
47
|
-
- `muse` and `copilot` are both absent from compact/compact-extended's sync
|
|
48
|
-
targets today, for two *different* reasons — `muse` because no native
|
|
49
|
-
command exists to send, `copilot` because the plugin has no delivery
|
|
50
|
-
mechanism at all. Neither is a silent drop: both are recorded here and
|
|
51
|
-
reported in the completion report for this table's original research pass.
|
|
52
|
-
- `gemini`/`kiro-cli`/`amp`/`shell` are recorded as **UNVERIFIED**, not
|
|
53
|
-
merged into the `muse`/`copilot` "no equivalent" rows above — those two are
|
|
54
|
-
confirmed negatives (verified by reading official docs); the four
|
|
55
|
-
UNVERIFIED rows are an absence of research, not an absence of a command.
|
|
56
|
-
`scripts/sync-skills.sh`'s `compact_command_for_runtime()` already returns
|
|
57
|
-
`""` for any of these four via its `*` default case, so the executable
|
|
58
|
-
mirror and this table already agree — no code change is needed to keep
|
|
59
|
-
them in lockstep, only this documentation. See also
|
|
60
|
-
`dev-docs/reference/compaction-lifecycle-attach-points.md` for the same
|
|
61
|
-
four runtimes' hook-attach-point status.
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description:
|
|
3
|
-
Shared generator-skill idempotency invariant consumed by config/doc
|
|
4
|
-
generator skills. Not user-invocable directly.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Generator Idempotency Protocol (shared partial)
|
|
8
|
-
|
|
9
|
-
Consumers: run `grep -rl _generator-idempotency-protocol claude-plugin/skills/`
|
|
10
|
-
for the current set — do NOT hardcode it here. A list of consumers inside the
|
|
11
|
-
consumed file is a second copy of a git-answerable fact and rots the moment a
|
|
12
|
-
skill is added or dropped.
|
|
13
|
-
|
|
14
|
-
The modes are idempotent — running the skill repeatedly on a stable project
|
|
15
|
-
should produce no file changes after the first run.
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description:
|
|
3
|
-
Shared project-specific-rules protocol consumed by role skills. Not
|
|
4
|
-
user-invocable directly.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Project-Specific Rules Protocol (shared partial)
|
|
8
|
-
|
|
9
|
-
Consumers: run `grep -rl _project-rules-protocol claude-plugin/skills/` 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 skill is
|
|
12
|
-
added or dropped.
|
|
13
|
-
|
|
14
|
-
Project-local rules of kind `agent_rule` at `--scope role` were loaded at
|
|
15
|
-
session start by your preamble (see your role template's Memory model block).
|
|
16
|
-
If a project-local rule conflicts with a universal rule above, the
|
|
17
|
-
project-local rule wins; surface the conflict in your reply so the user can
|
|
18
|
-
decide whether to graduate or remove the override.
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description:
|
|
3
|
-
Shared "Verify before you write" invariant consumed by state-writing
|
|
4
|
-
skills. Not user-invocable directly.
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Verify Before You Write Protocol (shared partial)
|
|
8
|
-
|
|
9
|
-
Consumers: run `grep -rl _verify-before-write-protocol claude-plugin/skills/`
|
|
10
|
-
for the current set — do NOT hardcode it here. A list of consumers inside the
|
|
11
|
-
consumed file is a second copy of a git-answerable fact and rots the moment a
|
|
12
|
-
skill is added or dropped.
|
|
13
|
-
|
|
14
|
-
A written fact is TRUE at the moment it's recorded and can silently become
|
|
15
|
-
FALSE later — the reader can't tell, because a note doesn't present itself as
|
|
16
|
-
a time-bound claim. Before writing anything:
|
|
17
|
-
|
|
18
|
-
- Only write what you've verified against current state — not what you
|
|
19
|
-
remember, assume, or were told once.
|
|
20
|
-
- A note recording an UNEXPLAINED artifact must carry the unexplained-ness
|
|
21
|
-
forward — "not mine, cause unknown, nobody has traced this" — rather than
|
|
22
|
-
resolving it to a disposition like "ignore it." The note isn't wrong to cope
|
|
23
|
-
with noise you can't act on; the defect is closing the question when
|
|
24
|
-
nothing is actually known. "Ignore it" is unfalsifiable by construction —
|
|
25
|
-
an instruction to not look can't be caught by looking, because diligence is
|
|
26
|
-
exactly what it switches off — and it can silently train every future
|
|
27
|
-
session to stop looking at the one visible symptom of a live bug.
|