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.
| Asset | Role in the medium | Ours today |
|---|---|---|
| Character sprite set | the same actor across expressions/poses; the workhorse of the form | one 3:4 portrait per character (SET_CHARACTER_IMAGE, single imageUrl) |
| Location plate | the stable frame the eye rests in; changes rarely and meaningfully | one 16:9 per location |
| Plate variants | time of day, weather, aftermath — the cheapest way to signal that the world moved | none |
| Artifact study | the examinable object; the medium's documentary register | one 1:1 per artifact — but no reader-facing presentation |
| Event CG | the composed moment a static stage cannot carry; consumable | none |
| Cut-in | a small overlay for impact/reaction without leaving the frame | none |
| Unit / creature | non-character presences | one 3:4 per unit |
| Map | spatial orientation across a long work | shipped (buildMapImagePrompts, regions + topology) |
| Cover | the artifact's face | shipped (3:4; displayed in the portrait cover frame) |
| UI frame | textbox, nameplate, rail — the chrome that must not change | reader.md owns it |
| Transitions | fade/dissolve/cut as punctuation between frames | none (a render concern, not an asset) |
| Audio bed | ambience + theme; the largest immersion-per-dollar in the medium | out of scope here |
| Voice | per line-version, cached; the largest per-episode cost | priced, 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-schnellat $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.
ImageGenRequestneeds 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:
- 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.statedistinguishesspeaking | thinking | acting | entering | exiting | shadowed, andScriptMomentdistinguisheslinefromthoughtfromreaction. Every one of those is currently rendered with the same face. - 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
ownershipDeltasorsystemDeltaschange that alters standing should be visible, and the reference chain makes "same person, new coat" cheap. - 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/systemDeltaschange 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:
- 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.
- 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
| Capability | State |
|---|---|
| One image per entity kind, per-kind aspect + composition | shipped |
Stored per-entity imagePrompt, editable | shipped |
Domain-scoped imageStyle threaded into every render path | shipped (optional, exact final-prompt constraint; unstamped on assets) |
| Map, cover | shipped |
| Bytes stored in the canonical record, refs committed by reducer | shipped |
Five staging slots, per-figure state / facing / shadowed | shipped (ScriptCastMember) |
Full moment register (line/thought/document/memory/…) | shipped (ScriptMoment) |
| Per-seat enforced projection for POV | shipped (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 set | build |
| Transparent-background standing sprites at consistent scale | build |
| Location plate variants | build |
| Event CGs + cut-ins, gated on irreversible deltas | build |
| Style as a mandatory, named, versioned, asset-stamped lock | build |
| Per-model, per-output image pricing | build — blocks honest tiering |
| Voice cache keyed by line + version | build |
| Document / memory presentation registers | build |
| Factory production workspace: entity coverage, lineages, variants, approval, repair, and estimates | build |
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:
| Layer | Meaning | Examples |
|---|---|---|
| Identity reference | Protected visual or vocal anchor for one entity | canonical portrait, voice identity |
| Appearance set (skin) | A branch/time-valid form of the same entity | uniform, injury, age, rank, season |
| Performance variant | Expression, pose, facing, action, or delivery within an appearance | neutral, guarded, recoil, speaking |
| Place rendition | Stable location identity and delta-earned variants | base plate, night, occupied, aftermath |
| Moment asset | Consumable material bound to one staged event | CG, cut-in, voiced line-version |
| Shared production asset | Reusable atmosphere or presentation material | map, 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
- 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.)
- 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.
- How many expressions is enough? Five is the medium's practical floor; our
stateenum implies six. - 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?
- Do CG-worthy moments get chosen by delta type alone (§5), or may a Director spend a CG budget by hand?
- 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.
- Should a production refuse to start when the style is unset, or default to a house style?
- Is Factory desktop-only at first, with phone limited to approval and coverage status?
- Are appearance-set validity bounds inferred from typed deltas, explicitly curated, or both with the inferred suggestion requiring confirmation?
- Does Factory store a route-level coverage manifest, or derive it on demand from pinned Scripts, Acting bindings, and asset lineages?