@@ -21,6 +21,7 @@ import {
2121 specifierSites ,
2222 type WorkspacePackage ,
2323} from './package-boundaries.ts' ;
24+ import { listTrackedTypeScriptFiles } from './tracked-sources.ts' ;
2425
2526const repoRoot = path . resolve ( import . meta. dirname , '../..' ) ;
2627
@@ -46,130 +47,36 @@ const contracts: WorkspacePackage = {
4647} ;
4748
4849const ALL = [ kernel , contracts ] ;
49- const CONTRACT_EXPORTS = [
50- '@agent-device/contracts/alert-contract' ,
51- '@agent-device/contracts/alert-runtime' ,
52- '@agent-device/contracts/android-clipboard-support' ,
53- '@agent-device/contracts/android-helper-artifacts' ,
54- '@agent-device/contracts/android-input-ownership' ,
55- '@agent-device/contracts/android-observation' ,
56- '@agent-device/contracts/android-snapshot-quality' ,
57- '@agent-device/contracts/android-system-chrome' ,
58- '@agent-device/contracts/android-touch-plan' ,
59- '@agent-device/contracts/app-deployment-runtime' ,
60- '@agent-device/contracts/app-deployment-runtime-plan' ,
61- '@agent-device/contracts/app-event-runtime' ,
62- '@agent-device/contracts/app-inventory-runtime' ,
63- '@agent-device/contracts/app-log-runtime' ,
64- '@agent-device/contracts/app-state-runtime' ,
65- '@agent-device/contracts/app-switcher-runtime' ,
66- '@agent-device/contracts/apple-multitouch-support' ,
67- '@agent-device/contracts/apple-runner-request' ,
68- '@agent-device/contracts/application-lifecycle-interaction' ,
69- '@agent-device/contracts/application-lifecycle-runtime' ,
70- '@agent-device/contracts/application-lifecycle-runtime-plan' ,
71- '@agent-device/contracts/async-lifecycle' ,
72- '@agent-device/contracts/audio-probe-result' ,
73- '@agent-device/contracts/audio-probe-runtime' ,
74- '@agent-device/contracts/audio-probe-runtime-host' ,
75- '@agent-device/contracts/audio-probe-support' ,
76- '@agent-device/contracts/audio-runtime-plan' ,
77- '@agent-device/contracts/back-mode' ,
78- '@agent-device/contracts/backend-diagnostics' ,
79- '@agent-device/contracts/back-runtime' ,
80- '@agent-device/contracts/boot-failure' ,
81- '@agent-device/contracts/capture' ,
82- '@agent-device/contracts/click-button' ,
83- '@agent-device/contracts/client' ,
84- '@agent-device/contracts/clipboard' ,
85- '@agent-device/contracts/clipboard-runtime' ,
86- '@agent-device/contracts/command' ,
87- '@agent-device/contracts/command-platform-execution' ,
88- '@agent-device/contracts/device' ,
89- '@agent-device/contracts/device-readiness-runtime' ,
90- '@agent-device/contracts/device-shutdown-runtime' ,
91- '@agent-device/contracts/divergence' ,
92- '@agent-device/contracts/durable-resource' ,
93- '@agent-device/contracts/durable-resource-envelope' ,
94- '@agent-device/contracts/element-text-runtime' ,
95- '@agent-device/contracts/focus-runtime' ,
96- '@agent-device/contracts/gesture-admission' ,
97- '@agent-device/contracts/gesture-input' ,
98- '@agent-device/contracts/gesture-normalization' ,
99- '@agent-device/contracts/gesture-plan' ,
100- '@agent-device/contracts/gesture-plan-types' ,
101- '@agent-device/contracts/gesture-runtime' ,
102- '@agent-device/contracts/home-runtime' ,
103- '@agent-device/contracts/host-diagnostics' ,
104- '@agent-device/contracts/daemon-owner-cleanup' ,
105- '@agent-device/contracts/interaction' ,
106- '@agent-device/contracts/interaction-error' ,
107- '@agent-device/contracts/interaction-guarantees' ,
108- '@agent-device/contracts/interactor-operation-catalog' ,
109- '@agent-device/contracts/interactor-types' ,
110- '@agent-device/contracts/ios-snapshot' ,
111- '@agent-device/contracts/is-predicate' ,
112- '@agent-device/contracts/keyboard' ,
113- '@agent-device/contracts/keyboard-runtime' ,
114- '@agent-device/contracts/local-interactor-operation-set' ,
115- '@agent-device/contracts/logs-runtime-plan' ,
116- '@agent-device/contracts/managed-device-allocation' ,
117- '@agent-device/contracts/managed-web-backend' ,
118- '@agent-device/contracts/navigation' ,
119- '@agent-device/contracts/network-runtime' ,
120- '@agent-device/contracts/network-runtime-plan' ,
121- '@agent-device/contracts/network-traffic' ,
122- '@agent-device/contracts/observability' ,
123- '@agent-device/contracts/orientation-runtime' ,
124- '@agent-device/contracts/perf-runtime' ,
125- '@agent-device/contracts/perf-runtime-host' ,
126- '@agent-device/contracts/perf-runtime-operation-builder' ,
127- '@agent-device/contracts/perf-runtime-plan' ,
128- '@agent-device/contracts/platform-module' ,
129- '@agent-device/contracts/platform-plugin' ,
130- '@agent-device/contracts/platform-providers' ,
131- '@agent-device/contracts/platform-resource-cleanup' ,
132- '@agent-device/contracts/platform-runtime' ,
133- '@agent-device/contracts/platform-runtime-host' ,
134- '@agent-device/contracts/platform-runtime-operations' ,
135- '@agent-device/contracts/platform-runtime-unavailable' ,
136- '@agent-device/contracts/progress' ,
137- '@agent-device/contracts/record-runtime-execution' ,
138- '@agent-device/contracts/recording' ,
139- '@agent-device/contracts/remote' ,
140- '@agent-device/contracts/replay' ,
141- '@agent-device/contracts/react-native-overlay' ,
142- '@agent-device/contracts/runner-lease-context' ,
143- '@agent-device/contracts/screen-recording-runtime' ,
144- '@agent-device/contracts/screen-recording-runtime-host' ,
145- '@agent-device/contracts/screen-recording-runtime-plan' ,
146- '@agent-device/contracts/screenshot-runtime' ,
147- '@agent-device/contracts/scroll-command' ,
148- '@agent-device/contracts/scroll-gesture' ,
149- '@agent-device/contracts/scroll-runtime' ,
150- '@agent-device/contracts/selector-observation-runtime' ,
151- '@agent-device/contracts/session' ,
152- '@agent-device/contracts/settings' ,
153- '@agent-device/contracts/settings-runtime' ,
154- '@agent-device/contracts/snapshot' ,
155- '@agent-device/contracts/snapshot-presentation' ,
156- '@agent-device/contracts/snapshot-runtime' ,
157- '@agent-device/contracts/snapshot-scope' ,
158- '@agent-device/contracts/snapshot-timeout-evidence' ,
159- '@agent-device/contracts/startup-recovery-fence' ,
160- '@agent-device/contracts/touch-runtime' ,
161- '@agent-device/contracts/tv-remote' ,
162- '@agent-device/contracts/tv-remote-runtime' ,
163- '@agent-device/contracts/type-text-runtime' ,
164- '@agent-device/contracts/viewport-runtime' ,
165- '@agent-device/contracts/wait' ,
166- '@agent-device/contracts/wait-runtime-plan' ,
167- ] as const ;
16850
16951function rules ( violations : { rule : string } [ ] ) : string [ ] {
17052 return violations . map ( ( violation ) => violation . rule ) ;
17153}
17254
55+ /**
56+ * The manifest is its own inventory: every `exports` target must resolve to an existing,
57+ * TRACKED source file, and every manifest entry must have produced exactly one `exportTargets`
58+ * entry (nothing dropped, nothing collapsed by a duplicate key). This replaces a ~120-line pinned
59+ * subpath list that every `packages/contracts/package.json` change also had to hand-edit; the
60+ * manifest is now the only place the export surface is declared.
61+ */
62+ function assertExportTargetsMatchManifest ( pkg : WorkspacePackage , manifestFile : string ) : void {
63+ const manifest = JSON . parse ( fs . readFileSync ( path . join ( repoRoot , manifestFile ) , 'utf8' ) ) as {
64+ exports ?: Record < string , unknown > ;
65+ } ;
66+ const trackedSources = new Set ( listTrackedTypeScriptFiles ( repoRoot ) ) ;
67+ for ( const [ specifier , target ] of pkg . exportTargets ) {
68+ assert . ok (
69+ trackedSources . has ( target ) && fs . existsSync ( path . join ( repoRoot , target ) ) ,
70+ `${ specifier } -> ${ target } must resolve to an existing, tracked file` ,
71+ ) ;
72+ }
73+ assert . equal (
74+ pkg . exportTargets . size ,
75+ Object . keys ( manifest . exports ?? { } ) . length ,
76+ `${ pkg . name } exports map entries must each produce one resolved export target` ,
77+ ) ;
78+ }
79+
17380test ( 'specifier sites carry 1-based lines for static and dynamic imports' , ( ) => {
17481 const sites = specifierSites (
17582 'src/a.ts' ,
@@ -451,7 +358,7 @@ test('the real tree parses, declares, and passes R11', () => {
451358 assert . ok ( kernelPackage . exportTargets . size >= 8 , 'kernel exports its vocabulary subpaths' ) ;
452359 const contractsPackage = packages . find ( ( pkg ) => pkg . name === '@agent-device/contracts' ) ;
453360 assert . ok ( contractsPackage , 'contracts package must exist' ) ;
454- assert . deepEqual ( [ ... contractsPackage . exportTargets . keys ( ) ] . sort ( ) , [ ... CONTRACT_EXPORTS ] . sort ( ) ) ;
361+ assertExportTargetsMatchManifest ( contractsPackage , 'packages/contracts/package.json' ) ;
455362 assert . deepEqual ( [ ...contractsPackage . workspaceDependencies ] , [ '@agent-device/kernel' ] ) ;
456363 const captureKitPackage = packages . find ( ( pkg ) => pkg . name === '@agent-device/capture-kit' ) ;
457364 assert . ok ( captureKitPackage , 'capture-kit package must exist' ) ;
0 commit comments