Found while implementing the bundle half of #16175 (PR #16240). Out of the declared file surface there and deliberately not ridden in.
What
inspectBundleFreshness in packages/spec/scripts/lib/dist-freshness.ts prints ONE cause for a stale verdict:
packages/spec/dist's .mjs/.js bundles are OLDER than packages/spec/src (or than
tsup.config.ts, which decides the entries, the externals and whether entries are
self-contained). The bundles on disk predate the sources.
Since PR #16240 that refusal can arrive from two distinguishable states, exactly as its declaration-axis sibling can:
- mismatch —
dist/.build-input-hash records a digest and src no longer hashes to it. A real content change; the message could print both digests and say so.
- unstamped — no stamp, unreadable, or not 64 hex characters. There is nothing to check the timestamp against; the message could say that instead of asserting a content claim it never measured.
inspectDistFreshness, immediately above it in the same file, already branches on all three states and names each one — that branch landed with #14985 as the "half a wrong message" repair. The bundle path has no equivalent, so a reader whose bundles are genuinely current but unstamped is told "the bundles on disk predate the sources", which is an mtime fact stated as a content fact.
Why it is a finding and not a defect
Nothing is wrong today: the mtime claim in the sentence is true whenever the refusal fires, and the refusal itself is correct in every state. What is missing is the same distinguishability #14985 argued for one axis over — the wrong-cause half of that card, unrepaired here.
Shape of the fix
Mirror the sibling: ask buildStamp(pkgDir) on the stale branch only (the digest is ~30 ms and is spent only on the path that was about to prescribe a rebuild), and select between a mismatch cause that prints recorded … / now hashes to … and an unstamped cause that says there is nothing to compare against. packages/spec/scripts/check-browser-reachable-entries.ts already carries the fixtures both states need.
Dedupe
search_issues, repo-scoped, control query first in the same session: dist freshness gate refuses because mtime moved but bytes did not, declaration stamp acquittal returned #16175 and #14985, both known present, so the instrument was answering. The query for this finding returned #15963, #16175 and #10595 — no twin. REST /search/issues is 403 in this container (sessions are bound to repository-scoped endpoints), which is why this dedupe ran on MCP.
Not assigned, per the filing discipline.
Generated by Claude Code
Found while implementing the bundle half of #16175 (PR #16240). Out of the declared file surface there and deliberately not ridden in.
What
inspectBundleFreshnessinpackages/spec/scripts/lib/dist-freshness.tsprints ONE cause for a stale verdict:Since PR #16240 that refusal can arrive from two distinguishable states, exactly as its declaration-axis sibling can:
dist/.build-input-hashrecords a digest andsrcno longer hashes to it. A real content change; the message could print both digests and say so.inspectDistFreshness, immediately above it in the same file, already branches on all three states and names each one — that branch landed with #14985 as the "half a wrong message" repair. The bundle path has no equivalent, so a reader whose bundles are genuinely current but unstamped is told "the bundles on disk predate the sources", which is an mtime fact stated as a content fact.Why it is a finding and not a defect
Nothing is wrong today: the mtime claim in the sentence is true whenever the refusal fires, and the refusal itself is correct in every state. What is missing is the same distinguishability #14985 argued for one axis over — the wrong-cause half of that card, unrepaired here.
Shape of the fix
Mirror the sibling: ask
buildStamp(pkgDir)on thestalebranch only (the digest is ~30 ms and is spent only on the path that was about to prescribe a rebuild), and select between a mismatch cause that printsrecorded … / now hashes to …and an unstamped cause that says there is nothing to compare against.packages/spec/scripts/check-browser-reachable-entries.tsalready carries the fixtures both states need.Dedupe
search_issues, repo-scoped, control query first in the same session:dist freshness gate refuses because mtime moved but bytes did not, declaration stamp acquittalreturned #16175 and #14985, both known present, so the instrument was answering. The query for this finding returned #15963, #16175 and #10595 — no twin. REST/search/issuesis 403 in this container (sessions are bound to repository-scoped endpoints), which is why this dedupe ran on MCP.Not assigned, per the filing discipline.
Generated by Claude Code