Skip to content

Blaze Source Patch CLI

Blaze source patches are versioned JSON requests that target #168 inspect handles and exact source revisions. Source is authoritative: patch, apply, and media bind never edit generated world JSON, fetch remote media, generate assets, upload, or publish. Run blaze build explicitly after source edits when a bundle refresh is wanted.

Commands

bash
npx tsx scripts/blaze.ts patch examples/blaze/adirondack-mystery/main.blaze --file patch.json
npx tsx scripts/blaze.ts apply examples/blaze/adirondack-mystery/main.blaze --file patch.json
npx tsx scripts/blaze.ts media bind examples/blaze/adirondack-mystery/main.blaze --file binding.json
npx tsx scripts/blaze.ts media unbind examples/blaze/adirondack-mystery/main.blaze --file binding.json

patch previews only. apply rechecks current source fingerprints and dependency fingerprint immediately before writing, validates a staged candidate project, then commits through .blaze-transactions/ with lock, journal, backups, rollback, and recovery before later Blaze reads.

Exit statuses: 0 successful preview/apply, 1 valid input rejected with no writes, 2 usage, schema, IO, or transaction lock errors.

Patch Schema

json
{
  "schemaVersion": "adventure-kit.blaze.patch.v0.1",
  "expectedRevisions": {
    "source": [{ "file": "/abs/main.blaze", "sha256": "...", "byteLength": 1234 }],
    "dependencyFingerprint": "..."
  },
  "operations": [
    {
      "id": "dialogue-copy",
      "kind": "update_text",
      "handle": "blaze://line/example.line",
      "field": "canonicalText",
      "value": "New authored line.",
      "allowSharedConsumers": true
    }
  ]
}

Supported operations are bounded to update_text, replace_typed_field, insert_local, remove_local, bind_media, and unbind_media. Typed replacements are limited to existing gate/effect/destination fields. Local insertion/removal is limited to line and choice lists. Untouched bytes, comments, field order, and declaration order are preserved; non-ASCII touched files fail closed until byte-index patching is implemented.

Common diagnostics include PATCH_SCHEMA, PATCH_STALE_REVISION, PATCH_ZERO_MATCH, PATCH_AMBIGUOUS, PATCH_UNSUPPORTED_KIND, PATCH_OUT_OF_SCOPE, PATCH_SHARED_CONSUMERS, PATCH_DANGLING_REFERENCE, PATCH_DUPLICATE_ID, PATCH_INVALID_MEDIA, PATCH_CANDIDATE_INVALID, PATCH_TRANSACTION_LOCKED, and PATCH_TRANSACTION_RECOVERED.

Media Binding

media bind accepts immutable external results only when evidence matches the current typed slot. The CLI preserves supplied rights, provenance, and evidence; it does not invent missing metadata.

Line audio requires current text/voice/synthesis evidence such as canonicalTextHash, voiceRevision, synthesisInputsHash, and generatedTtsId. Room visuals require visualBriefHash, variant, sourceIdentityHash, asset identity/version/dimensions, and sourceDimensionsHash when geometry is supplied. Character portraits use the same media_companion mechanism with character.portrait, immutable asset identity, dimensions, content hash, rights, provenance, alt text, intended use, visibility, and status.

Examples

Mechanics gate edit:

json
{
  "schemaVersion": "adventure-kit.blaze.patch.v0.1",
  "expectedRevisions": { "source": [], "dependencyFingerprint": "inspect-fingerprint" },
  "operations": [{
    "id": "gate-ridge",
    "kind": "replace_typed_field",
    "handle": "blaze://exit/to_ridge",
    "field": "conditions",
    "value": [{ "has_item": { "itemId": "trail_map" } }],
    "allowSharedConsumers": true
  }]
}

Dialogue-only edit:

json
{
  "schemaVersion": "adventure-kit.blaze.patch.v0.1",
  "expectedRevisions": { "source": [], "dependencyFingerprint": "inspect-fingerprint" },
  "operations": [{
    "id": "line-copy",
    "kind": "update_text",
    "handle": "blaze://line/story.line.check_in",
    "field": "canonicalText",
    "value": "The lobby clock chimes once.",
    "allowSharedConsumers": true
  }]
}

TTS association:

json
{
  "schemaVersion": "adventure-kit.blaze.media-binding.v0.1",
  "expectedRevisions": { "source": [], "dependencyFingerprint": "inspect-fingerprint" },
  "handle": "blaze://line/story.line.check_in",
  "slot": "line.audio",
  "binding": { "generatedTtsId": "tts.check_in.v1", "media": { "contentHash": "sha256:...", "byteCount": 123, "mimeType": "audio/mpeg" } },
  "evidence": { "canonicalTextHash": "sha256:...", "voiceRevision": "voice:v1", "synthesisInputsHash": "sha256:...", "generatedTtsId": "tts.check_in.v1" },
  "rights": { "consent": "licensed", "allowedUses": ["gameplay"] },
  "provenance": { "source": "moltazine", "jobId": "immutable-job" }
}

Room-art association:

json
{
  "schemaVersion": "adventure-kit.blaze.media-binding.v0.1",
  "expectedRevisions": { "source": [], "dependencyFingerprint": "inspect-fingerprint" },
  "handle": "blaze://room/story.room.lobby",
  "slot": "room.visual",
  "binding": { "assetIdentity": "sha256:asset", "assetVersion": "asset:v1", "dimensions": { "width": 1536, "height": 1024 } },
  "evidence": { "visualBriefHash": "sha256:brief", "variant": "fallback", "sourceIdentityHash": "sha256:source", "sourceDimensionsHash": "sha256:dims" }
}

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