ReviewOS

home-lang/home

fix(ts): terminate expanding structural inference on the pinned Zod graph

#921
Open glennmichael123 opened this 8 days ago ·
8 days ago

Parent: #548; related to #879 and #842, but distinct from the now-passing eight forward-alias reductions.

Current-main evidence (5fa14ef, Darwin arm64): the repository-pinned Zod 4.5.2 tarball matches SHA-512 5e46170a8975d3e6daffa17f72e79657e4decd478ea975b485d789b7909d5e34d8780800420e4dd37450749f349a17c513bdbea5b96f60c5b8c32d90a7841bae and contains exactly 106 non-test src/v4 TypeScript files. The strict NodeNext/noEmit project is reconstructed from scripts/ts-unmodeled-any-ratchet.py. The ratchet hit its 300-second bound without producing a diagnostic count. A direct fresh home-tsc run remained active at one CPU core; two read-only samples during that single guarded run showed a deep repeating Checker.inferFromPair -> inferUnionRemainder -> inferFromPair -> inferFromSignaturePair -> inferFromCovariantPair chain (check.zig around lines 165175-165574), while physical footprint grew from about 1.0 GiB to 1.8 GiB. The process was deliberately terminated at 6:46 to protect the host; supervisor recorded exit 143 and 1,897 MB peak tree footprint. No Zod admission, diagnostic total, or benchmark timing is claimed.

An exact-TypeId active-pair guard covering structural inference compiled, but the same graph still exceeded a 120-second bounded probe. That experiment was fully reverted and the normal CLI was rebuilt; it is not an adopted fix. The observed expansion may involve freshly interned type identities, so an exact-pair cycle check alone is insufficient. The sampled production source path and results are evidence, not proof of a particular semantic root cause.

Acceptance: isolate the source-level recursive inference expansion with a short reference-checked positive/negative reduction; preserve real type-parameter substitutions, recursive structural/callback semantics, and strict diagnostics without depth cutoffs, any erasure, skipped bodies, source-specific predicates, or benchmark shortcuts. Make the unchanged pinned 106-file project terminate under the existing 3,840 MB guard and match the reference diagnostic/admission contract; keep failed controls visible. Run unfiltered checker/Program/driver/CLI/entrypoint gates and the genuine consumer negative controls. Only after admission, qualify any performance claim through #548s unchanged interleaved protocol and publish full raw evidence plus concise README/doc results. Linux and other-platform proof remains separate.

8 days ago

Bounded reduction check on current main (no source edit): a project with only src/v4/core/schemas.ts as an explicit root still resolves 82 src/v4 files under installed TypeScript 5.7.3. Home exceeded 45s and again exceeded 30s under run_bounded/HOME_RUN_MAX_MB=3840; installed TypeScript 5.7.3 completed that same project, but this is not the pinned TS diagnostic control. A three-second read-only sample of the live Home process at about 16s showed 1,363/1,363 main-thread samples under Program.loadImportClosureImpl -> Program.compileAll -> Checker.checkSourceFile, mostly function/body/expression checking. inferFromPair appeared only sparsely in this sample, unlike the deep repeated inference chain sampled for the full 106-root graph. Thus this is NOT yet the required short reproduction of the #921 inference expansion; the extra roots or later check phase remain necessary to isolate. A noResolve diagnostic experiment was inconclusive: installed tsc lists one v4 source with that option, while Home still timed out before listFilesOnly output, and current Home source exposes no implemented noResolve propagation beyond the option table. No checker fix, diagnostic parity, admission or performance claim is made. The sample is local at /private/tmp/zod-core-schemas.sample.txt.

8 days ago

Further bounded diagnostic evidence, no checker patch/admission claim: on the unchanged pinned 106-root Zod graph, a temporary compileFile start/end trace reached 112 starts/111 ends by the 120 s bound, active in src/v4/core/to-json-schema.ts. A sole explicit to-json-schema.ts root (imports retained) reached 88 starts/87 ends at a 100 s bound, active in imported src/v4/core/schemas.ts; installed TypeScript 5.7.3 completes the same sole-root config in under 1 s. A 3-second sample at ~74 s of the latter run recorded 1,511/1,511 main-thread samples under checkVarDecl -> checkExpression -> instantiateReturn, with repeated Checker.inferFromPair/signature/covariant frames. This establishes a smaller real-project reproducer for the structural inference expansion, but not yet a short source reduction or semantic fix. Temporary source instrumentation was removed and the ordinary home-tsc Debug binary was rebuilt successfully under the 3,840 MB guard (peak tree footprint 2,200 MB). No Zod diagnostic or performance win is claimed; #921 remains open.

