fix(wiki): link index rows to their own article when labels collide (#3032, #3033) - #3095
Conversation
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Formal verification. 1 change(s) tested, no difference found (not proven).
Graphify review — findings
Fixes index rows pointing at the wrong article when two communities or god nodes share a label: _index_md now links each row by the slug the article was actually written under (community_slugs and god_articles) rather than re-deriving it from the label, which collapsed duplicates onto the first-registered file and orphaned the rest (#3032/#3033). Adds _md_link_to to render a link from a known slug, still falling back to plain text when no article exists. Backs this with regression tests asserting every written article is reachable from the index.
No blocking issues surfaced. 3 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 245 functions depend on the 77 functions this change touches.
Health — this change adds coupling hotspots:
- new:
to_wiki()— 44 callers, 7 callees - new:
dispatch_command()— 2 callers, 122 callees - new:
test_poisoned_manifest_is_healed()— 0 callers, 6 callees
Verification — 245 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 95 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify \_index\_md.
The verifier did not have enough to check \_index\_md, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: signature changed: no shared positional arity
No difference found (not proven): No behavior difference found in \_md\_link (not a proof).
The verifier ran both versions of \_md\_link on many inputs and saw identical behavior every time. Strong evidence the change is safe, but evidence, not a proof.
Guarantee: Empirical: differential testing (both versions run on many generated inputs). A divergence on an untested input remains possible, so this is 'no counterexample found', not 'proven equivalent'.
Note: An input the sampler did not try could still differ.
Could not verify: Could not verify to\_wiki.
The verifier did not have enough to check to\_wiki, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: parameter `output_dir` is annotated `str | Path` — outside the synthesizable primitive/collection set
· 3 more finding(s) on lines outside this diff (see the check run).
Fixes #3032
Fixes #3033
What
index.mdnow links every Communities row and every God Nodes row to the article that row was actually written to. Before this, when two entries shared a label, both rows pointed at the first article and the second file (<Label>_2.md) was written but unreachable.Both issues are the same defect in two adjacent loops of
wiki.py, so they are fixed together — #3032 is the community loop, #3033 the god-node loop.Why
to_wikialready assigns every article a unique filename via_unique_slug, and keeps them incommunity_slugs(cid -> slug) andgod_articles((node_id, slug))._index_mdthen discarded those and re-derived each link target fromresolver, a label -> slug map built withsetdefault, so the first label registered wins.A label -> slug map structurally cannot represent two articles that share a label. Both rows resolved to the same slug, and the correctly-written
_2.mdarticle had nothing linking to it — so anything crawling fromindex.md(the documented entry point) could never reach it.This is the residual half of #497: that fix stopped the files from overwriting each other; the index linking still went by label.
How
_index_mdtakescommunity_slugsandgod_articlesinstead ofresolver, and links by the slug each article was actually written under. Since it no longer receives the resolver, the index cannot fall back to a label lookup._md_link_to(label, slug)renders a link from a slug that is already known;_md_linkkeeps its behaviour and delegates to it, so article prose links are unchanged.G—test_to_wiki_skips_missing_god_node_ids) is absent from the slug map and renders as plain text, matchingtest_wiki_links_to_nodes_without_articles_are_plain_text, rather than linking to a same-labelled article that isn't it.Testing
Both issues' repro scripts, run verbatim, now print what each issue lists as "Expected":
#3032
#3033
Three regression tests added to
tests/test_wiki.py— one per issue, plus a general "every article written is reachable from the index" guard. Onv8without the source change all three fail; with it all pass.Full suite: 12 failed, 5035 passed, 43 skipped. Those 12 are pre-existing failures on my machine (Windows) in
test_hooks/test_install*/test_non_regular_files/test_uninstall_scope/test_watch— none importgraphify.wiki, and re-running them with this change reverted gives the same 12.ruff checkis clean on both files.