Skip to content

Blaze: story-first, phase-aware authoring

Status: target design for the next three bounded milestone-8 issues, approved for planning by Doug on 2026-09-21. Issue #167 implements the source-level syntax and lowering contract described in the "Implemented #167 source contract" section below; the inspection and editing commands remain future #168/#169 work. This addendum supersedes the base design's blanket prohibition on authoring defaults and its check/build-only scope for these follow-on issues; it does not change the runtime. See the small design trial for evidence and limits.

North star and ownership

Write the story; compile the plumbing. Blaze owns story intent and gameplay; Moltazine/Crucible provide media generation, storage, and provenance. The compiler assembles the existing WorldBundle. Moltazine can still hold narrative metadata, but its publication object layout must not dictate how authors write a scene.

There is one authored project, not three synchronized phase-specific documents:

Phase/viewContext returned by defaultNormally omitted
MechanicsStable entities, entry gates, visibility/availability, ordered effects, destinations, decisions, recovery and cross-scene consumersFull prose, asset payloads, post revisions
DialogueUtterances, menu labels, speakers, compact character continuity, local flow and relevant mechanics contractsMedia receipts and binary metadata
TTSStable line ID, canonical/caption/synthesis/pronunciation text where authored, speaker, resolved voice and locale/style, nearby dialogue on request, binding freshnessUnrelated rooms, inventory graph, art manifests
ArtRoom description, applicable visual state/variant, visible characters/items and their visual briefs, dimensions/asset identity, relevant geometry/mask constraintsIndividual dialogue choices and unrelated mechanics

Views are compiler-derived context packets, never a second source of truth. Mechanics affecting a selected visual variant remain visible in the art view. Likewise dialogue authors must see the difference between hidden and disabled choices, decision/recovery consequences, and reused lines' other consumers. Phases are iterative lenses, not a mandatory one-way workflow or phase scheduler.

1. Small source, explicit semantics

  • Declare a canonical world namespace once per compilation unit. Local symbols and imports are short; a documented declaration-kind mapping expands stable IDs. Explicit canonical IDs remain legal. Qualified external namespace aliases are typed references, not string substitution. Nested conversation/node/choice/line identities need documented scope rules, not only top-level aliases.
  • Stable authored labels, not prose, array position, or file path, determine inferred identity. Renaming a file/import alias must preserve output. Renaming an identity label is a compatibility change, not an ordinary text edit; use an explicit canonical-ID override when preserving an existing identity.
  • Author an utterance once. A source-level line carries a short label, speaker, text, and optional caption override. Omitted caption means canonical text; an explicit empty string stays explicit, subject to runtime validation.
  • References to that line lower into the existing node/choice text, line IDs, and ordered line registry. Preserve distinct menu labels, spoken text, response text and captions when authored. No mandatory media field in prose.
  • Define and test deterministic line-registry emission order; allow explicit ordering/identity overrides for the pinned port. No new runtime line is invented merely because an existing choice has response text without a responseLineId.
  • Reusable declarations may reduce repeated structures, but do not merge choices that share prose while having different decision hooks or effects. Keep the current low-level record form as a complete escape hatch.
  • Defaults are an explicit finite lowering contract, not permission for a new evaluator, implicit flags, auto-execution, or silent gameplay inference. Manifest auto-population is deferred; preserve existing explicit assembly and order.

Implemented #167 source contract

The compiler keeps the low-level v0.1 record form as a complete escape hatch and adds a finite source-lowering pass before the existing closed schema checker. Supported additions are intentionally small:

  • namespace "..."; may be declared once by the entry compilation unit. Imported modules may omit it or repeat the same namespace. Conflicting namespaces are BLAZE_IDENTITY errors.
  • Top-level room, character, item, npc and dialogue declarations can omit id; the compiler lowers them to <namespace>.<kind>.<identityLabel>. identityLabel defaults to the declaration name and is source-only. Explicit id remains the compatibility-preserving override.
  • Conversation-selected line declarations can omit id, canonicalText, captionText, speakerCharacterId and audioRef. Source fields are text, optional caption, speaker, optional audio, optional role, and optional identityLabel. Omitted captions lower to the canonical text. Player lines use <conversation-id>.line.player.<identityLabel>; other lines use <conversation-id>.line.<identityLabel>.
  • Node say: id(lineSymbol); lowers to lineId, npcText and captionText. Choice say, reply, optional menu, and optional caption lower to the existing playerLineId, responseLineId, text, responseText and captionText fields. Menu text can differ from spoken line text. Existing conditions, visibility/availability, blocked text, decisions, recovery, effects and destinations keep authored order.
  • id(symbol) is supported as a map key only in map-valued schema positions. Unsupported record-key positions remain errors.
  • media_companion declarations are source-only. They are checked for the #167 states unbound, fresh, stale and unverified, are never serialized into WorldBundle, and cannot be embedded as runtime gameplay records. Stale current bindings and required unbound media are BLAZE_MEDIA errors. Unverified legacy pinned bindings compile with a BLAZE_COMPANION warning.
  • Authored low-level fields that disagree with derived fields are BLAZE_IDENTITY errors. Source-only fields are removed before schema checking so they cannot leak into generated bundles.

