Tara Studio is the yoga-instructor tenant of the Lilith Metaverse, and this page
covers the part a teacher actually does before anyone enters a room: build a
sequence out of a canonical asana library, optionally stand up a supervised AI
persona to extend their reach, stay inside a trauma-informed tone and lineage
policy, and get paid for it — including for their cloned voice. Where the
avatars and spatial-audio page treats
embodiment and the world page treats
presence, Tara has a different burden of proof. It is not "is this
deterministic?" but "is this consent-shaped and provably attributable?" — an
instructor's avatar must not close its eyes or touch a student without
permission, a persona must not teach an asana its human sponsor never approved,
a lineage claim must carry a citation, and a voice signature must never leave
the surface it was licensed for. Every one of those is a state machine or a
fail-loud gate in real, test-covered TypeScript under libs/v3/tara-studio (the
@oshun/tenant-tara-studio package), with the grounding engine shared from
libs/v3/sophia-saraswati-grounding. The running-a-class and coaching side is
its sibling,
Tara instructors, classes & coaching;
the money mechanics it shares with concerts live in
commerce, rights & takedown; the deep
engine/pipeline treatment is the architecture companion,
../architecture/tara-classes-aja-and-commons.md.
For the full feature scope this slots into, start at the hub:
../V3_features.md.
What ships, honestly#
The split is worth stating up front, because the monolith describes a richer product than the code implements, and this page follows the code.
- Real and test-covered.
@oshun/tenant-tara-studiois substantive, domain-specific TypeScript — 19 source modules, 16 spec suites (~69itcases), a Prisma persistence layer, and a 21-entry capability ledger (v3TaraStudioDescriptor,src/index.ts:17). The asana library, the lineage grounder, the invitational linter, the eyes-open/style-mode policies, the four AI-persona gates, and the five-file TTS-voice economics stack are all genuine, deterministic, and covered. The Saraswati-side grounder inlibs/v3/sophia-saraswati-grounding(8 specs) is the structural twin of Tara's lineage grounder and the citation companion this page cross-references. - "300 asanas" is combinatorial.
TARA_CANONICAL_ASANA_LIBRARYis 30 base seeds × 10 lineage framings = 300 entries generated byflatMap(asana-library.ts:234), not 300 distinct shapes. Each entry carries real per-family contraindications, four modifications, and a three-cue Aja bundle — substantial content, honestly not 300 unique poses. - Grounding is deterministic, not an LLM. Both
groundLineageClaim(lineage-grounding.ts:316) andreviewSaraswatiBackstoryGrounding(backstory-grounding.ts:504) check claims against a static source registry with authority scores. They are genuine little reasoning engines; they are not live model calls. - The data/policy tier, not the editor UI. The drag-and-drop asana editor,
the stand-in-avatar timing preview, and the in-world cue rendering are the
Next.js web Studio (
apps/oshun/web/src/app/lilith-studio/asana/) and the UE5 client. This library owns the asana data, the consent/governance policies, the AI-persona contracts, and the voice economics — the contract behind those surfaces, not the surfaces themselves. - Economics here = the voice royalty, not the class split. The code implements the instructor TTS voice-signature royalty (a 5% added share). The 20/80 class-fee split, the 10/90 tip/donation rate, and the Tara Lineage Fund described in the monolith are settled in V1 Lilith-Commerce / Aje and are not in this library. The sections below say which is which.
Sequence and asana authoring#
The canonical asana library#
Authoring starts from a catalog, and the catalog is the flagship of the package.
TARA_CANONICAL_ASANA_LIBRARY (asana-library.ts:234) crosses 30 seeds —
Tadasana through Savasana, each typed with a family (standing,
backbend, inversion, arm-balance, restorative, …) and a difficulty —
against ten lineage framings (iyengar-supported, ashtanga-vinyasa,
krishnamacharya-viniyoga, yin-restorative, trauma-informed,
chair-accessible, senior-mobility, …). Every one of the 300 resulting
TaraCanonicalAsana entries (buildAsanaEntry, :297) carries three lineage
teaching notes, four modifications with real cue text and props (a prop is
chosen by family — block for backbends/inversions, wall for
standing/balance, strap for core/twist), family-keyed contraindications, a
three-cue Aja alignment bundle, an Isis editorial signature, and a Tara
design-council review.
The contraindications are the part that earns trust, because they are not
generic "consult a doctor" boilerplate — contraindicationsFor (:383) keys a
real clinical table off the asana's family: an inversion warns neck-injury
(severity avoid) and hypertension (caution); a backbend warns
lumbar-compression (caution) and pregnancy-compression (avoid); a
forward-fold warns hamstring-strain and disc-irritation. That is exactly
the data the monolith promises a sequence will surface in its listing and use to
gate minor cohorts.
The library is GA-gated all-or-nothing. validateTaraCanonicalAsanaLibrary
(:240) counts entries that are signed, design-approved, and carry ≥3 lineage
variants, ≥4 modifications, ≥2 contraindications, and a ≥3-cue bundle, and
passesGaGate is true only when every count equals the library length and
the length is ≥ 300 (TARA_ASANA_LIBRARY_GA_MINIMUM).
assertTaraCanonicalAsanaLibraryGaGate throws otherwise — one editorially-uns-
igned asana fails the whole gate, which is the point.
From asana to sequence — and to a plan#
An instructor authors a sequence entirely on the web (no UE install): drag
asanas from this library, insert breathwork/meditation/transition/prop blocks,
tag tradition/pace/difficulty/contraindications, preview pacing on a stand-in
avatar, and publish as a live-class template or on-demand class through the V1
environment-promotion gates. The library above is what populates that palette;
the published artifact is an AsanaSequence manifest the UE5 client and the
Tier-2 fallback bind at runtime, persisted through the V3AsanaSequence /
V3Asana Prisma models whose payloadHash column makes the shipped JSON
provable against its row (see the
content-pipeline companion).
The same "ordered sequence of asanas with durations" shape also drives guided
practice plans: completeTaraGuidedOnboarding (practice-plan.ts:170) scores a
5-minute intake against a starter-template library (scoreStarterTemplate
weights goal-match at 60, demotes crow-prep by 40 for a wrist-sensitive
practitioner) and emits a validated 4-week / 20-session schedule. Plans are a
student-continuity feature, so they live mostly on the
coaching sibling; the authoring
takeaway is that one canonical asana vocabulary feeds class sequences,
AI-persona scripts, and practice plans alike.
Supervised AI instructor personas#
Tara permits a small number of supervised AI personas to cover off-hours, localized, and beginner classes. The monolith's promise — "sponsored by a human, teaches only approved scripts, clearly labeled, rate-limited" — is implemented as four independent gates, each a real function with an audit event.
Sponsorship requires a verified human#
registerTaraAiPersonaSponsor (ai-persona-sponsor.ts:107) refuses to create a
persona unless validateSponsorInput (:181) confirms the sponsor's
verificationState === 'verified' and that they carry credential references;
the persona is then bound to a closed scope set drawn from
TARA_AI_PERSONA_SCOPE_OPTIONS (sequence-script-only, student-q-and-a,
post-class-reflection, booking-prep, safety-handoff). A sponsor can
disableTaraAiPersonaSponsor (:134) with a reason (≥ 8 chars) that appends a
disable audit event — editorial ownership is revocable and logged.
The region cap is floor division#
evaluateTaraAiPersonaRegionalSchedulingCap (ai-persona-region-cap.ts:50)
enforces one AI persona per four verified human instructors by
Math.floor(verifiedHumanInstructorCount / 4). The fixtures make the arithmetic
honest: a region with 3 verified humans (US-NY) gets floor(3/4) = 0
personas; 8 humans with 2 active personas (US-CA) is capReached.
Verified-human schedules never consume the cap, and an AI-persona attempt with
no aiPersonaId throws. There is no way to schedule the (N+1)th persona without
onboarding four more humans first.
Out-of-script asanas hand off or no-op#
A persona teaches only from a sponsor-approved script.
authorTaraAiPersonaSeq- uenceScript (ai-persona-sequence-script.ts:124)
requires an active sponsor registration carrying sequence-script-only scope,
validates every line's asana against the canonical library
(assertKnownCanonicalAsana, :259), and runs the script lines through the
invitational linter below. At runtime, evaluateTaraAiPersonaSequenceAttempt
(:154) matches a requested asana against the script: a scripted asana returns
speak-script-line; anything else returns handoff-to-sponsor or
graceful-noop per the script's restrictionMode — never an improvised pose.
The fixtures encode exactly the monolith's adversarial case: the in-script
tadasana-iyengar-supported is permitted; the out-of-script "improvise Lotus as
a surprise peak pose" (padmasana-iyengar-supported) is blocked.
The nameplate label can't come off#
buildTaraAiPersonaSponsorNameplate (ai-persona-nameplate.ts:29) stamps a
locked, removable: false label reading
AI persona — sponsored by <sponsorDisplayName>, and
validateTaraAiPersonaNameplate throws if the text is edited or the lock
cleared. blockTaraAiPersonaNameplateRemoval (:51) flips removalBlocked and
audit-logs any removal attempt rather than honoring it — the "sponsored by a
human" disclosure is structurally non-removable.
Tone, lineage, and citation#
Tara's trauma-informed defaults are "enforced by policy rather than left to instructor discretion," and the policy is four cooperating gates.
| Gate | File | Rule |
|---|---|---|
| Invitational language | invitational-language-linter.ts |
13 directive phrases flagged blocking; any hit forces needs-editorial-revision |
| Eyes-open default | eyes-open-policy.ts |
Eyes stay open; a close cue is suppressed without an explicit, pattern-matched invitation |
| Class style mode | class-style-mode.ts |
Directive cueing only in a declared advanced-directive-opt-in class, surfaced in the listing |
| Lineage grounding | lineage-grounding.ts |
An uncited lineage claim is needs-citation and blocks editorial review |
Invitational language. lintTaraInvitationalLanguageSequenceScript (:56)
runs each cue line against DIRECTIVE_LANGUAGE_RULES (:40) — 13
word-boundary, case-insensitive patterns (must, should, need to,
have to, do not, don't, never, force, push, hold, stand, move,
teach) — each with a concrete rewrite suggestion ("Replace 'must' with 'you
might' or 'if it works for you'"). Every match is emitted at blocking
severity, so a single must or force flips the whole review to
needs-editorial-revision, and assertTaraInvitationalLanguageReviewApproved
(:87) throws on it. This is the same linter the AI-persona script author
calls, so personas can't smuggle directive language in either.
Eyes-open and style mode. evaluateTaraSequenceEyeState
(eyes-open-policy.ts:43) defaults every cue to eyes-open; an eyes-closed
request is suppressed (applied state forced back to open,
autoCloseSuppressed: true) unless the cue carries an explicitInvitation flag
and the invitation text matches one of four permissive patterns
(EXPLICIT_EYES_CLOSED_INVITATION_PATTERNS — "if it feels…", "you may…",
"optional…", "invitation to close"). This TS policy deliberately mirrors the C++
runtime V3TaraEyesOpenPolicy so authoring and the avatar can't disagree about
whether an instructor's eyes may close. class-style-mode.ts then lets an
instructor opt a hard class into advanced-directive-opt-in (the only mode
where directiveCueingAllowed is true), and
composeTaraClassDescriptionWithStyleMode (:55) appends the mode declaration
to the listing so students self-select before booking.
Lineage grounding. Every published sequence carries a lineage tag, and
Sophia grounds it. buildTaraLineageEditorialReview
(lineage-grounding.ts:204) walks each claim through groundLineageClaim
(:316) against TARA_LINEAGE_SOURCE_REGISTRY (:103), where each source has
a sourceType, lineageTags, and an authorityScore (the verified Iyengar
registry profile scores 0.96; the Light on Yoga bibliographic card 0.91). A
claim with requiresCitation and no sources resolves needs-citation at
blocker severity; cited-but-unsupported resolves needs-citation at major;
an editorial-context claim that doesn't require citation passes as "does not
publish as factual lineage." The review's status is blocked if any claim needs
citation. The fixture is precise: Maya Anand's "verified Iyengar-aligned
lineage" and "Iyengar-method vocabulary" claims pass on their sources, but the
uncited "direct Mysore family teaching line from 1932"
(TARA_LINEAGE_UNSOURCED_CLAIM_ID) is exactly what blocks the review — the
unsourced "tradition self-attested" path the monolith describes.
This is the same grounding posture Saraswati applies to persona backstory, and
the engine is genuinely shared. libs/v3/sophia-saraswati-grounding grounds the
six GA persona dossiers (reviewSaraswatiBackstoryGrounding,
backstory-grounding.ts:504): every claim that touchesRealCulture — a raga
reference, a Sufi-poetry boundary, a Mandarin-language fragment — must carry a
Sophia citation trail whose source supports both the persona and the claim kind,
or the report is blocked; buildSaraswatiAudienceBackstoryCitationClaims
(:597) then renders those trails as hover/tap/gaze citation markers across
web, mobile, and VR. It is the Saraswati side of the same "no uncited cultural
claim ships" rule that gates a Tara lineage tag.
Instructor economics#
Two economies meet at Tara, and only one of them is in this library.
The class-fee split is the monolith's, settled in V1. The default 20%
platform / 80% instructor on paid classes, 10% / 90% on tips and donations, the
donation-floor fee waiver, the 10% private fee, and the optional 0–10% routing
to a Tara Lineage Fund are the product model in features§"Compensation,
Tips, and Studio Splits." They are encoded as an Aje royalty waterfall and
settled through V1 Lilith-Commerce / Stripe Connect — not implemented in
libs/v3/tara-studio. Treat them as the commerce posture, covered on
commerce, rights & takedown.
The voice-signature royalty is real and lives here. When an instructor lends their cloned voice, a separate, mandatory 5% added royalty share rides on top of their normal split — and that machinery is code, as a five-stage stack:
- Consent.
createTaraTtsVoiceConsentWorkspaceState(tts-voice-consent.ts:106) keeps two separate purpose records (aja-cues,localized-dubs), verified-instructor-only, each Lilith-Rights audit-logged, with a 30-day withdrawal deadline computed on opt-out. - Contract.
createTaraTtsVoiceContractTemplate(tts-voice-contract.ts:173) bakes the boundaries in as throwing invariants: Tara-surface-only, a mandatorydefaultAddedRoyaltyShareBasisPoints = 500(5%), a 30-day withdrawal right, Lilith-Rights counsel signoff, and aprohibitedUseslist that forbids cross-instructor, cross-tenant, Saraswati-persona, non-Tara-surface, arbitrary-prompt, and public-figure-impersonation reuse. A plain-language summary is surfaced in V1 Studio at/studio/tara/tts-voice-contract. - Recording.
reviewTaraTtsVoiceRecordingSession(tts-voice-recording-session.ts:279) requires ≥ 60 clean source minutes (≥ 240 for a studio-grade upgrade), full coverage (asana / breath / Sanskrit / localized-dub / phoneme), a 35 dB SNR floor with zero clipped samples, andencrypted-master-onlyegress (raw samples stay in Lilith-Rights). Its anti-impersonation gate blocks any voiceprint scoring ≥ 8600 bps (86%) against a public-figure registry and caps the similarity false-positive rate at 1%; only then doesbuildTaraTtsVoiceSignatureFromRecordingSessionmint thevoice-signature:tara:<instructor>:v1. - Runtime scope-lock.
enforceTaraTtsVoiceRuntimeScopeLock(tts-voice-scope-lock.ts:97) re-checks every playback.detectScopeViolationsflagscross-instructor,cross-tenant,saraswati-persona,non-tara-surface,missing-active-consent, orsignature-owner-mismatch; on any violation it fails loud — auto-withdraws all active consents, stamps a 30-day withdrawal deadline, and raises acriticalLilith-Rights operator alert. The misuse drill (runTaraTtsVoiceScopeMisuseDrill) proves three attack scenarios all block and auto-withdraw end-to-end. - Settlement.
settleTaraTtsVoiceRoyaltyDistribution(tts-voice-royalty-distribution.ts:201) pays the 5% added share only on the two payable use cases —on-demand-aja-cue-playbackandlocalized-dub-stream— and explicitly not on live-class cues.runTaraTtsVoiceRoyaltySettlement- Testis the worked example: $120.00 of on-demand playback yields 600¢, $83.00 of localized dub yields 415¢, for a 1,015¢ added share routed to the signature-owning instructor through an Aje waterfall ref and audit-logged to Lilith-Rights.settle…throws if the review isblocked.
Edge cases and failure modes#
- One unsigned asana fails the whole library. The GA gate is all-or-nothing equality, not a percentage.
- A single directive word fails the script.
must/force/pushflip the linter toneeds-editorial-revision; the AI-persona author runs the same linter. - Eyes-closed needs words, in two places. The TS Studio policy and the C++ avatar policy both suppress an auto eye-close cue without an explicitly permissive invitation.
- Personas are rate-limited by humans. Fewer than four verified humans in a region means zero personas, full stop — floor division, no rounding up.
- An uncited lineage (or cultural) claim blocks publish. Both grounders fail loud on a real-attribution claim with no supporting source.
- Voice misuse auto-revokes. Any out-of-scope playback request withdraws all active consents and alerts an operator, rather than silently serving the voice.
- The 5% share is voice-only. It never applies to live-class TTS or the general class-fee split — that economy is V1 Lilith-Commerce.
Where this connects#
- Tara instructors, classes & coaching — onboarding/verification, the live-class lifecycle, on-demand library, and the Aja body-coaching loop these authored sequences feed.
- Commerce, rights & takedown — the 20/80 split, tips/donations, the Tara Lineage Fund, and the Aje royalty waterfall this voice royalty rides into.
- ../architecture/tara-classes-aja-and-commons.md
— the architecture-side treatment of the same
@oshun/tenant-tara-studiopolicies, the Aja pose pipeline, and the Lilith Commons venues. - ../architecture/authoring-and-content-pipeline.md
— the web-Studio-vs-UE authoring split, the Prisma
payloadHashintegrity spine, and how a published manifest reaches a client. - The feature hub: ../V3_features.md.