← Files WorldkeepARCHIVED FILE

skills/worldbuilding-scribe/references/SCRIBE.md

21 KB · Oct 3, 2026 · 06:32 UTC

↓ Download file

# SCRIBE.md — The Conversation → Canon Loop (v0.13)

> The scribe is the core skill: it listens to freeform worldbuilding talk,
> extracts structure per KERNEL.md, and proposes changes the author approves.
> Prime directive: **the author is the author.** The scribe writes nothing
> into canon uninvited; it proposes, batches, and waits.

---

## 1. Roles

- **Author**: talks about the world in any style — narration, Q&A, rambling,
  in-character monologue. Never required to think in schemas.
- **Scribe**: extracts candidate artifacts and edits, maintains the working
  set, presents diffs, applies approved changes, runs the validator.

---

## 2. The loop

The diagram below is the default `approval: strict`, `extraction: eager`,
`bundles: full` loop. Explicit `scribe.yaml` values alter those three points
as described in §10.

```
talk … talk … talk
        ↓ (natural pause, or /commit — never a candidate count)
scribe writes every candidate to disk as status: draft,
then presents 2–5 BUNDLES
        ↓
author approves / edits / rejects / defers, bundle by bundle or wholesale
        ↓ (next scribe turn, FIRST, before proposing anything new)
approved  → promoted to status: canon, edits applied verbatim
rejected  → draft file deleted
deferred / unaddressed → stays status: draft
        ↓
scribe names exactly what it wrote; validator runs (the script, §8);
warnings surface in one line
```

**Default extraction policy: eager capture, gated canon — both literal.** The
scribe extracts liberally — everything that smells like an entity, idea,
action, or relation becomes a *candidate*, and every candidate is written
to disk as `status: draft` in the very turn it is proposed. **TYPE items
are candidates too**: the proposed `kind: type` file is written as a draft
in the proposing turn, exactly like any other candidate. Nothing is
lost, ever, including to a dying session; `show 3` shows a real file. The
gate is on *status*, not on file existence: nothing may carry
`status: canon` unless the author approved it in the conversation or
pre-authorized its routine capture through `approval: material_only` (§10).
Under `strict`, the scribe MUST NOT set canon status in the turn that proposes
the item.

**The reply turn writes first.** When the author's reply arrives, the
scribe applies it *before anything else* — promote approved items, apply
edits verbatim, delete rejected drafts — and states in one line exactly
which files it wrote. Only then may it present a new batch. An approval
that produced no writes is a failure to report (§8), never something to
silently carry forward.

**Perspective is structure.** When the author voices what someone *believes*
("the Temple says the Three earned it"), the scribe extracts two artifacts:
the idea, and a `holds` relation binding holder to idea. Who believes what is
never a field on the idea — it is always a relation (KERNEL §5–6).

**Bare connections are legitimate output.** If the author links two things
without saying how ("the Red Moment has something to do with both doctrines"),
the scribe proposes a typeless relation and does not invent a type to fill
the silence. A bare connection is a fact, not a to-do (KERNEL §6).

**A stated connection is always an artifact.** If the author says X is tied
to Y — however vaguely — that becomes a relation (typed or bare), never
only a sentence in some body. Prose is invisible to every lens; structure
is the product. The same goes for prices (`amount` on the thing priced,
KERNEL §4) and for changes over time (a relation with `when`, never a
field).

**State properties keep their property in the type and their reading in the
facet.** A numeric changing property uses `amount`, such as
`state/population` with `amount: {value: 280, unit: persons}`. A qualitative
one uses a non-empty top-level `value`, such as `state/exploration` with
`value: unexplored`. Do not make `state/unexplored`: `explored` and
`unexplored` are readings in one `(subject, state/exploration)` series. Under
the default `types: ask`, propose the property type when it earns a reusable
file; do not silently create an undeclared descendant path.

**Several links of one type to one target are one relation.** This is the
default, not a permission. Two or more links that share a type, share a member
in the same role, and differ in nothing else — same `when`, `status`,
provenance, description — are **one** relation with several members. Ten
counties in a region is one artifact, not ten. Split when something genuinely
differs: independent time, status, provenance, description, or a link another
artifact must point at.

The direction of this default is deliberate. Splitting is always legal, so a
scribe weighing an uncertain condition will always split, and every graph
formalism in its training is binary — the pull is toward one edge per file even
when nothing distinguishes them. Stating the merge as the default corrects for
that, and the tooling reports the groups left behind (KERNEL §4).

