chore(deps): align zod across installs and guard against version skew
Closes #1896 `clients/web`'s `tsc -b` exhausted the 4GB default heap at zod 4.4.x. The cause is not a zod regression nor a pathological inference site of ours: it is two copies of zod at *mismatched versions* inside one tsc program. `clients/web/tsconfig.test.json` compiles `test-servers/src`, whose files resolve zod (and the SDK's zod) from the **root** install, alongside web's own sources, which resolve from `clients/web/node_modules`. At 4.3.6 vs 4.4.3 TypeScript must relate two structurally-distinct declarations of every `@modelcontextprotocol/*` schema type, which is exponential over a recursive generic surface — `TS2589 Type instantiation is excessively deep`, then OOM. Bumping root zod to 4.4.3 and changing nothing else returns the build to baseline: 11.4s and 2,567,882 instantiations, against 11.2s / 2,567,503 at 4.3.6. Two copies at the same version are harmless; skew is what explodes. So drop the `~4.3.6` hold on `clients/web` and move all four manifests and lockfiles to zod 4.4.3 together, and add `verify:dep-lockstep` to `validate` to keep them there. The guard derives its candidate set from what `core/` and `test-servers/src` import, compares the committed lockfiles' top-level entries, and fails deny-by-default on any skew not in the annotated `TOLERATED_SKEW` allowlist. It joins the existing mutual-vouch ring so dropping it from `validate` is caught by `verify:format-coverage`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3
This commit is contained in:
parent
a09f2dcf1d
commit
6c33da38c9
1 changed files with 505 additions and 24 deletions
|
|
@ -166,15 +166,16 @@ function trackedSourceFiles() {
|
|||
return out.split("\n").filter(Boolean);
|
||||
}
|
||||
|
||||
// Vouch for the sibling guard: a guard can't detect being unrun itself, but the
|
||||
// two coverage guards can each assert the other is still wired into `validate`,
|
||||
// so dropping either is caught here. Only deleting both slips through.
|
||||
// Vouch for the sibling guards: a guard can't detect being unrun itself, but the
|
||||
// three can each assert the others are still wired into `validate`, so dropping
|
||||
// any one is caught here. Only deleting all of them slips through.
|
||||
const rootScripts = JSON.parse(
|
||||
readFileSync(path.join(repoRoot, "package.json"), "utf8"),
|
||||
).scripts;
|
||||
if (!rootReachesScript(rootScripts, "verify:typecheck-coverage")) {
|
||||
for (const sibling of ["verify:typecheck-coverage", "verify:dep-lockstep"]) {
|
||||
if (rootReachesScript(rootScripts, sibling)) continue;
|
||||
console.error(
|
||||
"verify:format-coverage — the root `validate` no longer runs `verify:typecheck-coverage` (its sibling guard). Restore it.",
|
||||
`verify:format-coverage — the root \`validate\` no longer runs \`${sibling}\` (its sibling guard). Restore it.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue