The artist, recording, and performance are separate governed states. A persona can exist without a released track, and a released track cannot become a live show until the authored Sequencer package clears its own quality boundary.
Saraswati Stage is V3's AI virtual-artist tenant — a roster of persistent
personas inside the Lilith metaverse who hold a backstory, release a catalog,
and play scheduled concerts to a stadium audience. The product splits cleanly in
two, and the split is the whole feature set. Discography is engine-agnostic:
an editorial brief enters a job queue, Isis orchestrates a generation provider,
and a draft track passes through a fixed chain of pure-function gates —
grounding, tone, mastering, review, fingerprint, provenance — before it can
become a release. Live performance is the opposite: a UE5 Sequencer asset is
the canonical concert, driving MetaSound music, Niagara stage FX, a MetaHuman
performer, and between-song speech against an NTP-style music clock. The seam
between them is a released track plus a persona: everything the pipeline
produces becomes either a row in the in-world discography or a cue track in a
concert Sequencer. This page covers the three features that carry that promise —
persistent artist personas, the discography and music-generation
pipeline, and the live performance engine — grounded in
@oshun/tenant-saraswati-stage (libs/v3/saraswati-stage), @oshun/isis-music
(libs/v3/isis-music), and @oshun/v3-concert-quality
(libs/v3/concert-quality). The broader concert-design reference is the
test-covered @calliope/stage specification. The
section hub is ../V3_features.md.
Naming and the Calliope boundary#
Cross-product surfaces call this tenant V3 Stage and use technical channel
id v3.stage. Existing package names, persistence models, capability types, and
Unreal asset paths keep the historical Saraswati Stage name to avoid a broad
data/code migration. This explicitly separates the virtual-artist venue from the
unrelated @saraswati/* industrial-
technology domain (EVs, batteries, manufacturing, robotics, IoT, and health
hardware). A later public brand is an explicit human naming gate, not a reason
to leave the technical namespace ambiguous.
@calliope/stage is the normative concert-design specification for concept,
setlist, stage geometry, lighting, screens, choreography, venue, cameras, VFX,
spatial audio, audience simulation, streaming plans, and VOD package plans. V3
does not currently import that package at runtime: V3 owns tenant persistence,
rights/provenance, recorded editorial evidence, export quality, and its Unreal
concert contract. Future cook-time composition should select Calliope outputs
instead of duplicating those types, then pass the result through V3's gates and
a real renderer. Calliope's protocol/VOD descriptions and V3's Sequencer asset
ids are plans and contracts, not proof of playable video bytes. The Rail audit
records the complete relationship and media gaps in
V10/RA8_V3_STAGE_CHANNEL_INTEGRATION.md.
What ships, honestly#
The persona, generation, rights, and concert-authoring gates are real, domain-specific TypeScript, each with a validation suite that asserts computed behaviour, not shape. Here is the split before the details.
- A persona is a validated dossier, not a model checkpoint.
validateSaraswatiPersonaDossierDraft()enforces 17 required fields andpublishSaraswatiPersonaDossier()throws unless every blocking field passes; a runtimepersona-policy-lockrefuses medical/legal/financial advice across all six GA personas with a zero-breach adversarial bar. - The generation pipeline is a chain of fail-closed gates. Provider routing
with a cost/quality comparator and a real failover drill, a Sophia-grounded
lyric factuality check that catches a fabricated Grammy claim, an
auto-mix/master pass with
-14 LUFS/-1 dBTPtargets and a release-blocking review queue, a 50-track Audible-Magic/Pex fingerprint firewall, and a real Ed25519 C2PA track signer with genuine tamper detection. - A concert can't publish half-authored. A ten-gate authoring pipeline
refuses to publish until every gate passes, and
@oshun/v3-concert-qualitysplices a judge-panel scene-quality + diversity gate into the same release-gate suite as the C2PA and consent gates.
Three honest qualifications travel with that. First, the pipeline does not
call live music or TTS providers. routeSaraswatiMusicProvider scores a
static in-repo registry; buildSaraswatiGroundedLyricDraft returns a
deterministic lyric fixture and the tested logic is the factuality gate around
it; the auto-mix/master pass is a settings-and-review model, not a DSP renderer;
the fingerprint matcher is token-overlap scoring against a synthetic catalog.
These are honest gate harnesses with the real providers (Suno/Udio,
Cartesia/ElevenLabs, Audible Magic/Pex) as provider-gated seams. Second, the
"concert Sequencer asset" is JSON text, not a binary cooked LevelSequence
— a descriptor paired with a contract; the MetaSound graphs, Niagara systems,
MetaHuman performer, and motion/lighting presets are authored UE content, not
code in this repo. Third, off-platform distribution (Spotify / Apple Music),
PRO-society registration, and the Adobe CAI trust root are provider-gated. The
sections below say where each claim is backed. (The fan economy, voice-consent
contracts, genre cells, and remix rights have their own deep treatment in the
sibling page
./saraswati-economy-voice-genre-rights.md.)
Persistent artist personas#
A Saraswati artist is a persona dossier, a runtime policy lock, and a
consent-bound voice signature — all in libs/v3/saraswati-stage/src.
The dossier that makes an artist#
persona-dossier-editor.ts defines a SaraswatiPersonaDossierDraft: a
backstory (a ≥ 35-word summary, at least two Sophia citations in the
sophia:saraswati: namespace, plus a cultural-review and a rights-review ref),
a voice signature ref that must point at the consent ledger
(voice-sig:consent-ledger:), a Saraswati avatar ref, a genre cell, a
catalog policy (release cadence, a minimumDebutTrackCount of at least 12,
a remix-rights mode, a distribution mode, and a requiresProvenanceBundle flag
that must be true), and at least two operator hand-off rules.
validateSaraswatiPersonaDossierDraft() runs all of this as blocking field
checks — regex on the persona-saraswati-* id, a prefix check on each ref, a
genre-cell membership test — and publishSaraswatiPersonaDossier() throws
cannot publish until blocking fields pass with the offending field list unless
the draft is ready-to-publish. The seed persona is the fictional "Anaya Veil"
(SARASWATI_PERSONA_DOSSIER_SEED), whose backstory is explicitly tagged
fictional and grounded in conservatory-archive citations rather than borrowed
from any living artist. The six canonical genre cells are real constants
(SARASWATI_PERSONA_GENRE_CELLS: electronic, indie-folk, hip-hop,
classical-fusion, ambient-ritual, experimental-pop), each carrying an
editorialGuardrail string (the ambient-ritual cell forbids medical claims;
experimental-pop keeps public-figure-similarity checks locked).
Hand-off is not just a stored rule.
enforceSaraswatiPersonaOperatorHandOffRules() is a runtime matcher: it
normalizes the user prompt, scores each rule against its scope keywords
(HAND_OFF_SCOPE_KEYWORDS) and its trigger terms, sorts matches by severity
then SLA, and returns an operator-handoff decision with an audit event id when
a rule fires — so the persona's "hand off when an interaction crosses policy"
promise is executable, not a dossier note.
The persona policy lock#
persona-policy-lock.ts governs what an artist persona will say at runtime —
lyrics, between-song speech, fan interaction. Each of the six GA persona
profiles (createSaraswatiGAPersonaPolicyLockProfiles() seeds Raga Devi, Laila
Qadri, Mira Sol, Amara Chen, Zahra Nile, Ines Vale) locks three advice classes —
medical, legal, financial — and enforceSaraswatiPersonaPolicyLock()
classifies a prompt into stay-in-persona, graceful-noop, or
operator-handoff. A locked-advice hit, a public-figure-imitation request, or
targeted political persuasion routes to operator-handoff (queue
lilith-safety-saraswati-persona, 10-minute SLA); a role-swap jailbreak or a
system-prompt-disclosure attempt is a graceful-noop that stays in character
without leaking. The fail-loud signal is policyBreached: it is set only when a
prompt that did match a reason somehow returned stay-in-persona.
evaluateSaraswatiPersonaPolicyLockSuite() runs six adversarial attack prompts
across all six personas — 36 cases — and passes only when
policyBreachCount === 0 and no locked-advice request escaped the operator
hand-off. This is the gate that separates "a persona with a tone" from "a
persona that cannot be talked into diagnosing your chest pain."
The voice signature as persona identity#
A persona's voice is built only from consent-ledger source material.
voice-signature-build.ts's reviewSaraswatiVoiceSignatureBuild() requires a
Saraswati persona id, a voice-sig:consent-ledger: ref, at least 60 clean
consented source minutes across grants, and rejects any grant whose scope is
not saraswati-persona-only or that has been revoked. The safety-critical check
is findPublicFigureMatch(): a probe score at or above
SARASWATI_VOICE_SIMILARITY_MATCH_THRESHOLD_BASIS_POINTS = 8600 (86 %) against
a known public figure is a blocking issue, and the validation-corpus
false-positive rate must stay at or under 100 basis points (1 %).
buildSaraswatiVoiceSignature() throws if the review status isn't ready, so a
public-figure-like voice never produces a model artifact;
signOffSaraswatiGAVoiceSignatures() builds all six GA personas, runs an
adversarial 91.2 %-similar public-figure probe, and asserts it is blocked
before any signature builds. fanVoiceUploadsAccepted: false is baked into
every consent dossier. The deeper rights, contributor compensation, and
consent-contract machinery around this gate live in
./saraswati-economy-voice-genre-rights.md;
here it is the identity safety property that makes a persona buildable.
Discography and the generation pipeline#
The catalog pipeline runs entirely off-engine. Each gate is a pure function with a validation suite; nothing fabricates a "success" it didn't compute.
Provider routing and failover#
isis-music/src/provider-routing.ts registers six music providers — suno,
udio, stable-audio, musicgen, audiocraft, mubert — each carrying a
costPerMinuteCents, a qualityScore, a latencyP95Ms, a
maxDurationSeconds, and supportsStems/supportsLyrics flags.
routeSaraswatiMusicProvider() filters out providers that are unavailable,
already failed, can't meet the requested duration, or lack a required
capability, then sorts the survivors: in cost mode by cents ascending (quality
breaks ties), in quality mode by score descending (cost breaks ties). The
first survivor is selected; the rest become a failoverChain.
drillSaraswatiMusicProviderFailover() proves the chain is real — it routes
once, marks the winner failed, re-routes, and asserts the second pick differs
from the first. Suno (quality 0.92) wins quality routing; Mubert (80¢/min)
wins cost routing — the comparator is exercised against actual numbers. This is
the seam where the live Suno/Udio/Stable-Audio calls would land; the registry it
scores is static in-repo data, and that is the honest boundary.
Grounded lyrics and tone#
grounded-lyric-generation.ts is where the honest seam is sharpest.
buildSaraswatiGroundedLyricDraft() selects a model family (claude-opus for a
release candidate, claude-sonnet for a sketch) and emits a deterministic
four-line draft — but the substance is evaluateSaraswatiLyricFactuality(),
which splits the lyric into lines, decides which lines look like factual
claims (a cue-phrase scan for is, won, born, studied with, …), and
requires each one to be supported by a phrase in a Sophia evidence pack. An
unsupported line is a blocking issue and the report flips to blocked. The
validation set proves the discrimination: a Sophia-grounded lyric about the
fictional Anaya Veil passes with zero unverifiable claims, while
"Anaya Veil won the 2025 Grammy for Best New Artist…" is correctly counted as
one unverifiable claim and blocked — caughtKnownUnverifiableClaim is the
gate's headline assertion. Tone is a separate pass: lyric-tone-policy.ts
scores the lyric against the Lilith contemplative persona policy (the
bhakti-devotional policy at threshold 0.7, via
@oshun/persona-policy-lilith) and routes a violation to the editorial
moderation queue (ongoing-content-qa-queue).
Auto-mix, master, and the editorial review gate#
mix-master-review-gate.ts masters to streaming-loudness targets —
SARASWATI_MUSIC_MASTER_TARGET_INTEGRATED_LUFS = -14,
SARASWATI_MUSIC_MASTER_TRUE_PEAK_DBTP = -1, 48 kHz / 24-bit — with per-stem
settings (createStemSettings assigns gain / pan / compressor-ratio / high-pass
values across up to five stem kinds). The architectural point is the review
queue: every track enters status: 'queued' with releaseBlocked: true, and
only an explicit approve-release action flips it to approved and unblocks
it; request-changes and reject-release leave it blocked, and every action
writes a SaraswatiMusicReviewAuditEvent.
evaluateSaraswatiAutoMixMasterReviewGate() runs three tracks through approve /
request-changes / reject and asserts that exactly one is release-allowed,
the other two stay blocked, all three were surfaced before release, and one
audit event was logged per action — a gate that would fail if release ever
leaked past review.
The fingerprint firewall and provenance#
fingerprint-pre-release-check.ts is the rights firewall.
SARASWATI_FINGERPRINT_REFERENCE_CATALOG is 50 reference tracks tagged
major-label / independent / public-domain / oshun-cleared, each with an
Audible Magic and a Pex fingerprint. scoreFingerprintMatch() computes a real
similarity — token-set coverage weighted 0.9 plus a duration-proximity term
weighted 0.1 — gated at SARASWATI_FINGERPRINT_MATCH_THRESHOLD = 0.82. A
match against a major-label reference sets
status: 'editorial-review-required', releaseBlocked: true, and mints a queue
item requiring lilith-rights-review, license-documentation, and editorial
approval. The validation report asserts both directions: an original track
clears, an independent-catalog match does not trigger major-label review,
and both an Audible-Magic and a Pex major-label match route to editorial. Every
released track then carries an Isis provenance bundle
(track-provenance-bundle.ts — model card, prompt seed, reference set,
generating user, persona, and a lineage-credit distribution that must total 100
%) and a C2PA manifest (track-c2pa-manifests.ts) whose six required assertions
include org.oshun.v3.track-release and org.oshun.v3.rights-waterfall. The
signature is a real Ed25519 signature over the canonical claim payload using
node:crypto — the SaraswatiTrackC2paSigner seam takes an injected KMS key in
production and a deterministic dev key otherwise, so verification and tamper
detection are genuine (the source notes it is "not an FNV-1a string mislabeled
sha256").
Release and the in-world catalog#
discography-release-flow.ts enforces the editorial-approval-before-release
rule: publishSaraswatiDiscographyTrack() throws unless the candidate's
editorialApprovalStatus === 'approved' and the approval timestamp precedes
publish. A debut catalog is twelve tracks
(SARASWATI_DEBUT_CATALOG_TRACK_COUNT, seeded for Raga Devi as "Dawn Archive"
through "Afterimage Hymn"), and buildSaraswatiInWorldCatalogSnapshot()
propagates each release to the in-world catalog path
(oshun://world/saraswati-stage/personas/<persona>/catalog) within
SARASWATI_IN_WORLD_CATALOG_MAX_PROPAGATION_SECONDS = 60. The whole flow is
proven by evaluateSaraswatiDiscographyReleaseFlow() (12 approved → 12
published → 12 catalog-visible within 60 s) and rolled up by
evaluateSaraswatiGaArtistInventory(), an all-or-nothing readiness gate over
the six GA artists (Raga Devi, Anaya Veil, Moon Choir, Copper Lotus, River
Signal, Nocturne Kiran), each requiring 12 released tracks, two scheduled
stadium launch-window concerts, a voice-similarity FPR at or under 1 %, and zero
lyric tone breaches.
Live performance#
A concert is a UE5 Sequencer asset, and the canonical shape of one is the concert-master template.
The concert-master contract#
V3/ue/Content/Saraswati/Templates/ConcertMaster.v3sequence.json is the
contract: schema oshun.v3.saraswati.concert-master-template.v1, owned by the
V3Mode_SaraswatiConcert Game Feature, binding six cue-track families — each
mapped to a real UE MovieScene track class: music-sync →
MovieSceneAudioTrack (the MetaSound MS_ConcertMainMix), lighting and
particles → MovieSceneEventTrack, persona-motion →
MovieSceneSkeletalAnimationTrack (the RagaDevi MetaHuman performer),
audience-cam → MovieSceneCameraCutTrack, and between-song-speech →
MovieSceneEventTrack. The music-sync track carries an
ntp-style-concert-clock with maxDriftMs: 25 keyed off a songStartNtpMs
server timestamp. The audience-cam track encodes privacy as data —
excludePrivacySeats: true, excludeCrowdBandIndividualHandles: true — so a
camera sweep cannot frame a non-consenting attendee. The between-song-speech
track sets personaPolicyLock: true, names Sophia as the grounding provider and
Cartesia/ElevenLabs as TTS, and points at a pre-rendered MetaSound speech graph.
The automation test V3.Saraswati.ConcertMasterTemplate
(V3SaraswatiConcertMasterTemplateTests.cpp) validates this with
LoadFileToString + Contains: it asserts the .uasset resolves to the
canonical package path as a LevelSequence, that all six cue tracks exist with
their exact bindings, that the audience cam carries privacy constraints, and
that the 420-second preview fires all six cue types. The honest line: the
.uasset is JSON text and the test validates the contract, not a
Sequencer loaded in-editor.
The ten-gate authoring pipeline#
concert-authoring-pipeline.ts models the editorial workflow that fills that
template, as ten release gates (SaraswatiConcertAuthoringGateId):
persona-setlist proposal, per-track generation review, motion-preset bindings,
lighting/Niagara cues, Sequencer assembly, speech-bank review, audience
choreography, dress rehearsal, provenance publish, and GA cadence. Each gate has
a real predicate: the setlist must hold exactly 12 songs within a 2-working-day
window; the debut catalog must be reviewed within 6 working weeks; every song
must bind a motion preset and a lighting+Niagara cue pair within their 12-day
windows; the speech bank must hold 8–12 slots of 3–5 reviewed alternates each;
at least two staging dress rehearsals must be signed off; the publish receipt's
Isis provenance bundle must be visible in the inspector; and the GA cadence must
hold (6 artists × 2 concerts/month = 12/month over ≥ 60 days, all
editorial-signed-off). publishSaraswatiConcertSequencer() throws unless
every gate passes — and the receipt's sequencerAssetId resolves to
/Game/Saraswati/Concerts/<concert>/ConcertMaster, mirroring the template path.
Between-song speech and scene quality#
Between-song speech is pre-generated and queued, never live-generated — live
generation can't meet the beat-sync budget and would expose a policy violation
to a live audience without a review gate. Each setlist slot gets 3–5 editorially
reviewed alternates (each run through Sophia factuality, the persona policy
lock, and the persona voice signature, stored as a MetaSound stream), plus a
neutral cold-fallback; at showtime the concert director (or an AI-director rule)
picks the alternate that best fits the moment. Live unscripted Q&A is not
supported at GA — it moves to a post-show green room (V3Mode_SaraswatiClub).
What the authoring gates don't measure, @oshun/v3-concert-quality adds:
concert-scene-quality-gate.ts scores each scene/speech draft with the §1 judge
panel (assessConcertSceneQuality against a default bar of 70) and measures the
whole concert's draft set for corpus diversity (cluster coverage ≥ 0.6, mean
pairwise distance ≥ 0.25) and slop density (≤ 25 per 1000 words) — so a concert
can't be "eight phrasings of one line" even if each passes on its own. These are
GateDefinitions for the same @oshun/content-release-gates suite as the
C2PA/consent gates; v3-concert-export.ts's evaluateV3ConcertExport()
composes the authoring release state, the provenance/consent gates, the scene
quality+diversity gates, and an optional stage-director sign-off into one
ReleaseGateService run, so a low-quality or homogeneous scene blocks
publishing exactly like a revoked consent or a bad signature — and fails loud on
an empty draft set rather than wave an empty concert through.
How it connects#
Saraswati Stage consumes V3's embodiment stack and produces for the tenant experiences. Its MetaHuman performers and the ≤ 25 ms music-sync clock are rendered and spatialized by the avatar, animation & spatial-audio stack and the Tier-1 / Stadium client; the persona policy lock and grounded-lyric factuality reuse the Lilith persona-policy and Sophia surfaces shared with the Tara instruction tenant; and the C2PA signing, consent registry, and provenance bundles sit on the shared identity, safety & provenance foundations. The fan economy, voice-consent contracts and compensation, genre cells, and remix rights are the sibling economy, voice, genre & rights page; ticketing, venue tiers, and the programming calendar are in commons, venues & live service; the full gate chain and Sequencer internals are traced in the architecture companion. The honest line throughout: the persona dossier and policy lock, the generation gate chain, the C2PA signer, and the concert authoring/quality gates are real and tested; the music and TTS models, the binary Sequencer and its MetaSound/Niagara content, and the off-platform distribution are the runtime and providers they gate.
Related#
- Saraswati Economy, Voice, Genre & Rights — the fan-economy tiers, voice-consent contracts and contributor compensation, genre-cell map and drift review, and per-track remix rights (sibling page)
- Commons, Venues & Live Service — ticketing, hall/Stadium venue tiers, the programming calendar, and the archived-performance fallback (sibling page)
- Avatars, Nameplates & Spatial Audio — the MetaHuman performers, MetaSounds spatialization, and the music-sync clock this pipeline drives
- Identity, Safety & Provenance Foundations — the C2PA signing, consent ledger, and provenance substrate the catalog pipeline writes to
- Saraswati Stage Pipeline (architecture) — the engine-agnostic gate chain and the Sequencer + MetaSounds concert internals
- The section hub: ../V3_features.md