8 days ago

Further bounded localization on the unchanged pinned Zod 4.5.2 source, with only src/v4/core/to-json-schema.ts as an explicit root and imports retained: a temporary checkVarDecl entry/exit trace reached 105 starts and 104 ends by the 105 s bound. The active declaration was const $ZodString: core.$constructor<$ZodString> at src/v4/core/schemas.ts:389 (source offset 13212). Earlier stack sampling had placed the time in structural return-type inference. Two import-free, TypeScript-clean reductions modeling the constructor and recursive trait completed quickly in Home, so neither reproduces the problem; this is localization, not a confirmed root cause or fix. The temporary trace has been removed, the ordinary Debug home-tsc rebuilt successfully under the 3,840 MB guard (peak tree footprint 2,266 MB), and the tracked worktree remains unchanged. No Zod admission, diagnostic, or performance improvement is claimed. #921 remains open.

8 days ago

Bounded, reverted differential probe on the same pinned Zod 4.5.2 one-root config (src/v4/core/to-json-schema.ts, imports retained): with only the $ZodString constructor initializer replaced by an empty callback, a temporary checkVarDecl trace printed both PROBE_ZOD_STRING_START and PROBE_ZOD_STRING_END during a 130 s run. The whole modified project still reached the 130 s bound, so this is not a Zod admission or global speed result. With the initializer containing only its original $ZodType.init(inst, def) statement, the same trace printed START but not END before the 90 s bound. The unchanged full initializer also remained inside that declaration in the prior 105 s trace. This localizes the expensive declaration path to checking the init call or its assertion/generic type effects; it does not yet distinguish those mechanisms or prove a fix. The exact original Zod initializer and checker source were restored, the ordinary Debug home-tsc rebuilt under HOME_RUN_MAX_MB=3840 (peak tree footprint 2,267 MB), and git diff is empty. Next diagnosis should vary the assertion signature versus call-body type relations while retaining the import graph, not add a cutoff or skip the call. #921 remains open.

8 days ago

Additional bounded differential, all temporary edits reverted: with the original pinned $ZodString initializer intact, changing only the extracted copy's core.$constructor.init(inst, def) signature from asserts inst is T to void let the one-declaration trace print both START and END during a 105 s guarded run. The modified whole project still hit the 105 s wall bound; its diagnostics cannot be used for parity. In the preceding 90 s one-call probe with the original assertion signature, START printed but END did not. This suggests assertion-signature work contributes to the long declaration path, but does not prove it is the only cause: the call and generic type relation remain expensive. Do not change the assertion contract as a fix. The pinned Zod signature and initializer are restored, the checker instrumentation is absent, tracked git diff is empty, and the ordinary Debug binary rebuilt under HOME_RUN_MAX_MB=3840 (peak tree footprint 2,046 MB). No patch, performance claim, or Zod admission is asserted. #921 stays open.

8 days ago

Current-main follow-up after 17dcfeb65: rebuilt the ordinary Debug home-tsc, then ran the unchanged SHA-512-pinned Zod 4.5.2 106-file ratchet (scripts/ts-unmodeled-any-ratchet.py) as the sole heavy process under HOME_RUN_MAX_MB=3840 with a 900-second wall bound. The memory supervisor terminated it with exit 125 when sampled tree footprint reached 3,841 MB (largest compiler process 3,827.1 MB; host low-water 30%). The script had not emitted a count or written its diagnostics output. Process-tree check afterward found no surviving ratchet/compiler process. This is an unqualified memory-bound result, not Zod admission, a diagnostic comparison, or proof that the recent #844 commit caused the expansion. #921 remains open; the structural-inference path still needs a source-level reduction and semantic fix without erasure or cutoffs.

Sign in to comment on this issue.