Skip to content

PHO-65/#121 T13: LumosSequence as serialisable data — steps of look / form / atmosphere / glyph, a shared clock with control(), captured by Oscilloscope and played by SignalGenerator - #178

Merged
wow-miley merged 4 commits into
mainfrom
miley/pho-65-t13-lumossequence-as-serialisable-data-steps-of-look-form
Oct 17, 2026
Merged

wow-miley merged 4 commits into
mainfrom
miley/pho-65-t13-lumossequence-as-serialisable-data-steps-of-look-form

Conversation

@wow-miley

Copy link
Copy Markdown
Contributor

Closes #121 (PHO-65).

The gate (Task A)

Recon is in .context/issue-121-lumos-sequence.md locally; the decisions that make this a wire format, for approval:

  1. One segment per step, named by the step. Socket's capture walk chains one-shots back to back (ready→thinking straight into thinking→idle) and loops a state only on its first visit; Dots' "loop step with an arriving transition" model cannot say that. Explicit steps round-trip the existing segment list 1:1.
  2. A step naming what the orb already shows applies nothing, and sample reports no arrival for it. Loop steps rest where their one-shot landed. Glyphs always fire.
  3. Step names are unique, because TraceStateMachine resolves by name.

Tasks B–E are built behind the gate so the format can be read against working code.

What's here

  • :phosphor-lumos — LumosStep, LumosTransition, LumosSequence (fromJson/toJson, sealed LumosSequenceError, pure sample), LumosSequencePlayer (ticks while connected ∧ uncontrolled ∧ playing, dt capped at 0.1 s, control()/connect() return releases), LiveFrameSource.follow(player, clock), OrbStepper(…, player). Look is now @Serializable. kotlinx-serialization-json added to commonMain; lockfiles regenerated and unchanged.
  • :phosphor-trace — SignalGenerator.play(sequence) / play(player) / stopSequence(), CaptureConfig.sequence + forSequence(…), LumosSequence.frameLayout(fps); the trace's paramSnapshot carries the sequence JSON. Validation: exclusive with cues/segments, fps >= 10, every step at least a frame, clip holds one pass.
  • :phosphor-lumos-compose — LumosOrb(source, player, …) connects while running and releases when off screen or paused.
  • :phosphor-lumos-cli — StateMachineDemo loads demo-sequence.json; runStateMachineDemo depends on jvmProcessResources.
  • :phosphor-core — AtmosphereChoreographer.transitionSpec(from, to) made public; timeline {} KDoc points here.
  • docs/LUMOS_SEQUENCE.md.

Proofs

  • FormSeamByteIdentityTest: the T3 20-frame clip restated as a sequence encodes to the same SHA-256 (with the cue config's paramSnapshot put in place).
  • StateMachineDemoSequenceTest: demo-sequence.json lays out to the old Beat frame table and captures to the same cell columns, ambient, glyphs and ticks as the cue script; every step name resolves through TraceStateMachine.
  • SequenceCaptureTest: the live generator playing the sequence emits frame for frame what the capture recorded; two captures are byte-identical.

Deviations from the ticket, flagged

  • No CHANGELOG.md — AGENTS.md forbids one. KDoc on CaptureConfig.cues, Oscilloscope, SignalGenerator and timeline {} carry the notes instead.
  • demo-sequence.json is the demo's existing 13-step state-and-form script, not seven PROPEL looks. A look baked into a loop drifts under rotation carry until PHO-59 (the PhaseCue KDoc says so), and the demo's seam tests measure that script. The format supports look steps; the demo doesn't dogfood them yet.
  • Phase isn't a step field; a step names a Look. The phase→look table stays with CognitiveLookSwitch.

Verification

./gradlew ktlintFormat :phosphor-lumos:jvmTest :phosphor-trace:jvmTest :phosphor-lumos-compose:jvmTest :phosphor-lumos-cli:jvmTest ktlintCheck --offline green locally. kotlinUpgradeYarnLock / kotlinWasmUpgradeYarnLock ran; no lockfile change. Web, iOS and Dokka are left to CI. The demo was not run interactively.

🤖 Generated with Claude Code

@wow-miley
wow-miley force-pushed the miley/pho-65-t13-lumossequence-as-serialisable-data-steps-of-look-form branch from 9834312 to 86c737f Compare October 17, 2026 09:53
wow-miley and others added 4 commits October 17, 2026 19:45
… form / atmosphere / glyph, a shared clock with control(), captured by Oscilloscope and played by SignalGenerator from one definition

Format (:phosphor-lumos): @serializable LumosStep / LumosTransition / LumosSequence
with fromJson / toJson, a sealed LumosSequenceError that names the step, and a
pure sample(seconds). One segment per step, named by the step; a step naming what
the orb already shows applies nothing; names are unique.

Clock: LumosSequencePlayer ticks while connected, uncontrolled and playing, dt
capped at 0.1 s; control() hands time to an external driver. LiveFrameSource.follow
applies steps; OrbStepper advances a player; LumosOrb(source, player) connects it
while the orb runs.

Capture and live: SignalGenerator.play(sequence | player); CaptureConfig.sequence
and CaptureConfig.forSequence derive segments by stepping the same player at
1 / fps. A sequence capture is frame-identical to the cue capture it restates
(FormSeamByteIdentityTest, StateMachineDemoSequenceTest). StateMachineDemo loads
demo-sequence.json. docs/LUMOS_SEQUENCE.md documents the format.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…s skipped on Kotlin/JS like its peers

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e builds its OrbStepper, which now takes a sequence player before it

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…enceFollower behind closures in LiveFrameSource, SequenceClock on OrbStepper; the DOM bundle returns to 72 KB

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@wow-miley
wow-miley force-pushed the miley/pho-65-t13-lumossequence-as-serialisable-data-steps-of-look-form branch from 0620b96 to 9382f89 Compare October 17, 2026 10:46
@wow-miley
wow-miley merged commit 163f9cf into main Oct 17, 2026
4 checks passed
@wow-miley
wow-miley deleted the miley/pho-65-t13-lumossequence-as-serialisable-data-steps-of-look-form branch October 17, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant