test: move the daemon-composition tests off the daemon's testing exports
Summary
Moved the daemon-composition suites to daemon owners, root command/module owners, and one public daemon composition test. The daemon package drops the 36 test exports freed by these consumers plus the unreferenced snapshot-interactor-capture test export. Shared daemon fakes gained a default-preserving option; the eager import-closure fixture now belongs to test-kit.
Test count and ownership evidence
Original paths below are under src/tests/daemon-composition. Old counts are the counts at b7c93e3a3. Head counts are the complete destination suite counts and include any tests that already lived there; rows are not additive.
| Original test | Old | Owner | Head destination suite(s) and count |
|---|---|---|---|
| android-dialog-readiness | 5 | a | packages/daemon/src/execution/tests/android-system-dialog-readiness.test.ts: 5 |
| app-event-delivery | 9 | a+c | packages/daemon/src/execution/app-events.test.ts: 8; src/core/interactors-app-events.test.ts: 3 |
| capture-disclosure | 12 | a | packages/daemon/src/execution/interaction/index-capture-disclosure.test.ts: 12 |
| generic-settle | 22 | a+c | packages/daemon/src/execution/generic-settle.test.ts: 14; src/commands/interaction/runtime/post-action-surface.test.ts: 4; settle-presented-surface.test.ts: 5; settle-default-quiet.test.ts: 11; settle-transition-baseline.test.ts: 5; settle-generic-surface.test.ts: 8 |
| gesture-admission-parity | 4 | a+c | packages/daemon/src/core/gesture-runtime-admission.test.ts: 3; src/platform-runtime-gateway-gesture-admission.test.ts: 4 |
| http-server-limrun-uploaded-apps | 1 | a+b | packages/daemon/src/server/http/http-server-limrun-uploaded-apps.test.ts: 1; src/daemon-runtime-limrun-public-http.test.ts: 1 |
| is-runtime | 13 | a+c | packages/daemon/src/execution/selector-runtime-is-admission.test.ts: 11; selector-runtime-is-reads.test.ts: 5; src/commands/interaction/runtime/selector-is.test.ts: 18 |
| perf-capture-session-resource | 1 | a+c | packages/daemon/src/core/session-capture-binding.test.ts: 1; src/platform-runtime-perf-capture-host.test.ts: 11 |
| providers-plugin-routing-parity | 3 | c | src/core/platform-plugin-registry-provider-routing.test.ts: 3 |
| request-dispatch-disclosure | 2 | a | packages/daemon/src/execution/request-dispatch-disclosure.test.ts: 13 |
| request-handler-chain | 13 | a+c | packages/daemon/src/sessions/request-handler-chain-routing.test.ts: 13; packages/platform-linux/src/interactor.test.ts: 2 |
| request-platform-providers | 9 | a+c | packages/daemon/src/server/request-platform-provider-context.test.ts: 4; src/platform-runtime-provider-scope.test.ts: 7 |
| request-router-android-modal | 3 | a | packages/daemon/src/server/tests/request-router-android-modal.test.ts: 3 |
| request-router-android-perf | 1 | a+c | packages/daemon/src/sessions/session-observability/internal/tests/session-perf-runtime.test.ts: 8; src/platform-runtime-perf-host.test.ts: 2 |
| request-router-android-snapshot-helper | 2 | a | packages/daemon/src/server/tests/request-router-android-snapshot-helper.test.ts: 2 |
| request-router-fill-text-stdin | 14 | a | packages/daemon/src/server/tests/request-router-fill-text-stdin.test.ts: 14 |
| request-router-lock-policy | 9 | a | packages/daemon/src/server/tests/request-router-lock-policy.test.ts: 9 |
| request-router-macos-app-lease | 4 | a | packages/daemon/src/server/tests/request-router-macos-app-lease.test.ts: 4 |
| request-router-open-claim-recovery | 1 | a | packages/daemon/src/server/tests/request-router-open-claim-recovery.test.ts: 1; existing src/tests/platform-runtime-claim-recovery.test.ts: 7 owns root recovery |
| request-router-provider-credentials | 2 | a | packages/daemon/src/server/tests/request-router-provider-credentials.test.ts: 2 |
| request-router-record-runtime-lock | 3 | a+c | packages/daemon/src/server/tests/request-router-record-runtime-lock.test.ts: 1; src/platform-runtime-gateway-recording.test.ts: 2 |
| request-router-recording-health | 2 | a | packages/daemon/src/server/tests/request-router-recording-health.test.ts: 2 |
| request-router-replay-scope | 4 | a | packages/daemon/src/server/tests/request-router-replay-scope.test.ts: 4 |
| request-router-replay-test-ime | 2 | a+c | packages/daemon/src/sessions/tests/replay-maestro/session-replay-runtime-maestro-dispatch.test.ts: 10; packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts: 28; packages/platform-android/src/lifecycle.test.ts: 19 |
| request-router-screenshot | 16 | a | packages/daemon/src/server/tests/request-router-screenshot.test.ts: 16 |
| screenshot-runtime | 12 | a | packages/daemon/src/execution/screenshot-runtime-execution.test.ts: 12 |
| selector-runtime-ambiguity-issuance | 4 | a | packages/daemon/src/execution/selector-runtime-ambiguity-issuance.test.ts: 4 |
| selector-runtime-backend | 2 | c | src/commands/interaction/runtime/wait-text.test.ts: 11; wait-stable.test.ts: 13 |
| selector-runtime | 2 | a | packages/daemon/src/execution/selector-runtime-get-lifecycle.test.ts: 2 |
| snapshot-command-runtime | 6 | a | packages/daemon/src/sessions/snapshot-command-runtime-cancellation.test.ts: 6 |
| snapshot-diff-runtime | 7 | a | packages/daemon/src/sessions/snapshot-diff-runtime-admission.test.ts: 7 |
| snapshot-quality-latch | 11 | a | packages/daemon/src/sessions/snapshot-quality-latch-disclosure.test.ts: 11 |
| snapshot-runtime-disclosure | 5 | a+c | packages/daemon/src/sessions/handlers/snapshot-runtime-disclosure.test.ts: 5; src/commands/capture/runtime/snapshot.test.ts: 35 |
| sparse-fallback-screenshot | 5 | a | packages/daemon/src/execution/sparse-fallback-screenshot.test.ts: 5 |
| wait-runtime | 35 | a+c | packages/daemon/src/execution/wait-runtime.test.ts: 17; src/commands/interaction/runtime/wait-text.test.ts: 11; wait-stable.test.ts: 13; wait-polling.test.ts: 16; wait-selector.test.ts: 9; wait-absent.test.ts: 16; wait-deadline.test.ts: 3; wait-capture-options.test.ts: 2 |
The application-lifecycle fixture/gateway and obsolete generic-settle/sheet-tree fixtures were retired after their consumers moved. The eager import-closure fixture moved to packages/test-kit. Its root and scripts consumers remain selected.
Title-level mapping for the reviewed suites
Each old test case in the wait, generic-settle, is-runtime, platform-provider, and open-claim-recovery suites maps to the destination that now drives its owning branch. Parameterized rows list every expanded case. No test in these suites was retired.
| Old title at origin/main | Destination file::title |
|---|---|
| sleep-only wait records in its admitted lifetime across rebuild | packages/daemon/src/execution/wait-runtime.test.ts::sleep-only wait records in its admitted lifetime across %s |
| sleep-only wait records in its admitted lifetime across retire | packages/daemon/src/execution/wait-runtime.test.ts::sleep-only wait records in its admitted lifetime across %s |
| a duration wait inspects no facts and binds no device | packages/daemon/src/execution/wait-runtime.test.ts::a duration wait inspects no facts and binds no device |
| an observing wait binds through the shared selector entry | packages/daemon/src/execution/wait-runtime.test.ts::an observing wait binds through the shared selector entry |
| a text wait binds the capture use once and polls through the bound operation | packages/daemon/src/execution/wait-runtime.test.ts::a text wait binds the capture use once and polls through the bound operation |
| a selector wait binds the capture use once and polls through the bound operation | packages/daemon/src/execution/wait-runtime.test.ts::a selector wait binds the capture use once and polls through the bound operation |
| a @ref wait binds the capture use once and polls through the bound operation | packages/daemon/src/execution/wait-runtime.test.ts::a @ref wait binds the capture use once and polls through the bound operation |
| a stable wait binds the capture use once and polls through the bound operation | packages/daemon/src/execution/wait-runtime.test.ts::a stable wait binds the capture use once and polls through the bound operation |
| strict wait absent refuses --scope before device admission | packages/daemon/src/execution/wait-runtime.test.ts::strict wait absent refuses --%s before device admission |
| strict wait absent refuses --depth before device admission | packages/daemon/src/execution/wait-runtime.test.ts::strict wait absent refuses --%s before device admission |
| an unavailable capture fact refuses an observing wait before binding | packages/daemon/src/execution/wait-runtime.test.ts::an unavailable capture fact refuses an observing wait before binding |
| a provider owner that cannot capture fails closed instead of borrowing the local runtime | packages/daemon/src/execution/wait-runtime.test.ts::a provider owner that cannot capture fails closed instead of borrowing the local runtime |
| a timed-out wait decorates its failure through the same single binding | packages/daemon/src/execution/wait-runtime.test.ts::a timed-out wait decorates its failure through the same single binding |
| a text wait is satisfied by the owner native reading when the tree never carries it | src/commands/interaction/runtime/wait-text.test.ts::a text wait is satisfied by the owner native reading when the tree never carries it |
| a read after a natively satisfied text wait captures instead of reusing the older tree | src/commands/interaction/runtime/wait-text.test.ts::a native text hit does not make an older captured tree fresh for the next read |
| a satisfied native reading short-circuits the poll without capturing | packages/daemon/src/execution/wait-runtime.test.ts::a text wait returns a native owner hit without capturing a snapshot |
| a negative native reading is not an answer ā the same poll consults the canonical tree | src/commands/interaction/runtime/wait-text.test.ts::runtime wait falls back to a snapshot after a native text miss |
| an owner that advertises no native reading polls the tree only | merged into packages/daemon/src/execution/wait-runtime.test.ts::an unavailable conditional native reading preserves the capture-backed wait path |
| native text failure cannot hide a canonical capture failure | packages/daemon/src/execution/wait-runtime.test.ts::native text failure cannot hide a canonical capture failure |
| an unavailable conditional observation preserves the capture-backed owner path | merged into packages/daemon/src/execution/wait-runtime.test.ts::an unavailable conditional native reading preserves the capture-backed wait path |
| the native text reading runs in the same runner context as the capture | packages/daemon/src/execution/wait-runtime.test.ts::the native text reading runs in the same runner context as the capture |
| a poll deadline aborts the in-flight capture, and aborts it as a deadline | src/commands/interaction/runtime/wait-deadline.test.ts::a poll deadline aborts the capture with a TimeoutError reason |
| the poll awaits the aborted capture instead of abandoning it | src/commands/interaction/runtime/wait-deadline.test.ts::the wait deadline awaits the capture after aborting it |
| a stalled capture reports capture-stalled with no readable captures | src/commands/interaction/runtime/wait-text.test.ts::a stalled capture reports capture-stalled with no readable captures |
| strict wait absent reports capture-stalled when every capture stalls | src/commands/interaction/runtime/wait-absent.test.ts::strict wait absent reports capture-stalled when every capture stalls |
| a runner restart that exhausts the wait reports typed restart evidence | src/commands/interaction/runtime/wait-polling.test.ts::runner restart exhaustion reports typed evidence without a readable poll |
| strict wait absent preserves runner-restart exhaustion as the deadline reason | src/commands/interaction/runtime/wait-absent.test.ts::strict wait absent keeps runner-restart exhaustion as the deadline reason |
| strict wait absent does not mask a runner restart after an earlier present capture | src/commands/interaction/runtime/wait-absent.test.ts::strict wait absent preserves runner-restart exhaustion over an earlier present capture |
| a runner-start that outlasts the wait reports readiness exhaustion, not a capture stall | src/commands/interaction/runtime/wait-polling.test.ts::readiness exhaustion preserves the %s phase |
| a target-discovery that outlasts the wait reports readiness exhaustion, not a capture stall | src/commands/interaction/runtime/wait-polling.test.ts::readiness exhaustion preserves the %s phase |
| strict wait absent reports readiness exhaustion over an earlier present capture | src/commands/interaction/runtime/wait-absent.test.ts::strict wait absent preserves readiness exhaustion over an earlier present capture |
| an earlier retriable refusal outranks readiness work on the final poll | src/commands/interaction/runtime/wait-polling.test.ts::an earlier retriable refusal outranks readiness work on the final poll |
| strict wait absent keeps its present evidence when a steady-state capture is cancelled | src/commands/interaction/runtime/wait-absent.test.ts::strict wait absent keeps target-present evidence when a steady-state capture is cancelled |
| a positive wait whose steady-state capture is cancelled reports the deadline, not readiness | src/commands/interaction/runtime/wait-text.test.ts::a positive wait whose steady-state capture is cancelled reports the deadline, not readiness |
| a readable capture that lacks the target stays target-absent, not capture-stalled | src/commands/interaction/runtime/wait-text.test.ts::runtime wait times out on text the polled snapshot does not carry |
| scroll --settle answers with the settled diff against the stored pre-action tree | packages/daemon/src/execution/generic-settle.test.ts::scroll --settle passes the stored baseline and attaches the observation with its issued refs |
| back --settle answers with the settled diff alongside the command result | packages/daemon/src/execution/generic-settle.test.ts::back --settle attaches the observation alongside the command result |
| scroll --settle attaches no diff across an app-to-sheet surface change and discloses it | src/commands/interaction/runtime/settle-generic-surface.test.ts::targetless scroll settle discloses the app-to-sheet surface change |
| scroll --settle attaches no diff across a sheet-to-app surface change and discloses it | src/commands/interaction/runtime/settle-generic-surface.test.ts::targetless scroll settle discloses the sheet-to-app surface change |
| back --settle attaches no diff across an app-to-sheet surface change and discloses it | src/commands/interaction/runtime/settle-generic-surface.test.ts::targetless back settle discloses the app-to-sheet surface change |
| back --settle attaches no diff across a sheet-to-app surface change and discloses it | src/commands/interaction/runtime/settle-generic-surface.test.ts::targetless back settle discloses the sheet-to-app surface change |
| the confirmation arms for one presented sheet whichever baseline flavour the route holds | merged into src/commands/interaction/runtime/settle-generic-surface.test.ts::targetless back settle confirms a dismissed sheet from the interactive baseline and ...from the full baseline |
| back --settle keeps the plain window when the stored tree presented nothing | src/commands/interaction/runtime/settle-generic-surface.test.ts::targetless back settle keeps the plain window when the baseline presented nothing |
| back --settle keeps the confirmation when a side effect outdated an absent stored tree | split between packages/daemon/src/execution/generic-settle.test.ts::generic settle drops an outdated presented-surface fact but keeps its stored nodes and src/commands/interaction/runtime/settle-generic-surface.test.ts::targetless back settle confirms a broad replacement when the baseline fact is unknown |
| the settle observation runs after the post-gesture stabilization marker | packages/daemon/src/execution/generic-settle.test.ts::the settle observation runs after the post-gesture stabilization marker |
| scroll --settle observes through the request-bound capture, once admitted | packages/daemon/src/execution/generic-settle.test.ts::scroll --settle observes through the request-bound capture, once admitted |
| scroll --settle still observes when the owner cannot capture | packages/daemon/src/execution/generic-settle.test.ts::scroll --settle still observes when the owner cannot capture |
| scroll without --settle takes no observation captures and issues no refs | packages/daemon/src/execution/generic-settle.test.ts::scroll without --settle takes no observation captures and issues no refs |
| an ended generic lifetime is refused before dispatch or settle construction | packages/daemon/src/execution/generic-settle.test.ts::an ended generic lifetime is refused before dispatch or settle construction |
| a generic command without the observation trait ignores a stray settle flag | packages/daemon/src/execution/generic-settle.test.ts::a generic command without the observation trait ignores a stray settle flag |
| an orphaned --settle-quiet is rejected before the command dispatches | packages/daemon/src/execution/generic-settle.test.ts::an orphaned --settle-quiet is rejected before the command dispatches |
| scroll stays successful when its lifetime retires during optional settle observation | packages/daemon/src/execution/generic-settle.test.ts::scroll stays successful when its lifetime retires during optional settle observation |
| held generic settle capture respects its lifetime after rebuild | packages/daemon/src/execution/generic-settle.test.ts::held generic settle capture respects its lifetime after ${change} |
| held generic settle capture respects its lifetime after retire | packages/daemon/src/execution/generic-settle.test.ts::held generic settle capture respects its lifetime after ${change} |
| scroll --settle without --settle-quiet uses the shorter default when the loop reads the simulator bridge | src/commands/interaction/runtime/settle-default-quiet.test.ts::a settle the simulator snapshot bridge performs uses the shorter default window |
| scroll --settle keeps the 500ms default when the loop reads the Apple runner | src/commands/interaction/runtime/settle-default-quiet.test.ts::the Apple runner tree read (same channel, different producer) keeps the 500ms default window |
| a stale bridge-sourced baseline does not shorten a settle the Apple runner performs | src/commands/interaction/runtime/settle-default-quiet.test.ts::a runner read during settle keeps the 500ms window despite a bridge-issued baseline |
| an admitted is inspects once, binds once, and answers through the bound capture | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::an admitted is inspects once, binds once, and answers through the bound capture |
| is absent uses the bound readAny capture for selector-first input without rects | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::is absent binds one unscoped readAny capture without rectangles |
| is absent bypasses a cached no-match snapshot before evaluating the bound capture | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::is absent bypasses the cached snapshot and binds a fresh readAny capture |
| is absent fails closed for a quality-less legacy iOS root-only capture | src/commands/interaction/runtime/selector-is.test.ts::runtime is absent fails closed for a quality-less legacy iOS root-only capture |
| is absent rejects depth and scope before binding with typed invalid arguments | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::is absent rejects depth and scope before binding with typed invalid arguments |
| an unavailable capture fact refuses before any bind | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::an unavailable capture fact refuses before any bind |
| an iOS session with no tracked app is refused with the open hint, not answered from a displaced capture | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::an iOS session with no tracked app is refused with the open hint, not answered from a displaced capture |
| an iOS session WITH a tracked app still answers, so the refusal is the plan split and not an iOS ban | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::an iOS session WITH a tracked app still answers, so the refusal is the plan split and not an iOS ban |
| an Android session with no tracked app proceeds, because the owner advertises the without-active-app capture | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::an Android session with no tracked app proceeds, because the owner advertises the without-active-app capture |
| a refused request reaches the device by no route at all | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::a refused request reaches the device by no route at all |
| a failing predicate answers COMMAND_FAILED from the bound capture | packages/daemon/src/execution/selector-runtime-is-reads.test.ts::a failing is predicate is COMMAND_FAILED, never a zero-exit pass |
| a miss on a surface that never settled carries the unsettled fact, and the re-read captures afresh | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::a miss on a surface that never settled carries the unsettled fact, and the re-read captures afresh |
| a read after a scroll that moved nothing carries the no-effect outcome, and the re-read reuses its settled tree | packages/daemon/src/execution/selector-runtime-is-admission.test.ts::a read after a scroll that moved nothing carries the no-effect outcome, and the re-read reuses its settled tree |
| request platform provider scope applies Apple tool provider only for Apple sessions | src/platform-runtime-provider-scope.test.ts::Apple provider scope uses the request device for Apple tool calls |
| request platform provider scope follows explicit apps selector for existing sessions | packages/daemon/src/server/request-platform-provider-context.test.ts::request provider context follows an explicit device selector for an existing session |
| request platform provider scope skips sharded test orchestration requests | packages/daemon/src/server/request-platform-provider-context.test.ts::request provider context skips sharded test orchestration requests |
| request platform provider scopes stay isolated across concurrent requests | src/platform-runtime-provider-scope.test.ts::concurrent provider scopes stay isolated |
| request platform provider scope applies web provider only for web sessions | src/platform-runtime-provider-scope.test.ts::web provider scope uses the context device |
| generic Apple runner provider cannot fall back to local recording authority | src/platform-runtime-provider-scope.test.ts::generic Apple runner provider cannot borrow local recording authority |
| request provider context preserves an explicitly empty request id | packages/daemon/src/server/request-platform-provider-context.test.ts::request provider context preserves an explicitly empty request id |
| focused Apple runner recording authority remains exact across recreated request scopes | src/platform-runtime-provider-scope.test.ts::Apple runner recording authority stays exact across recreated scopes |
| request platform provider scope follows explicit web selector | packages/daemon/src/server/request-platform-provider-context.test.ts::request provider context follows an explicit sessionless web selector |
| open reconciles a foreign dead owner through that owner state dir, never the daemon store | packages/daemon/src/server/__tests__/request-router-open-claim-recovery.test.ts::open composes claim recovery from the foreign owner state directory |
The daemon snapshot suite retains its response-success and stored-outcome assertions. Its user-facing no-effect warning assertion belongs to the root snapshot command suite, so it now lives in src/commands/capture/runtime/snapshot.test.ts as an explicit no-effect warning case.
Additional changed suites needed by the test-kit move: src/tests/daemon-composition/session-teardown-import-closure.test.ts: 3; scripts/tests/closure-growth-rule.test.ts: 13; scripts/tests/eager-closure-budgets.test.ts: 902; src/tests/cli-startup-import-closure.test.ts: 22; src/tests/snapshot-desktop-surface.test.ts: 4.
Classification: (a) daemon-owned tests now sit beside daemon modules and use package fakes; (b) only daemon-runtime-limrun-public-http.test.ts drives composed daemon behavior, through startDaemonRuntime and injected ports; (c) root command, platform gateway, and provider/plugin behavior sits beside its root owner. The shared command-surface option onlyStoreWhenSessionExists defaults to false. Rebased onto origin/main at 4c1c786968db, which includes #3728's seven daemon-export deletions. #3740 owns the Linux uninstall accepted limitation; its duplicate test and declaration change are absent from this branch.
Move commits and selection
Pure move commits precede edits: 1fab2e28d1 (27 R100 test moves), 12dba1c74c (1 R100 fixture move), 33c46ef8fe (1 R100 test-kit fixture move), 0698e9956b (1 R100 test move), and 13a6c588f9 (6 R100 test moves). git show --find-renames=100% reports those similarities. Functional test/fake edits are in cd4cbc0c50; the gate update is f1d699192c; review corrections are in 2757757ef9 and 00e44c6c3a; this coverage follow-up is 03d2a9e87a. src/commands/interaction/runtime/wait-text.ts matches origin/main.
vitest.config.ts selects root and package destinations in unit-core via src//.test.ts and packages//src//*.test.ts; it explicitly selects the touched scripts/tests gates. scripts/check-affected/checks.ts maps this suite to unit-ci, owned by the Coverage and Integration Tests jobs in .github/workflows/ci.yml. check:gate-manifest passed: 57 checks across 25 lanes. The Linux coverage smoke test and accepted-gap declaration are inherited from #3740 on main, not changed by this PR.
Mock and spy ledger
All 36 surviving vi.mock/spy entries have a positive response or recorded-call assertion in their destination suites. The negative-only Apple runner call guard is break-proved below.
- packages/daemon/src/server/tests/request-router-android-modal.test.ts:32 mocks Android mechanics; snapshotCalls and openAndroidApp assertions prove the modal/reopen route.
- packages/daemon/src/server/tests/request-router-android-modal.test.ts:110 mocks host runCmd; execCalls asserts the exact tap argv.
- packages/daemon/src/sessions/handlers/snapshot-runtime-disclosure.test.ts:15 substitutes legacy capture; response assertions verify targetActivation and its warning.
- packages/daemon/src/execution/generic-settle.test.ts:73 supplies the post-action capture; settled diff/ref assertions verify the capture result.
- src/platform-runtime-perf-host.test.ts:9 makes ADB fail with the typed host error; the metric reason/details and recorded dumpsys call are asserted.
- src/platform-runtime-perf-capture-host.test.ts:36 mocks Android mechanics; start/stop/cleanup calls are asserted.
- src/platform-runtime-perf-capture-host.test.ts:37 mocks Apple perf; xctrace start/cleanup calls and arguments are asserted.
- src/platform-runtime-perf-capture-host.test.ts:38 mocks the process host; termination and process identity calls are asserted.
- packages/daemon/src/server/tests/request-router-screenshot.test.ts:12 makes Android dialog observation deterministic; screenshot response and routed runtime arguments are asserted.
- src/tests/snapshot-desktop-surface.test.ts:12 mocks Linux capture; exact capture arguments and resulting snapshot are asserted.
- src/daemon-runtime-limrun-public-http.test.ts:45 mocks Limrun API I/O; list/create methods remain uncalled on public denial.
- src/daemon-runtime-limrun-public-http.test.ts:57 injects root runtime ports; gateway/lifecycle calls and shutdown are asserted.
- src/daemon-runtime-limrun-public-http.test.ts:64 injects provider composition; the Limrun runtime is installed and provider I/O stays at zero.
- packages/daemon/src/server/tests/request-router-replay-scope.test.ts:16 isolates Apple runner prewarm; replay reaches the bound app-switcher and scroll operations.
- packages/daemon/src/server/tests/request-router-replay-scope.test.ts:22 resolves the scripted iOS app; replay-created session response is asserted.
- packages/platform-android/src/lifecycle.test.ts:17 substitutes app lifecycle; open/close/observe call order is asserted.
- packages/platform-android/src/lifecycle.test.ts:194 pins Date.now; lifecycle action timestamps are deterministic.
- packages/daemon/src/execution/selector-runtime-is-admission.test.ts:38 mocks Apple runner operations; its no-runner assertion failed when a temporary runner call was injected, proving the mock records the forbidden call.
- packages/daemon/src/execution/selector-runtime-ambiguity-issuance.test.ts:56 replaces snapshot capture; the single-call assertion and tap-point result verify the issued refs came from that capture.
- packages/daemon/src/sessions/snapshot-quality-latch-disclosure.test.ts:22 supplies capture results; warning/latch transitions are asserted through runtime responses.
- packages/daemon/src/server/tests/request-router-record-runtime-lock.test.ts:27 controls target resolution; lock ownership and routed behavior are asserted.
- packages/daemon/src/server/tests/request-router-record-runtime-lock.test.ts:33 controls readiness; typed admission outcome is asserted.
- packages/platform-linux/src/interactor.test.ts:12 mocks Linux input; right/middle click, swipe, and unused press argv are asserted.
- packages/daemon/src/execution/interaction/index-capture-disclosure.test.ts:46 controls target resolution; capture disclosure results are asserted.
- packages/daemon/src/execution/interaction/index-capture-disclosure.test.ts:55 supplies interactor capture; target/warning results are asserted.
- packages/daemon/src/execution/interaction/index-capture-disclosure.test.ts:60 supplies readiness; response/error disclosure is asserted.
- packages/daemon/src/execution/request-dispatch-disclosure.test.ts:27 isolates Apple runner operations; route response and operation-spy calls are asserted.
- packages/daemon/src/execution/request-dispatch-disclosure.test.ts:33 supplies device readiness; dispatch/error path and call counts are asserted.
- packages/daemon/src/server/tests/request-router-lock-policy.test.ts:10 isolates Apple runner operations; route and app-switcher results are asserted.
- packages/daemon/src/server/tests/request-router-lock-policy.test.ts:16 supplies readiness; legacy dispatch and app-switcher calls are asserted.
- packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts:26 controls target resolution; inspection/bind calls and dispatched command are asserted.
- packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts:37 supplies readiness; refusal/dispatch behavior is asserted.
- packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts:40 resolves Apple apps; selected app and open call are asserted.
- packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts:45 supplies Android mechanics; open/IME lifecycle calls are asserted.
- packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts:53 supplies process identity; bind/open and cleanup outcomes are asserted.
- packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts:641 spies on recordAction; the recorded entry/ref is asserted.
Mutation evidence
The original 52 changed destination Vitest suites were mutation-checked during the migration review. The post-review root snapshot, wait, and generic-settle follow-ups received separate focused mutation checks. The mutants were reverted immediately after each focused run. The shared request-router mutation failed all 11 router suites (58 tests); the snapshot mutations failed all 5 snapshot suites; root runtime/facade probes failed their 10 suites (83 tests); the closure-fixture mutation failed its 5 suites (13 tests). Focused mutation runs that threw before an awaited lifecycle completed also emitted mutation-induced slow-test warnings; the unmutated changed-file run passed.
| Destination suite | Temporary behavior break that made it fail |
|---|---|
| packages/daemon/src/core/gesture-runtime-admission.test.ts | resolveBoundGestureRuntime throws |
| packages/daemon/src/core/session-capture-binding.test.ts | bindSessionPerfCapture throws |
| packages/daemon/src/execution/tests/android-system-dialog-readiness.test.ts | ensureAndroidBlockingSystemDialogReady throws |
| packages/daemon/src/execution/app-events.test.ts | resolveAppEventUrl throws |
| packages/daemon/src/execution/generic-settle.test.ts | dispatchGenericCommand throws |
| packages/daemon/src/execution/interaction/index-capture-disclosure.test.ts | dispatchFindReadOnlyViaRuntime throws |
| packages/daemon/src/execution/request-dispatch-disclosure.test.ts | discloseRequestDispatch throws |
| packages/daemon/src/execution/screenshot-runtime-execution.test.ts | resolveScreenshotGenericExecution throws |
| packages/daemon/src/execution/selector-runtime-ambiguity-issuance.test.ts | dispatchIsViaRuntime throws |
| packages/daemon/src/execution/selector-runtime-get-lifecycle.test.ts | dispatchGetViaRuntime throws |
| packages/daemon/src/execution/selector-runtime-is-admission.test.ts | dispatchIsViaRuntime throws |
| packages/daemon/src/execution/sparse-fallback-screenshot.test.ts | dispatchSnapshotViaRuntime throws |
| packages/daemon/src/execution/wait-runtime.test.ts | resolveBoundSelectorCapture throws |
| packages/daemon/src/server/tests/request-router-android-modal.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-android-snapshot-helper.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-fill-text-stdin.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-lock-policy.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-macos-app-lease.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-open-claim-recovery.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-provider-credentials.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-record-runtime-lock.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-recording-health.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-replay-scope.test.ts | createRequestHandler throws |
| packages/daemon/src/server/tests/request-router-screenshot.test.ts | createRequestHandler throws |
| packages/daemon/src/server/http/http-server-limrun-uploaded-apps.test.ts | createDaemonHttpServer throws |
| packages/daemon/src/server/request-platform-provider-context.test.ts | resolvePlatformProviderRequestContext throws |
| packages/daemon/src/sessions/tests/replay-maestro/session-replay-runtime-maestro-dispatch.test.ts | discloseRequestDispatch throws |
| packages/daemon/src/sessions/handlers/snapshot-runtime-disclosure.test.ts | dispatchSnapshotViaRuntime throws |
| packages/daemon/src/sessions/request-handler-chain-routing.test.ts | runRequestHandlerChain throws |
| packages/daemon/src/sessions/session-lifecycle/internal/tests/session-open-execution-runtime.test.ts | handleSessionOpenCommands throws |
| packages/daemon/src/sessions/session-observability/internal/tests/session-perf-runtime.test.ts | handleSessionObservabilityCommands throws |
| packages/daemon/src/sessions/snapshot-command-runtime-cancellation.test.ts | snapshot and diff dispatch functions throw |
| packages/daemon/src/sessions/snapshot-diff-runtime-admission.test.ts | dispatchSnapshotDiffViaRuntime throws |
| packages/daemon/src/sessions/snapshot-quality-latch-disclosure.test.ts | snapshot and diff dispatch functions throw |
| packages/platform-android/src/lifecycle.test.ts | bindAndroidApplicationLifecycle throws |
| packages/platform-linux/src/interactor.test.ts | swipeLinux receives a duration increased by 1 ms |
| scripts/tests/closure-growth-rule.test.ts | eagerClosureGraphOf throws |
| scripts/tests/eager-closure-budgets.test.ts | eagerClosureGraphOf throws |
| src/tests/cli-startup-import-closure.test.ts | eagerClosureOf throws |
| src/tests/daemon-composition/session-teardown-import-closure.test.ts | eagerClosureOf throws |
| src/tests/snapshot-desktop-surface.test.ts | eagerClosureOf throws |
| src/commands/interaction/runtime/selector-is.test.ts | createAgentDevice throws |
| src/commands/interaction/runtime/wait-stable.test.ts | createAgentDevice throws |
| src/commands/interaction/runtime/wait-text.test.ts | createAgentDevice throws |
| src/core/interactors-app-events.test.ts | getInteractor throws |
| src/core/platform-plugin-registry-provider-routing.test.ts | getPlugin throws |
| src/daemon-runtime-limrun-public-http.test.ts | invert the Limrun publicNetworkOnly admission guard |
| src/platform-runtime-gateway-gesture-admission.test.ts | createPlatformRuntimeGateway throws |
| src/platform-runtime-gateway-recording.test.ts | createPlatformRuntimeGateway throws |
| src/platform-runtime-perf-capture-host.test.ts | startApplePerfCapture throws |
| src/platform-runtime-perf-host.test.ts | Android sampleMemory throws |
| src/platform-runtime-provider-scope.test.ts | createRequestPlatformProviders throws |
| src/commands/capture/runtime/snapshot.test.ts | the no-effect outcome no longer adds its warning |
The negative-only Apple runner mock also has a break-proof: a temporary runner call was injected into dispatchIsViaRuntime; its focused suite failed because the mocked runner recorded one call. Reverted.
Post-review mutation evidence, from a disposable checkout at 61fea26f8 with the review patch applied: suppressing no-effect warning generation failed the root snapshot warning test; omitting the daemon capture's post-gesture stamp failed the stored-outcome assertion; and disabling the daemon's findText forwarding failed the native-hit case at its call assertion. Each mutation was reverted, and the disposable checkout was removed.
The wait fallback correction in 00e44c6c3a restores src/commands/interaction/runtime/wait-text.ts to the main version and places the native-read failure regression in packages/daemon/src/execution/wait-runtime.test.ts. The test drives handleSnapshotCommands through the real selectWaitObservationOperations binding. Its baseline suite passed 15/15. In a disposable checkout, removing the binding catch made this test fail: the response became UNKNOWN / native observation failed instead of COMMAND_FAILED / canonical capture failed with capture_failed. The mutation was reverted, the experiment diff matched the review patch, and the checkout was removed.
At head 03d2a9e87, ten isolated production mutants were detected after their focused baselines passed, then reverted:
| Behavior broken | Test failure |
|---|---|
| Remove runner-restart exhaustion classification | 2 wait-polling tests failed (14/16 passed) |
| Remove readiness-phase classification | Both readiness phase cases and the earlier-refusal precedence case failed (13/16 passed) |
| Treat a zero-readable cancellation as capture-truncated | 2 wait-polling tests failed (14/16 passed) |
| Treat a readable steady-state cancellation as capture-stalled | 1 wait-polling test failed (15/16 passed) |
| Route wait-absent capture-truncated through self-reported deadline handling | 1 wait-absent test failed (15/16 passed) |
| Change the deadline abort reason from TimeoutError to AbortError | 2 wait-deadline tests failed (1/3 passed) |
| Return before the aborted capture settles | All 3 wait-deadline tests failed |
| Suppress cross-surface settle disclosure | All 4 scroll/back surface cases failed (4/8 passed) |
| Ignore the presented fact for a full sheet baseline | The full-baseline confirmation test failed (7/8 passed) |
| Ignore the absent fact on a plain-window baseline | The plain-window confirmation test failed (7/8 passed) |
The mutation checkout was at 03d2a9e87ab8eaaeab3bb923170d06f3232610e9; it was built independently, restored to a clean tree, and removed.
Exports and remaining work
At the original base b7c93e3a3, packages/daemon/package.json had 78 exports / 77 testing entries. After #3728 merged, the rebase base had 71 / 70. This PR removes 37 more (36 freed by consumers and the unreferenced snapshot-interactor-capture export), leaving 34 total / 33 testing entries. R83 reports 46 expanded test-only exports against 83 at the merge-base; R84 reports 152 unmatched tests against 187. This PR adds no daemon testing-export subpaths, aliases, barrels, or export *. The remaining daemon testing exports belong to #3733 and the coordinated final layer. The root-only export map, no-export-star pin, ADR 0033 update, and any AGENTS.md surface note remain for after both sweeps merge.
Validation
Head: 03d2a9e87ab8eaaeab3bb923170d06f3232610e9, based on origin/main 4c1c786968db9c303e71e9ace3abadbd3d0f032d.
Passed at this head: CI=true pnpm install --frozen-lockfile && pnpm build, pnpm format, pnpm check:quick, pnpm check:layering, pnpm check:fallow, and pnpm check:gate-manifest (57 checks / 25 lanes). Fallow found no issues in 87 changed files. Layering reports R83 at 46 test-only exports against 83 at the merge-base and R84 at 152 unmatched tests against 187. The focused changed suites passed 7 files / 85 tests; the affected Vitest lane passed 1,872 files / 15,731 tests (1 skipped).
pnpm check:affected --run --head 03d2a9e87ab8eaaeab3bb923170d06f3232610e9 passed with exactCommit=true. It selected 63 checks: 36 passed, 25 were skipped as GitHub-authoritative or workflow-dispatch manual, and 2 were deduplicated. Selection failed open to the full set because package and closure-tooling changes can affect any gate. The local receipt is .tmp/validation/run-RZcutt/receipt.json. GitHub-authoritative coverage, provider integration, native and replay lanes remain for PR CI.
The Linux accepted-gap test and coverage declaration came from #3740 and were retained from main during the rebase.
š¤ Generated with Claude Code