Reference · miadi-chronicle:

The Chronicle, Addressed

An episode is a folder on a disk, a room on three fronts, and a node on the medicine wheel. miadi-chronicle:311 is the name of that one thing — host-free, so the same reference reads correctly from this host, from the tailnet, or from the public front. One resolver turns it into every door it opens, and the terminal, the HTTP route and article prose all ask that same resolver rather than each keeping a parser of its own.

packages/inquiry-weave/src/chronicle-dsl.ts · chronicle-terminal.ts · rispecs/miadi-chronicle-dsl/SPEC.md
Schememiadi-chronicle:
Resolver@miadi/inquiry-weave 0.8.0 (npm)
Specmiadi-chronicle-dsl SPEC v1.1 · SPEC-TERMINAL v1.2
Tests133 in the package
What resolve answers

One reference, every door

inquiry-weave resolve prints the doors as a row of brackets, each its own OSC 8 hyperlink, with the canonical reference visible beside them — the OSC 8 specification says a hyperlink “should not be the only means of figuring out the target”, and there is no way to detect whether a terminal supports one.

$ inquiry-weave resolve "miadi-chronicle:311/services-inventory"

écoute factorisation logiciels — the relational software factory
  [room·local] [room·tailnet] [room·public] [wheel·captures]
  [wheel·graph] [wheel·node] [wheel·relations] [file·inventory]
  <miadi-chronicle:311/services-inventory>
  episode 311 · 2026-08-05-episode-311-coute-… · matched by number
  path: /srv/miadi/episodes/…/services-inventory.json
  modality: relational
open

Where a human click should land — the episode room. An earlier draft returned only the file, and clicking it opened a text editor on raw JSON.

path

The bytes on this host. Local-first is about data ownership and availability, not about presentation — so the two answers are never collapsed into one field.

modality is the third answer, and it is printed on every human-readable run: a discretised harvest report in Fox & Brewer's sense — relational when the reference reached what it named, standalone when an artifact was asked for and not found although the episode resolved. HTTP shipped this field once as RFC 7234's Warning header and RFC 9111 obsoleted it for never being surfaced to users; a modality nobody renders is dead metadata within two releases.

room·local
The episode room on this host — $MIADI_WEB_URL, default http://127.0.0.1:3335.
room·tailnet
The same room over the tailnet — $MIADI_URL_BASE_INTERNAL. Absent when unset; never probed.
room·public
The public front — $MIADI_URL_BASE. The only door that survives being pasted somewhere else.
wheel·node
GET /api/nodes/chronicle:<folder> — the one answer that discriminates.
wheel·graph / wheel·relations
The wheel's own pages. Client-routed: a 200 from either says nothing about existence.
wheel·captures / ·inquiry / ·plans
The wheel API for an artifact kind it serves, keyed by episode_path.
file·<artifact>
The bytes on this disk — the vessel's own file, when the reference names one.
FlagDoes
--jsonThe full result: canonical, resolution, artifact, destinations[], open, shareable, path, modality.
--base local|internal|publicLead with one door. Reorders; never removes one.
--localLead with the file on this disk.
--verifyAsk the wheel whether the episode is really on it.
--rawNo escape sequences — clean capture for scripts and CI.
packages/inquiry-weave/README.md · src/chronicle-terminal.ts
Why it lives in a package

One resolver, three consumers

The parser and resolver moved into @miadi/inquiry-weave — the package that already ships built ESM, a bin, the catalog builder and the root precedence rule — so §7.1 of the spec stops living inside whichever of the three consumers happened to need it first.

Rendering diagram...
The terminal
inquiry-weave resolve <uri>
packages/inquiry-weave/src/chronicle-terminal.ts
The HTTP route
GET /api/chronicle/resolve?uri=<url-encoded>
app/api/chronicle/resolve/route.ts
The articles surface
{{ miadi-chronicle:311/state-machine }} in prose
app/articles/components/Chronicle{Ref,Diagram,Inventory}.tsx
The shape of a reference

Rootless, and why

miadi-chronicle:092/126?view=wheel#scene=rivercanonical

Rootless. This is what every producer emits.

miadi-chronicle://092/126accepted forever

Normalized away on parse. `//` is RFC 3986 §3.2's authority marker, so a conformant parser reads the first segment as a host — new URL("miadi-chronicle://126") yields host "126" and an EMPTY path.

miadi-chronicle:311/tolerated

A trailing slash is an empty final segment in RFC 3986, and people type it by reflex. Refusing it degraded the reference in an article to raw braces with nothing explaining why — earned 2026-08-15 on episode 103.

Producers emit rootless; parsers accept both, forever. The reserved //root@…/ growth slot the spec kept was unreachable while episode data occupied the authority position.

packages/inquiry-weave/src/chronicle-dsl.ts:44
Naming a part of an episode

Artifact segments

A reserved segment in the last position names an artifact inside the episode — and it is a registry, not a constant compared by ===. The tail is stripped before the episode is matched, so the reference resolves its episode either way. mc.show= is the second, independent trigger; the segment wins when the two disagree.

