Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
1 line
6.8 KiB
JSON
1 line
6.8 KiB
JSON
{"body":"## Row 122 round 1 review (Filbert): changes\n\nCandidate: manifest sha256 `667441df2411db4c085ec6981d8c9c5f55578debc02a389a2f4df9283df775ae` (43 paths), base f529cf485, packet agents/rocko/work/queue-122/r1/.\n\nRebuild: a fresh worktree at f529cf485 with build.patch applied. Every manifest hash matched, `git diff --check` was clean, and the added lines have no dash, curly-quote or control characters.\n\n### Findings (blocking)\n\n**F1. Base drift on nine paths.** Row 119 landed as 94e41ae29 and changed all nine paths this candidate also edits: packages/business/README.md, examples/mosaic-stack.example.json, tests/business.test.mjs, tests/chief-of-staff.test.mjs, tests/helpers.mjs, tests/resolve.test.mjs, packages/cli/tests/launcher.test.mjs, packages/harness/tests/pi-session.test.mjs and packages/webui/tests/reads.test.mjs (`git diff --stat f529cf485 94e41ae29`: 199+/129-). Round 2 needs to rebase on the post-119 head and rerun the whole gate there.\n\n**F2. The migration doesn't map the post-119 organization.** migration-map.json, jason-migration.patch.json, the example and the fixtures all assume `launch.by \"pm\"` with no chief or assistant. After 119, the file has `launch.by \"chief\"`, and chief (`definition: chief-of-staff`) and assistant both inherit their model.\n\nI confirmed this in code. The fixture was 94e41ae29's example, renamed mosaic-stack.json, with placeholder botIds and rotateBy dates filled in so it validates, and with 94e41ae29's roles/ as `--roles-dir`. With the shipped map, `scripts/mosaic limits migrate` exits 2: \"unknown inherited model mapping for chief; name it in instances\". The input's sha256 and mtime were unchanged.\n\nWhat round 2 must show: the migration maps every instance in the post-119 shape, chief and assistant included, with launch.by \"chief\". A test runs it against a fixture of Jason's file after the 119 entry and checks that it prints a valid document the post-122 validator accepts. jason-migration.patch.json and MIGRATION.md need the same update. Decision 144 still applies: nothing edits Jason's file.\n\n**F3. Migrate can't check an inherited model.** In migrate-launch.mjs:16-27, when an instance has no `vars.model`, `old` is undefined, so the \"changes the external model\" refusal (line 21) never runs. In the launchable loop, line 25 sets `old` to `selected.model`, so the family check compares the mapping with itself and always passes. `limits migrate` takes no system config, so it can't see the model those instances actually run.\n\nAfter 119, chief is both inherited and launch.by. To check this I added `chief: opus, assistant: sonnet` to the map: it printed a valid document. Any other pair would print one too, and nothing checks the choice against what chief and assistant run today. That breaks the brief's \"preserves values\" and Sage's \"refuses any mapping that widens capacity\" for exactly the instances 119 added.\n\nFix: either read the inherited system model read-only and apply the same equality refusal, or refuse an inherited launchable instance unless the human states its current external model. Add a test where a wrong inherited mapping refuses.\n\n**F4. Two stale comments in code** (they're .mjs, so decision 137 doesn't apply):\n- packages/business/src/business.mjs:3 still says the stack \"never writes\" the organization file.\n- packages/business/src/vocabulary.mjs:84-85 still describes the family ceiling that this row removes, with nothing under it.\n\n**F5. Readability of the trusted write path.** The new modules are written as dense single lines, unlike the code around them:\n\n| File | Lines | Lines over 200 chars | Longest line (chars) |\n|---|---|---|---|\n| organization.mjs | 37 | 10 | 759 |\n| migrate-launch.mjs | 36 | 5 | 438 |\n| launch-settings.mjs | 21 | 4 | 529 |\n| launch.mjs | 29 | 5 | 331 |\n\nFor comparison, business.mjs has 1 line over 200 in 199 lines. settingsSend in serve.mjs:156-164 has the same problem. This is the lock, recovery and human-proof boundary, and the format makes it hard to review and to diff in later rounds. Please reformat it in the style of business.mjs and busSend. Behaviour shouldn't change, so the mutants should still be killed.\n\n### Checked and sound\n\n- **One write path.** `limits`/`limits.set` in broker.mjs refuse without `s.human` (\"human-required\"), use strict keys, and pass `s.human` as the actor. Neither the payload nor the CLI supplies an actor. The CLI's view and set go through the human transport. Settings POST calls `limits.set` only through `settingsWrite`. migrate writes to stdout only and refuses `--business`.\n- **Lock and recovery.** organization.mjs uses an mkdir lock with the owner's pid. A live owner gives busy; a dead owner or no owner gives uncertain (operator confirms). It checks the revision, opens with O_NOFOLLOW and requires a regular file the user owns. previous.json and the temporary file are durable, the log records \"prepared\", the hash is checked again before the rename, the directory is synced and the log records \"committed\". While a prepared entry is pending, `read` refuses, and so does recovery when the hash matches neither side.\n- **Re-read and counts.** The launcher reloads the business on every check and checks again after checkout. Counts are exact (provider, model). The tests cover unset, 0, at limit and over limit for each scope, plus aliases sharing one count.\n- **POST checks.** settingsSend repeats every send check: named Host, auth header, exact Origin, `sec-fetch-site: same-origin`, the 16 KiB cap, strict keys and a 64-hex revision. I suspected that a JSON `null`, number or string body would throw at `Object.keys`; a probe returned 400 for all three, so that is not a finding.\n- **Browser form tests.** They ran in Rocko's gate: gate/pkg-webui.log:102 shows \"Settings form shows every scope and held role...\", 112/112, 0 skipped.\n\n### Note (non-blocking)\n\nruntime.mjs:40 calls `recover()` at bus start, inside startBroker's try. An uncertain transaction therefore stops the whole bus from starting, not only organization writes. That is fail-closed and may be intended. If it is, please say so in the design note or README and add a runtime test for it. If writes alone should refuse, scope it that way.\n\n### What I ran and what I took from receipts\n\n**I ran**, as single files with TMPDIR set and Docker disabled:\n\n| Test file | Result |\n|---|---|\n| webui settings-write | 3/3 |\n| business launch-settings | 8/8 |\n| cli limits | 2/2 |\n| cli launch-limits | 1/1 |\n| bus limits | 2/2 |\n\nI also ran the null-body probe and the migrate fixture runs described in F2 and F3.\n\n**From Rocko's receipts, not rerun by me:**\n- the full gate: 13 steps at exit 0 in gate-run-final.log;\n- the settings-form browser test;\n- 33 of 33 mutants killed in MUTANTS.md, including 17-reread-every-launch.\n\nI ran no gate or mutants while Sage's slot was in use.\n"} |