The Composition Surface is the customer- and creator-facing affordance that arranges Segments into a Scene Score. The Cinematographic Technique Catalog is the named layer that maps creator intent — "match cut," "L-cut," "smash cut" — onto the Blend Kernel's mechanical transition primitives, gated per Segment pair, per template, and per Lilith tone band. This page is part of the Living Scenes core (see Living Scenes — Concept and Customer Promise and Scene Score Schema); it sits one layer above the Blend Kernel's transition contracts and one layer below the rendered video that the Conductor streams. Everything documented here is deterministic, pure decision logic — the catalog, the compatibility scorer, the tone gates, and the compose-assist budgets are all real, contract-backed TypeScript with tests. The pixel-level work they govern (latent video generation, optical-flow warps, FVD computation, GPU determinism) lives downstream and is consumed only as score inputs, never computed in these modules.
What is real vs. what is modeled. The honest boundary matters here. The Blend Kernel (
@yemaya/blend-kernel) "owns the contracts + parameter validation"; its own header states "Implementations of the actual DSP / shader code live downstream." The compatibility scorer is a pure function over its inputs (same pair → same scores). FVD, flicker, color-jump and motion-vector numbers are thresholds the pure functions compare against, not measurements these modules take. When this page says a technique "requires a shape-similarity score ≥ 0.78" it is describing an eval threshold the catalog declares, not an embedding distance computed in this code — see the Accuracy notes at the end.
Where the Code Lives#
| Concern | Package / file |
|---|---|
| Technique catalog (12 entries), tone gating | @yemaya/blend-kernel v0.1.0 — libs/yemaya/blend-kernel/src/catalog/cinematographic-catalog.ts, tone-gating.ts |
| Transition primitives + parameter validation | libs/yemaya/blend-kernel/src/transitions.ts |
| Segment-pair compatibility scorer | libs/yemaya/blend-kernel/src/compatibility/scorer.ts |
| Conductor runtime, compose-assist, cue parser | @yemaya/living-scenes-runtime v0.1.0 — libs/yemaya/living-scenes-runtime/src/{conductor/conductor.ts, compose-assist/compose-assist.ts, cues/cue-parser.ts} |
| Score / Segment / RenderEnvelope Zod contracts | libs/contracts/src/living-scene/score.ts |
| Template catalog + per-template eval gates | libs/isis/workflow-classes/src/living-scene/template-catalog.ts |
| Tara sub-variant breath cycles | libs/isis/workflow-classes/src/living-scene/tara.ts |
| Scene telemetry events (Live Direction channel) | libs/oshun/embodiment-psyche/src/events/scene-events.ts |
| Customer compose surface (web / mobile) | apps/oshun/web/src/app/studio/compose/ComposeClient.tsx, apps/oshun/mobile/app/compose.tsx |
| AAA / operator Score editors | apps/yemaya/studio-web/src/score-editor/ScoreEditorPage.tsx, apps/oshun/web/src/app/lilith-studio/scenes/TaraSceneEditor.tsx |
| Public scene viewer + BFF | apps/oshun/web/src/app/scene/[id]/{page.tsx,embed,report}, apps/oshun/bff/src/routes/living-scenes.ts |
Customer-Tier Composition Surface#
V1 adds a curated composition affordance to the customer tier — distinct from the Live Direction Channel (which steers a single template in real time) and from the operator-tier Scene Score Editor (which exposes the full schema). The customer surface lets users assemble a Score from existing Segments and preview the resulting arc before committing.
-
Surfaces: web at
apps/oshun/web/src/app/studio/compose/(theComposeClient.tsxclient component) and mobile atapps/oshun/mobile/app/compose.tsx. Tablet gets the desktop affordance with touch-first interactions. -
Affordances: drag-arrange Segment cards on a timeline; tap a boundary to open the Technique Picker (showing only catalog entries compatible with the Segment pair and allowed by the current template and tier, via
templateAllowsCompositionTechnique(...)); scrub-preview the boundary at the picked technique'soverlapWindowRange; one-tap accept an AI-suggested cut. -
Sources of Segments (modeled as
CompositionSegmentSourcewith akinddiscriminant incompose-assist.ts): (a)kept-living-sceneSegments the user owns — re-composable across templates only when the destination allows it and the source isuserOwned; (b) per-template segment libraries (Tara breath-cycle anchors, Nyx celestial anchors, Veritas topic-hub anchors, Metis lesson-step anchors, Arete intention-derived anchors); (c)tenant-rights-importSegments, gated on thecomposition-importrights tag. This logic is the realcanUseSegmentSource(...)function. -
Tier caps (
CompositionTier = 'free' | 'paid' | 'aaa', enforced by the literalTIER_CAPStable incompose-assist.ts:447-452):Tier Max Segments Max duration Behavior free6 90 s curated compose surface paid24 8 min (480 s) curated compose surface aaa— (no cap) — routesToStudioEditor: true— full Scene Score Editor in Yemaya StudioCrisis frame disables composition entirely: when
crisisFrameActiveis true,validateCompositionDraftreturnsallowed: falsewith reasoncrisis-frame-composition-lockbefore tier caps are even evaluated. Active sessions complete on the technique already picked; no new composition is permitted while the frame is active. -
Score lifecycle: composition produces a
CompositionDraft; promotion to a renderable Score (promoteCompositionDraft) requires every boundary to clear the continuity gate (continuityPreScore ≥ 0.85, enforced both at the draft level and per boundary —compose-assist.ts:585and:688respectively), every Segment to passworkflowClassPolicyAllowed, and every Segment source to clearcanUseSegmentSource. Promoted Scores route through the standard Conductor + Render Envelope path (see Direction, Conductor, and Blend). -
Live Direction co-existence: a customer-composed Score still accepts Live Direction cues at runtime under the verb vocabulary, with the composition-time technique respected unless a cue overrides it. The real
resolveRuntimeTechniquefunction shows the precedence: akillcue always wins (returns'kill'); alingercue extends the current technique (returns${techniqueId}:linger-extended); otherwise the planned technique stands. -
Reduced-motion variant: every promoted Score ships a reduced-motion mapping automatically.
promoteCompositionDraftbuildsreducedMotionTechniquesByBoundaryby running every boundary technique throughreducedMotionTechniqueFor(...), which reads the per-techniqueREDUCED_MOTION_TECHNIQUE_FALLBACKStable (e.g.whip-pan → fade-to-black,match-cut → dissolve,montage → still-frame).
Cinematographic Technique Catalog#
The catalog is a versioned, frozen, contract-backed taxonomy. Each entry binds
creator intent to one or more Blend-Kernel primitives, declares its constraints,
and ships per-technique continuity-eval thresholds. V1 launches with exactly
twelve techniques (TECHNIQUE_IDS, cinematographic-catalog.ts:16-29), each
with a provenanceTag of the form technique:<id> recorded in the Render
Envelope; the catalog is extensible behind Isis release gates and pins versions
per kept artifact so deprecation never breaks playback.
Technique Schema#
The CinematographicTechnique interface (cinematographic-catalog.ts:54-67) is
richer than the prose summary:
interface CinematographicTechnique {
id: TechniqueId; // one of the 12
displayName: string;
kernelComposition: readonly TransitionKind[]; // which Blend-Kernel primitives
overlapWindowRange: { minSeconds; maxSeconds };
requires: readonly string[]; // semantic preconditions
forbids: readonly string[];
toneBands: readonly ToneBand[]; // contemplative|pedagogical|narrative|cinematic|entertainment
templateAllowlist: readonly string[]; // canonical template IDs
evalThresholds: EvalThresholds; // maxFvd, maxFlicker, maxColorJump, maxMotionVectorDelta, minNarrationAlignment
accessibilityNote: string;
reducedMotionFallback:
| 'hard-cut'
| 'dissolve'
| 'fade-to-black'
| 'still-frame';
provenanceTag: string; // matches /technique:[a-z0-9-]+/
}
ToneBand here (contemplative, pedagogical, narrative, cinematic,
entertainment) is the catalog's tone vocabulary; it is distinct from the
Score-level ToneClass enum on a Segment (contemplative,
gentle-instructive, celebratory, reverent, reflective, wonder) defined
in score.ts:28-35.
V1 Launch Catalog — Kernel Composition and Eval Thresholds#
The table below is taken verbatim from V1_TECHNIQUE_CATALOG. The maxFvd,
maxFlicker, maxColorJump, maxMVΔ (motion-vector delta), and minNarrAlign
(narration alignment) columns are the actual per-entry numbers — the values
the downstream continuity scorecard is checked against, not measurements taken
in this module.
| Technique | Kernel composition (TransitionKinds) |
Overlap (s) | maxFvd | maxFlicker | maxColorJump | maxMVΔ | minNarrAlign | Reduced-motion fallback |
|---|---|---|---|---|---|---|---|---|
hard-cut |
(none — instant) | 0–0 | 0.40 | 0.04 | 0.12 | 0.40 | 0.90 | hard-cut |
match-cut |
latent-warm-start, optical-flow-morph, motion-descriptor-handoff, color-lut-match | 0.5–2.0 | 0.30 | 0.04 | 0.10 | 0.30 | 0.92 | dissolve |
l-cut |
audio-crossfade, color-lut-match | 1.0–4.0 | 0.40 | 0.04 | 0.12 | 0.40 | 0.94 | hard-cut |
j-cut |
audio-crossfade, color-lut-match | 1.0–4.0 | 0.40 | 0.04 | 0.12 | 0.40 | 0.94 | hard-cut |
dissolve |
latent-warm-start, optical-flow-morph, color-lut-match, audio-crossfade | 0.5–3.0 | 0.30 | 0.03 | 0.08 | 0.30 | 0.90 | dissolve |
smash-cut |
motion-descriptor-reset, audio-level-jump | 0–0.2 | 0.50 | 0.06 | 0.18 | 0.60 | 0.85 | hard-cut |
whip-pan |
optical-flow-morph, motion-descriptor-handoff, variable-rate-sequencer | 0.2–0.8 | 0.50 | 0.05 | 0.18 | 0.70 | 0.85 | fade-to-black |
jump-cut |
motion-descriptor-reset, variable-rate-sequencer | 0–0 | 0.60 | 0.06 | 0.20 | 0.60 | 0.85 | dissolve |
match-action |
latent-warm-start, optical-flow-morph, motion-descriptor-handoff | 0.3–1.5 | 0.35 | 0.04 | 0.12 | 0.35 | 0.90 | dissolve |
cross-cut |
narrative-pivot, audio-crossfade | 0–0 | 0.40 | 0.05 | 0.15 | 0.45 | 0.88 | hard-cut |
montage |
variable-rate-sequencer, audio-crossfade, color-lut-match | 1.0–6.0 | 0.45 | 0.05 | 0.15 | 0.50 | 0.85 | still-frame |
fade-to-black |
color-lut-match, audio-crossfade, motion-descriptor-reset | 0.5–2.0 | 0.30 | 0.03 | 0.10 | 0.30 | 0.92 | fade-to-black |
Notable per-entry semantics drawn from requires/forbids:
hard-cutanddissolveboth carryforbids: ['active-narration-mid-sentence']— you may not hard-cut or dissolve through a spoken sentence.match-cutrequiresshared-shape-anchor;l-cut/j-cutrequireaudio-bus-continuity;smash-cutrequirespercussive-audio-spikeandforbids: ['contemplative-tone-band'];whip-panrequirescamera-pan-continuityand likewise forbids the contemplative band;jump-cutforbids bothcontemplative-tone-bandandpedagogical-tone-band;cross-cutrequiresparallel-action;montagerequires ashared-music-bed.fade-to-blackis the universal fallback: it has emptyrequires/forbids, is onALL_TEMPLATES, and is the recovery transition the policy gate demands for crisis boundaries. It is the graceful default for end-of-arc, section breaks, and any cut that fails every other technique's compatibility check.
Kernel Primitives the Catalog Composes#
The kernelComposition column references the nine TransitionKinds defined in
transitions.ts:13-23. The doc historically listed only five; the real array is
nine, each with its own typed parameter object and validated range
(validateTransition, transitions.ts:106-222):
TransitionKind |
Validated parameters and ranges |
|---|---|
latent-warm-start |
bridgeSteps ∈ [2, 12] (integer); optional cfgScale ∈ [0, 30] or null |
optical-flow-morph |
morphFrames ∈ [1, 48]; warpStrength ∈ [0, 1] |
color-lut-match |
non-empty sourceLutId/targetLutId; matchFrames ∈ [1, 240] |
audio-crossfade |
fadeMs ∈ [50, 8000]; curve ∈ {linear, equal-power, log} |
narrative-pivot |
non-empty pivotPromptId; resetMotionDescriptor boolean |
motion-descriptor-handoff |
non-empty source/target descriptor ids; blendFrames ∈ [1, 120] |
motion-descriptor-reset |
resetStrategy ∈ {clean-break, new-anchor}; holdFrames ∈ [0, 48] |
audio-level-jump |
deltaDb ∈ [-18, 18]; recoveryMs ∈ [0, 3000] |
variable-rate-sequencer |
non-empty beatGridId; minRate ≥ 0.25, maxRate ≤ 4, minRate ≤ maxRate |
TransitionValidationError carries a discriminated code of 'out-of-range',
'unknown-kind', or 'missing-required', so callers can react to why a
parameter was rejected, not just that it was.
Continuity Scorecard Gate#
Independent of the per-technique catalog thresholds, the Blend Kernel exposes a
ContinuityScorecard
({ fvd, flickerScore, colorJump, motionVectorContinuity, audioRmsDeltaDb })
and isBlendContinuityAcceptable(...). This gate first rejects any non-finite
metric, then checks each band (FVD/flicker/colorJump below their max,
motionVectorContinuity above its min, |audioRmsDeltaDb| below its max) and
returns { acceptable, reasons[] }. The §25.18 release gates consume this: any
score below the configured threshold blocks promotion.
Catalog Governance and Versioning#
Every technique carries a provenanceTag recorded in the Render Envelope; the
audit trail on a kept artifact shows which techniques the AI assist selected vs.
which the user overrode. Catalog versions are pinned per artifact via
PinnedTechnique { artifactId, techniqueId, catalogVersion }; deprecation never
breaks playback, and canReshareDeprecatedTechnique(...) returns true only when
the pinned catalogVersion equals the current version — i.e. re-share of a
deprecated-technique artifact requires a re-render against the current catalog.
Segment-Pair Compatibility Matrix#
Composition is not free-form. The compatibility scorer (scorer.ts,
scoreSegmentPair) runs at composition time (when the user places a Segment)
and at runtime (before the Blend Kernel executes), and gates Technique Picker
availability. It is a pure function over its inputs — same pair → same
scores — which is what makes the determinism release gate testable.
Scoring Dimensions#
The scorer computes seven per-dimension scores in [0, 1]
(COMPATIBILITY_DIMENSIONS, scorer.ts:21-29); the composite is the simple
mean of the seven (compositeOf, summed and divided by 7):
| Dimension | How it scores (real implementation) |
|---|---|
style-anchor |
Exact ID equality: styleAnchorId === styleAnchorId ? 1 : 0.35. Not a CLIP-embedding distance (see accuracy notes). |
motion-descriptor |
Exact equality: 1 if descriptors match, else 0.5. |
audio-role |
Role-pair table: identical roles 1; narration↔ambient 0.85; music-bed↔silence 0.3 (harsh); any other mismatch 0.6. |
narration |
1 if narrationTone matches, else 0.5. |
tone-band |
1 if toneBand matches, else 0.4. |
grounding |
Dice coefficient over groundingSourcePinHashes sets (both empty → 1). Real overlap measure: 2·|A∩B| / (|A| + |B|). |
persona |
1 if personaId matches, else 0.55. |
The verdict is a discriminated union: hard-incompatible (policy block,
technique-agnostic), soft-incompatible (composite below
compositeThresholdSoft or below compositeThresholdCompatible, with a
human-readable rationale like composite 0.421 below soft threshold 0.6), or
compatible. Malformed inputs (non-finite or inverted thresholds, empty
required fields) themselves return hard-incompatible with a reason — the
scorer fails loud rather than scoring garbage.
Hard-Incompatible Pairs (Policy Gate)#
policyGate(...) runs before any dimensional scoring and short-circuits four
classes of pair regardless of mechanical compatibility:
- Crisis ↔ non-crisis (
crisisLabel !== 'safe'on exactly one side) without afade-to-blackrecovery transition →hard-incompatible, reason "crisis ↔ non-crisis pair requires recovery transition (fade-to-black)". - Pedagogical ↔ entertainment tone bands within the same Score → blocked.
- Tara contemplative ↔ forbidden technique: when
templateId === 'tara-contemplative-arc'and the chosen transition issmash-cut,whip-pan, orjump-cut→ blocked. - Veritas mutually-retracted pins: under
veritas-grounded-explainer, a pair where both segments cite only Sophia source pins present inretractedSophiaPinHashes→ blocked (noCorrectionNotebridge).
Soft-incompatible pairs are surfaced as warnings with the rationale string; the user can override at AAA tier, never at customer tier, and overrides are audited. Promoted Scores carry the final scores so audit and replay can reconstruct why a technique was chosen.
AI Compose Assist#
The compose assist is a constrained agent that suggests next Segments, ranks candidate cinematographic techniques per pair, and explains its reasoning. It runs through Isis as an agent run with explicit budget caps, tool grants, and operator audit (see Agent Invocation, Budgets, Memory, and Feedback Loops).
- Request shape (
ComposeAssistRequest):{ requestId, templateId, locale, tier, priorSegmentSummary, budget, grants }, wheretieris one ofcontemplative | curated-creator | aaa-creator | operator-admin,budgetis anAgentRunBudget { maxTokens, maxCostCents, maxLatencyMs }, andgrantsisAgentRunGrants { toolIds[], allowEgress[] }. - Suggestion shape (
ComposeAssistSuggestion): acandidateSegment(styleAnchorId,motionDescriptor,audioRole,toneBand), an orderedrankedTechniqueslist where eachTechniqueSuggestioncarries aconfidence: [low, high]band, arationalestring, and acontinuityPreScore. - Budget enforcement:
isBudgetExceeded(...)aborts the run the instant any observed metric (tokens / cost cents / latency ms) crosses its cap. Every assist call therefore produces an audit-reconstructable envelope. - Gating of suggestions:
filterComposeAssistTechniqueSuggestions(...)runs every ranked technique throughtemplateAllowsCompositionTechnique(...), so the assist can only offer a technique the destination template, crisis state, Metis-assessment lock, and Arete operator grant all permit. - Soft refusal is mandatory:
softRefuse(reason)returns a{ kind: 'soft-refusal', explanation }verdict — the customer-tier promise is that the assist must produce a viable suggestion or explicitly decline ("there isn't a clean bridge from here yet — try a different anchor"); silent failure is forbidden. - Champion–challenger gold sets: assist quality is tracked with
evaluateGoldSet(...), which returns{ precision, recall, refusalRate, correctRefusals, falseRefusals }. Precision istp/(tp+fp), recall istp/(tp+fn)(both default to1on empty denominators), andcorrectRefusalscounts cases where a "should refuse" item was correctly declined, whilefalseRefusalscounts viable bridges wrongly refused.gateChampionChallenger(...)promotes a challenger only when it meets the floor on all three top-line metrics and is no worse than the champion on each. Fixtures include high-compatibility golden paths, low-compatibility "should refuse" pairs, and adversarial intent traces that try to bypass tone gating, evaluated across V1 launch locales and per template.
Per-Template Availability and Tone Gating#
The catalog is identical across templates, but each template publishes its own
technique allowlist and tone gating policy. The Customer Technique
Picker only surfaces allowed entries. Compose Assist only considers allowed
entries. The AAA-tier Scene Score Editor surfaces all entries but blocks
promotion of a Score that uses a disallowed technique for the target template.
The five canonical machine template IDs are tara-contemplative-arc,
nyx-sky-briefing, veritas-grounded-explainer, metis-lesson-visualizer, and
arete-living-offering (the friendly names "Tara Contemplative Arcs," etc., are
display strings; the IDs above are the keys used in code).
| Technique | Tara | Nyx | Veritas | Metis | Arete |
|---|---|---|---|---|---|
hard-cut |
✓ | ✓ | ✓ | ✓ | ✓ |
match-cut |
✓ | ✓ | — | ✓ | ✓ |
l-cut |
✓ | — | ✓ | ✓ | ✓ |
j-cut |
✓ | — | ✓ | ✓ | ✓ |
dissolve |
✓ | ✓ | ✓ | ✓ | ✓ |
match-action |
✓ | ✓ | — | ✓ | ✓ |
cross-cut |
— | — | ✓ | ✓ | ✓ |
montage |
— | — | — | ✓ | ✓ |
fade-to-black |
✓ | ✓ | ✓ | ✓ | ✓ |
whip-pan |
— | ✓ | — | — | ◆ |
smash-cut |
— | — | — | — | ◆ |
jump-cut |
— | — | — | — | ◆ |
✓ allowed · — disallowed · ◆ operator-curated only (Arete).
The ◆ entries are the OPERATOR_CURATED_ARETE_TECHNIQUES set
({smash-cut, whip-pan, jump-cut}). For Arete, these three require
operatorCuratedTechniqueGrant === true and
strictestLilithToneBand !== true to be admitted; under the strictest Lilith
tone band they are blocked outright. (whip-pan also appears on Nyx's standard
allowlist, for "pan across the sky" — it is operator-curated only on Arete.) The
same allowlist data is mirrored in two places that must stay in sync: the
per-technique templateAllowlist[] in cinematographic-catalog.ts and the
TEMPLATE_TECHNIQUE_ALLOWLISTS table in compose-assist.ts. They currently
agree for all five templates, but they are a duplicated source of truth that can
drift — a known maintenance hazard.
Enforcement Points and Crisis Collapse#
assertTechniqueAllowed(...) (tone-gating.ts) is enforced at three
ENFORCEMENT_POINTS — customer-picker, compose-assist, and
score-promotion — and evaluates gates in a deliberate precedence order:
- Crisis-frame collapse takes precedence over everything. When
inCrisisFrameis true, the allowlist collapses to theCRISIS_COLLAPSE_ALLOWLIST—{hard-cut, dissolve, fade-to-black}— for every template; anything else throwscrisis-frame-collapse. The tests require this to happen within 1 frame of crisis-frame activation, and Compose Assist explicitly declines to suggest a continuation. - Themis interlock for Metis. When the template is
metis-lesson-visualizerand the Segment's node is inmetisAssessmentLockedNodes, every technique is blocked (themis-assessment-locked) — you cannot cut into or out of an in-progress assessment item. - Per-template allowlist — disallowed technique →
technique-not-in-template-allowlist. - Arete operator-curated guard — strictest Lilith tone →
strictest-lilith-tone-block; missing grant →operator-curated-technique-required.
Tara additionally locks its tone-band swing to 0 (strictestToneBand: true in
the template catalog), which is why match-cut/match-action are admitted only
in their gentle forms and the high-energy techniques never are.
The Conductor Runtime State Machine#
A promoted Score is streamed by the Conductor
(@yemaya/living-scenes-runtime/conductor/conductor.ts). The Conductor is
pure scheduling logic; its header is explicit: "Actual GPU dispatch lives
outside this module." It models each Segment as a SegmentSlot whose
SegmentRenderState walks a fixed lifecycle:
pending → pre-warming → ready → streaming → done
↘ aborted
| Function | Role |
|---|---|
initialiseConductor({ score }) |
Builds one SegmentSlot per Segment, all pending, seeds each slot's carryStateInbound from the Segment's inboundCarryState, playhead at 0. |
planPreWarm({ state, nowUnixSeconds }) |
Marks pending slots in the window [playheadIdx+1, playheadIdx+minLookaheadSegments] as pre-warming. If backpressureActive, the lookahead truncates to 1 — only the immediate next slot pre-warms. |
completePreWarm({ state, segmentId, ... }) |
pre-warming → ready; throws invalid-transition if the slot is in any other state. |
advancePlayhead({ state, carryStateOutbound, ... }) |
Marks the current slot done with its outbound carry-state, then promotes the next slot to streaming — but only if it is already ready or streaming, else throws invalid-transition. Carry-state propagates: carryStateInbound = carryStateOutbound ?? next.carryStateInbound. |
setBackpressure({ state, active }) |
Toggles the backpressure flag that throttles lookahead. |
planReconnect({ state, atSegmentId }) |
Mid-segment reconnect: returns { resumable, resumeCarryState, reason }; resumable only if the slot is streaming or ready, in which case it hands back that slot's inbound carry-state for the client to resume from. |
ConductorError codes are invalid-playhead, invalid-transition,
missing-carry-state, segment-not-found.
Carry-State Handoff#
The continuity protocol the Conductor threads between Segments is the
CarryState schema (score.ts:38-44), and it maps almost one-to-one onto the
"CLIP-style style anchor / last-frame conditioning / motion-vector descriptor /
color-LUT alignment / audio tail" the customer promise describes — but with
concrete field names and constraints:
| Field | Constraint |
|---|---|
clipAnchorAssetId |
non-empty string |
lastFrameConditioningHash |
matches /^[0-9a-f]{32,}$/ (≥ 32 hex chars) |
motionDescriptor |
1–120 chars |
lutId |
non-empty string |
audioTailDescriptor |
1–120 chars |
Render Envelope Pins the Reproducibility Frame#
planPreWarm reads minLookaheadSegments straight off the RenderEnvelope
(score.ts:91-107), which is far richer than "engine version + model hashes"
prose. Every field is a literal union, so an out-of-range value fails at parse
time:
| Field | Type / allowed values |
|---|---|
envelopeId, displayName |
strings (≤ 120 chars for display name) |
widthPx |
literal 1080 | 1440 | 1920 | 2560 | 3840 |
heightPx |
positive int ≤ 7680 |
fps |
literal 24 | 30 | 60 |
maxBitrateKbps |
positive int |
gpuClass |
literal rtx-4090 | a100-40gb | a100-80gb | h100-80gb |
minLookaheadSegments |
literal 2 | 3 | 4 |
The lookahead is also a release-gate invariant: deepParseScore
(score.ts:151-168) re-checks minLookaheadSegments < 2 after schema parsing
and throws "renderEnvelope must require ≥ 2 lookahead segments" — a
belt-and-suspenders guard so no Score can stream with too little pre-warm
headroom even if the literal union were widened. deepParseScore also enforces
segment-id uniqueness and that every cue's appliesToSegmentId resolves to a
real segment (or the wildcard *).
Live Direction Channel Telemetry — Scene Events#
The Conductor's decisions and the policy interventions around them surface to
the viewer and the Score editor as a uniform, traceable event feed on the Psyche
envelope (scene-events.ts). There are eight SCENE_EVENT_KINDS:
| Event | Payload highlights |
|---|---|
scene.segment-start |
segment ref, plannedDurationSeconds, engineVersion, workflowClassVersion |
scene.segment-end |
actualDurationSeconds, endReason ∈ {planned, cue-advance, cue-abandon, policy-cut} |
scene.transition-start |
fromSegment/toSegment, techniqueId, overlapWindowSeconds |
scene.transition-end |
techniqueId + a continuityScorecard { fvd, flicker, colorJump, motionVector } |
scene.live-direction-applied |
cueVerb, cueArgs, cueChannel ∈ {voice, tap, text}, target segment |
scene.policy-intervention |
interventionKind ∈ {pse-strobe-cap, luminance-cap, motion-cap, tone-band-shift, persona-cap}, pre/post values, policyVersion |
scene.crisis-frame |
crisisLabel (8 labels from safe … self-harm-imminent … crisis-other), probability, enteredAtUnixMillis |
scene.fallback-engaged |
fallbackKind ∈ {reduced-motion-render, still-image-only, transcript-only, audio-with-still, pre-rendered-substitute}, trigger ∈ {provider-degraded, policy-rejection, eval-gate-fail, shareability-restriction} |
verifyEventStream(...) enforces a monotonic, gap-free sequence (each
sequence must be exactly last + 1) and a single trace-id across the
whole stream (a mid-stream trace-id change throws trace-id-missing), so audit
replay can prove the feed is complete and un-interleaved.
Continuity-Eval Extensions for Named Techniques#
The base Continuity Eval suite (FVD, flicker, color-jump, motion-vector,
narration-time) generalizes across all transitions. Named techniques
supplement those with their own catalog evalThresholds (the table in
V1 Launch Catalog)
— they never replace the base evals:
match-cutcarries the tightestmaxFvd(0.30) andmaxMotionVectorDelta(0.30) of the cinematic cuts, reflecting its shape/motion-continuity demand.l-cut/j-cutdemand the highest narration alignment (0.94), because audio leads or lags the visual and captions must align to the audio boundary (theiraccessibilityNotes spell out which side captions follow).whip-panallows the loosest motion-vector delta (0.70) because the technique is high-magnitude motion; under reduced motion it falls back tofade-to-black. A too-gentle whip pan is, by intent, the wrong technique.jump-cutallows the loosest FVD (0.60); it is restricted to cinematic / entertainment bands and forbidden in contemplative and pedagogical bands.montageis the only technique whose reduced-motion fallback isstill-frame, and itsaccessibilityNoterequires audio description per visual change.fade-to-blackverifies the tightest flicker (0.03) and a high narration alignment (0.92), since it is the section-break / recovery transition.
Per-technique gates are enforced at composition-draft promotion and at runtime before the Blend Kernel executes; below-threshold transitions surface as warnings at customer tier or block promotion at AAA tier, and every failure is logged with the failing metric so Compose Assist can learn from it.
Tara Sub-Variants — A Worked Example#
The Tara Contemplative Arc template ships five sub-variants (TARA_SUBVARIANTS,
template-catalog.ts:18-24), each with a concrete, deterministic BreathCycle
(tara.ts) of
{ inhaleSeconds, holdInSeconds, exhaleSeconds, holdOutSeconds }:
| Sub-variant | Inhale | Hold-in | Exhale | Hold-out | Cycle total |
|---|---|---|---|---|---|
loving-kindness |
4 | 1 | 6 | 1 | 12 s |
body-scan |
4 | 0 | 8 | 0 | 12 s |
breath-anchor |
4 | 4 | 4 | 4 | 16 s (box breathing) |
nature-immersion |
5 | 0 | 7 | 0 | 12 s |
gratitude |
4 | 1 | 6 | 1 | 12 s |
breathCycleSeconds(...) simply sums the four phases, and the Tara template
constrains its allowed cue verbs to
{linger, advance, save-moment, abandon, kill} with strictestToneBand: true
and reducedMotionVariantRequired: true. This is why the composition surface
for a Tara Score offers only the gentle technique set and locks tone-band swing
to 0.
Eval Gates and Tests#
Every template is held to a fixture-based eval gate (TEMPLATE_EVAL_GATES,
template-catalog.ts:147-199). All five require a minimumFixtures of 30,
a crisisTrigger pass rate of 1.0 (no crisis trigger may ever be missed),
and a localeParity floor of 0.90; the rest vary by template:
| Template | golden | adversarialCue | accessibilityParity | groundingCorrectness |
|---|---|---|---|---|
tara-contemplative-arc |
0.95 | 0.98 | 0.95 | — (none) |
nyx-sky-briefing |
0.95 | 0.97 | 0.95 | 0.92 |
veritas-grounded-explainer |
0.97 | 0.99 | 0.97 | 0.97 |
metis-lesson-visualizer |
0.95 | 0.97 | 0.97 | 0.95 |
arete-living-offering |
0.95 | 0.99 | 0.95 | — (none) |
Veritas carries the strictest golden, adversarial, and grounding thresholds,
reflecting its claim-grounding burden; Tara and Arete have no grounding gate
(groundingCorrectness: null) because they are not source-pinned.
The test coverage backing this page (across the libraries above and the BFF):
- Catalog round-trip and contract conformance across all twelve entries; the
twelve
provenanceTags are grep-confirmed. - Compatibility-scorer determinism (same pair → same scores), since it is a pure function.
- Per-template allowlist enforcement at all three enforcement points; every disallowed technique is rejected by the Technique Picker, Compose Assist, and Score promotion.
- Crisis-frame collapse to
{hard-cut, dissolve, fade-to-black}within one frame. - AI Compose Assist gold-set evaluation (
precision,recall,refusalRate,correctRefusals,falseRefusals) across V1 launch locales. - Hard-incompatible pair coverage (every documented pair detected and blocked).
- Reduced-motion fallback substitution per the
REDUCED_MOTION_TECHNIQUE_FALLBACKStable. - Scene-event stream verification: monotonic gap-free sequence + single trace-id.
- The customer scene viewer and BFF:
apps/oshun/bff/src/routes/living-scenes.tsis ~1,871 lines of real keep / share / idempotency logic, exercised byscene-viewer-deepening.spec.ts,living-scene-card.spec.ts, andpublic-scene-abuse-report.spec.ts(per the v1 triage walkthrough). - Determinism: a composed Score re-rendered under the same Envelope produces a pixel-equivalent video within Isis-defined tolerance — a release gate (§25.9).
Accuracy Notes (Real vs. Aspirational)#
Two points where the older prose overstated the implementation, corrected here so the page matches the code:
- Style-anchor "distance" is exact-ID equality, not CLIP-embedding distance.
The real
styleScore(scorer.ts:75-77) returns1whenstyleAnchorIdmatches and0.35otherwise;motionScoreis likewise1vs0.5exact equality. The "CLIP-region embedding similarity ≥ 0.78" and "motion-vector alignment ≥ 0.80" figures the prose attaches tomatch-cut/match-actionare catalog eval thresholds the downstream renderer is checked against, not embedding distances computed in this pure module. The compatibility scorer is deliberately string-grounded so it stays deterministic and dependency-free. - Segment fields are not the 13-field prose list. The real
SegmentSpec(score.ts:47-60) is{ segmentId, kind, displayName, durationSeconds, tone, workflowClassId, parameters, inboundCarryState }.intentlives on the Score (ScoreIntentLayer, with private/public-redacted text and a redaction-category list), not the Segment. Transitions are not stored on Segments (they are decided at boundaries). Grounding, persona, and accessibility role are not Segment fields. See Scene Score Schema for the full authoritative schema.
The entire pixel/frame layer — actual latent video generation, optical-flow warps, FVD computation, GPU-deterministic rendering — is aspirational relative to these modules: it is modeled as score inputs the pure functions consume, and its implementation lives downstream of the contracts documented here. Honest "planned/gated downstream" is the accurate posture; the decision logic on this page is shipped and tested.
Related#
- Living Scenes — Concept and Customer Promise
- Scene Score Schema
- Live Direction, Conductor Runtime, and Blend Kernel
- Domain Templates and the Scene Score Editor
- Scene Safety, Determinism, Provenance, and Cue Privacy
- Latency, Accessibility, Eval Sets, and Tests
- Agent Invocation, Budgets, Memory, and Feedback Loops
- Sophia Grounding
- Lilith Persona Policy
- Feature hub: ../features.md