10a. Markdown Documents
A description (Chapter 10) is flavored markdown attached to a declaration. An .md file is the same flavored markdown standing on its own — a native architecture document, not an opaque attachment. It renders with the same dialect: the [[…]] cross-references, aspect references, section references, foreign value getters, and backlinks you already know from descriptions, over the same core resolver. A design doc, a runbook, an onboarding guide, an ADR — write it in .md, drop it in the workspace, and it links straight into the model.
# Payments Platform
The [[Payments]] service authorizes and captures card payments. It runs in[[@@security-zone:pci]] and publishes events consumed by [[Orders]] and[[Notifications]]. On-call rotation is owned by [[#pay001]]@@team.
See [[Payments#compliance]] for the PCI scope.Every [[…]] here is a live link into the canonical model: [[Payments]] resolves to the module, [[@@security-zone:pci]] to the aspect overlay, [[#pay001]]@@team reads the team aspect off the referenced node, and [[Payments#compliance]] jumps to a section.
The hard constraint: .md cannot create model
Section titled “The hard constraint: .md cannot create model”Rule. A markdown document references and renders existing model; it never defines it. The
.archfiles remain the single source of truth.
This is the line that keeps documentation from quietly becoming a second, conflicting source of architecture. An .md can point at [[Payments]], embed a snippet, quote an aspect — but it cannot bring a Payments module into existence, set a field on it, or wire an edge. If it isn’t in an .arch file, it isn’t canonical. Markdown is a lens on the model, never the model.
Two ways a document participates
Section titled “Two ways a document participates”Bidirectional linking. A document references model elements with [[…]], and an .arch element (or its description) can link back out to a document — and to a #section inside it:
service Payments { docs.design: "platform-overview.md" "Full design rationale in [[platform-overview]]; PCI details in [[platform-overview#compliance]]."}The backlink index (“mentioned in”, below) spans both surfaces, so you can navigate .arch → .md and .md → .arch from either side.
Inline self-contained snippets. A fenced ```arch block holds a throwaway draft diagram — its own independent, self-contained model that is not part of the workspace’s canonical model:
Here's the shape we're proposing:
```archservice Gateway { > Payments > Orders}```That snippet renders live — a real diagram, not a screenshot — but defines nothing canonical, so the hard constraint still holds. It’s perfect for an RFC or a design doc where you want to sketch an idea without touching the real workspace. (Embedding a live view of the real model in a document is not available yet — it depends on view maturity. A self-contained snippet, being independent of the canonical model, is the supported inline form.)
The flavored-markdown dialect
Section titled “The flavored-markdown dialect”.md files use the exact dialect from Chapter 10 — the same CommonMark subset plus the archlang [[…]] extensions:
| Form | Links to |
|---|---|
[[#id]] / [[Name]] | a declaration (by stable ID or name) |
[[@@key]] / [[@@key:value]] | an aspect plane, or a specific aspect on it |
[[Doc#section]] | a #-header inside an .md document |
[[ref]]@@aspectPath | an aspect value read off the referenced node |
One form behaves differently in a document than in a description:
Rule. Bare
@@aspectPathinterpolation is description-only. A standalone.mdhas no owning node, so a bare@@in a document is an error. To read an aspect inside a document, use the explicit[[ref]]@@aspectPathform, which supplies its own context — it’s the only interpolation available in.md.
So a description on Payments can write @@team, but platform-overview.md must write [[Payments]]@@team. The composed form (a cross-reference plus the value getter) is one mechanism built from two pieces you already have, not new syntax — and it works everywhere, including back in descriptions.
Backlinks (“mentioned in”)
Section titled “Backlinks (“mentioned in”)”Every element maintains an automatic reverse index of all [[…]] references pointing at it, across both descriptions and .md documents. Open Payments and tooling shows everywhere it’s discussed — the design doc, the runbook, another service’s description — so you navigate from a declaration to its whole conversation without grepping.
Resolution scope
Section titled “Resolution scope”A document’s bare names ([[Payments]]) resolve against a package/space, the same as any reference. The scope is taken from the .md frontmatter when present, falling back to the file’s location in the workspace tree. Stable-ID references ([[#id]]) resolve regardless of scope.
Summary
Section titled “Summary”.mdfiles are a first-class archspace surface, rendered with the same flavored markdown as descriptions.- A document references and renders model — it can never create canonical model;
.archstays the source of truth. - It participates two ways: bidirectional
[[…]]linking (.arch↔.md, including#section) and inline self-contained```archsnippets (throwaway, non-canonical, rendered live). - Bare
@@aspectPathis description-only; in a document use the explicit[[ref]]@@aspectPathgetter. - Backlinks span both surfaces, so “mentioned in” reaches descriptions and documents alike.
What’s next
Section titled “What’s next”Chapter 11: The Standard Library → — from bare types to service, command, event, and the rest of the stdlib vocabulary.