mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* refactor(mobile): pin each RPC golden to its own mount adapter, not every domain's `recorderSha256` covered the whole recorder directory, mount adapters included, so a domain PR that adds its adapter module moved the header of all 153 goldens. #20568 did exactly that and its merge with main conflicted on that one line in 153 files; every future domain PR would collide with every other in flight the same way. Split the directory at a real seam instead of a filename convention: `adapters/` holds one module per domain, registered in `adapters/mounted-operation-modules.ts`, and `recorderSha256` now covers the engine only. A new `adapterSha256` covers the source of the module that mounts each operation a golden's scenarios drive, read off the same `mounts` calls that build the table the recording runs against, so the pin cannot name a file the runner did not use. Adding a domain's module now re-digests nothing already recorded; editing one fails exactly the goldens mounted through it. `adapter-seam.test.ts` keeps the split from drifting: an engine file inside `adapters/`, an adapter defined in an engine file, a register entry naming the wrong file, and an adapter importing a sibling each fail. The five adapters that were inline in `pilot-mount-adapters.ts` move into their own modules, which leaves that file as the registry and nothing else. `GOLDEN_FORMAT_VERSION` goes to 5 for the new header field; the goldens re-record in the next commit. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): re-record the RPC goldens under the split recorder/adapter digest Header-only. Every changed line is `recorderSha256` (the engine digest no longer covers `adapters/`), the new `adapterSha256`, or `goldenFormatVersion` 4 -> 5; `baseline` is unchanged and recording ran against the same pinned product tree. git diff -U0 -- mobile/rpc-foundation/goldens | grep -E '^[+-]' \ | grep -vE '^(\+\+\+|---)' \ | grep -vE '^[+-] "(recorderSha256|adapterSha256|goldenFormatVersion)":' | wc -l 0 The seven `adapterSha256` values partition the 153 goldens by the module each was recorded through: 58 settings, 37 hosted review, 21 source control, 11 new-tab agents, 9 file inventory, 9 tasks, 8 workspace settings. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * refactor(mobile): stop pinning goldens to recorder inputs no recording can read The adapter split left three per-domain edits still moving all 153 headers: the mutant table, the per-family mutant registry beside it, and the probe-hole witness. None can change a recording -- the loader consults a mutant only when a mutant test asks for one, and no suite but the two recording drivers writes a golden -- so pinning them claimed a provenance the goldens do not have and charged every domain a full re-record for it. `mutants/` now holds the table, the registry, the reference states, the mutant suites and the probe-hole witness, and `recorderSha256` skips it. What makes that sound is that no recording can reach it: `operationModuleLoader` takes a resolved mutation spec instead of importing a table by name, so nothing on the recording path names `mutants/` at all. `mutants/mutant-seam.test.ts` checks exactly that, and fails if an engine file names the directory or anything outside imports from it. `recorderSha256` also pins only the suites in `recording-drivers.ts`, which `scripts/rpc-recording.mts` records from, so the two cannot drift. A suite that reads goldens, or writes one to a scratch directory, is no longer provenance for a recorded file. `OPERATION_EXPOSURES` went the other way, because it does change what a recording loads: withhold the resume-metadata exposure and exactly four goldens fail. Each domain module now declares its own exposures and gets its own loader, so `adapterSha256` pins the ones that reached each golden. Two assertions in the digest boundary test were vacuous: `join(root, '.')` normalises back to `root` and hit `recorderSha256`'s per-root cache, so the prose-is-ignored claim never recomputed anything. Each call now spells the root differently. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): re-record the RPC goldens under the mutant and driver exclusions Header-only, and no format bump: the header shape is unchanged. `recorderSha256` moves on all 153 because the engine set shrank, and `adapterSha256` moves on the 58 settings goldens because that module now carries its own exposure declaration. git diff -U0 HEAD~1 -- mobile/rpc-foundation/goldens | grep -E '^[+-]' \ | grep -vE '^(\+\+\+|---)' \ | grep -vE '^[+-] "(recorderSha256|adapterSha256)":' | wc -l 0 Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * fix(mobile): restore the preferences actions the merge resolution dropped #20568 added `resume` and `trust` actions to the `settings.task-preferences` adapter while it still lived in `pilot-mount-adapters.ts`. This branch had already moved that adapter into `adapters/task-mount-adapters.ts`, so resolving the `pilot-mount-adapters.ts` conflict in favour of the registry merge silently discarded them and `tw-task-preferences-resume-write` failed to record at all ("Missing or completed request: ui.set#1"). Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): re-record the RPC goldens at main's tip after the merge All 208 goldens, header-only. `baseline` moves from50e752fc66to main's tipc6a7216984, `goldenFormatVersion` from 4 to 5, `recorderSha256` to the value of the engine with `adapters/` and `mutants/` carved out, and `adapterSha256` is new on every file. Nine distinct adapter digests over 208 goldens: each golden now pins only the module that mounts it. No observation moved. The whole-diff census against origin/main reports exactly four changed keys and nothing else: 208 "adapterSha256": 416 "baseline": 416 "goldenFormatVersion": 416 "recorderSha256": Recorded in place rather than through the README's detached-baseline dance: this branch changes no product file, so its tree at the merge is byte-identical toc6a7216984under mobile/src, src/shared and the lockfile, and the parity claim stays non-circular. README says so now. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): hold the recording drivers to the engine's mutant-seam rule The name scan exempted every `.test.ts` on the ground that a test cannot change a recording. Two of them can: the recording drivers are the recording path. A driver that read the mutant table by path rather than importing it passed both seam checks — the import scan sees no import, and the name scan waved it through as a test: const table = resolve(import.meta.dirname, 'mutants/operation-mutations.ts') console.log(readFileSync(table, 'utf8').length) at the top of `pilot-recordings.test.ts` gave 2 passed before, and after this change fails with ["pilot-recordings.test.ts"]. Only non-driver tests are exempt now. This file lives in `mutants/`, which `recorderSha256` skips, so no golden moves: the recorder suite is green on the existing 208 with zero dirty. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * refactor(mobile): drop the registry parameter no caller varies `pilotMountAdapters` took `registered` so a caller could mount a different module set; all six callers take the default. The header-digest tests vary the registry through `goldenRecording`, which keeps its own parameter and is where the stub roots need it. Engine source, so `recorderSha256` moves and the goldens follow in the next commit. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): re-record the RPC goldens after the registry parameter came out All 208, `recorderSha256` only. The re-record against the previous commit moves 416 lines, every one of them that field: 416 "recorderSha256": Against origin/main the picture is unchanged from the merge: 208 goldens, 0 added or deleted, 0 non-header lines, and exactly four keys differing — 208 "adapterSha256" 416 "baseline" 416 "goldenFormatVersion" 416 "recorderSha256" Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * docs(mobile): wrap the recording README at the width the rest of it uses Seven lines this branch added ran past 100 columns, worst 124. No wording changed. Markdown is outside `recorderSha256`, so no golden moves. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * docs(mobile): name the worktree overlay, not the archive that cannot work `git archive` was offered alongside a detached checkout as a way to lay this branch's recorder over the pinned baseline. It cannot work: the fence in scripts/rpc-recording.mts runs `git diff --quiet <baseline>` and an untracked-file check, both of which need a real `.git`. In an archive tree git exits non-zero for lack of a repository and the script reports "Product sources or lockfile differ from the pinned main baseline", which reads as a product mismatch that is not there. The transport agent lost time to exactly that. Names `git worktree add --detach` only, and says what the misleading failure looks like if someone tries an archive anyway. Markdown is outside `recorderSha256`, so no golden moves. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): close two ways an adapter module escapes its own digest Two holes, one class: the seam was checked by how an import was spelled and by what the register's values evaluated to, never by where they resolve or where they were written. Inward imports: the scan dropped every specifier starting with `..`, so `'../adapters/settings-mount-adapters'` climbed out of the directory and back into it unseen. A reviewer had `new-tab-agent-mount-adapters.ts` project a value read from the settings module, edited that module, and watched the mounted state change while the new-tab adapter digest held. Specifiers now resolve against the directory and anything landing back inside it fails: ["new-tab-agent-mount-adapters.ts imports ../adapters/settings-mount-adapters"] The register: `adapters/mounted-operation-modules.ts` is pinned by nothing — `recorderSha256` skips the directory and `adapterSha256` reads each entry's `source`. An `exposes` written inline there drives the mounted product module with no digest covering it. The same reviewer replaced the new-tab entry's `exposes` with a literal overriding `loadMobileNewTabAgentOptions`; twelve fence tests passed. Both `mounts` and `exposes` must now be identifiers the register imports from that entry's own module: ["new-tab-agent-mount-adapters.ts writes exposes inline instead of importing it"] Checked on the register's syntax, not its values, because an inline literal and an imported binding are indistinguishable once evaluated. Pinning the register in the engine digest would also close it, and is the wrong trade: every domain adding a register line would re-digest all 208 goldens, which is the conflict this PR exists to remove. Keeping the register an index costs nothing and keeps a domain's line local. Both fixes live in a `.test.ts` outside the drivers, so no golden moves. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): prove the mutant seam from the drivers out, not by spelling The seam rested on a grep for the literal `mutants`, which the exported `MUTANT_DIRECTORY` spells without containing. A reviewer had `pilot-mount-adapters.ts` read the mutant table through that constant and both checks passed. The README's claim — that nothing on the recording path names the directory — was false as written. Three changes, in order of strength: Reachability is now proved forward. The suite walks the static import graph from the two recording drivers and fails if any module under `mutants/` is in it. That answers the real question, what a golden's bytes can depend on, instead of the old inward scan's question, who mentions this directory. Non-emptiness is asserted on both sides so a graph that resolved nothing cannot pass by reaching nothing. The name scan covers both spellings, for paths a module can be read by rather than imported. The reviewer's probe now fails as ["pilot-mount-adapters.ts"]. `MUTANT_DIRECTORY` is no longer exported. Its two consumers were both tests of the digest, and they now spell the path instead, which is strictly better for them: a test that imports the constant follows a rename silently, while one that spells it fails on a rename — and that specific directory name is the whole soundness argument. This edits `recorder-digest.ts`, so the goldens re-record in the next commit. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): re-record the RPC goldens after MUTANT_DIRECTORY stopped being exported All 208, `recorderSha256` only. Against the previous commit the diff is 416 lines and every one of them is that field: 416 "recorderSha256": Against origin/main, unchanged: 208 goldens, 0 added or deleted, 0 non-header lines, four keys differing — 208 "adapterSha256" 416 "baseline" 416 "goldenFormatVersion" 416 "recorderSha256" Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * docs(mobile): state the mutant seam's actual argument, and its edge The README claimed nothing on the recording path names `mutants/`. That was the old inward scan's claim and a reviewer falsified it with the exported constant. It now describes what the check does: a forward walk of the import graph from the two recording drivers, plus a name scan in both spellings for read-by-path, plus the constant no longer being exported. It also names the case neither closes — a path assembled from fragments at runtime. Markdown is outside `recorderSha256`, so no golden moves. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): prove the engine/adapter seam in both directions The inward scan only held adapters to the seam. An engine file importing an adapter executes code its own digest skips and that every golden recorded through another domain leaves out of `adapterSha256`, so the register is now the only crossing allowed from the engine side. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * test(mobile): name what the driver walk missed instead of counting it Seeding `seen` with the drivers made the driver-presence check true by construction, and the size bound compared a graph inflated by `typeof import` product modules against a recorder-sized number. Both go; the walk now reports the recording files it failed to reach, which is empty today and names an orphan engine file the moment one appears. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb * docs(mobile): reflow four paragraphs left ragged by the rewrap Orphan fragments only, no wording change: the golden-schema field list, the mutant-evidence paragraph, the probe-witness sentence and the re-anchor note. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb