Guided Stories
Chapter 8 gave you a curated projection: the right nodes, grouped and styled for one audience. A projection is still a picture, and a picture answers “what is there” — not “how do I read this”. The person who drew it fills that gap by talking over it, and when they leave, the gap comes back.
A story closes it in the model. It is an ordered walk over what the view already draws — the construct that makes an architecture explainable rather than merely correct.
view PaymentsStory { show @@team:"payments" story { chapter "Order comes in" { "A customer hits the storefront; an order is created." Web, Checkout, Orders } chapter "Money moves" { "Payments charges the card, then Ledger records it." Payments, Bank, Ledger } }}That is the whole authored surface. Titles, an optional note, and an ordered list of nodes — deliberately nothing else.
Declaring a story changes nothing
Section titled “Declaring a story changes nothing”Read that heading literally. A story clause does not restyle the board, does not reorder it, does not filter it. Open PaymentsStory normally and you get exactly the board show @@team:"payments" describes, as though the clause were not there.
The story is inert until the viewer is asked to present it, with ?present=1 on the URL (?play=1 autoplays and implies it). This is the point of the design: a story is a reading of a view, so declaring one never costs the ordinary reader anything. See Present mode below.
What you write
Section titled “What you write”chapter "Title" { … } — at most five
Section titled “chapter "Title" { … } — at most five”The five-chapter cap is a hard grammar rule, not a style guideline. A story is a walk a reader holds in their head, and the entire claim of the construct is that the authored part stays small enough to be worth reviewing. A sixth chapter raises a diagnostic and is dropped.
The note is the chapter’s leading string
Section titled “The note is the chapter’s leading string”chapter "Money moves" { "Payments charges the card, then Ledger records it." Payments, Bank, Ledger}It is optional, and it obeys the same law module and view descriptions do (Chapter 10): the string comes first, before anything else in the body. A string written after the nodes is a diagnostic rather than a silent append — it reads like a per-node caption, and a chapter has no slot for one.
Then the nodes, in order
Section titled “Then the nodes, in order”Nodes are separated by commas or newlines, and any node selector works (Chapter 31) — not just a bare name:
chapter "Everything the gateway fronts" { PaymentGateway, @@zone:"dmz", nodes of (PaymentGateway > *)}Order is the meaning. Consecutive nodes are what a beat is derived from, so the written order is the narration’s order. Within one selector that resolves to several nodes, order is the deterministic ascending key. A node named twice in one chapter appears once, where it was first introduced.
What is derived
Section titled “What is derived”Everything that isn’t in the list above. You never write a beat, a transition sentence, or a camera move:
| Derived | From |
|---|---|
| beats | each consecutive pair of nodes |
| the relation each beat crosses | calls / called by / mutual / contains / contained in / reaches-in-N-hops / unrelated — most specific first, so a direct call is never reported as a 1-hop reach |
| the sentence per beat | the relation plus the interfaces it goes through |
| the camera’s follow window | the node just left, the node in hand, the node coming up (≤3) |
| the chapter handoff | a stay / enter / leave set diff against the previous chapter |
This is why a story survives a refactor. Move a call from Payments to a new Settlements module and the beat’s sentence changes with the model, because the sentence was never text you typed.
Narration deliberately does not claim whether a call is sync or async. That is not a property of the edge — it’s a stdlib widget-field convention on the target interface’s type chain (Chapter 11) — so stating it would be a guess.
A chapter only walks what the view draws
Section titled “A chapter only walks what the view draws”The story rides on the view’s selection; it never widens it. A chapter that selects something outside show keeps the rest of its nodes, and a chapter left with nothing at all is dropped with a diagnostic.
The practical consequence: when a chapter needs an anchor from another domain, show it explicitly.
view PaymentJourney { "How money actually moves through the system." show @@domain:"Payments" or @@domain:"Orders" // The gateway and the ledger anchor the first and last chapters but live // in other domains — a chapter can only walk what the view DRAWS. show APIGateway or Ledger story { chapter "An order arrives" { "Traffic lands on the gateway and becomes an order." APIGateway, Orders } chapter "Money moves" { "The order asks Payments to charge; the gateway routes it out." Orders, Payments, PaymentGateway } chapter "The outside world" { "Only the gateway talks to the processors — everything else is internal." PaymentGateway, Stripe } chapter "And it is written down" { "Every movement lands in the ledger, which nothing else calls." Payments, Ledger } }}A story is not a representation
Section titled “A story is not a representation”A view carries at most one representation clause — table, matrix, grid, flow — and the board is the absence of one (Chapter 8). A story does not compete for that slot. It rides on whatever the view already is, so it composes with any of them.
Two constraints do apply:
- Not with
focus. A standingfocusand a story both claim the emphasis channel, and composition intersects — a chapter intersected with afocuscollapses to a near-empty board. Nothing stops you writing both; the result is simply a story not worth presenting, so pick one. - One per view. A view instance (Chapter 8) may not add a second
storyon top of its parent’s. The instance’s own wins, with a diagnostic.
Present mode
Section titled “Present mode”?present=1 is a link you hand to someone — that is the whole shape of the feature:
- The reader’s position lives in the URL fragment as
#beat=<chapter>.<stop>, so any stop is a link a review comment can point at. ?play=1autoplays and implies?present=1.- While a story runs it takes the emphasis channel outright: the chapter’s nodes are the figure, everything else is ground.
- Present mode shows the view you are already on when that view has a story, and otherwise opens the first view that declares one — a presentation link has to work for someone who has never opened the workspace, and present mode hides the navigation they would otherwise use to find it. It steers once: stepping to another tab mid-talk leaves you there.
The parameters go on whatever surface is hosting the viewer — an embedded <archlang-viewer> (Chapter 23), a archlang serve session, or an exported single-file HTML bundle (Chapter 21).
When to write one
Section titled “When to write one”- Onboarding. The walk a senior engineer gives a new hire at a whiteboard, written down once and kept true by the compiler.
- Review and design docs. A
#beat=link is a citation: “this is the hop I’m objecting to”, pinned to a stop rather than a screenshot. - The talk you give twice. If you have explained the same diagram in the same order more than once, that order is a story and belongs in the model.
Do not reach for one to work around a busy board. If the picture needs a story to be legible at all, the fix is a narrower show — a story explains a readable view, it does not rescue an unreadable one.