flybrain/docs/design/session-framework
dev 6655a1b1c6 session: coherent all-participant checkpoint and recovery
STATE-01 over the FLYSESS1 envelope CONTRACT-01 specified.

fly-session gains a `state` module: the durable store with its generations, its
rotation and the commit order of checkpoint-envelope-v1 section 5, where the store
manifest rename is the durable commit point; a compatibility block whose comparison
names the identity that differs rather than one opaque digest; and a bounded writer
that owns its payload handles until the bytes are committed or the job fails.

The writer's queue slot is taken before the first State.Capture, so a saturated
writer refuses a capture rather than queueing it without bound, and the refusal is a
BUSY the stepping session survives. Capture and durability are two events: a capture
completes when an immutable capture exists, and only the store manifest rename moves
the durable mark. A lost save reply is an outcome, and the resolution asks the store
about the same checkpoint instead of saving again.

Both worker roles implement State.Capture, State.StageRestore and
State.ActivateRestore, with once-only restore tokens bound to checkpoint, scope,
payload and incarnation. A restore selects a complete compatible generation, imports
every payload as a fresh artifact, stages the group, validates the coordinator's own
ledgers, and only then activates; a failure anywhere leaves the fence closed and
records every participant that staged as one that must be replaced. The fence lifts
at Failed -> Restoring(k) -> Paused(k) and nowhere else.

The task and the action executor gain the capture/validate_restore/install_restore
interfaces workers-v1 section 4 lists, and the ledger can re-derive the event
identities it issued under another epoch, which is what lets a resumed run's
behaviour trace be compared with an uninterrupted one.

media: check_required_audio now takes the observation's provenance instead of
exempting boundary 0. A chunk is the audio of an interval, and the observation
ActivateRestore installs covers none.

checkpoint-envelope-v1 section 3 gains a dated amendment adding `environment` to the
manifest, the holder of the world's own payload, which the table named for every
other participant; `helperState`, which that table already listed, joins the
required-field set in Rust and TypeScript. The fixture was regenerated by the
existing example; the schema set and contractDigest are unchanged.

state-media-v1 section 5 gains a dated amendment for three readings this slice
enforces: the State RPCs' compatibilityDigest is the participant's, not the
manifest's composition-level block; a restored observation carries no audio chunk;
and a participant that staged into an abandoned install must be replaced.
2026-09-22 17:43:43 +00:00
..
bus-conformance.md media: no best-effort defaults in the audio path 2026-09-22 15:15:06 +00:00
bus-v1.md test(flybus): prove the two section 9 rows a review found cited but unproven 2026-09-22 12:39:07 +00:00
checkpoint-envelope-v1.md session: coherent all-participant checkpoint and recovery 2026-09-22 17:43:43 +00:00
implementation.md docs(design): session-framework specs (bus-v1, ipc-v1, step-v1, workers-v1, publishing-v1, state-media-v1) and the MaleCNS modular-session plans 2026-09-22 11:01:55 +00:00
ipc-v1.md session: resolve uncertain calls, and measure each mode in its own process 2026-09-22 15:41:42 +00:00
publishing-v1.md docs(design): session-framework specs (bus-v1, ipc-v1, step-v1, workers-v1, publishing-v1, state-media-v1) and the MaleCNS modular-session plans 2026-09-22 11:01:55 +00:00
README.md Merge main: the bus slice, whose write-gate fix removes the flybus teardown flake under parallel load 2026-09-22 13:17:30 +00:00
seed-derivation-v1.md docs(session-framework): seed derivation v1 and the FLYSESS1 checkpoint envelope 2026-09-22 12:47:48 +00:00
state-media-v1.md session: coherent all-participant checkpoint and recovery 2026-09-22 17:43:43 +00:00
step-v1.md session: both transports for every integration test, and the mid-step pause written into step-v1 2026-09-22 13:00:14 +00:00
workers-v1.md session: resolve uncertain calls, and measure each mode in its own process 2026-09-22 15:41:42 +00:00

Application and session framework: architecture and contracts

Status: implementation specification, draft 2, 2026-09-18. This is a guide for future agents; none of the new runtime is implemented yet. Baseline code is 83090a9 on docs/improvement-suggestions. MUST/SHOULD requirements apply to the proposed new path, not retroactively to existing public feed, control API, or legacy numerical/checkpoint behavior.

Decisions from the architecture discussion

  1. Applications orchestrate components and develop their presentation alongside them. “Director” is application code, not a mandatory framework service. A tournament is an example application, not the system's organizing data model.
  2. One lightweight Rust bus supports RPC and pub/sub everywhere internally. Flybus replaces separate direct worker transports and an application broker. No NATS dependency.
  3. Messages stay small; large artifacts live in managed storage. Delivery guards and explicit cache/retention owners keep data alive until its last actual use, then GC reclaims it.
  4. The router moves messages and tracks generic ownership. It never schedules game frames, understands macro actions, composites video or operates a stream.
  5. Sessions synchronize worlds; agent workers compute in parallel. One logical clock is not one execution thread. The coordinator alone commits complete world-control batches.
  6. Game-aware executors receive current game state and task progress. Rich inspection data does not become undeclared neural input.
  7. Native observations are framework outputs. Resizing, overlays, browser delivery, audio mixing, encoding, narration and streaming belong to the application/presentation layer.

