sprig and prose docs classic docs
Reference› ADRs› ADR017 LinksInDescribe

ADR017 LinksInDescribe

Title: Links in describe

  • Status: Accepted
  • Decided: D2026-08-24
  • Follows: ADR015 MarkdownInDescribe
  • Affects: Describe, Parser, Relates
  • Pairings:
    • Document — While links in describe were rejected as a feature, there may be a prose-native way to accomplish the same tasks that could normally be done in markdown.

Context

Links in describe are an obvious want. An author writing about a concept already wants to send a reader to an external URL, or to another concept in the same universe. 015 had just named lists and emphasis as the marks that still read as prose, and left them open as a possible editorial syntax. Markdown links look like the next piece of that syntax: [label](url) sits in the same family as *emphasis* and a hyphen list.

They are not the same family. Lists and emphasis, ignored as markup, are still readable sentences. A markdown link, rendered as itself, is punctuation around a hidden destination. Rendered as a link, it is a word that goes somewhere the sentence does not say. Either way the reader of the source, or of a plain-text consumer, is worse off than if the URL had been written as a URL. That is the opposite of editorial syntax, which is supposed to survive being ignored.

Internal links have a different problem, and it is not mechanical. A prose-first form such as @ConceptName reads cleanly, and a consumer of the manifest could turn it into a jump. The cost is meaning. An easy mention of another concept records that the two names occurred near each other. It does not record why. Prose already has a place for that: a relates block, which names the edge and can itself be described. A describe-local link would compete with that place, and the weaker record would be the one that is easier to type.

What remains is the external URL that should be readable as something other than itself, and the documentation-shaped need to point at a page. Those are the jobs a dedicated link form could do inside a document block — the same Candidate syntax Document in universe/prose.prose that 015 pointed at for code and embedded concepts. Describe is not that layer.

Decision

Describe has no link feature. Not markdown links, not an @-reference to a concept.

External URLs, if they appear in describe, are written as themselves. A connection between two concepts is a relates. Readable external references, if they become a language feature, belong on a document block as a dedicated link form, not in describe.

Consequences

Authoring. Pointing at a URL means writing the URL. Connecting two ideas means writing a relates and, if the connection needs explaining, describing that. Describe stays a statement about this concept, not a web of unmarked jumps.

Cost. Describe cannot send a reader to another page or another concept in one gesture. Navigation is graph-shaped, or it is a raw URL in a paragraph. That is clumsier than markdown. It is also the cost of keeping the graph as the place relationships live. Authors who would have written see @Literals have to write a relates instead, or write the name as a name and accept that it will not jump.

Relates carries the meaning. @ConceptName in a paragraph says this mentions that. A relates says what the mention is, and the describe on that relates can say why. The first is easy to write and easy to lose. The second is the record. Losing the information between the concept being described and the concept being linked to is the failure this decision exists to prevent.

What this does not do. It does not stop a consumer from noticing a URL in describe and making that span clickable. The URL is still the text, which is the verbatim rule 016 settled six days later. It does not stop a consumer from matching a name it recognises. It refuses to make either of those a language feature, because a language feature is a promise that the mention is a relationship, and a mention is not.

Document. A link block inside a document block is the named home for external references that need to be more readable than a raw URL. Document is still Candidate. Until it exists, describe does not grow a substitute.

Alternatives considered

Markdown links as editorial syntax. [label](url) next to lists and emphasis, interpreted by the same consumers 016 already permits. Rejected. Unlike those marks, a markdown link is not friendly when rendered directly, and when it is rendered as a link it hides the destination behind other words. Editorial syntax has to remain readable as prose. This does not.

A prose-first @ConceptName (or similar) for internal jumps. Readable, cheap to scan for, and a consumer could decide what to do with it. Rejected, and not for mechanics. An easy link to a concept loses the information between the two. The better description of that fact is a relates, where the relationship is preserved and can be described. Shipping @ would teach authors to skip that.

Auto-link any recognised concept name that appears in describe. No marker, no extra syntax. Rejected for the same meaning reason as @, and more so: the author did not even mark a mention, so a homonym, an example identifier, or a word that happens to be a concept name becomes a relationship the graph did not assert.

Markdown links for external URLs only; keep internal connections as relates. A split that looks tidy. Rejected on the external half. A verbatim URL is already a link a consumer can make clickable without hiding anything. The markdown form's only extra is a label that is not the URL, which is the unreadability this record refuses. The internal half already has relates.

A link block inside describe itself. Describe would grow a structured slot for references. Rejected. That is the documentation surface 015 refused to let describe become. The document block is the layer above describe for work describe cannot do. Putting the slot in describe would make Document unnecessary for the one case that most invites it.

Evidence

Even the consumer that went furthest toward markdown-lite does not interpret links. parseMarkdownLite in packages/sprig-ui/src/lib/components/Prose.svelte handles unordered lists, ordered lists, and paragraphs. It does not recognise [label](url) or @Name. Lists were treated as obvious. Links were not.

Authors already write the @ form as ordinary text, and the language leaves it as text. adr TemporalDimensions in universe/adr.prose says "You can read more about that in @Literals." The compiled describe in universe/.sprig/manifest.json holds those characters. No edge is created from the mention; the actual connection is the follows { Literals } assertion on that concept. That is the distinction this record is protecting.

syntax Document in universe/prose.prose is Candidate, and this record is already related to Prose.Document for the same reason 015 is: links in describe were refused as a feature, and a prose-native block is the remaining way to do the work a markdown link would have done.