Eliza check-in is the bounded witness. The apology player line and apology recovery reply are authored as local story-first lines and referenced by the choice, while the registry follow-up keeps a distinct menu label and spoken line. The generated Adirondack bundle remains byte-identical to the committed artifact.

#167 source receipt

Receipt metrics were collected with wc -c, rg -o, and a whitespace token estimator named rg-nonspace-token-count on 2026-09-21. For the migrated Eliza witness, examples/blaze/adirondack-mystery/dialogue/eliza.blaze is 25,131 bytes. The entry assembly file is 25,427 bytes. Eliza source contains 124 repeated canonical namespace tokens, 2,111 ASCII identifier tokens, average identifier length 7.57, maximum identifier length 71, and approximately 1,575 non-space text tokens by the estimator. The source-only media companion currently lives in Eliza and contributes to those bytes; no media payloads or generated receipts were moved or republished for #167.

The trial notation is a design witness, not a parallel grammar to support.

2. Media companions and incomplete projects

Use small companion modules/data scoped by scene or conversation. A stable semantic slot (line audio, character portrait, room visual variant) links authored intent to a typed, immutable accepted reference. Keep generation receipts, rights, source hashes, geometry and media metadata outside the normal prose view. Reuse the existing typed hash-pinned data boundary where it fits; do not introduce an untyped JSON escape hatch for gameplay. Speaker defaults and media selection must be explicit and inspectable; no hidden filename-to-asset convention.

Bindings may be absent while writing. Inspection and source-only checking must report unbound media and unfinished authoring separately from malformed syntax, broken symbols or invalid gameplay. An incomplete project is not certified as a playable WorldBundle. Build remains strict: missing runtime-required media/data needs an explicit valid local placeholder or accepted binding, or build fails with an actionable diagnostic. Never silently invent a fake published World ref. Optional unvoiced dialogue can stay unbound under the existing runtime contract.

This iteration does not require a new generic draft AST or a missing-prose runtime: mechanics-first fixtures may use explicitly authored placeholder prose. It does require inspection of parseable unfinished projects, with diagnostics and clear partial-result labeling. Lowering errors must not prevent listing unaffected symbols. This is bounded inspection, not error recovery for arbitrary bad syntax.

Compilation is local/offline; bindings are pinned. Media generation, credentials, uploads, publication and remote discovery remain Moltazine tooling's job. Blaze exports a generation brief and accepts reviewed results; it does not become a second media orchestration platform.

Freshness and compatibility

A TTS association records the generation-input fingerprint: at minimum canonical text plus speaker/voice revision and effective synthesis/pronunciation/locale/style inputs used. A canonical-text hash alone cannot catch a changed voice. Caption-only changes must not claim audio regeneration is necessary unless they change effective synthesis input; any copied runtime caption metadata must remain consistent.

An art association records relevant visual brief, slot/variant and source identity inputs, not a hash of unrelated dialogue. Changes invalidate only affected bindings. Freshness is source-side metadata unless a matching existing runtime field exists; no new WorldBundle fields are silently added. Imported legacy bindings without full input evidence are explicitly unverified, not labeled fresh from invented history.

Distinguish unbound, fresh, stale and unverified in inspection. Stale accepted media must not be silently emitted as current: require a new binding or explicit valid fallback/unbinding decision. Unverified pinned legacy bindings remain preservable with a visible diagnostic so the baseline is not rewritten; new binding operations require input evidence. Never automatically repin media or fetch a mutable latest.

Changing room image identity/dimensions invalidates source-bound masks/geometry. An art binding operation must either carry matching reviewed evidence, explicitly select a valid fallback, or fail with a precise blocker. It cannot certify geometry by copying it from the previous image. The existing validator/runbooks remain binding; registering media is not granting publication/activation authority.

3. Compiler-backed inspection

Logical CLI examples below are proposed, not current commands:

