Skip to content

Commit cb3fcc2

Browse files
committed
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.
1 parent 077a173 commit cb3fcc2

86 files changed

Lines changed: 258 additions & 149 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/adr/0019-request-bound-platform-runtime.md

Lines changed: 19 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -902,42 +902,25 @@ target, unverified**, not a derived number.
902902
The root files that remain are either declared host-port adapters (e.g. `adb-host`, bound only
903903
by its named root file per Decision §1) or mechanics whose wave has not landed yet — the two are
904904
not distinguished by filename and need per-file classification before a target is set.
905-
- `src/recording`, `src/snapshot`, `src/snapshot-quality`, `src/screenshot-diff`. Corrected
906-
2026-09-03: `packages/capture-kit/src/` already has broad production ownership across
907-
recording (`screen-recording-live-handle.ts`, `screen-recording-completion.ts`,
908-
`screen-recording-options.ts`, consumed by `platform-android`/`platform-apple`/
909-
`platform-harmonyos`/`platform-web`'s `recording/runtime.ts`), screenshot/diff
910-
(`png.ts`, `png-worker-client.ts`, imported by `src/screenshot-diff/screenshot-diff.ts`),
911-
snapshot quality (`snapshot-quality-verdict.ts`, `snapshot-quality-backend-capabilities.ts`
912-
`src/snapshot-quality/` now holds only a cross-package regression test, no production file),
913-
occlusion (`snapshot-occlusion.ts`), audio/app-log (`audio-probe-runtime.ts`,
914-
`app-log-live-handle.ts`, consumed by `platform-android`, `platform-apple`, and
915-
`provider-limrun`), and iOS acquisition/engine (`ios-snapshot-acquisition.ts`,
916-
`ios-snapshot-planning.ts`, `ios-snapshot-engine/`, consumed by
917-
`src/snapshot/ios-snapshot-runtime.ts`). ADR §1's amendment already assigns this capture
918-
domain to `capture-kit`; the domain mechanics are migrated. What remains under `src/` in
919-
these four directories, verified file-by-file at HEAD, is daemon-facing composition with no
920-
existing package equivalent, not unmigrated capture mechanics:
921-
- `src/recording/{output-path,overlay,swift-cache,telemetry,video,video-webm}.ts` — video
922-
playability polling, overlay burn-in, telemetry persistence, and output-path resolution,
923-
imported only by `src/platform-runtime-screen-recording-*.ts` and
924-
`src/daemon/handlers/record-runtime*.ts`. Equivalent: none.
925-
- `src/snapshot/ios-snapshot-runtime.ts` and `snapshot-visibility.ts` — composition over the
926-
capture-kit acquisition/planning/engine/semantics calls above. Equivalent: capture-kit
927-
(mechanics already migrated; these are the composition callers).
928-
- `src/snapshot/{android-replacement-surface-occlusion,rect-coverage,scroll-edge-state,
929-
snapshot-desktop-surface,snapshot-diff,snapshot-evidence,snapshot-label-dedup,
930-
snapshot-lines,snapshot-node-label,snapshot-timeout-policy}.ts` — none import capture-kit.
931-
`android-replacement-surface-occlusion.ts` implements a distinct Android-specific
932-
footprint algorithm, not the generic viewport pruning in capture-kit's
933-
`snapshot-occlusion.ts`. Equivalent: none.
934-
- `src/snapshot-quality/__tests__/warnings.test.ts` — the sole survivor in that directory;
935-
exercises `renderSnapshotQualityWarnings` (root) against capture-kit's
936-
`readSnapshotQualityVerdict`. Equivalent: capture-kit (production logic fully migrated).
937-
- `src/screenshot-diff/*.ts` (region split/overlay/summarization/component composition) —
938-
pixel-diff computation and PNG decode/encode already call capture-kit's `png`/
939-
`png-worker-client`; the root files remain for daemon/CLI diff-report composition.
940-
Equivalent: none (built atop already-migrated capture-kit mechanics).
905+
- `src/recording`, `src/snapshot`, `src/snapshot-quality`**migrated to
906+
`packages/capture-kit/src/` (2026-09-07)**: the whole trees moved as-is (`recording/`,
907+
`snapshot/` including its `snapshot-presentation/` and `snapshot-freshness/` subtrees),
908+
together with the cross-package `warnings.test.ts` regression test. The four snapshot
909+
modules from `src/core/` (`snapshot-chrome.ts`, `snapshot-state.ts`,
910+
`snapshot-tree-ingestion.ts`, `snapshot-node-lookup.ts`, with their tests) joined the
911+
package root. External consumers (daemon, commands, platform hosts, integration tests)
912+
use package subpath exports (e.g. `@agent-device/capture-kit/snapshot-lines`,
913+
`/recording-video`, `/ios-snapshot-runtime`); `snapshot-tree-ingestion` carries no
914+
subpath because only `snapshot-state.ts` (same package) consumes it. Three tests stayed
915+
at the root — `src/core/__tests__/snapshot-state.test.ts` and
916+
`snapshot-chrome-android-statusbar.test.ts` (pinned to root-owned
917+
`interaction-targeting` and the android UI-hierarchy fixtures) and
918+
`src/__tests__/snapshot-desktop-surface.test.ts` (pinned to the root
919+
eager-import-closure fixtures).
920+
- `src/screenshot-diff/*.ts` (region split/overlay/summarization/component composition) —
921+
pixel-diff computation and PNG decode/encode already call capture-kit's `png`/
922+
`png-worker-client`; the root files remain for daemon/CLI diff-report composition.
923+
Equivalent: none (built atop already-migrated capture-kit mechanics).
941924
- `src/provider-device-runtime.ts`, `src/provider-device-runtimes.ts`,
942925
`src/provider-limrun-runtime.ts`, `src/provider-webdriver.ts`. Mostly already thin: the bulk of
943926
WebDriver and Limrun provider logic lives in `packages/provider-webdriver/src/` and

packages/capture-kit/package.json

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
"types": "./src/index.ts",
1515
"default": "./src/index.ts"
1616
},
17+
"./android-replacement-surface-occlusion": {
18+
"types": "./src/snapshot/android-replacement-surface-occlusion.ts",
19+
"default": "./src/snapshot/android-replacement-surface-occlusion.ts"
20+
},
1721
"./durable-capture": {
1822
"types": "./src/durable-capture/index.ts",
1923
"default": "./src/durable-capture/index.ts"
@@ -34,6 +38,10 @@
3438
"types": "./src/ios-snapshot-planning.ts",
3539
"default": "./src/ios-snapshot-planning.ts"
3640
},
41+
"./ios-snapshot-runtime": {
42+
"types": "./src/snapshot/ios-snapshot-runtime.ts",
43+
"default": "./src/snapshot/ios-snapshot-runtime.ts"
44+
},
3745
"./mobile-snapshot-semantics": {
3846
"types": "./src/mobile-snapshot-semantics.ts",
3947
"default": "./src/mobile-snapshot-semantics.ts"
@@ -66,10 +74,34 @@
6674
"types": "./src/post-gesture-stability.ts",
6775
"default": "./src/post-gesture-stability.ts"
6876
},
77+
"./quality-warnings": {
78+
"types": "./src/snapshot/snapshot-presentation/quality-warnings.ts",
79+
"default": "./src/snapshot/snapshot-presentation/quality-warnings.ts"
80+
},
6981
"./react-native-overlay": {
7082
"types": "./src/react-native-overlay.ts",
7183
"default": "./src/react-native-overlay.ts"
7284
},
85+
"./recording-output-path": {
86+
"types": "./src/recording/output-path.ts",
87+
"default": "./src/recording/output-path.ts"
88+
},
89+
"./recording-overlay": {
90+
"types": "./src/recording/overlay.ts",
91+
"default": "./src/recording/overlay.ts"
92+
},
93+
"./recording-telemetry": {
94+
"types": "./src/recording/telemetry.ts",
95+
"default": "./src/recording/telemetry.ts"
96+
},
97+
"./recording-video": {
98+
"types": "./src/recording/video.ts",
99+
"default": "./src/recording/video.ts"
100+
},
101+
"./repeated-nav-subtree": {
102+
"types": "./src/snapshot/snapshot-presentation/repeated-nav-subtree.ts",
103+
"default": "./src/snapshot/snapshot-presentation/repeated-nav-subtree.ts"
104+
},
73105
"./screenshot-density": {
74106
"types": "./src/screenshot-density.ts",
75107
"default": "./src/screenshot-density.ts"
@@ -82,14 +114,58 @@
82114
"types": "./src/screenshot-overlay.ts",
83115
"default": "./src/screenshot-overlay.ts"
84116
},
117+
"./scroll-edge-state": {
118+
"types": "./src/snapshot/scroll-edge-state.ts",
119+
"default": "./src/snapshot/scroll-edge-state.ts"
120+
},
121+
"./snapshot-chrome": {
122+
"types": "./src/snapshot-chrome.ts",
123+
"default": "./src/snapshot-chrome.ts"
124+
},
85125
"./snapshot-desktop-projection": {
86126
"types": "./src/snapshot-desktop-projection.ts",
87127
"default": "./src/snapshot-desktop-projection.ts"
88128
},
129+
"./snapshot-desktop-surface": {
130+
"types": "./src/snapshot/snapshot-desktop-surface.ts",
131+
"default": "./src/snapshot/snapshot-desktop-surface.ts"
132+
},
133+
"./snapshot-diff": {
134+
"types": "./src/snapshot/snapshot-diff.ts",
135+
"default": "./src/snapshot/snapshot-diff.ts"
136+
},
137+
"./snapshot-evidence": {
138+
"types": "./src/snapshot/snapshot-evidence.ts",
139+
"default": "./src/snapshot/snapshot-evidence.ts"
140+
},
141+
"./snapshot-freshness": {
142+
"types": "./src/snapshot/snapshot-freshness/index.ts",
143+
"default": "./src/snapshot/snapshot-freshness/index.ts"
144+
},
145+
"./snapshot-label-dedup": {
146+
"types": "./src/snapshot/snapshot-label-dedup.ts",
147+
"default": "./src/snapshot/snapshot-label-dedup.ts"
148+
},
149+
"./snapshot-lines": {
150+
"types": "./src/snapshot/snapshot-lines.ts",
151+
"default": "./src/snapshot/snapshot-lines.ts"
152+
},
153+
"./snapshot-node-lookup": {
154+
"types": "./src/snapshot-node-lookup.ts",
155+
"default": "./src/snapshot-node-lookup.ts"
156+
},
89157
"./snapshot-occlusion": {
90158
"types": "./src/snapshot-occlusion.ts",
91159
"default": "./src/snapshot-occlusion.ts"
92160
},
161+
"./snapshot-presentation-android-helper": {
162+
"types": "./src/snapshot/snapshot-presentation/android/helper.ts",
163+
"default": "./src/snapshot/snapshot-presentation/android/helper.ts"
164+
},
165+
"./snapshot-presentation-ios-transitions-fixtures": {
166+
"types": "./src/snapshot/snapshot-presentation/ios/transitions.fixtures.ts",
167+
"default": "./src/snapshot/snapshot-presentation/ios/transitions.fixtures.ts"
168+
},
93169
"./snapshot-quality-backend-capabilities": {
94170
"types": "./src/snapshot-quality-backend-capabilities.ts",
95171
"default": "./src/snapshot-quality-backend-capabilities.ts"
@@ -101,6 +177,22 @@
101177
"./snapshot-rect-projection": {
102178
"types": "./src/snapshot-rect-projection.ts",
103179
"default": "./src/snapshot-rect-projection.ts"
180+
},
181+
"./snapshot-state": {
182+
"types": "./src/snapshot-state.ts",
183+
"default": "./src/snapshot-state.ts"
184+
},
185+
"./snapshot-timeout-policy": {
186+
"types": "./src/snapshot/snapshot-timeout-policy.ts",
187+
"default": "./src/snapshot/snapshot-timeout-policy.ts"
188+
},
189+
"./snapshot-visibility": {
190+
"types": "./src/snapshot/snapshot-visibility.ts",
191+
"default": "./src/snapshot/snapshot-visibility.ts"
192+
},
193+
"./text-surface": {
194+
"types": "./src/snapshot/snapshot-presentation/text-surface.ts",
195+
"default": "./src/snapshot/snapshot-presentation/text-surface.ts"
104196
}
105197
},
106198
"devDependencies": {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function likelyPlayableWebmContainer(): Buffer {
2+
// One 16x16 VP8 keyframe generated by ffmpeg. Unlike a marker-only synthetic fixture,
3+
// ffprobe identifies this as a WebM video stream with a 40ms duration.
4+
return Buffer.from(
5+
'GkXfo59ChoEBQveBAULygQRC84EIQoKEd2VibUKHgQJChYECGFOAZwEAAAAAAAHpEU2bdLpNu4tTq4QVSalmU6yBoU27i1OrhBZUrmtTrIHYTbuMU6uEElTDZ1OsggElTbuMU6uEHFO7a1OsggHT7AEAAAAAAABZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmsirXsYMPQkBNgI1MYXZmNjIuMTIuMTAxV0GNTGF2ZjYyLjEyLjEwMUSJiEBEAAAAAAAAFlSua8iuAQAAAAAAAD/XgQFzxYgNIomR4viG6pyBACK1nIN1bmSIgQCGhVZfVlA4g4EBI+ODhAJiWgDgkLCBELqBEJqBAlWwhFW5gQESVMNn/HNzoGPAgGfImkWjh0VOQ09ERVJEh41MYXZmNjIuMTIuMTAxc3PWY8CLY8WIDSKJkeL4hupnyKFFo4dFTkNPREVSRIeUTGF2YzYyLjI4LjEwMSBsaWJ2cHhnyKFFo4hEVVJBVElPTkSHkzAwOjAwOjAwLjA0MDAwMDAwMAAfQ7Z1qOeBAKOjgQAAgBACAJ0BKhAAEAAARwiFhYiFhIgCAgAMDWAA/v+rUIAcU7trkbuPs4EAt4r3gQHxggGm8IED',
6+
'base64',
7+
);
8+
}

packages/capture-kit/src/recording/__tests__/overlay.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
22
import fs from 'node:fs';
33
import path from 'node:path';
4-
import { mkdtempForTestSync } from '../../__tests__/test-utils/tmp-dir.ts';
4+
import { mkdtempForTestSync } from '../../tmp-dir.fixtures.ts';
55

66
vi.mock('@agent-device/host-kit/command', async (importOriginal) => {
77
const fs = await import('node:fs');

packages/capture-kit/src/recording/__tests__/recording-scripts.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import { getRecordingOverlaySupportWarning } from '../overlay.ts';
88
const __dirname = path.dirname(fileURLToPath(import.meta.url));
99
const recordingScriptsDir = path.resolve(
1010
__dirname,
11-
'../../../apple/runner/AgentDeviceRunner/RecordingScripts',
11+
'../../../../../apple/runner/AgentDeviceRunner/RecordingScripts',
1212
);
13-
const recordingTestSupportDir = path.resolve(__dirname, '../../../test/integration/support');
13+
const recordingTestSupportDir = path.resolve(__dirname, '../../../../../test/integration/support');
1414
const SWIFT_TYPECHECK_TIMEOUT_MS = 60_000;
1515
let swiftCompilerPath = 'swiftc';
1616
let swiftSdkPath = '';

packages/capture-kit/src/recording/swift-cache.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { afterEach, beforeEach, expect, test, vi } from 'vitest';
22
import fs from 'node:fs';
33
import path from 'node:path';
4-
import { mkdtempForTestSync } from '../__tests__/test-utils/tmp-dir.ts';
4+
import { mkdtempForTestSync } from '../tmp-dir.fixtures.ts';
55

66
vi.mock(import('@agent-device/host-kit/command'), async (importOriginal) => ({
77
...(await importOriginal()),

packages/capture-kit/src/recording/video-webm.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'node:fs';
22
import path from 'node:path';
33
import { expect, test } from 'vitest';
44
import { likelyPlayableWebmContainer } from '../__tests__/test-utils/video-fixtures.ts';
5-
import { mkdtempForTestSync } from '../__tests__/test-utils/tmp-dir.ts';
5+
import { mkdtempForTestSync } from '../tmp-dir.fixtures.ts';
66
import { hasPlayableWebmStructure } from './video-webm.ts';
77

88
const directory = mkdtempForTestSync('agent-device-video-webm-structure-');

packages/capture-kit/src/recording/video.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'node:fs';
22
import path from 'node:path';
33
import { expect, test } from 'vitest';
44
import { likelyPlayableWebmContainer } from '../__tests__/test-utils/video-fixtures.ts';
5-
import { mkdtempForTestSync } from '../__tests__/test-utils/tmp-dir.ts';
5+
import { mkdtempForTestSync } from '../tmp-dir.fixtures.ts';
66
import { isPlayableVideo } from './video.ts';
77

88
const directory = mkdtempForTestSync('agent-device-video-webm-');

packages/capture-kit/src/snapshot-chrome.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { test } from 'vitest';
22
import assert from 'node:assert/strict';
33
import { attachRefs, type RawSnapshotNode, type SnapshotNode } from '@agent-device/kernel/snapshot';
4-
import { collectSettleChromeRefs } from '../snapshot-chrome.ts';
4+
import { collectSettleChromeRefs } from './snapshot-chrome.ts';
55

66
function refFor(nodes: SnapshotNode[], label: string): string {
77
const node = nodes.find((candidate) => candidate.label === label);

packages/capture-kit/src/snapshot-node-lookup.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import assert from 'node:assert/strict';
22
import { test } from 'vitest';
33
import { attachRefs } from '@agent-device/kernel/snapshot';
4-
import { findNodeByLabel, resolveRefLabel } from '../snapshot-node-lookup.ts';
4+
import { findNodeByLabel, resolveRefLabel } from './snapshot-node-lookup.ts';
55

66
test('findNodeByLabel matches label, value, and identifier case-insensitively', () => {
77
const nodes = attachRefs([

0 commit comments

Comments
 (0)