fix(drift): resolve MISSING_PATH false positives from #143 - #200
Merged
Merged
Conversation
Three defects reported in #143 still reproduced on 0.8.x. Each one drops a claim that was never a path, rather than demoting the issue it produced, so a healthy scaffold stops losing points instead of losing them more slowly. - Negation was heading-scoped only. It is now also scoped to the sentence that contains a reference. The sentence, not the line, is the unit that governs: markdown wraps prose freely, so a cue and the reference it applies to routinely sit on different lines of one bullet. Scoping to the whole paragraph was tried first and proved too coarse -- on this repository it silenced four real directories because an unrelated clause elsewhere in the same block mentioned a removal. - A bare trailing directory was excluded from the unrooted-reference guard by its own separator. The separator now marks a directory reference instead of disqualifying the value, so `screenshots/` is prose when nothing by that name exists while `.mex/local/` still roots at a real directory and remains a claim the checker tests. - The fallback filename globs lacked `dot: true`, so a file documented by its bare name was never found inside a hidden directory such as `.github/workflows/`. The numeric-delta, `overall/overall` and glob cases from the same report already pass through the unrooted-reference guard added since, and needed no change. All are covered by tests so they stay fixed. Adds the first tests under src/drift, which had no coverage across its 19 source files. A version-shaped reference such as `release/2.1.0` is still reported, because a trailing version number reads as a file extension to the same guard; that case is covered by a skipped test and tracked separately.
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.
What
Fixes the three MISSING_PATH defects reported in #143, each of which still
reproduced on 0.8.x:
containing a reference. The sentence — not the line — is the unit that
governs: markdown wraps prose freely, so a cue and the reference it applies
to routinely sit on different lines of one bullet.
by its own separator. The separator now marks a directory reference
instead of disqualifying the value, so
screenshots/is prose when nothingby that name exists, while
.mex/local/still roots at a real directory andremains a claim the checker tests.
dot: true, so a file documented byits bare name was never found inside a hidden directory such as
.github/workflows/.The numeric-delta,
overall/overalland glob cases from the same reportalready pass through the
isUnrootedReferenceguard added since 0.7.x andneeded no change. All are covered by tests so they stay fixed.
Deliberate divergence from the report
The reporter also proposed demoting surviving MISSING_PATH issues from error to
warning. That is not included, per the maintainer reasoning in the issue
thread: demotion does not remove a false positive, it only makes it cheaper, so
it takes ~34 issues to floor the score instead of ~10 — bigger bucket, same
leak. It also answers the open question left for the reporter: all three
defects turned out decidable, so each one drops the claim before it becomes an
issue and nothing needed demoting.
An approach that was tried and rejected
Scoping negation to the whole paragraph passes all the same tests, but an
audit across this repository's scaffold showed it suppressed 7 of 167 path
claims where only 1 was a true negation — including four real, existing
directories, silenced because an unrelated clause elsewhere in the same block
mentioned a removal. A false negative is worse than the false positive this is
meant to kill. Sentence scope brings that to 2 of 167.
Known residual
One false negative remains: a sentence that both names a path and contains a
cue after it (
… implemented on \X`: successful agent exit no longerauthorizes …
) is still suppressed. Making a colon a sentence boundary would fix it and break the reporter's primary case (Deleted orphaned files:`check_commands.js``), so it is left as the accepted cost of keyword-based
negation.
Why
Closes #143.
mex checkreported errors for files that were intentionally absent or werenever paths at all, which zeroes drift scores on healthy repositories.
Two things this PR does not claim:
with real
.mex/directories: 0 issues removed, 0 introduced on everyone. A clean 100/100 scaffold stays 100/100 — the safety property the
reporter observed across their known-good projects — but none of these
projects contain the defects MISSING_PATH false positives: negation only heading-scoped, non-path tokens treated as paths, dot-dir glob blind spot #143 describes. The false positives dominating
them are different classes, which will be filed separately.
Type of change
How to test
npx vitest run src/drift— 10 pass, 1 skipped. These are the first testsunder
src/drift, which had no coverage across its 19 source files.reference such as
release/2.1.0orpython/3.11reads as a file extensionto the same guard and is still reported. Tracked separately; unskip with
that fix.
removed, none introduced). The score reads 0/100 either way, because it is
floored and dominated by staleness.
still checks a directory reference rooted at a directory that existspins that the trailing-separator change did notquietly turn every documented directory into prose.
Checklist
npm test) — not run in full locally.tsc --noEmitisclean and the targeted suites (
src/drift,src/wiki/migration,src/__tests__,src/agent-skills) pass. The twoagent-skills/installerfailures seen locally are pre-existing and reproduce identically on stock
main. Leaving this to CI.isNegatedTextis a new internal export ofsrc/markdown.tsand is notre-exported from
src/index.ts.builds compared issue-by-issue.
Code-graph changes
mainLanguageExtractororFrameworkResolverinterfacecore / discuss-firstissue is linked above