Chronicle · the attention loop

What Needs a Human

Agents reach questions only a human can answer — a name to rule, a consent to give, a direction to pick. The requirement is one sentence: those questions are stored inside the chronicle, and a surface renders them. No terminal, no raw markdown file. An episode folder carries an attention.json; the board on /chronicle is the first thing the human meets, and the room now lets that human review context and answer in place.

packages/episodic-memory-schema/src/attention.ts · app/chronicle/lib/attention.ts
Storeattention.json at an episode folder's root
Contract@miadi/episodic-memory-schema 0.8.0
Verbspassages attention add · answer · list · sync
Schemachronicle.attention.v1
Human UI@miadi/attention-ui 0.1.2
Agent UIinquiry-weave-mcp · list · get · answer
The shape of it

One file, three doors, one answer transaction

Rendering diagram...
The file is authoritative
A wheel outage never rolls back the human's question: the write lands, the receipt records pending loudly, and attention sync is the redemption path. A malformed existing store refuses the write — never write over a store you could not read.
The store

attention.json, field by field

{
  "attention": 1,
  "items": [
    {
      "id": "d1-consent-render",
      "question": "Answer ep300's consent question — may the film render?",
      "unlocks": "the eury render (issue draft ready in the vessel), and the
                  first true visual-music object",
      "asked": "2026-08-15",
      "state": "open",
      "answer": null,
      "answered_at": null,
      "depth": [
        "2026-07-27-episode-300-from-shadow-to-song/film/consent.md",
        "ep332 vessel: DRAFT-mightyeagle-render-issue.md"
      ]
    }
  ]
}

The first store, transcribed from episode 332 — six open items on the day the loop shipped, one line wrapped here to fit the page.

FieldRequiredIs
idrequiredStable per-episode identity, e.g. d1-consent-render.
questionrequiredOne line: what is asked of the human.
unlocksoptionalWhat answering it releases — why this one is worth a minute.
askedoptionalISO date the question was raised. The board sorts newest-asked first.
staterequired"open" or "answered". Anything else reads as open.
answeroptionalThe human's word, once given.
answered_atoptionalWhen it was given.
depthoptionalWhere the full record lives — paths, owner/repo#n refs, chart ids.

Reading is tolerant but never silent: an item missing id or question is dropped, and a store that cannot be parsed at all returns its parse error alongside an empty list — so an empty answer stays distinguishable from a failed look.

packages/episodic-memory-schema/src/attention.ts:22
Where it shows

The board, and the room

/chronicle — the board

Every open item across the chronicle, newest-asked first, above the explorer. Each row carries its question, what it unlocks, its episode, and links into that room. A quiet board renders nothing at all — an empty statement is still a true one.

/chronicle/<episode> — the room

Open items render first and stay actionable. Answered decisions live under History; when 0 remain open, the entire surface becomes one quiet completion row with the full decision record available on demand.

Existence is checked per folder before anything is read, so a 175-episode chronicle costs 175 stats rather than 175 reads.

packages/attention-ui/src/attention-panel.tsx · app/chronicle/components/EpisodeAttention.tsx
Human and agent doors

The question can now be pulled, discussed, and answered

Reusable React

@miadi/attention-ui accepts items and an explicit answer or read-only interaction. It owns no route or credential, so another page can reuse the same open/history/context surface safely.

Public Read · Gated Answer

GET /api/chronicle/attention is public testimony. It reports answer capability so the room renders honestly. POST still requires loopback, an allowlisted TailScale human, or the writer token; a public reader sees no answer form.

Agent MCP

chronicle_attention_list, _get, and _answer let an agent carry the same item through a discussion.

pnpm add @miadi/attention-ui

import { AttentionPanel } from "@miadi/attention-ui"
import "@miadi/attention-ui/styles.css"

// A public host may render the same record without a write door:
<AttentionPanel items={items} interaction="read-only" />

API, MCP, and passages attention answer converge on answerChronicleAttention. A caller supplies episode + item identity, never a filesystem path; malformed, already-answered, empty, concurrent, and episode-escaping writes refuse.

packages/attention-ui/src/attention-panel.tsx · attention-panel.css · packages/inquiry-weave/src/attention.ts · packages/inquiry-weave/src/mcp-server.ts · app/api/chronicle/attention/route.ts
Honesty on the surface

The badge that shows a disagreement

Two surfaces read two different sources: this app reads the file, forgewright reads the wheel. They can disagree, and the disagreement is exactly what a reader needs to know — so each item is annotated from the .mw-attention.json receipt and wears the weaker word on the surface the human is already looking at.

wheel: registered

The receipt says registered AND verified, and the store is not newer than the sync. The two surfaces agree; no badge is drawn.

wheel: pending

The wheel leg has not completed, or the store was written more than two seconds after the last sync — the projection may be stale, and the honest word is the weaker one until a sync proves otherwise.

wheel: unregistered

No receipt at all, or no entry for this item. The wheel has never heard of it.

packages/inquiry-weave/src/attention.ts
From an agent's hands

passages attention

npm i -g passages

passages attention add --episode 332 \
  --question "Which name does the composer workspace take?" \
  --unlocks "the folder can be created and the env var pinned"
VerbDoes
add
--episode <ref> --question <text> [--unlocks <text>] [--id <id>] [--depth <ref>]…
Raise an item (state: open) and project it to the wheel.
answer
--episode <ref> --id <id> --answer <text>
Answer an item and project the new state.
list
[--episode <ref>] [--open]
Read items — every episode when no --episode is given.
sync
(--episode <ref> | --all)
Re-project file state onto the wheel; redeem what is pending.
exit 0done + verifiedexit 3file written, wheel leg pendingexit 2usageexit 1error

The wheel is read from MW_API_URL_OVERRIDE → MW_API_URL → MIADI_CHRONICLE_MW_URL, in that order; the vessel root from MIADI_CHRONICLE_ROOT. Without a wheel URL the file still writes and the receipt says pending — exit 3, loudly.

packages/passages/js/lib/attention.js:27
Who owns which relation

One contract, five owners

Every surface types against the same module, so the shape cannot fork into drifting copies. The dependency edge stays one-directional: the app and passages call inquiry-weave, inquiry-weave imports the schema, the reusable UI accepts structural data + callbacks, and the schema imports nobody.

@miadi/episodic-memory-schema
The contract. Types, tolerant parseAttentionStore, canonical serialize — a pure module with no fs and no fetch, so browser bundles and CJS CLIs both consume it.
packages/episodic-memory-schema/src/attention.ts
passages
The creation and operator CLI. add/list/sync remain its verbs; answer delegates to inquiry-weave's shared transaction instead of implementing a second mutation path.
packages/passages/js/lib/attention.js
@miadi/inquiry-weave
The reusable read/answer service and wheel projection. Resolve identity, preview safe episode-local context, lock + atomically answer, verify the projection, and write the truthful receipt once for API, MCP, and CLI.
packages/inquiry-weave/src/attention.ts · attention-node.ts
@miadi/attention-ui
The transport-free React interaction and responsive stylesheet. It separates open work from answered history, makes completed attention a compact disclosure, and renders explicit answer or read-only interaction. No URL, token, root, or wheel address is embedded, so other hosts can reuse it.
packages/attention-ui/src/attention-panel.tsx · attention-panel.css
app/chronicle
The Miadi host adapters: Chronicle root, public read/answer transport gated to writers and the Address Episode Attention permission, capability discovery, palette, credential carrier, router refresh, aggregate board, and episode placement.
app/api/chronicle/attention/route.ts · app/chronicle
Where to look next

Two doors