Skip to content

T5 · TraceStateMachine — segment looping, transition policies, pop-free state switching #75

Description

@wow-miley

Suggested model tier: Sonnet 4.6 low effort (pure logic over T1/T3 contracts; well-bounded)

Context

Traces are linear; cognition isn't. The Arc changes state at arbitrary moments, and a clip can't anticipate that. TraceStateMachine bridges the two: named states map to TraceSegments, and a transition policy decides how playback moves between them without visual pops.

Deliberately generic — this type knows nothing about Arc, Socket, or Lumos semantics. It maps strings to segments. Socket binds Arc Signal states to segment names in its own integration ticket. (Preserve optionality: the morphology renderer, future NPCs, anything emitting VoxelFrames gets state-driven playback for free.)

Objective

TraceStateMachine in :phosphor-trace that drives a TracePlayer through segment changes with deterministic, pop-free transition behavior.

Expected outcomes

  • TraceStateMachine(trace, initialState: String) with requestState(name: String).
  • Transition resolution order, checked at request time:
    1. If a one-shot transition segment named "$current→$target" exists in the trace → finish current loop iteration is NOT required; play the transition segment once, then enter the target's loop.
    2. Else → FinishLoopThenSwitch: complete the current loop iteration, switch at the loop boundary (boundaries are visually continuous by construction since loops are recorded to wrap).
    3. Configurable override: Crossfade(durationMs) — player exposes two concurrent read heads and a blend weight; the blending itself is performed downstream (the player emits BlendedFrameRequest or pre-blended frames — recon decides which is cheaper given the dynamic-channel layout from T1).
  • Re-entrant requests collapse (requesting the current state is a no-op; rapid A→B→A settles correctly).
  • state: StateFlow<String> for observers.

Technical constraints

commonMain, :phosphor-trace; no Compose; deterministic given a deterministic clock (testable with virtual time); Result-typed error for unknown state/segment names.

Tasks

A — Recon (comment before code): Read T1's final channel layout and T3's player internals; decide where blending happens (player-side pre-blend vs downstream) with a one-paragraph cost rationale. STOP for approval.

B — State machine + transition policies.

C — Fuzz test: Seeded random sequence of requestState calls at random virtual-time offsets across a synthetic 3-state trace; assert: never an out-of-range frame index, never a discontinuity exceeding the crossfade envelope, terminal state always reached, same seed → same playback log.

Validation / DoD

Fuzz test green with 3 different seeds pinned in CI; unknown-state request returns typed failure without crashing playback; demo shows idle→thinking→idle driven by buttons with no visible pop.

Out of scope

Arc/Signal mapping (Socket integration ticket); authoring transition segments (Workbench usage, not code); easing curves beyond linear crossfade.

Human review gate

Miley approves the blend-placement recon before B; visually confirms the 3-state demo before close.

Agent handoff prompt

You are implementing PHO-39 in socket-link/phosphor. Depends on PHO-37 (merged).
1. RECON FIRST: read VoxelTrace channel layout + TracePlayer internals; comment
   blend-placement decision (player pre-blend vs downstream) + rationale. STOP.
2. Implement TraceStateMachine: transition resolution order exactly as
   specified (explicit "a→b" segment > FinishLoopThenSwitch > configured
   Crossfade). StateFlow<String> for observers. Result-typed unknown-state error.
3. Generic only — no Arc/Socket/Lumos references in this module.
4. Fuzz test with seeded virtual time: no OOB index, no pop beyond crossfade
   envelope, deterministic playback log per seed.
5. DoD: green JVM + iosSimulatorArm64; 3-state demo recording in PR.
If recon contradicts any assumption in this ticket, STOP and comment.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions