MeridiansMeridians

Production — the asset inventory, the style lock, and what a novel costs to look like

From the Meridians Wiki · Public · Maintained · human-contract

Status: rough spec (direction). Not an implementation contract; nothing here ships until scheduled.

Experimental baseline: the local VN experiment audit 🔒 records candidate reader, VN composition, CG, catalog, receipt, and readiness machinery. It narrows the next integration move but does not change the shipped/build ledger below.

Fifth companion to the visual-novel delivery, and the asset-side pair to budgeted fate exploration (which owns whether a branch earns production; this owns what production is and the directional Factory surface that controls it).

Decisions covers the fork, reader the interface, structures the topology, branching the instrument. This one covers the thing a reader actually experiences first: the world looking like one world.

The claim it argues:

Richness in this medium is not resolution — it is inventory and consistency. A VN reads as rich when the same character appears a hundred times and is recognisably the same person in a recognisably single art style, and when the register changes (a document, a memory, a CG) arrive as deliberate breaks in a stable frame. Our substrate is close, with one structural gap: identity currently rests on prose, not on a reference image.

Two economic classes run through everything below:

CAPITAL      generated once, reused across every scene, episode, and route
             sprites · location plates · artifacts · UI · audio bed · voice per line-version
             → reconvergence INCREASES their reuse (branching.md §7), so our preferred
               topology is also our cheapest art posture

CONSUMABLE   one moment, one bill, no reuse
             event CGs · cut-ins · one-off composites
             → must be rationed by a rule, not by taste

1. What the medium actually needs

The inventory below is what separates a VN from a slideshow of illustrated text. Each row is marked with what we have.

AssetRole in the mediumOurs today
Character sprite setthe same actor across expressions/poses; the workhorse of the formone 3:4 portrait per character (SET_CHARACTER_IMAGE, single imageUrl)
Location platethe stable frame the eye rests in; changes rarely and meaningfullyone 16:9 per location
Plate variantstime of day, weather, aftermath — the cheapest way to signal that the world movednone
Artifact studythe examinable object; the medium's documentary registerone 1:1 per artifact — but no reader-facing presentation
Event CGthe composed moment a static stage cannot carry; consumablenone
Cut-ina small overlay for impact/reaction without leaving the framenone
Unit / creaturenon-character presencesone 3:4 per unit
Mapspatial orientation across a long workshipped (buildMapImagePrompts, regions + topology)
Coverthe artifact's faceshipped (3:4; displayed in the portrait cover frame)
UI frametextbox, nameplate, rail — the chrome that must not changereader.md owns it
Transitionsfade/dissolve/cut as punctuation between framesnone (a render concern, not an asset)
Audio bedambience + theme; the largest immersion-per-dollar in the mediumout of scope here
Voiceper line-version, cached; the largest per-episode costpriced, uncached

The honest summary: we have one image per entity and no variants. That is a domain illustration set, not a VN asset set. The gap is not fidelity — it is axes.

2. Identity comes from a reference image, not from a better prompt

This is the load-bearing finding of the document, so it is stated as a fact about our code.

The render call sends exactly this:

// src/lib/engine/image/generate.ts — renderToUrl
body: JSON.stringify({ input: { prompt, aspect_ratio: aspectRatio } })

