Skip to content

fix(drift): resolve MISSING_PATH false positives from #143 - #200

Merged
theyashasvipandey merged 1 commit into
mainfrom
fix-143-missing-path-false-positives
Sep 19, 2026
Merged

theyashasvipandey merged 1 commit into
mainfrom
fix-143-missing-path-false-positives

Conversation

@theyashasvipandey

Copy link
Copy Markdown
Collaborator

What

Fixes the three MISSING_PATH defects reported in #143, each of which still
reproduced on 0.8.x:

  1. Negation was heading-scoped only. It is now also scoped to the sentence
    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.
  2. 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.
  3. 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 isUnrootedReference guard added since 0.7.x and
needed 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 longer
authorizes …) 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 check reported errors for files that were intentionally absent or were
never paths at all, which zeroes drift scores on healthy repositories.

Two things this PR does not claim:

Type of change

  • Bug fix
  • New feature
  • Refactor
  • Docs
  • CI/Tooling

How to test

  1. npx vitest run src/drift — 10 pass, 1 skipped. These are the first tests
    under src/drift, which had no coverage across its 19 source files.
  2. The skipped case documents an out-of-scope defect: a version-shaped
    reference such as release/2.1.0 or python/3.11 reads as a file extension
    to the same guard and is still reported. Tracked separately; unskip with
    that fix.
  3. On a scaffold, check the before/after issue list rather than the score:
    node dist/cli.js check --json
    
    On this repository the raw deduction moves from −163 to −150 (two issues
    removed, none introduced). The score reads 0/100 either way, because it is
    floored and dominated by staleness.
  4. Regression guard worth reading: still checks a directory reference rooted at a directory that exists pins that the trailing-separator change did not
    quietly turn every documented directory into prose.

Checklist

  • Tests pass (npm test) — not run in full locally. tsc --noEmit is
    clean and the targeted suites (src/drift, src/wiki/migration,
    src/__tests__, src/agent-skills) pass. The two agent-skills/installer
    failures seen locally are pre-existing and reproduce identically on stock
    main. Leaving this to CI.
  • No breaking changes — no public API, severity or format change.
    isNegatedText is a new internal export of src/markdown.ts and is not
    re-exported from src/index.ts.
  • Tested locally with a real project — five scaffolds, stock vs. patched
    builds compared issue-by-issue.

Code-graph changes

  • This PR targets main
  • A linked issue agrees on the bounded extractor/resolver scope
  • The change follows the frozen LanguageExtractor or FrameworkResolver interface
  • A focused fixture and assertions for the expected node/edge shape are included
  • Any new grammar WASM, extension mapping, extractor, or resolver is registered
  • No graph identity, reconciliation, schema, or drift-semantics changes are included, or a core / discuss-first issue is linked above

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.
@theyashasvipandey
theyashasvipandey merged commit 2f074dc into main Sep 19, 2026
9 checks passed
@theyashasvipandey
theyashasvipandey deleted the fix-143-missing-path-false-positives branch September 19, 2026 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MISSING_PATH false positives: negation only heading-scoped, non-path tokens treated as paths, dot-dir glob blind spot

1 participant