Skip to content

Commit 4a31e6d

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 8ad1292 commit 4a31e6d

19 files changed

Lines changed: 1671 additions & 1838 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-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: 15 additions & 59 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,31 +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';
11599
import { recordRuntimeDaemonMechanicsViolations } from './record-runtime-mechanics-policy.ts';
116100
import { recordRuntimeRegistryJoinViolations } from './record-runtime-registry-policy.ts';
117101

@@ -191,16 +175,6 @@ function checkCycles(edges: readonly ResolvedImportEdge[]): LayeringViolation[]
191175
}));
192176
}
193177

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-
204178
function checkContractsImplementationAuthority(
205179
sources: ReadonlyMap<string, string>,
206180
): LayeringViolation[] {
@@ -209,31 +183,15 @@ function checkContractsImplementationAuthority(
209183
);
210184
}
211185

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[] {
186+
/**
187+
* Record's daemon-mechanics and registry-join policies stay separate modules: they are
188+
* record-specific structural scans, not per-command cutover rows. They keep the R16 id.
189+
*/
190+
function checkRecordRuntimeMechanics(sources: ReadonlyMap<string, string>): LayeringViolation[] {
230191
const production = [...sources].map(([file, source]) => ({ path: file, source }));
231192
return [
232-
...recordLegacyRouteViolations(production),
233193
...recordRuntimeDaemonMechanicsViolations(production),
234-
...recordRuntimeNarrowingViolations(production),
235194
...recordRuntimeRegistryJoinViolations(production),
236-
...recordRuntimeRouteViolations(production),
237195
].map((violation) => {
238196
const separator = violation.indexOf(': ');
239197
return {
@@ -618,7 +576,7 @@ function report(
618576
`inside its declared owner (R7); every zero-dep CI job resolves without ` +
619577
`node_modules (R8); ${typeCycleNote(typeCycle)}; ${daemonModularitySummary()}; ` +
620578
`${packageBoundariesSummary(repoRoot)}; ${platformPackagePolicySummary()}; ` +
621-
`${deviceInventoryCutoverSummary()}; and bin.ts imports normalizeCliCommandAlias, ` +
579+
`${runtimeCommandCutoverSummary()}; and bin.ts imports normalizeCliCommandAlias, ` +
622580
`actually passes it into buildCommandUsageText, and holds no local alias literals ` +
623581
`(R12).\n`,
624582
);
@@ -657,10 +615,9 @@ export function main(): number {
657615
const violations = [
658616
...checkLayeringRules(edges),
659617
...checkCycles(edges),
660-
...checkLogsRuntimeCutover(sources),
618+
...checkRuntimeCommandCutover(sources),
619+
...checkRecordRuntimeMechanics(sources),
661620
...checkContractsImplementationAuthority(sources),
662-
...checkNetworkRuntimeCutover(sources),
663-
...checkRecordRuntimeCutover(sources),
664621
...checkContractsImplementationAuthority(sources),
665622
...checkBackEdges(edges),
666623
...checkTypeInversions(edges),
@@ -677,7 +634,6 @@ export function main(): number {
677634
readTrackedPlatformPackageDeclarations(repoRoot),
678635
{ untrackedProductionFiles: listUntrackedProductionTypeScriptFiles(repoRoot) },
679636
),
680-
...checkDeviceInventoryCutover(sources),
681637
];
682638
return report(sourceFiles, violations, typeCycle);
683639
}

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)