text
blaze inspect <entry> --kind dialogue --room check_in_lobby --characters clara,eliza
blaze inspect <entry> --select eliza.check_in.repair --view mechanics --json
blaze inspect <entry> --select eliza.check_in --view dialogue --json
blaze inspect <entry> --select apology_with_whistle --view tts --json
blaze inspect <entry> --select check_in_lobby --view art --json

Use explicit semantic filters and exact stable selection handles; no LLM search or natural-language query engine. A "story line" filter initially means an authored conversation, StoryBeat or explicit module, not inferred plot membership. Room associations are resolved through actual runtime/source links, not added runtime room ownership on conversations. Ambiguity lists bounded candidates; zero matches is explicit. Never pick the first match. Preserve source order in results.

Each versioned packet includes selector/handle, stable IDs, editable source spans, source/dependency revision fingerprint, typed relevant imports, inbound/outbound references, diagnostics, and omitted-context counts/continuation handles. Bound output by a requested budget; never silently drop critical gates/effects. If the minimum safe context exceeds it, return a summary plus explicit expansion handles and mark it incomplete. Read-only consumers can request prose without media; mutations must resolve the complete dependency set regardless of display budget. No claim of runtime reachability from static references. Scenario execution remains in the existing runtime tests, not a new CLI simulator.

Implementation note: the read-only inspect command shipped in Blaze Inspect CLI follows this static packet contract for issue #168. Short selectors that hit multiple phase records now return ambiguous with candidate handles; exact handles or typed selectors select one record. Mechanics packets retain critical choices/actions/exits even when the requested budget is below the minimum safe context, and media slots/diagnostics distinguish unresolved references from missing, stale, unverified, and fresh media evidence.

4. Surgical source edits and media binding

Proposed workflow: inspect -> prepare patch -> review diff -> apply -> check/build. Offer a versioned structured patch input via file/stdin, not hundreds of flags. Allow a bounded operation set: update utterance/caption/menu label, replace an existing node/choice's typed conditions/effects/destination, insert/remove a local choice or line with reference checks, and bind/unbind an existing media slot. A media-binding convenience command must use the same patch/validation machinery. No arbitrary AST-path/JSON-patch authority over generated output.

A patch names exact stable handles and expected source/dependency fingerprints. Reject stale state, ambiguous targets, incompatible types, duplicate IDs, dangling references and out-of-scope writes. Shared-line changes surface every consumer; cloning a line is explicit, not an accidental fork of identity. Identity renaming and automatic save migrations are deferred. Typed graph edits may deliberately change behavior; report consequences, do not promise behavioral equivalence.

Retain concrete source ranges/trivia so unchanged bytes, comments and ordering stay unchanged outside intended edits. Do not pretty-print the entire corpus or round-trip through generated JSON. Preview lists exact file/source diffs, affected IDs/references, media invalidations and whole-project diagnostics. Apply rechecks fingerprints immediately before committing writes and validates the candidate project before replacement. Invalid patches leave originals unchanged. Draft-mode success must not be labeled build success; it may retain explicitly reported pre-existing missing-media obligations but must not add structural/type failures.

Multi-file source/companion edits require a project lock, staged writes and a recoverable transaction journal or equivalent rollback. Readers using Blaze must not observe partial transactions; interrupted writes are recovered before the next operation. Do not claim cross-file filesystem atomicity from individual renames. No networking or media generation inside patch application. Generated artifact refresh remains an explicit build, never a separately edited authority.

Bounded delivery and evaluation

Three implementation slices:

  1. #167 — Source ergonomics and media companions.
  2. #168 — Phase-aware read-only index/inspection.
  3. #169 — Bounded source patches and media bind/unbind.

Run #160 baseline parity before these changes, then require that harness throughout. #161 follows all three and dogfoods their documented behavior. The existing #165 Pages issue remains separate documentation publication, not a hidden new editor.

The trial is strategic, not a parser implementation or proof. Later implementation receipts measure bytes/context actually read, dependency expansion, changed source span and successful verification for four tasks: a mechanics gate change, a prose change with unchanged mechanics, a TTS binding, and a room-art binding. Count media companions in whole-corpus measurements; moving bytes is not deleting bytes. Measure task-local context separately from total source size. A smaller packet that omits a critical dependency is a failure, not an optimization.

Keep pinned canonical IDs, meaningful order, accepted references, reducer behavior, saves and non-Blaze worlds intact. For source-only migrations target byte-identical canonical JSON; any serialization-only difference requires an explained comparison, not normalization that hides semantic drift. No new runtime, generic rule engine, natural-language editor, visual editor, language server, asset generator, deployment or broad benchmark suite is required by these three issues.

BARKLINE mark is served from a local, hash-pinned repository asset.