Oshun Platform · Features

Tara — Rituals and Contemplative Practice

A focused page within the Oshun Platform Features documentation. The full map and every sibling page live in the Features hub.

12sections16 minread5tables

On this page

Tara is Oshun V1's experiential spine: the contemplative-practice domain that turns a stated mood or moment into a single trustworthy invitation to sit, breathe, or rest, and then carries the person humanely across days, programs, and lineages. It serves both everyday customers seeking meditation, breathwork, sound, and prayer-style practice (the consumer hub at /tara) and practitioners or operators who need depth tools (the /domains/tara/* surface tree). This page is the feature-side companion to the architecture catalog; the hub for the set is ../features.md. Unlike a CRUD library of audio files, Tara's domain model is genuinely contemplative: per-mood recommendation slates with crisis handoff, breathwork cadences measured in inhale/hold/exhale seconds, lineage syncretism gates, a session state machine, and a continuation model that respects prerequisites. All of it is shipped as validated contracts in libs/contracts/src/tara/index.ts (2,688 lines, re-exported via export * from './tara' at libs/contracts/src/index.ts:25).

What ships, honestly#

The contract model, the domain adapter, and the BFF read/write layers are real and tested. The audit (v1-completeness-audit-2026-06-22.md) rates the core experiential journeys — tara-daily-ritual, first-tara-sit, and tara-to-nisaba-handoff — as deep coverage, which confirms the spine is genuinely shipped rather than mocked. A handful of more ambitious promises are spec-described and only partially evidenced: cross-device resume, watermarked download with preserved attribution, vibration-based pacing for hearing-impaired users, and the full Living Scenes "Contemplative Arc" immersive runtime that paces card transitions to a breath-cycle clock. Companion components for those exist; the full immersive arc runtime is not confirmed in code. Where something is planned or gated, this page says so — honest "planned/gated" beats fake "shipped."

Surfaces#

