# Tara — Rituals and Contemplative Practice

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](../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](./lilith-persona-policy.md).

### 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:

- **`programArc`** — `programId`, `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
  (`introductory` → `developing` → `deepening`), 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](./privacy-consent-portability.md)
and [Iris Memory and Identity](./iris-memory-identity.md).

## 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](./domain-arete.md),
[Nisaba — Scholarly Study](./domain-nisaba.md),
[Nyx — Sky Events and Perspective](./domain-nyx.md),
[Veritas — Grounded Stories and Claims](./domain-veritas.md), and
[Metis — Education and Tutoring](./domain-metis.md).

## 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](./living-scenes-overview.md) and
[Scene Score Schema](./scene-score-schema.md).

## 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](./mentor-presence.md).

## Libraries behind Tara

The domain adapter and two further library families back Tara:

- **Domain adapter** — `libs/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`.

## Related

- [Lilith Persona Policy](./lilith-persona-policy.md) — crisis handoff and the
  contemplative tone band
- [Mentor Presence — Meditating with a Master](./mentor-presence.md) — the
  embodied-mentor layer for the sit player (§36; implemented, release-gated)
- [Living Scenes — Concept and Customer Promise](./living-scenes-overview.md)
  and [Scene Score Schema](./scene-score-schema.md)
- [Nisaba — Scholarly Study](./domain-nisaba.md),
  [Arete — Goals, Habits, and Reflection](./domain-arete.md),
  [Nyx — Sky Events and Perspective](./domain-nyx.md),
  [Metis — Education and Tutoring](./domain-metis.md),
  [Veritas — Grounded Stories and Claims](./domain-veritas.md)
- [Privacy, Consent, Data Portability, and User Controls](./privacy-consent-portability.md)
  and [Iris Memory and Identity](./iris-memory-identity.md)
- [Product Surfaces](./product-surfaces.md) and the hub
  [../features.md](../features.md)
