Release-path guards: post-emit dangling-ref check (#202) + latest-blend gate (#203) - #207
Open
jagguji wants to merge 2 commits into
Open
Release-path guards: post-emit dangling-ref check (#202) + latest-blend gate (#203)#207jagguji wants to merge 2 commits into
jagguji wants to merge 2 commits into
Conversation
…-blend gate (#203) Two allowlist-independent safety nets for the crash/dangling-ref class the #198 post-mortem surfaced. Neither changes generated output. #202 — post-emit dangling-reference guard (src/validate.mjs): - After emit, assert every `Module.type`/`JsFn.t` reference into one of our own file-modules resolves to a real declaration. Catches the failure that shipped four times (an emitter change outran the reachability sweep's roots, stranding a reference whose declaration was dropped -> ReScript compile error) WITHOUT compiling. - Hard-fails the golden suite; warns (non-fatal) at generation time for real packages. - Verified zero false positives across every golden + benchmark baseline; trips on a synthetic dangling ref (test/dangling-refs.mjs). Handles decorated/@unboxed/rec decls, nested modules, externals, and comment/string noise. #203 — latest-blend pre-release gate (benchmark/run.mjs --latest-blend): - Resolves the LIVE `@juspay/blend-design-system@beta` dist-tag (not a pin), generates with this checkout, fails on crash / empty output / compile break; informational diff vs the newest pinned baseline. Validated: resolved 0.0.38-beta.1, 321 files, compiles. - Weekly + on-demand workflow; run before cutting a release. Catches "compiles on pinned, breaks on latest" (the exact #198 gap; a crash-before-emit is invisible to compile gates). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adversarial review found five latent defects (no P1s; all zero-flag today, but each would break CI on legitimate output under a plausible emitter change, or was a correctness bug). All fixed + pinned as unit tests / verified: #202 dangling-ref guard (src/validate.mjs): - P2: first @unboxed/variant arm (no leading `|`) was not collected, so a cross-module `Mod.FirstArm` value ref would false-positive. Collect after `=` too. - P2: stripNoise stripped line-comments before strings, so `//` inside a `@module("http://…")` string ate the line's declaration -> false positive. Rewrote stripNoise as a single left-to-right tokenizer (strings/line/block interact correctly; block comments nest; backslash escapes respected). - P3: nested block comments no longer leak their tail (same tokenizer). - Still 0 false positives across all 132 golden+baseline trees; still trips on a synthetic dangling ref. Three regression cases added to test/dangling-refs.mjs. #203 latest-blend gate (benchmark/run.mjs): - P3: rank() sorted a prerelease AFTER its release (backwards). Replaced with a correct cmpVersion (prerelease < release; numeric prerelease ids compare numerically). Only affected the informational baseline-diff target, not PASS/FAIL. - P3: npm view parse took the blind last line; now takes the last line MATCHING a version (still fails closed). Gate re-verified: 0.0.38-beta.1, 321 files, compiles. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Benchmark: ✅ PASS
|
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Batches the two release-path safety nets from the #198 post-mortem. Neither changes generated output — they only catch bad output before it ships. Closes #202, closes #203.
#202 — post-emit dangling-reference guard
The reachability sweep's root/child allowlist fell behind the emitter four times (#191, #195, #197 ×2), each shipping output where a
Module.type/JsFn.treference pointed at a declaration the sweep dropped — a ReScript compile error caught only by manual review or downstream validation. Each fix widened the allowlist; the next change outran it again.src/validate.mjsadds an allowlist-independent post-emit check: after every.resis written, assert each reference into one of our own file-modules resolves to a real declaration (plus bareJsFn.trequires a writtenJsFn.res). It never compiles anything — it's a fast, offline structural mirror of "does this compile?" for the one failure mode that recurs..resfiles), and it trips on synthetic dangling refs (test/dangling-refs.mjs, 11 cases).stripNoiseis a single-pass tokenizer (strings / line / nestable block comments interact correctly;\escapes respected);collectDeclaredNamesis deliberately over-collecting (can only miss a real dangling ref, never invent a false positive).#203 — latest-blend pre-release gate
The benchmark pins specific blend versions, but blend is the primary downstream target and moves faster than the pins. Twice a regression compiled on the pins yet broke on a newer real blend (#110, and #198's crash-before-emit — invisible to compile gates because there's no output to compile).
npm run bench:latest-blend(benchmark/run.mjs --latest-blend) resolves the live@juspay/blend-design-system@betadist-tag, generates with this checkout, and fails on crash / empty output / compile break; informational diff vs the newest pinned baseline. Weekly + on-demand workflow (.github/workflows/latest-blend-gate.yml); run before cutting a release. Complements the permanent regression pin: the pin catches that case forever, this gate catches the next one.0.0.38-beta.1, generated 321 files, compiled clean, fails closed.Review
Two adversarial subagent review rounds. Round 1 found 5 latent issues (no P1s; parser under-collection / comment-string ordering / semver sort) — all fixed in
f6cb926and pinned as regression tests. Round 2 re-reviewed the current HEAD (tokenizer attacked with 12 adversarial inputs,cmpVersionordering table, gate-fails-closed): clean, no P1/P2.Tests
npm testgreen (121 goldens + newtest/dangling-refs.mjs).🤖 Generated with Claude Code