diff --git a/scripts/layering/check.ts b/scripts/layering/check.ts index 0adacb1bf..f2682152c 100644 --- a/scripts/layering/check.ts +++ b/scripts/layering/check.ts @@ -89,6 +89,14 @@ function isDaemonServer(rel: string): boolean { return rel.startsWith('src/daemon/') && !rel.startsWith('src/daemon/client/'); } +// sdk/ are the package's PUBLIC re-export barrels (§5.5 "sdk = re-export barrels +// only"). They legitimately re-export platform symbols as part of the public API, +// and are OFF the CLI cold path (not imported by bin.ts/cli), so exempting them +// from R3 does not regress cold-start — they sit above the internal DAG R3 governs. +function isSdkBarrel(rel: string): boolean { + return rel.startsWith('src/sdk/'); +} + // ── Import extraction ─────────────────────────────────────────────────────── function scanDynamicImports(line: string, lineNo: number): ImportEdge[] { @@ -180,7 +188,7 @@ function ruleCommandsFloor(ctx: EdgeContext): Violation | null { // daemon server; everywhere else use a dynamic import() or a type-only import. function rulePlatformsSeam(ctx: EdgeContext): Violation | null { if (ctx.toTop !== 'platforms' || ctx.imp.dynamic || ctx.imp.typeOnly) return null; - if (isCoreInteractor(ctx.file) || isDaemonServer(ctx.file)) return null; + if (isCoreInteractor(ctx.file) || isDaemonServer(ctx.file) || isSdkBarrel(ctx.file)) return null; return { rule: 'R3 platforms-seam', file: ctx.file,