Skip to content

fix(doc-links): report references into a moved directory as missing (#2588) - #2602

Open
bline wants to merge 1 commit into
DeusData:mainfrom
bline:fix/doc-link-moved-directory
Open

bline wants to merge 1 commit into
DeusData:mainfrom
bline:fix/doc-link-moved-directory

Conversation

@bline

@bline bline commented Oct 12, 2026

Copy link
Copy Markdown

What does this PR do?

Fixes #2588. A Markdown reference whose directory no longer exists counted as
no reference to the repository at all: no MENTIONS edge and no unresolved
row. After git mv src/util src/helpers, a reference to
src/util/rounding.py::clamp disappeared without a trace.

The doc-rot rule in mdr_resolve_path required the path's own parent
directory to be a Folder. It now also accepts any directory above it that the
reference itself wrote:

reference (in docs/notes.md, after src/util moved) before after
src/util/rounding.py::clamp nothing unresolved missing
[rounding](../src/util/rounding.py) nothing unresolved missing
scratch/new/thing.py (no scratch/ in the repository) nothing nothing (unchanged)

Only directories the reference wrote count, not the directory it is read from.
That is the document's directory, or wherever the reference's leading ./ and
../ lead. So a document's own directory never turns a foreign path into doc
rot. A path with no directory in the repository still counts as no reference
(a file a tutorial asks the reader to create, or a system path).

This is the issue's suggestion, generalized. Its "top-level segment exists"
test is the root-relative case of this rule, and relative links get the same
treatment.

One tradeoff: a tutorial that asks the reader to create a file in a new
subdirectory of an existing directory (src/newpkg/x.py) now gets a
missing row where it got none before. I think that is the right default:
the path names this repository's tree. A narrower rule, such as requiring the
top-level segment only, would still have this case.

This is independent of #2601 (#2587). The two touch different parts of
mdr_resolve_path and different spots in the test file.

Evidence

doc_links_md_moved_directory_issue2588 in tests/test_doc_links_md.c
indexes the fixture, moves src/util to src/helpers, and re-indexes
incrementally. dm_step requires the incremental state to equal a full
index. Without the source change it fails on the defect itself:

FAIL tests/test_doc_links_md.c:484: "" != "missing"

With it, scripts/test.sh --suites doc_links_md,doc_links_rst,doc_links_adoc,doc_mentions
reports 96 passed, 0 failed.

Checklist

  • Every commit is signed off (git commit -s) — required, CI rejects
    unsigned commits (DCO, see CONTRIBUTING.md)
  • Tests pass locally: scripts/test.sh (the canonical leg), 9275 passed, 0 failed, 10 skipped,
    186 suites, Linux x86-64, gcc
  • Lint passes: scripts/lint.sh --ci in test-infrastructure lint container
    (cppcheck + clang-format-20 + memory-core), "All linters passed"
  • New behavior is covered by a test (reproduce-first for bug fixes)

Written with an AI agent (Claude); I reviewed the change and certify it via
the DCO sign-off.

🤖 Generated with Claude Code

@bline
bline requested a review from DeusData as a code owner October 12, 2026 04:15
@github-actions

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

@bline

bline commented Oct 12, 2026

Copy link
Copy Markdown
Author

The lint / lint failure here looks unrelated to this change. cppcheck reports:

src/pipeline/doc_links_pdf.c:422:68: style: Condition 'strcmp(n->name?n->name:"",f->name?f->name:"")!=0' is always false [knownConditionTrueFalse]

This PR touches only src/pipeline/doc_links_md.c and tests/test_doc_links_md.c. With main merged with this branch, scripts/lint.sh --ci in the test-infrastructure lint container passes locally (cppcheck, clang-format-20, memory-core: "All linters passed"). Could you re-run the lint job when you have a moment? Fork PRs can't re-run checks themselves.

…eusData#2588)

A Markdown reference whose directory no longer exists counted as no
reference to the repository: no MENTIONS edge and no unresolved row. After
`git mv src/util src/helpers`, `src/util/rounding.py::clamp` simply
disappeared, so a moved or renamed directory left no trace of the stale
reference.

The doc-rot rule required the path's own parent directory to be a Folder.
It now also accepts any directory above it that the reference itself wrote:
`src` for `src/util/rounding.py` read from the root, or for
`../src/util/rounding.py` read from docs/. The directory a try is read from
(the document's directory, or what its leading `./` and `../` reach) does
not count, so a document's own directory never turns a foreign path into
doc rot. A path none of whose written directories exists (a file a tutorial
asks the reader to create in a new directory, a system path) stays no
reference, as before.

Test (tests/test_doc_links_md.c) indexes a document that references
src/util/rounding.py both from the root and relatively, moves src/util to
src/helpers, and re-indexes incrementally, requiring the same state as a
full index. Without the fix it fails on the defect: the reference has no
row ("" != "missing").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Scott Beck <296871+bline@users.noreply.github.com>
@bline
bline force-pushed the fix/doc-link-moved-directory branch from cc8a93a to 6530142 Compare October 14, 2026 22:14
@bline

bline commented Oct 14, 2026

Copy link
Copy Markdown
Author

Correction to my comment above: a re-run wouldn't have helped, since it checks the same merge commit. I've rebased the branch onto current main, which already rewrites that line (337f868d), so the new run should pass. Nothing is needed from you for this.

This branch has not been deployed

No deployments
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.

References into a moved directory vanish without unresolved rows

1 participant