No reference image. The model is fixed in the endpoint URL (https://api.replicate.com/v1/models/bytedance/seedream-4.5/predictions), and identity is carried entirely by prose: the crafted visual prompt, the stored per-entity imagePrompt (SET_*_IMAGE_PROMPT), the world summary, and continuityHints. Every render now passes that complete source context through the shared image-context compactor first. A supplied imagePrompt is a candidate visual hypothesis, not a bypass or canonical truth: extraction and earlier generation are not expected to have solved the final image. The model checks it against all available evidence beneath fixed kind constraints and the Domain's cross-asset style, improving or replacing unsupported choices. It reads appearance together with role, history, motive, belief, vulnerability, relationships, use, ownership, control, and current state to form one coherent visual thesis. It may derive a few plausible production choices—posture, grooming, wear, material, handling traces, palette, light, framing, spatial order, environment, or an earned motif—without turning those choices into new canon, contradicting explicit facts, or literalising every node. If the source exceeds the selected text model's context window, it is compacted in model-sized chunks and consolidated before formulation. Character/Unit continuity is no longer clipped to the first handful of nodes, and board context carries every region plus current topology.

Cover art uses that same evidence boundary with deliberately broader illustrative licence. It is not a literal synopsis or a collage of entities. The formulation pass distils the Domain's premise, stakes, mood, and governing constraints into one memorable editorial concept, using symbolic juxtaposition, stylised scale, silhouette, rhythm, negative space, and a decisive palette where they strengthen the promise of the book. The focal idea must remain legible at thumbnail size and leave breathing room for later typography; the generated bitmap itself contains no title or other text. Domain cover generation supplies both the chronological outline and canonical Domain context as labelled source material, in addition to metadata and System rules. Constellation covers supply the member-domain premises and cross-Domain graph, including its rationale and guidance. These sources are retained in full until the shared hierarchical compactor judges their editorial value; callers do not pre-select a handful of allegedly visual facts.

Prose cannot hold a face. Two renders of the same excellent paragraph produce two different people, so today every regeneration re-rolls the character — which is survivable when an entity has one portrait and fatal when it needs twelve images that must be the same person.

The fix is the medium's own practice, and the models already support it: generate the canonical portrait once, then use that image as the reference for every subsequent asset of that entity.

canonical portrait  (text → image, expensive, generated once, human-approvable)
        │  becomes the reference
        ├── expression variants   (reference + "same character, <expression>")
        ├── pose / outfit variants (reference + "same character, <pose>")
        └── event CG appearances   (references for EVERY character in frame)

Consequences to accept up front:

  • The reference chain is why the scout tier cannot make sprites. Reference-consistency models price at the top of the range (~$0.039–$0.04 per output image, i.e. no cheaper than what we already pay), while the cheap tier (flux-schnell at $0.003) is for disposable scouting art. Consistency is the thing being bought; there is no discount on it.
  • The canonical portrait becomes a protected asset. Regenerating it invalidates every derived asset's identity. It should be treated like a decision, with the derived set explicitly re-rendered or explicitly kept.
  • ImageGenRequest needs a reference field, and the model needs to stop being a constant. Both are prerequisites for a sprite set, not follow-ups.

3. The sprite set — axes, and why our portrait is not a sprite

A sprite is not a portrait. The shipped composition line is:

character: 'Single character portrait, head and shoulders, one subject only'

Head-and-shoulders at 3:4 is a bust. The medium's staging idiom — five slots (far-left | left | center | right | far-right), facing, and a shadowed state for the non-speaker, all already in ScriptCastMember — wants a standing figure on transparency, so that the same asset can sit on any plate at any slot. Concretely: alpha channel, consistent framing and scale across the cast (two characters who don't share a scale look like a collage), and a neutral base pose.

The axes worth paying for, in priority order:

  1. Expression (5–8 per character). The highest immersion-per-dollar asset in the entire medium, and the one our data model already asks for: ScriptCastMember.state distinguishes speaking | thinking | acting | entering | exiting | shadowed, and ScriptMoment distinguishes line from thought from reaction. Every one of those is currently rendered with the same face.
  2. Pose / outfit (1–3 per character). Marks arc-scale change — an injury, a rank, a season. This is where typed state earns visible payoff: an ownershipDeltas or systemDeltas change that alters standing should be visible, and the reference chain makes "same person, new coat" cheap.
  3. Everything else — angles, blinks, mouth flaps — is polish. Do not buy it before the reader ships.

4. Location plates and variants

Plates are the cheapest immersion we can buy, because they are pure capital: one 16:9 per location, reused every time a scene sets there, across every route.

Variants (time of day, weather, aftermath) deserve their own line item because they do work no prose can do: returning to a known place changed is the medium's most efficient signal that the world moved. Two rules:

  • A variant is earned by a delta, not by mood: the same location plus a worldDeltas/systemDeltas change that would visibly alter it. Otherwise it's a re-render of something we own.
  • Variants derive from the canonical plate by reference, exactly like sprite expressions — otherwise "the same street at night" becomes a different street.