Read in this order

  1. Flybus v1 — authoritative wire/routing/RPC/pub-sub/artifact lifecycle contract.
  2. Session RPCs — domain payloads, worker capability negotiation and safe retries.
  3. Step protocol — session state machine, ordering and clocks.
  4. Worker/task interfaces — exact method bodies and game-aware executor boundary.
  5. Session media/state — observation timing and coherent recovery.
  6. Application/presentation boundary — snapshots, flexible data and effects.
  7. Implementation guide — sequenced build tasks and acceptance tests.
  8. Flybus conformance report — the flybus crate audited sentence by sentence against bus-v1, with the test that proves each row, the measurements and the draft's own contradictions. A review artifact, not a contract.

Two derived specifications, written by CONTRACT-01 because the slices that need them cannot be built without them:

  • Seed derivation v1 — independent per-agent seeds from one recorded master seed and stable agent ids, with test vectors in both languages.
  • Checkpoint envelope v1 — the exact bytes of the new FLYSESS1 envelope and the durable commit sequence. FLYSIM01 is unchanged and stays separately readable.

For context: modular-session analysis and Melee audit. Each contract owns its named subject; step ordering wins over an informal diagram, and Flybus owns transport/resource rules. Resolve contradictions before implementation. The existing HTML report is an overview, not a contract.

1. Composition and processes

Application / supervisor                 Application presentation
  run policies, identity, history           UI, media composition, audience, stream
                \                           /
                   Flybus: RPC + pub/sub
                /          |              \
        Session        Agent workers      Environment worker
      coordinator      brain + encoder    emulator/world + native observations
      task/executors    + fixed readout
                           |
                  artifact store (same bus API)

This diagram is connectivity, not execution order. The step contract defines causal order. One router can host several independent sessions and application consumers; a deployment may choose one router per application for fault isolation. A router crash affects all its clients, so choose that boundary deliberately. In-process mode still exercises routing and ownership.

Defaults: coordinator per session, worker per fly, environment worker per world. Task and per-agent executors begin as coordinator-local libraries. An environment helper may own a separate emulator child process and adapt its native protocol. There is no second framework socket/lease API between those logical components.

Multiple players in one game share one environment/barrier. Independent games use independent sessions. Linked emulators require a composite backend with link-appropriate timing.

2. Ownership and authority

Owner State and responsibility
Application Composition, persistent personas/brain lineage, lifecycle policies, supported interventions, application schema/history
Session Clock/epoch, port assignments, admission, task ledger, executor state, barriers and coherent recovery
Agent Private membrane, RNG, rates, learning, sensory encoding, decoder and tick remainder
Environment World, actual controller application, backend parser, native media and state capabilities
Flybus Opaque endpoint/topic routing, delivery/call correlation, bounded queues, artifact-owner graph and GC
Storage client Durable event/checkpoint writes and replay APIs; owns artifact handles during writes
Presentation Application UI, display focus, clocks/buffers, media processing, audio/stream output and narrative cues

Immutable graph data can be shared; neural mutable state cannot. Do not concurrently dispatch the existing single-job WorkerPool through cloned handles from different brains.

Applications use declared session capabilities, not arbitrary emulator writes. Bus registration and method privileges preserve a single controller authority for a session. Browser/audience clients do not gain controller access by knowing a service name. Existing public rules remain.

3. Domain independence

The kernel knows no task or bus. The environment knows no neuron populations. A task interprets game state and requests outcomes/recovery; its executor translates a selected decision using read-only current game/progress context. The coordinator orders and applies these results. The bus handles no such semantics. Presentation combines framework observations with an application-owned schema and can change without changing simulation behavior.

Persistent AssetRefs identify installed release content. Transient Flybus ArtifactRefs identify live bytes with ownership. Domain epoch/step identity and bus route/store incarnation are different: the first protects simulation order, the second protects delivery/resource validity. Never substitute game-frame number, persona identity or array position for either.

4. Initial scope and compatibility

First build a generic bus example (RPC + pub/sub + artifact retained beyond message lifetime), then a synthetic two-agent session using it. One local machine, Unix sockets/in-memory parity, immutable file-backed artifacts, fixed cadence, 1-ms LIF, direct control and exact-checkpoint synthetic backend are sufficient. Dolphin, MaleCNS and richer effects are later integrations.

Deferred: cross-machine artifact access, durable broker queues, wildcard/queue-group routing, dynamic native plugins, hot-join, speculative netplay rollback and pooled GPU buffers.

Keep legacy-gameboy-v1 distinct from lockstep-v1. Preserve TypeScript as oracle, existing default versions, historical arithmetic/fingerprints and FLYSIM01 reader. New identities include sensor, readout/executor/task/scheduler semantics. New public feed v2 is an application/presentation gateway contract built on the same internal bus; it does not replace the bus or expose it raw.

5. Reuse criterion

Adding a third environment/application requires a backend, task/profile, composition and application presentation. It must not require game-specific edits to the coordinator, router, artifact manager, kernel, generic stores or transport. Schematized task extensions are valid; an unchecked data blob or universal tournament schema is not a substitute for interfaces.