ADR-025: Wikilinks: [[CODE]] is a typed reference, and typing it changes the rules

Status Active · Filed 2026-08-04 · Issue #9 · Influenced by ADR-005 · ADR-024

Context

The bare-reference scanner is conservative by design: masking rules, an ambiguity heuristic for low #N, prefixes that never match unregistered, and a DP-N spelling it deliberately does not take without a #. Right for prose — a confidently wrong link is worse than a bare code — but it leaves no way for an author to assert a reference the heuristics would pass over, and no syntax familiar to the Obsidian/Roam/wiki muscle memory that types [[…]] reflexively.

ADR-024 made the reference shape general and deliberately unbundled how references are typed. This is that half (#9).

Decision

[[CODE]] and [[CODE|label]] are typed references. The inner text may be anything the machinery can construct a target for, tried in order: a foreign code in any registered shape (ADR-016, ADR-024), a local scheme code — including the bare DP-3 spelling and a document-rendered scheme’s anchor — and an issue number.

The brackets change the rules symmetrically:

  • No heuristics inside. [[#10|10]] needs no cue word — the brackets are the cue. The low-#N ambiguity rule exists to avoid guessing about prose; there is nothing to guess about here.
  • No silence outside. An unresolvable wikilink is a lint violation, not a bare code left alone. This is the one deliberate exception to the invariant that the lint never demands what --fix cannot do (ADR-005) — the author explicitly asked, so the refusal must be explicit too (DP-1). The message names the three likely causes: a typo, an unregistered prefix, a self-link.

Wikilinks are consumed, not rendered. luria link --fix rewrites them into ordinary markdown links — an <a href> inside a raw-HTML block, where markdown wouldn’t render — and the committed source contains no brackets. GitHub renders [[…]] as literal text, and sources are read directly wherever views aren’t generated (the decisions, every fragment), so leaving the syntax in place would trade a moment of authoring convenience for a permanently broken reading surface.

One masking rule keeps the checks disjoint: a wikilink’s span is masked from the prose scanner, so [[ADR-013]] is one demand (the wikilink check’s), never two. A wikilink in backticks is a quoted specimen, as everywhere else.

Alternatives considered

  • Expand at view-generation time (leave [[…]] in sources, render on assembly). Fails exactly where the record lives: decision files and journal entries are read in place, arrived at by link, and GitHub shows them with literal brackets. The collected/generated split (ADR-012) doesn’t help — sources are a reading surface here, per the read/write boundary’s own rule that a source arrived at by link is the reading experience (ADR-021).
  • Make the prose scanner more aggressive instead. The heuristics exist because prose is full of code-shaped non-references; loosening them trades a typed opt-in for a global increase in wrong links. The brackets are consent, per reference.
  • [[target|label]] deferred. Considered and kept — it is one optional group in the regex and the label slot is where half the value lives (citing a paper by name rather than by its arxiv id).

Consequences

  • The authoring loop for any reference becomes: type [[X]], run luria link --fix (or let the lint remind you), commit plain markdown.
  • A lingering [[X]] in a merged file is always a violation — either fix the code or register the prefix; there is no acknowledged state for a broken explicit reference, unlike url-ok’s domain where the target is hand-chosen but valid.
  • The fixer’s rewrite count includes expansions, so luria link reports them like any other fix.