5. CGs are consumable, so ration them by rule

CGs are the only asset class where the bill scales with the story's length rather than with the world's size, and they cannot be amortised across routes. They therefore need a gate, and the gate should be one we already compute rather than an author's enthusiasm.

Spend a CG where an irreversible delta lands. Decisions §4 already requires that at least one fork branch carry a lasting consequence (systemDeltas / ownershipDeltas / thread closure / entityResolutionDeltas). That is precisely the set of moments a static stage cannot carry — and it is already typed, so CG budget can be allocated deterministically instead of per-scene.

Corollaries:

  • Endings get CGs; middles usually do not. Thread closure is the medium's natural CG moment.
  • A CG must be reachable more than once to be worth its price at all — which favours CGs at bottlenecks (shared by every route through them) over CGs deep in a single branch. This is the same argument branch structures makes on content, arriving independently from the art budget.
  • Gallery unlocking makes a CG a reward, which is the medium's own answer to "was that worth $0.04": the asset keeps paying after the scene ends (README gallery).
  • Cut-ins are the cheap substitute and should absorb most of the demand for "this moment needs impact".

Current CG evidence and next gate

Episode 006's local Experience proof contains three digest-pinned, reference-conditioned CG candidates that work as one causal sequence. This is meaningful evidence for reference roles and contextual composition, but it does not establish an approved identity family, cross-shot continuity, the intended automated provider path, or a production-ready CG lane.

Freeze that sequence. The next proof is an authored editorial clock, restrained sound, two motivated transitions, and human phone-scale review with sound on and off. Only after it passes should Factory add a moment-scoped CG record with source coordinate, irreversible delta or explicit Director exception, reference roles, generation receipt, approval, cost, dependants, gallery state, and orphan status. More images would widen inventory without resolving the current production risk.

6. Dialogue-first is the authentic posture and the cheap one

The reading is the product. ScriptMoment already carries the medium's full register:

line? · thought? · action? · reaction? · narration? · environment? · memory? · document? · comic? · direction?