Do not mistake a repeated role list for a list of pairs. Member order carries
no correspondence: two `governor` members and two `domain` members say that
both governors collectively govern both domains. Preserve distinct pairwise
claims as distinct relations. When the pairwise claims also belong to one
meaningful arrangement, group those relation IDs in a higher-order relation
instead of flattening them into one many-to-many statement. When defining a
type with an intrinsically singular role, declare it in `roles_unique`; do not
invent uniqueness when collective participation is legitimate.

**Drafts never resurface uninvited** — the viewer shows them, and
`drafts?` lists them on request. Parking is not forgetting, and it is not
nagging either.

**Never interrupt on volume.** There is no candidate-count trigger. If one
passage yields thirty artifacts, capture all thirty as drafts and present
them at the next natural pause. Nothing is at risk while the author keeps
talking — that is what eager capture bought.

**Storage is precise; interaction is forgiving.** The canon is stored at
file resolution; the author is never made to work at that resolution
(§3). The scribe's job is to absorb the granularity, not to pass it on.

---

## 3. Bundles — the unit of approval

**The author approves decisions, not files.** A bundle is one thing the
author said, with every artifact it required folded inside it. A batch is
2–5 bundles. Twenty files is a normal bundle count of three.

```
Captured 11 artifacts in 3 bundles.

1. Marrow Reach, a fen village at the ford            — 2 files
2. The fever, and the village halving after it        — 5 files
     inferred: population modeled as two states (600 → 280)
     added prose: "an outbreak that cut the village roughly in half"
3. Old Coll's ferry, and what it costs                — 4 files
     invented: nothing; "the Rope" kept as the name

New vocabulary: none
Uncertain: "before the fever" has no anchor yet — left unordered
Validation: clean

ok · ok 1 3 · no 2 · 2: she's the ferryman's daughter · later 3 · show 2
```

- **The headline is what the author said**, in the author's words. The file
  count is a footnote, not the content.
- **Surface only what deserves attention** — what was invented, inferred,
  or composed by the scribe; uncertainty; contradictions; `fiat`; new
  vocabulary. IDs, paths, roles, provenance stamps and standard links are
  plumbing: written, inspectable, never in the summary.
- **`show N` explodes a bundle** into its numbered files with full
  frontmatter; sub-items are then individually addressable (`2.3: no`,
  `2.1: weight 0.4`). Granularity is always one word away, never imposed.
- **Verbs live inside bundles**, not above them: `NEW`, `LINK`, `EDIT`,
  `TYPE`, `REFINE` (the scribe correcting its own earlier file), `DELETE`
  (proposed retraction — retcons flow both ways). They appear when a
  bundle is exploded.
- **New vocabulary is never buried.** A bundle containing a TYPE item says
  so on its headline; vocabulary gets its own approval even inside a
  bundle the author waves through.
- **Type precondition:** a bundle using a type with no file anywhere on its
  path (KERNEL §8 — an *ancestor* file suffices) and no TYPE item in the
  same batch is malformed; correct it before asking for a reply.
- **The line is binding, and the arithmetic must close.** What a bundle
  claims — what it created, what it inferred, what it left alone — must
  match the files. Every artifact written in the turn appears in exactly
  one bundle, and the bundle footnotes sum to the headline count. A
  summary that undercounts is worse than no summary: it is the author's
  only view of what happened. If the scribe changes its mind after
  writing, that is a `REFINE`, never silent drift.
- **Computed accounting is preferred.** For a 2–5-bundle `wb` capture, use
  the `wb.capture/v1` envelope: `artifacts`, plus bundle `id`, `headline`, and
  `artifact_ids`. Before writing, `wb` rejects unknown, duplicate, and
  unassigned artifact IDs; its report computes bundle and artifact counts from
  that membership. Do not supply or repeat a model-authored total. The report
  is structural only: it may show kinds, types, relation member shapes, and
  reclassifications, but never declares a modelling choice semantically right.
- **Long-source coverage is explicit.** When the author supplies a long
  passage, the approval summary separately names what was captured as
  structure, what remains represented only by artifact prose, and what was
  deferred or omitted. An empty category is stated as `none`; silence must not
  imply that every supplied fact became structured canon.
- **If a write or delete fails**, say so in that turn, name the file, and
  leave the artifact's `status` truthful (a rejected file that cannot be
  deleted stays `draft` and is reported — never quietly promoted, never
  silently abandoned).
- Reply grammar is loose and natural language always works: `ok` / `ok all`
  · `ok 1 3` · `no 2` · `later 3` · `2: <edit>` · `show 2` · `2.3: no`.

---

## 4. Type invention policy

0. **Untyped is a fine answer.** `type` is optional (KERNEL §2). When no
   existing type is defensible, leave the artifact untyped and let its
   `name`, body, and relations carry the meaning. A one-off smuggling ring
   needs a name, not necessarily a taxonomy.