The consumer hub is at /tara (apps/oshun/web/src/app/tara/page.tsx, rendered through the Lilith-design-system TaraRoom). The immersive session page is a real route at /tara/sit/[id] (apps/oshun/web/src/app/tara/sit/[id]). The high-level surface list in the source describes "immersive session pages" but omits this path; it is the actual session route a customer lands on when they begin a sit. Power-user depth tools live under /domains/tara/*, and every one of these directories resolves to a real page in apps/oshun/web/src/app/domains/tara/:

Surface Route Purpose
Consumer hub /tara Mood-first entry, recommended slate, continue, streak
Immersive session /tara/sit/[id] The actual sit: audio, transcript, breath pacing
Analytics /domains/tara/analytics Practice analytics depth
Collections /domains/tara/collections Saved/curated practice sets
Courses /domains/tara/courses/[id] Multi-session course detail
Programs /domains/tara/programs Program arcs
Search /domains/tara/search Taxonomy-aware practice search
Sounds /domains/tara/sounds Sound-modality catalog
Teachers /domains/tara/teachers, /domains/tara/teachers/[id] Teacher profiles

On mobile, Tara is not a screen-tree. The mobile app (apps/oshun/mobile/src) is organized by feature, and Tara appears as companion components and sections rather than a tara/ surface directory — the previously documented apps/oshun/mobile/.../tara/ path glob does not resolve to a real directory. Concretely, mobile ships TaraDomainHomeSection.tsx, TaraQuickResetSection.tsx, TaraSleepDownshiftSection.tsx, TaraReflectionCaptureCard.tsx, MobileTaraLiveClassBookingCard.tsx, and the cross-domain companion cards TaraNisabaPassageCompanionCard.tsx, TaraAreteNextStepCompanionCard.tsx, TaraNyxPerspectiveCompanionCard.tsx, TaraVeritasSophiaCompanionCard.tsx, TaraMetisStudyCompanionCard.tsx, and TaraAssistantFollowUpCompanionCard.tsx (all under apps/oshun/mobile/src/components/, each with a sibling .test.tsx).

The BFF exposes Tara at apps/oshun/bff/src/routes/tara.ts (registerTaraRoutes) over read adapters in apps/oshun/bff/src/adapters/tara-read-adapters.ts. The route set under /v1/tara/* includes /v1/tara/recommended, /v1/tara/continue, /v1/tara/favorites (GET/POST/DELETE :meditationId), /v1/tara/streak, /v1/tara/history, and the adapter introspection trio /v1/tara/adapter/{capabilities,availability,search}.

The canonical taxonomies — shipped reference datasets, not just types#

Tara's taxonomies are not only Zod types; the canonical content is exported as runtime constants validated by satisfies against their entry schemas, so the same dataset that drives recommendations is the one tests assert against. This is the difference between a documented axis and a shipped, validated reference dataset.

Mood taxonomy (TARA_MOOD_TAXONOMY — 12 entries)#

The enum MoodTaxonomySchema is anxious, scattered, restless, heavy, low, neutral, curious, joyful, agitated, grieving, fearful, peaceful — an exact match to the source. Each entry carries a distressLevel (none/low/moderate/high), a recommendationSlate (1–4 unique themes), and a crisisHandoff object. The interesting part is the superRefine guard on MoodTaxonomyEntrySchema: any mood at distressLevel: 'high' must set crisisHandoff.required: true, a required handoff must carry a non-null reason, and a non-required handoff must leave the reason null. The schema makes it impossible to ship a high-distress mood without a crisis route.

Mood Distress Recommendation slate Crisis handoff
anxious moderate grounding, breath, presence, release
scattered low focus, breath, presence
restless low grounding, breath, body-scan
heavy moderate body-scan, release, lovingkindness
low moderate gratitude, lovingkindness, body-scan
neutral none presence, focus, gratitude
curious none awe, perspective, presence
joyful none gratitude, lovingkindness, awe
agitated high grounding, release, breath required — route through crisis-aware safety review
grieving high lovingkindness, body-scan, release required — surface crisis-aware support resources
fearful high grounding, breath, courage required — route through crisis-aware safety review
peaceful none presence, equanimity, gratitude

The crisis-handoff branch is wired into the domain adapter via lilith-mood-crisis-handoff (re-exported from libs/oshun/domain-tara/src/index.ts), so a high-distress mood does not merely get a gentler slate — it hands off to Lilith's persona-policy safety frame. See Lilith Persona Policy.

Theme taxonomy (TARA_THEME_TAXONOMY — 15 entries)#

ThemeTaxonomySchema = presence, breath, body-scan, lovingkindness, equanimity, gratitude, sleep, focus, awe, perspective, grounding, release, devotion, surrender, courage. Each entry binds compatibleMoods and defaultModalities, which is what lets a mood's recommendation slate resolve to concrete practices rather than just labels.

Modality taxonomy (TARA_MODALITY_TAXONOMY — 14 entries)#

ModalityTaxonomySchema has 14 values across six families (ModalityFamilySchema: stillness, guided, breathwork, sound, embodiment, visualization, devotional): silent, guided, the four breathwork variants breathwork-box / breathwork-4-7-8 / breathwork-coherent / breathwork-alternate-nostril, the three sound variants sound-singing-bowl / sound-drone / sound-mantra, plus movement, posture, visualization, prayer, and devotional-reading. Every entry records family, requiresAudio, requiresMovementSpace, a sensoryLoad (low/moderate), an accessibilityFallback string, contraindicationNotes, and a nullable breathworkCadence. This is why accessibility is structural, not bolted on: e.g. silent falls back to "Text timer, haptic bell, and screen-reader completion cue," and breathwork-4-7-8 carries the contraindication "Avoid long holds for dizziness, panic spikes, or respiratory strain."

Breathwork cadences (BreathworkCadenceSchema)#

The breathwork modalities embed a real cadence — inhale, hold-after-inhale, exhale, hold-after-exhale (seconds) plus a cycleDescription — so a sit can pace UI, haptics, and audio against the actual breath:

Modality Inhale Hold Exhale Hold Cycle
breathwork-box 4 4 4 4 Four equal phases
breathwork-4-7-8 4 7 8 0 Inhale 4, hold 7, exhale 8, no final hold
breathwork-coherent 5 0 5 0 Even five-second in/out

(breathwork-alternate-nostril carries no fixed cadence — breathworkCadence: null — because it is paced by side-switching, not a fixed clock.)

Duration buckets (TARA_DURATION_BUCKETS)#

Five buckets gate not just length but recommendation cadence. The DurationBucketSchema superRefine pins every shipped bucket to its canonical requirement table, so a long retreat practice can never masquerade as a daily interrupt:

Bucket Range Cadence Default min Min hours between recommendations
micro 0–2 min interrupt 2 0.5
short 3–10 min daily 7 8
standard 11–25 min daily 15 12
long 26–60 min weekly 45 72
retreat 61+ min (maxMinutes: null) retreat 90 168

getTaraDurationBucketForMinutes() resolves a duration to its bucket and is used inside TaraPracticeSchema to reject practices whose declared durationBucket disagrees with their durationMinutes.

Context tags (TARA_CONTEXT_TAGS)#

ContextTagSchema = morning, midday, evening, night, pre-meeting, post-stress, transition, sleep-onset, after-conflict, awe-inspired. Each tag carries a recommendationWindow, a quietHoursSensitive flag, a triggerKind, eligible triggerSignals, preferredLocalHourBands, default duration buckets, and a themeBias. For example, night is quietHoursSensitive: false with band 21:00–05:00; it biases toward sleep/release/surrender and prefers micro/short — the model keeps late invitations low-arousal and brief.

Lineage taxonomy (TARA_LINEAGE_TAXONOMY — 8 lineages)#

LineageTaxonomyIdSchema declares eight lineages: secular-breath-awareness, theravada-anapanasati, mahayana-bodhicitta, vajrayana-tara-devotion, yogic-pranayama, bhakti-devotional-prayer, advaita-self-inquiry, and comparative-contemplative-study. Each lineage names real teachers and scriptural references — Gautama Buddha and Buddhaghosa (cited for the Visuddhimagga meditation taxonomy) under Theravada Anapanasati with the Anapanasati Sutta (MN 118) and Satipatthana Sutta (MN 10); Shantideva (Bodhicaryavatara) under Mahayana Bodhicitta; Padmasambhava under Vajrayana Tara Devotion; Patanjali (Yoga Sutras, YS 2.49–2.53) under Yogic Pranayama; Mirabai under Bhakti Devotional Prayer.

The lineage superRefine enforces the syncretism gate: if syncretism.allowsCrossLineage is true, then comparativePersonaRequired must also be true (cross-lineage blending only happens behind a comparative persona), and any lineage whose family is comparative must allow cross-lineage comparison. So the model literally cannot offer a syncretic blend without disclosing it through a comparative frame — the user's declared frame is respected, and unrequested mixing is structurally blocked. Each lineage also ships a disclosureLabel (e.g. secular breath: "Secular breath practice with Buddhist source context; no lineage initiation implied.") and localeCoverage.

Session model#

Session state (SessionStateSchema)#

The session state enum is not-started, started, paused, drifted, resumed, abandoned, completed, partially-completed (libs/contracts/src/tara/index.ts around line 314). These are not free-form strings — legal transitions live in a real table, SESSION_STATE_TRANSITIONS, checked by isValidSessionStateTransition(from, to):

From Allowed next states
not-started started
started paused, drifted, abandoned, completed, partially-completed
paused drifted, resumed, abandoned
drifted resumed, abandoned
resumed paused, drifted, abandoned, completed, partially-completed
abandoned resumed
completed (terminal)
partially-completed (terminal)

A RitualSession records state, the full events log (max 200), and nullable timestamps startedAt, pausedAt, resumedAt, driftDetectedAt, completedAt, abandonedAt. Its superRefine runs validateSessionTimeline, which checks three invariants: each event's priorState must equal the previous event's newState; each transition must be legal per the table; and the session's top-level state must equal the final event's newState. The model is self-consistent by construction — you cannot persist a session whose declared state contradicts its own history.

About drifted — correcting the spec#

The source describes drifted as "idle beyond the per-modality drift_idle_seconds threshold." That per-modality numeric threshold does not exist in code: a search of libs/oshun/domain-tara/src and libs/contracts/src/tara finds no drift_idle_seconds, driftIdleSeconds, or idleThreshold identifier. Drift is modeled as an event, not a config constant: a RitualSessionEvent of type: 'drift' whose validateEventTypeState guard requires newState === 'drifted' ("Drift events must enter drifted state"), plus the nullable driftDetectedAt timestamp on the session. In other words, something upstream decides idleness and emits a drift event; the contract enforces where that event lands in the state machine, but does not itself hold a per-modality idle-seconds number. Treat the drift_idle_seconds language as aspirational until a real threshold ships.

Events and consequences (RitualSessionEvent)#

Every lifecycle action is a first-class event with type (start, edit, skip, recover, reschedule, pause, resume, drift, abandon, complete), timestamp, actor (user/assistant/system/operator), priorState, newState, a free-text reason, and a structured consequence (RitualSessionEventConsequenceSchema): stateChanged, scheduleChanged, stepId, completionPercent, completed, partialCompletion, recoveryOpened, changedFields, and a human message. The guard treats edit/reschedule/skip as state-preserving (they must keep the same state), while start/pause/drift/abandon/complete must change state. That is how the source's "humane skip and recovery" promise is encoded: a skip is a recorded event with a reason and a consequence, not a silent gap.

Partial completion#

RitualCompletionContractSchema carries minimumRequiredStepCount, minimumAudioCompletionPercent, partialCompletionThresholdPercent, the literal completionEventName: 'tara.ritual.completed', a reflectionCapture mode (required/optional/off), and emitsContinuationUpdate. The "≥ 80% of audio counts" rule from the source is expressed as a per-template threshold here rather than a single global constant, so each ritual can set its own completion bar. The domain adapter contributes two related constants in libs/oshun/domain-tara/src/types.ts: TARA_SESSION_CHECKPOINT_THRESHOLD_PERCENT = 5 (the minimum progress before a checkpoint is worth persisting) and TARA_SESSION_RECENT_COMPLETION_WINDOW_HOURS = 12 (the window used to treat a completion as "recent").

Continuation state (ContinuationStateSchema)#

ContinuationState is a richer model than "per-program progress." It holds a status (active/paused/recovery/completed) and four sub-models:

  • programArcprogramId, title, totalSessions, completedSessions, currentSessionIndex, with invariants enforced by superRefine: completedSessions cannot exceed totalSessions, and currentSessionIndex cannot exceed totalSessions.
  • teacherContinuity — per-teacher completedSessionCount and lastSessionAt, so the system can keep a learner with a teacher's voice.
  • themeContinuity — per-theme completedSessionCount, a depth ladder (introductorydevelopingdeepening), and lastSessionAt.
  • prerequisites and nextRecommendation — the prerequisite-respecting recommendation. If nextRecommendation.prerequisitesSatisfied is false, its blockedPrerequisiteIds must reference actually-unsatisfied prerequisites (and must be non-empty); if prerequisites are satisfied, it must carry no blocked ids. Satisfied prerequisites require a satisfiedAt; unsatisfied ones must not have one. The recommendation can therefore be honestly blocked on a missing prerequisite rather than silently skipping ahead.

A governance block (memoryScope of profile/session/notebook/tenant plus a nullable consentRecordId) ties continuation memory to consent — see Privacy, Consent, Data Portability, and User Controls and Iris Memory and Identity.

Rituals, steps, triggers, and scheduling#

A RitualStep (RitualStepSchema) has a kind, modality, durationMinutes, required/skippable flags, accessibility flags (transcriptRequired, captionsRequired, reducedMotionVariant), an optional breathworkPattern, audioAssetId, resourceRefs, and a reflectionPrompt. Its superRefine enforces real coherence: breathwork steps require a breathwork modality (and vice versa); the step's breathworkPattern must match the modality's canonical pattern; sound-* modalities require a non-null audioAssetId; and any non-required step must be skippable. A RitualTemplate composes steps, a RitualTrigger, RitualSchedulingRules, the completion contract, and a Lilith tone review.

RitualSchedulingRules carry cadence (on-demand/daily/weekdays/weekends/weekly/custom), preferredTimeLocal (validated HH:MM), quietHoursRespect, a calendarConflictPolicy (skip/defer/ask), and the humaneMissPolicy (no-accumulation/single-recovery/manual-only) — the contract-level expression of the source's "missed sessions never accumulate guilt-inducing UI." RitualTrigger carries quietHoursRespect and minHoursSinceLastCompletion, which is how the cross-domain cadence promise (no Tara push immediately after a heavy Veritas read) is realized. The scheduling and assembly logic lives in libs/oshun/domain-tara/src/ritual-scheduling.ts (~16 KB) and ritual-assembly.ts (~14 KB).

Contemplative tone review#

RitualTemplateLilithToneReviewSchema records a review by the literal reviewer 'lilith-contemplative-tone-rubric', scored across eight axes (RitualTemplateLilithToneReviewAxisSchema: pace, directness, metaphor-use, complexity, warmth, formality, patience-markers, avoid-phrase-absence), with an aggregateScore, a threshold, and a passesThreshold boolean, plus a script fingerprint, line count, and word count. This is the data behind the "contemplative tone review" promise — a ritual script that fails the rubric is flagged, not shipped. The adapter side is lilith-ritual-tone-review (re-exported from libs/oshun/domain-tara/src/index.ts).

Audio, accessibility, and save/share#

Playback rate is a real contract#

The source's "voice speed (0.85×–1.25×)" is implemented as a real policy in libs/contracts/src/tara/playback-rate.ts. PlaybackRatePolicy has { minRate, maxRate, step, decimalPlaces, preservePitch }, and the shipped QUALITY_PRESERVING_PLAYBACK_RATE_POLICY is frozen at minRate: 0.85, maxRate: 1.25, step: 0.05, decimalPlaces: 2, preservePitch: true. normalizePlaybackRate() snaps a requested rate to the nearest step, and throws PlaybackRateRangeError for non-finite or out-of-range input unless the caller passes { clamp: true }. The doc comment explains the rationale plainly: "Breath cues, room tone, and vocal formants degrade quickly outside this narrow range, so all Tara playback surfaces use the same contract." This is why the range is narrow and shared rather than a generic 0.5×–2× slider.

json
{
  "minRate": 0.85,
  "maxRate": 1.25,
  "step": 0.05,
  "decimalPlaces": 2,
  "preservePitch": true
}

Audio session controls#

The play/pause/scrub, ambient/voice mix, and sleep-fade controls from the source are implemented in libs/oshun/domain-tara/src/audio-session.ts (~22 KB) and audio-session-manager.ts (~11 KB), each with substantial sibling test files (audio-session.test.ts ~27 KB, audio-session-manager.test.ts ~20 KB).

Accessibility#

Accessibility is carried structurally: every modality entry has an accessibilityFallback and contraindicationNotes; ritual steps flag transcriptRequired, captionsRequired, and reducedMotionVariant; and TeacherProfile.accessibility records voiceDescription and a nullable transcriptVoiceName. Vibration-based (haptic) pacing for hearing-impaired users appears in the modality fallback strings (e.g. "haptic pacing," "haptic bell"), but the device-haptics runtime is spec-described — treat the hearing-impaired pacing as partially evidenced, not fully shipped.

Save / share / export and recovery#

Save-to-collection, send-to-friend (permission-gated), export-to-journal, and recovery (resume from any point, save partial-session reflection) are part of the surface set. Two pieces are spec-only / planned: watermarked download with preserved attribution (rights-gated), and cross-device resume — the single-device resume model exists, but cross-device resume is described, not confirmed in code.

Teachers#

TeacherProfileSchema defines a teacher with id, displayName, biography, an embedded lineage (a full LineageTaxonomy), roles (1–6 of teacher, breath-guide, narrator, scholar, reviewer), credentialSummary, localeCoverage, rights (TaraContentRights), and an accessibility block (voiceDescription, nullable transcriptVoiceName). Roles and locales are de-duplicated by superRefine. Teacher pages render at /domains/tara/teachers/[id].

Cross-domain companions#

Tara composes the rest of V1 rather than duplicating it. The domain adapter re-exports relationship modules arete-relationship, nisaba-relationship, nyx-relationship, and metis-relationship (from libs/oshun/domain-tara/src/index.ts), which back the mobile companion cards. That is how a sit can offer a Nisaba passage, an Arete next step, a Nyx perspective prompt, a Veritas/Sophia explanatory note, or a Metis study handoff. The audit's tara-to-nisaba-handoff deep-coverage rating reflects this; several of the other bridges remain unit-tested only, not yet end-to-end verified. See Arete — Goals, Habits, and Reflection, Nisaba — Scholarly Study, Nyx — Sky Events and Perspective, Veritas — Grounded Stories and Claims, and Metis — Education and Tutoring.

Living Scenes integration#

Tara delivers Contemplative Arc Living Scenes (loving-kindness, body-scan, breath-anchor, nature-immersion, gratitude) via the customer-tier Living Scene card. The Living Scenes contracts exist at libs/contracts/src/living-scene/{index.ts,score.ts,technique.ts}. The promise that arcs pace to the breath-cycle clock and honor the strictest Lilith contemplative tone band is spec-described: the contracts and companion components exist, but the full immersive arc runtime is not confirmed in code. For the full surface, see Living Scenes — Concept and Customer Promise and Scene Score Schema.

Mentor Presence#

An extension (implemented 2026-07-06 behind a default-off opt-in) replaces the sit player's static artwork with an embodied mentor: one to three governed mentor personas in a contemplative setting who arrive (already present, walking in, rising from water, or condensing from mist), settle into a lineage-appropriate posture, and guide the sit with voice, breath paced to the real BreathworkCadence, and held silence — choreographed as a pure function of the session state machine above (paused = rest-with-you, drifted = one soft bell, abandoned = no performed disappointment). It is opt-in, entitlement-gated, honors reduced motion and high-distress moods by forcing the calmest arrival, and collapses to the static safe frame under the crisis handoff. The §36 backlog is implemented (20 of 22 tasks; the open two are human gates — the lineage review and the release rehearsals/signoffs, which evaluateMentorPresenceRelease fails closed on until they happen) — see Mentor Presence — Meditating with a Master.

Libraries behind Tara#

The domain adapter and two further library families back Tara:

  • Domain adapterlibs/oshun/domain-tara/src (~54 TypeScript files), including types.ts (~35 KB), practice-models.ts (~24 KB), audio-session.ts (~22 KB), ritual-model.ts (~17 KB), ritual-scheduling.ts (~16 KB), ritual-assembly.ts (~14 KB), and audio-session-manager.ts (~11 KB).
  • @tara/* content/app stack@tara/content, @tara/config, @tara/api-client, @tara/monitoring, @tara/ui, @tara/features, @tara/analytics, @tara/database (under libs/tara/).
  • @oshun/meditation-* runtime libraries@oshun/meditation-core, @oshun/meditation-breathing, @oshun/meditation-session, @oshun/meditation-player, @oshun/meditation-progress, @oshun/meditation-timer, @oshun/meditation-offline, @oshun/meditation-analytics (under libs/meditation/).

The canonical contracts file exports more than the legacy "key contracts" list suggests — alongside RitualTemplate, RitualStep, RitualSession, ContinuationState, and SessionState, it ships TeacherProfile, BreathworkCadence, RitualSessionEvent, the Lilith tone-review schemas, the playback-rate contract, and the full canonical datasets TARA_MOOD_TAXONOMY, TARA_THEME_TAXONOMY, TARA_MODALITY_TAXONOMY, TARA_LINEAGE_TAXONOMY, TARA_CONTEXT_TAGS, and TARA_DURATION_BUCKETS.