Component: tools/luhmann/ — luhmann lint subcommand
Severity: Low (cosmetic — no incorrect data, just noise)
Impact: Across a 26-note batch, ~8 false-positive FAILs per note (≈200 total) drowned out any real lint findings. Subagents wasted tool calls verifying
each "dangling" target on disk to confirm it actually existed.
Behavior
The linter treats Obsidian-style aliased wiki-links as dangling when the target file exists.
Example: A note containing:
This relies on [[sanity-perspectives-let-one-dataset-serve-many-query-time-views|perspectives]].
…where notes/sanity-perspectives-let-one-dataset-serve-many-query-time-views.md exists on disk.
Expected: PASS — target file exists.
Actual: FAIL — "dangling wiki-link" reported for the full string sanity-perspectives-let-one-dataset-serve-many-query-time-views|perspectives.
Root cause (hypothesis)
The link-extraction regex appears to capture everything between [[ and ]] and pass that as the lookup key, rather than splitting on | first and using
only the pre-pipe portion as the filename. So [[target|display]] is looked up as target|display.md, which never exists.
Reproduction
- In any note in the vault, write [[draft-and-published-are-document-properties-not-environment-properties-in-modern-cmses|the per-doc draft model]]
(target exists).
- Run luhmann lint .
- Observe a "dangling wiki-link" FAIL listing the entire target|alias string.
Suggested fix
Where wiki-links are extracted (likely a regex like [[([^\]]+)]]), post-process the capture:
let target = capture.split('|').next().unwrap().trim();
Then resolve notes/{target}.md against the filesystem. The display alias is informational and should be ignored by the linter.
Adjacent observations
- The source: frontmatter field intentionally points to documents in inbox/ (e.g., PDFs), not to .md notes. Lint currently flags these as dangling too.
Worth either excluding the source: field from link validation or resolving it against inbox/**/* in addition to notes/.
- The aliased-link syntax is used heavily across the existing vault — fixing this single bug likely silences the vast majority of current lint noise.
Pipeline-level workaround (already in place)
Subagents have been instructed to tolerate "dangling" FAILs that match the piped pattern after verifying the target exists. This works but is wasteful —
each subagent re-derives this every run.
Component: tools/luhmann/ — luhmann lint subcommand
Severity: Low (cosmetic — no incorrect data, just noise)
Impact: Across a 26-note batch, ~8 false-positive FAILs per note (≈200 total) drowned out any real lint findings. Subagents wasted tool calls verifying
each "dangling" target on disk to confirm it actually existed.
Behavior
The linter treats Obsidian-style aliased wiki-links as dangling when the target file exists.
Example: A note containing:
This relies on [[sanity-perspectives-let-one-dataset-serve-many-query-time-views|perspectives]].
…where notes/sanity-perspectives-let-one-dataset-serve-many-query-time-views.md exists on disk.
Expected: PASS — target file exists.
Actual: FAIL — "dangling wiki-link" reported for the full string sanity-perspectives-let-one-dataset-serve-many-query-time-views|perspectives.
Root cause (hypothesis)
The link-extraction regex appears to capture everything between [[ and ]] and pass that as the lookup key, rather than splitting on | first and using
only the pre-pipe portion as the filename. So [[target|display]] is looked up as target|display.md, which never exists.
Reproduction
(target exists).
Suggested fix
Where wiki-links are extracted (likely a regex like [[([^\]]+)]]), post-process the capture:
let target = capture.split('|').next().unwrap().trim();
Then resolve notes/{target}.md against the filesystem. The display alias is informational and should be ignored by the linter.
Adjacent observations
Worth either excluding the source: field from link validation or resolving it against inbox/**/* in addition to notes/.
Pipeline-level workaround (already in place)
Subagents have been instructed to tolerate "dangling" FAILs that match the piped pattern after verifying the target exists. This works but is wasteful —
each subagent re-derives this every run.