cc-libs/docs/adrs/adr-0013-markdown-link-syntax-for-cross-references.md

2.9 KiB

ADR 0013: Cross-reference Markdown Files With []() Syntax

Status

Accepted

Date

2026-06-09

Context

ADR-0012 and the broader docs/ tree increasingly cross-reference each other, and ADRs reference one another by number. We recently wired lychee into just check (see the lint-markdown recipe in Justfile) so broken local links fail the build. Lychee, however, only validates links it can see: a bare prose mention of docs/foo.md or ADR-0005, or a backticked path like `docs/foo.md`, is invisible to it. When a doc is renamed or moved, those mentions silently rot until a human happens to read the surrounding paragraph.

We want renames to break the build, not the docs.

Decision

In every markdown file in the repository, references to other .md files must use markdown link syntax [text](relative/path.md). This includes:

  • Direct file references (`docs/install-craftos-pc.md`[`docs/install-craftos-pc.md`](docs/install-craftos-pc.md)).
  • ADR-number references (ADR-0005[ADR-0005](docs/adrs/adr-0005-craftos-pc-harness.md), with the path adjusted to be relative to the referencing file).
  • Plain-prose mentions (called out in CLAUDE.mdcalled out in [CLAUDE.md](../../CLAUDE.md)).

Excluded by design:

  • Mentions inside fenced code blocks. They are example/code content, not cross-references, and lychee.toml already skips them via include_verbatim = false.
  • Mentions inside inline code spans used purely to illustrate the wrong form (as in this ADR's examples above). The reader can see they are placeholders, and lychee does not extract them as links either.
  • A file's own title (e.g. # CLAUDE.md as a heading is not a reference).

Link paths are written relative to the file containing the link, so that lychee --offline resolves them on the local filesystem with no --base indirection.

Consequences

  • just lint-markdown (and therefore just check, pre-commit, and pre-push via ADR-0011) catches dead cross-references the moment a doc is moved or renamed.
  • The convention is social — humans and agents must remember to apply it when writing prose. Lychee enforces correctness only once a link exists; it cannot flag a mention that should have been a link but wasn't.
  • The [path](path) style (backticked path as link text) is preferred for direct file references, matching the existing house style in docs/README.md and docs/adrs/README.md. For ADR mentions in flowing prose, [ADR-####](path) reads better than the backticked form.

Future Work

  • If rot reappears anyway, add a small grep-based lint that flags unbracketed .md and ADR-#### mentions and wire it into just check. Deferred until there is evidence the social convention is insufficient.