fix(kb-lint): a markdown link may not resolve into the quarantine
The link-integrity pass ended in `is_file()`, and `.AGENTTRASH/` is a real directory on this machine: a page pointing at `[x](.AGENTTRASH/gone.md)` passed the gate here and was a dead link everywhere else, because the quarantine is gitignored. This is incident #57 — the wikilink resolver resolving `[[log]]` onto a quarantined copy — reproduced in markdown clothing, which is to say: fixing one resolver while leaving the identical assumption in the other one is not a fix. A link that lands inside the bundle must land on a page that belongs to the bundle. A link that leaves the bundle is still honoured (`tools/live-sync.md` -> `../../AGENTS.md` points at the operating contract, which is not bundle content and is real on disk). Red test added first, both link spellings covered; nothing previously green changed. Refs #64
This commit is contained in:
1 parent
22d2f3bcd8
commit
4735702965
2 files changed
+26
-2
No files matched your search
+11
-2
@@ -23,6 +23,7 @@ def pages():
|
||||
# Names that a wikilink may point at: exactly the pages pages() reports. Deriving this
|
||||
# once keeps linting and link resolution from disagreeing about what exists.
|
||||
live = {p.stem for p in pages()}
|
||||
live_paths = {p.resolve() for p in pages()}
|
||||
|
||||
for p in pages():
|
||||
rel = p.relative_to(kb)
|
||||
@@ -70,8 +71,16 @@ for p in pages():
|
||||
text = re.sub(r"^```[^\n]*$^```[^\n]*$", "", p.read_text(errors="replace"), flags=re.M)
|
||||
rel = p.relative_to(kb)
|
||||
for m in re.finditer(r"\]\((?!https?:|#)([^)#\s]+\.md)", text):
|
||||
target = (p.parent / m.group(1)).resolve() if not m.group(1).startswith("/") else (kb / m.group(1).lstrip("/"))
|
||||
if not Path(target).is_file():
|
||||
target = (p.parent / m.group(1)).resolve() if not m.group(1).startswith("/") else (kb / m.group(1).lstrip("/")).resolve()
|
||||
# A link INSIDE the bundle must land on a page that belongs to the bundle: `is_file()`
|
||||
# alone also accepted a target parked in .AGENTTRASH/, which is gitignored — green here,
|
||||
# a dead link on every machine that pulls (#57 again, in markdown clothing). A link that
|
||||
# leaves the bundle is allowed: ../../AGENTS.md is the operating contract, not bundle
|
||||
# content, and it is real on disk.
|
||||
if kb in target.parents:
|
||||
if target not in live_paths:
|
||||
violations.append(f"{rel}: broken relative link -> {m.group(1)}")
|
||||
elif not target.is_file():
|
||||
violations.append(f"{rel}: broken relative link -> {m.group(1)}")
|
||||
for m in re.finditer(r"\[\[([^\]|#]+)", text):
|
||||
# wikilinks resolve by filename anywhere in the KB (Obsidian semantics) — but only
|
||||
|
||||
Reference in new issue
Block a user