Living Scenes ship at V1 as five authored domain templates — one per practicing domain (Tara, Nyx, Veritas, Metis, Arete) — plus the authoring surfaces creators and operators use to build, rehearse, and promote new scores from those templates. A template is not a loose theme: it is a real workflow class with a machine ID, a locked cue-verb allowlist, a tone band, grounding and intent requirements, and a per-fixture eval gate that blocks promotion. This page sits in the living-scenes-core area alongside Scene Score Schema, Live Direction, Conductor Runtime, and Blend Kernel, and Composition Surface and Cinematographic Technique Catalog; it is where the abstract Score contract meets concrete, named, tested domain content.
What is real vs. modeled. The template catalog, the per-template cue and technique allowlists, the tone-gating with crisis collapse, the breath-cycle pacing, the fixture eval gates, the compose-assist budgets, and the editor's pure decision helpers are all implemented and tested today. What is modeled but not computed here is everything pixel- and frame-level: latent video generation, optical-flow warps, FVD computation, and GPU determinism. Those arrive as score inputs the pure functions consume — the runtime and blend kernel state plainly that "Actual GPU dispatch lives outside this module" and "Implementations of the actual DSP / shader code live downstream." This page keeps that line honest.
Where the code lives#
| Concern | Package / path |
|---|---|
| Template catalog, eval gates, Tara breath specs | libs/isis/workflow-classes/src/living-scene/template-catalog.ts, tara.ts |
| Score / Segment / RenderEnvelope / CarryState contracts | libs/contracts/src/living-scene/score.ts (mirrored at libs/yemaya/living-scenes-runtime/src/score/score-schema.ts) |
| Conductor state machine | @yemaya/living-scenes-runtime (v0.1.0) — src/conductor/conductor.ts |
| Transitions, technique catalog, tone gating, compatibility scorer | @yemaya/blend-kernel (v0.1.0) — src/transitions.ts, src/catalog/, src/compatibility/scorer.ts |
| Compose Assist budgets + gold-set eval | libs/yemaya/living-scenes-runtime/src/compose-assist/compose-assist.ts |
| Scene telemetry events | libs/oshun/embodiment-psyche/src/events/scene-events.ts |
| AAA Score Editor (web + desktop) | apps/yemaya/studio-web/src/score-editor/ScoreEditorPage.tsx, apps/yemaya/studio-desktop/src/renderer/pages/ScoreEditorPage.tsx |
| Lilith Studio Tara venue editor (contemplative web app) | apps/oshun/web/src/app/lilith-studio/scenes/TaraSceneEditor.tsx, /lilith-studio/scene/new |
The two runtime packages carry exactly the names the docs cite:
@yemaya/living-scenes-runtime and @yemaya/blend-kernel.
Domain Templates#
All five templates ship at V1 launch as workflow-class instances under the
living-scene.* family. Each template has its own grounding, persona, locale,
accessibility, and eval pipeline; none is descoped to V1.x. Templates are
versioned and promotable through Isis; the contemplative-product Studio Living
Scene card resolves the available templates from the user's tier and tenant
entitlements.
The catalog (LIVING_SCENE_TEMPLATES in template-catalog.ts) pins five
canonical machine IDs — these, not the friendly names, are what the runtime,
the allowlists, and the gates key off:
| Machine ID | Display name | Allowed cue verbs | morphForbidden |
Reduced-motion required | Strictest Lilith tone | Sophia grounding | Intent capture |
|---|---|---|---|---|---|---|---|
tara-contemplative-arc |
Tara Contemplative Arc | linger, advance, save-moment, abandon, kill | no | yes | yes | no | no |
nyx-sky-briefing |
Nyx Sky Briefing | linger, advance, morph, shift-style, save-moment, abandon, kill | no | yes | no | yes | no |
veritas-grounded-explainer |
Veritas Grounded Explainer | linger, advance, recall, save-moment, abandon, kill | yes | no | no | yes | no |
metis-lesson-visualizer |
Metis Lesson Visualizer | linger, advance, recall, shape-by, save-moment, abandon, kill | no | yes | no | yes | no |
arete-living-offering |
Arete Living Offering | linger, advance, morph, shape-by, save-moment, abandon, kill | no | yes | yes | no | yes |
templateAllowsVerb({ templateId, verb }) enforces this allowlist, and it
short-circuits morph whenever morphForbidden is set — which is why Veritas
can never accept a morph cue even though morph is a valid verb in the global
ScoreCueVerbSchema. The complete verb vocabulary is the nine-member
ScoreCueVerbSchema (score.ts:62-72): linger, advance, morph, recall,
shift-style, shape-by, save-moment, abandon, kill, mirrored verbatim
as CUE_VERBS_VOCABULARY in the cue parser so the parser and the contract can
never drift.
Tara — Contemplative Arcs (tara-contemplative-arc)#
-
Five sub-variants ship at V1 (
TARA_SUBVARIANTS):loving-kindness,body-scan,breath-anchor,nature-immersion,gratitude. -
Score templates pace visuals to a breath-cycle clock. Each sub-variant carries a concrete
BreathCycleof{inhaleSeconds, holdInSeconds, exhaleSeconds, holdOutSeconds}plus a target arc length, a palette bias for the blend kernel, and a captions cadence:Sub-variant Breath cycle (in / holdIn / ex / holdOut) Arc minutes Palette Captions WPM loving-kindness 4 / 1 / 6 / 1 12 dawn-rose 80 body-scan 4 / 0 / 8 / 0 15 stone-grey 70 breath-anchor 4 / 4 / 4 / 4 (box breathing) 8 cool-sea 60 nature-immersion 5 / 0 / 7 / 0 18 forest-moss 75 gratitude 4 / 1 / 6 / 1 10 warm-amber 85 buildBreathPacedShapesizes a score by dividing the arc seconds by the cycle seconds (Math.floor(arcSeconds / secondsPerCycle)), clamping the arc to(0, 30]minutes, so a user-configurable override still produces a whole number of breath cycles. A cue likelingerextends the current segment without breaking continuity — useful when the user wants to dwell in a phase. -
Persona binding to approved contemplative voice profiles only; Lilith contemplative-tone band on the strictest setting (
strictestToneBand: true); no Sophia source pin (sophiaGroundingRequired: false) because there are no empirical claims. -
The reduced-motion alternative ships in lockstep (
reducedMotionVariantRequired: true).assertReducedMotionLockstepfails loud with aTaraVariantParityErrorif a normal variant has no reduced-motion sibling, or if the two variants disagree on captions WPM — caption cadence must match across the pair, or promotion is blocked.
Nyx — Sky Briefings (nyx-sky-briefing)#
- Tonight-only sky briefing tied to the Nyx celestial-event clock; the score advances camera/visual focus across visible objects as the narrator names them, time-aligned to ±60 ms.
- Requires observer location (sensitive PII); explicit opt-in per session, with locale fallback to a regional-default location.
- Northern and Southern hemisphere parity at V1 launch; ephemeris computed from Skyfield-class libraries; constellation art from Yemaya-cleared rights or Isis-generated under licensed style anchors.
- Event coverage: planetary alignments, moon phases, meteor showers, ISS passes, aurora forecasts (where available), comets, conjunctions.
- Cue verbs include
linger(stay on a constellation),morph(to a target sky region),shift-style, andshape-by(e.g. narrator pace). Grounding is required (sophiaGroundingRequired: true) because positions and timing are empirical, and itsgroundingCorrectnessgate is set at a 0.92 pass rate. - Caching: tonight's briefing materializes once per location-bucket per night; per-user personalization is on top of the cached base render. See Domain — Nyx.
Veritas — Grounded Explainers (veritas-grounded-explainer)#
- Score template binds to a Sophia source pin set; visuals are mood/style anchors drawn from the topic hub, never empirical claims. Specific facts arrive via narration/text only, never via inferred imagery.
- The cue verb set excludes
morph(morphForbidden: true), since free-form visual morph would risk visual claim drift; the available verbs arelinger,advance,recall,save-moment,abandon,kill. - The counterclaim, retraction, and source-update cascade reaches into kept
Veritas Living Offerings: an artifact whose pinned source is later corrected
surfaces a banner and offers re-render under the corrected source. The
compatibility scorer reinforces this at the boundary level — a Veritas pair
where both segments cite only retracted Sophia source pins is declared
hard-incompatibleregardless of mechanical scores (see below). - Eval fixtures include adversarial would-be-misleading cases (e.g., a cited claim about a 19th-century printing press where the visual could plausibly assert a date or location not in the source); the template must hold the line. Veritas carries the strictest gates of all five — golden 0.97, adversarial-cue 0.99, grounding-correctness 0.97. See Domain — Veritas and Sophia Grounding.
Metis — Lesson Visualizers (metis-lesson-visualizer)#
- Score template binds to a lesson's knowledge-graph anchor set; the "what if X?" branch is constrained to what-ifs the lesson's KG supports, with graceful fallback ("let's see — that'll need a different lesson") when the cue exits the supported manifold.
- Themis academic-integrity interlock: the tone-gating module blocks every
technique on any segment whose KG node is in an in-progress assessment set.
When
templateId === 'metis-lesson-visualizer',metisSegmentNodeIdis set, and that node is inmetisAssessmentLockedNodes,assertTechniqueAllowedthrowsGatingError('themis-assessment-locked')— the lesson visualizer simply cannot run on an assessment surface. - Standards-aligned for institutional delivery: tenant-specific standards bindings (Common Core, IB, NGSS, etc.) are honored where the tenant's curriculum metadata is wired.
- Persona binding to approved teacher personas; Lilith teacher-persona safety
policy applies (no diagnostic statements, no treatment plans). Grounding is
required, with a
groundingCorrectnessgate at 0.95. - Its cue verb set is among the most expressive:
linger,advance,recall,shape-by(e.g. student pace),save-moment,abandon,kill. See Domain — Metis.
Arete — Living Offerings (arete-living-offering)#
- The most personal template; the user states an intention (voice/text), and the
score generates a contemplative arc tuned to it. Default duration: 4–8
minutes; user-configurable within Arete's pace bands. This is the one template
with
intentCaptureRequired: true. - The intent is captured on the Score, not on a segment, in the
ScoreIntentLayer(score.ts:121-129):intentId,privateText,publicRedactedText,privateIntentHash(64-hex),capturedAtUnixSeconds, andredactionCategoriesHit. The private intent is kept for the originating user only; the public-redacted intent (a Lilith-redacted version) is the only intent text ever exposed in shared artifacts or in operator inspection without elevated authorization. The redaction categories themselves are an enum:named-person,deceased,medical-condition,abuse-disclosure,location-of-safety,minor-identity,financial-account,legal-status. - Strongest crisis-signal pre-screen on the intent text; an intent that triggers a crisis frame produces no offering and routes to the existing Lilith crisis pathway.
- Reusable by the user: re-engaging the same offering produces a deterministic
re-render unless the user requests a
branch from this moment(which forks a new score with the same intent and a new seed). - Sharing is opt-in per artifact, governed by the Shareability Matrix; a shared Living Offering carries only the public-redacted intent, never the private intent. See Domain — Arete and Keep, Share, Shareability, Takedown, and Lineage.
- Arete is the only template whose technique allowlist spans the full catalog, including the three operator-curated high-energy cuts; those three are gated separately (see Tone gating below).
The Segment is leaner than it reads — the real schema#
Earlier drafts of this material described a thirteen-field segment
({intent, public_redacted_intent, duration_band, style_anchor, motion_descriptor, audio_role, narration_script_pin, sophia_grounding_pin, lilith_tone_band, persona_binding, transition_in, transition_out, accessibility_role}).
None of those fields exist verbatim. The real SegmentSpecSchema
(score.ts:47-60) is:
{
"segmentId": "string (1..80)",
"kind": "opening | breath-anchor | visual-meditation | narration-bed | sky-event-arc | lesson-visualizer | grounded-explainer | living-offering | closing",
"displayName": "string (1..120)",
"durationSeconds": "number, (0, 3600]",
"tone": "contemplative | gentle-instructive | celebratory | reverent | reflective | wonder",
"workflowClassId": "string",
"parameters": "Record<string, number | string>",
"inboundCarryState": "CarryState | null",
}
Several facts follow from this and matter for authoring:
- Intent lives on the Score, not the Segment —
ScoreIntentLayer, above. - Transitions are not stored on segments. A segment has no
transition_in/transition_out; transitions are computed at the boundary between two adjacent segments by the blend kernel and recorded by Compose Assist astechniquesByBoundary(a boundary id → technique id map). - Grounding, persona, and accessibility are not Segment fields. They are template-level requirements (the catalog flags above), persona/voice bindings, and accessibility variants enforced elsewhere — not columns on the segment.
- Free-form per-segment knobs live in the open
parametersrecord, constrained by the segment'sworkflowClassId. The full schema, includingCueSpecand the deep-validation invariants, is documented in Scene Score Schema.
The RenderEnvelope is richer than "engine version + model hashes"#
RenderEnvelopeSchema (score.ts:91-107) pins concrete, literal-union
production parameters so a kept artifact re-renders identically:
| Field | Type / allowed values |
|---|---|
envelopeId, displayName |
strings |
widthPx |
literal 1080 | 1440 | 1920 | 2560 | 3840 |
heightPx |
positive int ≤ 7680 |
fps |
literal 24 | 30 | 60 |
maxBitrateKbps |
positive int |
gpuClass |
rtx-4090 | a100-40gb | a100-80gb | h100-80gb |
minLookaheadSegments |
literal 2 | 3 | 4 |
deepParseScore enforces a hard ≥ 2 lookahead release-gate invariant on top
of the literal union (score.ts:165-167): even though the type already excludes
1, the deep parse throws renderEnvelope must require ≥ 2 lookahead segments so
that cross-process payloads (BFF, queues, persistence) cannot smuggle a
single-segment lookahead past the schema. The same function deduplicates segment
ids and rejects any cue that targets an unknown segment (a cue may target the
wildcard *).
CarryState — the boundary handoff protocol#
The "CLIP-style style anchor, last-frame conditioning, motion-vector descriptor,
color-LUT alignment, audio tail" prose maps almost one-to-one onto a real
schema, CarryStateSchema (score.ts:38-44), which the docs previously never
named:
| Field | Constraint | Carries |
|---|---|---|
clipAnchorAssetId |
non-empty | the style anchor asset |
lastFrameConditioningHash |
regex /^[0-9a-f]{32,}$/ |
last-frame conditioning (≥ 32 hex chars) |
motionDescriptor |
≤ 120 chars | motion-vector descriptor |
lutId |
non-empty | color-LUT alignment |
audioTailDescriptor |
≤ 120 chars | the audio tail handed to the crossfade |
This is the contract the Conductor propagates across boundaries (next section) and the Latent-carry inspector visualizes.
How a template's content reaches frames#
Templates do not render pixels. They produce decisions that the Conductor, the Blend Kernel, and the compatibility scorer consume. The full runtime is covered in Live Direction, Conductor Runtime, and Blend Kernel; here is the slice that template authors must understand.
The Conductor state machine (modelled, deterministic)#
@yemaya/living-scenes-runtime's conductor.ts is a pure segment-slot state
machine. Each slot moves through a SegmentRenderState:
pending → pre-warming → ready → streaming → done
(or → aborted)
initialiseConductor({ score })builds oneSegmentSlotper segment, allpending, playhead at index 0, backpressure off, seeding each slot'scarryStateInboundfrom the segment'sinboundCarryState.planPreWarmmarks everypendingslot in the window[playheadIdx + 1, playheadIdx + minLookaheadSegments]aspre-warming. This is whereminLookaheadSegmentsearns its ≥ 2 invariant — there is always at least one slot warming ahead of the playhead.setBackpressure(active: true)truncates the lookahead to 1: when downstream is slower than realtime, the conductor only pre-warms the immediate next slot, shedding speculative work rather than piling up.completePreWarmflips apre-warmingslot toready(and fails loud with aConductorError('invalid-transition')if the slot wasn't pre-warming).advancePlayhead({ carryStateOutbound })marks the current slotdone, writes itscarryStateOutbound, and promotes the next slot tostreaming— carrying the outbound carry-state forward as the next slot's inbound state (carryStateInbound: input.carryStateOutbound ?? next.carryStateInbound). It refuses to advance into a slot that isn'tready/streaming.planReconnect({ atSegmentId })answers the resumability question after a client drops: it returns{ resumable, resumeCarryState, reason }, resumable only when the slot isstreamingorready, handing back the inbound carry-state the client needs to rejoin mid-segment.
Pure logic throughout — the module's own header is explicit: "the conductor models scheduling decisions in deterministic state. Actual GPU dispatch lives outside this module."
Transitions and the technique catalog#
The blend kernel owns nine transition kinds — the low-level DSP/shader
primitives (TRANSITION_KINDS, transitions.ts:13-23): latent-warm-start,
optical-flow-morph, color-lut-match, audio-crossfade, narrative-pivot,
motion-descriptor-handoff, motion-descriptor-reset, audio-level-jump,
variable-rate-sequencer. (Earlier prose listed only the first five; the
catalog has nine.) Each has real, specific validateTransition parameter ranges
that fail loud with a TransitionValidationError when violated:
| Transition | Validated ranges |
|---|---|
latent-warm-start |
bridgeSteps ∈ [2, 12]; cfgScale (nullable) ∈ [0, 30] |
optical-flow-morph |
morphFrames ∈ [1, 48]; warpStrength ∈ [0, 1] |
color-lut-match |
non-empty source/target LUT ids; matchFrames ∈ [1, 240] |
audio-crossfade |
fadeMs ∈ [50, 8000]; curve ∈ {linear, equal-power, log} |
narrative-pivot |
non-empty pivotPromptId |
motion-descriptor-handoff |
non-empty 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; 0.25 ≤ minRate ≤ maxRate ≤ 4 |
Above those primitives sit the twelve cinematographic techniques authors and
customers actually pick (TECHNIQUE_IDS, cinematographic-catalog.ts:16-29):
hard-cut, match-cut, l-cut, j-cut, dissolve, smash-cut, whip-pan,
jump-cut, match-action, cross-cut, montage, fade-to-black. Each entry
binds a kernelComposition of transition kinds, an overlap-window range, tone
bands, a per-template allowlist, an accessibility fallback, a provenanceTag
matching technique:[a-z0-9-]+, and concrete evalThresholds — not just
qualitative descriptions. A few illustrative numbers from the real catalog:
| Technique | maxFvd |
maxFlicker |
maxColorJump |
minNarrationAlignment |
Reduced-motion fallback |
|---|---|---|---|---|---|
dissolve |
0.3 | 0.03 | 0.08 | 0.90 | dissolve |
match-cut |
0.3 | 0.04 | 0.10 | 0.92 | dissolve |
smash-cut |
0.5 | 0.06 | 0.18 | 0.85 | hard-cut |
whip-pan |
0.5 | 0.05 | 0.18 | 0.85 | fade-to-black |
fade-to-black |
0.3 | 0.03 | 0.10 | 0.92 | fade-to-black |
fade-to-black is the universal fallback: the only technique allowed in every
tone band, and the one reached for when a clean recovery is needed. These
thresholds are gate inputs: the blend kernel's isBlendContinuityAcceptable
compares a downstream-supplied ContinuityScorecard (fvd, flickerScore,
colorJump, motionVectorContinuity, audioRmsDeltaDb) against the thresholds
and returns a pass/fail with reasons. The FVD and flicker numbers themselves are
computed downstream, not by this module — this is the honest line between the
deterministic gate and the modeled perceptual metrics. The full technique table
and overlap windows live in
Composition Surface and Cinematographic Technique Catalog.
Compatibility scoring at a boundary#
scoreSegmentPair (scorer.ts) returns a verdict for any adjacent pair across
seven dimensions: style-anchor, motion-descriptor, audio-role,
narration, tone-band, grounding, persona; the composite is the plain
mean of the seven. Two honesty notes about the style-anchor and
motion-descriptor dimensions: the doc once described "CLIP-embedding distance
between the outgoing and incoming anchors," but the implemented scorer uses
exact-ID equality, not an embedding distance — styleScore returns 1 when
styleAnchorId matches and 0.35 otherwise (scorer.ts:75-77); motionScore
likewise returns 1 vs 0.5 on exact descriptor equality. Grounding overlap
is a real set metric — a Dice coefficient over the two segments' Sophia
source-pin hashes. A CLIP-style embedding metric is modeled as a possible future
input, not computed in this pure module.
Before any mechanical scoring, a hard-incompatible policy gate runs and can veto a pair outright:
- crisis ↔ non-crisis pair without a
fade-to-blackrecovery transition; - pedagogical ↔ entertainment intra-Score pairing;
- a Tara contemplative arc paired with a forbidden high-energy technique
(
smash-cut,whip-pan,jump-cut); - a Veritas pair where both segments cite only mutually-retracted Sophia pins.
Tone gating, allowlists, and crisis collapse#
assertTechniqueAllowed (tone-gating.ts) is the enforcement point that runs
in three places — the customer technique picker, Compose Assist candidate
generation, and score promotion (ENFORCEMENT_POINTS). Its precedence order
matters:
- Crisis-frame collapse takes absolute precedence. Regardless of template,
within one frame of crisis-frame activation the technique allowlist collapses
to the safe trio
CRISIS_COLLAPSE_ALLOWLIST = {hard-cut, dissolve, fade-to-black}. Anything else throwsGatingError('crisis-frame-collapse'). - Themis interlock for Metis — every technique blocked on in-progress assessment segments (above).
- Per-template allowlist — the technique must be in
technique.templateAllowlist. - Arete operator-curated cuts.
OPERATOR_CURATED_ARETE_TECHNIQUES = {smash-cut, whip-pan, jump-cut}are never allowed under Lilith's strictest tone band (GatingError('strictest-lilith-tone-block')) and otherwise require an explicitoperatorCuratedTechniqueGrant(GatingError('operator-curated-technique-required')).
Two allowlists, kept in sync. There are intentionally two technique allowlists in code: the per-technique
templateAllowlistincinematographic-catalog.ts, and the per-templateTEMPLATE_TECHNIQUE_ALLOWLISTSmap incompose-assist.ts. They currently agree for all five templates (e.g. Tara allows hard-cut, match-cut, l-cut, j-cut, dissolve, match-action, fade-to-black; Arete spans the full twelve), but they are a duplicated source of truth that can drift, so any new technique must be added in both places. The docs describe a single conceptual allowlist; the code has two enforcement copies.
Compose Assist — budgets and gold-set eval#
Compose Assist runs as an Isis AgentRun with budget caps, tool grants, a cost
ledger, and operator audit (per §18). Its request carries an AgentRunBudget
(maxTokens, maxCostCents, maxLatencyMs) and AgentRunGrants (toolIds,
allowEgress), a tier
(contemplative | curated-creator | aaa-creator | operator-admin), the
templateId, locale, and a priorSegmentSummary. The output is a candidate
segment plus ranked techniques with confidence bands, a rationale, and a
continuityPreScore; a soft-refusal fires when no viable suggestion exists.
Tier caps (TIER_CAPS, compose-assist.ts:447-452):
| Tier | Segment cap | Duration cap | Routing |
|---|---|---|---|
| free | 6 segments | 90 seconds | inline compose surface |
| paid | 24 segments | 8 minutes | inline compose surface |
| aaa | — | — | routesToStudioEditor: true (full AAA editor) |
A draft can only be promoted to a score when its continuityPreScore
(overall and per boundary) is ≥ 0.85 — both validateCompositionDraft and
the per-boundary assertPromotableBoundary throw
ComposeAssistError('continuity-pre-score-out-of-range') below that threshold.
They also check that each boundary connects adjacent segment cards and clears
the workflow-class policy gate. Promotion produces a PromotedCompositionScore
with a segmentOrder, a techniquesByBoundary map, and a parallel
reducedMotionTechniquesByBoundary map so the reduced-motion variant is fixed
at promotion time, not improvised at playback.
The gold-set harness evaluateGoldSet returns a real
GoldSetEvaluation = {precision, recall, refusalRate, correctRefusals, falseRefusals}
over labeled items (each marked expectsSuggestion or not), and a
champion/challenger comparison gates promotion of the assistant model itself
against minPrecision / minRecall floors. See
Agent Invocation, Budgets, Memory, and Feedback Loops.
Template eval gates#
Before any template version can be promoted to production, its fixture set must
clear the per-template gate in TEMPLATE_EVAL_GATES
(template-catalog.ts:147-199). evaluateFixtureSet reports
{ pass, failures }, listing every threshold a FixtureSetReport misses. All
five templates require a minimum of 30 fixtures; the pass-rate thresholds are
tuned per template:
| Template | min fixtures | golden | adversarial-cue | crisis-trigger | locale-parity | a11y-parity | grounding-correctness |
|---|---|---|---|---|---|---|---|
tara-contemplative-arc |
30 | 0.95 | 0.98 | 1.00 | 0.90 | 0.95 | n/a |
nyx-sky-briefing |
30 | 0.95 | 0.97 | 1.00 | 0.90 | 0.95 | 0.92 |
veritas-grounded-explainer |
30 | 0.97 | 0.99 | 1.00 | 0.90 | 0.97 | 0.97 |
metis-lesson-visualizer |
30 | 0.95 | 0.97 | 1.00 | 0.90 | 0.97 | 0.95 |
arete-living-offering |
30 | 0.95 | 0.99 | 1.00 | 0.90 | 0.95 | n/a |
The crisis-trigger gate is 1.0 for every template — there is zero tolerance
for a crisis-signal fixture that fails to route correctly. Templates without
empirical claims (Tara, Arete) carry no groundingCorrectness gate (null);
the grounded templates (Nyx, Veritas, Metis) require it, and
evaluateFixtureSet fails loud if a grounding gate is configured but no
grounding pass-rate was reported. More on the eval philosophy in
Latency, Accessibility, Eval Sets, and Tests.
Scene telemetry — the Live Direction Channel#
Every authored scene emits a uniform, traceable event feed on the Psyche
envelope. scene-events.ts defines eight SCENE_EVENT_KINDS:
scene.segment-start, scene.segment-end, scene.transition-start,
scene.transition-end, scene.live-direction-applied,
scene.policy-intervention, scene.crisis-frame, scene.fallback-engaged.
Each event extends a SceneEventEnvelope carrying eventId, sessionId,
sequence, emittedAtUnixMillis, traceId, parentSpanId, and spanId.
verifyEventStream enforces a monotonic, gap-free sequence (sequence
strictly lastSequence + 1) and a single trace-id for the whole session —
any trace-id change mid-stream or any sequence gap throws a SceneEventError.
This is the real telemetry surface the contemplative viewer and the Score
Editor's replay scrubber both consume; see
Psyche Real-Time Runtime.
Authoring (the Scene Score Editor)#
AAA Scene Score Editor — Yemaya Studio#
The primary Scene Score Editor lives in Yemaya Studio
(apps/yemaya/studio-{web,desktop}) and is gated to the AAA-creator tier and to
operators. It is built from the runtime's pure decision helpers — the editor UI
calls real functions, not mocks: runFixtureRehearsal, getReplayEventAtFrame,
getTransitionFindings, isTransitionGatePassed, createPromotedVersion, and
updateSegmentParameter (imported into ScoreEditorPage.tsx).
- Timeline view: ordered Segment cards (
SegmentCard) with duration bands, transition pickers between cards (TransitionPicker), narration-script overlay, motion-descriptor strip, narrator-cadence overlay, audio-bus tracks. - Segment inspector (
SegmentInspector): editable fields from the score schema, with workflow-class-locked parameter ranges (updateSegmentParameter(segment, range.key, value)), persona/voice picker (allowlist), Lilith tone-band selector, Sophia source pin selector, accessibility-role selector. - Transition inspector (
TransitionInspector): typed transition with overlap window slider, preview against the fixture set, an eval scorecard surfaced viagetTransitionFindings, and manual override blocked whenisTransitionGatePassedis false — the editor will not let an author save a boundary below the release-gate threshold. - Latent-carry inspector: visualizes the
CarryStatehandoff across each boundary; surfaces violations of the carry-state contract. - Fixture-rehearsal harness (
runFixtureRehearsal(score)): runs the score against the workflow class's fixture set; reports per-fixture eval scores; promotion to the contemplative tier is blocked until all fixtures pass the thresholds in the table above. - Replay scrubber (
getReplayEventAtFrame(score, frame)): scrubs a previously rendered session frame-by-frame with per-event annotations (cue applied, transition fired, policy intervention, fallback engaged) drawn from the scene event feed. - Score versioning (
createPromotedVersion): every save creates a new score version; promotion through Isis environments (dev → staging → prod) is gated through workflow-class release gates and Lilith policy review. - Score templates library: the editor seeds new scores from approved templates (the five domain templates above plus any tenant-specific templates) with locked policy bindings.
A second editor exists on the contemplative product#
The AAA editor is not the only authoring surface. A distinct Lilith Studio
Tara venue editor ships on the contemplative Oshun web app at
apps/oshun/web/src/app/lilith-studio/scenes/TaraSceneEditor.tsx, with a
new-scene flow at /lilith-studio/scene/new. It is a venue/staging editor for
Tara contemplative sessions — exporting concrete authoring data such as
TARA_SCENE_EDITOR_ZONES, TARA_SCENE_EDITOR_LIGHTING,
TARA_SCENE_EDITOR_AUDIO, and accessibility profiles
(TARA_SCENE_MOTION_PROFILES with reduced-motion remediation,
TARA_SCENE_CAPTION_PROFILES). So the earlier claim that the Scene Score Editor
"does not appear on the contemplative product under any entitlement" is only
partly accurate: the full AAA Score Editor is Studio-only, but a Lilith-Studio
scene authoring surface does live on the contemplative product. See
Creator Roles and the Authoring Workspace
and Lilith Persona Policy.
Customer-facing surfaces and the BFF#
Customers see authored scenes through the public scene viewer
(apps/oshun/web/src/app/scene/[id]/page.tsx, plus /scene/[id]/embed and
/scene/[id]/report) and compose new ones through the inline compose surfaces
(apps/oshun/web/src/app/studio/compose/ComposeClient.tsx and the mobile
apps/oshun/mobile/app/compose.tsx). All of these talk to the Living Scenes BFF
route (apps/oshun/bff/src/routes/living-scenes.ts, ~1,871 lines), which owns
the real keep / share / idempotency logic and is covered by end-to-end tests
(scene-viewer-deepening.spec.ts, living-scene-card.spec.ts,
public-scene-abuse-report.spec.ts). The surface-by-tier boundaries are
detailed in Product Surfaces and
Generation Audience Tiers and Surface Boundaries.
Related#
- Scene Score Schema
- Live Direction, Conductor Runtime, and Blend Kernel
- Composition Surface and Cinematographic Technique Catalog
- Living Scenes — Concept and Customer Promise
- Scene Safety, Determinism, Provenance, and Cue Privacy
- Latency, Accessibility, Eval Sets, and Tests
- Creator Roles and the Authoring Workspace
- Domains: Tara · Nyx · Veritas · Metis · Arete
- Hub: ../features.md