# Row 301 build notes (Launchpad): R6-N4, fold user-bus.mjs back into bus.mjs (#1808) Brief: docs/plans/2026-10-23_r6-followup-rows.md § Brief: R6-N4. Reviewer Duckworth, gate owner Sage. Base e551cd846 (refactor after row 303). Branch launchpad/row301. ## Change - packages/webui/src/bus.mjs: the user transport moves in beside humanCall, after `busReader`: `USER_CLI`, `userCall`, `busBusiness` and `userCaller`, byte for byte from user-bus.mjs (checked with diff), under a three-line header. One import is added, `fileURLToPath` from node:url. `readHostState`, `spawn`, `randomBytes` and `BusReadError` were already in bus.mjs. humanCall and busCaller are untouched. - packages/webui/src/user-bus.mjs: deleted. - packages/webui/src/cli.mjs: the two imports become one, from './bus.mjs'. - packages/webui/src/console-bus.mjs: a comment names bus.mjs instead of user-bus.mjs. - packages/webui/tests/granted-user.test.mjs:22-23: the two imports become one, from '../src/bus.mjs'. Only the import path changes. Mos ruled (mos-1449, via sage-3399) that this is covered by "update its imports" and is not an old-test change. No other reference to user-bus.mjs remains under packages/. tools/agent-watch's "user-bus" means something unrelated. The 294 packet's mutants name the old file as history only. ## Re-pin channel-proof.test.mjs:28 pinned packages/webui/src/bus.mjs at 15e8123f…3313. After the fold the file hashes to 39fcb27c82e917ef05e1a7a650d522c9f3c656bf8dbade87b8ddb3661b67ad6c. A pin change is an old-test change. Mos approved it under mos-1272 in mos-1449 (via sage-3399), as its own commit, with row 301 making its own re-pin window. Mos checked fd4b8c36e read-only: bus.mjs hashes to 39fcb27c, its diff removes no lines, user-bus.mjs from `export const USER_CLI` to the end is in it byte for byte, and nothing else imports user-bus.mjs. The second commit changes that one value and adds one comment line in the row 165/171/194 style. ## Gate Duckworth approves the manifest. channel-proof.test, the webui suite and the 294 user-transport tests (granted-user.test.mjs) run whole and green, on Sage's CLEAR. MANIFEST.sha256 lists the changed paths. DELETED.txt names the one removed path. ## Run 1 (sage-3408 CLEAR, 12:08Z, head 04a179740) npm ci root and webui green. channel-proof.test whole 2 pass 0 fail. The webui suite whole went 374 tests, 372 pass, 2 fail, 0 skipped, so the gate stopped. granted-user.test whole, run after the stop to see whether the stop hid another red: 19 pass 0 fail. No file changed. Both reds were in old tests: library-cli.test.mjs:10 (C2-04) and thread-claims.test.mjs:54 (row278 Console adapter). Each failed with `SyntaxError: The requested module './bus.mjs' does not provide an export named 'busBusiness'` at cli.mjs:5. Each test spawns cli.mjs with a registerHooks load hook that replaces /webui/src/bus.mjs with a fixture exporting only BusReadError and busCaller. Before the fold, cli.mjs took busBusiness and userCaller from the real user-bus.mjs. Now they come from the stubbed bus.mjs, so cli.mjs fails to link. cli.mjs calls them only under --sso (:98, :103), and neither test passes --sso. A URL-keyed stub is not an import, so the "nothing else imports user-bus.mjs" check and the static reviews missed it. `git grep "webui/src/bus.mjs" -- 'packages/*/tests/*'` finds exactly channel-proof, library-cli and thread-claims. ## Fixture change (mos-1451 under mos-1272, via sage-3418) Mos approved option A with one change and refused option B, a namespace import in cli.mjs. Each of the two busSource template strings (library-cli.test.mjs:17, thread-claims.test.mjs:58) gets this appended, and nothing else changes in either file: export const busBusiness=()=>{throw Error('busBusiness outside --sso')};export const userCaller=()=>{throw Error('userCaller outside --sso')}; The stubs throw rather than return null, so a test that reaches them outside --sso fails loudly. The text has no backtick, `${` or backslash, so the template literal carries it unchanged. The manifest goes from five paths to seven. Sage's gate: webui 374/0, channel-proof 2/0, granted-user 19/0. Any other red stops the gate and goes to Mos.