The ref hygiene gate dies on a mid-rename tree instead of reporting (#940) - #948
Closed
philcunliffe wants to merge 1 commit into
Closed
The ref hygiene gate dies on a mid-rename tree instead of reporting (#940)#948philcunliffe wants to merge 1 commit into
philcunliffe wants to merge 1 commit into
Conversation
…940) `trackedFiles()` fed `git ls-files -z` straight into `readFileSync`. The index is not the working tree, so a path tracked but absent from disk (mid-rebase, mid-rename) threw ENOENT at module load and the whole gate reported nothing at all instead of reporting that the annotations are fine. Filter the listing with `existsSync` before reading it. The regression test spawns the real gate with a `git` on PATH that delegates to the real one except that `ls-files -z` names one extra path with no file behind it, so the only difference from a normal run is the condition under test. It clears `NODE_TEST_CONTEXT` for the child: the test runner skips nested runs, and without that the child exits 0 having loaded nothing and the assertions pass against a gate that never ran. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Author
Issues #940 and #942 are follow-ups from two different PRs (#929 and #933), but both
Both branch off This needs a human call: pick one approach (or merge one and rebase the other onto |
philcunliffe
pushed a commit
that referenced
this pull request
Aug 19, 2026
philcunliffe
added a commit
that referenced
this pull request
Aug 19, 2026
…porting (#942) (#947) * The @ref hygiene gate dies on a mid-rename working tree instead of reporting (#942) `git ls-files` reports the index, not the working tree, so a path it names can have no file behind it: mid-rebase, mid-rename, or any other moment where the two have not converged. `trackedFiles()` in the `@ref` hygiene gate fed that list straight into `fs.readFileSync` at module scope, so one such path threw ENOENT before a single test ran and took the whole file with it. A developer on a transiently inconsistent checkout got a stack trace where a hygiene result belonged. Extract the listing into `test/helpers/tracked_files.js` and filter it to paths that are present on disk, so every caller of the shared gate listing gets the guarantee that what it returns can be read. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Preserve ref-hygiene integration coverage from #948 --------- Co-authored-by: test <test@test.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Phillip Cunliffe <filco@Macmini.localdomain>
Contributor
Author
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.
Deferred finding 1 from the triage of PR #933, carried into #940.
What was wrong
trackedFiles()intest/core/llp-ref-hygiene.test.jsfedgit ls-files -zoutput straight intofs.readFileSyncwith no presence filter.ls-filesanswers from the index, not the working tree, so a path that is tracked but absent from disk (mid-rebase, mid-rename) threw ENOENT at module load. The whole gate then reported nothing at all instead of reporting that the annotations are fine. Loud, not silent, and developer-tree only, which is why it was deferred rather than blocking.The fix
Filter the listing with
fs.existsSync(path.join(REPO_ROOT, f))before reading, with a comment saying why the index and the working tree can disagree.The regression test
test/core/llp-ref-hygiene-absent-path.test.js, one test:the ref hygiene gate reports a result on a tree missing a tracked file.It exercises the real gate rather than a copy of its logic. It builds a
gitshim on PATH that delegates to the real binary except thatls-files -zappends one extra path with no file behind it, then spawnsnode --test test/core/llp-ref-hygiene.test.jsand asserts the run reports test results, never prints ENOENT, and exits 0.One subtlety worth flagging for review: the child's environment has
NODE_TEST_CONTEXTdeleted. The node test runner refuses nested runs (node:test run() is being called recursively within a test file. skipping running files.), and without clearing it the child exits 0 having loaded nothing, so every assertion passes against a gate that never ran. The first assertion (# testsappears in the output) is the guard against that failure mode coming back.Evidence
Without the fix the failure message carries the reported symptom verbatim:
Error: ENOENT: no such file or directory, open '.../src/core/absent-from-the-working-tree.js' at .../llp-ref-hygiene.test.js:336.Full suite:
npm test4529 pass, 0 fail, 1 skipped.npm run typecheckclean.Fixes #940