SegmentKindServed byNote
services-inventoryinventorythe vesselservices-inventory.json — an episode's running world.
state-machinestate-machinethe vesselThe diagrams/ convention smcraft's rispec 78 calls proven, falling back to smdf_files in services-inventory.json.
capturescapturesthe medicine wheelGET /api/captures?episode_path=<folder>
recordingscapturesthe medicine wheelDeprecated alias on the wheel — same records, older name.
inquiryinquirythe medicine wheelGET /api/inquiry-weaves?episode_path=<folder>
plansplansthe medicine wheelGET /api/plan-perspectives?episode_path=<folder>
The number is a nickname; the folder name is the key
Every wheel-backed kind is keyed by episode_path — the full folder name. Measured 2026-08-16: ?episode_number=320 returns 0 records for an episode whose ?episode_path=<folder> returns 1, because the records carry no episode_number field and the filter compares strictly.
packages/inquiry-weave/src/chronicle-dsl.ts:52
Addressing inside the episode

Which fragments are spellable

#state= · #event=spellable

State names are unique tree-wide (SMDF's V002), so they survive structural motion — a sibling insert cannot retarget them.

#transition= · #parameter= · #action= · #source=not spellable

Addressed positionally. A sibling insert silently retargets the reference, and silence is the defect.

Name-keyed fragments are durable against structural motion and fragile against rename: SMDF's V002 gives uniqueness at a point in time, not immutability. The rename policy is named and pending (alias-table-pending) rather than assumed away.

packages/inquiry-weave/src/chronicle-dsl.ts:238 · SPEC-TERMINAL.md §4.3a
Why --verify exists

A 200 proves nothing

The wheel's /graph, /nodes and /relations pages all begin "use client", and so does forgewright's chronicle view. The HTML shell is byte-identical for any parameter — focus happens in the browser, after it fetches /api/nodes. Measured 2026-08-16: ?episode=9999-99-99-episode-000-nope answers 200. Two services, two codebases, one trap.

Only GET /api/nodes/<id> discriminates — it returns the node or a real 404. That is what --verify asks, and it stays opt-in because it is a network call: a resolution answered from the catalog on disk is already true about the disk. Both answers are real, and they can disagree.

Unreachable is not absent. A wheel that cannot be asked has not said no — the verdict carries the error rather than reporting the episode missing.

packages/inquiry-weave/src/chronicle-terminal.ts:388
In the terminal

Clickable references: desktop, Terminator, tmux

sudo apt install miadi-terminal
miadi-terminal front https://<your Miadi>   # when MIADI_URL_BASE is not already it
miadi-terminal enable                       # per user: desktop, terminator, tmux
/usr/bin/miadi-chronicle-open
Turns a reference into <front>/api/chronicle/open?uri=… — the server resolves it, the client never does.
/usr/share/applications/miadi-chronicle-open.desktop
desktop: the miadi-chronicle: scheme handler, reached by OSC 8 links in any terminal and by links in a page.
/usr/share/miadi-terminal/terminator/miadi_chronicle_url_handler.py
terminator: the URL handler, linked into Terminator's plugin directory. Enabling adds it to enabled_plugins, after a backup.
/usr/share/miadi-terminal/tmux/miadi-chronicle.conf
tmux: a click (a tap, on Termux) on a reference opens it. Enabling adds one source-file line to your tmux config.

Restart Terminator, then Ctrl+click a miadi-chronicle: reference anywhere in its output. In tmux, a click on the reference opens it, with set -g mouse on; on Termux that is a tap, from the Termux build of the same package. miadi-terminal status says what a click opens here, miadi-terminal disable reverses it. Running enable twice is safe.

Rendering diagram...
Why a plugin when OSC 8 exists

An OSC 8 hyperlink calls open_url(prepare=False) and goes straight to xdg-open; only a regex match calls prepare=True, the sole path that consults url_handler plugins. The plugin covers what OSC 8 structurally cannot: a bare reference in output that knows nothing about miadi.

Why the server resolves

A click builds <front>/api/chronicle/open?uri=… and the browser follows the server's redirect to the room. The client holds no catalog and runs no node, so the same click works on a laptop, on a phone and on the host itself. The front is MIADI_CHRONICLE_OPEN_URL, else MIADI_URL_BASE, read through miadi-config at click time — nothing is baked in at install.

jgwill/miadi-orchestration-kit packages/miadi/deb/miadi-terminal · SPEC-TERMINAL.md §3
In the browser

The same reference, in prose and over HTTP

GET /api/chronicle/resolve?uri=<url-encoded> — the whole URI travels url-encoded so its #fragment survives HTTP. A parseable-but-unknown episode is a 200 with resolved:false: a broken reference is data, not a server error. Missing or invalid input is a 400 carrying a usage document, so the endpoint describes itself.

In an article, the same reference written as a directive — {{ miadi-chronicle:311/state-machine }} — renders as a chip, a diagram card, or an inventory, resolved server-side. The + chronicle ref helper in the article editor drops the directive for you.

A missing diagram renders as an invitation rather than an error, and an artifact reference answers {kind, name, path, exists} — resolve, then hand the path to an editor or a canvas.
app/api/chronicle/resolve/route.ts · app/articles/components/ChronicleDiagram.tsx
Where to look next

Two doors