That is dialogue, interiority, stage action, narration, recollection, and documentary evidence — with zero new assets. Text is a rounding error against images and voice (the exploration spec's ~89% figure), so the richest affordable novel is one that is written densely and illustrated selectively.

Which reframes the whole production question: assets are not what makes it rich, they are what makes it stable. A consistent cast on consistent plates gives the prose a world to happen in; more images do not give it more meaning.

Two registers deserve elevation beyond stage props, because they are what "artifact-driven" means:

  • document — a presented artifact with its own reading surface (a letter, a ledger, an intercept), using the artifact's own 1:1 image as a plate rather than the location's. Cheap (the asset already exists), and the strongest immersion device we are not using.
  • memory — a visually marked recollection (the medium's standard treatment: desaturation, a framing change, a plate variant), which needs a render convention rather than a new asset.

7. POV — the projection boundary is already the mechanism

Single-POV and multi-POV are not new plumbing. Scenario runs on per-seat projection: projectForSeat returns a redacted room plus a domain slice, and the concealment regime (tableMode: "house" | "stealth") is documented as "enforced at the projection boundary (projectForSeat) so a player client never receives the concealed data — not merely hides it."

That is exactly the guarantee a POV needs. It means:

  • Single POV = the reader is bound to one seat; scenes are projected through that seat's boundary, so what the reader does not know is absent, not merely unrendered. Dramatic irony becomes structural rather than authorial discipline.
  • Multi POV = the parallel-stories topology from branch structures, with each track bound to a seat. Its payoff — the reader knowing something a character doesn't — is legible precisely because the boundaries are enforced separately.
  • The reveal is a real event. Crossing POVs (or reaching a route that unlocks another seat's knowledge) is the enforced-route-order mechanism, already derivable from revelation dependencies.

Production consequence: POV is a cost multiplier on scenes, not on assets — the same sprites and plates serve every POV. Multi-POV is therefore the cheapest kind of richness we can add, and the argument against it is craft (does the story want it?), never budget.

8. Style is a lock, not a hint

We have a domain-scoped imageStyle (DomainState.imageStyle), generated with the domain ("A concise visual style directive for all generated images") and threaded into every render path — entity images, cover, map, and the ops handlers, which default to domain.imageStyle. So the mechanism exists.

The Drive can also suggest this shared directive from the same complete chronological outline, canonical Domain context, and System rules used by rich cover formulation. The current style remains candidate evidence, not an instruction to paraphrase. A dedicated semantic-compaction call derives medium, palette logic, light, texture, shape and line language, spatial sensibility, and degree of stylisation as one reusable production grammar across characters, Units, locations, artifacts, boards, and covers. The suggestion only fills the editable Drive field; SET_IMAGE_STYLE remains the sole canonical write and occurs only when the Director chooses Save style.

Two remaining things keep it from becoming a production-grade style lock:

  1. It is optional. A domain with no style produces a set of images in whatever style each prompt happened to imply — the most common way generated worlds look incoherent.
  2. It is not stamped on the asset. Nothing records which style an existing image was rendered under, so after a style edit the domain silently holds a mixed set with no way to identify the stragglers.

At the current render boundary, the authored imageStyle is already stronger than evidence. Render requests remove it from the reducible evidence stream and pass it once as a protected formulation constraint: the formulator must obey it silently and may not quote, paraphrase, improve, replace, or compete with it. The exact directive is then reasserted verbatim at the head of the final image-model prompt. It therefore sits outside both the direct formulation branch and every hierarchical compaction branch. Compaction may improve the subject prompt, but it cannot rewrite the cross-asset style; kind-specific composition and no-text guards are appended at the same protected boundary. A style suggestion is intentionally different: only there is the current style candidate evidence for an editable replacement.

The spec position: for a VN production the style is mandatory, chosen from a named family, versioned, and stamped on every asset. A named family (pixel-art · painterly · cel/anime · photoreal · ink) is better than free text because it can also select the model and the composition line — and because it lets the Director choose fidelity with the cost consequences visible:

  • Pixel-art is the most forgiving fidelity for automated production: reference drift, anatomy errors, and detail inconsistency — the failure modes of generated sprite sets — are largely invisible at low resolution. It is the strongest choice for a first shipped production, not a retro affectation.
  • Photoreal is the least forgiving: the closer to real, the more a wrong face reads as wrong rather than as style.

Changing a locked style is then an explicit, priced decision — re-render the world or keep the mixed set — rather than a silent drift.

9. What a production costs, and the accounting blocker

Order-of-magnitude, at the verified $0.04 production-tier rate, using this document's axes:

CAPITAL (once per world)
  canonical portraits        5 chars ×  1  =  5 imgs
  expression sets            5 chars ×  5  = 25 imgs
  location plates            6 locs  ×  1  =  6 imgs
  plate variants             3 locs  ×  2  =  6 imgs
  artifacts                  4               4 imgs
                                            ─────────
                                             46 imgs ≈ $1.84   amortised over EVERY episode and route

CONSUMABLE (per production)
  event CGs at irreversible deltas    2–4  ≈ $0.08–0.16
  voice per new line-version                the dominant per-episode cost (cache by line+version)
  text generation                           a rounding error

The shape that matters more than the numbers: capital dominates the first production and approaches zero thereafter, so the marginal cost of the tenth episode in a world is voice plus a couple of CGs. An endlessly growing novel gets cheaper per episode, which is the economic case for the whole vision — and it is another argument for reconvergence, since branches that rejoin share their capital.

The blocker, restated because it is worse than "model-blind". In calculateApiCost:

if (isImageGenCall(entry)) return IMAGE_FLAT_RATE_USD;   // 0.04
if (entry.costUsd != null) return entry.costUsd;

The flat rate is checked first, so it outranks even a stamped costUsd — a caller that knows the true price cannot report it. And isImageGenCall matches on any replicate/ model prefix or a generateImage caller. Therefore, today:

  • every image bills $0.04 regardless of model, so a scout-tier render shows zero saving in the gauges;
  • a cheap utility call on Replicate (e.g. background removal, ~$0.0005) is billed ~80× its real cost;
  • a multi-output render would bill once for N images, under-counting — and a sprite set is exactly the multi-output case.

Per-model, per-output image pricing is a prerequisite for the tiering and the sprite set, not a follow-up: without it the ceilings (unit economics) are enforcing against a fiction in both directions. Note also that each ordinary image is two priced calls — a mandatory image-context-compact OpenRouter synthesis plus the render. An oversized source context adds one or more separately metered image-context-compact-chunk calls before the final synthesis; a ready imagePrompt remains candidate evidence beneath the style and fixed kind constraints, but neither bypasses context fitting nor outranks contradictory established continuity. After either branch, the exact authored image style is prepended again to the final render prompt, so the model sees one unambiguous cross-asset production contract. The shared Replicate create/poll boundary emits exactly one terminal render receipt—success or error—for both browser routes and headless operations. Browser callers do not mirror that paid receipt; route-scoped Domain or Constellation context and the operation scope attribute it to the canonical owner.


10. Shipped vs. build

CapabilityState
One image per entity kind, per-kind aspect + compositionshipped
Stored per-entity imagePrompt, editableshipped
Domain-scoped imageStyle threaded into every render pathshipped (optional, exact final-prompt constraint; unstamped on assets)
Map, covershipped
Bytes stored in the canonical record, refs committed by reducershipped
Five staging slots, per-figure state / facing / shadowedshipped (ScriptCastMember)
Full moment register (line/thought/document/memory/…)shipped (ScriptMoment)
Per-seat enforced projection for POVshipped (projectForSeat, tableMode)
Reference-image conditioning (input_image)build — prerequisite for everything below
Per-request model selection (currently fixed in the endpoint URL)build
Expression / pose axes on an entity's asset setbuild
Transparent-background standing sprites at consistent scalebuild
Location plate variantsbuild
Event CGs + cut-ins, gated on irreversible deltasbuild
Style as a mandatory, named, versioned, asset-stamped lockbuild
Per-model, per-output image pricingbuild — blocks honest tiering
Voice cache keyed by line + versionbuild
Document / memory presentation registersbuild
Factory production workspace: entity coverage, lineages, variants, approval, repair, and estimatesbuild

11. The asset-library contract

The asset library is not a folder of images. It is a set of production renditions attached to stable Domain identities and moments, with enough lineage to answer four questions: what does this depict, what was it derived from, where is it valid, and which prepared artifacts already depend on it?

The first contract needs these distinctions:

LayerMeaningExamples
Identity referenceProtected visual or vocal anchor for one entitycanonical portrait, voice identity
Appearance set (skin)A branch/time-valid form of the same entityuniform, injury, age, rank, season
Performance variantExpression, pose, facing, action, or delivery within an appearanceneutral, guarded, recoil, speaking
Place renditionStable location identity and delta-earned variantsbase plate, night, occupied, aftermath
Moment assetConsumable material bound to one staged eventCG, cut-in, voiced line-version
Shared production assetReusable atmosphere or presentation materialmap, effect, sound, motion, UI frame

“Skin” is useful surface language, but it never creates a second character. An appearance set retains the entity id and records its valid branch, earliest moment, latest moment when known, formative state or delta, reference ancestor, style version, generation model, approval state, and dependent Experiences or Worlds. Expressions and poses derive from that appearance, not directly from an unversioned portrait.

Assets do not encode psychology. Acting may yield a Behaviour Reading that requests an expression family or micro-movement; Factory resolves that request to approved coverage. The Entity Interpretation Graph remains an evidence-based, time-specific performance context, the rendition remains presentation, and neither becomes canonical entity state.

12. Factory — the production control surface

Factory is a directional top-level desktop workspace beside Base, Content, Mind, Station, and Signals. It is the supply-side counterpart to Content: Content prepares scene artifacts; Factory prepares the reusable cast, place, prop, sound, motion, and style coverage those scenes require. It should not be hidden inside a single entity inspector because its core question is cross-route coverage: can the selected production be made coherently from the library we have?

Founder roadmap 🔒

Factory owns:

  • an entity-first catalog of identity references, appearance sets, sprites, expressions, poses, voices, motion, and effects;
  • location plates, variants, maps, artifacts, CGs, cut-ins, and shared presentation assets;
  • reference ancestry, style/model/version stamps, branch-and-moment applicability, rights, and provenance;
  • draft → approved → stale/invalidated status, including the blast radius of regenerating an identity;
  • production coverage for a selected branch, route, Experience, or World origin: available, reusable, missing, incompatible, and orphaned;
  • itemized generation and repair estimates, followed by explicit Director approval at the existing paid boundary;
  • the queue of production demands emitted by promoted Fate Exploration candidates.

Factory does not own entity facts, Scene deltas, latent traits, branch selection, or canonical files. The Domain remains the identity and state authority; the existing content-addressed asset storage keeps the bytes; Media Drive remains the lightweight generation/gallery seam. Factory adds the semantic production graph and workflow over those existing seams rather than becoming a second asset store or writer.

First implementation increment: a rebuildable production-memory projection

The lab already has catalogs, source/output digests, asset usage, dependency closure, approvals, costs, dailies, retained failures, demand manifests, and Stage Kit readiness. The missing capability is not another manifest type or asset gallery; it is one queryable projection that joins those existing owners without claiming to replace them.

For a selected route or origin, the projection should report:

  • demanded entity, place, moment, sound, and behavioural-expression coordinates;
  • the exact candidate, approved, demonstrated, missing, incompatible, ambiguous, stale, and orphaned coverage at each coordinate;
  • source ancestry and downstream blast radius for every rendition;
  • human and mechanical evidence separately, including held-out-trial status;
  • estimated and actual cost, repair count, and the paid action that would close a selected gap.

It is rebuildable from the underlying records and writes nothing merely because a query discovers a gap. Its first UI can be modest: route coverage, one entity lineage, dependency impact, and an explicit approval queue are more valuable than broad media browsing. Concurrent paid acquisition remains blocked until the shared budget writer is serialized.

Demand arrives from exploration

Fate Exploration scouts causal terrain cheaply. When a candidate clears promotion, it should emit a coverage manifest rather than immediately generate everything it mentions:

promoted route
→ entities + locations + staged moments + behavioural expression needs
→ reuse against approved Factory lineages
→ missing/incompatible coverage with estimated cost
→ Director confirms a production batch
→ approved renditions pin to the Experience or World origin

The manifest may include branch-specific Acting bindings because those bindings change expected expression and performance coverage. It must not expose the graph as a diagnosis or let an asset request become evidence for the graph.

First Factory proof

Take one character across two divergent branches. Preserve one identity reference; create two branch-and-time-valid appearance sets only where history justifies them; derive a small expression set for each; show which assets can be reused and which route has a gap; then freeze exact revisions into one prepared Experience and one static World tour. Regenerating the identity must report, rather than silently apply, the dependent assets and artifacts it would invalidate.

The proof should also consume one current lab production package, so the projection demonstrates migration from real receipts rather than succeeding only on a new ideal fixture.

13. Open questions

  1. Is the style family a domain property or a production property? (Two productions of one world in two styles is a legitimate artifact — and doubles the capital.)
  2. Does a canonical portrait require human approval before it becomes the reference for a whole set? It is the highest-leverage single asset in a world.
  3. How many expressions is enough? Five is the medium's practical floor; our state enum implies six.
  4. When a sprite set exists and the canonical portrait is regenerated, is the derived set invalidated, re-rendered automatically, or kept with a stamped-style mismatch warning?
  5. Do CG-worthy moments get chosen by delta type alone (§5), or may a Director spend a CG budget by hand?
  6. Is voice per-character (a consistent voice as capital) or per-line (consumable)? The former needs a voice identity per character, exactly parallel to the reference portrait.
  7. Should a production refuse to start when the style is unset, or default to a house style?
  8. Is Factory desktop-only at first, with phone limited to approval and coverage status?
  9. Are appearance-set validity bounds inferred from typed deltas, explicitly curated, or both with the inferred suggestion requiring confirmation?
  10. Does Factory store a route-level coverage manifest, or derive it on demand from pinned Scripts, Acting bindings, and asset lineages?