Skip to content

Commit bf67324

Browse files
committed
refactor(layering): fold the four cutover policies into one parametrized gate
ADR 0019 §8: the per-command cutover gates consolidate into one parametrized runtime-command-cutover gate driven by a table of migrated commands. Adding a migrated command adds a row; the mechanism carries one planted-red proof instead of one per command. Part of #1739 (wave 0)
1 parent 4c1c429 commit bf67324

21 files changed

Lines changed: 1921 additions & 1843 deletions

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@
130130
"check:affected:test": "node --experimental-strip-types scripts/node-test-tmpdir.ts --experimental-strip-types --test scripts/check-affected/model.test.ts scripts/check-affected/platform-packages.test.ts scripts/check-affected/run.test.ts",
131131
"check:coverage-changed": "node --experimental-strip-types scripts/coverage-changed/run.ts",
132132
"check:coverage-changed:test": "node --experimental-strip-types scripts/node-test-tmpdir.ts --experimental-strip-types --test scripts/coverage-changed/model.test.ts scripts/coverage-changed/run.test.ts",
133-
"check:layering": "node --experimental-strip-types scripts/node-test-tmpdir.ts --experimental-strip-types --test scripts/layering/model.test.ts scripts/layering/zone-policy.test.ts scripts/layering/daemon-modularity.test.ts scripts/layering/package-boundaries.test.ts scripts/layering/platform-package-policy.test.ts scripts/layering/platform-package-repository.test.ts scripts/layering/platform-package-source-policy.test.ts scripts/layering/device-inventory-cutover-policy.test.ts scripts/layering/logs-runtime-cutover-policy.test.ts scripts/layering/network-runtime-cutover-policy.test.ts scripts/layering/record-runtime-cutover-policy.test.ts scripts/layering/contracts-implementation-policy.test.ts scripts/layering/facade-exports.test.ts scripts/layering/bin-alias-fast-path.test.ts && node --experimental-strip-types scripts/layering/check.ts",
133+
"check:layering": "node --experimental-strip-types scripts/node-test-tmpdir.ts --experimental-strip-types --test scripts/layering/model.test.ts scripts/layering/zone-policy.test.ts scripts/layering/daemon-modularity.test.ts scripts/layering/package-boundaries.test.ts scripts/layering/platform-package-policy.test.ts scripts/layering/platform-package-repository.test.ts scripts/layering/platform-package-source-policy.test.ts scripts/layering/runtime-command-cutover-policy.test.ts scripts/layering/runtime-command-cutover-table.test.ts scripts/layering/runtime-command-cutover-extensions.test.ts scripts/layering/contracts-implementation-policy.test.ts scripts/layering/facade-exports.test.ts scripts/layering/bin-alias-fast-path.test.ts && node --experimental-strip-types scripts/layering/check.ts",
134134
"depgraph": "node --experimental-strip-types scripts/depgraph/build.ts",
135135
"depgraph:test": "node --experimental-strip-types scripts/node-test-tmpdir.ts --experimental-strip-types --test scripts/depgraph/model.test.ts scripts/depgraph/affected.test.ts",
136136
"check:production-exports": "fallow dead-code --config fallow-production-exports.json --production --unused-exports --fail-on-issues",

scripts/layering/check.ts

Lines changed: 17 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@
3333
// owner" shape as R7's SessionState ownership, applied to bin.ts's `--help` fast path.
3434
// - Over PLATFORM PACKAGE COMPOSITION: six private metadata façades meet at the exact root
3535
// composition file; premature implementation loading and forbidden cross-boundary edges fail (R13).
36-
// - Over the DEVICES COMMAND CUTOVER: the handler calls the neutral inventory gateway and no
37-
// superseded inventory module, import, or identifier remains in production (R13).
38-
// - Over COMMAND-ATOMIC RUNTIME CUTOVERS: retired logs, network, and record routes/admission cannot
39-
// coexist with their operation-fact-derived descriptor and handler paths (R14-R16).
36+
// - Over COMMAND-ATOMIC RUNTIME CUTOVERS: one parametrized gate reads the migrated-command
37+
// table (devices R13, logs R14, network R15, record R16) and proves each command keeps
38+
// exactly one platform-execution path — retired routes, admission, modules, and widened
39+
// runtime access cannot coexist with its operation-fact-derived descriptor and handler.
4040
// Only `(root)` is unranked among src/ zones (see `UNRANKED_ZONES` in model.ts):
4141
// it holds entrypoints and composition roots. Extracted workspace package zones
4242
// are classified separately and held behind R11 instead of the src folder spine.
@@ -87,32 +87,15 @@ import {
8787
platformPackagePolicySummary,
8888
} from './platform-package-policy.ts';
8989
import {
90-
checkDeviceInventoryCutover,
91-
deviceInventoryCutoverSummary,
92-
} from './device-inventory-cutover-policy.ts';
90+
checkRuntimeCommandCutover,
91+
runtimeCommandCutoverSummary,
92+
} from './runtime-command-cutover-policy.ts';
9393
import {
9494
listUntrackedProductionTypeScriptFiles,
9595
readTrackedPlatformPackageDeclarations,
9696
} from './platform-package-repository.ts';
9797
import { policyLead, policyViolation, ZONE_POLICIES } from './zone-policy.ts';
98-
import {
99-
logsLegacyRouteViolations,
100-
logsRuntimeNarrowingViolations,
101-
logsSessionStateOwnershipViolations,
102-
sourceExecutedUsingDeclarationViolations,
103-
} from './logs-runtime-cutover-policy.ts';
10498
import { contractsImplementationAuthorityViolations } from './contracts-implementation-policy.ts';
105-
import {
106-
networkLegacyRouteViolations,
107-
networkRuntimeNarrowingViolations,
108-
networkRuntimeRouteViolations,
109-
} from './network-runtime-cutover-policy.ts';
110-
import {
111-
recordLegacyRouteViolations,
112-
recordRuntimeNarrowingViolations,
113-
recordRuntimeRouteViolations,
114-
} from './record-runtime-cutover-policy.ts';
115-
import { recordRuntimeDaemonMechanicsViolations } from './record-runtime-mechanics-policy.ts';
11699
import { recordRuntimeRegistryJoinViolations } from './record-runtime-registry-policy.ts';
117100

