Skip to content

Nightly narrative queue

Nightly narrative queue

Mechanical narrative work queue, drained by narrative-ops (Sonnet sidekick to narrative-designer). Each entry is a bounded task whose creative decisions have already been made elsewhere — by a narrative-designer decision log, a tech-architect rename map, or an existing canon page.

This page is the task queue specification plus the live queue itself. It is status:canon because the schema is canonical even when the queue is empty.

Purpose

The naming-discipline pipeline (ratified 2026-05-20) splits narrative work into two tiers:

  • Creative tiernarrative-designer (Opus). Four-phase writing schema, tonal calibration, canon authorship, naming picks. Expensive, slow, irreplaceable.
  • Mechanical tiernarrative-ops (Sonnet). Glossary backfill, EN body cleanup, rename propagation, wiki expansion from existing canon, items/materials/recipes flavour text. Cheap, fast, traceable.

The queue is the contract between the two tiers: narrative-designer (or any lead with the right context) posts a queue entry; narrative-ops drains it on nightly cron. The queue makes the boundary auditable — every mechanical edit traces back to a queue entry with explicit acceptance criteria and a source pointer.

Entry schema

Queue entries are YAML-fenced inside this Markdown page. Humans write them; agents read them. Do not migrate to TypeScript — the queue is editing-prone and reviewable-in-diff in YAML.

- handle: <short-kebab-case-task-handle>
kind: glossary-entry | en-body-cleanup | cross-file-propagation | wiki-expansion | flavour-text
scope: <one-paragraph description of what files / what range>
acceptance: <verifiable criterion — REQUIRED, e.g. "lint:naming passes; npcs/X.ts handle field == 'X'; transcreationNote >= 10 chars">
source: <pointer to canon evidence — decision log path, data file path, or canon wiki path — REQUIRED for kinds glossary-entry, wiki-expansion, flavour-text>
status: pending | in-flight | done | blocked
blocked-reason: <only present if status == blocked>

Field semantics

  • handle — short, kebab-case, unique within the queue. Names the task, not the entity being worked on. Example: glossary-backfill-cech-faction, propagate-rename-pan-kepka.
  • kind — one of the five allowed narrative-ops task types. Any other value is a malformed entry; narrative-ops will refuse and FLAG_LEAD. See .claude/agents/narrative-ops.md for the canonical definitions.
  • scope — one paragraph. What files, what range, what subset. Specific enough that two agents reading it would touch the same files.
  • acceptanceREQUIRED for every entry. A verifiable criterion the executor can check after the work. Vague acceptance is not acceptance — the criterion must name a lint command, a typecheck result, a field value, or a measurable property. Examples:
    • lint:naming passes; all npcs/*.ts files have non-empty handle field
    • wiki/src/content/docs/lore/npcs/pan-kepka.mdx ≥ 300 PL words; every paragraph carries source trace comment
    • data/src/content/factions/cech-niedokonczonych-wypraw.ts en.description field contains zero PL characters
  • source — pointer to canon evidence. Required for kinds that touch creative-adjacent content (glossary-entry, wiki-expansion, flavour-text); optional for purely mechanical kinds (en-body-cleanup, cross-file-propagation) where the glossary itself or the rename map is the source.
  • status — lifecycle. pending → posted, waiting. in-flightnarrative-ops is working it. done → committed. blocked → executor hit a FLAG_LEAD condition; narrative-designer must triage.
  • blocked-reason — only present when status == blocked. One sentence naming the FLAG condition (e.g. grammar collapse on word-level swap line 47, kind=flavour-text but no style precedent exists for this material category).

Required-fields-by-kind matrix

kindhandlekindscopeacceptancesourcestatus
glossary-entryyesyesyesyesyesyes
en-body-cleanupyesyesyesyesoptionalyes
cross-file-propagationyesyesyesyesoptionalyes
wiki-expansionyesyesyesyesyesyes
flavour-textyesyesyesyesyesyes

A glossary-entry, wiki-expansion, or flavour-text entry posted without a source is malformed. narrative-ops will refuse and FLAG_LEAD: narrative-designer. No source = no canon evidence = no autonomous work.

Queue

# Queue (empty — Phase A bootstrap; first entries land in Phase C)
tasks: []

How nightly runs work (DRAFT — Phase D decision required before activation)

This section is the operational shape of the nightly run. It is DRAFT — autonomous nightly execution is NOT enabled in Phase A. Activation requires a D-level decision in Phase D after Phase C populates the queue with real entries and the dry-run cycle has been observed manually for at least one iteration.

  • Trigger. A /schedule cron entry (Phase D) runs narrative-ops against this page once per night. The agent picks all status: pending entries in queue order, executes them sequentially, and updates status in-place to in-flightdone (or blocked).
  • Boundaries. narrative-ops will refuse any entry whose kind is unknown, whose required fields for the kind are missing, or whose work would require creative invention. Refused entries flip to status: blocked with a populated blocked-reason.
  • Morning review discipline. First action of the working day: narrative-designer (or CEO when narrative-designer is offline) reviews the overnight diff. done entries are spot-checked against their acceptance criterion. blocked entries are triaged: either reformulated with the missing context, escalated, or closed as out-of-scope.
  • Commit discipline. Each completed entry is its own commit with the entry handle in the message (e.g. chore(narrative-ops): drain glossary-backfill-cech-faction). Pre-existing uncommitted work in the tree at run start is not touched.
  • Rollback. Every commit is reversible by git reset --soft HEAD~N per the repo’s destructive-ops policy (CEO consent required for force-push or hard reset).

Until the Phase D ratification, this page exists as the specification + empty queue. Entries can be added to the queue (status: pending) during Phase C for manual dry-run dispatch — but no cron, no autonomous drain.