Repository navigation
Conversation
Size Report
Startup median (7 runs, lower is better):
|
|
I reviewed e51dff5 and found two problems to fix before merge. Both are copied test fakes, and one shared owner should replace each. The new device-inventory-gateways.ts is about 110 lines copied from the existing device-selection fake. It also re-states the discover/providerFirst flow of the real The new replay-script-source.ts copies Not blocking, and you can take or leave these: the Android archived captures and walker builders in android-ui-hierarchy-fixtures.ts are platform fixtures, and they have several non-daemon consumers (core interactor tests, snapshot-chrome tests, Could the daemon avoid new fakes altogether? Export the existing inventory fake through one test-support owner, or move it into test-kit with an injected context wrapper, and point the 43 daemon importers and the root importers at it. That removes about 150 lines. Keep one replay-source helper module with the collector passed in. Keep plugin.fixtures in test-kit, as you have it. Put the Android captures with platform-android if the eager-closure rule allows, or leave them at the root and accept those few edges explicitly instead of inverting core to daemon. The first decision is which module owns the inventory fake: a device-selection test-support subpath or a test-kit dependency edge. The test-kit rejection from ADR-0019 applies only to the Android pieces. The changes are test-only, so I ran no tests or gates here. I relied on your reported 433 files and 3305 tests green, and on the green layering, DI-seams and eager-closure checks. Smoke Tests is still queued, not failed, and this diff does not touch the runtime code that run exercises. There are no conflicts. The next step before merge is to replace the two copied fakes with one shared owner each. |
e51dff5 to
2e636d1
Compare
2e636d1 to
93356dc
Compare
|
The code still has two copied test fakes and two failing checks at 93356dc, so it is not ready to merge. The earlier review at e51dff5 raised the same two copies. The inline bridge is now an in-file helper, but both copies are still there, and the Required evidence is satisfied. First, src/daemon/tests/support/device-inventory-gateways.ts is still a roughly 110-line copy of the fake in Second, src/daemon/tests/support/replay-script-source.ts is a second implementation of the bundle helpers and collector. It has no glob support, no bundle size cap, no not-found Third, Fourth, Not blocking, and you can take or leave these: the delta stat lists limrun, CONTRIBUTING, coverage and website-docs changes, which are probably base movement from the rebase, so please confirm the diff against 2c7a8d0 is test-side only (the PR body says 83 files and I count 84), and the header comments in the new support files narrate the root modules they replace, so drop them or keep one line stating the contract. Could both daemon copies be deleted, with the device-selection fake exposed through one test-support subpath or moved to test-kit, and a single replay-source helper that takes the collector as a parameter? That would remove about 250 lines and keep the edge count at 0 for On checks, the fallow and Lint & Format failures look related to this diff. I did not read the Coverage failure log, and Smoke Tests is still queued. I did not run tests or gates, and I did not grep the head to confirm 0 |
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
93356dc to
c61535e
Compare
|
Rework pushed at c61535e (rebased onto the refreshed base 57b6b9b; findings → fixes):
|
|
The PR is ready at c61535e. Both earlier problems from the 93356dc review are fixed: the fallow findings sat on the copied fakes, and the Lint & Format failure sat on the unformatted fixture, so both are gone or formatted. All 36 checks pass, and the review found no code problems. Not blocking, and you can take or leave these: the single fake in packages/device-selection/src/inventory-gateways.fixtures.ts (https://github.com/callstack/agent-device/blob/c61535e/packages/device-selection/src/inventory-gateways.fixtures.ts#L77) restates createComposedDeviceInventoryGateways without assertProviderOutcome and assertSourceFamily, so a malformed provider outcome in root tests would fail with a TypeError or pass instead of the typed provider_inventory_contract_violation, and the composer pin already owns that contract; the three new APPROVED_OVER_CEILING rows and the mechanics-facet exceptions in scripts/tests/eager-closure-budgets.ts (https://github.com/callstack/agent-device/blob/c61535e/scripts/__tests__/eager-closure-budgets.ts#L135) could be dropped once 11a-2 settles and the Android fixture subpaths can live in test-kit; and the PR body names the inventory pin as src/tests/platform-runtime-device-inventory.test.ts when the file is src/platform-runtime-device-inventory.test.ts. I did not run tests or gates myself, so the parity and gate results rest on the PR body and green CI. I also did not check that moving the collector adds no CLI startup import-closure weight beyond the passing guard, or that the 43-file count in the body matches the 37 files I counted under src/daemon. The total of 60 importers does confirm one owner. Nothing else needs to happen before merge. |
|
Non-blocking items taken; pushed as bd49bf8 (normal push):
Gates: 11,030 tests green across |
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
bd49bf8 to
1159838
Compare
|
Coordinator: rebased onto the current tip of the PR below (stack sync, no content changes). |
|
This PR is ready at 1159838. The earlier clean review at c61535e still stands, and the new commit adds a contracts export, device-selection fixture, root composer and one daemon test change that I found correct when reading the diff. All 36 checks are green, and they cover those routes. I did not run the tests locally, and I did not execute a check that the new fixture test fails without assertProviderOutcome; I reasoned that from the code. I also did not confirm beyond green CI that the export-pin and eager-closure gates account for the two new contracts facade exports. Not blocking, and you can take or leave these: the rebase comment says "stack sync, no content changes" and the body cites bd49bf8, but this head adds a real contracts export and test changes, so a corrected comment and hash would help; and the web-close teardown test change in daemon-runtime-web-close-teardown.test.ts (installFakeManagedAgentBrowser plus a stderr assertion) is a separate concern from the contracts inventory work, so it is worth keeping out of the stated scope. No conflicts are known. The PR is still a draft with the ready-for-human label, so nothing else stands between this delta and merge. |
|
Coordinator correction to my earlier sync comment: the sync itself changed nothing. It only rebased the branch's existing commits onto #3519's new tip, 773f78b. 1159838 is bd49bf8 (the worker's contracts-export and inventory-assertion commit) rebased; the hash changed but the content didn't. The web-close teardown test change ( |
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
1159838 to
2354fd0
Compare
|
The earlier review at 1159838 found no problems, and the rebase onto the new #3519 head (2354fd0) changed only the base. Your patch is the same apart from hunk offsets, and all 41 checks pass. Not blocking, take or leave: Two questions. First, the fake exists only because the daemon test tree cannot import the root module. Could the composer move into I did not run the tests or |
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
2354fd0 to
e4eee6b
Compare
|
Both design questions taken; pushed at e4eee6b (stack of two commits on the fresh 11a-2f base — force-with-lease was needed because the base moved under the previous push; content of the earlier commits unchanged):
Gates on the pushed head: typecheck, layering (incl. enumeration + eager-closure hub budgets), quick, di-seams, gate-manifest, fallow green; full |
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
77c1009 to
e615de3
Compare
|
Coordinator: rebased onto #3519's new head |
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
e615de3 to
f5ed49c
Compare
|
Rebased onto the rewritten |
|
Reviewed f5ed49c. The code looks good, and I found no defects. Before the label, please answer the design questions below. I ran no tests or gates locally, and CI status comes from the check list only. The earlier points from 77c1009 are fixed. The test fake now composes through the real composer, and the consumer-gate and fixture-path items are addressed at this head. The only checks not passing are the Mutants shards for kernel-errors, selectors and interaction-settle. They are queued or in progress, not failed. This diff touches nothing under packages/selectors or packages/kernel, and nothing on the settle or errors routes, so they look unrelated. Smoke Tests, which covers the daemon startup route through the dynamic import of the package composer, is no longer in the not-passing list. I did not re-review the base move from c13c1bd to df0af2a, because the base commits for 11a-2a..2g belong to PR #3519. I know of no conflicts. Not blocking, and you can take or leave it: assertSourceFamily and assertProviderOutcome were exported from the public contracts device facade so the fake could share them. The fake now uses the real composer, so the only consumer left is composed-inventory-gateways.ts. The docstrings also carry review-history narration, and the facade gained an AppError import only for these helpers. Moving them back as private functions would drop those imports from contracts. The new concept is sound: device-selection owns the composed inventory flow, and the root keeps only the host-specific Apple probe. Can the two helpers above go back to being private in composed-inventory-gateways.ts? Can the wrapper in src/platform-runtime-device-inventory.ts be folded into createPlatformDeviceInventoryGateways in platform-runtime.ts, or renamed for what it does, for example attachAppleInstalledAppProbe? It is async and shares its name with the sync package function it wraps, and it carries a comment about where the flow moved. A smaller gap: the Android fixture entries have a consumer-gate pin in platform-package-policy.ts. Should the new test-only subpaths device-selection/inventory-gateways-fixtures and replay-port/replay-script-source-fixtures get the same? Of the earlier inline threads, the four from cubic-dev-ai are fixed at this head and can be resolved: the test-only subpath check order, the Android IME fixture path, the R71 retired path, and the consumer accept and deny test. Once the design questions above are answered, this can follow base PR #3519. |
|
All three design questions are addressed in new commits on top of 1. Helpers back to private — done ( 2. Wrapper — renamed, not folded ( 3. Consumer-gate pins — added ( Evidence at the new head: |
There was a problem hiding this comment.
All reported issues were addressed across 9 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
…akes Daemon tests and fixtures no longer import the root test-utils and plugin fixture modules: - device-inventory-gateways: daemon policy tests get a support fake at the ComposedDeviceInventoryGateways port composed from contracts projection and provider-request scoping only; root composition tests keep the real helper. - replay-script-source: daemon tests get a support fake that builds client replay source bundles through the package replay-backend registry and a deterministic suite walk, with no root command-layer imports. - android-snapshot-capture, android-ui-hierarchy-fixtures (plus the archived raw capture JSON) move under src/daemon/__tests__/support/ and are imported from the root test trees that share them (root -> daemon test support is an allowed direction); plugin.fixtures moves to @agent-device/test-kit as a data-only fixture over package vocabulary.
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
…-android test entries
…the test fake Move assertProviderOutcome and assertSourceFamily from src/platform-runtime-device-inventory.ts into @agent-device/contracts/device (device-inventory.ts, exported through ./device). The test fake in device-selection previously restated the provider flow without the outcome assertion, so a malformed provider outcome surfaced as a TypeError or fell through instead of the provider_inventory_contract_violation AppError. Both the production composer and the fake now call the same validators, and a fixture test pins the fail-closed behavior on the fake. The fake's local path keeps its per-family filter: the local option is a flat whole-inventory discoverer fanned out per family, so filtering there is the adapter to the per-family source contract rather than a contract the fake would assert against itself.
…on port The replay source bundle loader and caller-side path discovery run on the client (#1802: the daemon opens no caller path), yet they sat under packages/replay-port/src/daemon-port/, where nothing stopped daemon code from importing them. Move script-source-bundle, source-discovery, and the request fixture to the replay-port source root, which stays outside the engine-prefix policy and the daemon-port zone; the subpath names are unchanged, so consumers and the CLI closure guard retarget by path only.
…package The composed-gateways flow (provider-first discovery, declined-to-local fallback, request projection, per-family fan-out) moves from the root composition into @agent-device/device-selection/composed-inventory-gateways with the installed-app probe injected rather than hardcoded, exported as a production subpath. The test fake now builds its gateways through that real composer with fake registry sources instead of restating the flow, so the root, daemon-composition and integration consumers exercise production behavior rather than a copy that could drift from it. src/platform-runtime-device-inventory.ts keeps its path as the production wiring that attaches the Apple simulator probe, importing the package composer function-scoped so the composition root's eager closure does not grow, and its root-side suite pins that factory composition.
- The relocated archived-capture pin in the affected-lanes test names its real path: packages/platform-android/src/fixtures/android-ime-capture.raw.json. - The two Android test-only fixture subpaths keep export validation but leave the general mechanics-facet consumer allowlist: only non-production files may import them, so production code (src/commands/ style) importing a fixture now trips R13 instead of riding the facet seam. - R71's guidance and owner list follow the caller collector to packages/replay-port/src/; the retired src/commands/replay/ path was deleted by the collector move and left the policy naming a stranded owner.
Mirror the mechanics/adb-host facet tests: a test or integration file importing @agent-device/platform-android/snapshot-capture-fixtures passes R13, while the same import from production files (src/commands/ and src/core/interactors/, the latter proving production files ride no fixture seam) is denied. Guards the ANDROID_TEST_ONLY_SUBPATHS predicate added for the review's P2.
The test fake now composes through the real composer, so composed-inventory-gateways.ts is the only consumer of assertSourceFamily and assertProviderOutcome. They go back as private functions there, and the contracts device facade drops them along with the AppError import that only served the re-export. Answers the review's first simplicity question.
createComposedDeviceInventoryGateways at the root shared its name with the sync package composer it wraps while being an async wrapper that attaches the Apple installed-app probe; it is now attachAppleInstalledAppProbe and the where-the-flow-moved narration is cut to one line naming the probe. Folding it into platform-runtime.ts was evaluated and rejected: the composition import allowlist is category-based (contracts, platform facades, host adapters), so the fold would widen it for one dynamic import of the package composer — a looser gate than the wrapper file the zones and composition policy already carry.
The new device-selection/inventory-gateways-fixtures and replay-port/replay-script-source-fixtures subpaths belong to non-platform packages, so R13's ANDROID_TEST_ONLY_SUBPATHS predicate cannot reach them; TEST_ONLY_FIXTURE_SUBPATHS makes the same non-production-consumer claim at R11, in both the package-internal and root scans, and a planted production import in src/daemon/ was confirmed to fire before it was removed. Mirrors the Android fixture accept/deny test.
- The R11 accept/deny test now pins TEST_ONLY_FIXTURE_SUBPATHS against an independent expectation before iterating it, so deleting an entry from the checker's set can no longer take its production-denial coverage with it. - The non-production consumer predicate recognizes package-local test trees (packages/*/test/), not just the root test/ directory: a package harness importing a fixture subpath is a test consumer, matching how R13's file vocabulary treats harness trees. Pin extends the accept list accordingly.
…y source collector Owner review on #3517: the two daemon-side fakes restated logic that already had owners. Both are replaced by single importable owners: - The device-selection test fake becomes the one inventory-gateways fixture: moved to packages/device-selection/src/inventory-gateways.fixtures.ts and exported as ./inventory-gateways-fixtures (with findInstalledApp already in its options and createTestDeviceInventoryGatewaysFromProvider now exported). The daemon copy, the root fake, and its pin (the real composer's fail-closed contract is pinned in platform-runtime-device-inventory.test.ts) are deleted; daemon, root, device-selection, and integration consumers all import the owner. - The real client collector moves into its package: script-source-bundle and source-discovery move from src/commands/replay into replay-port (own exports ./script-source-bundle, ./source-discovery). The bundle helpers live once in packages/replay-port/src/daemon-port/replay-script-source.fixtures.ts (./replay-script-source-fixtures), typed on DaemonWireRequest; both test trees import it and run the same globs, size cap, AppErrors and ranking. - The Android capture fixtures move to platform-android test-only entries (./snapshot-capture-fixtures, ./ui-hierarchy-fixtures) so no test tree reaches sideways; the archived raw JSONs move with them.
|
Coordinator: rebased onto #3519's new head |
3bdeef3 to
6b4b1d9
Compare
…ize tripwire Unblocks the stack: 9dc0bb5 (the design-question round on #3517) grew package-boundaries.test.ts from 961 to 1005 lines, crossing the 1000-line test-file tripwire, so the size ratchet fails unit-core on #3517 itself and every branch stacked on it. The ratchet's own message prescribes the repair: split along the mirrored source. Pure move — the test body is byte-identical; the in-memory parser fixtures it shares with the R11 suite move to package-boundaries.fixtures.ts so the split files parse one pair.
package-boundaries.test.ts is over the 1,000-line tripwire (961 at the merge-base), so the size ratchet rejects the consumer-gate pins these branches add to it. Tests mirror source topology: the test-only fixture subpath inventory (R11's TEST_ONLY_FIXTURE_SUBPATHS accept/deny gate and the platform-android manifest's fixture export entries, both owned by package-boundaries.ts) moves with its rule into scripts/layering/test-only-fixture-subpaths.test.ts, mirroring the R13-side pin in platform-package-policy.test.ts. Move-only: the accept/ deny test is byte-identical and the manifest assertion keeps its full sorted key list; it reads the tree itself instead of sharing the real- tree test's package list. package-boundaries.test.ts ends at 955 lines, under its base length.
|
Coverage was red on the size ratchet:
Verified: ratchet test green, |
Plan step 11a-3: daemon test files stop importing the root
src/__tests__/test-utils/data fixtures, and the review's copied-fake findings are resolved with one owner each.Targeted root modules (scan edges now 0): device-inventory-gateways, replay-script-source, android-ui-hierarchy-fixtures, android-snapshot-capture, plugin.fixtures. Total daemon→root scan residue after the cut: 23 edges, all into the platform-runtime cluster owned by step 11a-2 (the only remaining 11a-1 residue).
Review resolutions:
packages/device-selection/src/inventory-gateways.fixtures.ts, exported as@agent-device/device-selection/inventory-gateways-fixtures, withfindInstalledAppin options,createTestDeviceInventoryGatewaysexported, and the nullable-provider bridge (withTestDeviceInventoryProvider) extracted once. Daemon (37 files undersrc/daemon), root composition, device-selection's own tests, and test/integration all import it. The root wrapper and its pin are deleted: the wrapper's fail-closed pin duplicated the real composer's pin already atsrc/platform-runtime-device-inventory.test.ts, and the real adapter has its own direct tests. test-kit was not viable: the fake needs the root composition'screateDeviceInventoryContext(device-selection's production entry), which would make test-kit→device-selection while device-selection's tests need test-kit — atsc -bproject-reference cycle — so the package's own test-only subpath (the fallback) is the one owner.script-source-bundle,source-discovery, byte-pure moves with their own test suites), and the bundle helpers live once inreplay-port/src/daemon-port/replay-script-source.fixtures.ts(./replay-script-source-fixtures), typed onDaemonWireRequestso it serves both trees without a production seam. Both test trees exercise the same globs, size cap, not-found AppErrors and ranking through it. The rootsrc/__tests__/test-utils/replay-script-source.tsis deleted (its exports move with it; nothing suppressed via.fallowrc).snapshot-capture-fixturesandui-hierarchy-fixturesare test-only entries on@agent-device/platform-android(the Apple runner requests-fixtures pattern), with the archived raw JSONs underpackages/platform-android/src/fixtures/whereown:package-captureowns them. Contract comments kept to one line.plugin.fixturesstays in@agent-device/test-kit/plugin.fixtures(package vocabulary over the filesystem install, no platform adapters).createTestDeviceInventoryGatewaysFromProvideris used (lock-policy test + integration harness), so it stays exported; the daemon-side copy that fallow flagged is deleted.pnpm formatrun repo-wide.src/commands/replay/index.ts; everything else is test/fixture moves, import retargets, and gate wiring. No limrun/CONTRIBUTING/coverage/website files in the delta against the current base.Gates (on the pushed commit, under the host gate lock):
check:affected --runclean across all selected lanes;check:quick,check:layering,check:di-seams,check:gate-manifest,check:fallow, the eager-closure budgets table (threeAPPROVED_OVER_CEILINGrows + the mechanics-facet exception for the Android fixture entries), the R13 export-pin tests, and the test-file-size ratchet green. Targeted full runs:src/daemon,src/__tests__,packages,scriptswith zero failures;vitest list srcparity vs base is exact modulo the moved test files' path keys and one intentionally deleted duplicate pin (the root inventory wrapper's fail-closed case, already owned root-side).Risk: no production behavior change (CLI startup import-closure guard green through the replay move). Eager-require weight: daemon suites now pull replay-port's real collector instead of the local test twin.
NO DOCS — test topology and fixture ownership only; no user-facing behavior or CLI surface changes.
Follow-up commit (bd49bf8, second review round):
assertProviderOutcome/assertSourceFamilymoved from the root composer into@agent-device/contracts/device; the fake now calls the sharedassertProviderOutcomeinstead of restating the flow (a malformed provider outcome fails closed withprovider_inventory_contract_violationin both paths, pinned by a new fixture test). The fake's local path keeps its per-family filter because thelocaloption is a flat whole-inventory discoverer fanned out per family — that filter is the adapter to the per-family source contract, not a restated assertion site.Design answers at e4eee6b (review follow-up round):
@agent-device/device-selection/composed-inventory-gatewayswith the installed-app probe injected instead of hardcoded;src/platform-runtime-device-inventory.tsstays as the production wiring that attaches the Apple probe (function-scoped import keeps the composition root's eager closure flat; the hub no-growth gate is green). The test fake composes through the real composer with fake registry sources — the root, daemon-composition, and integration consumers exercise the production flow, not a restatement. No root-side wrapper is needed anymore: the one owner is the package entry both trees build on.script-source-bundle,source-discovery, and the request fixture now sit atpackages/replay-port/src/(client-side replay vocabulary, likesession-replay-vars), outside thedaemon-port/engine-prefix zone; the./script-source-bundle,./source-discovery, and./replay-script-source-fixturessubpaths keep their names. Caller filesystem reads stay out of the daemon's dispatch vocabulary.