docs: lead decision 91, row 68 build log, pin and coder grant brief (#1561)

Decision 91 amends 89: the bus pins ~/.local/bin/claude through
MOSAIC_CLAUDE_BIN, so the package upgrade is no longer needed for the
first PM launch. The brief covers two Rocko rows: tests for row 68's
surviving mutants, and dropping the coder's dead task.reassign grant.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-11 16:47:15 -05:00
co-authored by Claude Opus 5.5
parent 4100fa68c0
commit 32aa572788
3 changed files with 145 additions and 0 deletions
+8
View File
@@ -4226,3 +4226,11 @@ Gate (Sage, scratch worktree of 918a4a19 plus the candidate, sequential and teed
Live read (`agents/sage/work/vikunja-setup/tick-62.mjs`, record `2026-10-11_tick-62.json`, 902b3d0e), 21:28:03Z, tasks.woltje.com v2.7.0: the candidate's own `reconcile()` and `tick()` with descendants on, root #19, the sync key only, a real Store and Broker in a scratch root, and a fetch guard refusing anything but GET. `startup()` was not run, since its scope probes send a PATCH, a DELETE and a POST as role keys; the script made the root's install check from the same two reads. Reconcile 15 GETs, 42 snapshots (30 on #19, 4 on 18, 3 on 20, 5 on 21; the cross-project probe in `2026-10-11_probe-62.json` also counted 42). Tick 8 GETs, 0 snapshots, the count `probes.md` predicted. 18, 20 and 21 are watch-only. 0 writes. Darkwing's deleted-view probe: a missing view id on #18 answers 404 code 3014 while `GET /projects/18` answers 200, so the README's account holds live (the child stays and the tick fails until the next reconcile reads it watch-only, which Filbert notes stops the root's tick too). The fake answers 13001; the adapter treats any 404 without code 4002 the same, so behavior doesn't change. No README change needed. The live bus is still on descendants off (host config `tracker.descendants` false); turning it on is a config change for when row 63 lands.
Row 62 done at rev 452 (86f65766); #1555 closed with comment 27352. Follow-up: row 71, #1565, brief 9d715276, owner Darkwing, after their rows 58, 61 and 69: tests for the surviving confirm-read mutants (`r3-confirm-4xx`, `r3-confirm-error-on-throw`) and the fake's view 404 set to 3014.
### 2026-10-11 — Sage, row 68 landed: the bus host runs an explicit Claude Code binary (#1561)
Round 1 (manifest a2008d8b, base a86de1f1) had both approvals, Filbert 27349 and Dewey 27350, but couldn't land. Row 55 (79d9fc2d) changed `docs/TOOLS.md` and `packages/cli/README.md` after that base, and a manifest pins whole files. Round 2 (`agents/sage/work/queue-68/r2/`, b31cc8a9, manifest 21c1ab05) is round 1's patch applied on f2f2861b with `git apply --index --3way`; its `+` and `-` lines are byte-identical to round 1's. Sage's gate on f2f2861b plus the patch finished 21:37:18Z: cli 112, seat 27, harness 57 node tests and nine `scripts/test-*.sh`, all 0 failed, Docker on, manifest OK before and after. Filbert approved round 2 (27374), Dewey too (27375, after a rerun: their first harness run failed 5 pi tests on a missing node_modules link).
Landed as 11dae0c7; `queue review verify-commit 68 11dae0c7` matched the manifest (13 paths). Installed 21:42:39Z with `bus-service.sh install --claude /home/jwoltje/.local/bin/claude`: the unit's diff was its comments and `Environment=MOSAIC_CLAUDE_BIN=/home/jwoltje/.local/bin/claude`, then `daemon-reload` only. The symlink resolves to 2.1.296. Probe at 21:43:03Z, `adapters/claude/adapter.sh` under `env -i` with the unit's PATH, claude-opus-5-5, empty settings and MCP config, in a scratch dir since removed: the pin answered "OK" rc 0; `/usr/bin/claude` (2.1.259) got "2.1.280 or newer is required" rc 1. The running bus (PID 1242258, since 13:19:28 CDT) was not restarted; it picks up the pin at Mos's watched Q18 `--pm` restart. Lead decision 91 amends 89: Jason's package upgrade is no longer needed.
Row 68 done at rev 463 (4100fa68). The surviving mutants (a directory pin in both scripts, the symlink default, an adapter pin with a space) and the dead `task.reassign` grant in `roles/coder.json` that decision 90 named go to two Rocko rows, brief `docs/plans/2026-10-11_claude-pin-and-coder-grant.md`.
+23
View File
@@ -1919,3 +1919,26 @@ which stay with him. Each item names who decided it and what happened.
reviewer who isn't assigned can't comment on the task through the
bus. If slice 1 acceptance needs that, it is a new verb or a
change to `task.update.assigned`, decided then.
91. **The bus pins the user's Claude Code binary; this amends 89
(2026-10-11).** Decision 89 left the bus on `/usr/bin/claude` and made
the fix Jason's package upgrade. Row 68 (#1561, 11dae0c7) took the
other path: `bus-service.sh install --claude PATH` writes
`Environment=MOSAIC_CLAUDE_BIN=PATH` into the unit, and the claude
adapter runs that binary when it is set.
- Installed 2026-10-11T21:42:39Z with
`--claude /home/jwoltje/.local/bin/claude` (a symlink, now to
2.1.296). The unit's only change was that line and its comments;
`daemon-reload` only, no restart.
- Probe at 21:43:03Z, the adapter under `env -i` with the unit's PATH
and claude-opus-5-5: the pinned binary answered "OK", rc 0;
`/usr/bin/claude` still gets "2.1.280 or newer is required", rc 1.
- Jason's sudo upgrade is no longer needed for the first PM launch.
The pacman package stays installed and untouched. The running bus
(PID 1242258, up since 13:19:28 CDT) keeps its old environment until
Mos's watched Q18 `--pm` restart; Sage doesn't restart it.
- The tradeoff: the symlink follows the user's auto-updates, so a bad
Claude Code release reaches the bus at its next restart without a
review. Decision 89 valued the root-owned package for that reason.
No version floor check runs at start; one would catch a
downgrade, not a bad upgrade. Re-pinning to a versioned path is one
`install --claude` away if a release breaks it.
@@ -0,0 +1,114 @@
# Follow-ups after row 68 and lead decision 90 (2026-10-11)
Status: written by Sage, lead. It follows `docs/plans/BRIEF-TEMPLATE.md`.
Two rows, both small, both Rocko's.
## Claude pin tests: a directory pin, a symlink default, a pin with a space
### Problem
Row 68 (#1561, commit 11dae0c7) pins the bus's Claude Code binary with
`MOSAIC_CLAUDE_BIN`. Filbert (comment 27349) and Dewey (comment 27350)
approved it and named mutants no test kills:
- `bs-no-f`, `ad-no-f`, `bs-x-only` and `ad-x-only`. The `[ -f … ]` check
in `scripts/bus-service.sh` (`claude_line`) and in
`adapters/claude/adapter.sh` can go and every test still passes. A
directory is `-x`, so the unit would carry a directory pin, and the
adapter would fail at exec (exit 126, "Is a directory") instead of
exiting 2 with its own message.
- `bs-resolve-default`. Resolving the default `command -v claude` with
`readlink -f` passes, because the test's `claude` on `PATH` is a plain
file. On Jason's host `~/.local/bin/claude` is a symlink, and the pin is
meant to keep the symlink so updates follow.
- `ad-unquoted-run`. The adapter runs `"$CLAUDE"`. Unquoted, a pin with a
space breaks. `bus-service.sh` refuses a space, but the adapter takes a
hand-set pin. Nothing in the adapter checks the pin's characters.
`bs-status-no-env` and `bs-sed-unanchored` stay untested; both reviewers
asked for no test.
### Owner and reviewer
Owner: Rocko. Reviewer: Filbert. Rocko has no Gitea token; Sage runs the
review request as jarvis.
### Files owned
- `packages/cli/tests/host.test.mjs`
- `packages/harness/tests/claude-session.test.mjs`
- `agents/rocko/work/queue-<row>/`
### What ships
- A `render --claude DIR` test and a default test where the `claude` on
`PATH` is a directory: both refuse with "not an executable file" and
print nothing on stdout.
- A default test where the `claude` on `PATH` is a symlink to an
executable: the unit's `MOSAIC_CLAUDE_BIN` is the symlink path, not its
target.
- An adapter test with `MOSAIC_CLAUDE_BIN` a directory (exits 2 before
anything runs) and one with a stand-in under a directory whose name has
a space (runs).
- The packet reruns the six named mutants against the candidate and lists
each killed.
### Out of scope
Any change to `bus-service.sh`, `adapter.sh`, the launcher or the seat
session code. If a test shows the code is wrong, stop and tell Sage.
### Gate
Filbert approves on the row's issue naming the candidate manifest. The
cli and harness node suites and every `scripts/test-*.sh` green on Sage's
gate rerun.
## Coder role: drop the task.reassign grant the broker always refuses
### Problem
`roles/coder.json` lists `task.reassign` under `crossRole`. The task verbs
refuse every pm-only verb to any other role (`packages/tasks/src/verbs.mjs`,
`PM_VERBS`, `field-writer`), so a coder's resolved decision to reassign
always ends in `field-writer`. Lead decision 90 kept assignee pm-only and
named this a dead grant for its own row. A grant that can never succeed
misleads anyone reading the role file and wastes a decision round.
### Owner and reviewer
Owner: Rocko. Reviewer: Dewey. Sage runs the review request as jarvis.
### Files owned
- `roles/coder.json`, the `crossRole` list only
- any test that lists the coder's grants, and a bus test for the
classification
- `agents/rocko/work/queue-<row>/`
### What ships
- `task.reassign` removed from the coder's `crossRole`; `task.scope.change`
stays.
- A test that the broker now classes a coder's `task.reassign` as
`gated`, not `cross-role` (`packages/bus/src/broker.mjs`,
`#classification`: an action in neither list is gated). The verb
still refuses with `field-writer` if it ever runs.
- The packet lists every place that read the old grant (role resolution,
tests, docs), with what each now says. It also says plainly what a
coder's `task.reassign` does end to end after the change. A gated
request asks a human for a decision that can only end in
`field-writer`. Refusing it before any decision opens is a broker
change and would be its own row. The packet names it; it doesn't make it.
### Out of scope
Any other role's grants, the `PM_VERBS` set, `broker.mjs` and the slice 1
field table.
Who may reassign doesn't change; only the grant that never worked goes.
### Gate
Dewey approves on the row's issue naming the candidate manifest. The
tasks, bus, business and harness node suites and every `scripts/test-*.sh` green
on Sage's gate rerun.