bug, lint, knowledge-graph
Summary
When Wiki Lint fixes a broken wikilink by creating a placeholder, it keeps the directory of the broken target but hard-codes type: query. The result is a page such as wiki/concepts/clash-detection.md carrying type: query. Two things follow immediately:
- It is deleted from the knowledge graph.
wiki-graph.ts removes every node whose type is query (HIDDEN_TYPES), so the page and all links pointing at it vanish from the graph.
- It violates the project's own schema. If
schema.md declares a Page Types table, validateWikiPageRouting will drop that file on the next ingest ("Pages under wiki/concepts/ must use type concept"), i.e. the app later refuses content it created itself.
In my project this accumulated to 106 pages, and among them was the single most-referenced page in the entire wiki (160 inbound references) — completely invisible in the graph, which in turn made the Insights panel report a large number of isolated pages.
Where it comes from
src/lib/lint-fixes.ts:
export function stubRelativePathFromBrokenTarget(brokenTarget: string): string {
const parts = normalized.split("/").map(makeQuerySlug).filter(Boolean)
const rel = parts.length > 1 ? parts.join("/") : `queries/${parts[0] ?? "missing-page"}`
return `${rel}.md`
}
const content = [
"---",
"type: query", // <-- always query, regardless of destination folder
`title: "${...}"`,
...
"tags: [stub, lint]",
So a broken [[concepts/foo]] produces wiki/concepts/foo.md with type: query. Only single-segment targets land in wiki/queries/, where type: query would be correct.
Note the app already has the function needed to do this right — inferWikiTypeFromPath in src/lib/wiki-page-types.ts maps concepts → concept, standards → standard, etc. — but it is currently only used for UI labels.
Related second half: "Create Page" + sweep never agree
The same class of problem makes review suggestions repeat. src/lib/wiki-filename.ts always appends a timestamp:
fileName: `${slug}-${date}-${time}.md` // e.g. attention-2026-09-06-143052.md
while sweepResolvedReviews resolves a missing-page item only on an exact name match (src/lib/sweep-reviews.ts, pageExists → index.byId / index.byTitle). A page created from the suggestion therefore never matches the suggestion that produced it, and the item comes back on the next sweep.
I realise #495 already made review IDs content-stable so resolved state survives regeneration — this is the remaining gap: the page the user creates cannot be recognised, independently of how the ID is computed.
Environment / measurements
LLM Wiki v0.6.11, Windows 11, 2,933 markdown files.
- 106 pages with
type: query sitting in knowledge folders (concepts/ 55, entities/ 25, sources/ 9, playbooks/ 6, findings/ 5, standards/ 3, synthesis/ 2, comparisons/ 1), all created by Lint's "Fix".
- After correcting their
type to match the folder, those pages rejoined the graph and the isolated-page count dropped sharply.
- 266 pages carried the
-YYYY-MM-DD-HHMMSS suffix outside wiki/queries/, mostly from "Create Page".
Proposed fixes
- Derive the stub's
type from its destination folder using the existing inferWikiTypeFromPath, falling back to query only for wiki/queries/. One line of intent, and it makes Lint's output consistent with the schema routing the app enforces elsewhere.
- Or always place stubs in
wiki/queries/ regardless of the target's path, so type: query is truthful. (Less good: it loses the author's intended location, and the broken link still will not resolve unless the target was single-segment.)
- Do not append a timestamp when the slug is free. Use
slug.md if it does not exist and only fall back to slug-YYYY-MM-DD-HHMMSS.md on collision. That alone would let pageExists recognise pages created from suggestions.
- Optionally, have
pageExists strip a trailing -YYYY-MM-DD(-HHMMSS) before comparing, so existing wikis benefit without a migration.
bug,lint,knowledge-graphSummary
When Wiki Lint fixes a broken wikilink by creating a placeholder, it keeps the directory of the broken target but hard-codes
type: query. The result is a page such aswiki/concepts/clash-detection.mdcarryingtype: query. Two things follow immediately:wiki-graph.tsremoves every node whose type isquery(HIDDEN_TYPES), so the page and all links pointing at it vanish from the graph.schema.mddeclares aPage Typestable,validateWikiPageRoutingwill drop that file on the next ingest ("Pages underwiki/concepts/must use typeconcept"), i.e. the app later refuses content it created itself.In my project this accumulated to 106 pages, and among them was the single most-referenced page in the entire wiki (160 inbound references) — completely invisible in the graph, which in turn made the Insights panel report a large number of isolated pages.
Where it comes from
src/lib/lint-fixes.ts:So a broken
[[concepts/foo]]produceswiki/concepts/foo.mdwithtype: query. Only single-segment targets land inwiki/queries/, wheretype: querywould be correct.Note the app already has the function needed to do this right —
inferWikiTypeFromPathinsrc/lib/wiki-page-types.tsmapsconcepts → concept,standards → standard, etc. — but it is currently only used for UI labels.Related second half: "Create Page" + sweep never agree
The same class of problem makes review suggestions repeat.
src/lib/wiki-filename.tsalways appends a timestamp:while
sweepResolvedReviewsresolves amissing-pageitem only on an exact name match (src/lib/sweep-reviews.ts,pageExists→index.byId/index.byTitle). A page created from the suggestion therefore never matches the suggestion that produced it, and the item comes back on the next sweep.I realise #495 already made review IDs content-stable so resolved state survives regeneration — this is the remaining gap: the page the user creates cannot be recognised, independently of how the ID is computed.
Environment / measurements
LLM Wiki v0.6.11, Windows 11, 2,933 markdown files.
type: querysitting in knowledge folders (concepts/55,entities/25,sources/9,playbooks/6,findings/5,standards/3,synthesis/2,comparisons/1), all created by Lint's "Fix".typeto match the folder, those pages rejoined the graph and the isolated-page count dropped sharply.-YYYY-MM-DD-HHMMSSsuffix outsidewiki/queries/, mostly from "Create Page".Proposed fixes
typefrom its destination folder using the existinginferWikiTypeFromPath, falling back toqueryonly forwiki/queries/. One line of intent, and it makes Lint's output consistent with the schema routing the app enforces elsewhere.wiki/queries/regardless of the target's path, sotype: queryis truthful. (Less good: it loses the author's intended location, and the broken link still will not resolve unless the target was single-segment.)slug.mdif it does not exist and only fall back toslug-YYYY-MM-DD-HHMMSS.mdon collision. That alone would letpageExistsrecognise pages created from suggestions.pageExistsstrip a trailing-YYYY-MM-DD(-HHMMSS)before comparing, so existing wikis benefit without a migration.