Phases 8 and 9: shots, and a production design per track

Both phases come out of the manual gate — watching whole tracks — and both
fix something no automated check was looking for.

Phase 8: shots. A section is a STAGE of the song and can run ninety
seconds; one scene held that long reads as a still image with a wobble on
it. Each section kind now gets a roster of three or four stage visuals
instead of one scene, and each section is cut into shots that rotate
between them on phrase lines, never holding past 22s. The roster stays per
kind, so a track's drops still cut between the same images and the video
keeps its identity; the anchor opens each section and the rotation returns
to it, and when a companion is due it is the least recently shown one.

The arc driver stopped working in sections and started working in cues, one
per shot, so a shot cut and a section change take the same code path and
differ only in transition length. The default transition is a slow
dissolve — two bars calm, one loud; a straight cut is reserved for
sections above the energy threshold, because on calm material a cut reads
as a glitch rather than as an edit.

Phase 9: production design. With cuts every fifteen seconds the next
problem was that the images being cut between shared nothing but the
palette. What a music video actually shares across shots is a location, a
cast, a camera operator and an art direction, so each track now generates a
personality in four traits (shape, camera, space, style) off the look seed.
The traits reach shaders as uniforms plus four helpers in the contract, and
each scene expresses them its own way: Classic Wave's rings take the
signature polygon, Metaballs merge as one, Floating Geometry no longer
picks between a box and a circle because the production already decided.

The part that makes it a design rather than a filter: scenes DECLARE which
traits they honour, a track is built on one or two, and a scene that does
not honour all of them is not cast in that track. The library shrinks per
track on purpose.

Two gates keep the declaration honest — lint greps each shader for evidence
of every trait it claims, and a render check measures that each declared
trait actually moves the image (41 scene/trait pairs, weakest response 64
of 255). A layer with no personality renders bit-identically to before,
which is what keeps every earlier sweep and regression valid.

Checks changed rather than added:
  - P4 scene-change and drift checks now measure per shot, not per section;
    the crossfade check reads its length off the cue.
  - P5 flash sweep runs per shot, so the visuals that only appear
    mid-section are measured too.
  - P6 preview/export parity primes first (as both real paths do) and
    compares at the one-LSB tolerance Phase 7 already uses. Measured over
    four consecutive shows: 3 frames at delta 1, then bit-exact — GPU
    variance on first render, not a divergence.
  - P2's contract-uniform list is derived from the contract instead of
    retyped, so the signature uniforms cannot fall out of sync.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dejvino
2026-08-05 20:04:33 +02:00
co-authored by Claude Opus 5
parent 9d15c3cf49
commit ca5a68eb84
39 changed files with 1795 additions and 209 deletions
+76
View File
@@ -452,6 +452,82 @@ Toward six families. Each new scene is a shader plus a schema block.
- Library-wide regression contact sheet at a fixed seed, diffed against last known good, so
shared-code changes can't silently break existing scenes.
### Phase 8 — shots
Not in the original plan. It exists because the manual gate in Phase 4 caught exactly what it
was written to catch: watching whole tracks, long stretches went by without the image
changing. Sections are the song's *stages*, and a stage can run ninety seconds; one scene held
for ninety seconds reads as a still image with a wobble on it, however reactive the wobble is.
So a third level sits between section and frame. Each section KIND gets a roster of three or
four **stage visuals** instead of one scene, and each section is cut into **shots** that
rotate between them on phrase lines — four to eight bars in a drop, eight to sixteen in an
intro, never longer than twenty-two seconds. The roster stays per kind, so all of a track's
drops still cut between the same visuals and the video keeps its identity; the first entry is
the anchor, opens every section of that kind, and the rotation keeps returning to it. When a
companion is due it is the least recently shown one, so a long section reaches its whole
roster instead of ping-ponging between two images.
Mechanically this is one change: the arc driver stopped working in sections and started
working in **cues**, one per shot, so a shot cut and a section change take the same code path
and differ only in transition length. The default transition is a slow dissolve — two bars on
calm material, one on loud, capped at 40% of the shot. A straight cut is reserved for genuinely
high-energy sections: below the energy threshold nothing ever cuts, because on calm material a
cut reads as a glitch rather than as an edit.
**Gate:**
- No image held longer than the ceiling, and none shorter than the floor. Both measured across
several seeds; the first is the complaint that started the phase, expressed as a number.
- Intra-section cuts land within a quarter-bar of a downbeat.
- Identity holds: a kind's roster is stable across its sections, the anchor opens each section
and stays within one showing of the most-shown visual, and no variant repeats back to back.
- A section with four or more shots reaches at least three distinct visuals — otherwise the
rotation has collapsed back to A/B and the roster is decoration.
- Dissolves outnumber cuts, and no section below the energy threshold cuts at all.
- No black frame or discontinuity at a cut; the flash-rate sweep runs per shot rather than per
section, so the visuals that only appear mid-section are measured too.
- **Watch the battery again.** The phase exists because of a manual finding and the fix is a
pacing judgement, which no delta threshold can make.
### Phase 9 — production design
Also not in the original plan, and for the same reason as Phase 8: watching real tracks. With
cuts every fifteen seconds the next problem became obvious — the images being cut between had
nothing in common but the palette. That is a slideshow, not a music video.
What a music video actually shares across its shots is a location, a cast, a camera operator
and an art direction. So each track now generates a **personality** in four traits, once, off
the look seed:
| trait | what it fixes | how a scene expresses it |
|---|---|---|
| `shape` | the cast | a signature form — round, or an n-gon at a tilt — stamped wherever a scene draws elements |
| `camera` | the operator | one slow returning pan, sway, roll and bar-locked breath, applied to the coordinate a scene works in |
| `space` | the location | a shared horizon height, depth falloff and background wash |
| `style` | the art direction | line weight, edge softness, surface grain, fold count |
The traits reach shaders as ordinary uniforms plus four helper functions in the contract
(`sigShape`, `sigCamera`, `sigAir`, `sigEdge`/`sigGrain`), so a scene honours a trait in its own
way — the rings of Classic Wave become hexagonal, Metaballs merge as hexagons, Floating
Geometry stops choosing between a box and a circle because the production already decided.
The part that makes it a design rather than a filter: each scene DECLARES which traits it
honours, each track is built on one or two of them, and **a scene that does not honour all of
them is not cast in that track**. The library shrinks per track on purpose. A scene with no way
to draw a hexagon should not appear in the hexagon video.
**Gate:**
- Personality reproduces exactly from the seed, and differs between seeds.
- Every trait has at least six scenes, or a track built on it could not fill its rosters.
- No scene is ever cast in a track it does not honour, and no signature starves a track below
three distinct scenes (the fallback to a one-trait signature exists for this).
- **Every declared trait visibly changes the scene that declares it.** The lint proves a scene
mentions a trait; only rendering proves it matters. Measured as a frame delta against a
one-LSB floor — the tolerance the determinism checks already call noise.
- Changing the personality moves every scene in a track's cast, not just one.
- A layer with no personality renders exactly what it rendered before the phase existed, which
is what keeps every earlier sweep and regression valid.
- **Watch the battery.** The target is that a viewer could name the through-line on a second
viewing — not the first. No metric expresses that.
---
## 10. Detachment from `party-stage`