Skip to content

Commit c4bd9df

Browse files
committed
chore(gates): forbid platform and provider imports in the snapshot router
Declare the snapshot-router executable policy with every platform, provider, apple-runner and tv-cdp package as a forbidden target. Pin it with a real-tree check, a coverage check over the platform-* and provider-* packages, and a positive control for static and dynamic imports. Pin the two new capture-kit exports in the R11 manifest check.
1 parent 9793a47 commit c4bd9df

3 files changed

Lines changed: 109 additions & 0 deletions

File tree

‎scripts/layering/architecture-ownership.ts‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,27 @@ export const ARCHITECTURE_OWNERSHIP = {
282282
roots: ['packages/capture-kit/src/snapshot/'],
283283
forbiddenTargetRoots: [DAEMON_SOURCE_ROOT],
284284
},
285+
{
286+
// ADR 0038: the snapshot source router depends on no platform or provider code.
287+
name: 'snapshot-router',
288+
kind: 'executable-policy',
289+
roots: ['packages/capture-kit/src/snapshot-router/'],
290+
forbiddenTargetRoots: [
291+
'packages/apple-runner/',
292+
'packages/platform-android/',
293+
'packages/platform-apple/',
294+
'packages/platform-harmonyos/',
295+
'packages/platform-linux/',
296+
'packages/platform-vega/',
297+
'packages/platform-web/',
298+
'packages/provider-limrun/',
299+
'packages/provider-revyl/',
300+
'packages/provider-testmu/',
301+
'packages/provider-webdriver/',
302+
'packages/provider-webos/',
303+
'packages/tv-cdp/',
304+
],
305+
},
285306
],
286307
} as const;
287308

‎scripts/layering/package-boundaries.test.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ test('the real tree parses, declares, and passes R11', () => {
554554
'@agent-device/capture-kit/snapshot-quality-backend-capabilities',
555555
'@agent-device/capture-kit/snapshot-quality-verdict',
556556
'@agent-device/capture-kit/snapshot-rect-projection',
557+
'@agent-device/capture-kit/snapshot-router',
558+
'@agent-device/capture-kit/snapshot-source-channel',
557559
'@agent-device/capture-kit/snapshot-state',
558560
'@agent-device/capture-kit/snapshot-state-fixtures',
559561
'@agent-device/capture-kit/snapshot-timeout-policy',
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import assert from 'node:assert/strict';
2+
import fs from 'node:fs';
3+
import path from 'node:path';
4+
import { test } from 'node:test';
5+
import { ARCHITECTURE_OWNERSHIP, matchesDeclaredRoot } from './architecture-ownership.ts';
6+
import { resolveImportEdges } from './model.ts';
7+
import { workspaceSpecifierTargets } from './package-boundaries.ts';
8+
import { listTrackedTypeScriptFiles } from './tracked-sources.ts';
9+
10+
const repoRoot = path.resolve(import.meta.dirname, '../..');
11+
12+
/**
13+
* ADR 0038: the snapshot source router in `packages/capture-kit/src/snapshot-router/` is platform
14+
* neutral. A platform or provider package declares its channels and binds them to the router; the
15+
* router never imports one back. The positive controls below exist because a clean tree looks the
16+
* same as a filter that stopped matching.
17+
*/
18+
function routerPolicy() {
19+
const policy = ARCHITECTURE_OWNERSHIP.executablePolicies.find(
20+
({ name }) => name === 'snapshot-router',
21+
);
22+
if (!policy) throw new Error('snapshot-router ownership declaration is missing');
23+
return policy;
24+
}
25+
26+
function platformImportsFromRouter(
27+
sources: ReadonlyMap<string, string>,
28+
workspaceTargets?: ReadonlyMap<string, string>,
29+
): string[] {
30+
const policy = routerPolicy();
31+
return resolveImportEdges(sources, workspaceTargets)
32+
.filter(
33+
(edge) =>
34+
policy.roots.some((root) => matchesDeclaredRoot(edge.file, root)) &&
35+
policy.forbiddenTargetRoots.some((root) => matchesDeclaredRoot(edge.target, root)),
36+
)
37+
.map((edge) => `${edge.file}:${edge.line} -> ${edge.target}`);
38+
}
39+
40+
test('the snapshot router imports no platform or provider package', () => {
41+
const files = listTrackedTypeScriptFiles(repoRoot);
42+
const sources = new Map(
43+
files.map((file) => [file, fs.readFileSync(path.join(repoRoot, file), 'utf8')]),
44+
);
45+
46+
assert.deepEqual(platformImportsFromRouter(sources, workspaceSpecifierTargets(repoRoot)), []);
47+
});
48+
49+
test('every platform and provider package is a forbidden router target', () => {
50+
const packages = fs
51+
.readdirSync(path.join(repoRoot, 'packages'))
52+
.filter((name) => /^(platform|provider)-/.test(name))
53+
.map((name) => `packages/${name}/`);
54+
55+
assert.ok(packages.length > 0, 'expected platform and provider packages');
56+
for (const root of packages) {
57+
assert.ok(routerPolicy().forbiddenTargetRoots.includes(root), `${root} is not forbidden`);
58+
}
59+
});
60+
61+
test('the boundary reports a router module that imports a platform or provider package', () => {
62+
const sources = new Map([
63+
['packages/platform-apple/src/snapshot-target.ts', 'export const resolve = 1;\n'],
64+
['packages/provider-limrun/src/index.ts', 'export const limrun = 1;\n'],
65+
[
66+
'packages/capture-kit/src/snapshot-router/router.ts',
67+
[
68+
"import { resolve } from '@agent-device/platform-apple/snapshot-target';",
69+
"const { limrun } = await import('../../../provider-limrun/src/index.ts');",
70+
'export const x = [resolve, limrun];',
71+
'',
72+
].join('\n'),
73+
],
74+
]);
75+
const workspaceTargets = new Map([
76+
[
77+
'@agent-device/platform-apple/snapshot-target',
78+
'packages/platform-apple/src/snapshot-target.ts',
79+
],
80+
]);
81+
82+
assert.deepEqual(platformImportsFromRouter(sources, workspaceTargets), [
83+
'packages/capture-kit/src/snapshot-router/router.ts:1 -> packages/platform-apple/src/snapshot-target.ts',
84+
'packages/capture-kit/src/snapshot-router/router.ts:2 -> packages/provider-limrun/src/index.ts',
85+
]);
86+
});

0 commit comments

Comments
 (0)