mirror of
https://github.com/callstack/agent-device.git
synced 2026-09-14 20:06:34 +08:00
refactor(capture-kit): complete ADR 0019 end state — relocate snapshot and recording zones (#2385)
* refactor(capture-kit): relocate snapshot and recording zones into capture-kit
Move the ADR 0019 end-state capture zones into @agent-device/capture-kit:
- src/snapshot/** -> packages/capture-kit/src/snapshot/** (presentation,
freshness, scroll-edge-state, ios-snapshot-runtime, android occlusion)
- src/recording/** -> packages/capture-kit/src/recording/**
- src/core/snapshot-{chrome,state,tree-ingestion,node-lookup}.ts ->
packages/capture-kit/src/
- src/snapshot-quality/ test -> capture-kit presentation tree (directory
retires with its last file)
Pure renames: import re-pointing and gate updates follow in the next commit.
The snapshot-desktop-surface test parks in src/__tests__/ because it pins
the root eager-import-closure walker.
* refactor(capture-kit): re-point capture and recording consumers to the new subpaths
Rewires every consumer of the relocated snapshot/recording modules to the new @agent-device/capture-kit subpath exports, adds the 23 subpath entries to the capture-kit exports map, fixes the moved recording-scripts test's __dirname-relative paths for the deeper location, and records the completed migration in ADR 0019's end state.
* chore(gates): align layering, mutation, fallow and CI gates with the capture-kit relocation
Moves the executable-policy roots, presentation-owner constant, zone ranks, authority fixture, mutation sharding globs, stryker aliases, fallow baselines and the iOS workflow's android-owned paths-ignore entry onto the new packages/capture-kit paths, and extends the planted-red coverage to the new presentation-owner subpath.
* chore: point capture-domain source-of-truth comments at the relocated capture-kit modules
* test: point shutdown recording mock at capture-kit and cover interactor acquisition presentation
* test(capture-kit): update upstream presentation test imports
* chore(gates): follow relocated snapshot assembly in R74
* test(daemon): freeze prewarm deadline assertion clocks
This commit is contained in:
committed by
GitHub
parent
a6cf1b1fd4
commit
1f9d940bff
@@ -29,7 +29,7 @@ on:
|
||||
- 'packages/*/src/**/*.test.ts'
|
||||
- 'packages/*/src/**/__tests__/**/*.ts'
|
||||
- 'packages/platform-android/src/**'
|
||||
- 'src/snapshot/snapshot-presentation/android/**'
|
||||
- 'packages/capture-kit/src/snapshot/snapshot-presentation/android/**'
|
||||
- 'packages/platform-harmonyos/src/**'
|
||||
- 'packages/platform-linux/src/**'
|
||||
- 'packages/platform-vega/src/**'
|
||||
|
||||
@@ -902,42 +902,25 @@ target, unverified**, not a derived number.
|
||||
The root files that remain are either declared host-port adapters (e.g. `adb-host`, bound only
|
||||
by its named root file per Decision §1) or mechanics whose wave has not landed yet — the two are
|
||||
not distinguished by filename and need per-file classification before a target is set.
|
||||
- `src/recording`, `src/snapshot`, `src/snapshot-quality`, `src/screenshot-diff`. Corrected
|
||||
2026-09-03: `packages/capture-kit/src/` already has broad production ownership across
|
||||
recording (`screen-recording-live-handle.ts`, `screen-recording-completion.ts`,
|
||||
`screen-recording-options.ts`, consumed by `platform-android`/`platform-apple`/
|
||||
`platform-harmonyos`/`platform-web`'s `recording/runtime.ts`), screenshot/diff
|
||||
(`png.ts`, `png-worker-client.ts`, imported by `src/screenshot-diff/screenshot-diff.ts`),
|
||||
snapshot quality (`snapshot-quality-verdict.ts`, `snapshot-quality-backend-capabilities.ts` —
|
||||
`src/snapshot-quality/` now holds only a cross-package regression test, no production file),
|
||||
occlusion (`snapshot-occlusion.ts`), audio/app-log (`audio-probe-runtime.ts`,
|
||||
`app-log-live-handle.ts`, consumed by `platform-android`, `platform-apple`, and
|
||||
`provider-limrun`), and iOS acquisition/engine (`ios-snapshot-acquisition.ts`,
|
||||
`ios-snapshot-planning.ts`, `ios-snapshot-engine/`, consumed by
|
||||
`src/snapshot/ios-snapshot-runtime.ts`). ADR §1's amendment already assigns this capture
|
||||
domain to `capture-kit`; the domain mechanics are migrated. What remains under `src/` in
|
||||
these four directories, verified file-by-file at HEAD, is daemon-facing composition with no
|
||||
existing package equivalent, not unmigrated capture mechanics:
|
||||
- `src/recording/{output-path,overlay,swift-cache,telemetry,video,video-webm}.ts` — video
|
||||
playability polling, overlay burn-in, telemetry persistence, and output-path resolution,
|
||||
imported only by `src/platform-runtime-screen-recording-*.ts` and
|
||||
`src/daemon/handlers/record-runtime*.ts`. Equivalent: none.
|
||||
- `src/snapshot/ios-snapshot-runtime.ts` and `snapshot-visibility.ts` — composition over the
|
||||
capture-kit acquisition/planning/engine/semantics calls above. Equivalent: capture-kit
|
||||
(mechanics already migrated; these are the composition callers).
|
||||
- `src/snapshot/{android-replacement-surface-occlusion,rect-coverage,scroll-edge-state,
|
||||
snapshot-desktop-surface,snapshot-diff,snapshot-evidence,snapshot-label-dedup,
|
||||
snapshot-lines,snapshot-node-label,snapshot-timeout-policy}.ts` — none import capture-kit.
|
||||
`android-replacement-surface-occlusion.ts` implements a distinct Android-specific
|
||||
footprint algorithm, not the generic viewport pruning in capture-kit's
|
||||
`snapshot-occlusion.ts`. Equivalent: none.
|
||||
- `src/snapshot-quality/__tests__/warnings.test.ts` — the sole survivor in that directory;
|
||||
exercises `renderSnapshotQualityWarnings` (root) against capture-kit's
|
||||
`readSnapshotQualityVerdict`. Equivalent: capture-kit (production logic fully migrated).
|
||||
- `src/screenshot-diff/*.ts` (region split/overlay/summarization/component composition) —
|
||||
pixel-diff computation and PNG decode/encode already call capture-kit's `png`/
|
||||
`png-worker-client`; the root files remain for daemon/CLI diff-report composition.
|
||||
Equivalent: none (built atop already-migrated capture-kit mechanics).
|
||||
- `src/recording`, `src/snapshot`, `src/snapshot-quality` — **migrated to
|
||||
`packages/capture-kit/src/` (2026-09-07)**: the whole trees moved as-is (`recording/`,
|
||||
`snapshot/` including its `snapshot-presentation/` and `snapshot-freshness/` subtrees),
|
||||
together with the cross-package `warnings.test.ts` regression test. The four snapshot
|
||||
modules from `src/core/` (`snapshot-chrome.ts`, `snapshot-state.ts`,
|
||||
`snapshot-tree-ingestion.ts`, `snapshot-node-lookup.ts`, with their tests) joined the
|
||||
package root. External consumers (daemon, commands, platform hosts, integration tests)
|
||||
use package subpath exports (e.g. `@agent-device/capture-kit/snapshot-lines`,
|
||||
`/recording-video`, `/ios-snapshot-runtime`); `snapshot-tree-ingestion` carries no
|
||||
subpath because only `snapshot-state.ts` (same package) consumes it. Three tests stayed
|
||||
at the root — `src/core/__tests__/snapshot-state.test.ts` and
|
||||
`snapshot-chrome-android-statusbar.test.ts` (pinned to root-owned
|
||||
`interaction-targeting` and the android UI-hierarchy fixtures) and
|
||||
`src/__tests__/snapshot-desktop-surface.test.ts` (pinned to the root
|
||||
eager-import-closure fixtures).
|
||||
- `src/screenshot-diff/*.ts` (region split/overlay/summarization/component composition) —
|
||||
pixel-diff computation and PNG decode/encode already call capture-kit's `png`/
|
||||
`png-worker-client`; the root files remain for daemon/CLI diff-report composition.
|
||||
Equivalent: none (built atop already-migrated capture-kit mechanics).
|
||||
- `src/provider-device-runtime.ts`, `src/provider-device-runtimes.ts`,
|
||||
`src/provider-limrun-runtime.ts`, `src/provider-webdriver.ts`. Mostly already thin: the bulk of
|
||||
WebDriver and Limrun provider logic lives in `packages/provider-webdriver/src/` and
|
||||
|
||||
@@ -456,7 +456,7 @@
|
||||
"count": 2
|
||||
}
|
||||
},
|
||||
"src/snapshot/snapshot-lines.ts": {
|
||||
"packages/capture-kit/src/snapshot/snapshot-lines.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -471,12 +471,12 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/snapshot/scroll-edge-state.ts": {
|
||||
"packages/capture-kit/src/snapshot/scroll-edge-state.ts": {
|
||||
"crap_moderate": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"src/snapshot/snapshot-presentation/text-surface.ts": {
|
||||
"packages/capture-kit/src/snapshot/snapshot-presentation/text-surface.ts": {
|
||||
"crap_high": {
|
||||
"count": 1
|
||||
}
|
||||
@@ -550,7 +550,7 @@
|
||||
"packages/kernel/src/success-text.ts:high impact",
|
||||
"src/cli.ts:complexity",
|
||||
"src/commands/interaction/output.ts:high impact",
|
||||
"src/snapshot/snapshot-lines.ts:high impact",
|
||||
"packages/capture-kit/src/snapshot/snapshot-lines.ts:high impact",
|
||||
"packages/kernel/src/rect-center.ts:high impact",
|
||||
"packages/platform-apple/src/core/app-launch.ts:complexity",
|
||||
"packages/kernel/src/record.ts:high impact",
|
||||
@@ -562,7 +562,7 @@
|
||||
"src/client/screenshot-result.ts:high impact",
|
||||
"packages/platform-web/src/json-utils.ts:high impact",
|
||||
"packages/platform-android/src/settings.ts:complexity",
|
||||
"src/snapshot/snapshot-presentation/text-surface.ts:high impact",
|
||||
"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/platform-apple/src/core/debug-symbols/utils.ts:high impact",
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
"types": "./src/index.ts",
|
||||
"default": "./src/index.ts"
|
||||
},
|
||||
"./android-replacement-surface-occlusion": {
|
||||
"types": "./src/snapshot/android-replacement-surface-occlusion.ts",
|
||||
"default": "./src/snapshot/android-replacement-surface-occlusion.ts"
|
||||
},
|
||||
"./durable-capture": {
|
||||
"types": "./src/durable-capture/index.ts",
|
||||
"default": "./src/durable-capture/index.ts"
|
||||
@@ -34,6 +38,10 @@
|
||||
"types": "./src/ios-snapshot-planning.ts",
|
||||
"default": "./src/ios-snapshot-planning.ts"
|
||||
},
|
||||
"./ios-snapshot-runtime": {
|
||||
"types": "./src/snapshot/ios-snapshot-runtime.ts",
|
||||
"default": "./src/snapshot/ios-snapshot-runtime.ts"
|
||||
},
|
||||
"./mobile-snapshot-semantics": {
|
||||
"types": "./src/mobile-snapshot-semantics.ts",
|
||||
"default": "./src/mobile-snapshot-semantics.ts"
|
||||
@@ -66,10 +74,34 @@
|
||||
"types": "./src/post-gesture-stability.ts",
|
||||
"default": "./src/post-gesture-stability.ts"
|
||||
},
|
||||
"./quality-warnings": {
|
||||
"types": "./src/snapshot/snapshot-presentation/quality-warnings.ts",
|
||||
"default": "./src/snapshot/snapshot-presentation/quality-warnings.ts"
|
||||
},
|
||||
"./react-native-overlay": {
|
||||
"types": "./src/react-native-overlay.ts",
|
||||
"default": "./src/react-native-overlay.ts"
|
||||
},
|
||||
"./recording-output-path": {
|
||||
"types": "./src/recording/output-path.ts",
|
||||
"default": "./src/recording/output-path.ts"
|
||||
},
|
||||
"./recording-overlay": {
|
||||
"types": "./src/recording/overlay.ts",
|
||||
"default": "./src/recording/overlay.ts"
|
||||
},
|
||||
"./recording-telemetry": {
|
||||
"types": "./src/recording/telemetry.ts",
|
||||
"default": "./src/recording/telemetry.ts"
|
||||
},
|
||||
"./recording-video": {
|
||||
"types": "./src/recording/video.ts",
|
||||
"default": "./src/recording/video.ts"
|
||||
},
|
||||
"./repeated-nav-subtree": {
|
||||
"types": "./src/snapshot/snapshot-presentation/repeated-nav-subtree.ts",
|
||||
"default": "./src/snapshot/snapshot-presentation/repeated-nav-subtree.ts"
|
||||
},
|
||||
"./screenshot-density": {
|
||||
"types": "./src/screenshot-density.ts",
|
||||
"default": "./src/screenshot-density.ts"
|
||||
@@ -82,14 +114,58 @@
|
||||
"types": "./src/screenshot-overlay.ts",
|
||||
"default": "./src/screenshot-overlay.ts"
|
||||
},
|
||||
"./scroll-edge-state": {
|
||||
"types": "./src/snapshot/scroll-edge-state.ts",
|
||||
"default": "./src/snapshot/scroll-edge-state.ts"
|
||||
},
|
||||
"./snapshot-chrome": {
|
||||
"types": "./src/snapshot-chrome.ts",
|
||||
"default": "./src/snapshot-chrome.ts"
|
||||
},
|
||||
"./snapshot-desktop-projection": {
|
||||
"types": "./src/snapshot-desktop-projection.ts",
|
||||
"default": "./src/snapshot-desktop-projection.ts"
|
||||
},
|
||||
"./snapshot-desktop-surface": {
|
||||
"types": "./src/snapshot/snapshot-desktop-surface.ts",
|
||||
"default": "./src/snapshot/snapshot-desktop-surface.ts"
|
||||
},
|
||||
"./snapshot-diff": {
|
||||
"types": "./src/snapshot/snapshot-diff.ts",
|
||||
"default": "./src/snapshot/snapshot-diff.ts"
|
||||
},
|
||||
"./snapshot-evidence": {
|
||||
"types": "./src/snapshot/snapshot-evidence.ts",
|
||||
"default": "./src/snapshot/snapshot-evidence.ts"
|
||||
},
|
||||
"./snapshot-freshness": {
|
||||
"types": "./src/snapshot/snapshot-freshness/index.ts",
|
||||
"default": "./src/snapshot/snapshot-freshness/index.ts"
|
||||
},
|
||||
"./snapshot-label-dedup": {
|
||||
"types": "./src/snapshot/snapshot-label-dedup.ts",
|
||||
"default": "./src/snapshot/snapshot-label-dedup.ts"
|
||||
},
|
||||
"./snapshot-lines": {
|
||||
"types": "./src/snapshot/snapshot-lines.ts",
|
||||
"default": "./src/snapshot/snapshot-lines.ts"
|
||||
},
|
||||
"./snapshot-node-lookup": {
|
||||
"types": "./src/snapshot-node-lookup.ts",
|
||||
"default": "./src/snapshot-node-lookup.ts"
|
||||
},
|
||||
"./snapshot-occlusion": {
|
||||
"types": "./src/snapshot-occlusion.ts",
|
||||
"default": "./src/snapshot-occlusion.ts"
|
||||
},
|
||||
"./snapshot-presentation-android-helper": {
|
||||
"types": "./src/snapshot/snapshot-presentation/android/helper.ts",
|
||||
"default": "./src/snapshot/snapshot-presentation/android/helper.ts"
|
||||
},
|
||||
"./snapshot-presentation-ios-transitions-fixtures": {
|
||||
"types": "./src/snapshot/snapshot-presentation/ios/transitions.fixtures.ts",
|
||||
"default": "./src/snapshot/snapshot-presentation/ios/transitions.fixtures.ts"
|
||||
},
|
||||
"./snapshot-quality-backend-capabilities": {
|
||||
"types": "./src/snapshot-quality-backend-capabilities.ts",
|
||||
"default": "./src/snapshot-quality-backend-capabilities.ts"
|
||||
@@ -101,6 +177,22 @@
|
||||
"./snapshot-rect-projection": {
|
||||
"types": "./src/snapshot-rect-projection.ts",
|
||||
"default": "./src/snapshot-rect-projection.ts"
|
||||
},
|
||||
"./snapshot-state": {
|
||||
"types": "./src/snapshot-state.ts",
|
||||
"default": "./src/snapshot-state.ts"
|
||||
},
|
||||
"./snapshot-timeout-policy": {
|
||||
"types": "./src/snapshot/snapshot-timeout-policy.ts",
|
||||
"default": "./src/snapshot/snapshot-timeout-policy.ts"
|
||||
},
|
||||
"./snapshot-visibility": {
|
||||
"types": "./src/snapshot/snapshot-visibility.ts",
|
||||
"default": "./src/snapshot/snapshot-visibility.ts"
|
||||
},
|
||||
"./text-surface": {
|
||||
"types": "./src/snapshot/snapshot-presentation/text-surface.ts",
|
||||
"default": "./src/snapshot/snapshot-presentation/text-surface.ts"
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export function likelyPlayableWebmContainer(): Buffer {
|
||||
// One 16x16 VP8 keyframe generated by ffmpeg. Unlike a marker-only synthetic fixture,
|
||||
// ffprobe identifies this as a WebM video stream with a 40ms duration.
|
||||
return Buffer.from(
|
||||
'GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAHpEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHYTbuMU6uEElTDZ1OsggElTbuMU6uEHFO7a1OsggHT7AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmsirXsYMPQkBNgI1MYXZmNjIuMTIuMTAxV0GNTGF2ZjYyLjEyLjEwMUSJiEBEAAAAAAAAFlSua8iuAQAAAAAAAD/XgQFzxYgNIomR4viG6pyBACK1nIN1bmSIgQCGhVZfVlA4g4EBI+ODhAJiWgDgkLCBELqBEJqBAlWwhFW5gQESVMNn/HNzoGPAgGfImkWjh0VOQ09ERVJEh41MYXZmNjIuMTIuMTAxc3PWY8CLY8WIDSKJkeL4hupnyKFFo4dFTkNPREVSRIeUTGF2YzYyLjI4LjEwMSBsaWJ2cHhnyKFFo4hEVVJBVElPTkSHkzAwOjAwOjAwLjA0MDAwMDAwMAAfQ7Z1qOeBAKOjgQAAgBACAJ0BKhAAEAAARwiFhYiFhIgCAgAMDWAA/v+rUIAcU7trkbuPs4EAt4r3gQHxggGm8IED',
|
||||
'base64',
|
||||
);
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { mkdtempForTestSync } from '../../__tests__/test-utils/tmp-dir.ts';
|
||||
import { mkdtempForTestSync } from '../../tmp-dir.fixtures.ts';
|
||||
|
||||
vi.mock('@agent-device/host-kit/command', async (importOriginal) => {
|
||||
const fs = await import('node:fs');
|
||||
+2
-2
@@ -8,9 +8,9 @@ import { getRecordingOverlaySupportWarning } from '../overlay.ts';
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const recordingScriptsDir = path.resolve(
|
||||
__dirname,
|
||||
'../../../apple/runner/AgentDeviceRunner/RecordingScripts',
|
||||
'../../../../../apple/runner/AgentDeviceRunner/RecordingScripts',
|
||||
);
|
||||
const recordingTestSupportDir = path.resolve(__dirname, '../../../test/integration/support');
|
||||
const recordingTestSupportDir = path.resolve(__dirname, '../../../../../test/integration/support');
|
||||
const SWIFT_TYPECHECK_TIMEOUT_MS = 60_000;
|
||||
let swiftCompilerPath = 'swiftc';
|
||||
let swiftSdkPath = '';
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { mkdtempForTestSync } from '../__tests__/test-utils/tmp-dir.ts';
|
||||
import { mkdtempForTestSync } from '../tmp-dir.fixtures.ts';
|
||||
|
||||
vi.mock(import('@agent-device/host-kit/command'), async (importOriginal) => ({
|
||||
...(await importOriginal()),
|
||||
+1
-1
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { expect, test } from 'vitest';
|
||||
import { likelyPlayableWebmContainer } from '../__tests__/test-utils/video-fixtures.ts';
|
||||
import { mkdtempForTestSync } from '../__tests__/test-utils/tmp-dir.ts';
|
||||
import { mkdtempForTestSync } from '../tmp-dir.fixtures.ts';
|
||||
import { hasPlayableWebmStructure } from './video-webm.ts';
|
||||
|
||||
const directory = mkdtempForTestSync('agent-device-video-webm-structure-');
|
||||
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { expect, test } from 'vitest';
|
||||
import { likelyPlayableWebmContainer } from '../__tests__/test-utils/video-fixtures.ts';
|
||||
import { mkdtempForTestSync } from '../__tests__/test-utils/tmp-dir.ts';
|
||||
import { mkdtempForTestSync } from '../tmp-dir.fixtures.ts';
|
||||
import { isPlayableVideo } from './video.ts';
|
||||
|
||||
const directory = mkdtempForTestSync('agent-device-video-webm-');
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { test } from 'vitest';
|
||||
import assert from 'node:assert/strict';
|
||||
import { attachRefs, type RawSnapshotNode, type SnapshotNode } from '@agent-device/kernel/snapshot';
|
||||
import { collectSettleChromeRefs } from '../snapshot-chrome.ts';
|
||||
import { collectSettleChromeRefs } from './snapshot-chrome.ts';
|
||||
|
||||
function refFor(nodes: SnapshotNode[], label: string): string {
|
||||
const node = nodes.find((candidate) => candidate.label === label);
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'vitest';
|
||||
import { attachRefs } from '@agent-device/kernel/snapshot';
|
||||
import { findNodeByLabel, resolveRefLabel } from '../snapshot-node-lookup.ts';
|
||||
import { findNodeByLabel, resolveRefLabel } from './snapshot-node-lookup.ts';
|
||||
|
||||
test('findNodeByLabel matches label, value, and identifier case-insensitively', () => {
|
||||
const nodes = attachRefs([
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { SnapshotState } from '@agent-device/kernel/snapshot';
|
||||
import { extractNodeText, isMeaningfulLabel } from '@agent-device/contracts/snapshot';
|
||||
import { findNodeByLabel } from '../snapshot/snapshot-node-label.ts';
|
||||
import { findNodeByLabel } from './snapshot/snapshot-node-label.ts';
|
||||
|
||||
export { findNodeByLabel };
|
||||
|
||||
@@ -17,11 +17,11 @@ import {
|
||||
import {
|
||||
annotateCoveredSnapshotNodes,
|
||||
annotateSnapshotNodesCoveredByPolicy,
|
||||
} from '@agent-device/capture-kit/snapshot-occlusion';
|
||||
import { coveredAndroidReplacementNodeIndexes } from '../snapshot/android-replacement-surface-occlusion.ts';
|
||||
import { scopeSnapshotNodes } from '@agent-device/capture-kit/snapshot-desktop-projection';
|
||||
import { normalizeSnapshotTree, pruneGroupNodes } from '../core/snapshot-tree-ingestion.ts';
|
||||
import { iosSnapshotComparisonIdentityKey } from '@agent-device/capture-kit/ios-snapshot-planning';
|
||||
} from './snapshot-occlusion.ts';
|
||||
import { coveredAndroidReplacementNodeIndexes } from './snapshot/android-replacement-surface-occlusion.ts';
|
||||
import { scopeSnapshotNodes } from './snapshot-desktop-projection.ts';
|
||||
import { normalizeSnapshotTree, pruneGroupNodes } from './snapshot-tree-ingestion.ts';
|
||||
import { iosSnapshotComparisonIdentityKey } from './ios-snapshot-planning.ts';
|
||||
import type { IosSnapshotComparisonIdentity } from '@agent-device/contracts/ios-snapshot';
|
||||
|
||||
/**
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'vitest';
|
||||
import { normalizeSnapshotTree, pruneGroupNodes } from '../snapshot-tree-ingestion.ts';
|
||||
import { normalizeSnapshotTree, pruneGroupNodes } from './snapshot-tree-ingestion.ts';
|
||||
|
||||
test('pruneGroupNodes drops unlabeled group wrappers and rebalances depth', () => {
|
||||
const raw = [
|
||||
+2
-1
@@ -1,9 +1,10 @@
|
||||
import type { Rect } from '@agent-device/kernel/snapshot';
|
||||
import fc from 'fast-check';
|
||||
import { expect, test } from 'vitest';
|
||||
import { PROPERTY_RUNS } from '../../__tests__/test-utils/property-arbitraries.ts';
|
||||
import { unionCoverage } from '../rect-coverage.ts';
|
||||
|
||||
const PROPERTY_RUNS = 100;
|
||||
|
||||
const smallRect = fc.record({
|
||||
x: fc.integer({ min: -4, max: 20 }),
|
||||
y: fc.integer({ min: -4, max: 20 }),
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test, vi } from 'vitest';
|
||||
import type { SnapshotCaptureAnnotations } from '@agent-device/contracts/capture';
|
||||
import { makeSnapshotState } from '../../__tests__/test-utils/snapshot-builders.ts';
|
||||
import { makeSnapshotState } from '../../snapshot-state.fixtures.ts';
|
||||
import { captureFreshnessRecoveredAttempt } from '../snapshot-freshness/recovery.ts';
|
||||
import type {
|
||||
SnapshotFreshnessReason,
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'vitest';
|
||||
import type { RawSnapshotNode } from '@agent-device/kernel/snapshot';
|
||||
import { makeSnapshotState } from '../../__tests__/test-utils/snapshot-builders.ts';
|
||||
import { makeSnapshotState } from '../../snapshot-state.fixtures.ts';
|
||||
import {
|
||||
androidFreshnessReason,
|
||||
buildSnapshotSignatures,
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { expect, test } from 'vitest';
|
||||
import { attachRefs, type RawSnapshotNode } from '@agent-device/kernel/snapshot';
|
||||
import { buildSnapshotVisibility } from '../snapshot-visibility.ts';
|
||||
import { presentIosInteractiveSnapshot } from '@agent-device/capture-kit/ios-snapshot-engine';
|
||||
import { presentIosInteractiveSnapshot } from '../../ios-snapshot-engine/index.ts';
|
||||
|
||||
function buildSnapshotState(data: { nodes?: RawSnapshotNode[]; backend?: 'xctest' }) {
|
||||
return {
|
||||
+2
-5
@@ -2,11 +2,8 @@ import {
|
||||
IosSnapshotEngineError,
|
||||
publishIosSnapshot,
|
||||
toIosSnapshotEngineErrorDetails,
|
||||
} from '@agent-device/capture-kit/ios-snapshot-engine';
|
||||
import {
|
||||
createIosSnapshotRequest,
|
||||
deriveIosCaptureHint,
|
||||
} from '@agent-device/capture-kit/ios-snapshot-planning';
|
||||
} from '../ios-snapshot-engine/index.ts';
|
||||
import { createIosSnapshotRequest, deriveIosCaptureHint } from '../ios-snapshot-planning.ts';
|
||||
import type {
|
||||
IosAcquisitionResidue,
|
||||
IosSnapshotFact,
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { deriveMobileSnapshotHiddenContentHints } from '@agent-device/capture-kit/mobile-snapshot-semantics';
|
||||
import { deriveMobileSnapshotHiddenContentHints } from '../../mobile-snapshot-semantics.ts';
|
||||
import {
|
||||
createSnapshotVisibility,
|
||||
isScrollableNodeLike,
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from 'vitest';
|
||||
import { presentIosInteractiveSnapshot } from '@agent-device/capture-kit/ios-snapshot-engine';
|
||||
import { presentIosInteractiveSnapshot } from '../../../ios-snapshot-engine/index.ts';
|
||||
import {
|
||||
closedComposerWithRetainedActionShelfNodes,
|
||||
closedComposerWithRetainedRegularTreeActionNodes,
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from 'vitest';
|
||||
import { elementClassicRoomListNodes, legitimatelyLabeledCellNodes } from './rows.fixtures.ts';
|
||||
import { presentIosInteractiveSnapshot } from '@agent-device/capture-kit/ios-snapshot-engine';
|
||||
import { presentIosInteractiveSnapshot } from '../../../ios-snapshot-engine/index.ts';
|
||||
|
||||
test('iOS row presentation associates generic room cells with their descendant titles', () => {
|
||||
const nodes = presentIosInteractiveSnapshot(elementClassicRoomListNodes);
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { test } from 'vitest';
|
||||
import { readSnapshotQualityVerdict } from '@agent-device/capture-kit/snapshot-quality-verdict';
|
||||
import { renderSnapshotQualityWarnings } from '../../snapshot/snapshot-presentation/quality-warnings.ts';
|
||||
import { readSnapshotQualityVerdict } from '../../snapshot-quality-verdict.ts';
|
||||
import { renderSnapshotQualityWarnings } from './quality-warnings.ts';
|
||||
|
||||
const sharedRecoveryReason =
|
||||
'iOS XCTest snapshot failed while serializing the accessibility tree. Error kAXErrorIllegalArgument getting snapshot for element <AXUIElementRef 0x1>';
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { buildMobileSnapshotPresentation } from '@agent-device/capture-kit/mobile-snapshot-semantics';
|
||||
import { buildMobileSnapshotPresentation } from '../mobile-snapshot-semantics.ts';
|
||||
import {
|
||||
usesMobileSnapshotPresentation,
|
||||
type SnapshotState,
|
||||
@@ -2,7 +2,7 @@ import type { SnapshotNode } from '@agent-device/kernel/snapshot';
|
||||
|
||||
/**
|
||||
* Android status-bar/navigation-bar chrome identity, shared by the settle-chrome
|
||||
* classifier (`core/snapshot-chrome.ts`) and the helper content classifier
|
||||
* classifier (`packages/capture-kit/src/snapshot-chrome.ts`) and the helper content classifier
|
||||
* (`packages/platform-android/src/snapshot-content-recovery.ts`). SystemUI also hosts actionable
|
||||
* overlays — volume panel, media pickers, the shade itself — so chrome is never a
|
||||
* package-level fact: only the status/nav-bar container's subtree is chrome.
|
||||
|
||||
@@ -56,7 +56,7 @@ export const SELECTOR_KEY_NAMES: readonly SelectorKey[] = [...ALL_KEYS];
|
||||
|
||||
// Role/element-type words that show up as accessibility roles, not selector keys (e.g. the
|
||||
// `button` in `button="Push Article"`). Superset of the ROLE_LABELS vocabulary in
|
||||
// src/snapshot/snapshot-lines.ts (plus a few common role words like list/tab/alert/dialog/header,
|
||||
// packages/capture-kit/src/snapshot/snapshot-lines.ts (plus a few common role words like list/tab/alert/dialog/header,
|
||||
// minus valid selector keys such as `text`, which ALL_KEYS short-circuits before this set is
|
||||
// consulted), kept locally to avoid a selectors -> snapshot layering dependency. Drifts silently
|
||||
// if ROLE_LABELS grows; that's fine here since this only sharpens a hint, not validates anything.
|
||||
|
||||
@@ -35,7 +35,7 @@ import type { ConnectVerification } from '../../src/cli/connection/connect-provi
|
||||
import type { RemoteConnectionState } from '../../src/remote/remote-connection-state.ts';
|
||||
import { AppError, normalizeError } from '@agent-device/kernel/errors';
|
||||
import type { SnapshotQualityVerdict } from '@agent-device/kernel/snapshot';
|
||||
import { renderSnapshotQualityWarnings } from '../../src/snapshot/snapshot-presentation/quality-warnings.ts';
|
||||
import { renderSnapshotQualityWarnings } from '@agent-device/capture-kit/quality-warnings';
|
||||
import { printHumanError } from '../../src/commands/output/error.ts';
|
||||
import { formatSnapshotText } from '../../src/commands/output/snapshot.ts';
|
||||
|
||||
|
||||
@@ -46,9 +46,9 @@ function authorityFixture(): Map<string, string> {
|
||||
"import { SessionStore } from './session-store.ts';",
|
||||
].join('\n'),
|
||||
'src/daemon/type-consumer.ts': "import type { SessionStore } from './session-store.ts';\n",
|
||||
'src/snapshot/policy-consumer.ts': [
|
||||
"import type { SessionState } from '../daemon/session-state.ts';",
|
||||
"import type { SessionRef } from '../daemon/session-state.ts';",
|
||||
'packages/capture-kit/src/snapshot/policy-consumer.ts': [
|
||||
"import type { SessionState } from '../../../../src/daemon/session-state.ts';",
|
||||
"import type { SessionRef } from '../../../../src/daemon/session-state.ts';",
|
||||
"import './ordinary-target.ts';",
|
||||
].join('\n'),
|
||||
'src/daemon/ordinary-consumer.ts': [
|
||||
@@ -62,7 +62,7 @@ function authorityFixture(): Map<string, string> {
|
||||
'src/daemon/session-script-publication-capability.ts':
|
||||
'export function isSessionRecording() {}\n',
|
||||
'src/daemon/session-state-store.ts': 'export const SessionState = 1;\n',
|
||||
'src/snapshot/ordinary-target.ts': 'export const ordinary = 1;\n',
|
||||
'packages/capture-kit/src/snapshot/ordinary-target.ts': 'export const ordinary = 1;\n',
|
||||
'packages/contracts/src/facades/client.ts': 'export type ClientShape = string;\n',
|
||||
'packages/contracts/src/facades/capture.ts': 'export type CaptureShape = string;\n',
|
||||
'packages/contracts/src/facades/replay.ts': 'export type ReplayShape = string;\n',
|
||||
@@ -108,7 +108,11 @@ test('authority overlay uses declared roots and symbols, keeps kind separate, an
|
||||
labels: ['live-state-authority'],
|
||||
});
|
||||
assert.deepEqual(
|
||||
graphEdge(graph, 'src/snapshot/policy-consumer.ts', 'src/snapshot/ordinary-target.ts'),
|
||||
graphEdge(
|
||||
graph,
|
||||
'packages/capture-kit/src/snapshot/policy-consumer.ts',
|
||||
'packages/capture-kit/src/snapshot/ordinary-target.ts',
|
||||
),
|
||||
{ kind: 'value', labels: ['executable-policy'] },
|
||||
);
|
||||
assert.deepEqual(
|
||||
@@ -122,12 +126,16 @@ test('authority overlay uses declared roots and symbols, keeps kind separate, an
|
||||
|
||||
const stateEdges = resolveImportEdges(files, authorityWorkspaceTargets()).filter(
|
||||
(edge) =>
|
||||
edge.file === 'src/snapshot/policy-consumer.ts' &&
|
||||
edge.file === 'packages/capture-kit/src/snapshot/policy-consumer.ts' &&
|
||||
edge.target === 'src/daemon/session-state.ts',
|
||||
);
|
||||
assert.equal(stateEdges.length, 2, 'the fixture must exercise raw same-pair imports');
|
||||
assert.deepEqual(
|
||||
graphEdge(graph, 'src/snapshot/policy-consumer.ts', 'src/daemon/session-state.ts'),
|
||||
graphEdge(
|
||||
graph,
|
||||
'packages/capture-kit/src/snapshot/policy-consumer.ts',
|
||||
'src/daemon/session-state.ts',
|
||||
),
|
||||
{
|
||||
kind: 'type',
|
||||
labels: ['live-state-shape', 'executable-policy'],
|
||||
|
||||
@@ -72,7 +72,7 @@ hint: The UI kept changing for the whole settle budget (animation, carousel, or
|
||||
|
||||
// Recovered snapshot: the private-ax fallback fired but still exposed
|
||||
// actionable refs. Warning wording is renderSnapshotQualityWarnings
|
||||
// (src/snapshot/snapshot-presentation/quality-warnings.ts); lines are the structured snapshot
|
||||
// (packages/capture-kit/src/snapshot/snapshot-presentation/quality-warnings.ts); lines are the structured snapshot
|
||||
// renderer (src/commands/output/snapshot.ts formatSnapshotText).
|
||||
export const PRIVATE_AX_RECOVERY_SAMPLE = {
|
||||
command: 'agent-device snapshot -i',
|
||||
|
||||
@@ -235,7 +235,7 @@ export const ARCHITECTURE_OWNERSHIP = {
|
||||
{
|
||||
name: 'snapshot-policy',
|
||||
kind: 'executable-policy',
|
||||
roots: ['src/snapshot/'],
|
||||
roots: ['packages/capture-kit/src/snapshot/'],
|
||||
forbiddenTargetRoots: ['src/daemon/'],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -56,7 +56,7 @@ export function contractsImplementationAuthorityViolations(
|
||||
violation(
|
||||
file.path,
|
||||
1,
|
||||
'contracts may not own snapshot quality warning rendering; that presentation policy belongs in src/snapshot/snapshot-presentation',
|
||||
'contracts may not own snapshot quality warning rendering; that presentation policy belongs in packages/capture-kit/src/snapshot/snapshot-presentation',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ test('classifyZone separates the ranked spine from intentionally-unranked zones'
|
||||
// Every satellite zone joined the spine; only the composition root stays out, because R2
|
||||
// forbids daemon/ from importing commands/ so the files that wire them cannot be ranked.
|
||||
assert.equal(classifyZone('mcp'), 'ranked');
|
||||
assert.equal(classifyZone('snapshot'), 'ranked');
|
||||
assert.equal(classifyZone('screenshot-diff'), 'ranked');
|
||||
// A zone that is neither ranked nor listed peripheral must be flagged, never
|
||||
// silently treated as back-edge-free.
|
||||
assert.equal(classifyZone('not-a-real-zone'), 'unclassified');
|
||||
|
||||
@@ -41,13 +41,11 @@ const TARGET_DAG_RANK = new Map([
|
||||
['command-registry', 1],
|
||||
['contracts', 1],
|
||||
['maestro', 1],
|
||||
['recording', 1],
|
||||
['replay-test', 1],
|
||||
['request', 1],
|
||||
['screenshot-diff', 1],
|
||||
['selectors', 1],
|
||||
['session-journal', 1],
|
||||
['snapshot', 1],
|
||||
['core', 2],
|
||||
['cli-schema', 3],
|
||||
['commands', 3],
|
||||
|
||||
@@ -392,11 +392,13 @@ test('the real tree parses, declares, and passes R11', () => {
|
||||
);
|
||||
assert.deepEqual([...captureKitPackage.exportTargets.keys()].sort(), [
|
||||
'@agent-device/capture-kit',
|
||||
'@agent-device/capture-kit/android-replacement-surface-occlusion',
|
||||
'@agent-device/capture-kit/durable-capture',
|
||||
'@agent-device/capture-kit/durable-json',
|
||||
'@agent-device/capture-kit/ios-snapshot-acquisition',
|
||||
'@agent-device/capture-kit/ios-snapshot-engine',
|
||||
'@agent-device/capture-kit/ios-snapshot-planning',
|
||||
'@agent-device/capture-kit/ios-snapshot-runtime',
|
||||
'@agent-device/capture-kit/mobile-snapshot-semantics',
|
||||
'@agent-device/capture-kit/png',
|
||||
'@agent-device/capture-kit/png-crop',
|
||||
@@ -405,15 +407,36 @@ test('the real tree parses, declares, and passes R11', () => {
|
||||
'@agent-device/capture-kit/png-size',
|
||||
'@agent-device/capture-kit/png-worker-client',
|
||||
'@agent-device/capture-kit/post-gesture-stability',
|
||||
'@agent-device/capture-kit/quality-warnings',
|
||||
'@agent-device/capture-kit/react-native-overlay',
|
||||
'@agent-device/capture-kit/recording-output-path',
|
||||
'@agent-device/capture-kit/recording-overlay',
|
||||
'@agent-device/capture-kit/recording-telemetry',
|
||||
'@agent-device/capture-kit/recording-video',
|
||||
'@agent-device/capture-kit/repeated-nav-subtree',
|
||||
'@agent-device/capture-kit/screenshot-density',
|
||||
'@agent-device/capture-kit/screenshot-diff-pixels',
|
||||
'@agent-device/capture-kit/screenshot-overlay',
|
||||
'@agent-device/capture-kit/scroll-edge-state',
|
||||
'@agent-device/capture-kit/snapshot-chrome',
|
||||
'@agent-device/capture-kit/snapshot-desktop-projection',
|
||||
'@agent-device/capture-kit/snapshot-desktop-surface',
|
||||
'@agent-device/capture-kit/snapshot-diff',
|
||||
'@agent-device/capture-kit/snapshot-evidence',
|
||||
'@agent-device/capture-kit/snapshot-freshness',
|
||||
'@agent-device/capture-kit/snapshot-label-dedup',
|
||||
'@agent-device/capture-kit/snapshot-lines',
|
||||
'@agent-device/capture-kit/snapshot-node-lookup',
|
||||
'@agent-device/capture-kit/snapshot-occlusion',
|
||||
'@agent-device/capture-kit/snapshot-presentation-android-helper',
|
||||
'@agent-device/capture-kit/snapshot-presentation-ios-transitions-fixtures',
|
||||
'@agent-device/capture-kit/snapshot-quality-backend-capabilities',
|
||||
'@agent-device/capture-kit/snapshot-quality-verdict',
|
||||
'@agent-device/capture-kit/snapshot-rect-projection',
|
||||
'@agent-device/capture-kit/snapshot-state',
|
||||
'@agent-device/capture-kit/snapshot-timeout-policy',
|
||||
'@agent-device/capture-kit/snapshot-visibility',
|
||||
'@agent-device/capture-kit/text-surface',
|
||||
]);
|
||||
|
||||
const provisionKitPackage = packages.find((pkg) => pkg.name === '@agent-device/provision-kit');
|
||||
|
||||
@@ -57,6 +57,26 @@ test('R73 rejects an out-of-adapter provider presentation import', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('R73 rejects a provider import of the capture-kit presentation runtime subpath', () => {
|
||||
const result = violations(
|
||||
new Map([
|
||||
[
|
||||
providerHelper,
|
||||
`import { presentIosSnapshot } from '@agent-device/capture-kit/ios-snapshot-runtime';\nvoid presentIosSnapshot;\n`,
|
||||
],
|
||||
]),
|
||||
);
|
||||
assert.ok(
|
||||
result.some(
|
||||
(entry) =>
|
||||
entry.rule === PROVIDER_SNAPSHOT_PRESENTATION_RULE &&
|
||||
entry.file === providerHelper &&
|
||||
entry.message.includes(IOS_SNAPSHOT_PRESENTATION_OWNER),
|
||||
),
|
||||
JSON.stringify(result),
|
||||
);
|
||||
});
|
||||
|
||||
for (const planted of [
|
||||
{
|
||||
name: 'a planted provider residue discard',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Catches: a provider-* package acquiring an iOS snapshot outside the capture-kit acquisition
|
||||
// entrypoint, or presenting it outside src/snapshot/ios-snapshot-runtime.ts — the exact split
|
||||
// R72's engine convergence closed for the runner layer, mirrored here one layer up for the
|
||||
// provider packages that call into it.
|
||||
// entrypoint, or presenting it outside packages/capture-kit/src/snapshot/ios-snapshot-runtime.ts
|
||||
// — the exact split R72's engine convergence closed for the runner layer, mirrored here one
|
||||
// layer up for the provider packages that call into it.
|
||||
// Evidence: 7ee1a5ded7 (#2233) carried provider acquisitions through this one presentation
|
||||
// owner, the change this policy was written to hold in place.
|
||||
// Cost: 195 LOC (111 rule + 84 test).
|
||||
@@ -9,7 +9,7 @@
|
||||
// reaching presentation only through @agent-device/capture-kit/ios-snapshot-acquisition, and
|
||||
// never constructing, discarding, or reassigning acquisition residue, no longer matter. An
|
||||
// exports map cannot replace it: it restricts external specifiers, not the transitive walk
|
||||
// into src/snapshot/ or a provider-local `residue` property or assignment.
|
||||
// into packages/capture-kit/src/snapshot/ or a provider-local `residue` property or assignment.
|
||||
|
||||
import { parseSync } from 'oxc-parser';
|
||||
import type { LayeringViolation, ResolvedImportEdge } from './model.ts';
|
||||
@@ -18,7 +18,8 @@ import { memberPath, propertyName, visitAst } from './layering-ast.ts';
|
||||
export const PROVIDER_SNAPSHOT_PRESENTATION_RULE = 'R73 provider-snapshot-presentation-ownership';
|
||||
export const IOS_SNAPSHOT_ACQUISITION_ENTRYPOINT =
|
||||
'@agent-device/capture-kit/ios-snapshot-acquisition';
|
||||
export const IOS_SNAPSHOT_PRESENTATION_OWNER = 'src/snapshot/ios-snapshot-runtime.ts';
|
||||
export const IOS_SNAPSHOT_PRESENTATION_OWNER =
|
||||
'packages/capture-kit/src/snapshot/ios-snapshot-runtime.ts';
|
||||
|
||||
const PROVIDER_SOURCE = /^packages\/provider-[^/]+\/src\//;
|
||||
const IOS_SNAPSHOT_CAPTURE_KIT_ROOT = 'packages/capture-kit/src/ios-snapshot-';
|
||||
@@ -109,7 +110,7 @@ function residueViolations(providerFile: string, source: string): LayeringViolat
|
||||
function isPresentationTarget(target: string): boolean {
|
||||
return (
|
||||
target === IOS_SNAPSHOT_PRESENTATION_OWNER ||
|
||||
target.startsWith('src/snapshot/') ||
|
||||
target.startsWith('packages/capture-kit/src/snapshot/') ||
|
||||
(target.startsWith(IOS_SNAPSHOT_CAPTURE_KIT_ROOT) &&
|
||||
target !== 'packages/capture-kit/src/ios-snapshot-acquisition.ts')
|
||||
);
|
||||
|
||||
@@ -12,7 +12,7 @@ import { workspaceSpecifierTargets } from './package-boundaries.ts';
|
||||
import { listTrackedProductionSources } from './tracked-sources.ts';
|
||||
|
||||
const repoRoot = path.resolve(import.meta.dirname, '../..');
|
||||
const assemblyFile = 'src/core/snapshot-state.ts';
|
||||
const assemblyFile = 'packages/capture-kit/src/snapshot-state.ts';
|
||||
const producerAdapter = 'packages/platform-apple/src/snapshot-source/adapter.ts';
|
||||
|
||||
function currentSources(overrides: ReadonlyMap<string, string> = new Map()): Map<string, string> {
|
||||
|
||||
@@ -25,7 +25,7 @@ export const SNAPSHOT_ASSEMBLY_PRESENTATION_RULE = 'R74 snapshot-assembly-presen
|
||||
* refs; it does not present, and it does not know which channel it is holding.
|
||||
*/
|
||||
export const SNAPSHOT_ASSEMBLY_FILES: readonly string[] = [
|
||||
'src/core/snapshot-state.ts',
|
||||
'packages/capture-kit/src/snapshot-state.ts',
|
||||
'src/daemon/snapshot-capture.ts',
|
||||
];
|
||||
|
||||
|
||||
@@ -52,12 +52,12 @@ test('the boundary reports a facet module that reaches back into the daemon', ()
|
||||
const sources = new Map([
|
||||
['src/daemon/types.ts', 'export type SessionState = { id: string };\n'],
|
||||
[
|
||||
'src/snapshot/snapshot-freshness/android.ts',
|
||||
"import type { SessionState } from '../../daemon/types.ts';\nexport type X = SessionState;\n",
|
||||
'packages/capture-kit/src/snapshot/snapshot-freshness/android.ts',
|
||||
"import type { SessionState } from '../../../../../src/daemon/types.ts';\nexport type X = SessionState;\n",
|
||||
],
|
||||
]);
|
||||
|
||||
assert.deepEqual(daemonImportsFromSnapshotFacet(sources), [
|
||||
'src/snapshot/snapshot-freshness/android.ts:1 -> src/daemon/types.ts',
|
||||
'packages/capture-kit/src/snapshot/snapshot-freshness/android.ts:1 -> src/daemon/types.ts',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -61,8 +61,14 @@ export const KERNEL_MODULES: readonly KernelModule[] = [
|
||||
{
|
||||
id: 'scroll-edge-state',
|
||||
label: 'Scroll edge-state detection',
|
||||
mutate: ['src/snapshot/scroll-edge-state.ts', 'src/snapshot/scroll-edge-state/**/*.ts'],
|
||||
owns: ['src/snapshot/scroll-edge-state.ts', 'src/snapshot/scroll-edge-state/'],
|
||||
mutate: [
|
||||
'packages/capture-kit/src/snapshot/scroll-edge-state.ts',
|
||||
'packages/capture-kit/src/snapshot/scroll-edge-state/**/*.ts',
|
||||
],
|
||||
owns: [
|
||||
'packages/capture-kit/src/snapshot/scroll-edge-state.ts',
|
||||
'packages/capture-kit/src/snapshot/scroll-edge-state/',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'selectors',
|
||||
|
||||
@@ -80,9 +80,14 @@ test('a lane-tooling diff selects real mutants', () => {
|
||||
// The weekly sweep is the kernel report; selecting on derived ownership would
|
||||
// run the full ten-shard sweep on most PRs for a report nobody gates on.
|
||||
test('a kernel diff selects nothing — only a harness diff spends mutants', () => {
|
||||
const dir = worktreeWithCommit('kernel', ['src/snapshot/scroll-edge-state.ts']);
|
||||
const dir = worktreeWithCommit('kernel', [
|
||||
'packages/capture-kit/src/snapshot/scroll-edge-state.ts',
|
||||
]);
|
||||
assert.deepEqual(listAffected(dir), []);
|
||||
assert.deepEqual(affectedMatrixFor(['src/snapshot/scroll-edge-state.ts']), []);
|
||||
assert.deepEqual(
|
||||
affectedMatrixFor(['packages/capture-kit/src/snapshot/scroll-edge-state.ts']),
|
||||
[],
|
||||
);
|
||||
});
|
||||
|
||||
test('a docs-only diff selects nothing', () => {
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
resetAndroidSnapshotHelperSessions,
|
||||
} from '@agent-device/platform-android/mechanics';
|
||||
import { ANDROID_SNAPSHOT_HELPER_FIXTURE_ARTIFACT } from './test-utils/android-snapshot-helper.ts';
|
||||
import { isAndroidSnapshotTimeoutError } from '../snapshot/snapshot-timeout-policy.ts';
|
||||
import { isAndroidSnapshotTimeoutError } from '@agent-device/capture-kit/snapshot-timeout-policy';
|
||||
import '../platform-runtime-android-adb-host.ts';
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,8 +9,8 @@ import {
|
||||
snapshotAndroid,
|
||||
type AndroidAdbExecutor,
|
||||
} from '@agent-device/platform-android/mechanics';
|
||||
import { buildSnapshotState } from '../core/snapshot-state.ts';
|
||||
import { coveredAndroidReplacementNodeIndexes } from '../snapshot/android-replacement-surface-occlusion.ts';
|
||||
import { buildSnapshotState } from '@agent-device/capture-kit/snapshot-state';
|
||||
import { coveredAndroidReplacementNodeIndexes } from '@agent-device/capture-kit/android-replacement-surface-occlusion';
|
||||
import {
|
||||
ANDROID_SNAPSHOT_HELPER_FIXTURE_ARTIFACT,
|
||||
androidSnapshotHelperOutput,
|
||||
|
||||
@@ -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 { buildSnapshotState } from '../core/snapshot-state.ts';
|
||||
import { buildSnapshotState } from '@agent-device/capture-kit/snapshot-state';
|
||||
import { parseUiHierarchy } from './test-utils/android-ui-hierarchy-fixtures.ts';
|
||||
import {
|
||||
AndroidSnapshotPresentationFailure,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test } from 'vitest';
|
||||
import assert from 'node:assert/strict';
|
||||
import { buildSnapshotState } from '../core/snapshot-state.ts';
|
||||
import { buildSnapshotState } from '@agent-device/capture-kit/snapshot-state';
|
||||
import { createSnapshotVisibility } from '@agent-device/contracts/snapshot';
|
||||
import {
|
||||
androidSnapshotPublicationInput,
|
||||
|
||||
+12
-3
@@ -11,7 +11,7 @@ const { captureLinuxSurfaceSnapshot, captureMacOsSurfaceSnapshot } = vi.hoisted(
|
||||
|
||||
vi.mock('@agent-device/platform-linux', () => ({ captureLinuxSurfaceSnapshot }));
|
||||
|
||||
import { createSnapshotRuntimeHost } from './snapshot-desktop-surface.ts';
|
||||
import { createSnapshotRuntimeHost } from '@agent-device/capture-kit/snapshot-desktop-surface';
|
||||
|
||||
const macosDevice = {
|
||||
id: 'desktop',
|
||||
@@ -41,8 +41,17 @@ function createHost() {
|
||||
}
|
||||
|
||||
test('desktop snapshot host keeps iOS presentation outside its eager import closure', () => {
|
||||
const closure = eagerClosureOf(path.join(import.meta.dirname, 'snapshot-desktop-surface.ts'));
|
||||
expect(closure).not.toContain(path.join(import.meta.dirname, 'ios-snapshot-runtime.ts'));
|
||||
const entry = path.resolve(
|
||||
import.meta.dirname,
|
||||
'../../packages/capture-kit/src/snapshot/snapshot-desktop-surface.ts',
|
||||
);
|
||||
const closure = eagerClosureOf(entry);
|
||||
expect(closure).not.toContain(
|
||||
path.resolve(
|
||||
import.meta.dirname,
|
||||
'../../packages/capture-kit/src/snapshot/ios-snapshot-runtime.ts',
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('Apple snapshot host preserves non-app macOS surface capture and menubar identity', async () => {
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { CaptureSnapshotResult } from '@agent-device/contracts/client';
|
||||
import { dedupeInheritedSnapshotLabels } from '../../snapshot/snapshot-label-dedup.ts';
|
||||
import { dedupeInheritedSnapshotLabels } from '@agent-device/capture-kit/snapshot-label-dedup';
|
||||
import { formatSnapshotText } from '../output/snapshot.ts';
|
||||
import type { CliOutput } from '../command-contract.ts';
|
||||
import { messageOutput, type CliOutputFormatter } from '../output-common.ts';
|
||||
|
||||
@@ -20,9 +20,9 @@ import type { AgentDeviceRuntime, CommandSessionRecord } from '../../../runtime-
|
||||
import {
|
||||
buildSnapshotDiff,
|
||||
countSnapshotComparableLines,
|
||||
} from '../../../snapshot/snapshot-diff.ts';
|
||||
import { renderSnapshotQualityWarnings } from '../../../snapshot/snapshot-presentation/quality-warnings.ts';
|
||||
import { buildSnapshotVisibility } from '../../../snapshot/snapshot-visibility.ts';
|
||||
} from '@agent-device/capture-kit/snapshot-diff';
|
||||
import { renderSnapshotQualityWarnings } from '@agent-device/capture-kit/quality-warnings';
|
||||
import { buildSnapshotVisibility } from '@agent-device/capture-kit/snapshot-visibility';
|
||||
import { ANDROID_SYSTEM_SURFACE_DISCLOSURE } from '../../../core/android-system-surface-disclosure.ts';
|
||||
import { formatReactNativeOverlayWarning } from '../../react-native/overlay.ts';
|
||||
import { now } from '../../runtime-common.ts';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user