Lilith is the V1 contemplative policy substrate — the deterministic rule engine that decides how Oshun is allowed to speak whenever a persona, a generated artifact, or an assistant turn touches contemplative, spiritual, therapeutic, or safety-sensitive ground. It is a substrate, not a customer domain: there is no first-read Lilith surface; instead its tone, claim, crisis, voice, lineage, and unsafe-output rules are meant to fire inline across whichever surface the member is on — a Tara ritual, a Veritas claim, a Sophia answer, a Metis tutor exchange, a Living Scene render. This page documents the policy catalogs and detectors that exist as real, versioned, tested code, names the concrete TypeScript symbols that back each rule, and is candid about which parts are fully wired into every runtime surface versus which are catalog-complete but only partially fanned out. It serves platform and trust-and-safety readers who need to reason about exactly what Lilith refuses, where its teeth actually bite, and what is still design intent.
The library lives at libs/oshun/persona-policy-lilith. Its src/index.ts
re-exports 30 modules — every catalog, detector, eval suite, and binding
named below is a real export from that barrel. The architectural companion to
this page is
Lilith — Contemplative Policy Substrate;
the feature hub is ../features.md.
Three things called "Lilith" — do not conflate them#
The name is overloaded across the monorepo, and a reader can easily merge three genuinely distinct things. This page calls it out explicitly because the naming collision is a real source of confusion:
- The persona-policy substrate (the subject of this page) —
libs/oshun/persona-policy-lilith. A pure policy library: catalogs, detectors, eval suites, and adapter wiring. No UI, no server. - The
/lilithdesign-system showcase route —apps/oshun/web/src/app/lilith/page.tsx. Its own header comment calls it the page where "the whole design system reads as one page" — a broadsheet card grid (the "cream-paper newspaper-grade design system") where each card is a real route into a real component. This is not a mount point for crisis policy; it is the index of the Oshun web design language. - The
apps/lilith/meditation product — an entirely separate application tree (bff,svc-ai,svc-analytics,mobile,desktop,cli,seed-corpus), with its own substrate libraries underlibs/lilith/(fastify-core,sdk,service-lib,partner-sdk,event-publisher,continuous-video-policy). This is a full meditation app, distinct from the V1 persona-policy substrate.V1/ARCHITECTURE.mdcorrectly disambiguates the two.
Note also what does not exist: there is no services/lilith,
infrastructure/lilith, or libs/contracts/lilith (unlike their psyche
equivalents). Lilith V1 is a library substrate, not a deployed service.
There is no /lilith/* customer route, no dedicated /lilith/crisis page, and
no canonical first-read surface for crisis policy. The operator-facing Lilith
work lives under
apps/oshun/web/src/app/operator/{admin,incidents,personas,studio}, the Lilith
studio at apps/oshun/web/src/app/lilith-studio/, the operator depth data at
apps/oshun/web/src/lib/lilith-data/operator-depth.ts, and the operator
component at apps/oshun/web/src/components/lilith/operator.tsx. (As an honest
triage note: the customer-side LilithExplore component in
apps/oshun/web/src/components/lilith/customer-shell.tsx is defined but is
imported by no route — a real example of the partial-fan-out caveat below.)
What is real, and what is still wiring#
The bright line worth stating up front: the policy library is overwhelmingly real and domain-specific, but the enforcement fan-out into every surface is partial. Concretely:
- Real: deterministic detectors with regex phrase catalogs, versioned policy sets, validated taxonomies, the canonical adapter's defense-in-depth crisis guarantee, and six named eval suites plus two cross-product harnesses. Every enum and constant cited on this page matches the source verbatim.
- Partial / aspirational: the completeness audit rates the
crisis-aware-tone-policyand thearete-living-offering-createLilith crisis pre-screen as partial. The architecture's promise that Lilith is "enforced on every assistant turn / Living Scenes render / Tara invitation" is the design intent and is encoded as a required-surface binding catalog — but uniform runtime fan-out across all surfaces is not fully proven, and the live cloned-voice provenance pipeline and the operator-override governance UI were not verifiable end-to-end (the catalog logic exists; the runtime/UI wiring is less so).
This page documents what is in the code; where something is intent rather than proven runtime, it says so.
The canonical adapter and the no-bypass crisis guarantee#
The entry point is createCanonicalLilithPersonaPolicyAdapter
(canonical-adapter.ts). It wraps an injected LilithPersonaPolicyApiAdapter
and exposes the policy surface every consumer calls: selectPolicy,
getToneGuidance, assessSafety, checkTopicScope, buildPromptOverlay, and
evaluateInteraction.
The most important property of this adapter is its defense-in-depth crisis
guarantee, and it is a concrete, testable mechanism rather than prose. When
constructed, the adapter binds createLilithCrisisSafetyAnalyzer() — the
validated 13-rule crisis catalog — on by default:
// canonical-adapter.ts
const crisisSafetyAnalyzer =
options.crisisSafetyAnalyzer ?? createLilithCrisisSafetyAnalyzer();
On every safety analysis at the adapter boundary, the injected backend's verdict
is merged with the crisis analyzer's verdict via mergeLilithSafetyAnalyses,
always taking the more severe signal on every axis (category, risk level,
and the boolean shouldEscalate / shouldBlock / requiresDisclaimer flags
are OR-ed; never downgraded). The merge ranks categories
safe < needs_disclaimer < out_of_scope < needs_escalation < blocked and risk
levels none < low < moderate < high < critical. The practical consequence: an
integrator who injects an always-"safe" stub analyzeSafety cannot silently
bypass the validated crisis catalog — a crisis the catalog detects is honored
regardless of what the injected backend returned. Because the merge can only
escalate, enabling it by default can only make a turn's disposition stricter.
This is the real teeth behind the "no-bypass guarantees" promise: crisis policy
supersedes persona, lineage, pedagogy, and grounding policy and cannot be
overridden by user prompt or admin copilot.
crisis-safety-analyzer.ts is the module that supplies this. Its
analyzeLilithSafetyViaCrisisPolicy runs detectLilithCrises
(severity-ordered) and, on any detection, builds a response plan with
buildLilithCrisisResponsePlan, emitting category: 'needs_escalation',
shouldEscalate: true, and a shouldBlock equal to the plan's haltSynthesis.
It is intentionally fail-closed: a detected crisis yields a hard block +
escalation so the downstream disposition resolves to block/escalate. When no
crisis is found, it returns the frozen SAFE_ANALYSIS constant — an honest
"nothing detected," not a fabricated success.
Accuracy note:
V1/ARCHITECTURE.md(§ Lilith · Adapter) once described the adapter assrc/adapter.tspluscontemplative-tone-policy.ts,assistant-persona-binding.ts, andcontent-qa-hooks.ts. All four files exist, but that list names 3 of ~30 modules and omits the largest, most load-bearing policy files —crisis-behavior-policy.ts(68 KB),unsafe-claim-policy.ts(65 KB),voice-policy.ts(62 KB),spiritual-boundary-policy.ts(43 KB),policy-model.ts(38 KB),surface-policy-binding.ts(34 KB),generation-gentleness-floor.ts(33 KB),teacher-safety-policy.ts(32 KB) — plus thecrisis-recovery/,sacred-symbols/, andtone-bands/subtrees. The canonical entry iscanonical-adapter.ts(createCanonicalLilithPersonaPolicyAdapter), not the bareadapter.ts.
Persona taxonomy — the seven canonical roles#
Every Lilith-governed persona inherits from exactly one of seven typed roles.
This is the single canonical persona taxonomy for V1; the Persona Registry, the
assistant persona-handoff surface, and every Lilith eval suite reference these
role names verbatim. The enum is LINEAGE_PERSONA_ROLES
(sacred-symbols/lineage-binding.ts:20) and the count is exactly seven:
| Role | Where it serves | Capabilities | Hard bans |
|---|---|---|---|
teacher |
Tara teachers, Metis tutors, Nisaba scholar-personas | instruction, scaffolded guidance, source citation | clinical diagnoses, treatment plans, prophecy, financial advice, legal advice |
coach |
Arete coaches, recovery-aware support personas | humane prompting, accountability, plan re-scope, friction | shaming language, escalating-stake framing, punitive streak rhetoric |
comparative |
cross-lineage comparative-religion / comparative-philosophy | even-handed comparison with named-source attribution | syncretic erasure of declared lineages, prescriptive synthesis |
explainer |
Veritas explainers, Nyx narrators, Metis lecture voices | grounded explanation with citation, counterclaim presentation | editorialization beyond source warrant, speculation framed as fact |
narrator |
Living Scenes narration personas | scene narration, time-aligned cues, mood pacing | outside-script improvisation, source citation in live scene flow |
steward |
admin-copilot, operator assistant, moderation/review-triage | operational tooling, audit-aware suggestion, policy reference | substituting for a human reviewer/moderator on consequential decisions |
assistant |
the general-purpose customer assistant | navigation, recall, light explanation, domain hand-off | pretending to be a teacher/coach/steward when one is specifically required |
Role inheritance is final: a Persona record fixes the capability ceiling
and default tone band on construction and cannot widen its inherited
capability set; tenant policy can only narrow it further. The specific persona
record adds named voice, avatar, lineage binding, locale, and approval state on
top of the inherited role. (teacher-safety-policy.ts carries a parallel
persona-family notion — coach, support, contemplative_teacher — used to
scope which teacher-safety policy set applies via fitsPersonaFamilies.)
Tone band catalog and per-band capability caps#
Tone bands are the named, ordered axis Lilith uses to gate behavior per surface,
persona, and context. The catalog is fully data-modeled in
tone-bands/catalog.ts: TONE_BAND_IDS declares the 8 bands in
strictest-first order, and TONE_BANDS is an array of ToneBandCap records
carrying the actual ceilings:
| Band | order |
Motion level (motionMax) |
audacityMax |
Share policy | Generation tiers |
|---|---|---|---|---|---|
contemplative-strict |
0 | reduced-motion (0.1) |
0 | opt-in-redacted-intent |
customer (gated) |
contemplative |
1 | low (0.25) |
1 | opt-in |
customer |
reflective |
2 | low (0.25) |
1 | opt-in |
customer |
neutral |
3 | medium (0.5) |
2 | allowed |
customer, curated-creator |
briefing |
4 | medium (0.5) |
2 | allowed-with-citations |
customer, curated-creator |
instructional |
5 | medium (0.5) |
2 | allowed-with-citations |
customer, curated-creator |
celebratory |
6 | high-pse-safe (0.8) |
3 | allowed |
customer, curated-creator |
urgent-safe |
7 | low (0.25) |
0 | operational-only |
operator (platform-emitted) |
The contemplative-strict band sets customerGenerationGated: true — its
customer generation requires an explicit product gate. The urgent-safe band is
the only one with shareAllowed: false; it is reserved for operational
notifications about safety-relevant state (degraded service, crisis-frame entry,
account security).
audacity is a 0–5 scale that Isis uses to cap generation parameters (style
intensity, motion magnitude, narrative novelty). clampAudacity enforces the
ordering literally:
Math.min(requested, bandCeiling, tenantCeiling ?? 5, userCeiling ?? 5).
Bands cap the ceiling; tenant policy may lower further; user preference may
lower further still — none can widen. narrowestBand returns whichever of a
set of bands has the lowest order, the mechanism by which a persona's default
band is merged with tenant/user narrowings.
validateToneBandCatalog is a real structural validator: it enforces canonical
ordering (order === index), motion-max in [0, 1], valid generation tiers,
and the coherence rule that operational-only and shareAllowed cannot
disagree. Lilith also publishes a per-surface transition graph
(tone-bands/transitions.ts) declaring which bands may follow which within a
session (for example, contemplative-strict may transition to contemplative
for a closing reflection but not directly to briefing); forbidden transitions
are rendered as section breaks, and the band caps are enforced downstream in
tone-bands/enforcement.ts.
Contemplative tone rubric#
contemplative-tone-policy.ts models the tone rubric as data, not adjectives.
It exports LILITH_CONTEMPLATIVE_TONE_POLICY_IDS, the pace axis
LILITH_TONE_PACE_LEVELS, LILITH_TONE_SILENCE_TOLERANCES,
LILITH_TONE_METAPHOR_USAGES (sparing | moderate | generous | poetic),
LILITH_TONE_WARMTH_LEVELS (reserved | warm | tender | effusive), and
per-policy ceilings in LILITH_CONTEMPLATIVE_TONE_CEILINGS. The
certainty-marker rule is concrete: the contemplative band's avoidPhrases
catalog literally contains 'obviously', 'everyone knows', 'the truth is',
and 'beyond debate' — the prohibited absolute claims the feature spec names.
Gentleness floor#
generation-gentleness-floor.ts is the pre-synthesis guard for any voiced or
contemplative generation. LILITH_PROHIBITED_GENERATION_LANGUAGE_CATEGORIES
includes 'fear-inducing-framing', backed by a real regex —
/\b(if you don'?t|or else|you'?ll fail|you are unsafe unless|something bad will happen|you will suffer|dangerous to stop)\b/i
— which directly implements the spec's certainty-marker prohibitions. The module
also encodes LILITH_INTERPRETIVE_UNCERTAINTY_MARKERS (the required-hedging
side), LILITH_AUTHORITY_POSITIONING_CATEGORIES (a regex catching
/\bi am (?!not\b)(?:your\s+)?(?:guru|prophet|healer|master|sole authority)\b/i,
the voice-of-authority avoidance rule), and
LILITH_MEDITATION_FRAMING_CATEGORIES (the descriptive-not-prescriptive
sensory-language rule). On failure, the prescribed runtime behavior is to not
synthesize and fall back to text until the draft is revised — the floor is
fail-closed, not advisory.
Teacher persona safety policy#
teacher-safety-policy.ts (version LILITH_TEACHER_SAFETY_POLICY_VERSION = 1)
governs persona-bound promises. It declares LILITH_TEACHER_SAFETY_POLICY_IDS
(including coach-practitioner, mental-health-support), an
LILITH_TEACHER_ABSOLUTE_NEVER list of advice categories that are categorically
banned, LILITH_TEACHER_CLAIM_SCOPES, and
LILITH_TEACHER_VETTING_EVIDENCE_KINDS for persona review. The
prohibited-promise catalog covers enlightenment, healing of medical conditions,
prophetic foreknowledge, romantic and financial outcomes, and guaranteed
transformation timelines; a missing financial-disclaimer maps to the required
"financial advisor" hand-off disclaimer. Required disclaimers include
present-time-only language, the "consult a qualified
[physician/therapist/financial advisor]" hand-off pattern for medical,
psychiatric, and financial framings, and synthetic-content disclosure on every
voiced or avatar persona. Identity rules forbid impersonation of named living
individuals without consent and contract, and of named historical or religious
figures without an explicit, reviewed lineage frame.
Crisis-aware behavior#
crisis-behavior-policy.ts (the 68 KB core) holds the validated 13-rule
crisis catalog. LILITH_CRISIS_TYPES is the canonical 13-entry enum:
suicide-ideation, active-self-harm, acute-panic, dissociation,
trauma-resurfacing, substance-crisis, interpersonal-violence,
violence-toward-others, abuse-disclosure, eating-disorder, child-safety,
psychosis-adjacent, acute-grief.
Staleness note: the prose in
V1/features.mdonce described the signal taxonomy as "suicidal ideation (active, passive, planned), self-harm (active, ideation)… psychotic-symptom indicators, child-protection signals." That prose does not map 1:1 to the code enum: the canonical enum useschild-safety(not "child-protection") andpsychosis-adjacent(not "psychotic-symptom"), addstrauma-resurfacingandacute-grief(absent from the old prose), and does not break suicide into separateactive/passive/plannedenum members at the type level. Those sub-qualifiers live one layer down, in the signal taxonomy.
Beneath the 13 response types is a finer-grained signal layer:
LILITH_CRISIS_SIGNAL_TYPES (15 entries, including suicide-active,
suicide-passive, suicide-planned, self-harm-active, self-harm-ideation,
domestic-violence, psychotic-symptom, child-protection) and the
LILITH_CRISIS_SIGNAL_TAXONOMY — an array of LilithCrisisSignalTaxonomyRule
records, each mapping a signalType to a responseCrisisType, a human label,
phrasePatterns (e.g. 'kill myself', 'end my life', 'want to die' for
suicide-active, with minimumRiskLevel: 'critical'), advisory
contextSignals, and a forced minimumRiskLevel. detectLilithCrisisSignals()
runs the catalog against an utterance.
Crisis resources are first-class: LILITH_CRISIS_RESOURCE_KINDS includes
suicide-hotline, crisis-text-line, emergency-services,
domestic-violence-hotline, and eating-disorder-hotline, resolved
region-aware (universal + regional registries, with a 'DEFAULT' fallback).
buildLilithCrisisResponsePlan assembles the resourcesToSurface,
statementsToDeliver, mustBreakPersona, and haltSynthesis directives for a
detection.
The per-signal response is fail-closed and well-defined: break persona to plain operator voice, surface region-aware crisis resources, halt synthesis (no ritual continuation, no avatar/voice rendering), suspend persona memory writes for the session, and open a parallel safety-incident record routed to crisis-trained reviewers. During an open crisis frame: no recall of prior contemplative scripts that would re-enter the crisis state, no generative summarization, no recommendation of contemplative practices, and no admin-copilot inspection without elevated authorization.
Crisis recovery journey#
The crisis frame is only half the story; the recovery journey is the
user-facing path back into the product, implemented as the crisis-recovery/
subtree (not just prose):
stillness-window.ts— after a crisis frame fires, every non-safety surface is suspended.STILLNESS_WINDOW_DEFAULT_SECONDS = 600(10 minutes),STILLNESS_WINDOW_FLOOR_SECONDS = 180(the floor is never less than 3 minutes), andSTILLNESS_WINDOW_EXTENSION_CEILING_SECONDS = 7200. The module enumeratesNON_SAFETY_SURFACES(teaching,invitation,scheduled-generation,companion-suggestion,studio,gallery,voice-clone,live-scene) that are suspended, andSAFETY_SURFACES(crisis-resources,safety-resources,audit-platform,support-handoff,incident-record,reentry-prompt) that remain available. Extensions carry a typed reason (crisis-reframe | new-indicator | operator-extension).reentry-flow.ts— at the end of the window the product asks once whether the member wants to continue; declining routes to an idle-safe surface and the product does not re-ask until a fresh session. On accept, the member lands on a re-entry home with conservative defaults (contemplative-strictband, no scheduled invitations, no sensitive-category recommendations).reframe-protection.ts— if a new crisis indicator lands inside an open stillness window or within 24h of frame close (REFRAME_PROTECTION_AFTER_CLOSE_SECONDS = 24 * 3600),decideReframeextends the existing frame (kind: 'extend',REFRAME_EXTENSION_SECONDS = 600) rather than re-firing a fresh one — guarding against thrash and re-traumatization (double-surfaced resources, double-restart of the window).check-ins.ts—CHECK_IN_KINDS = ['24h', '7d']withCHECK_IN_DELAY_SECONDS = { '24h': 86400, '7d': 604800 }. Soft follow-ups are default opt-in, user-disable-able, delivered via the assistant only — never via push or notification.scheduleCheckIns,applyCheckInEvent, andlistDueCheckInsmodel the lifecycle.incident-record.ts— every crisis frame generates anIncidentrecord (TODOS §1.2); operator review is required within the tenant-policy time-box.locales.ts— support-resource sets and operator voice strings are localized per V1 launch locale and declared frame.
The member also gets a "what happened" surface in profile/safety that shows the audit-platform-visible record of the frame (entry time, exit time, suppressed surfaces, operator actions) — the member owns the record of what occurred.
Launch locales#
The V1 launch-locale set is canonical and exact: OSHUN_LAUNCH_LOCALES
(libs/oshun/i18n/src/index.ts:26) = en-US, es-US, fr-FR, de-DE,
ar, he, ja-JP, pt-BR (8 locales), with
OSHUN_DEFAULT_LAUNCH_LOCALE = 'en-US' and ar / he being RTL. The web shell
consumes this via apps/oshun/web/src/i18n/config.ts (which imports
OSHUN_LAUNCH_LANGUAGE_PREFERENCES and RTL_LOCALES from the same i18n
package). Both doc-cited paths resolve. Default-frame crisis copy must be
reviewed by a regional safety advisor before launch in a new locale; every
reference to "V1 launch locales" in the feature docs means exactly this set.
Voice-quality and voice-abuse policy#
voice-policy.ts (62 KB) backs both the voice-quality and voice-abuse rules.
Domains and quality. LILITH_VOICE_DOMAINS = guided-practice, teaching,
sacred-reading, breathwork, silent-sitting, crisis-response. The
LilithVoiceQualityTarget interface models acoustic targets a contemplative
voice must meet — pace WPM band, inter-clause pause band, loudness in integrated
LUFS, a true-peak ceiling in dBTP (loudness-war mastering is prohibited in
practice audio), minimum SNR, pitch-variation band in semitones (too flat is
robotic, too wild is theatrical), and a sibilance-harshness ceiling.
LilithVoiceNaturalnessFloor is the minimum-naturalness gate (below floor
forces fallback to text), LILITH_VOICE_DOMAIN_TIMING_POLICY_SET carries
per-domain pace bands (a Tara meditation pace ≠ a Veritas explainer pace), and
LilithVoiceRerenderPolicy caps re-render attempts per turn. The runtime checks
are checkLilithVoiceQuality(...) and checkLilithVoiceDomainTiming(...).
Abuse and provenance. LILITH_VOICE_ABUSE_PATTERNS is a 16-entry catalog —
sustained-shout, coercive-command-cadence, manic-cadence,
deceptive-warmth, simulated-confidant-intimacy,
simulated-breathing-inconsistent-with-content,
hypnotic-induction-without-disclosure, rapid-gasping-loop,
subliminal-layer, impersonation-of-real-teacher,
impersonation-of-clinician, parasocial-intimacy-escalation,
sexualized-prosody, infrasound-entrainment, unwatermarked-cloned-output,
and identity-drift-from-consented-profile. LILITH_VOICE_WATERMARK_ALGORITHMS
names the two real algorithm identifiers (oshun-phase-watermark-v1,
oshun-spread-spectrum-v1).
LILITH_CLONED_VOICE_CONSENT_STATUSES = ['signed', 'revoked', 'expired'] gates
cloned voices, and LilithVoiceProvenanceRequirements models the immutable
provenance record (consent ID, prompt, model, watermark hash, timestamp,
invoking user, tenant). Above-threshold abuse halts generation, notifies the
operator, suspends entitlement, and opens review; consent revocation cascades
across all generated assets.
Honest caveat: the catalog logic above is real and tested, but the live cloned-voice provenance pipeline — end-to-end from consent record through watermarked render to immutable provenance — was not verifiable end-to-end at the runtime/UI level. Treat the runtime fan-out as design intent backed by real policy primitives.
Spiritual-domain boundary rules#
spiritual-boundary-policy.ts (43 KB) encodes declared-lineage respect and
extractive-syncretism prevention. LILITH_SPIRITUAL_BOUNDARY_RULE_IDS covers
within-tradition-exegesis, cross-tradition-comparison,
cross-tradition-practice-transfer, inter-tradition-conversion-pressure,
claiming-universal-truth, supernatural-claim,
initiation-or-empowerment-claim, protected-lineage-disclosure,
secular-translation, and scholarly-citation. Each rule resolves to one of
four LILITH_BOUNDARY_STANCES — permit, permit-with-attribution,
redirect, or refuse. LILITH_PROHIBITED_SPIRITUAL_CLAIM_CLASSES includes
prophecy, soteriological-guarantee, spiritual-level-diagnosis,
karmic-pronouncement, and cosmology-as-fact, each with a phrase catalog —
e.g. the soteriological-guarantee class catches 'you will reach nirvana' and
the boundary catalog catches 'you will enter samadhi'.
LILITH_TRADITION_SENSITIVITIES (closed-practice, initiation-required,
oral-transmission-only, gendered-role-restricted, age-restricted,
community-gatekept, tribal-sovereignty-protected) tags traditions whose
practices require extra care.
Cultural and lineage sensitivity policy#
sacred-symbols/lineage-binding.ts is the validator behind declared-lineage
respect. checkPublishLineage rejects an artifact at composition time with a
typed LineageBlockReason — missing-lineage-tag,
cross-lineage-without-comparative, invalid-lineage, or duplicate-lineage —
across the PUBLISHABLE_KINDS set (Tara passage, Nisaba passage, Veritas story,
Living Scene template, etc.). The comparative-only mixing gate is literal:
only a comparative persona may juxtapose lineages within a single arc;
teacher and coach personas must hold to a single declared lineage per arc.
recommendationFraming surfaces a recommendation from outside the member's
declared frame as "comparative" with a soft notice, and emitLineageBinding /
captureLineageBindingAuditRecord /
attachLineageBindingToLivingScenesRenderEnvelope emit the per-session
LineageBinding attestation captured in the audit trail and the Living Scenes
Render Envelope. The companion sacred-symbols/register.ts is the curated
catalog of symbols/elements declared sacred-in-context, whose first-time use in
any surface requires operator-tier approval.
Unsafe-claim handling#
unsafe-claim-policy.ts (65 KB) is the claim engine.
LILITH_UNSAFE_CLAIM_CLASSES is the 9-class taxonomy: medical,
psychiatric, financial, legal, prophetic, conspiratorial,
defamatory, retaliatory, electoral-influence.
LILITH_UNSAFE_CLAIM_CLASS_TAXONOMY maps each class to a
LilithUnsafeClaimClassRule carrying a defaultSeverity (one of
LILITH_UNSAFE_CLAIM_SEVERITIES = ['elevated', 'high', 'critical']), linked
category IDs, and a detectionPhrases catalog — for example, the medical
class defaults to critical severity, links the miracle-cure-physical,
reject-medical-care, and dangerous-breathwork categories, and detects
phrases like 'cure', 'medical treatment', 'surgery', 'chemotherapy',
'vaccine'.
The per-class default response is one of the seven
LILITH_UNSAFE_CLAIM_CLASS_RESPONSE_TYPES: refuse, refuse-with-resources,
hedge-with-redirect, allow-with-citation-mandatory, allow-with-disclaimer,
allow-only-from-approved-source-set, expert-handoff. The engine ranks these
when multiple fire so the most-restrictive dominates, and every claim-handling
decision is logged with classifier output, the response chosen, the source set
used, and a user-feedback receipt.
Surface wiring, override governance, tenant constraints, and versioning#
These are the operational seams the feature docs describe narratively but which exist as concrete modules.
Surface binding. surface-policy-binding.ts
(LILITH_SURFACE_POLICY_BINDING_VERSION = 1) binds policy to named consumers.
LILITH_REQUIRED_SURFACE_WIRING_IDS enumerates the ten wiring points the docs
list as prose: tara-teacher-personas, contemplative-assistant-personas,
ritual-script-generation, meditation-script-narration, voice-rendering,
avatar-rendering, veritas-explainer-generation, sophia-grounded-answers,
metis-tutor-responses, support-copilot. Each binding runs through the
LILITH_SURFACE_POLICY_STAGES pipeline (registration, pre-generation,
draft-review, pre-render, post-render, audit) and selects from the 19
LILITH_SURFACE_POLICY_CHECK_IDS (teacher-safety, contemplative-tone,
generation-gentleness-floor, crisis-behavior, spiritual-boundary,
ritual-content-rules, unsafe-claim, citation-mandatory,
approved-source-set, voice-quality, voice-abuse,
cloned-voice-provenance, voice-watermark, avatar-persona-release,
synthetic-content-disclosure, operator-human-review,
operator-override-governance, tenant-policy-floor, claim-handling-audit).
validateLilithSurfacePolicyBindingSet proves the set is complete and
well-formed. This catalog is the concrete encoding of the "wiring points" — but,
per the candor section above, the runtime fan-out across every one of these
surfaces is the part rated partial; the binding catalog asserts the contract,
not that every surface currently executes it.
Override governance. operator-override-governance.ts
(LILITH_OPERATOR_OVERRIDE_GOVERNANCE_VERSION = 1) requires elevated
authorization for any operator override:
LILITH_OPERATOR_OVERRIDE_AUTHORIZATION_ROLES = governance-lead,
trust-safety-operator, safety-engineer, clinical-advisor, legal;
authorization statuses are approved | pending | rejected | expired; outcomes
are
allow | allow-with-disclaimer | redirect | escalate | block | send-to-human-review.
Overrides are time-bound (LilithOperatorOverrideScope), rationale-captured,
and audited (LilithOperatorOverrideAuditRecord), and recurring overrides trip
the LILITH_OPERATOR_OVERRIDE_RECURRING_POLICY review trigger. (The governance
UI that drives this was not verifiable end-to-end; the policy logic is real.)
Tenant constraints. tenant-policy-constraints.ts
(LILITH_TENANT_POLICY_CONSTRAINT_POLICY_ID = 'tenant-policy-constraint-floor')
encodes the asymmetry: a tenant cannot loosen the operator baseline and
can only tighten it. validateLilithTenantPolicyConstraint literally
rejects with errors like
tenant cannot loosen operator baseline: missing check "…",
…added modality "…", a weaker grounding requirement, or a more permissive
memory envelope — so, e.g., an institutional Metis can tighten unsafe-claim
thresholds but never relax them.
Versioning and moderation. policy-versioning.ts makes every Lilith policy
a versioned artifact with changelog, evaluation evidence, rollout cohort, and
rollback plan; persona-release-metadata.ts carries the persona-release bundle
and lifecycle
(proposed → in-review → approved → deployed → maintained → deprecated → retired,
every transition writing a PersonaLifecycleEvent); and
moderation-queue-binding.ts routes flagged output into the review queue.
Evaluation suites#
The eval modules are real, not placeholders, and directly back the feature docs' "Evaluation suites" promise:
| Suite | What it gates |
|---|---|
eval-tone-quality |
gentleness, certainty markers, lineage attribution |
eval-crisis-handling |
per-signal response correctness and the no-bypass guarantee |
eval-clone-abuse-resistance |
cloned-voice abuse resistance |
eval-spiritual-boundary |
boundary-class refusals and stances |
eval-unsafe-claim |
per-claim-class default response correctness |
eval-regression-blockers |
release-blocking regression suite for safety degradation |
tone-cross-product-harness |
the band × persona × context cross-product |
lineage-per-tradition-harness |
per-tradition lineage policy parity |
Each ships with a co-located .test.ts exercising it. The regression blockers
suite is the gate that blocks a release when safety quality degrades.
Continuous-video tone class (Living Scenes)#
For Living Scenes, Lilith adds a continuous-video tone class covering
rhythmic-pattern + strobe detection (PSE-safe per ITU-R BT.1702-2 / WCAG, hard
kill before frames reach the user), per-persona luminance / contrast /
motion-density caps, color-cycle and flicker bands, narrative-cadence pacing
bands, the live-cue policy gate, sensitive-topic pre-roll on kept artifacts, and
a scene crisis frame (fade-to-still + plain operator voice + Iris memory-write
suspension + safety-incident record creation) that supersedes persona, lineage,
pedagogy, grounding, and any user/admin override. See
Scene Safety, Determinism, Provenance, and Cue Privacy
for the full scene safety surface; the separate
libs/lilith/continuous-video-policy library belongs to the meditation app, not
this substrate.
Tests (invariants worth naming)#
- Persona taxonomy: every persona inherits exactly one role; capability widening is rejected at construction.
- Tone-band caps: every band's caps are enforced in Isis generation, Living
Scenes, and share controls;
validateToneBandCatalogenforces canonical order and coherence. - Band transition graph: forbidden transitions render as section breaks; allowed transitions emit no break.
- Lineage policy: comparative-only mixing enforced; sacred-symbol register triggers a per-symbol approval gate; user-declared frame respected in recommendations.
- Crisis:
mergeLilithSafetyAnalysesonly ever escalates; the canonical adapter binds the 13-rule catalog by default so an always-"safe"injected backend cannot bypass it. - Crisis recovery: stillness-window minimum (3-minute floor) honored; re-frame protection extends rather than re-fires; localization parity across the 8 V1 launch locales; check-in cadence respects opt-out.
Related#
- Assistant Experience — the conversational surface where persona roles and tone bands are applied per turn.
- Persona, Avatar, and Voice Packs — the governed assets whose release lifecycle and voice policy this page gates.
- Iris Memory and Identity — the memory substrate whose writes a crisis frame suspends.
- Psyche Real-Time Runtime — the live session runtime that carries crisis-frame continuity.
- Isis Generation Control — the generation control plane that consumes tone-band audacity caps and generation tiers.
- Sophia Grounding — the grounding gate the unsafe-claim and explainer policies sit beside.
- Review, Compliance, and Trust & Safety — the operator queues and crisis-incident workflow Lilith feeds.
- Living Scenes — Concept and Customer Promise and Scene Safety, Determinism, Provenance, and Cue Privacy — the continuous-video tone class and scene crisis frame.
- Lilith — Contemplative Policy Substrate — the architectural deep-dive.
- ../features.md — the feature hub. Backlog: §1.2 (Incident),
§12.9 (tone bands), and §12.12 (crisis recovery) in
../TODOS.md; dependency ordering in../DEPENDENCIES.md.