ADR 0005 — The Reading Room: spatial trails over temporal history
Status: accepted (2026-06-12; agent-symmetry amendment same day). Locks the invariants of the Reading Room redesign. Full design + phasing in /plans/reading-room.md; this records what is decided and why.
Context
Linear back/forward history forces readers to rebuild branching context in their heads on every pop — the tax this design removes. The library becomes a digital universe library: a Tufte-styled reading column with a working margin, stacked panes holding the reasoning path, status as trust signal, lateral movement by tag and link. Content is agent-maintained: agents are first-class writers and consumers of everything the room shows.
Decisions (locked)
- The trail is spatial, single-path, and server-owned. The stack is always one path root→focus, encoded in the URL as ordered path segments (depth cap 10). The server renders the whole canvas from the URL; every link is rendered already carrying its post-click trail URL. No client state — ADR 0003 rule 3 holds. Browser back/forward = temporal history over spatial states.
- Truncate-and-append. A click in pane N discards panes right of N and appends the target. A target already on the path is focused, never duplicated. The stack is a reasoning path, NOT a browsing history.
- Canvas scrolls; panes never resize to fit. Left panes collapse to
spines (title + status badge); focused pane + parent render full; only
the focused pane shows its margin.
overscroll-behavior-x: contain(macOS swipe-back). External links leave the graph via the browser — never a pane. - Everything navigational joins the trail as a pane. The card catalog (tag pages, lookup) is a pane; the graph view is a pane; the universe view/floor is pane zero. Nothing navigational breaks the reader out of context — it adds into it.
- No global search box. Lookup survives as the catalog pane: tag clicks
and a filter input inside that pane (
mark_lookupunderneath). No sidebar file tree, no comments/reactions, no WYSIWYG. - Status is the trust signal. Badge at margin top. Authority order:
demarkus metadata tag axis (
status:draft|wip|accepted|archived) first, body-frontmatterstatus:key as fallback, absent ⇒ rendered as draft (unlabeled reads as untrusted — the correct failure mode). - Frontmatter is parsed and rendered friendly, never raw. The strip stays for the body; the parsed keys render into the margin's document-properties block. demarkus out-of-band metadata remains the authoritative catalog channel.
- The margin holds exactly: status, tags, provenance (modified / version / agent — from response metadata), canonical mark:// address + raw-source escape (decision 12), backlinks (R3), document properties (parsed frontmatter), and position-anchored sidenotes (footnote syntax → server-side AST transform → margin spans; degrades to footnotes). An empty margin is correct.
- Rendered-HTML cache is a hard requirement of the trail engine — keyed (world, path, version). A trail click fetches only the new document; everything else re-renders from cache. Without it an N-pane trail costs N reads per click and 429s against the broker budget.
- Desktop only.
Agent symmetry (amendment, 2026-06-12)
The room is human-facing but the universe is agent-maintained. These hold for every current and future feature:
- The room is a projection, never a source. No information may exist only in the rendered layer. Every visual affordance derives from something an agent can read AND write via MCP: sidenotes ⇄ footnote syntax, status badge ⇄ metadata tag axis, properties ⇄ frontmatter, backlinks ⇄ the graph, trails ⇄ the URL format. A feature that would require HTML-only state is rejected or redesigned.
- Every pane escapes to protocol. The margin's provenance block
carries the document's canonical
mark://address and a raw-source view. The projection is always one click from the real thing. - The authoring contract is published in-universe — a style document
agents fetch (agent-manifest/
mark_discoverterritory) defining what the room rewards: footnote→sidenote behavior, the status-axis vocabulary, alert/mermaid/KaTeX syntax, tag conventions. A publishing agent targets the room without ever seeing it. - Trail URLs are a documented, stable, constructible format. Agents mint trails (hand a human their reasoning chain, reconstructed on screen pane by pane) and parse trails (load a human's shared trail as reading context). The trail is the serialized context object both species produce and consume.
- The Phase 4 librarian consumes the trail as context. The librarian joins the canvas as a pane and sees the current stack as its context — "ask about this trail" needs no prompt assembly; the URL is the context spec.
Consequences
- Implementation stays htmx-hard / no-build: server-rendered panes + CSS; hover previews are plain htmx fragments; the only new JS is a scroll-focused-pane-into-view snippet riding islands.js.
- The graph/universe view will likely exercise ADR 0003's pre-agreed canvas island concession — research first (what universe-scale graph rendering should be; record findings in the plan before building).
- Phasing R1 (Tufte pane) → R2 (trail engine) → R3 (previews + backlinks + graph pane); universe view research runs alongside. The authoring contract (13) ships with R1 — the room's conventions exist the moment the room renders them. Trail format documentation (14) ships with R2.
- The nav bar's current global search form is removed in R1.