498 lines
23 KiB
Markdown
498 lines
23 KiB
Markdown
# Ink Branching Scenes
|
|
|
|
Ink is the branching scene format.
|
|
|
|
Ghostlight should not invent a parallel dialogue-tree language unless Ink
|
|
fails a concrete requirement. Ink already gives us readable interactive fiction,
|
|
choices, knots, stitches, variables, compiled JSON, and a format writers
|
|
can inspect without needing to wear a compiler helmet indoors.
|
|
|
|
Ghostlight's job is the machinery around Ink:
|
|
|
|
- build actor-local awareness from agent state and scene state
|
|
- project plausible speech and non-speech choices
|
|
- save generation receipts when a model proposes branches
|
|
- annotate why those choices make sense
|
|
- preserve listener interpretation as separate from actor intent
|
|
- record consequence surfaces for later state mutation
|
|
- keep fuzzy social updates reviewed until there is training data
|
|
- compile Ink into game-consumable JSON
|
|
|
|
Ink owns the playable branch structure. Ghostlight owns the psychological,
|
|
cultural, memory, relationship, and consequence rationale.
|
|
|
|
## Runtime Shape
|
|
|
|
The artifact flow is:
|
|
|
|
```text
|
|
agent state + scene state + lore grounding
|
|
-> local awareness
|
|
-> projected branch choices for the acting character
|
|
-> selected branch as observable action
|
|
-> event resolution from selected observable action
|
|
-> participant appraisals and reviewed state mutation
|
|
-> next actor local awareness from updated state
|
|
-> next actor action
|
|
-> Ink scene
|
|
-> compiled Ink JSON
|
|
-> reviewed training annotations
|
|
-> selected branch consequences
|
|
-> state, memory, belief, and relationship updates
|
|
```
|
|
|
|
The Ink file should be readable as Aetheria content on its own. The sidecar
|
|
training annotation should explain which Ghostlight state produced each branch
|
|
and which consequences are automatic, reviewed, or deferred.
|
|
|
|
Each character turn must be generated from that character's local awareness.
|
|
The protagonist-choice generator should not receive the responder's private
|
|
state. The responder generator should not receive the protagonist's private
|
|
intent except as an observable action, spoken text, gesture, object use,
|
|
silence, or other perceivable cue. A listener is allowed to misunderstand.
|
|
|
|
Participant appraisal is symmetrical. If an action hurts, threatens, reassures,
|
|
humiliates, obligates, or overloads anyone present, that change is consolidated
|
|
for the affected character before the next actor is selected. The next actor may
|
|
reply, walk away, comply, escalate, or end the interaction. A branch artifact can
|
|
still display this as `choice -> reaction`, but Ghostlight should model it as
|
|
turns over updated state, not as a mandatory paired response.
|
|
|
|
One-shot generation of both sides is allowed only as bootstrap scaffolding, and
|
|
must be marked as such in the capture review. It is not the target runtime
|
|
shape.
|
|
|
|
The current target path is source-grounded coordinator state, projected local
|
|
context, reviewed character turns, branch compiler materialization, and IF
|
|
artifact review.
|
|
|
|
## Ink Comments
|
|
|
|
Use Ink comments for lightweight traceability in writer-facing drafts:
|
|
|
|
- `ghostlight.scene`
|
|
- `ghostlight.fixture`
|
|
- `ghostlight.branch`
|
|
- `ghostlight.action`
|
|
- `ghostlight.intent`
|
|
- `ghostlight.npc_response`
|
|
- `ghostlight.consequence`
|
|
- `ghostlight.training_hook`
|
|
- `aetheria.flashpoint`
|
|
|
|
Use `//`, not Ink tags (`#`), for this metadata in drafts. Inky exposes tags in
|
|
preview, which makes Ghostlight state leak into the readable scene. The
|
|
sidecar remains the machine-readable receipt; comments are only local handles
|
|
for humans and simple tools.
|
|
|
|
## Sidecar Annotations
|
|
|
|
Each Ink scene should have a `.training.json` sidecar with:
|
|
|
|
- source fixture reference
|
|
- protagonist and NPC ids
|
|
- actor-local awareness summary
|
|
- projection controls
|
|
- branch ids and Ink knot paths
|
|
- action type and actor intent
|
|
- state basis
|
|
- reviewed consequences
|
|
- training hooks
|
|
- mutation policy
|
|
|
|
This sidecar is intentionally not a new branching format. It is a receipt. Ink
|
|
remains the scene tree; the sidecar says why the tree grew that way and which
|
|
state changes a reviewer accepted.
|
|
|
|
Visual planning should live beside the sidecar, not inside it. Use a separate
|
|
`.visual.json` artifact for illustrated replay data: style cue, visual scene
|
|
anchors, image prompts, character refs, prompt assembly rules, and visual
|
|
modifiers. The training annotation may reference that file with
|
|
`visual_plan_ref`, but it should remain focused on branch semantics and
|
|
mutation surfaces.
|
|
|
|
## Mutation Policy
|
|
|
|
Ink variables can record local playthrough outcomes. They should not silently
|
|
become canonical Ghostlight state.
|
|
|
|
Automatic:
|
|
|
|
- Ink compilation
|
|
- branch id and knot validation
|
|
- local variables for the current playthrough
|
|
- mechanical comment handles and training hook checks
|
|
|
|
Manual reviewed until trained:
|
|
|
|
- relationship deltas
|
|
- belief updates
|
|
- memory writes
|
|
- listener misread classification
|
|
- activation changes
|
|
- promotion from branch outcome into durable Aetheria lore
|
|
|
|
The current accepted-as-draft scaffold lives in
|
|
`examples/ink/pallas-species-strikes.branch-and-fold.v0.ink`.
|
|
|
|
## Cross-Scene Consequence Carryover
|
|
|
|
Ghostlight branching scenes should not behave like disconnected dialogue samples.
|
|
Interactive fiction needs consequences that survive the scene boundary. A branch
|
|
choice should write durable effects into later context: relationship stance,
|
|
perceived motives, resource costs, authority flags, object custody, active
|
|
constraints, unresolved hooks, and available future options.
|
|
|
|
For training data, every material branch should preserve:
|
|
|
|
- the player/NPC-visible choice or action
|
|
- the immediate responder output
|
|
- accepted world-state, resource, memory, and relationship deltas
|
|
- branch flags that later scenes must read
|
|
- deferred consequences that should surface later rather than immediately
|
|
- scene text showing how the consequence changes the feel of the next beat
|
|
|
|
The coordinator owns this continuity for now. Later, the trainable coordinator
|
|
model should learn to carry these consequences forward without flattening them
|
|
into cosmetic callbacks. If a choice does not change later affordances, trust,
|
|
resources, risk, or interpretation, it is probably not a meaningful branch.
|
|
|
|
A complete interactive fixture needs an ordinary-world opening, consequential
|
|
branches before the crisis peak, and a resolution that visibly reflects earlier
|
|
choices. A single tense exchange can prove a seam; it is not enough to prove the
|
|
story machine.
|
|
|
|
## Branch And Fold
|
|
|
|
Do not model every choice as an indefinitely isolated authored subtree. Strict
|
|
worldline splitting creates a combinatoric writing burden after a handful of
|
|
choices, which interactive fiction authors have been discovering the painful
|
|
way since approximately the first time someone let a player open a second door.
|
|
|
|
Ghostlight should branch locally and fold structurally:
|
|
|
|
```text
|
|
choice
|
|
-> consequence packet
|
|
-> normalized state deltas
|
|
-> shared later scene reads compact variables
|
|
-> conditional options, callbacks, imagery, and relationship texture
|
|
-> major route split only when convergence would be false
|
|
```
|
|
|
|
Most branches should converge onto shared later scenes. The consequences should
|
|
survive as compact variables, bands, and flags rather than bespoke scenes for
|
|
every exact history.
|
|
|
|
Good consequence state looks like this:
|
|
|
|
- `sella_trust_maer: wary`
|
|
- `ledger_debt_level: high`
|
|
- `clinic_staff_exhaustion: true`
|
|
- `veyr_evidence_disclosed: partial`
|
|
- `isdra_reads_maer_as: procedurally_dangerous`
|
|
- `route_authority_pressure: escalated`
|
|
|
|
Those variables should alter later scenes by changing available options,
|
|
relationship posture, timing pressure, resource costs, callback prose, visual
|
|
state modifiers, and participant appraisals. They should not usually require a
|
|
fully separate scene route.
|
|
|
|
Use coarse bands instead of fake precision. `blocked`, `wary`, `conditional`,
|
|
`cooperative`, and `personally_invested` are more useful than pretending the
|
|
story can meaningfully maintain 37 decimals of trust. The same applies to heat
|
|
debt, legal exposure, institutional pressure, staff exhaustion, reputation, and
|
|
social suspicion.
|
|
|
|
Major route splits are allowed when a consequence changes the playable world so
|
|
much that folding would lie. Examples:
|
|
|
|
- a character dies, leaves, defects, or becomes unavailable
|
|
- a location is destroyed, locked, opened, or politically inaccessible
|
|
- a faction becomes hostile, allied, exposed, or legally empowered
|
|
- a key object is destroyed, stolen, transferred, or transformed
|
|
- the protagonist loses or gains institutional authority
|
|
- a quest route, rescue path, market, technology, or branch-local future opens
|
|
or closes entirely
|
|
|
|
The coordinator owns the fold decision for now. Every material branch should
|
|
record whether it folds into an existing later scene, opens a conditional
|
|
variant inside that scene, or creates a justified route split. If a route split
|
|
is created, the artifact should name the reason and the expected future writing
|
|
debt. Trees are cheap to grow and expensive to prune. The machine should not
|
|
act surprised by botany.
|
|
|
|
## Branch Compiler
|
|
|
|
The Branch Compiler is the organ that turns Ghostlight scene intent into a
|
|
playable Ink artifact. It is not the character agent, the responder, the
|
|
appraiser, or the final reviewer. It assembles branch structure from already
|
|
available scene state, projected actor affordances, proposed actions, accepted
|
|
consequence packets, and coordinator constraints.
|
|
|
|
The Branch Compiler receives:
|
|
|
|
- fixture brief and scene spine
|
|
- source-grounded lore digest
|
|
- current world, scene, resource, relationship, and branch state
|
|
- actor-local branch candidates, including speech and non-speech actions
|
|
- responder outputs or coordinator-authored placeholder reactions
|
|
- consequence packets from reviewed turns
|
|
- branch-and-fold plan
|
|
- visual continuity requirements
|
|
- schema and Ink formatting constraints
|
|
|
|
The Branch Compiler emits:
|
|
|
|
- readable `.ink` scene content
|
|
- Ink variables, knots, stitches, choices, gathers, and conditionals
|
|
- a `.training.json` sidecar tying each branch to state basis, action intent,
|
|
consequence surfaces, and later callbacks
|
|
- compiler notes for fold decisions, route-split decisions, and known review
|
|
risks
|
|
- image prompt anchors and branch/state modification handles when the fixture is
|
|
meant for illustrated output
|
|
|
|
The Branch Compiler may propose structure. It must not invent hidden character
|
|
truth, private motivations, or durable social mutations as if compilation made
|
|
them real. Character behavior comes from projected local context and responder
|
|
or coordinator-authored action proposals. Social interpretation and memory
|
|
changes come from appraiser/mutator review. The compiler's job is to make the
|
|
branching artifact playable, legible, and traceable.
|
|
|
|
The compiler should prefer compact state variables, bands, and flags over
|
|
runaway branch trees. It should create major route splits only when the
|
|
coordinator or reviewed consequence packet says folding would falsify the
|
|
world. When it folds branches, it must preserve the variables and callbacks that
|
|
make the fold honest.
|
|
|
|
The Branch Compiler output is draft until the IF Artifact Reviewer accepts it.
|
|
That separation matters. A compiler can make a scene valid Ink while still
|
|
producing cosmetic choices, fake folds, unused variables, or endings that ignore
|
|
the whole moral machinery. Valid syntax is not wisdom. It is barely hygiene.
|
|
|
|
## IF Artifact Review
|
|
|
|
Branching fixtures need an independent review pass before acceptance. The
|
|
coordinator should not be the only thing grading its own Ink, sidecar, and
|
|
branch logic. That is how a scene ends up proudly tracking variables that do
|
|
nothing except sit there in a tiny uniform.
|
|
|
|
The reviewer may start as a prompted specialist sub-agent. Later it should
|
|
become evaluator/classifier training data and eventually a trainable review
|
|
organ. Its job is not prose polish. Its job is to catch false consequence.
|
|
|
|
The reviewer receives:
|
|
|
|
- the Ink file
|
|
- the `.training.json` sidecar
|
|
- the coordinator artifact
|
|
- the intended branch plan, when available
|
|
- the declared state variables, flags, bands, resources, risks, and visual
|
|
modifiers
|
|
- any compiled Ink or validation output available for the fixture
|
|
|
|
The reviewer emits:
|
|
|
|
- `accepted`, `needs_revision`, or `rejected`
|
|
- severity-ranked findings
|
|
- a fake-variable audit
|
|
- a choice-consequence audit
|
|
- a fold/callback audit
|
|
- a state-gated prose audit
|
|
- a visual-continuity audit
|
|
- major-route-split justification notes
|
|
- specific required fixes
|
|
|
|
Acceptance requires every material choice to change at least one later surface:
|
|
|
|
- available options
|
|
- scene route or justified route split
|
|
- relationship, trust, appraisal, or social standing
|
|
- resource cost, time pressure, legal exposure, authority pressure, heat burden,
|
|
exhaustion, or other risk
|
|
- object custody, evidence quality, access, or technology state
|
|
- later callback prose implemented as an actual conditional
|
|
- ending texture or outcome band
|
|
- visual state modifier tied to a real branch flag or state variable
|
|
|
|
Every declared variable must either be read later or be marked as telemetry-only
|
|
in the sidecar. Ominous variables need threshold behavior. If a variable named
|
|
`authority_pressure` rises and nobody with authority ever reacts, the artifact
|
|
fails review. If `heat_time` counts down and no route, ending, resource cost, or
|
|
staff condition changes, the artifact fails review. The name is allowed to be
|
|
dramatic only if the machinery has teeth.
|
|
|
|
Any prose that says "if X happened" must be implemented as an actual conditional
|
|
or moved into reviewer/coordinator notes. Writer-facing text should not name a
|
|
branch possibility while dodging the state check that proves which version of
|
|
history occurred.
|
|
|
|
Common failure labels:
|
|
|
|
- `potemkin_state`: a tracked variable never materially changes the artifact
|
|
- `cosmetic_choice`: a choice changes wording but not affordance, cost, risk,
|
|
appraisal, callback, visual state, or outcome
|
|
- `missing_state_read`: a set variable is never read by later Ink, sidecar, or
|
|
coordinator consequence logic
|
|
- `fake_fold`: branches claim to fold, but the folded scene ignores their state
|
|
- `unearned_convergence`: branches converge despite consequences that should
|
|
make convergence false
|
|
- `unjustified_route_split`: a separate route exists without enough world or
|
|
story consequence to justify the writing debt
|
|
- `state_named_instead_of_checked`: prose mentions alternate branch states
|
|
instead of checking variables
|
|
- `visual_callback_missing`: image modifiers or visual prose ignore branch
|
|
consequences that should be visible
|
|
- `authority_without_consequence`: institutional pressure rises but never bites
|
|
- `resource_without_cost`: ledgers, heat, staff time, supplies, or access are
|
|
invoked without affecting later choices or outcomes
|
|
- `ending_ignores_major_state`: the ending does not respond to major variables
|
|
established earlier
|
|
|
|
Early branch-and-fold review exposed this exact class of failure: variables can
|
|
look important while doing nothing. Review must force important variables to
|
|
alter gates, callbacks, visuals, appraisals, or outcomes before a fixture enters
|
|
the accepted corpus.
|
|
|
|
## Scene Imagery
|
|
|
|
Ghostlight scenes are also website content. A complete fixture should emit a
|
|
visual plan artifact alongside prose and training receipts so story branches can
|
|
be illustrated without a later model guessing what the room looked like.
|
|
|
|
Interactive fiction replay also needs screen rhythm. A narrative scene may move
|
|
through several visual sections: establishing shot, workstation, break table,
|
|
object closeup, alarm state, crowd line, supervisor arrival, aftermath. These
|
|
should be segmented so an InkJS replay can click through the scene at the pace
|
|
the story needs. A pivotal beat may be a single sentence on its own screen when
|
|
the point is to let the image and silence do the work.
|
|
|
|
Each distinct visual section should preserve an art-direction block with:
|
|
|
|
- global style cue: the fixture-level visual language when the art direction
|
|
depends on a specific non-default look
|
|
- establishing shot: location, scale, camera distance, and dominant geometry
|
|
- light and color: practical light sources, palette, exposure, haze, glare,
|
|
reflection, water, vacuum, screen glow, or other atmosphere
|
|
- bodies and interfaces: how each relevant body occupies the space, including
|
|
nonhuman access, assistive infrastructure, suits, avatars, wet/dry boundaries,
|
|
displays, tools, and machinery
|
|
- material evidence: objects, damage, records, ledgers, cargo, alarms, clothing,
|
|
stains, frost, heat shimmer, or other concrete traces of what has happened
|
|
- branch marks: visible changes caused by earlier choices, such as a sealed
|
|
hatch, an exhausted staffer, a live debt ledger, missing equipment, guarded
|
|
posture, or a route marker left blinking
|
|
- base image prompt: one stable prompt for the unbranched scene, suitable for
|
|
generating the reusable background or canonical key frame
|
|
- branch modification prompts: additive edit prompts for visible consequences,
|
|
changed character positions, opened or sealed routes, damaged objects,
|
|
lighting changes, emotional posture, crowd pressure, or other scene states
|
|
|
|
Named characters need stable visual references. An image model does not know
|
|
what Lio Vale looks like because the prose named Lio Vale. Each illustrated
|
|
fixture should define `visual_character_refs` for recurring named characters:
|
|
body type, apparent age range if relevant, face/hair/skin or equivalent visual
|
|
identity, clothing and equipment, silhouette, posture language, and
|
|
`do_not_change` continuity details. Scene prompts may then reference those
|
|
character refs instead of repeating the whole description every time.
|
|
|
|
Prompts must be imagegen-ready. Do not rely on unexplained Aetheria jargon as
|
|
if the image model knows the lore. If the prompt says "wet-service cradle" or
|
|
"dry-operation harness," it should also describe the visible thing according to
|
|
the faction, location, and labor regime. A Navigator comfort habitat and an AU
|
|
industrial yard should not quietly become the same room. If a scene uses a
|
|
biodrone limiter interface, cavity seal assembly, or life-support bypass kit,
|
|
describe the shape, scale, materials, lights, cables, seals, or displays that
|
|
make it drawable.
|
|
|
|
The same rule applies to environments. "Manifold line," "cavity yard,"
|
|
"supervisor glass," and "anchor rail" are not images by themselves. A base
|
|
prompt should describe the physical space a general image model can draw:
|
|
corridor shape, wall/ceiling/floor geometry, pipe runs, cable bundles, panels,
|
|
screens, rails, doors, windows, gauges, warning lights, materials, scale, and
|
|
where bodies stand inside that geometry.
|
|
|
|
Image prompts should be affirmative. Describe the desired geometry, material,
|
|
composition, lighting, bodies, tools, and state. Negative prompt constructions
|
|
such as "do not draw X," "without X," or "rather than X" tend to feed the image
|
|
model the wrong object and then hope it obeys the minus sign. That is weak
|
|
magic. Put the target in the prompt, and keep forbidden assumptions in reviewer
|
|
notes or validation errors.
|
|
|
|
For Aetheria Bloom habitats, prompt the engineered object directly: rotating
|
|
cavity-shell infrastructure, consolidated asteroid rubble/debris, TCS
|
|
substrate, shell plating, ribbed supports, seals, hub/spoke interfaces,
|
|
manifolds, and service systems. Source-specific exceptions should be represented
|
|
as their own positive visible description.
|
|
|
|
Every visual section should identify:
|
|
|
|
- `visual_scene_id`: stable handle for the screen or key frame
|
|
- `ink_anchor`: knot, stitch, or comment handle where the visual applies
|
|
- `base_image_prompt`: durable scene prompt for the unmodified frame
|
|
- `visible_characters`: characters allowed in the frame and their default
|
|
position or stance, plus a `visual_ref` when the character is named
|
|
- `state_image_modifiers`: additive prompts tied to explicit variables,
|
|
thresholds, or route flags
|
|
- `branch_image_modifiers`: additive prompts tied to specific branch ids
|
|
- `visual_continuity_notes`: facts that must remain stable across edits
|
|
|
|
Prompt assembly for illustrated replay should combine:
|
|
|
|
```text
|
|
global style cue
|
|
+ visual_character_refs for named characters actually visible in this rendered frame
|
|
+ visual section base_image_prompt
|
|
+ triggered state or branch image modifiers
|
|
```
|
|
|
|
The base image prompt is allowed to focus on the room and staging only if the
|
|
assembled prompt includes the relevant character refs. If a tool sends the base
|
|
prompt alone to imagegen, the base prompt must carry enough character detail by
|
|
itself. The same applies to visual style: if a fixture depends on a specific
|
|
look, the assembled prompt must carry that style cue every time. Names are
|
|
handles, not faces.
|
|
|
|
Keep `visual_continuity_notes` out of assembled image prompts. They are tooling
|
|
and review constraints for keeping repeated generations coherent. If a
|
|
continuity fact needs to reach the image model, rewrite it as affirmative,
|
|
concrete visible prompt text in the base prompt, a character ref, or a
|
|
branch/state modifier.
|
|
The image generator only sees the prompt you send it. It does not remember the
|
|
previous scene unless a real image-editing workflow supplies that image as
|
|
input.
|
|
|
|
The coordinator owns this surface for now. The responder should not receive
|
|
omniscient visual art direction unless the character can observe it. Character
|
|
packets may receive the local visible subset: what this actor can see, hear,
|
|
touch, smell, monitor, or infer from their interface.
|
|
|
|
Visual continuity is part of consequence carryover. If an earlier branch cost
|
|
heat, trust, time, equipment, or social standing, the later scene should show
|
|
that cost somewhere on the page or in the frame. Otherwise the choice may be
|
|
mechanically recorded while still feeling fake, which is the stupid little
|
|
trapdoor interactive fiction keeps setting for itself.
|
|
|
|
When continuity matters, use one durable base visual prompt and branch/state
|
|
modification prompts that describe only what changed. The base prompt owns the
|
|
room, palette, dominant geometry, key props, bodies, and interface layout. A
|
|
modification prompt owns the delta: Sella moves from the dryside console to the
|
|
decon sleeve, the route marker flips from amber to white, a wet access hatch
|
|
seals, an exhausted staffer appears behind the glass, Maer's ledger panel gains
|
|
a live debt line.
|
|
|
|
Keep these prompts separate from canonical prose:
|
|
|
|
- `base_image_prompt`: stable scene anchor
|
|
- `state_image_modifiers`: reusable prompts for common scene states
|
|
- `branch_image_modifiers`: prompts tied to specific branch ids
|
|
- `visual_continuity_notes`: non-prompt reminders about what must remain stable
|
|
|
|
Image edits are allowed to stylize, compose, and beautify. They are not allowed
|
|
to silently change canonical facts. If an edit introduces a new visible object,
|
|
body affordance, damage mark, or faction symbol that was not in the scene state,
|
|
the coordinator must either reject it, mark it as noncanonical illustration
|
|
noise, or promote it through the normal reviewed lore/state path. The picture
|
|
does not get to smuggle a gun onto the mantel just because it had a strong
|
|
personal brand that morning.
|