opencode-thrum-pro 0.1.3 → 0.1.5
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/skills/agent-messaging-protocol/SKILL.md +35 -0
- package/assets/skills/brainstorm-steward/SKILL.md +3 -2
- package/assets/skills/brainstormer-dashboard-needs/SKILL.md +62 -0
- package/assets/skills/brainstormer-staying-current/SKILL.md +116 -0
- package/assets/skills/conversation-only-context/SKILL.md +16 -8
- package/assets/skills/conversation-only-context/resources/driver-subagent-pattern.md +138 -0
- package/assets/skills/conversation-only-context/resources/remote-environment-scenarios.md +97 -0
- package/assets/skills/coordinator-assessing-agent-completion/SKILL.md +24 -3
- package/assets/skills/coordinator-dashboard-human-loop/SKILL.md +72 -0
- package/assets/skills/coordinator-deploying-the-fleet/SKILL.md +396 -0
- package/assets/skills/coordinator-hotpath-merge-gate/SKILL.md +7 -3
- package/assets/skills/coordinator-philosophy-merge-gate/SKILL.md +7 -3
- package/assets/skills/coordinator-running-brainstorm-cycles/SKILL.md +38 -52
- package/assets/skills/efficient-multi-agent-research/SKILL.md +3 -4
- package/assets/skills/persistent-watcher-archetype/SKILL.md +49 -15
- package/assets/skills/persistent-watcher-archetype/resources/thrum-capture-fallback.sh +8 -4
- package/assets/skills/persistent-watcher-archetype/resources/thrum-watch-pane-capture.sh +1 -1
- package/assets/skills/state-migration/SKILL.md +1 -1
- package/assets/skills/using-the-dashboard/SKILL.md +148 -0
- package/assets/skills/using-thrum-state/SKILL.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-messaging-protocol
|
|
3
|
+
description: "Use when forwarding or relaying information between parties, routing an owner answer, carrying a decision or request through an intermediary, summarizing another author's message, or adding interpretation to someone else's words."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Agent Messaging Protocol for Forwarding and Relaying
|
|
7
|
+
|
|
8
|
+
- Communicate directly with the intended party whenever possible.
|
|
9
|
+
- Treat the original message as the authoritative source.
|
|
10
|
+
- Forward a pointer to the original message instead of retyping or paraphrasing its body.
|
|
11
|
+
- Include the original author, original message ID, intended recipient, and requested action.
|
|
12
|
+
- Attach `message:<original-message-id>` as a message reference when supported.
|
|
13
|
+
- Read the original message before acting: `thrum message get <message-id> --json`.
|
|
14
|
+
- Reply against the original message: `thrum reply <message-id> ...`.
|
|
15
|
+
- Do not route the response back through the intermediary.
|
|
16
|
+
- Add commentary or interpretation only when requested or necessary.
|
|
17
|
+
- Label added reasoning as `INTERPRETATION - @agent`.
|
|
18
|
+
- Never present an interpretation, summary, or recommendation as words or authority from the original author.
|
|
19
|
+
- Label a requested summary as `SUMMARY - @agent` and retain the original message ID.
|
|
20
|
+
- Preserve the original scope, urgency, constraints, and requested action.
|
|
21
|
+
- Do not introduce new requirements, decisions, risks, or authorization while routing.
|
|
22
|
+
- Ask the original author directly when clarification is required.
|
|
23
|
+
- Continue referencing the original message rather than an intermediary's summary.
|
|
24
|
+
- Identify corrections by the exact message they supersede.
|
|
25
|
+
- Distinguish delivery, acknowledgement, execution, and verification.
|
|
26
|
+
- Preserve the original thread audience when replying unless a deliberately narrower audience is required.
|
|
27
|
+
|
|
28
|
+
## Routing Envelope
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
ROUTE POINTER
|
|
32
|
+
From: @original-author
|
|
33
|
+
Message: msg_...
|
|
34
|
+
Action: Read and reply to the original message.
|
|
35
|
+
```
|
|
@@ -27,8 +27,9 @@ to that coordinator). Everything below is additive — the brainstorm-specific
|
|
|
27
27
|
duties layered on top of that base.
|
|
28
28
|
|
|
29
29
|
Your roster is entirely remote (other boxes), so the base skill's remote
|
|
30
|
-
modal-unblock note applies to every roster member by default —
|
|
31
|
-
|
|
30
|
+
modal-unblock note applies to every roster member by default — use
|
|
31
|
+
`thrum tmux send` (peer-routed, works fleet-wide); the local-only
|
|
32
|
+
tmux-key primitive it replaces is retired.
|
|
32
33
|
|
|
33
34
|
## Roster = brainstormers
|
|
34
35
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstormer-dashboard-needs
|
|
3
|
+
description: "Use when running as a brainstormer or researcher whose steward/coordinator publishes NEEDs to the human via a dashboard board — author NEEDs as answerable action-picks, consume routed ANSWERS from dashboard results, and keep the board's view of your question in sync with reality."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Brainstormer/researcher: NEEDs on the dashboard
|
|
7
|
+
|
|
8
|
+
When your steward or coordinator runs a dashboard board for the human (the
|
|
9
|
+
steward-console pattern), your NEED travels as an **action-pick widget** the
|
|
10
|
+
human answers by clicking. This is a thin overlay on `using-the-dashboard`
|
|
11
|
+
(invoke it first for the CLI contract and the honesty table) and on the
|
|
12
|
+
queue-aware pattern you already run — same discipline, new surface: the
|
|
13
|
+
question leaves your hands as a structured pick, and the answer comes back as
|
|
14
|
+
a routed ANSWER message, exactly as before.
|
|
15
|
+
|
|
16
|
+
## Authoring a NEED for the board
|
|
17
|
+
|
|
18
|
+
Send your steward the NEED in board-ready shape — question, 2-3 discrete
|
|
19
|
+
options with one-line consequences, and what nuance the human might add:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
NEED [topic]: Does X count deleted agents' messages?
|
|
23
|
+
A) Live-only — deleted history can't manufacture recency (no migration)
|
|
24
|
+
B) Include deleted — needs a new (agent_id, created_at) index
|
|
25
|
+
allow_text: yes (owner usually adds "but weigh X")
|
|
26
|
+
context: blocks gap-analysis step 3
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Rules with teeth:
|
|
30
|
+
|
|
31
|
+
- **Discrete options or no board.** If the NEED is genuinely open-form, say so
|
|
32
|
+
— the pick is for choices, not for open essays.
|
|
33
|
+
- **One NEED, one pick.** Split multi-part rulings.
|
|
34
|
+
- **Say what it blocks.** The human triages by consequence.
|
|
35
|
+
|
|
36
|
+
## Consuming the ANSWER
|
|
37
|
+
|
|
38
|
+
The routed ANSWER arrives as a message (steward-relayed, owner's words — pick
|
|
39
|
+
plus typed nuance) and the board flips your question to ANSWERED. Your job:
|
|
40
|
+
|
|
41
|
+
1. Fold the answer into the design exactly as you would a terminal relay.
|
|
42
|
+
2. If the ANSWER changes the board's framing (follow-up question), author the
|
|
43
|
+
follow-up as a NEW pick — don't mutate the answered one's meaning.
|
|
44
|
+
3. Never re-ask an ANSWERED question; `thrum dashboard show` marks it
|
|
45
|
+
ANSWERED, and the durable record is the answer MESSAGE.
|
|
46
|
+
|
|
47
|
+
Note: if nothing has been posted for you yet, `dashboard show`/`get` return
|
|
48
|
+
`found: false` with an empty envelope, not an error — don't read that as a
|
|
49
|
+
failure.
|
|
50
|
+
|
|
51
|
+
## Honesty (same table as the commons)
|
|
52
|
+
|
|
53
|
+
While E4 (answer round-trip) is NOT landed, board picks cannot be answered in
|
|
54
|
+
the UI — your NEED still routes via the steward/message channel exactly as
|
|
55
|
+
`brainstorm-queue-aware` prescribes. The board-shaped authoring above is the
|
|
56
|
+
format to keep using so the transition is seamless when E4 lands. Until then,
|
|
57
|
+
a board is rehearsal surface only: never assume the human saw a widget.
|
|
58
|
+
|
|
59
|
+
## Refs to other skills
|
|
60
|
+
|
|
61
|
+
- `using-the-dashboard` — surface + CLI contract + honesty table (invoke first)
|
|
62
|
+
- `brainstorm-queue-aware` — the steward NEED/ANSWER loop this overlays
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: brainstormer-staying-current
|
|
3
|
+
description: "Use when a long-lived brainstormer worktree may be behind its configured merge target, before review or handoff, or when asked to merge-forward and leave the worktree clean. Resolves the target and merge owner from Thrum config, preserves local work, and verifies freshness after the merge."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Brainstormer: Stay Current with the Merge Target
|
|
7
|
+
|
|
8
|
+
Keep a long-lived brainstorm branch current without landing it into the merge
|
|
9
|
+
target. Every git write in this skill (commit, merge, revert, push) stays with
|
|
10
|
+
you — never delegate a git write to a subagent. Every `fetch` also stays with
|
|
11
|
+
you, the acting agent, per Preserve and Bind freshness below. If you delegate
|
|
12
|
+
the read-only merge-base/status analysis, load `choosing-subagent-models`
|
|
13
|
+
first and fence the subagent to `show`, `log`, `diff`, `grep`, `rev-parse`,
|
|
14
|
+
`merge-base`, `status` — the same read-only git surface CLAUDE.md requires for
|
|
15
|
+
every sub-agent — never `stash`, `reset`, `rebase`, `restore`, `clean`,
|
|
16
|
+
`commit`, `push`, or `checkout`.
|
|
17
|
+
|
|
18
|
+
## Resolve authority from config
|
|
19
|
+
|
|
20
|
+
Locate the canonical config from the current worktree:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
CONFIG=.thrum/config.json
|
|
24
|
+
if [ ! -f "$CONFIG" ]; then
|
|
25
|
+
COMMON_DIR=$(git rev-parse --path-format=absolute --git-common-dir)
|
|
26
|
+
CONFIG="${COMMON_DIR%/.git}/.thrum/config.json"
|
|
27
|
+
fi
|
|
28
|
+
test -f "$CONFIG"
|
|
29
|
+
TARGET=$(jq -er '.orchestration.merge_target | select(type == "string" and length > 0)' "$CONFIG")
|
|
30
|
+
MERGE_KING=$(jq -r --arg target "$TARGET" '.orchestration.merge_kings[$target] // "unset"' "$CONFIG")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Treat an absent config or target as a blocker — merge-forward has nowhere to
|
|
34
|
+
target without them. A merge-forward only brings `origin/$TARGET` into the
|
|
35
|
+
brainstorm branch; it never grants permission to merge the brainstorm branch
|
|
36
|
+
into `$TARGET`, so it needs no landing authority to run and an `unset`
|
|
37
|
+
`MERGE_KING` never blocks it.
|
|
38
|
+
|
|
39
|
+
`orchestration.merge_kings` may not be populated for every target yet: `unset`
|
|
40
|
+
does NOT mean "nobody owns landing, proceed however" — it means the map
|
|
41
|
+
hasn't caught up (same gap `coordinator-merging-code/SKILL.md` documents for
|
|
42
|
+
branch-keyed lookups). `MERGE_KING` matters only when a conflict needs routing
|
|
43
|
+
or at final report. With it `unset` at either point, fall back to whichever
|
|
44
|
+
coordinator has actually been the merge authority for `$TARGET` in practice
|
|
45
|
+
(check with your team, or the project's operational convention) and
|
|
46
|
+
route/report to them the same as if the map had named them explicitly.
|
|
47
|
+
|
|
48
|
+
## Preserve before merging
|
|
49
|
+
|
|
50
|
+
Record the current branch, HEAD, status, and ahead/behind counts. Require an
|
|
51
|
+
attached non-target feature branch. Fetch the target branch explicitly:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git fetch origin "refs/heads/$TARGET:refs/remotes/origin/$TARGET"
|
|
55
|
+
git rev-list --left-right --count HEAD..."origin/$TARGET"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If the worktree is dirty, preserve tracked and untracked changes as a WIP
|
|
59
|
+
commit and record its SHA — never `git stash`. `stash` is a single shared
|
|
60
|
+
stack across every worktree on this box, not scoped to this worktree or to
|
|
61
|
+
you; a stash push or pop here can silently destroy or restore another agent's
|
|
62
|
+
uncommitted work, with no reflog entry and no recoverable blob for unstaged
|
|
63
|
+
content. A commit is yours alone and fully recoverable.
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git add -A
|
|
67
|
+
git commit -m "wip: preserve <branch> before merge-forward <timestamp>"
|
|
68
|
+
git rev-parse HEAD
|
|
69
|
+
git status --short
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Do not squash, drop, or revert the WIP commit when the requested outcome is a
|
|
73
|
+
clean worktree — it is real history now, not something to discard.
|
|
74
|
+
|
|
75
|
+
Stop if the worktree is still dirty after the WIP commit. Never use `stash`,
|
|
76
|
+
reset, rebase, force checkout, clean, or force push to obtain a clean state —
|
|
77
|
+
`stash` is banned here exactly like the others, with no worktree-scoped
|
|
78
|
+
exception.
|
|
79
|
+
|
|
80
|
+
## Merge-forward
|
|
81
|
+
|
|
82
|
+
Merge the remote-tracking target into the brainstorm branch:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
git merge --no-edit "origin/$TARGET"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Resolve a conflict only when the correct result is supported by current source
|
|
89
|
+
and the branch's intended work. Otherwise stop with the conflict intact and
|
|
90
|
+
send the branch, worktree, target, and conflicted paths to the user or
|
|
91
|
+
`$MERGE_KING` for direction — falling back to the operational-convention
|
|
92
|
+
authority per above if `$MERGE_KING` is `unset`.
|
|
93
|
+
|
|
94
|
+
After a successful merge, run validation relevant to every resolved file and
|
|
95
|
+
always run `git diff --check origin/$TARGET..HEAD`.
|
|
96
|
+
|
|
97
|
+
## Bind freshness to handoff
|
|
98
|
+
|
|
99
|
+
Immediately before reporting success, fetch the target branch explicitly again
|
|
100
|
+
and verify the fetched target is an ancestor of HEAD:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
git fetch origin "refs/heads/$TARGET:refs/remotes/origin/$TARGET"
|
|
104
|
+
git rev-list --left-right --count HEAD..."origin/$TARGET"
|
|
105
|
+
git merge-base --is-ancestor "origin/$TARGET" HEAD
|
|
106
|
+
git status --short
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
If the target advanced, repeat the merge-forward and verification, up to three
|
|
110
|
+
merge cycles in one run. After three moving-target results, stop and report the
|
|
111
|
+
new target SHA instead of claiming the branch is current.
|
|
112
|
+
|
|
113
|
+
Report the branch and target SHAs, ahead/behind counts, `$MERGE_KING` (or the
|
|
114
|
+
fallback authority if `unset`), validation, clean status, and the WIP commit
|
|
115
|
+
SHA if one was made. Do not push, squash, or drop the WIP commit unless the
|
|
116
|
+
user separately asks.
|
|
@@ -141,15 +141,18 @@ Write to the pane only when the human asked, or when the decision is one only th
|
|
|
141
141
|
human can make. Everything else goes through `thrum send` / `thrum reply`.
|
|
142
142
|
Surface an owner-only decision crisply, with a recommendation attached.
|
|
143
143
|
|
|
144
|
-
## VM work
|
|
144
|
+
## Remote and VM work
|
|
145
145
|
|
|
146
|
-
Use a named persistent driver (`vmdriver_<slug>`)
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
(execute now · drive to completion yourself · then stop and
|
|
150
|
-
isolation proof
|
|
151
|
-
|
|
152
|
-
|
|
146
|
+
Use a named persistent driver (`vmdriver_<slug>`), continued by `SendMessage`
|
|
147
|
+
across rounds. Reach the remote environment only through the persistent-session
|
|
148
|
+
command your project sanctions, never a one-shot remote exec. State the
|
|
149
|
+
three-clause GO (execute now · drive to completion yourself · then stop and
|
|
150
|
+
report), require the isolation proof before anything touches a shared service,
|
|
151
|
+
and require the 3-section report. Never do the remote work yourself.
|
|
152
|
+
|
|
153
|
+
The full pattern is `resources/driver-subagent-pattern.md`; five worked shapes,
|
|
154
|
+
including the restart handoff of a live driver, are in
|
|
155
|
+
`resources/remote-environment-scenarios.md`.
|
|
153
156
|
|
|
154
157
|
## Restart handoff
|
|
155
158
|
|
|
@@ -170,6 +173,11 @@ Restart on a number read from the pane footer, never on a felt sense.
|
|
|
170
173
|
disk, consolidate, for N>6 items. This skill sets the session's posture; that one
|
|
171
174
|
runs a single pass.
|
|
172
175
|
- `choosing-subagent-models` — the tier policy and source of the CONSTRAINTS block.
|
|
176
|
+
- [driver-subagent-pattern.md](resources/driver-subagent-pattern.md) — the full
|
|
177
|
+
remote-work pattern: the named driver, the three-clause GO, the isolation
|
|
178
|
+
proof, the report contract, the parent's duties, the anti-patterns.
|
|
179
|
+
- [remote-environment-scenarios.md](resources/remote-environment-scenarios.md) —
|
|
180
|
+
five worked shapes, from a long lab run to a restart handoff of a live driver.
|
|
173
181
|
|
|
174
182
|
## Failure modes
|
|
175
183
|
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# The driver subagent pattern — running remote work without spending your context
|
|
2
|
+
|
|
3
|
+
Use this when the work lives somewhere your session should never go directly: a
|
|
4
|
+
remote host, a virtual machine, a lab box, a container, a sandboxed service. You
|
|
5
|
+
stay two steps removed.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
you (parent) holds: the question, the yes/no, a short evidence summary
|
|
9
|
+
└─ named driver subagent holds: commands, logs, retries, waiting, troubleshooting
|
|
10
|
+
└─ remote environment holds: the real system under test
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Your context never receives build logs, file dumps, or command transcripts. The
|
|
14
|
+
driver holds those and answers questions about them.
|
|
15
|
+
|
|
16
|
+
## 1. One driver, named, continued by message
|
|
17
|
+
|
|
18
|
+
Create the driver once with an explicit `name` and an explicit `model`, then
|
|
19
|
+
continue it in rounds: GO, report, next GO. It keeps its remote session, its
|
|
20
|
+
findings, and its troubleshooting state across rounds.
|
|
21
|
+
|
|
22
|
+
Do this:
|
|
23
|
+
|
|
24
|
+
1. `Agent(name: "vmdriver_<slug>", model: "sonnet", prompt: <round-1 GO>)`.
|
|
25
|
+
2. Wait for its report.
|
|
26
|
+
3. `SendMessage(to: "vmdriver_<slug>", message: <round-2 GO>)`.
|
|
27
|
+
|
|
28
|
+
Do not dispatch a fresh subagent per step, and do not dispatch one told to
|
|
29
|
+
"monitor until done". A subagent whose turn ends is not waiting, it is gone, and
|
|
30
|
+
a monitor it armed in that turn never reports. Run one driver per investigation
|
|
31
|
+
thread and parallelize across threads, not across the steps of one thread.
|
|
32
|
+
|
|
33
|
+
## 2. Every GO carries the three clauses
|
|
34
|
+
|
|
35
|
+
State all three, every round:
|
|
36
|
+
|
|
37
|
+
1. This is the GO. Execute the sequence now. It is not another round of
|
|
38
|
+
questions.
|
|
39
|
+
2. Drive it to completion yourself. Poll, retry, troubleshoot. Do not arm a
|
|
40
|
+
monitor and end your turn.
|
|
41
|
+
3. Then stop and report. Nothing pending.
|
|
42
|
+
|
|
43
|
+
Clause 2 is the one that decides whether the round produces work or silence.
|
|
44
|
+
|
|
45
|
+
## 3. What a GO must contain
|
|
46
|
+
|
|
47
|
+
1. Goal, then ordered steps, each naming the exact fields to capture before and
|
|
48
|
+
after.
|
|
49
|
+
2. The one sanctioned way to reach the environment, named explicitly, with the
|
|
50
|
+
alternatives ruled out. A one-shot remote exec is usually a different shell
|
|
51
|
+
with a different path and a different caller identity, so it silently tests a
|
|
52
|
+
different thing than an interactive session does.
|
|
53
|
+
3. The exact host or target, the working directories, and the revision under
|
|
54
|
+
test. A stale host alias that resolves elsewhere will pass every check while
|
|
55
|
+
measuring the wrong machine, so have the driver print the resolved hostname.
|
|
56
|
+
4. An isolation gate, written as a numbered step, not as a caveat. See section 4.
|
|
57
|
+
5. Fences that bind the driver and anything it dispatches: read-only version
|
|
58
|
+
control outside its own workspace, no installs that touch shared binaries, no
|
|
59
|
+
restart of a shared service, and no recursive delete flags.
|
|
60
|
+
6. The report shape from section 6, including what you do not want back.
|
|
61
|
+
|
|
62
|
+
## 4. Isolation proof before acting on a shared service
|
|
63
|
+
|
|
64
|
+
If the environment also runs a shared instance of the service, every restart,
|
|
65
|
+
stop, or reconfigure must target the sandboxed instance. Make the driver print
|
|
66
|
+
the identity of the instance it is about to touch, and confirm it is the
|
|
67
|
+
sandboxed one, before each such action.
|
|
68
|
+
|
|
69
|
+
Verify isolation by effect rather than by intent. The sandboxed instance and the
|
|
70
|
+
shared one should report different identifiers, and the test participants should
|
|
71
|
+
be visible to the sandboxed instance and absent from the shared one.
|
|
72
|
+
|
|
73
|
+
Sandboxing is rarely total. Check what your isolation mechanism does not cover,
|
|
74
|
+
and have the driver clean up by hand at teardown whatever the sandbox reaper
|
|
75
|
+
cannot reach.
|
|
76
|
+
|
|
77
|
+
## 5. Long-running work in the remote environment
|
|
78
|
+
|
|
79
|
+
1. Prefer a persistent interactive session. Working directory, environment, and
|
|
80
|
+
background jobs then survive between calls.
|
|
81
|
+
2. Anything longer than a couple of minutes runs detached, writing its exit code
|
|
82
|
+
to its own file. A chained command hides the exit code. The driver polls that
|
|
83
|
+
file. The parent never polls.
|
|
84
|
+
3. Run tests in the foreground with a bounded timeout and send output to a file.
|
|
85
|
+
Piping through a pager or a line filter masks the real exit status and drops
|
|
86
|
+
the lines that carry the stack dump.
|
|
87
|
+
4. When anything looks crossed or stale, tear the session down and reconnect
|
|
88
|
+
rather than reasoning about which host you are on.
|
|
89
|
+
|
|
90
|
+
## 6. The report contract, driver to parent
|
|
91
|
+
|
|
92
|
+
Three sections, in this order, and nothing else:
|
|
93
|
+
|
|
94
|
+
1. Isolation proof. Which instance was touched, and evidence it was the
|
|
95
|
+
sandboxed one.
|
|
96
|
+
2. Measured results, per step, with the exact fields captured before and after,
|
|
97
|
+
and verbatim error text wherever a command failed. "It worked" without the
|
|
98
|
+
fields is not a result.
|
|
99
|
+
3. Explicit close. Either "stopping here as instructed, nothing pending", or the
|
|
100
|
+
precise point it is blocked and why.
|
|
101
|
+
|
|
102
|
+
No logs, no transcripts, no command dumps. Those stay with the driver. Ask a
|
|
103
|
+
follow-up round for any specific one.
|
|
104
|
+
|
|
105
|
+
## 7. Your duties as the parent
|
|
106
|
+
|
|
107
|
+
1. Verify, do not trust. An idle notification means a turn ended, not that the
|
|
108
|
+
work finished. Check the agent's state before acting on it.
|
|
109
|
+
2. Spot-check one or two load-bearing claims from each report, such as a
|
|
110
|
+
revision, an instance identifier, or a single field value. Decide which ones
|
|
111
|
+
before you send the GO.
|
|
112
|
+
3. If a round produces no report and no progress, stop that driver and
|
|
113
|
+
re-dispatch with clause 2 stated more forcefully. Do not queue another GO
|
|
114
|
+
behind a dead one.
|
|
115
|
+
4. Never do the remote work yourself to just check quickly. That is exactly the
|
|
116
|
+
context this pattern protects. Ask the driver a smaller question instead.
|
|
117
|
+
|
|
118
|
+
## 8. Anti-patterns
|
|
119
|
+
|
|
120
|
+
| Anti-pattern | What it produces | Replacement |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| Fire-and-forget subagent told to monitor | Long runs, large token spend, no output | Named driver, message rounds, clause 2 |
|
|
123
|
+
| One-shot remote exec instead of a session | Wrong path, wrong caller identity, wrong test | The one sanctioned access path, stated in the GO |
|
|
124
|
+
| A stale host alias | Results from the wrong machine, all checks green | Print the resolved hostname in the isolation proof |
|
|
125
|
+
| Driving behavior from a raw shell | Tests the unbound caller path, not the real one | Send the command into the participant's own pane |
|
|
126
|
+
| Parent reading logs to help | Spends the context the pattern exists to protect | Ask the driver for the one field you need |
|
|
127
|
+
| Work committed on a stale base | Invisible to everyone, diverges quietly | Cut the workspace from current trunk, check the base revision |
|
|
128
|
+
|
|
129
|
+
## 9. Checklist before sending a GO
|
|
130
|
+
|
|
131
|
+
1. The driver is named, and I will continue it by message rather than
|
|
132
|
+
re-dispatch.
|
|
133
|
+
2. The GO has ordered steps with captures, the sanctioned access path, the host
|
|
134
|
+
and paths and revision, the isolation gate as a step, the fences, the report
|
|
135
|
+
shape, and the three clauses.
|
|
136
|
+
3. `model` is passed explicitly.
|
|
137
|
+
4. I know which one or two claims I will spot-check.
|
|
138
|
+
5. Nothing in the GO can reach a shared service or install a shared binary.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Worked scenarios — driving remote work through a driver subagent
|
|
2
|
+
|
|
3
|
+
Five shapes you will meet. Each names what the parent keeps, what the driver
|
|
4
|
+
owns, and the trap specific to that shape. The pattern itself is in
|
|
5
|
+
`driver-subagent-pattern.md`. Placeholders: `<remote-host>` is the machine,
|
|
6
|
+
`<your-ssh-wrapper>` is whatever persistent-session command your project
|
|
7
|
+
sanctions for reaching it.
|
|
8
|
+
|
|
9
|
+
## Scenario 1 — a long lab run on a remote box
|
|
10
|
+
|
|
11
|
+
You want a multi-hour load or soak run and a verdict, not a log.
|
|
12
|
+
|
|
13
|
+
1. Spawn `vmdriver_<slug>` with `model: "sonnet"`. The GO names the run, the
|
|
14
|
+
revision under test, and the exact metrics to report.
|
|
15
|
+
2. The driver opens a persistent session with `<your-ssh-wrapper> <remote-host>`,
|
|
16
|
+
starts the run detached, and writes the exit code to its own file.
|
|
17
|
+
3. The driver polls that file. You do not. You go on talking to the operator.
|
|
18
|
+
4. The driver reports the three sections and stops.
|
|
19
|
+
|
|
20
|
+
Trap: a run started inside a one-shot remote exec dies with the connection, and
|
|
21
|
+
the failure reads as a crash in the thing under test. Start it detached from a
|
|
22
|
+
persistent session.
|
|
23
|
+
|
|
24
|
+
## Scenario 2 — a reproduction that needs a sandboxed service
|
|
25
|
+
|
|
26
|
+
The bug only appears in a running system, so a source read cannot settle it.
|
|
27
|
+
|
|
28
|
+
1. The GO orders: build the revision under test, bring up a sandboxed instance
|
|
29
|
+
of the service, print that instance's identity, and confirm it differs from
|
|
30
|
+
the shared instance before touching anything.
|
|
31
|
+
2. Only then does the driver run the reproduction steps, capturing the named
|
|
32
|
+
fields before and after.
|
|
33
|
+
3. The report leads with the isolation proof.
|
|
34
|
+
|
|
35
|
+
Trap: sandboxing usually covers the service and its data but not every process
|
|
36
|
+
the service spawns. Ask the driver, in the GO, to state what its sandbox does
|
|
37
|
+
not cover, and to hand-clean those at teardown.
|
|
38
|
+
|
|
39
|
+
## Scenario 3 — a multi-round measurement with a parked driver
|
|
40
|
+
|
|
41
|
+
You need a baseline, a change, and a comparison, with your own judgment between
|
|
42
|
+
rounds.
|
|
43
|
+
|
|
44
|
+
1. Round 1 GO: take the baseline, report the fields, stop.
|
|
45
|
+
2. You read a short report, decide, and send round 2 by message. The driver
|
|
46
|
+
still holds its session, its build, and its earlier numbers, so round 2 costs
|
|
47
|
+
almost nothing to set up.
|
|
48
|
+
3. Round 3 asks for the comparison in the driver's own words plus the raw fields.
|
|
49
|
+
|
|
50
|
+
Trap: re-dispatching a fresh subagent between rounds throws away the warm
|
|
51
|
+
environment and the earlier context, then pays to rebuild both. Continue the
|
|
52
|
+
named driver instead.
|
|
53
|
+
|
|
54
|
+
## Scenario 4 — driving real agents inside the remote environment
|
|
55
|
+
|
|
56
|
+
You are testing behavior that only exists for a properly bound, running agent.
|
|
57
|
+
|
|
58
|
+
1. The driver brings up participants in the sandboxed environment and starts
|
|
59
|
+
their runtimes.
|
|
60
|
+
2. It exercises behavior by sending commands into each participant's own pane,
|
|
61
|
+
not from the raw shell. A raw shell is an unbound caller and tests a
|
|
62
|
+
different, usually always-failing, path.
|
|
63
|
+
3. It reads results by capturing the pane and by inspecting the participant's
|
|
64
|
+
own state files before and after.
|
|
65
|
+
4. It can ask a participant an investigative question and get reasoned findings
|
|
66
|
+
back. These are full agents, so delegate cognition, not just keystrokes.
|
|
67
|
+
|
|
68
|
+
Trap: a pane reported alive may still be parked at a first-run trust prompt with
|
|
69
|
+
no runtime behind it. Verify by pane content, never by a status field.
|
|
70
|
+
|
|
71
|
+
## Scenario 5 — restart handoff of a live driver
|
|
72
|
+
|
|
73
|
+
Your context is near its limit and a driver is mid-investigation.
|
|
74
|
+
|
|
75
|
+
1. Message the driver: finish the current step, write your file, report, and
|
|
76
|
+
stop.
|
|
77
|
+
2. Record in your restart snapshot, for that driver: its name, what it owns, its
|
|
78
|
+
result file path, its model, the round it was on, and any state it left
|
|
79
|
+
behind in the remote environment such as a running job, a live session, or a
|
|
80
|
+
sandbox that has not been torn down.
|
|
81
|
+
3. State plainly which drivers have already exited.
|
|
82
|
+
4. Your successor respawns the driver with the result file as seed and resumes
|
|
83
|
+
at the next round.
|
|
84
|
+
|
|
85
|
+
Trap: a driver left mid-flight across a restart leaves an orphaned sandbox and a
|
|
86
|
+
detached job nobody owns. The snapshot line about leftover state is the part
|
|
87
|
+
that gets skipped and the part that costs the most.
|
|
88
|
+
|
|
89
|
+
## Choosing between shapes
|
|
90
|
+
|
|
91
|
+
| Signal | Shape |
|
|
92
|
+
|---|---|
|
|
93
|
+
| One question, one long run | Scenario 1 |
|
|
94
|
+
| Behavior only reproduces in a live system | Scenario 2 |
|
|
95
|
+
| You must judge between rounds | Scenario 3 |
|
|
96
|
+
| The bound-caller path is what is under test | Scenario 4 |
|
|
97
|
+
| Your context is the binding constraint | Scenario 5 |
|
|
@@ -123,9 +123,30 @@ salvaged files distinct names and land the salvage somewhere durable (the main r
|
|
|
123
123
|
**`thrum agent delete --force` is REFUSED by the CAS guard on a stale agent with an empty
|
|
124
124
|
`agent_pid_start_time`** (*"expected-state premise is required … refusing rather than treating
|
|
125
125
|
an empty/never-read premise as a match"*). `--force` does NOT bypass it; the guard is
|
|
126
|
-
correct. So the reap that actually frees load is
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
correct. So the reap that actually frees load is worktree removal — but salvage BEFORE you remove,
|
|
127
|
+
then remove PLAIN (no `--force`):
|
|
128
|
+
|
|
129
|
+
1. Enumerate untracked+ignored `.thrum` content — BOTH flags, one flag alone misses a class
|
|
130
|
+
(thrum-j14q3): `git status --untracked-files=all --ignored -- .thrum`
|
|
131
|
+
2. Salvage BOTH kinds to their canonical redirect paths, and `cmp`-verify each copy is
|
|
132
|
+
byte-identical to its source:
|
|
133
|
+
- `?? .thrum/agents/<agent>/sessions/*-restart.md` — the restart snapshot.
|
|
134
|
+
- `!! .thrum/context/<agent>.md` — gitignored, NOT daemon-held, the **only copy**;
|
|
135
|
+
losing it is permanent. (`_preamble.md` is regenerable — skip it.)
|
|
136
|
+
3. THEN `git worktree remove <path>` — **plain, no `--force`.** ⚠️ This refusal is a REAL
|
|
137
|
+
backstop only for untracked/modified content (git's own rc=128 refusal) — it is NOT a
|
|
138
|
+
backstop for the gitignored `.thrum/context/<agent>.md` file: `git worktree remove`
|
|
139
|
+
silently deletes ignored-only content with exit 0, no refusal, no warning (verified by
|
|
140
|
+
direct reproduction). **Step 2's salvage is the ONLY protection for that file — there is
|
|
141
|
+
no git-level safety net behind it.** The rc=128 refusal still matters (it catches a stray
|
|
142
|
+
untracked restart-snapshot salvage missed, or any other unexpected untracked file), so
|
|
143
|
+
still read the BARE rc and still treat a refusal as a signal to investigate — just don't
|
|
144
|
+
mistake it for protecting the ignored-file class. (Not a pipe — a pipe returns the last
|
|
145
|
+
command's rc, not `git`'s.)
|
|
146
|
+
|
|
147
|
+
The delete (`thrum agent delete`) best-effort-fails and leaves a **benign orphan DB row**,
|
|
148
|
+
which you LEAVE (filtered at query per the fleet ruling; never `agent cleanup --force` to
|
|
149
|
+
tidy them).
|
|
129
150
|
|
|
130
151
|
⚠️ **After a large reap you may see a `DeadAgentSweeper` skip alert + elevated write-RPC
|
|
131
152
|
latency — do NOT assume the reap caused it.** This box carries a standing single-writer
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coordinator-dashboard-human-loop
|
|
3
|
+
description: "Use when the coordinator publishes or maintains a dashboard board FOR the human owner (roster, NEED queue, owner decisions, pipeline) or routes owner answers from a dashboard back to agents. Loads the human-loop mandate - a posted question is a PROMISE — it stays answerable and visible until answered, and nothing on the board disappears silently on your side."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Coordinator dashboard: the human loop
|
|
7
|
+
|
|
8
|
+
You own boards the HUMAN reads — the reference shape is the Brainstorm Steward
|
|
9
|
+
console: ① NEED queue (unified, oldest-first, each an action-pick) ② roster
|
|
10
|
+
health ③ owner decisions (pending + recently-resolved) ④ pipeline status.
|
|
11
|
+
Surface basics live in `using-the-dashboard` — invoke it for the CLI shapes
|
|
12
|
+
and the live-vs-coming honesty table. THIS skill carries the loop mandate.
|
|
13
|
+
|
|
14
|
+
## 🔴 The mandate: posted questions don't disappear until answered
|
|
15
|
+
|
|
16
|
+
When a board carries a question for the human (an action-pick), that question
|
|
17
|
+
is a PROMISE with four parts:
|
|
18
|
+
|
|
19
|
+
1. **Visible** — it stays on the board (status PENDING) until answered or
|
|
20
|
+
explicitly withdrawn by YOU (update its text to withdrawn, don't just
|
|
21
|
+
delete it).
|
|
22
|
+
2. **Answerable** — while E4 is NOT landed, an action-pick cannot actually be
|
|
23
|
+
answered in the UI. Until then, pair every board question with its
|
|
24
|
+
answering channel (the NEED still routes via message/steward as today) and
|
|
25
|
+
say so on the board — never let the human hit a dead control.
|
|
26
|
+
3. **Tracked** — check `thrum dashboard results` after every relevant nudge;
|
|
27
|
+
an answer arrives as a message carrying `question_id` + pick + optional
|
|
28
|
+
text. Unread answers + a PENDING widget = you broke the loop.
|
|
29
|
+
4. **Closed** — on consuming an answer, `thrum dashboard update <widget-id>`
|
|
30
|
+
to flip that pick's `status` to `resolved` (and log the resolution in your
|
|
31
|
+
decisions list). An answered question that still shows PENDING is the
|
|
32
|
+
coordinator-loop failure mode. If something else wrote the board first,
|
|
33
|
+
your `update` can be rejected as an `expected_rev` mismatch — re-read with
|
|
34
|
+
`dashboard show` and resubmit against the fresh `rev` (see
|
|
35
|
+
`using-the-dashboard`).
|
|
36
|
+
|
|
37
|
+
## Authoring discipline
|
|
38
|
+
|
|
39
|
+
- **One question, one action-pick.** Don't bundle three rulings into one
|
|
40
|
+
widget — the human answers picks discretely (that's why pick+optional-text
|
|
41
|
+
won over free-text).
|
|
42
|
+
- **Options carry the tradeoff.** Each option's label states the choice AND
|
|
43
|
+
its one-line consequence ("Live-only — no new migration"); the human should
|
|
44
|
+
not need `get` to understand a vote. Set `allow_text: true` — "B, but weigh
|
|
45
|
+
X" is how owners actually answer.
|
|
46
|
+
- **Board hygiene is part of the loop.** Stale roster stats and resolved
|
|
47
|
+
pipelines rot the board's credibility; refresh stat-rows when state moves
|
|
48
|
+
and prune sections that no longer serve. The user can delete any widget
|
|
49
|
+
SILENTLY (you are not nudged) — a widget that vanished was seen and
|
|
50
|
+
dismissed; check `show` before reposting.
|
|
51
|
+
- **`clear` is a reset, not an archive.** Need history? It lives in the
|
|
52
|
+
answer messages and your memories, not on the board.
|
|
53
|
+
|
|
54
|
+
## Routing answers
|
|
55
|
+
|
|
56
|
+
An answer message is routed to the OWNING agent of the question (for steward
|
|
57
|
+
consoles: relay to the originating brainstormer, in the owner's words — the
|
|
58
|
+
pick plus their typed nuance). Relay the TEXT the human wrote; paraphrasing
|
|
59
|
+
away their nuance defeats the optional-text feature.
|
|
60
|
+
|
|
61
|
+
## Ship gate
|
|
62
|
+
|
|
63
|
+
The USE-mandate blocks of this skill activate when E3 (web UI tab) + E2 (CLI)
|
|
64
|
+
land. Before that, the board renders nowhere — publishing is a daemon-side
|
|
65
|
+
rehearsal only, and the mandate sections are inert by the honesty table in
|
|
66
|
+
`using-the-dashboard`.
|
|
67
|
+
|
|
68
|
+
## Refs to other skills
|
|
69
|
+
|
|
70
|
+
- `using-the-dashboard` — surface + CLI contract + honesty table (invoke first)
|
|
71
|
+
- `coordinator-running-brainstorm-cycles` — where board NEEDs come from
|
|
72
|
+
- `coordinator-managing-state-and-lifecycle` — state ownership the boards reflect
|