Files
callstack__agent-device/scripts/layering/snapshot-presentation-boundary.test.ts
Michał Pierzchała 1f9d940bff 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
2026-09-08 12:41:39 +02:00

64 lines
2.5 KiB
TypeScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import path from 'node:path';
import { test } from 'node:test';
import { ARCHITECTURE_OWNERSHIP, matchesDeclaredRoot } from './architecture-ownership.ts';
import { resolveImportEdges } from './model.ts';
import { workspaceSpecifierTargets } from './package-boundaries.ts';
import { listTrackedTypeScriptFiles } from './tracked-sources.ts';
const repoRoot = path.resolve(import.meta.dirname, '../..');
/**
* The `snapshot-policy` declaration owns presentation, freshness, timeout and overlay policy;
* `src/daemon/` owns the assembly that orders them (#1983, ADR 0004). The dependency runs one way
* only, so a policy stays testable without standing up a session.
*
* The real tree is clean, which is exactly why the positive control below exists: a filter that
* stopped matching would look identical to a boundary being obeyed.
*/
function daemonImportsFromSnapshotFacet(
sources: ReadonlyMap<string, string>,
workspaceTargets?: ReadonlyMap<string, string>,
): string[] {
const snapshotPolicy = ARCHITECTURE_OWNERSHIP.executablePolicies.find(
({ name }) => name === 'snapshot-policy',
);
if (!snapshotPolicy) throw new Error('snapshot-policy ownership declaration is missing');
return resolveImportEdges(sources, workspaceTargets)
.filter(
(edge) =>
snapshotPolicy.roots.some((root) => matchesDeclaredRoot(edge.file, root)) &&
snapshotPolicy.forbiddenTargetRoots.some((root) => matchesDeclaredRoot(edge.target, root)),
)
.map((edge) => `${edge.file}:${edge.line} -> ${edge.target}`);
}
test('the snapshot facet cannot import daemon assembly', () => {
const files = listTrackedTypeScriptFiles(repoRoot);
const sources = new Map(
files.map((file) => [file, fs.readFileSync(path.join(repoRoot, file), 'utf8')]),
);
assert.deepEqual(
daemonImportsFromSnapshotFacet(sources, workspaceSpecifierTargets(repoRoot)),
[],
'the host-side snapshot facet must not depend on daemon assembly',
);
});
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'],
[
'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), [
'packages/capture-kit/src/snapshot/snapshot-freshness/android.ts:1 -> src/daemon/types.ts',
]);
});