118101
const repoRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], {
@@ -191,16 +174,6 @@ function checkCycles(edges: readonly ResolvedImportEdge[]): LayeringViolation[]
191174
}));
192175
}
193176

194-
function checkLogsRuntimeCutover(sources: ReadonlyMap<string, string>): LayeringViolation[] {
195-
const production = [...sources].map(([file, source]) => ({ path: file, source }));
196-
return [
197-
...logsLegacyRouteViolations(production),
198-
...logsRuntimeNarrowingViolations(production),
199-
...logsSessionStateOwnershipViolations(production),
200-
...sourceExecutedUsingDeclarationViolations(production),
201-
];
202-
}
203-
204177
function checkContractsImplementationAuthority(
205178
sources: ReadonlyMap<string, string>,
206179
): LayeringViolation[] {
@@ -209,32 +182,14 @@ function checkContractsImplementationAuthority(
209182
);
210183
}
211184

212-
function checkNetworkRuntimeCutover(sources: ReadonlyMap<string, string>): LayeringViolation[] {
213-
const production = [...sources].map(([file, source]) => ({ path: file, source }));
214-
return [
215-
...networkLegacyRouteViolations(production),
216-
...networkRuntimeNarrowingViolations(production),
217-
...networkRuntimeRouteViolations(production),
218-
].map((violation) => {
219-
const separator = violation.indexOf(': ');
220-
return {
221-
rule: 'R15 network-runtime-cutover',
222-
file: separator < 0 ? '(network runtime)' : violation.slice(0, separator),
223-
line: 1,
224-
message: separator < 0 ? violation : violation.slice(separator + 2),
225-
};
226-
});
227-
}
228-
229-
function checkRecordRuntimeCutover(sources: ReadonlyMap<string, string>): LayeringViolation[] {
185+
/**
186+
* The record registry-join scan is a descriptor-shape check, not a cutover claim, so it
187+
* stays its own module. Record's daemon-mechanics scan is the row's lifecycle proof and
188+
* runs from the cutover table. Both report under R16.
189+
*/
190+
function checkRecordRuntimeRegistryJoin(sources: ReadonlyMap<string, string>): LayeringViolation[] {
230191
const production = [...sources].map(([file, source]) => ({ path: file, source }));
231-
return [
232-
...recordLegacyRouteViolations(production),
233-
...recordRuntimeDaemonMechanicsViolations(production),
234-
...recordRuntimeNarrowingViolations(production),
235-
...recordRuntimeRegistryJoinViolations(production),
236-
...recordRuntimeRouteViolations(production),
237-
].map((violation) => {
192+
return recordRuntimeRegistryJoinViolations(production).map((violation) => {
238193
const separator = violation.indexOf(': ');
239194
return {
240195
rule: 'R16 record-runtime-cutover',
@@ -618,7 +573,7 @@ function report(
618573
`inside its declared owner (R7); every zero-dep CI job resolves without ` +
619574
`node_modules (R8); ${typeCycleNote(typeCycle)}; ${daemonModularitySummary()}; ` +
620575
`${packageBoundariesSummary(repoRoot)}; ${platformPackagePolicySummary()}; ` +
621-
`${deviceInventoryCutoverSummary()}; and bin.ts imports normalizeCliCommandAlias, ` +
576+
`${runtimeCommandCutoverSummary()}; and bin.ts imports normalizeCliCommandAlias, ` +
622577
`actually passes it into buildCommandUsageText, and holds no local alias literals ` +
623578
`(R12).\n`,
624579
);
@@ -657,10 +612,9 @@ export function main(): number {
657612
const violations = [
658613
...checkLayeringRules(edges),
659614
...checkCycles(edges),
660-
...checkLogsRuntimeCutover(sources),
615+
...checkRuntimeCommandCutover(sources),
616+
...checkRecordRuntimeRegistryJoin(sources),
661617
...checkContractsImplementationAuthority(sources),
662-
...checkNetworkRuntimeCutover(sources),
663-
...checkRecordRuntimeCutover(sources),
664618
...checkContractsImplementationAuthority(sources),
665619
...checkBackEdges(edges),
666620
...checkTypeInversions(edges),
@@ -677,7 +631,6 @@ export function main(): number {
677631
readTrackedPlatformPackageDeclarations(repoRoot),
678632
{ untrackedProductionFiles: listUntrackedProductionTypeScriptFiles(repoRoot) },
679633
),
680-
...checkDeviceInventoryCutover(sources),
681634
];
682635
return report(sourceFiles, violations, typeCycle);
683636
}

scripts/layering/record-runtime-policy-ast.ts renamed to scripts/layering/cutover-policy-ast.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export type RecordRuntimeProductionSource = Readonly<{ path: string; source: string }>;
1+
/** A production file the cutover policies scan: repo-relative path plus its source. */
2+
export type ProductionSource = Readonly<{ path: string; source: string }>;
23

34
export function memberName(node: Record<string, unknown>): string | undefined {
45
const property = node.property as Record<string, unknown> | undefined;

scripts/layering/device-inventory-cutover-policy.test.ts

Lines changed: 0 additions & 100 deletions
This file was deleted.

0 commit comments

Comments
 (0)