Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion fallow-baselines/health.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",

@cubic-dev-ai cubic-dev-ai Bot Sep 28, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This line fixes the native-command.ts baseline but two sibling entries in the same target_keys list were not moved with their renames: src/daemon/replay/internal/session-replay-heal.ts (line 539) and src/daemon/replay/internal/session-test-infrastructure.ts (line 579) still key paths that no longer exist, while the files now live at packages/replay-port/src/daemon-port/. Since fallow baselines are path-keyed and must move on rename, update both entries to the new package paths as well.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At fallow-baselines/health.json, line 566:

<comment>This line fixes the `native-command.ts` baseline but two sibling entries in the same `target_keys` list were not moved with their renames: `src/daemon/replay/internal/session-replay-heal.ts` (line 539) and `src/daemon/replay/internal/session-test-infrastructure.ts` (line 579) still key paths that no longer exist, while the files now live at `packages/replay-port/src/daemon-port/`. Since fallow baselines are path-keyed and must move on rename, update both entries to the new package paths as well.</comment>

<file context>
@@ -563,7 +563,7 @@
     "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",
</file context>
Fix with cubic

"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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
2 changes: 1 addition & 1 deletion packages/ad-replay/src/internal/step-loop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion packages/ad-replay/src/internal/target-verification.ts
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type IdentityTreeNode = Pick<RawSnapshotNode, 'type' | 'identifier' | 'label'>;
* 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.
Expand Down
33 changes: 33 additions & 0 deletions packages/replay-port/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:*",
Expand All @@ -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"
Expand All @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 14 additions & 17 deletions scripts/layering/architecture-ownership.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down Expand Up @@ -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',
Expand All @@ -123,23 +129,14 @@ export const LOGICAL_MODULE_POLICIES = [
'src/compat/',
'packages/maestro/',
'packages/ad-replay/',
'packages/replay-port/',
],
},
{
name: 'replay-port',
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/'],
Expand Down
67 changes: 17 additions & 50 deletions scripts/layering/daemon-modularity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}'],
]),
Expand All @@ -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',
],
);
Expand Down Expand Up @@ -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 {}'],
Expand All @@ -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',
},
],
);
Expand Down
2 changes: 1 addition & 1 deletion scripts/layering/daemon-modularity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/test-utils/android-ui-hierarchy-fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading
Loading