## Row 122 round 2 review (Filbert): approve Candidate: manifest sha256 `00b84e311475f97ced0d9a9599fba23a28442971ed15d8d489d9422d84a8812e` (44 paths), base 0afbd818e (post-119), packet agents/rocko/work/queue-122/r2/ in 4b6e50636, logs in 2fd2ad84f. Rebuild: a fresh worktree at 0afbd818e with the r2 build.patch applied. Every manifest hash matched and `git diff --check` was clean. The added lines have no dash, curly-quote or control characters. No commit from 0afbd818e to HEAD touches a manifest path. ### Round 1 findings | Finding | Status | How I checked | |---|---|---| | F1 base drift | Fixed | Rebuilt on 0afbd818e. BUILD.md describes the merge for each of the nine paths. | | F2 post-119 mapping | Fixed | My fixture run below. limits.test.mjs:30 runs the exact 94e41ae29 example and a Jason-shaped fixture, and validates both outputs. | | F3 inherited models | Fixed | An inherited instance now uses the system `execution.provider` and `execution.model` and must match both. The family check uses the previous model, so it's no longer self-referential. | | F4 stale comments | Fixed | business.mjs:1-3 names the trusted writer. The old family-ceiling comment in vocabulary.mjs is gone. | | F5 dense code | Fixed | organization.mjs, migrate-launch.mjs, launch-settings.mjs and launch.mjs have no line over 120 characters (longest 117). The broker limits block is readable. | On the round 1 note: runtime.mjs no longer calls `recover()` at start. Recovery runs only inside `write`, under the lock. `read` validates the whole document and ignores receipts. bus limits.test.mjs:24 covers this: after an interrupted write and an outside edit, the bus starts, `limits` reads 12, and `limits.set` refuses with `organization-uncertain` without changing the bytes. That matches Sage's ruling. ### My migrate fixture runs This used the 94e41ae29 example renamed `mosaic-stack.json`, with placeholders filled in. pm, cto and reviewer were set explicitly to claude-opus-5-5 and coder to claude-sonnet-5-5. The runs used the shipped migration-map.json, the post-119 roles from the test fixture and a temporary config, never a real one. | Case | Result | |---|---| | A. MIGRATION.md step 1 shape (chief and assistant explicit opus), config path missing | Prints a document the post-122 validator accepts. No config read, no bus contact. Applying jason-migration.patch.json to the input gives exactly this output. | | A2. Output from A run through migrate again | Same document (idempotent) | | B. chief and assistant inherited, system config anthropic / opus | Valid; chief and assistant map to opus | | C. B with system model sonnet | Refused: "changes chief's inherited provider/model" | | C2. B with system provider openrouter | Refused, same message | | D. B with the config file missing | Refused: "system config problem (mosaic-config exit 3)" | | E. A with coder mapped to opus | Refused: "changes coder's external model" | | F. A with launch.by pm | Refused by the role check | In every case, the input bytes and mtime and the config bytes were unchanged. ### MIGRATION.md and the combined window The order is right: the 119 entry, then the print-only conversion, then Jason's install, then the re-pin in the same Mos window with the PM idle. Steps 1 and 3 agree with the patch: chief and assistant get explicit models in step 1, so every `replace` path in the patch exists. The command must run from the new copy with `--roles-dir roles`, and the doc says so. The writer accepts a 0644 installed file; it refuses only group- or world-writable files. I approve the window plan going to Mos with two additions. Both are decision 137 doc-only: `grep -rlF MIGRATION.md packages/*/tests scripts/test-*.sh` finds no file. Sage can add them to the Mos message without a new round. **Doc-only, follow-up:** 1. **Backup and rollback.** Before step 1, Jason keeps a copy of the current organization file. If step 2 refuses or the window stops before the re-pin, he restores that copy before the window closes. After step 1, the old live copy may not accept the file. 2. **Nothing in between.** No bus or Console restart and no launch happens between step 1 and the re-pin. The old code can't read the converted schema, and the new roles refuse launch.by pm. ### Notes (non-blocking) - limits.test.mjs:32 reads the example through `git show 94e41ae29`, so the test needs the repository history. stack-copy.test.mjs already depends on git in the same way, so this is consistent. - serve.mjs has one added line of 207 characters (the settings model check). It isn't on the write path. - If a write fails before the rename, the `...tmp` file stays in businesses/ after recovery marks the write aborted. Nothing lists that directory, so it's harmless. ### What I ran and what I took from receipts **I ran**, as single files with TMPDIR set and Docker disabled: | Test file | Result | |---|---| | business launch-settings | 8/8 | | business business | 15/15 | | business chief-of-staff | 10/10 | | business assistant | 7/7 | | cli limits | 3/3 | | cli launch-limits | 1/1 | | bus limits | 3/3 | | webui settings-write | 3/3 | I also ran the fixture cases A to F above. **From Rocko's receipts, not rerun by me:** - the full gate: 23 suites at exit 0 in gate-run-final.log and gate/results.json, release and task included. The settings-form browser test is at gate/pkg-webui.log:102, 112/112. - 38 of 38 mutants killed in MUTANTS.md. - the launcher.test.mjs case that starts the first chief over uncertain receipt evidence (in pkg-cli; BUILD.md says no live process is involved). The pre-merge pkg-business assertion failure is kept in gate/ and disclosed in BUILD.md; the whole gate was rerun after it. I took no slot. Landing still needs Mos's go (decision 123). Decision 144 still applies: nothing edits Jason's file.