15 KiB
Ghostlight Implementation Plan
Objective
Rebuild Ghostlight Dungeon as one legible world machine: one lifecycle, one typed ontology, one command ingress, one authority derivation path, and one atomic persistence owner. Preserve narrative roleplay where it matters and use direct operational cognition where it is a better fit, without granting either mode additional authority.
Current mechanism
Pushed commit 6bb6869 makes the sealed mailbox/kernel architecture the crate
and executable runtime identity. Pushed commit 13d5136 places app sessions,
the world journal, and controller custody behind the one vendored CultCache
implementation and removes the duplicate persistence dependency. The committed
daemon tree contains no pre-rebuild Session Zero, legacy kernel, scheduler,
assessor, verifier/reconciliation, or legacy-transition module path.
Production has not crossed that source boundary. Yggdrasil still runs legacy
release a4080d4 under an enabled Restart=always unit and a legacy state
root. CultNet 87d0b0f lands shared runtime activation, signed presence-health,
and process-write-lease contracts; Odin cebe425 lands deterministic recipe and
operator-binding parsing, compiled plans, sealed releases, and sanitized
Expected projections. Git materialization, runners, workload and route drivers,
lease/fencing, CultCache/CultMesh control-plane state, and Idunn main integration
remain absent. The active move is that actuation integration and one-way live
cutover, not more Ghostlight runtime wiring.
Authority map
- Owner: one sealed per-world
WorldKernelowns its private aggregate, reducer, ID allocator, and journal writer. The public crate boundary exposes only create/open, immutable snapshot, command submission, and typed receipts; it does not expose mutableWorldState, the canonical entity-ID allocator, reducer entry points, or generic journal writes. - Inputs: an authenticated
CommandEnvelopewith stable command ID, exact world and expected revision, principal evidence, one closed command body, and exact source receipts where needed. The kernel privately loads current state, derives authority, and supplies deterministic clock or entropy. Human, Interpreter, operational-agent, author, scheduler, and external-owner output is proposal material only. - Outputs: a rejection receipt changes nothing. An accepted command returns
one
WorldCommit, including any reducer-issued ID mapping, and atomically appends one digest-chained revision. A structurally valid command that lowers to no factual, speech, lifecycle, or time mutation returnsNoEffectand does not advance revision, change either digest, allocate IDs, or append a journal row. - Derived state: immutable snapshots and subject views, currently executable
affordance catalogs, revision-bound
DecisionOpportunityvalues, scheduler queues, translation gaps, projections, news, transcripts, model receipts, checkpoints, coverage counts, and evaluations. Translation gaps may be kept as inference/evaluation telemetry or motivate a later explicit author proposal; they are not aWorldStatecomponent, event, or mutation. - Forbidden writers: public state setters or ID issuers; direct reducer callers; generic CultCache insert/append handles; schedulers or controllers that assign authority, mint executable affordances, consume opportunities, or commit; automatic translation-gap lowering; empty commits; the old Session Zero publication path, aggregate Campaign writer, legacy transition projection, alternate elaboration and mutation inputs, verifier/reconciliation agents, recovery repair loops, and external consumer callbacks.
- Shared paths: draft creation, approval, activation, player action, autonomous action, author expansion, time, travel, imports, reload, and administration use create/open/snapshot/submit and the same private derive/reduce/commit primitive. Controller harnesses submit an exact typed proposal as an ordinary command. Recovery opens and verifies the same journal; it cannot call a repair reducer.
- Cut line: the rejected public ontology stays deleted. Translation-gap records stay outside canonical world state. No public constructor or helper may issue a canonical ID, mutate an aggregate, invoke the reducer, or write the journal. Obsolete writers are deleted or reduced to read-only evidence before their replacement path is called complete.
- Verification layer: compile-time visibility proves that an external crate
cannot invoke the ID allocator, mutate
WorldState, call the reducer, or obtain the journal writer. Focused black-box tests prove that a caller-supplied unknown ID cannot become canonical, plus atomic rejection, no-op non-commit, reducer-only ID allocation, exact restart/digest recovery, translation-gap non-authority, and opportunity rejection when revision, controller, scope, or executable affordance does not match.
SessionZeroKernel is no longer a target owner; Draft is a WorldState phase.
Aggregate Campaign state is no longer an owner; aggregate views are derived
from typed components. A checkpoint is no longer a repair authority; it is a
projection of committed history.
Invariants
- Every world mutation passes through one deterministic reducer and one atomic compare-and-swap commit.
- Authority is derived inside the kernel from canonical membership, governance, custody, jurisdiction, and controller scope.
- Each autonomous decision scope has exactly one controller. Cognition mode changes representation only; there is no fallback or double action.
- Narrative interpretation is total. Persona prose is preserved; faithful typed proposals and exact translation gaps account for the turn. The Interpreter does not accept, reject, or commit world state.
- Structural invalidity is rejected deterministically before persistence and without a model verifier. A failed batch changes nothing.
- Private knowledge remains scoped until an explicit communication command changes it.
- External consumers retain sovereignty. Ghostlight views, proposals, and acknowledgements cannot mutate external-owned state.
- Sparse causal sufficiency controls elaboration. Counts and qualitative review remain evaluation evidence only.
- Restart reconstructs the exact committed world and idempotency history; a recovery loop cannot repair or reinterpret it.
- Canonical IDs are allocated only while a complete private reduction is being admitted. Rejected and no-effect commands cannot consume or reveal them.
- Controller assignment and affordance grants are canonical aggregate state. Current executability and decision opportunities are deterministic revision-bound derivations. A scheduler can order those opportunities but cannot mint their authority.
Implementation sequence
1. Seal the aggregate boundary — landed
Establish WorldKernel with a private aggregate and private journal child before
publishing ontology types. Expose only create/open, immutable snapshot, submit,
and typed receipts. Make canonical state mutation, ID allocation, reduction,
and CultCache writes unreachable from outside the owning module. Prove the
visibility boundary and the one-writer transaction seam before widening the
state vocabulary.
2. Add the minimal private reducer — landed
66ed2ec implements the state and command vocabulary required for Draft
creation, approval, activation, one human action, and one autonomous action.
The aggregate owns controller assignments and affordance grants and derives
exact revision-bound opportunities. IDs issue only after complete seed
validation; rejected and empty reductions do not commit. Places, relations,
resources, external ownership, and other ontology components wait for a live
typed causal boundary.
3. Prove the private authority slice — landed
Eighteen focused tests exercise Draft creation, approval, activation, one human decision, one NarrativePersona-controlled decision, and one OperationalAgent-controlled decision through the same aggregate action command. They cover exact controller scope and affordance matching, revision-bound opportunity rejection, restart, immutable genesis, idempotency, serialized mailbox ownership, cancellation, lost reply semantics, and forged-history rejection. Controller mode changes representation only; it does not create a second reducer path.
Live NarrativePersona integration still requires the Projector to emit prose
context, the Persona to return prose only, and the runner first to persist an
immutable receipt-bound Persona
turn. The Interpreter returns a completed report containing that exact
noncanonical source prose, zero or more typed proposals, and zero or more
translation gaps. Spoken words require a typed speech proposal. Invalid capture
spans and normal step exhaustion become exact unresolved-source gaps. Any
transport or dispatch fault before explicit finalization discards partial
captures and leaves the immutable source pending for a fresh attempt; it does
not become semantic interpretation failure.
Live OperationalAgent integration receives only its permissioned typed
view and tools. Its proposals enter the same command path as narrative
proposals. It does not bypass projection privacy, authority derivation, or the
reducer.
4. Expose, wire, and cut — landed in source
Commits 6bb6869 and 13d5136 expose the replacement facade as the crate and
executable runtime identity while keeping mutable state, ID issuance,
reduction, journal access, and authenticated-caller construction sealed.
Startup creates or opens one replacement owner and spawns one mailbox; runtime
consumers receive only the mailbox-facing command and snapshot surface.
Draft creation, approval, activation, player decisions, and autonomous controller proposals now enter that boundary. The committed daemon tree no longer contains the old Session Zero, legacy kernel, scheduler, verifier, reconciliation, or recovery-writer routes. There is no dual-write or live compatibility router in source.
Resolution, elaboration, transcript/news projection, and external publication remain future typed consumers at their causal boundaries. Model transport, Vault retrieval, Heimdall identity, Eve/CultMesh projection, Idunn health, and external adapters survive only where their ownership remains clean.
5. Integrate deployment actuation and cut production — active
The deterministic foundation is landed: target recipes and Idunn operator bindings compile into private plans and sealed releases, and only a sanitized Expected incarnation may leave that control plane. Shared CultNet contracts own runtime activation, service-signed Present health, and process-bound write leases. Idunn main integration and the Git, runner, workload, lease/fencing, route, CultCache, and CultMesh drivers are not implemented yet.
Targets own constrained launch declarations, never raw unit or container templates. The operator binding selects the workload driver, which alone lowers that declaration into process-manager configuration. Likewise, deterministic plan validation retains exact commit, tree, recipe, and Gitlink facts but proves neither ancestry, signatures, nor object custody; the narrow Idunn-owned source driver must establish those facts before actuation.
The integrated path must publish Expected from the sealed plan and release, record Idunn's observation of the exact runtime activation, and require the service's signed Present health. A stateful candidate receives its process-bound write lease before it opens writable state. Odin alone correlates Expected, activation, and Present into Ready. Only after Ready may Idunn change stable route membership and drain the incumbent. The deployment brake gates body changes; same-release continuity remains separately owned and may be stopped only by an explicit lifecycle brake.
Deploy CodexConnector first, then Ghostlight. Ghostlight's live cut archives the entire legacy state root, creates a clean world-v2 root, and validates a complete allowed live layout. After route, health, process, write lease, restart, and negative legacy checks agree, delete the old units, releases, state roots, acceptance debris, gamecult-ops target deploy programs, and local run scaffolding.
6. Contract verification
Required black-box proofs:
- Draft → Active → player action → autonomous action → restart preserves the exact digest and commit history.
- Invalid ontology patches are atomic and model-free; a typed causal boundary can activate sparse new state.
- Models, scheduler, projection, and recovery are inert without an explicit aggregate submission.
- Private knowledge stays private until explicit communication.
- External proposals and acknowledgements cannot mutate consumer-owned state; only a fresh owner snapshot can update the local observation.
- Narrative and operational controllers have exact disjoint scopes, never fall through, and never consume one opportunity twice.
- Interpretation always completes semantically and preserves unlowered material as translation gaps.
- A no-effect command leaves revision, state digest, commit digest, ID allocation, and journal length unchanged.
- An external crate cannot obtain mutable aggregate state, invoke the canonical ID allocator, call the reducer, or write the journal; a caller-supplied unknown ID is rejected rather than admitted.
- A decision proposal is rejected when its revision-bound opportunity, controller, scope, or currently executable affordance is wrong; the scheduler cannot manufacture or consume authority.
A 1,200-actor synthetic fixture may measure load after these pass. It cannot serve as an ontology or completeness gate. No live Delvehold acceptance run is admitted before the focused suite passes and the old writers are structurally unable to override the aggregate.
Subtraction budget
Prefer deletion, collapse, or reuse before adding surfaces. The replacement buys explicit capabilities: one lifecycle owner, one structural reducer, one persistence writer, disjoint cognition controllers, total interpretation, and restart proof. It must retire more writer and stage liability than it adds. Review each completed pass for modules, binaries, schemas, dependencies, processes, and tests added or removed.
Build budget
- Build host: Yggdrasil through Idunn-configured pinned Linux containers. Do not build the deployment body on Windows.
- Control plane:
odin-corelibrary tests plusidunn-daemonlibrary/binary checks; Linux x86_64 release artifacts areidunnandidunn-provisiononly. - Targets:
codex-connectorlibrary tests with and withoutdaemon, then thecodex-connectorrelease binary withdaemon;ghostlight-dungeonfocused tests, then theghostlight-dungeonrelease binary. Default target features remain unchanged unless the target-owned recipe names an existing required feature. - Output roots, container digests, cache mounts, current footprints, retention, and expected deltas are operator-binding inputs and must be measured on Yggdrasil before the first build. No workspace-wide, all-target, clean, or cross-platform build is admitted.
Deferred research lanes
The 36-case agency corpus, separate-account multiplayer proof, visual/Ink fixtures, newspaper variation, and direct-tool Persona comparison remain useful research lanes. They do not steer the authority rebuild and cannot reopen a retired writer. Historical plans and results remain recoverable through Git, the evidence ledger, and the frozen pre-rebuild system map.