From f45805942f2e6e14c64cf40ccfe7ed4a1d1e80f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 28 Sep 2026 15:18:03 +0200 Subject: [PATCH 1/4] refactor(move): relocate connected replay daemon port --- .../replay-port/src/daemon-port}/native-command.ts | 0 .../src/daemon-port}/session-replay-action-runtime.ts | 0 .../src/daemon-port}/session-replay-dispatch-narrowing.ts | 0 .../src/daemon-port}/session-replay-divergence-publication.ts | 0 .../replay-port/src/daemon-port}/session-replay-divergence.ts | 0 .../src/daemon-port}/session-replay-maestro-failure.ts | 0 .../src/daemon-port}/session-replay-maestro-response.ts | 0 .../src/daemon-port}/session-replay-maestro-runtime.ts | 0 .../src/daemon-port}/session-replay-runtime-engine-adapter.ts | 0 .../src/daemon-port}/session-replay-runtime-failure.ts | 0 .../src/daemon-port}/session-replay-runtime-plan.ts | 0 .../src/daemon-port}/session-replay-runtime-session.ts | 0 .../src/daemon-port}/session-replay-target-verification.ts | 0 .../src/daemon-port}/session-test-source-discovery.ts | 0 .../replay-port/src/daemon-port}/test-command.ts | 0 .../session-replay-divergence-android-occlusion.test.ts | 2 +- .../session-replay-divergence-capture-policy.test.ts | 2 +- .../session-replay-divergence-chrome-filter.test.ts | 2 +- .../session-replay-divergence-observation.test.ts | 2 +- .../session-replay-divergence-overlay.test.ts | 2 +- .../session-replay-divergence-publication.test.ts | 4 ++-- .../session-replay-divergence-suggestions.test.ts | 2 +- .../session-replay-maestro-error-projection.test.ts | 2 +- .../replay-maestro/session-replay-maestro-failure.test.ts | 2 +- .../session-replay-maestro-session-address.test.ts | 2 +- src/daemon/__tests__/replay-runtime/application.test.ts | 3 ++- src/daemon/__tests__/replay-runtime/replay-command-fixture.ts | 2 +- .../replay-runtime/session-replay-action-runtime.test.ts | 2 +- .../__tests__/replay-suite/session-test-command-trust.test.ts | 4 ++-- .../replay-suite/session-test-source-discovery.test.ts | 2 +- .../session-test-suite-command-cancellation.test.ts | 2 +- .../session-test-suite-command-flag-policy.test.ts | 2 +- .../session-test-suite-command-nested-flags.test.ts | 2 +- .../session-test-suite-command-remote-artifacts.test.ts | 2 +- .../replay-suite/session-test-suite-command-video.test.ts | 2 +- src/daemon/handlers/session-replay-command.ts | 3 ++- src/daemon/replay/index.ts | 3 --- .../remote-test-artifacts-materialization.test.ts | 2 +- 38 files changed, 26 insertions(+), 27 deletions(-) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/native-command.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-action-runtime.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-dispatch-narrowing.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-divergence-publication.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-divergence.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-maestro-failure.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-maestro-response.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-maestro-runtime.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-runtime-engine-adapter.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-runtime-failure.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-runtime-plan.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-runtime-session.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-replay-target-verification.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/session-test-source-discovery.ts (100%) rename {src/daemon/replay/internal => packages/replay-port/src/daemon-port}/test-command.ts (100%) delete mode 100644 src/daemon/replay/index.ts diff --git a/src/daemon/replay/internal/native-command.ts b/packages/replay-port/src/daemon-port/native-command.ts similarity index 100% rename from src/daemon/replay/internal/native-command.ts rename to packages/replay-port/src/daemon-port/native-command.ts diff --git a/src/daemon/replay/internal/session-replay-action-runtime.ts b/packages/replay-port/src/daemon-port/session-replay-action-runtime.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-action-runtime.ts rename to packages/replay-port/src/daemon-port/session-replay-action-runtime.ts diff --git a/src/daemon/replay/internal/session-replay-dispatch-narrowing.ts b/packages/replay-port/src/daemon-port/session-replay-dispatch-narrowing.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-dispatch-narrowing.ts rename to packages/replay-port/src/daemon-port/session-replay-dispatch-narrowing.ts diff --git a/src/daemon/replay/internal/session-replay-divergence-publication.ts b/packages/replay-port/src/daemon-port/session-replay-divergence-publication.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-divergence-publication.ts rename to packages/replay-port/src/daemon-port/session-replay-divergence-publication.ts diff --git a/src/daemon/replay/internal/session-replay-divergence.ts b/packages/replay-port/src/daemon-port/session-replay-divergence.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-divergence.ts rename to packages/replay-port/src/daemon-port/session-replay-divergence.ts diff --git a/src/daemon/replay/internal/session-replay-maestro-failure.ts b/packages/replay-port/src/daemon-port/session-replay-maestro-failure.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-maestro-failure.ts rename to packages/replay-port/src/daemon-port/session-replay-maestro-failure.ts diff --git a/src/daemon/replay/internal/session-replay-maestro-response.ts b/packages/replay-port/src/daemon-port/session-replay-maestro-response.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-maestro-response.ts rename to packages/replay-port/src/daemon-port/session-replay-maestro-response.ts diff --git a/src/daemon/replay/internal/session-replay-maestro-runtime.ts b/packages/replay-port/src/daemon-port/session-replay-maestro-runtime.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-maestro-runtime.ts rename to packages/replay-port/src/daemon-port/session-replay-maestro-runtime.ts diff --git a/src/daemon/replay/internal/session-replay-runtime-engine-adapter.ts b/packages/replay-port/src/daemon-port/session-replay-runtime-engine-adapter.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-runtime-engine-adapter.ts rename to packages/replay-port/src/daemon-port/session-replay-runtime-engine-adapter.ts diff --git a/src/daemon/replay/internal/session-replay-runtime-failure.ts b/packages/replay-port/src/daemon-port/session-replay-runtime-failure.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-runtime-failure.ts rename to packages/replay-port/src/daemon-port/session-replay-runtime-failure.ts diff --git a/src/daemon/replay/internal/session-replay-runtime-plan.ts b/packages/replay-port/src/daemon-port/session-replay-runtime-plan.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-runtime-plan.ts rename to packages/replay-port/src/daemon-port/session-replay-runtime-plan.ts diff --git a/src/daemon/replay/internal/session-replay-runtime-session.ts b/packages/replay-port/src/daemon-port/session-replay-runtime-session.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-runtime-session.ts rename to packages/replay-port/src/daemon-port/session-replay-runtime-session.ts diff --git a/src/daemon/replay/internal/session-replay-target-verification.ts b/packages/replay-port/src/daemon-port/session-replay-target-verification.ts similarity index 100% rename from src/daemon/replay/internal/session-replay-target-verification.ts rename to packages/replay-port/src/daemon-port/session-replay-target-verification.ts diff --git a/src/daemon/replay/internal/session-test-source-discovery.ts b/packages/replay-port/src/daemon-port/session-test-source-discovery.ts similarity index 100% rename from src/daemon/replay/internal/session-test-source-discovery.ts rename to packages/replay-port/src/daemon-port/session-test-source-discovery.ts diff --git a/src/daemon/replay/internal/test-command.ts b/packages/replay-port/src/daemon-port/test-command.ts similarity index 100% rename from src/daemon/replay/internal/test-command.ts rename to packages/replay-port/src/daemon-port/test-command.ts diff --git a/src/daemon/__tests__/replay-divergence/session-replay-divergence-android-occlusion.test.ts b/src/daemon/__tests__/replay-divergence/session-replay-divergence-android-occlusion.test.ts index 4053a5102d..6f03e1c8ff 100644 --- a/src/daemon/__tests__/replay-divergence/session-replay-divergence-android-occlusion.test.ts +++ b/src/daemon/__tests__/replay-divergence/session-replay-divergence-android-occlusion.test.ts @@ -13,7 +13,7 @@ import { captureSnapshotThroughLegacyDispatchFixture, legacyDispatchCapture, } from '../legacy-snapshot-capture-fixture.ts'; -import { buildReplayFailureDivergence } from '../../replay/internal/session-replay-divergence.ts'; +import { buildReplayFailureDivergence } from '@agent-device/replay-port/session-replay-divergence'; import { captureSnapshotWithInteractor } from '../../snapshot-interactor-capture.ts'; vi.mock('@agent-device/device-selection/dispatch-resolve', async (importOriginal) => { diff --git a/src/daemon/__tests__/replay-divergence/session-replay-divergence-capture-policy.test.ts b/src/daemon/__tests__/replay-divergence/session-replay-divergence-capture-policy.test.ts index 1b94c033b1..8bb184e656 100644 --- a/src/daemon/__tests__/replay-divergence/session-replay-divergence-capture-policy.test.ts +++ b/src/daemon/__tests__/replay-divergence/session-replay-divergence-capture-policy.test.ts @@ -3,7 +3,7 @@ import { beforeEach, expect, test, vi } from 'vitest'; import { mkdtempForTestSync } from '../../../__tests__/test-utils/tmp-dir.ts'; import { makeAndroidSession } from '../../../__tests__/test-utils/session-factories.ts'; import { SessionStore } from '../../session-store.ts'; -import { buildReplayFailureDivergence } from '../../replay/internal/session-replay-divergence.ts'; +import { buildReplayFailureDivergence } from '@agent-device/replay-port/session-replay-divergence'; import { replayDivergenceForTest } from './replay-session-fixture.ts'; import { legacyDispatchCapture, diff --git a/src/daemon/__tests__/replay-divergence/session-replay-divergence-chrome-filter.test.ts b/src/daemon/__tests__/replay-divergence/session-replay-divergence-chrome-filter.test.ts index f51b1e58ca..96b8ce8153 100644 --- a/src/daemon/__tests__/replay-divergence/session-replay-divergence-chrome-filter.test.ts +++ b/src/daemon/__tests__/replay-divergence/session-replay-divergence-chrome-filter.test.ts @@ -10,7 +10,7 @@ import { walkNonRawAndroidFixture, } from '../../../__tests__/test-utils/android-ui-hierarchy-fixtures.ts'; import { SessionStore } from '../../session-store.ts'; -import { buildReplayFailureDivergence } from '../../replay/internal/session-replay-divergence.ts'; +import { buildReplayFailureDivergence } from '@agent-device/replay-port/session-replay-divergence'; import { replayDivergenceForTest } from './replay-session-fixture.ts'; import { legacyDispatchCapture, diff --git a/src/daemon/__tests__/replay-divergence/session-replay-divergence-observation.test.ts b/src/daemon/__tests__/replay-divergence/session-replay-divergence-observation.test.ts index 46da2c50ea..a5a4cfd878 100644 --- a/src/daemon/__tests__/replay-divergence/session-replay-divergence-observation.test.ts +++ b/src/daemon/__tests__/replay-divergence/session-replay-divergence-observation.test.ts @@ -4,7 +4,7 @@ import { mkdtempForTestSync } from '../../../__tests__/test-utils/tmp-dir.ts'; import { AppError } from '@agent-device/kernel/errors'; import { makeIosSession } from '../../../__tests__/test-utils/session-factories.ts'; import { SessionStore } from '../../session-store.ts'; -import { captureDivergenceObservation } from '../../replay/internal/session-replay-divergence.ts'; +import { captureDivergenceObservation } from '@agent-device/replay-port/session-replay-divergence'; import { replayDivergenceForTest } from './replay-session-fixture.ts'; import { legacyDispatchCapture, diff --git a/src/daemon/__tests__/replay-divergence/session-replay-divergence-overlay.test.ts b/src/daemon/__tests__/replay-divergence/session-replay-divergence-overlay.test.ts index 10142889ad..b72ebe7b4d 100644 --- a/src/daemon/__tests__/replay-divergence/session-replay-divergence-overlay.test.ts +++ b/src/daemon/__tests__/replay-divergence/session-replay-divergence-overlay.test.ts @@ -7,7 +7,7 @@ import { walkNonRawAndroidFixture, } from '../../../__tests__/test-utils/android-ui-hierarchy-fixtures.ts'; import { SessionStore } from '../../session-store.ts'; -import { buildReplayFailureDivergence } from '../../replay/internal/session-replay-divergence.ts'; +import { buildReplayFailureDivergence } from '@agent-device/replay-port/session-replay-divergence'; import { replayDivergenceForTest } from './replay-session-fixture.ts'; import { refFrameScope, refFrameState } from '../../ref-frame.ts'; import { diff --git a/src/daemon/__tests__/replay-divergence/session-replay-divergence-publication.test.ts b/src/daemon/__tests__/replay-divergence/session-replay-divergence-publication.test.ts index 95b34a2072..916e7b5238 100644 --- a/src/daemon/__tests__/replay-divergence/session-replay-divergence-publication.test.ts +++ b/src/daemon/__tests__/replay-divergence/session-replay-divergence-publication.test.ts @@ -14,8 +14,8 @@ import type { ReplayDivergence } from '@agent-device/contracts/divergence'; import { expireRefFrame, refFrameScope, refFrameState, refFrameTree } from '../../ref-frame.ts'; import { markSessionPartialRefsIssued, setSessionSnapshot } from '../../session-snapshot.ts'; import { SessionStore } from '../../session-store.ts'; -import { captureDivergenceObservation } from '../../replay/internal/session-replay-divergence.ts'; -import { boundReplayDivergenceForSession } from '../../replay/internal/session-replay-divergence-publication.ts'; +import { captureDivergenceObservation } from '@agent-device/replay-port/session-replay-divergence'; +import { boundReplayDivergenceForSession } from '@agent-device/replay-port/session-replay-divergence-publication'; import { replaySessionForTest } from './replay-session-fixture.ts'; import { captureSnapshotThroughLegacyDispatchFixture, diff --git a/src/daemon/__tests__/replay-divergence/session-replay-divergence-suggestions.test.ts b/src/daemon/__tests__/replay-divergence/session-replay-divergence-suggestions.test.ts index 5845b30ec0..eeef2819df 100644 --- a/src/daemon/__tests__/replay-divergence/session-replay-divergence-suggestions.test.ts +++ b/src/daemon/__tests__/replay-divergence/session-replay-divergence-suggestions.test.ts @@ -3,7 +3,7 @@ import { beforeEach, expect, test, vi } from 'vitest'; import { mkdtempForTestSync } from '../../../__tests__/test-utils/tmp-dir.ts'; import { makeIosSession } from '../../../__tests__/test-utils/session-factories.ts'; import { SessionStore } from '../../session-store.ts'; -import { buildReplayFailureDivergence } from '../../replay/internal/session-replay-divergence.ts'; +import { buildReplayFailureDivergence } from '@agent-device/replay-port/session-replay-divergence'; import { replayDivergenceForTest } from './replay-session-fixture.ts'; import { legacyDispatchCapture, diff --git a/src/daemon/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts b/src/daemon/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts index c5ab4450cd..a9593097bd 100644 --- a/src/daemon/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts +++ b/src/daemon/__tests__/replay-maestro/session-replay-maestro-error-projection.test.ts @@ -2,7 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { expect, test } from 'vitest'; import { stringify } from 'yaml'; -import { runTypedMaestroReplay } from '../../replay/internal/session-replay-maestro-runtime.ts'; +import { runTypedMaestroReplay } from '@agent-device/replay-port/session-replay-maestro-runtime'; import { SessionStore } from '../../session-store.ts'; import { replayCommandForTest } from '../replay-runtime/replay-command-fixture.ts'; import { makeIosSession } from '../../../__tests__/test-utils/session-factories.ts'; diff --git a/src/daemon/__tests__/replay-maestro/session-replay-maestro-failure.test.ts b/src/daemon/__tests__/replay-maestro/session-replay-maestro-failure.test.ts index 233fcc1b63..13b01bec0e 100644 --- a/src/daemon/__tests__/replay-maestro/session-replay-maestro-failure.test.ts +++ b/src/daemon/__tests__/replay-maestro/session-replay-maestro-failure.test.ts @@ -23,7 +23,7 @@ import { import { buildTypedMaestroFailureReportProjection, buildTypedMaestroFailureResponse, -} from '../../replay/internal/session-replay-maestro-failure.ts'; +} from '@agent-device/replay-port/session-replay-maestro-failure'; import { runReplayForTest } from '../replay-runtime/replay-command-fixture.ts'; import { SessionStore } from '../../session-store.ts'; import { captureSnapshotWithInteractor } from '../../snapshot-interactor-capture.ts'; diff --git a/src/daemon/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts b/src/daemon/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts index 95e599b783..0e0a7e8154 100644 --- a/src/daemon/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts +++ b/src/daemon/__tests__/replay-maestro/session-replay-maestro-session-address.test.ts @@ -2,7 +2,7 @@ import fs from 'node:fs'; import path from 'node:path'; import { expect, test } from 'vitest'; import { stringify } from 'yaml'; -import { runTypedMaestroReplay } from '../../replay/internal/session-replay-maestro-runtime.ts'; +import { runTypedMaestroReplay } from '@agent-device/replay-port/session-replay-maestro-runtime'; import { SessionStore } from '../../session-store.ts'; import { replayCommandForTest } from '../replay-runtime/replay-command-fixture.ts'; import { makeIosSession } from '../../../__tests__/test-utils/session-factories.ts'; diff --git a/src/daemon/__tests__/replay-runtime/application.test.ts b/src/daemon/__tests__/replay-runtime/application.test.ts index e75968b2c7..d72e748a3d 100644 --- a/src/daemon/__tests__/replay-runtime/application.test.ts +++ b/src/daemon/__tests__/replay-runtime/application.test.ts @@ -17,7 +17,8 @@ import { createReplaySession, replayDaemonDependencies, } from '../../handlers/session-replay-command.ts'; -import { runReplayCommand, runReplayTestCommand } from '../../replay/index.ts'; +import { runReplayCommand } from '@agent-device/replay-port/native-command'; +import { runReplayTestCommand } from '@agent-device/replay-port/test-command'; import { replayInvokeOverDispatch, splitReplayCommandRequest, diff --git a/src/daemon/__tests__/replay-runtime/replay-command-fixture.ts b/src/daemon/__tests__/replay-runtime/replay-command-fixture.ts index 53788c8365..453d3ccd02 100644 --- a/src/daemon/__tests__/replay-runtime/replay-command-fixture.ts +++ b/src/daemon/__tests__/replay-runtime/replay-command-fixture.ts @@ -5,7 +5,7 @@ import { createReplaySession, replayDaemonDependencies, } from '../../handlers/session-replay-command.ts'; -import { runReplayCommand } from '../../replay/index.ts'; +import { runReplayCommand } from '@agent-device/replay-port/native-command'; import { replayInvokeOverDispatch, splitReplayCommandRequest, diff --git a/src/daemon/__tests__/replay-runtime/session-replay-action-runtime.test.ts b/src/daemon/__tests__/replay-runtime/session-replay-action-runtime.test.ts index db3adb1b3a..2234c80b44 100644 --- a/src/daemon/__tests__/replay-runtime/session-replay-action-runtime.test.ts +++ b/src/daemon/__tests__/replay-runtime/session-replay-action-runtime.test.ts @@ -3,7 +3,7 @@ import { expect, test } from 'vitest'; import { makeIosSession } from '../../../__tests__/test-utils/session-factories.ts'; import { recordActionEntry } from '../../session-action-recorder.ts'; import type { DaemonRequest } from '../../daemon-request.ts'; -import { invokeReplayAction } from '../../replay/internal/session-replay-action-runtime.ts'; +import { invokeReplayAction } from '@agent-device/replay-port/session-replay-action-runtime'; import { replayDaemonDependencies } from '../../handlers/session-replay-command.ts'; import { resolveReplayAction } from '@agent-device/ad-script'; diff --git a/src/daemon/__tests__/replay-suite/session-test-command-trust.test.ts b/src/daemon/__tests__/replay-suite/session-test-command-trust.test.ts index 42cf6b5420..2b5b8017ab 100644 --- a/src/daemon/__tests__/replay-suite/session-test-command-trust.test.ts +++ b/src/daemon/__tests__/replay-suite/session-test-command-trust.test.ts @@ -10,7 +10,7 @@ import { createReplaySession, replayDaemonDependencies, } from '../../handlers/session-replay-command.ts'; -import { runReplayTestCommand } from '../../replay/index.ts'; +import { runReplayTestCommand } from '@agent-device/replay-port/test-command'; import type { ReplayCommand, ReplayTestCommand } from '@agent-device/replay-port/command-types'; import { replayScriptSourceBundleFor } from '../../../__tests__/test-utils/replay-script-source.ts'; import { mkdtempForTestSync } from '../../../__tests__/test-utils/tmp-dir.ts'; @@ -18,7 +18,7 @@ import type { DaemonInvokeFn, DaemonRequest } from '../../daemon-request.ts'; const capturedCommands: ReplayCommand[] = []; -vi.mock('../../replay/internal/native-command.ts', () => ({ +vi.mock('@agent-device/replay-port/native-command', () => ({ runReplayCommand: async (command: ReplayCommand) => { capturedCommands.push(command); return { ok: true as const, data: { replayed: 1 } }; diff --git a/src/daemon/__tests__/replay-suite/session-test-source-discovery.test.ts b/src/daemon/__tests__/replay-suite/session-test-source-discovery.test.ts index aa70cd3279..c6c28dd106 100644 --- a/src/daemon/__tests__/replay-suite/session-test-source-discovery.test.ts +++ b/src/daemon/__tests__/replay-suite/session-test-source-discovery.test.ts @@ -2,7 +2,7 @@ import { test } from 'vitest'; import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; -import { buildReplayTestSourceDiscovery } from '../../replay/internal/session-test-source-discovery.ts'; +import { buildReplayTestSourceDiscovery } from '@agent-device/replay-port/session-test-source-discovery'; import { mkdtempForTestSync } from '../../../__tests__/test-utils/tmp-dir.ts'; import { maestroScriptSourceBundleFor, diff --git a/src/daemon/__tests__/replay-suite/session-test-suite-command-cancellation.test.ts b/src/daemon/__tests__/replay-suite/session-test-suite-command-cancellation.test.ts index 5661957437..4f95ffe37f 100644 --- a/src/daemon/__tests__/replay-suite/session-test-suite-command-cancellation.test.ts +++ b/src/daemon/__tests__/replay-suite/session-test-suite-command-cancellation.test.ts @@ -6,7 +6,7 @@ import { markRequestCanceled, registerRequestAbort, } from '@agent-device/host-kit/request'; -import { bindReplayTestAttemptCancellation } from '../../replay/internal/test-command.ts'; +import { bindReplayTestAttemptCancellation } from '@agent-device/replay-port/test-command'; // The daemon half of the replay-test cancellation seam (#1478 P3b). The scheduler only says // "cancel" and "release"; everything here — registry entries, the parent-abort relay, and diff --git a/src/daemon/__tests__/replay-suite/session-test-suite-command-flag-policy.test.ts b/src/daemon/__tests__/replay-suite/session-test-suite-command-flag-policy.test.ts index f31b81d0ae..977524527e 100644 --- a/src/daemon/__tests__/replay-suite/session-test-suite-command-flag-policy.test.ts +++ b/src/daemon/__tests__/replay-suite/session-test-suite-command-flag-policy.test.ts @@ -13,7 +13,7 @@ import { createReplaySession, replayDaemonDependencies, } from '../../handlers/session-replay-command.ts'; -import { runReplayTestCommand } from '../../replay/index.ts'; +import { runReplayTestCommand } from '@agent-device/replay-port/test-command'; import { replayInvokeOverDispatch, splitReplayCommandRequest, diff --git a/src/daemon/__tests__/replay-suite/session-test-suite-command-nested-flags.test.ts b/src/daemon/__tests__/replay-suite/session-test-suite-command-nested-flags.test.ts index f040bbfbe1..9e5cc3fc2d 100644 --- a/src/daemon/__tests__/replay-suite/session-test-suite-command-nested-flags.test.ts +++ b/src/daemon/__tests__/replay-suite/session-test-suite-command-nested-flags.test.ts @@ -5,7 +5,7 @@ */ import assert from 'node:assert/strict'; import { test } from 'vitest'; -import { buildNestedReplayFlags } from '../../replay/internal/test-command.ts'; +import { buildNestedReplayFlags } from '@agent-device/replay-port/test-command'; test('buildNestedReplayFlags returns parent flags untouched when neither override is set', () => { const parent = { platform: 'android' as const, timeoutMs: 5000 }; diff --git a/src/daemon/__tests__/replay-suite/session-test-suite-command-remote-artifacts.test.ts b/src/daemon/__tests__/replay-suite/session-test-suite-command-remote-artifacts.test.ts index 3b576c4a3b..2ecf85e505 100644 --- a/src/daemon/__tests__/replay-suite/session-test-suite-command-remote-artifacts.test.ts +++ b/src/daemon/__tests__/replay-suite/session-test-suite-command-remote-artifacts.test.ts @@ -18,7 +18,7 @@ import path from 'node:path'; import { test } from 'vitest'; import type { ReplaySuiteResult } from '@agent-device/contracts/replay'; import type { DaemonRequest } from '../../daemon-request.ts'; -import { attachRemoteReplayTestArtifacts } from '../../replay/internal/test-command.ts'; +import { attachRemoteReplayTestArtifacts } from '@agent-device/replay-port/test-command'; import { mkdtempForTestSync } from '../../../__tests__/test-utils/tmp-dir.ts'; const SUITE_INVOCATION_ID = 'cd5f9c01feec8d70'; diff --git a/src/daemon/__tests__/replay-suite/session-test-suite-command-video.test.ts b/src/daemon/__tests__/replay-suite/session-test-suite-command-video.test.ts index b331e9d632..da008d36ab 100644 --- a/src/daemon/__tests__/replay-suite/session-test-suite-command-video.test.ts +++ b/src/daemon/__tests__/replay-suite/session-test-suite-command-video.test.ts @@ -6,7 +6,7 @@ import { beforeEach, test, vi } from 'vitest'; import { SessionStore } from '../../session-store.ts'; import type { DaemonRequest, DaemonResponse } from '../../daemon-request.ts'; import { makeIosSession } from '../../../__tests__/test-utils/session-factories.ts'; -import { runReplayTestCommand } from '../../replay/index.ts'; +import { runReplayTestCommand } from '@agent-device/replay-port/test-command'; import { replayInvokeOverDispatch, splitReplayCommandRequest, diff --git a/src/daemon/handlers/session-replay-command.ts b/src/daemon/handlers/session-replay-command.ts index 7109133c7d..ce15cc7685 100644 --- a/src/daemon/handlers/session-replay-command.ts +++ b/src/daemon/handlers/session-replay-command.ts @@ -6,7 +6,8 @@ import { bindInternalObservationAuthority } from '../internal-observation.ts'; import type { LeaseRegistry } from '../lease-registry.ts'; import type { BindDeviceRuntime, InspectDeviceRuntimeFacts } from '../request-runtime-binding.ts'; import type { PlatformResourceCleanup } from '../platform-resource-cleanup.ts'; -import { runReplayCommand, runReplayTestCommand } from '../replay/index.ts'; +import { runReplayCommand } from '@agent-device/replay-port/native-command'; +import { runReplayTestCommand } from '@agent-device/replay-port/test-command'; import { bindReplaySession } from '@agent-device/replay-port/replay-session-binding'; import { replayInvokeOverDispatch, diff --git a/src/daemon/replay/index.ts b/src/daemon/replay/index.ts deleted file mode 100644 index 28b2a346d5..0000000000 --- a/src/daemon/replay/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -/** Public replay application seam for daemon handlers and their admitted owner capabilities. */ -export { runReplayCommand } from './internal/native-command.ts'; -export { runReplayTestCommand } from './internal/test-command.ts'; diff --git a/test/integration/provider-scenarios/remote-test-artifacts-materialization.test.ts b/test/integration/provider-scenarios/remote-test-artifacts-materialization.test.ts index 8f645c409c..06e947e16f 100644 --- a/test/integration/provider-scenarios/remote-test-artifacts-materialization.test.ts +++ b/test/integration/provider-scenarios/remote-test-artifacts-materialization.test.ts @@ -11,7 +11,7 @@ import { } from '../../../src/daemon/artifact-tracking.ts'; import type { DaemonRequest } from '../../../src/daemon/daemon-request.ts'; import { createDaemonHttpServer } from '../../../src/daemon/server/http-server.ts'; -import { attachRemoteReplayTestArtifacts } from '../../../src/daemon/replay/internal/test-command.ts'; +import { attachRemoteReplayTestArtifacts } from '@agent-device/replay-port/test-command'; import { downloadRemoteArtifact, materializeRemoteArtifacts, From a09d092c587154b1e4c5e6ccaab260353da67e33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 28 Sep 2026 15:18:03 +0200 Subject: [PATCH 2/4] chore(gates): enforce replay port package ownership --- .../src/internal/__tests__/step-loop.test.ts | 2 +- packages/ad-replay/src/internal/step-loop.ts | 2 +- .../src/internal/target-verification.ts | 2 +- .../internal/target-annotation-identity.ts | 2 +- packages/replay-port/package.json | 33 +++++++++ .../__tests__/session-test-runtime.test.ts | 2 +- pnpm-lock.yaml | 3 + scripts/layering/architecture-ownership.ts | 31 ++++----- scripts/layering/daemon-modularity.test.ts | 67 +++++-------------- scripts/layering/daemon-modularity.ts | 2 +- .../android-ui-hierarchy-fixtures.ts | 2 +- .../replay-coordinator-ownership.test.ts | 10 +-- src/daemon/session-action-recorder.ts | 2 +- 13 files changed, 80 insertions(+), 80 deletions(-) diff --git a/packages/ad-replay/src/internal/__tests__/step-loop.test.ts b/packages/ad-replay/src/internal/__tests__/step-loop.test.ts index 026c6615ff..0cd7ee6abf 100644 --- a/packages/ad-replay/src/internal/__tests__/step-loop.test.ts +++ b/packages/ad-replay/src/internal/__tests__/step-loop.test.ts @@ -11,7 +11,7 @@ import type { TargetAnnotationV1 } from '@agent-device/contracts/replay'; * terminal-close suppression) is engine-private — never re-exported by the * façade (`packages/ad-replay/src/index.ts`) — so these tests exercise it * only through `runAdReplay` itself, the same way the daemon's own - * `src/daemon/replay/internal/native-command.ts` (`runReplayCommand`) does. The equivalent + * `packages/replay-port/src/daemon-port/native-command.ts` (`runReplayCommand`) does. The equivalent * daemon-level assertions (full `SessionStore`/`runReplayCommand` round * trip, including the `--keep-session` live-session postcondition) live in * `src/daemon/__tests__/replay-runtime/session-replay-runtime-keep-session.test.ts` diff --git a/packages/ad-replay/src/internal/step-loop.ts b/packages/ad-replay/src/internal/step-loop.ts index a9f0814759..bc79d08af7 100644 --- a/packages/ad-replay/src/internal/step-loop.ts +++ b/packages/ad-replay/src/internal/step-loop.ts @@ -15,7 +15,7 @@ import type { /** * #1478 P5 stage C2b: the `.ad` step-loop ENGINE policy, split out of - * `src/daemon/replay/internal/native-command.ts`'s replay orchestration / + * `packages/replay-port/src/daemon-port/native-command.ts`'s replay orchestration / * `resolveReplayStepResponse` / `buildReplayActionFailure`. Everything that * touches a real device, a snapshot, `SessionStore`, or the P4b repair * coordinator is daemon authority and stays behind the narrow diff --git a/packages/ad-replay/src/internal/target-verification.ts b/packages/ad-replay/src/internal/target-verification.ts index 838304d63b..0d3264e4fa 100644 --- a/packages/ad-replay/src/internal/target-verification.ts +++ b/packages/ad-replay/src/internal/target-verification.ts @@ -1,6 +1,6 @@ /** * #1478 P5 stage C2a: the target-verification ENGINE policy — moved verbatim - * out of `src/daemon/replay/internal/session-replay-target-verification.ts`, which + * out of `packages/replay-port/src/daemon-port/session-replay-target-verification.ts`, which * keeps the DAEMON-AUTHORITY half (capture, `SessionStore`, resume stamping, * wire projection into `DaemonResponse`). This module decides, over already- * available plain values, whether/how a recorded target-binding annotation diff --git a/packages/ad-script/src/internal/target-annotation-identity.ts b/packages/ad-script/src/internal/target-annotation-identity.ts index 1a7169c8a9..80ba39047d 100644 --- a/packages/ad-script/src/internal/target-annotation-identity.ts +++ b/packages/ad-script/src/internal/target-annotation-identity.ts @@ -50,7 +50,7 @@ type IdentityTreeNode = Pick; * normalized (NFC, label whitespace collapse, `normalizeType` role) AND * 256-byte field-capped, on every path. Shared by the record-time writer * (`@agent-device/selectors/target-evidence`), replay-time verification - * (`src/daemon/replay/internal/session-replay-target-verification.ts`), and the + * (`packages/replay-port/src/daemon-port/session-replay-target-verification.ts`), and the * dispatch-side post-resolution guard * (`src/commands/interaction/runtime/resolution.ts`), so all three compute * a node's identity with byte-identical semantics. diff --git a/packages/replay-port/package.json b/packages/replay-port/package.json index 0a7b727e4c..2aecce22a2 100644 --- a/packages/replay-port/package.json +++ b/packages/replay-port/package.json @@ -9,6 +9,7 @@ "@agent-device/ad-replay": "workspace:*", "@agent-device/ad-script": "workspace:*", "@agent-device/capture-kit": "workspace:*", + "@agent-device/command-registry": "workspace:*", "@agent-device/contracts": "workspace:*", "@agent-device/device-selection": "workspace:*", "@agent-device/host-kit": "workspace:*", @@ -23,6 +24,10 @@ "types": "./src/daemon-port/command-types.ts", "default": "./src/daemon-port/command-types.ts" }, + "./native-command": { + "types": "./src/daemon-port/native-command.ts", + "default": "./src/daemon-port/native-command.ts" + }, "./repair-hint": { "types": "./src/daemon-port/repair-hint.ts", "default": "./src/daemon-port/repair-hint.ts" @@ -43,10 +48,26 @@ "types": "./src/daemon-port/script-source.ts", "default": "./src/daemon-port/script-source.ts" }, + "./session-replay-action-runtime": { + "types": "./src/daemon-port/session-replay-action-runtime.ts", + "default": "./src/daemon-port/session-replay-action-runtime.ts" + }, + "./session-replay-divergence": { + "types": "./src/daemon-port/session-replay-divergence.ts", + "default": "./src/daemon-port/session-replay-divergence.ts" + }, + "./session-replay-divergence-publication": { + "types": "./src/daemon-port/session-replay-divergence-publication.ts", + "default": "./src/daemon-port/session-replay-divergence-publication.ts" + }, "./session-replay-heal": { "types": "./src/daemon-port/session-replay-heal.ts", "default": "./src/daemon-port/session-replay-heal.ts" }, + "./session-replay-maestro-failure": { + "types": "./src/daemon-port/session-replay-maestro-failure.ts", + "default": "./src/daemon-port/session-replay-maestro-failure.ts" + }, "./session-replay-maestro-observer": { "types": "./src/daemon-port/session-replay-maestro-observer.ts", "default": "./src/daemon-port/session-replay-maestro-observer.ts" @@ -55,6 +76,10 @@ "types": "./src/daemon-port/session-replay-maestro-request.ts", "default": "./src/daemon-port/session-replay-maestro-request.ts" }, + "./session-replay-maestro-runtime": { + "types": "./src/daemon-port/session-replay-maestro-runtime.ts", + "default": "./src/daemon-port/session-replay-maestro-runtime.ts" + }, "./session-replay-report-action": { "types": "./src/daemon-port/session-replay-report-action.ts", "default": "./src/daemon-port/session-replay-report-action.ts" @@ -103,6 +128,10 @@ "types": "./src/daemon-port/session-test-shard-devices.ts", "default": "./src/daemon-port/session-test-shard-devices.ts" }, + "./session-test-source-discovery": { + "types": "./src/daemon-port/session-test-source-discovery.ts", + "default": "./src/daemon-port/session-test-source-discovery.ts" + }, "./target-classification": { "types": "./src/daemon-port/target-classification.ts", "default": "./src/daemon-port/target-classification.ts" @@ -114,6 +143,10 @@ "./target-token": { "types": "./src/daemon-port/target-token.ts", "default": "./src/daemon-port/target-token.ts" + }, + "./test-command": { + "types": "./src/daemon-port/test-command.ts", + "default": "./src/daemon-port/test-command.ts" } } } diff --git a/packages/replay-test/src/internal/__tests__/session-test-runtime.test.ts b/packages/replay-test/src/internal/__tests__/session-test-runtime.test.ts index 0a59ba7f1e..6bd8cb8fbd 100644 --- a/packages/replay-test/src/internal/__tests__/session-test-runtime.test.ts +++ b/packages/replay-test/src/internal/__tests__/session-test-runtime.test.ts @@ -11,7 +11,7 @@ import { mkdtempForTestSync } from '../../tmp-dir.fixtures.ts'; // What the scheduler owes its host around cancellation (#1478 P3b): cancel exactly once when // an attempt times out, and always release when it settles. How the daemon then maps that onto // its request registry is the adapter's contract, pinned in -// `src/daemon/replay/internal/__tests__/session-test-suite-command-cancellation.test.ts`. +// `src/daemon/__tests__/replay-suite/session-test-suite-command-cancellation.test.ts`. const cancellations: Array<{ attemptId: string; canceled: number; released: number }> = []; function trackCancellation() { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1bcb944f51..9d3122356f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -515,6 +515,9 @@ importers: '@agent-device/capture-kit': specifier: workspace:* version: link:../capture-kit + '@agent-device/command-registry': + specifier: workspace:* + version: link:../command-registry '@agent-device/contracts': specifier: workspace:* version: link:../contracts diff --git a/scripts/layering/architecture-ownership.ts b/scripts/layering/architecture-ownership.ts index 21aad68ba2..aa42c574f7 100644 --- a/scripts/layering/architecture-ownership.ts +++ b/scripts/layering/architecture-ownership.ts @@ -11,11 +11,6 @@ export type LogicalModulePolicy = Readonly<{ facade?: FacadeDeclaration; }>; -const DAEMON_REPLAY_FACADE = { - root: 'src/daemon/replay/index.ts', - exports: ['runReplayCommand', 'runReplayTestCommand'], -} as const; - const DAEMON_SESSION_LIFECYCLE_FACADE = { root: 'src/daemon/session-lifecycle/index.ts', exports: [ @@ -106,12 +101,23 @@ export const LOGICAL_MODULE_POLICIES = [ { name: 'ad-replay', roots: ['packages/ad-replay/src/'], - forbiddenTargetRoots: ['src/daemon/', 'src/providers/', 'src/compat/', 'packages/maestro/'], + forbiddenTargetRoots: [ + 'src/daemon/', + 'src/providers/', + 'src/compat/', + 'packages/maestro/', + 'packages/replay-port/', + ], }, { name: 'maestro', roots: ['packages/maestro/src/'], - forbiddenTargetRoots: ['src/daemon/', 'src/providers/', 'packages/ad-replay/'], + forbiddenTargetRoots: [ + 'src/daemon/', + 'src/providers/', + 'packages/ad-replay/', + 'packages/replay-port/', + ], }, { name: 'replay-test', @@ -123,6 +129,7 @@ export const LOGICAL_MODULE_POLICIES = [ 'src/compat/', 'packages/maestro/', 'packages/ad-replay/', + 'packages/replay-port/', ], }, { @@ -130,16 +137,6 @@ export const LOGICAL_MODULE_POLICIES = [ roots: ['packages/replay-port/src/'], forbiddenTargetRoots: ['src/daemon/', 'src/providers/', 'src/compat/'], }, - { - name: 'daemon-replay', - roots: ['src/daemon/replay/'], - forbiddenTargetRoots: [ - 'src/daemon/handlers/record-runtime.ts', - 'src/daemon/session-store.ts', - 'src/daemon/session-lifecycle/', - ], - facade: DAEMON_REPLAY_FACADE, - }, { name: 'daemon-session-lifecycle', roots: ['src/daemon/session-lifecycle/'], diff --git a/scripts/layering/daemon-modularity.test.ts b/scripts/layering/daemon-modularity.test.ts index f0533ae2c7..9939ee25f4 100644 --- a/scripts/layering/daemon-modularity.test.ts +++ b/scripts/layering/daemon-modularity.test.ts @@ -161,21 +161,21 @@ test('logical modules reject forbidden imports', () => { assert.match(violations[0]!.message, /replay-test must not import/); }); -test('replay-test rejects request-global and engine-internal imports', () => { +test('replay-test rejects request-global and replay-port imports', () => { const edges = resolveImportEdges( new Map([ [ 'packages/replay-test/src/internal/scheduler.ts', [ "import { emitRequestProgress } from '../../../../src/request/progress.ts';", - "import { readReplayScriptMetadata } from '../../../../src/daemon/replay/internal/native-command.ts';", + "import { runReplayCommand } from '../../../replay-port/src/daemon-port/native-command.ts';", "import { parseMaestroProgram } from '../../../../src/compat/maestro/program-ir-parser.ts';", ].join('\n'), ], ['src/request/progress.ts', 'export function emitRequestProgress() {}'], [ - 'src/daemon/replay/internal/native-command.ts', - 'export function readReplayScriptMetadata() {}', + 'packages/replay-port/src/daemon-port/native-command.ts', + 'export function runReplayCommand() {}', ], ['src/compat/maestro/program-ir-parser.ts', 'export function parseMaestroProgram() {}'], ]), @@ -190,7 +190,7 @@ test('replay-test rejects request-global and engine-internal imports', () => { violations.map(({ message }) => message.replace(/;.*/, '')), [ 'replay-test must not import src/request/progress.ts', - "packages/replay-test/src/internal/scheduler.ts must not import daemon-replay's internal tree (src/daemon/replay/internal/native-command.ts)", + 'replay-test must not import packages/replay-port/src/daemon-port/native-command.ts', 'replay-test must not import src/compat/maestro/program-ir-parser.ts', ], ); @@ -230,33 +230,20 @@ test('internal trees reject deep imports globally, including from daemon', () => assert.match(violations[0]!.message, /must not import maestro's internal tree/); }); -test('daemon replay rejects handler, owner, session-store, and engine deep edges', () => { +test('replay-port rejects daemon source imports and engine back edges', () => { const edges = resolveImportEdges( new Map([ [ - 'src/daemon/handlers/session.ts', - "import { runReplayCommand } from '../replay/internal/native-command.ts';", - ], - [ - 'src/daemon/replay/internal/test-command.ts', - "import { handleSessionCloseCommands } from '../../session-lifecycle/internal/session-close.ts';", + 'packages/replay-port/src/daemon-port/test-command.ts', + "import { handleSessionCloseCommands } from '../../../../src/daemon/session-lifecycle/index.ts';", ], [ - 'src/daemon/replay/internal/close-command.ts', - "import { handleSessionCloseCommands } from '../../session-lifecycle/index.ts';", - ], - [ - 'src/daemon/replay/internal/command-types.ts', - "import { SessionStore } from '../../session-store.ts';", + 'packages/replay-port/src/daemon-port/native-command.ts', + "import { SessionStore } from '../../../../src/daemon/session-store.ts';", ], [ 'packages/ad-replay/src/internal/step-loop.ts', - "import { runReplayCommand } from '../../../../src/daemon/replay/internal/native-command.ts';", - ], - ['src/daemon/replay/internal/native-command.ts', 'export function runReplayCommand() {}'], - [ - 'src/daemon/session-lifecycle/internal/session-close.ts', - 'export function handleSessionCloseCommands() {}', + "import { runReplayCommand } from '../../../replay-port/src/daemon-port/native-command.ts';", ], ['src/daemon/session-lifecycle/index.ts', 'export function handleSessionCloseCommands() {}'], ['src/daemon/session-store.ts', 'export class SessionStore {}'], @@ -269,39 +256,19 @@ test('daemon replay rejects handler, owner, session-store, and engine deep edges REFERENCE, ); assert.deepEqual( - violations.map(({ file, line, message }) => ({ - file, - line, - message: message.replace(/;.*/, ''), - })), + violations.map(({ file, message }) => ({ file, message: message.replace(/;.*/, '') })), [ { - file: 'src/daemon/handlers/session.ts', - line: 1, - message: - "src/daemon/handlers/session.ts must not import daemon-replay's internal tree (src/daemon/replay/internal/native-command.ts)", + file: 'packages/replay-port/src/daemon-port/test-command.ts', + message: 'replay-port must not import src/daemon/session-lifecycle/index.ts', }, { - file: 'src/daemon/replay/internal/test-command.ts', - line: 1, - message: - "src/daemon/replay/internal/test-command.ts must not import daemon-session-lifecycle's internal tree (src/daemon/session-lifecycle/internal/session-close.ts)", - }, - { - file: 'src/daemon/replay/internal/close-command.ts', - line: 1, - message: 'daemon-replay must not import src/daemon/session-lifecycle/index.ts', - }, - { - file: 'src/daemon/replay/internal/command-types.ts', - line: 1, - message: 'daemon-replay must not import src/daemon/session-store.ts', + file: 'packages/replay-port/src/daemon-port/native-command.ts', + message: 'replay-port must not import src/daemon/session-store.ts', }, { file: 'packages/ad-replay/src/internal/step-loop.ts', - line: 1, - message: - "packages/ad-replay/src/internal/step-loop.ts must not import daemon-replay's internal tree (src/daemon/replay/internal/native-command.ts)", + message: 'ad-replay must not import packages/replay-port/src/daemon-port/native-command.ts', }, ], ); diff --git a/scripts/layering/daemon-modularity.ts b/scripts/layering/daemon-modularity.ts index 75f8f3834d..37349b2b36 100644 --- a/scripts/layering/daemon-modularity.ts +++ b/scripts/layering/daemon-modularity.ts @@ -38,7 +38,7 @@ const DAEMON_TYPE_MODULES: readonly string[] = [ const ENGINE_FILE_PREFIXES = [ 'packages/ad-replay/src/', 'packages/maestro/src/', - 'src/daemon/replay/internal/', + 'packages/replay-port/src/daemon-port/', 'packages/replay-test/src/', ] as const; diff --git a/src/__tests__/test-utils/android-ui-hierarchy-fixtures.ts b/src/__tests__/test-utils/android-ui-hierarchy-fixtures.ts index bc2f756e7b..2adf8c6fd2 100644 --- a/src/__tests__/test-utils/android-ui-hierarchy-fixtures.ts +++ b/src/__tests__/test-utils/android-ui-hierarchy-fixtures.ts @@ -121,7 +121,7 @@ export function parseUiHierarchy( * node (`status_bar_container`, `status_bar_contents`, ...), unlike a default * capture. Shared across the chrome-classification tests * (`core/__tests__/snapshot-chrome-android-statusbar.test.ts`) and the replay - * divergence route test (`daemon/replay/internal/__tests__/session-replay-divergence-chrome-filter.test.ts`) + * divergence route test (`daemon/__tests__/replay-divergence/session-replay-divergence-chrome-filter.test.ts`) * so both exercise the exact same real screen through `walkNonRawAndroidFixture`. */ export const ANDROID_IME_CAPTURE_RAW_NODES: RawSnapshotNode[] = imeCapture; diff --git a/src/daemon/__tests__/replay-coordinator-ownership.test.ts b/src/daemon/__tests__/replay-coordinator-ownership.test.ts index 2011a32c73..716a1cf8e5 100644 --- a/src/daemon/__tests__/replay-coordinator-ownership.test.ts +++ b/src/daemon/__tests__/replay-coordinator-ownership.test.ts @@ -33,9 +33,9 @@ const RUNTIME_FILE = 'src/daemon/handlers/session-replay-command.ts'; /** The divergence-report chain: never a second `ReplayCoordinator`, never a bare `SessionStore`. */ const DIVERGENCE_CHAIN_FILES = [ 'packages/replay-port/src/daemon-port/session-replay-resume.ts', - 'src/daemon/replay/internal/session-replay-divergence.ts', - 'src/daemon/replay/internal/session-replay-target-verification.ts', - 'src/daemon/replay/internal/session-replay-runtime-failure.ts', + 'packages/replay-port/src/daemon-port/session-replay-divergence.ts', + 'packages/replay-port/src/daemon-port/session-replay-target-verification.ts', + 'packages/replay-port/src/daemon-port/session-replay-runtime-failure.ts', 'packages/replay-port/src/daemon-port/session-replay-runtime-failure-response.ts', ] as const; @@ -51,7 +51,7 @@ type ImportSite = { }; function listProductionSourceFiles(): string[] { - const roots = ['src']; + const roots = ['src', 'packages/replay-port/src']; const out: string[] = []; const walk = (dir: string): void => { for (const entry of fs.readdirSync(path.join(REPO_ROOT, dir), { withFileTypes: true })) { @@ -404,7 +404,7 @@ test('coordinator ownership scanning catches aliases, namespaces, and dynamic im test('daemon replay production files never import the P4a ReplaySessionTransaction projection', () => { const offenders = PRODUCTION_FILES.filter( (file) => - file.startsWith('src/daemon/replay/') && + file.startsWith('packages/replay-port/src/') && collectImportSites(file).some((site) => importsAnyBinding(site, TRANSACTION_MODULE)), ); assert.deepEqual( diff --git a/src/daemon/session-action-recorder.ts b/src/daemon/session-action-recorder.ts index b60131d39d..3335c3bc2a 100644 --- a/src/daemon/session-action-recorder.ts +++ b/src/daemon/session-action-recorder.ts @@ -308,7 +308,7 @@ const OBSERVATION_ONLY_COMMANDS: ReadonlySet = new Set(['snapshot', 'get * Two facts, ANDed, and the second is the one that matters: * 1. the command is observation-only (above); and * 2. it is NOT a replay plan step (`internal.replayPlanStep`, stamped by - * `invokeResolvedReplayAction`, `daemon/replay/internal/session-replay-action-runtime.ts`). + * `invokeResolvedReplayAction`, `packages/replay-port/src/daemon-port/session-replay-action-runtime.ts`). * * (2) is why this is a PROVENANCE rule, not a command-class rule. Replayed * plan steps dispatch through the ordinary request path and land in From 9315a302a76482a53a415cde3e5157ecdd446a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 28 Sep 2026 15:52:50 +0200 Subject: [PATCH 3/4] test(replay): resolve package-relative ownership imports --- .../replay-coordinator-ownership.test.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/daemon/__tests__/replay-coordinator-ownership.test.ts b/src/daemon/__tests__/replay-coordinator-ownership.test.ts index 716a1cf8e5..21bd581a4c 100644 --- a/src/daemon/__tests__/replay-coordinator-ownership.test.ts +++ b/src/daemon/__tests__/replay-coordinator-ownership.test.ts @@ -50,8 +50,9 @@ type ImportSite = { declarationTypeOnly: boolean; }; +const PRODUCTION_ROOTS = ['src', 'packages/replay-port/src'] as const; + function listProductionSourceFiles(): string[] { - const roots = ['src', 'packages/replay-port/src']; const out: string[] = []; const walk = (dir: string): void => { for (const entry of fs.readdirSync(path.join(REPO_ROOT, dir), { withFileTypes: true })) { @@ -65,14 +66,14 @@ function listProductionSourceFiles(): string[] { out.push(relPath); } }; - for (const root of roots) walk(root); + for (const root of PRODUCTION_ROOTS) walk(root); return out; } function resolveRelativeTarget(fromFile: string, spec: string): string | null { if (!spec.startsWith('.')) return null; const resolved = path.posix.normalize(path.posix.join(path.posix.dirname(fromFile), spec)); - return resolved.startsWith('src/') ? resolved : null; + return PRODUCTION_ROOTS.some((root) => resolved.startsWith(`${root}/`)) ? resolved : null; } function collectImportSites( @@ -401,6 +402,17 @@ test('coordinator ownership scanning catches aliases, namespaces, and dynamic im ); }); +test('a package-relative dynamic import resolves within the scanned replay port', () => { + const probe = 'packages/replay-port/src/daemon-port/probe.ts'; + const source = "void import('./session-replay-divergence.ts');"; + const overrides = new Map([[probe, source]]); + assert.deepEqual(unresolvedDynamicImportSites([probe], overrides), []); + assert.equal( + collectImportSites(probe, source)[0]?.target, + 'packages/replay-port/src/daemon-port/session-replay-divergence.ts', + ); +}); + test('daemon replay production files never import the P4a ReplaySessionTransaction projection', () => { const offenders = PRODUCTION_FILES.filter( (file) => From 199f35f7eaad46d8ac1a4101423224cb3dd0cb53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Pierzcha=C5=82a?= Date: Mon, 28 Sep 2026 17:37:07 +0200 Subject: [PATCH 4/4] fix(replay): move native command complexity baseline --- fallow-baselines/health.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fallow-baselines/health.json b/fallow-baselines/health.json index be35214a66..128c213878 100644 --- a/fallow-baselines/health.json +++ b/fallow-baselines/health.json @@ -563,7 +563,7 @@ "packages/platform-android/src/settings.ts:complexity", "packages/capture-kit/src/snapshot/snapshot-presentation/text-surface.ts:high impact", "src/daemon/handlers/session-test-sharding.ts:high impact", - "src/daemon/replay/internal/native-command.ts:complexity", + "packages/replay-port/src/daemon-port/native-command.ts:complexity", "packages/platform-apple/src/core/debug-symbols/utils.ts:high impact", "packages/platform-linux/src/snapshot.ts:high impact", "packages/selectors/src/interaction-targeting.ts:high impact",