# Journey: Crisis-aware tone policy interception

This journey specifies how distress input must interrupt persona output, expose
plain-language resources, and place the rest of the product inside a reversible
crisis frame. It is the customer-side walk of the
[Crisis-frame cascade](../../V1/ARCHITECTURE.md#crisis-frame-cascade) and the
[Crisis-Aware Behavior](../../V1/features.md#crisis-aware-behavior) policy
section of `V1/features.md`. It is also a walk of the
[Crisis recovery journey](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey)
user-facing path back into the product.

This is a sensitive journey. It describes substrate behavior, never product
messaging language, and never asks a reviewer to invent specific crisis
indicators or therapeutic recommendations. Specific signal taxonomy lives in
`V1/features.md` and is owned by the Lilith policy team.

**Current implementation boundary.** Four shipped seams are distinct and must
not be read as one complete, universal interception path:

1. `/arete/offering` preflights typed intention text through
   `POST /v1/lilith/adapter/safety-assessment` and fails closed before a
   keep/send write.
2. An operator-scoped activation route publishes
   `lilith.crisis_frame.activated`; its worker stores markers for `assistant`,
   `iris`, `lilith-video`, `psyche`, and `tara`.
3. Several BFF handlers consult the bound crisis-frame store before serving
   non-safety work.
4. `/profile/safety` reads the member's markers, then builds its stillness,
   re-entry, and check-in controls in the browser from the recovery library.

The repository does **not** yet prove that typed input on every named surface
activates the durable frame, that recovery decisions clear the server markers,
or that every target telemetry event below is emitted. Unchecked steps are the
remaining policy contract, not claims about the current runtime.

## Personas

- **Long-tenured user who experiences acute distress** — primary persona; has
  Iris memory, declared lineage, ongoing Arete and Tara cadence
- **First-time user surfacing distress on first contact** — no Iris memory; the
  substrate cannot read prior context; the policy must still fire cleanly
- **User the operator has flagged from a separate signal** — an operator
  escalation triggers the frame; the customer-side experience is the same
- **Mobile user on a standalone PWA** — verifies the safety surface renders
  without the URL bar and with safe-area insets
- **User in a tenant with stricter institutional policy** — per
  [`V1/features.md#wiring-versioning-and-evaluation`](../../V1/features.md#wiring-versioning-and-evaluation),
  tenant policy can tighten beyond platform baseline; the frame still fires;
  resources are localized per tenant where applicable

## Pre-conditions

- A signed-in member is required for the member-owned `/profile/safety` record.
  The resource catalog itself is public at `GET /v1/safety/crisis-resources`;
  there is not yet an anonymous customer web safety view.
- The target policy requires Lilith interception on Tara teacher personas,
  contemplative assistants, journal capture, Veritas explainers, Sophia answers,
  Metis tutoring, and support copilot output — per
  [`V1/features.md#wiring-versioning-and-evaluation`](../../V1/features.md#wiring-versioning-and-evaluation)
- The shipped active-input proof is currently `/arete/offering`; the durable
  cross-surface proof starts from the operator activation route.
- A safety-resource set is loadable. The public BFF currently returns its
  globally scoped catalog; tenant/locale selection remains a target requirement
  per
  [`V1/features.md#crisis-aware-behavior`](../../V1/features.md#crisis-aware-behavior)
- Redis and the durable snapshot store must be bound for operator activation to
  project member-visible crisis-frame markers. Without that composition, the
  member endpoint honestly returns an empty set.
- The architecture requires an audit-platform attestation per
  [`V1/ARCHITECTURE.md#crisis-frame-cascade`](../../V1/ARCHITECTURE.md#crisis-frame-cascade)
- There is no `/lilith/crisis` customer-facing route in V1; this journey
  describes substrate behavior across the existing surfaces (assistant, Tara,
  journals, etc.)

## Steps

### 1. User submits input on a Lilith-wired surface

- [x] On `/arete/offering`, the user enters an intention and chooses Save draft
      or Send. `AreteOfferingActions` sends the exact text and region to the
      Lilith safety-assessment route before any offering write.
- [ ] Extend the same preflight guarantee to every target free-text surface:
      assistant chat (see
      [`shell/05-notifications.md`](../shell/05-notifications.md) message center
      / assistant), Arete journal capture
      ([`customer/04-arete/domains-arete-journal.md`](../customer/04-arete/domains-arete-journal.md)),
      Tara session reflection, Metis tutor turn, Veritas explainer prompt,
      Living Scenes prompt input
- [ ] The user submits text expressing distress (the substrate decides
      classification; this walkthrough does not invent specific tokens)
- [ ] The input flows through the per-surface Lilith hook before any persona,
      generation pipeline, or review queue ingests it (per
      [`V1/features.md#lilith-persona-policy`](../../V1/features.md#lilith-persona-policy):
      "wires them into every persona, generation pipeline, and review queue")

### 2. Lilith evaluates the signal

- [x] `POST /v1/lilith/adapter/safety-assessment` evaluates the request through
      the current 13-rule classifier and returns `allow` or a blocking crisis
      disposition with escalation metadata and resources.
- [ ] Every target surface evaluates input against the
      [Crisis-Aware Behavior signal taxonomy](../../V1/features.md#crisis-aware-behavior)
      using its versioned classifier
- [x] An authorized operator can activate a durable frame through
      `POST /v1/admin/safety/crisis-frame/activate`; the route publishes
      `lilith.crisis_frame.activated` with the normalized crisis detection and
      target surfaces.
- [ ] A blocking user-input assessment directly activates that same durable
      frame without a separate operator call. This bridge is not wired today.
- [ ] If the evaluation reaches the crisis threshold (severity × scope per
      [`V1/ARCHITECTURE.md#crisis-frame-cascade`](../../V1/ARCHITECTURE.md#crisis-frame-cascade)),
      the activation carries an explicit expiry/deactivation lifecycle. The
      current event stores activation time and surfaces, not a TTL.
- [ ] If the input is below threshold but adjacent (e.g., distress that doesn't
      meet the crisis signal threshold), the substrate may apply a softer
      [`reflective`](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey)
      tone band, hedge claims, and surface a "we're here" affordance — without
      firing the full frame

### 3. The frame cascades across substrates

The shipped worker projects one marker for each of `assistant`, `iris`,
`lilith-video`, `psyche`, and `tara`. Route handlers including assistant,
reminders, Living Scenes, customer messages, mentor presence, and Telegram
consult the bound store through `isCrisisFrameActiveForUser`. Per the broader
cascade in
[`V1/ARCHITECTURE.md#crisis-frame-cascade`](../../V1/ARCHITECTURE.md#crisis-frame-cascade),
the product contract still requires, in parallel:

- [ ] **Tara**: suspends scheduled rituals and humane recovery prompts; no new
      Tara push, no scheduled invitations
- [ ] **Living Scenes**: locks renders into reduced motion and disables opt-in
      share
- [ ] **Isis**: caps generation audacity, enforces reduced provenance, blocks
      premium personas
- [ ] **Assistant**: switches to a crisis-aware persona that surfaces support
      resources
- [ ] **Iris**: tags active session memory so recall doesn't re-surface charged
      content; suspends new memory writes during the frame per
      [`V1/features.md#iris-memory-and-identity`](../../V1/features.md#iris-memory-and-identity)
      "Crisis-frame suppression"

### 4. The customer-side surface presents the safety response

Per the [Per-signal response](../../V1/features.md#crisis-aware-behavior) and
the
[Crisis recovery journey "Entry"](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey):

- [x] The Arete offering branch replaces the action area with a plain safety
      interruption, exposes 988 support and `/profile/safety`, redacts the
      submitted text, and performs no keep/send write.
- [x] `/profile/safety` exposes a member-owned marker timeline and an actionable
      `tel:988` resource link; opening it emits `lilith_safety_resource_opened`.
- [ ] Every Lilith-wired persona breaks to plain operator voice (no teacher
      voice, no contemplative narration, no avatar render)
- [ ] The surface presents:
  - A clear, non-clinical message in plain operator voice
  - The region-aware safety-resource set for the user's locale + declared frame
    (hotlines, text lines, emergency services as appropriate)
  - A "we're here" affordance — routes to a human-support handoff where the user
    has consented to support contact, or to the asynchronous support inbox
    otherwise
- [ ] Ongoing audio synthesis halts immediately; no ritual continuation; no
      voice / avatar render
- [ ] Telemetry: a crisis-frame entry event is recorded; the event is
      audit-platform visible per
      [`V1/ARCHITECTURE.md#crisis-frame-cascade`](../../V1/ARCHITECTURE.md#crisis-frame-cascade)

### 5. Stillness window

Per the
[Crisis recovery journey "Stillness window"](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey):

`/profile/safety` currently derives this window from the marker's activation
time with `openStillnessWindow` and stores member interaction state in
frame-namespaced localStorage. This is a real recovery UI over a real marker,
but it is not yet a server-authoritative recovery state machine.

- [ ] A configurable minimum interval (default 10 minutes, never less than 3)
      elapses before any non-safety surface re-enables
- [ ] Tara recovery rituals are surfaced as invitations during the window, never
      as scheduled events
- [ ] Living Scenes, Veritas briefings, and Isis generation remain disabled for
      the window
- [ ] Push notifications scheduled to fire during the window are deferred or
      suppressed per [`shell/05-notifications.md`](../shell/05-notifications.md)
      quiet hours pattern

### 6. Re-entry prompt at the end of the window

- [ ] At the end of the stillness window, the product asks once whether the user
      wants to continue
- [ ] If the user declines, the surface routes to an idle-safe surface (a chosen
      calm Tara ritual or the device home screen); the product does NOT re-ask
      until a fresh session
- [ ] If the user accepts, the user lands on a re-entry home with conservative
      defaults: `contemplative-strict` band, no scheduled invitations, no
      recommendations from sensitive categories
- [ ] The user can manually re-enable categories from profile settings

### 7. Visible audit

Per the
[Visible audit](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey)
rule:

- [ ] A "what happened" surface in profile/safety shows the user the
      audit-platform-visible record of the frame (entry time, exit time,
      suppressed surfaces, operator actions if any)
- [ ] The user owns the record of what occurred — no operator-only hidden log
- [ ] Per
      [`V1/features.md#iris-memory-and-identity`](../../V1/features.md#iris-memory-and-identity),
      the user can elect (consent-gated) to keep a memory of the event;
      otherwise the suppression remains

### 8. Follow-up cadence

Per the
[Follow-up cadence](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey)
rule:

- [ ] 24h and 7d soft check-ins (default opt-in; user can disable)
- [ ] Check-ins flow via the assistant only — NEVER via push or notification
- [ ] Each check-in offers the same support-resource set and the same idle-safe
      surface

### 9. Re-frame protection

- [ ] If a new crisis indicator fires during the stillness window or within 24h,
      the frame EXTENDS rather than re-fires — protects against thrash and
      re-traumatization per the
      [Re-frame protection](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey)
      rule

### 10. Operator-side correlate (out of customer scope)

For reference (not a customer step, but the customer experience depends on it
firing): every crisis frame generates an `Incident` record per
[`V1/features.md#crisis-aware-behavior`](../../V1/features.md#crisis-aware-behavior)
and a `Persona Lifecycle Event`-style attestation; operator review is required
within tenant-policy time-box. The customer-side journey assumes the
operator-side path is healthy.

## Post-conditions

- A blocking Arete assessment prevents the offering write and leaves the safety
  handoff visible.
- Operator activation yields member-owned durable markers for all five declared
  crisis-frame surfaces when Redis and snapshot persistence are bound.
- `GET /v1/safety/crisis-frames/mine` returns only the authenticated member's
  markers with `cache-control: no-store`; `/profile/safety` renders those
  markers or an honest empty/unavailable state.
- The member can operate the browser-local stillness, re-entry, check-in, and
  resource UI. These choices do not currently deactivate or delete the BFF
  markers.
- The verified customer telemetry event is `lilith_safety_resource_opened`. The
  larger activation/surface/re-entry/ follow-up telemetry sequence remains a
  release requirement until source and automation prove each event.

## Failure modes to verify

### False positive (system intervenes when it shouldn't)

- [ ] **Benign-but-adjacent input** — the classifier mis-classifies a
      contemplative phrase or a journal entry quoting a teacher's lineage text;
      the safety surface fires unnecessarily. The user MUST have a low-friction
      "this isn't a crisis for me" affordance that:
  - Records feedback for the evaluation suite per
    [`V1/features.md#wiring-versioning-and-evaluation`](../../V1/features.md#wiring-versioning-and-evaluation)
  - Does NOT require the user to re-explain
  - Restores the prior surface state if appropriate; the audit record notes the
    user-initiated dismissal
- [ ] **Cross-lineage misreading** — distress markers in one tradition are
      benign in another (e.g., devotional surrender language); per the
      [Cultural and lineage sensitivity policy](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey),
      the classifier must respect declared lineage; verify the eval suite
      includes lineage-respect false-positive cases

### Missed true (system doesn't intervene when it should)

- [ ] **Below-threshold-but-real distress** — input reads as ambient but the
      user is in actual distress; the substrate may apply the softer
      `reflective` tone band; the user MUST still have a discoverable "we're
      here" affordance on every Lilith-wired surface (not just on the safety
      surface). The journey verifies this affordance exists on Tara reflection,
      Arete journal, and assistant chat
- [ ] **Operator-flagged session** — when the signal source is operator
      escalation rather than user input, the frame must fire as cleanly as a
      user-input trigger; verify the customer experience is identical
- [ ] **Voice-input distress** — per
      [`V1/features.md#voice-quality-policy`](../../V1/features.md#voice-quality-policy),
      naturalness floor and silence-density floor apply; verify the classifier
      reads voice input as well as text and the surface degrades to text +
      recorded-voice library + apology if needed

### Recovery (user recovers gracefully from intervention)

- [ ] **User dismisses the safety surface** — the journey continues with the
      stillness window enforced; even on dismiss, the `contemplative-strict`
      band holds, no scheduled invitations fire, and no premium personas are
      available until the frame clears
- [ ] **User accepts the re-entry prompt** — lands on the re-entry home with
      conservative defaults; the audit record carries the timing; Iris memory
      writes resume per the user's consent state
- [ ] **User declines the re-entry prompt** — routes to a chosen calm Tara
      ritual or the device home; the product does NOT re-ask until a fresh
      session
- [ ] **User explicitly opts out of follow-up check-ins** — per the
      [Follow-up cadence](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey)
      "user can disable" rule, the 24h and 7d check-ins are suppressed
- [ ] **User wants to keep a memory of the event** — consent-gated memory of the
      event is recorded per
      [`V1/features.md#iris-memory-and-identity`](../../V1/features.md#iris-memory-and-identity);
      otherwise the suppression remains
- [ ] **Tenant-specific safety resources missing for the user's locale** — the
      default frame copy must have been reviewed by a regional safety advisor
      before launch in that locale per the
      [Localization](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey)
      rule; missing resources fall back to a globally-vetted default set and
      trigger an operator alert
- [ ] **Anonymous user encounters distress** — the safety surface and
      region-aware resources must still render (PUBLIC_PATHS includes the paths
      the user can reach); per
      [`shell/04-auth-session.md`](../shell/04-auth-session.md), the sign-in
      gate must NOT block the safety surface
- [ ] **Crisis frame extends rather than re-fires** — a new indicator within the
      stillness window or 24h must extend, not re-fire, per
      [Re-frame protection](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey);
      verify the telemetry shows a single `activated` event, not multiple

### Other failure modes

- [ ] **Override attempts** — neither user prompt nor admin copilot can override
      the crisis policy per
      [`V1/features.md#crisis-aware-behavior`](../../V1/features.md#crisis-aware-behavior)
      "No-bypass guarantees"; verify by attempting (in a test environment) to
      instruct the assistant to ignore the frame
- [ ] **Voice abuse coincident with distress** — per
      [`V1/features.md#voice-abuse-policy`](../../V1/features.md#voice-abuse-policy),
      an above-threshold abuse score halts generation independently; verify the
      two policies compose without conflict (the more restrictive applies)
- [ ] **Crisis-frame deactivation** — the frame is reversible; verify the
      deactivation event is audited and the user-facing record reflects both
      entry and exit times; verify Tara invitations resume per cadence and Iris
      memory writes resume per user consent
- [ ] **Performance budget for the safety surface** — the surface must render
      even when the network is degraded; the resource set must be cached on the
      SW; verify per [`shell/03-pwa-behavior.md`](../shell/03-pwa-behavior.md)

## E2E coverage

- Backed by
  [`apps/oshun/web/e2e/profile-safety-crisis-recovery.spec.ts`](../../apps/oshun/web/e2e/profile-safety-crisis-recovery.spec.ts)
  — exercises the `profile/safety` surface directly against real dev infra:
  signed-in member starts with an empty `GET /v1/safety/crisis-frames/mine`;
  operator activation through `POST /v1/admin/safety/crisis-frame/activate`
  projects the durable frame; the browser then renders `/profile/safety` from
  the live member readback with no route interception. The spec asserts that the
  four recovery-model rows (`teaching`, `invitation`, `scheduled-generation`,
  `studio`) report suspended together during the stillness window and lift
  together in the browser model after it. This assertion does not clear the
  durable BFF markers. The spec also covers the re-entry prompt **accept** flow
  (landing on `contemplative-strict`); 24h check-in delivery and dismissal;
  opt-out of the 7d follow-up; and the re-entry **decline** failure mode (routed
  to an idle-safe surface via `data-profile-safety-reentry-status="idle"`) with
  the visible "what happened" audit card (`data-profile-safety-what-happened`)
  and the 988 crisis resource (`data-profile-safety-resource="us-988"`) staying
  available. The same real-BFF profile-safety flow now verifies that the 988
  resource is an actionable `tel:988` link and that opening it emits
  `lilith_safety_resource_opened` with the active frame ID. It also verifies the
  live cross-surface `frames[]` timeline across assistant, Iris, Lilith video,
  Psyche, and Tara markers with an expandable assistant-frame metadata row, plus
  the no-frame empty state and anonymous redirect-before-render branch.
- Backed by
  [`apps/oshun/web/e2e/crisis-safety-policy-bff.spec.ts`](../../apps/oshun/web/e2e/crisis-safety-policy-bff.spec.ts)
  — real HTTP integration against the live BFF safety substrate (steps 2 + 4):
  `POST /v1/lilith/adapter/safety-assessment` runs the real 13-rule crisis
  classifier (a distress message classifies as a crisis → `block` disposition +
  escalation + `suicide-ideation`/`self_harm` crisisTypes + the 988 Suicide &
  Crisis Lifeline / 741741 Crisis Text Line resources; a benign self-care
  message → `allow` with no crisis types; missing `userMessage` → 400;
  wrong-domain token → 403; no bearer → 401). The **public**
  `GET /v1/safety/crisis-resources` returns the 988 + 741741 resource set with
  **no Authorization header**, proving the no-sign-in-gate-blocks-resources
  guarantee at the BFF layer; `POST /v1/safety/resources/suggest` exercises the
  real relevance scorer (401 no bearer, 400 invalid observations, 200 with a
  scored direct safety suggestion). The member-owned crisis-frame audit API is
  also proved through the live BFF: unauthenticated
  `GET /v1/safety/crisis-frames/mine` returns 401, an authenticated member with
  no active frame receives an uncached (`cache-control: no-store`) honest empty
  record, customer-scoped activation is rejected with `admin_scope_missing`, and
  an authorized malformed activation is rejected with `invalid_request`. The
  same spec now drives the substrate cascade through real dev infrastructure: an
  operator-scoped `POST /v1/admin/safety/crisis-frame/activate` publishes the
  activation to the Redis-backed worker, the worker persists one crisis-frame
  marker per required contemplative surface (`assistant`, `iris`,
  `lilith-video`, `psyche`, `tara`), and the affected member reads those durable
  markers back from `GET /v1/safety/crisis-frames/mine` while an unrelated
  member receives an empty set.
- Backed by
  [`apps/oshun/web/e2e/arete-offering-actions.spec.ts`](../../apps/oshun/web/e2e/arete-offering-actions.spec.ts)
  — real browser coverage for the shipped active-surface preflight branch on
  `/arete/offering`: the user types a blocking intention into the offering
  textarea, clicks Save draft, and the browser sends the live
  `POST /v1/lilith/adapter/safety-assessment?role=safety` request with the
  auth-context bearer and exact `{ userMessage, region: 'US' }` payload. The
  same browser state then swaps the action region into the plain safety
  interruption, renders 988 resources plus the `/profile/safety` handoff, and
  proves no `/v1/arete/offerings/keep` write occurs.
- **Coverage depth**: partial — see [`coverage.md`](./coverage.md).
- **Uncovered**:
  - A shipped **browser active-surface preflight** is now proven for Arete, but
    the full durable cross-substrate cascade is still not triggered from real
    active-surface user input. Coverage proves operator activation → Redis
    worker → durable per-surface markers → browser `/profile/safety` member
    read-back, and Arete typed distress → direct Lilith BFF preflight → in-place
    safety interruption. It does not yet prove typed distress creates the same
    durable crisis-frame markers without operator activation, nor that
    assistant/Tara/Metis surfaces swap in place from their own text input.
  - False-positive dismissal affordance ("this isn't a crisis for me") is not
    asserted (the affordance is feature-absent in the web surface).
  - The **anonymous web** safety surface is not exercised — `/profile/safety` is
    auth-gated and redirects before render; the public-resource guarantee is
    verified at the BFF (`GET /v1/safety/crisis-resources`, no auth) but not on
    a customer-facing public web view.
  - Re-frame protection (extension rather than re-fire on a second indicator
    within 24h) remains library-only and is not e2e-surfaced.

## Per-view files touched by this journey

The journey crosses every Lilith-wired customer surface. Most relevant:

- [`customer/04-arete/domains-arete-journal.md`](../customer/04-arete/domains-arete-journal.md)
  — journal capture
- [`customer/04-arete/arete-recovery.md`](../customer/04-arete/arete-recovery.md)
  — recovery surface that is suspended in favor of the safety surface
- [`customer/03-tara/tara.md`](../customer/03-tara/tara.md) — Tara scheduling
  suspended in the cascade
- [`customer/05-veritas/veritas.md`](../customer/05-veritas/veritas.md) —
  Veritas briefings suspended in the stillness window
- [`customer/10-lilith/lilith.md`](../customer/10-lilith/lilith.md) — the Lilith
  design-system catalog (note: this is the public showcase, not the crisis
  surface; there is no `/lilith/crisis` route in V1)
- [`shell/04-auth-session.md`](../shell/04-auth-session.md) — sign-in gate must
  not block the safety surface
- [`shell/05-notifications.md`](../shell/05-notifications.md) — push suppression
  in the stillness window; follow-up check-ins via assistant only (NEVER push)
- [`shell/03-pwa-behavior.md`](../shell/03-pwa-behavior.md) — safety surface
  available offline / on degraded network

## Cross-references

- Feature spec:
  [`V1/features.md#lilith-persona-policy`](../../V1/features.md#lilith-persona-policy),
  [`V1/features.md#crisis-aware-behavior`](../../V1/features.md#crisis-aware-behavior),
  [`V1/features.md#voice-quality-policy`](../../V1/features.md#voice-quality-policy),
  [`V1/features.md#voice-abuse-policy`](../../V1/features.md#voice-abuse-policy),
  [`V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey`](../../V1/features.md#persona-taxonomy-tone-band-catalog-and-crisis-recovery-journey),
  [`V1/features.md#iris-memory-and-identity`](../../V1/features.md#iris-memory-and-identity)
- Architecture:
  [`V1/ARCHITECTURE.md#crisis-frame-cascade`](../../V1/ARCHITECTURE.md#crisis-frame-cascade)
  — the substrate-level cascade
- Related journeys:
  - [`arete-streak-recovery.md`](./arete-streak-recovery.md) — humane recovery
    is suspended by the crisis frame; the recovery is NOT a substitute for the
    safety surface
  - [`tara-to-nisaba-handoff.md`](./tara-to-nisaba-handoff.md) — Tara
    cross-domain bridges suspend during the frame
  - [`nyx-to-tara-bridge.md`](./nyx-to-tara-bridge.md) — Tara perspective
    recommendations suspend during the frame
  - [`veritas-to-nisaba-deeper.md`](./veritas-to-nisaba-deeper.md) — citation
    depth surfacing softens during the stillness window

## Open questions / known gaps

- [x] No `/lilith/crisis` customer-facing route exists in V1 — confirmed by
      design. The crisis-aware substrate lives in
      `libs/oshun/persona-policy-lilith/src/crisis-recovery/` (check-ins,
      incident-record, locales, reentry-flow, reframe-protection,
      stillness-window) and is wired through each Lilith-using surface
      individually. The user-facing audit lives at `/profile/safety` (per
      `customer/09-account/profile-safety.md`). A dedicated `/lilith/crisis`
      route would conflict with the cascade model — the safety surface mounts
      in-place on the active surface.
- [ ] Snapshot the customer-side "this isn't a crisis for me" affordance shape
      (button label, placement, telemetry event) so the false-positive feedback
      loop has a concrete UI.
- [ ] Confirm the offline-availability of the region-aware safety-resource set
      on first cold-start (the SW must precache the default-locale resource
      set).
- [ ] Confirm the assistant follow-up check-ins at 24h and 7d use the assistant
      inbox channel (per
      [`customer/02-home-discovery/home.md`](../customer/02-home-discovery/home.md)
      Companion bridge rail) rather than push.
- [ ] Verify the tenant-policy-tighten path: institutional tenants can tighten
      unsafe-claim thresholds and crisis thresholds — document where the
      tenant-policy review surface lives in operator tooling.
- [x] Pin the visible audit copy at profile/safety so a reviewer can confirm the
      user actually owns the record of what occurred. The browser spec asserts
      `data-profile-safety-what-happened` includes the crisis label and redacted
      excerpt, and the BFF spec asserts the backing
      `/v1/safety/crisis-frames/mine` record is authenticated, uncached, and
      member-owned.
- [ ] Add the classifier-to-activation bridge so typed distress on each named
      active surface creates the same durable markers currently created by the
      operator route.
- [ ] Add and verify a server-side close/extend/deactivate lifecycle. The
      current recovery UI advances local state, while the snapshot store retains
      active markers and exposes no deactivation route.
- [ ] Move re-entry decisions and check-in preferences from frame-namespaced
      localStorage into member-owned server state before calling recovery
      cross-device or audit-complete.