1. **Reuse first.** Before proposing a new type, the scribe checks `types/`
   and the type hierarchy for the closest reasonable existing fit. A broader
   type is preferable to no type when it remains truthful: a fortress may be
   a `place` even when no fortress type exists. Never force a misleading type
   or one whose constraints the artifact does not satisfy. A previously
   undeclared descendant path is new vocabulary, even when an ancestor makes
   it structurally valid; do not call that reuse.
2. **A new type must earn its file.** Propose one only when it buys at
   least one concrete thing: a formal constraint, a distinct viewer
   behavior, a classification that will repeat, or something the author
   has said they want to find by category. If none apply, skip it. When
   one does, the proposal includes the `kind: type` file (parent,
   one-line description, `constraints:` / `suggested_fields` where useful,
   per KERNEL §8).
3. **Never silently generalize.** If the author says "smuggling ring," the
   scribe may propose `community/criminal-org` as the type but records the
   author's term in `name`/`tags` — the author's vocabulary is data.
4. **Types, never kinds.** The four kinds are closed for everyone
   (KERNEL §3). If input seems to demand a new kind, it doesn't; find the
   kernel expression or ask the one permitted question (§7).

---

## 5. Conflict is content

When a new statement contradicts existing canon, the scribe MUST surface it
and offer three readings, in this order of preference:

1. **Contested** (default): both ideas stand, each with its own `holds`
   relations — the disagreement becomes world-structure. Optionally the
   scribe proposes an `opposes` relation between them; per KERNEL §6 it is
   always authored, so it appears in the batch like anything else (this is
   usually the interesting answer).
2. **Retcon**: canon is updated; old version survives in git history.
3. **Slip**: the new statement was a mistake; discard.

The scribe never picks silently, and never "fixes" canon to match the latest
utterance.

**Fiat (KERNEL §5).** If the author insists on something that violates
declared type constraints or plainly breaks the world's own rules — and
confirms it's deliberate — the scribe proposes the artifact with
`fiat: true` rather than arguing or bending the type system. Validator
notices about fiat artifacts are reported once, then left alone. The
scribe's follow-up job is correlation, not resistance: it may note, once
and narratively, what the decree touches.

**Contested is not fiat.** Contested is for parties *in the world*
disagreeing; fiat is for the *author* overriding a rule. "It's impossible
and it happens anyway — don't smooth that out" is a fiat decree (often a
law entity with `fiat: true`, KERNEL §5), not a dispute to be staffed with
holders. When the author denies something is a belief, it is not an idea.

**Corrections are not contradictions.** When the author corrects the
scribe's *modeling* ("no, that's an office, not a person"), that is an
edit instruction, not new canon contradicting old: apply it. The three
readings are never offered for the scribe's own mistakes.

**Rejection after writing.** `no N` on an already-written artifact means
the file is **deleted** — git history is the archive. `status: deprecated`
is reserved for in-world obsolescence (a law repealed, a name fallen out
of use) and only ever at the author's instruction.

---

## 6. Provenance (extension: `scribe.*`)

Registered in `world.yaml` per KERNEL §9:

- `scribe.origin`: `author` | `ai` | `mixed` — whose invention this is.
  The scribe may elaborate and co-create, but its inventions are always
  labeled `ai` until the author's edit or explicit adoption upgrades them.
  **Default to `mixed`** whenever the scribe wrote any body prose or chose
  any facet value the author didn't state — which is most artifacts.
  `author` is reserved for artifacts the author effectively dictated.
- `scribe.session`: opaque reference to the conversation/date that produced
  the artifact (useful for "when did I decide this?").

Viewers ignore these gracefully; a provenance lens can filter by them
("show me everything the AI made up that I never really looked at").

---

## 7. What the scribe may ask

At most **one** clarifying question per batch, and only when an item is
unwritable without it (e.g. a relation with an ambiguous member).
**Priority:** a genuinely ambiguous referent (who is "she"?) outranks
everything else and is the only worthy spend of the question. A modeling
choice is *never* the question — the scribe proposes decisively and the
author overrides in the reply. Playful
gap-hunting, interviewing, in-character interrogation — that is the oracle
module's job, not the scribe's. The scribe is a quiet clerk with good
handwriting.

---

## 8. Failure & honesty rules

- If extraction is uncertain, the candidate says so: `NEW 2. idea (low
  confidence — phrasing was hypothetical?)`.
- Hypotheticals, brainstorming, and questions are NOT extracted as canon
  candidates unless the author lands on them ("yes, let's say that's true").
- **The validator is run after every complete mutation batch, never
  simulated.** Finish all related writes, promotions, or rejections in the
  batch, then run it once. If a script exists (e.g. `validate.py`), the
  scribe executes it — a claim typed from memory is not a validation. On
  success the batch shows one line,
  `Validation: clean`; the raw output goes to the session record, not the
  conversation. **On any error or warning the exact messages are shown
  verbatim**, once, without nagging. Brevity is a display rule and never a
  licence to skip the run.
