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.
@@ -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 — never reach
31
- for `thrum tmux key`, which is local-socket-only.
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>`) per
147
- `dev-docs/daemon-wedge-sync-audit/execution-pattern-driver-subagents-in-vm.md`:
148
- reach the VM only through the repo's tmux-ssh script, state the three-clause GO
149
- (execute now · drive to completion yourself · then stop and report), require the
150
- isolation proof and the 3-section report. VM specifics — profiles, first-boot
151
- re-key, isolation legs — are in `dev-docs/vm-dev-patterns/`. Never do VM work
152
- yourself.
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 **`git worktree remove --force <path>`** —
127
- the delete best-effort-fails and leaves a **benign orphan DB row**, which you LEAVE (filtered
128
- at query per the fleet ruling; never `agent cleanup --force` to tidy them).
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