diff --git a/BUILD-LOG.md b/BUILD-LOG.md index f504378d5..dae0a3513 100644 --- a/BUILD-LOG.md +++ b/BUILD-LOG.md @@ -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`. diff --git a/docs/plans/2026-09-26_lead-decisions.md b/docs/plans/2026-09-26_lead-decisions.md index 109eb8365..0a0fc2095 100644 --- a/docs/plans/2026-09-26_lead-decisions.md +++ b/docs/plans/2026-09-26_lead-decisions.md @@ -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. diff --git a/docs/plans/2026-10-11_claude-pin-and-coder-grant.md b/docs/plans/2026-10-11_claude-pin-and-coder-grant.md new file mode 100644 index 000000000..e425fe1cc --- /dev/null +++ b/docs/plans/2026-10-11_claude-pin-and-coder-grant.md @@ -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-/` + +### 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-/` + +### 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.