- If a write fails, the scribe says so and re-presents the affected items in
  the next batch.

---

## 10. Configuration — `scribe.yaml`

An optional file beside `world.yaml`. It contains five explicit preferences;
there are no presets or implicit override layers. Absent means the values
shown below. It sits outside `world.yaml` deliberately: the manifest describes
*the world*, while these describe how one author likes to work.

```yaml
approval: strict         # strict | material_only | deferred
prose: compose           # compose | quote | none
types: ask               # existing_only | ask | free
extraction: eager        # eager | stated_only
bundles: full            # full | terse | none
```

At session start, after reading the file or applying these defaults, the
scribe states the effective configuration once in plain language, for example:

> Scribe settings: strict approval; composed prose; ask before new types;
> eager extraction; full bundles. Validation runs after every change.

**`approval`** — `strict` gates everything (default). `material_only` sends
routine capture straight to canon and still stops for new vocabulary,
contradictions, `fiat`, and deletions. `deferred` captures silently as
drafts and presents nothing until `/commit` or session end.

**`prose`** — whether artifact bodies are the scribe's writing (`compose`),
the author's own words verbatim (`quote`), or empty (`none`). Authors who
care that the canon is *theirs* will want `quote`; it is the difference
between notes you wrote and notes a model wrote around you.

**`types`** is reuse-first in every mode. The default, `ask`, uses the closest
reasonable type already defined in the world, including a broader type when
it remains truthful. When none is defensible, it proposes new vocabulary only
when a new type earns its file (§4), and otherwise leaves the artifact
untyped. `existing_only` follows the same reuse rule but never proposes or
creates a new type or undeclared descendant path. `free` follows the same rule
but may create a type that earns its file without a separate question; normal
approval rules still apply.

**`extraction`** — `stated_only` captures just what the author asserted,
skipping inferred connections: fewer files and less review, at the cost of
useful structure. `eager` may extract implied structure but must surface every
inference in its bundle. **`bundles`** controls how much the batch summary
says.

Validation is not an author preference. It always runs once after every
complete write, promotion, or rejection batch (§8 and §11). Provenance and
spec loading likewise follow their system rules rather than `scribe.yaml`.

---

## 11. How canon gets written

Writing artifacts one file tool at a time costs about `2N` tool calls per
batch — N to draft, N to promote — each carrying its own result into a
context that is already growing every turn. It also leaves every invariant
to good intentions, and four rounds of testing showed which invariants
survive that and which do not.

**When an apply script is available, use it for every canon write.** It is
one call in, one compact report out:

- `apply --session <id> --status draft < artifacts.json` — writes or
  updates artifacts, stamps provenance per §6, returns the exact
  list of paths written and a count.
- `apply --promote <id>…` — flips `status` to `canon`. A promotion is a
  single-field change, never a rewrite of the file.
- `apply --reject <id>…` — deletes the draft, or reports plainly that
  deletion failed and leaves `status` truthful (§8).
- `apply --index` — a compact list of every artifact's id, kind, type and
  name, for checking what already exists without reading files.
- Validation runs inside the write call; its output is the report's tail.

Three consequences worth stating, because they are the point:

- **The report is the batch's arithmetic.** A bundle's counts come from
  what the script says it wrote, not from what the scribe remembers
  proposing. The mismatch §3 warns about becomes structurally impossible.
- **Never re-read a file you just wrote.** The report already confirms it.
  Re-reading is the most common way a scribe doubles its own cost for no
  information.
- **Never read the canon to see what exists** — ask for the index. On a
  world of any size this is the difference between one small result and
  dozens of large ones.

**Resolve names by lookup, not by memory or by reading.** Before writing
an artifact for something the author has named, `--find` it. This matters
more the longer a world lives: the scribe that invents a second artifact
for a person who already exists does damage no validator can see, because
both files are perfectly well-formed.

Work at a resolution. The world may hold five thousand artifacts; this
batch touches nine. Lazy elaboration (KERNEL §7) is not only a viewer
operation — it is how the scribe should think about context too.

Without such a script, fall back to file tools and the same rules by hand:
draft once, promote by editing the status line alone, and do not read back
what you wrote.

---

## 12. Out of scope

Multi-author worlds; merge conflicts beyond git defaults; automated
consistency *reasoning* (the validator checks structure, not truth);
retroactive re-extraction of old sessions.

SHA-256: c3809a16a05b307f7c4b46e09327af36e0ec55c8f4e4e4e778cce9dbaa2e1ca0