Context. surface customer · domain lilith · route /lilith-studio/personas · auth signed-in + role:v1_editorial_producer (default) · source apps/oshun/web/src/app/lilith-studio/personas/page.tsx
Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; content re-verified 2026-06-03 against current source 2026-06-28 focused automated Playwright + component walk — route hydration, seeded draft, validation acknowledgement, all identity inputs, genre guardrails, catalog controls, clear/public-figure voice build branches, matched and no-match hand-off runtime states, add/edit/remove hand-off rule rows, publish-ready/blocked/published states, manifest readouts, provenance inspector, shell entry, and mobile no-horizontal-overflow check verified. Evidence: apps/oshun/web/e2e/lilith-saraswati-persona-dossier-smoke.spec.ts; apps/oshun/web/src/app/lilith-studio/personas/SaraswatiPersonaDossierEditor.test.tsx
Purpose#
Publish a complete Saraswati artist persona only when backstory, voice
signature, avatar, genre cell, catalog policy, and operator hand-off rules all
pass validation. Backed by @oshun/tenant-saraswati-stage
(createSaraswatiPersonaDossierEditorState, voice-signature build / review,
operator hand-off enforcement, dossier publish). The page
(apps/oshun/web/src/app/lilith-studio/personas/page.tsx) returns
<SaraswatiPersonaDossierEditor /> directly; the
<ShellLayout active="studio"> wrapper and the editorial scope gate are
supplied by the route's apps/oshun/web/src/app/lilith-studio/layout.tsx.
Entry points#
- Lilith Studio shell (
/lilith-studio) — "Persona dossiers" surface tab → "Open Persona dossiers" link - Direct URL / bookmark — yes (signed-in)
Layout regions#
SaraswatiPersonaDossierEditor
(apps/oshun/web/src/app/lilith-studio/personas/SaraswatiPersonaDossierEditor.tsx):
- Header: eyebrow "Saraswati editorial", title "Persona dossier editor",
lede, two header actions — "Studio shell" →
/lilith-studioand "Validate dossier" button (data-saraswati-persona-validate) - Multi-panel grid:
- Identity panel (
aria-labelledby="persona-identity-title"):- Persona id input (
data-saraswati-persona-id) - Display name input (
data-saraswati-persona-display-name) - Backstory summary textarea (
data-saraswati-persona-backstory) - Sophia citation ids input (comma-separated;
data-saraswati-persona-citations) - Cultural review ref (
data-saraswati-persona-cultural-review) - Rights review ref (
data-saraswati-persona-rights-review) - Voice signature ref (
data-saraswati-persona-voice-signature) - Avatar ref (
data-saraswati-persona-avatar-ref) - Genre cell select (
data-saraswati-persona-genre-cell); options fromSARASWATI_PERSONA_GENRE_CELLS - Genre guardrail list (
aria-label="Genre guardrails") — read-only percell.id
- Persona id input (
- Catalog policy panel:
- Release cadence select (
data-saraswati-persona-release-cadence) — options: Single monthly / EP quarterly / Album at GA - Track count input (
data-saraswati-persona-track-count) - Remix rights mode select (
data-saraswati-persona-remix-rights) — Editorial only / Licensed community remix / Blocked remix - Distribution mode select (
data-saraswati-persona-distribution-mode) — In-world only / In-world plus DSP / Concert exclusive window - Provenance required toggle (
data-saraswati-persona-provenance-required) - Explicit content toggle (
data-saraswati-persona-explicit-content)
- Release cadence select (
- Voice signature build panel — voice probe controls and receipt textarea
(
aria-label="Voice signature build receipt"); public-figure match probe option vs "clear" build - Voice ownership clauses list
(
aria-label="Voice ownership contract clauses") - Operator hand-off rules panel:
- "Add rule" button (
data-saraswati-persona-handoff-add) - Runtime prompt input (
data-saraswati-persona-handoff-runtime-prompt); default copy "A fan asks for medical advice in persona voice before the listening room opens." - Runtime decision result block
(
data-saraswati-persona-handoff-runtime-result) - Rule grid (
data-saraswati-persona-handoff-rule-list); per rule: Remove icon (aria-label="Remove <label>"), Rule ID, Label, Trigger, Scope select, Severity select (Routine / Priority / Urgent), SLA input, Queue input
- "Add rule" button (
- Validation panel: empty state (
data-saraswati-persona-no-issues) or issue list (data-saraswati-persona-issue-list) - Publish controls:
- "Publish dossier" button (
data-saraswati-persona-publish) - Publish receipt textarea (
data-saraswati-persona-publish-manifest,aria-label="Persona dossier publish receipt")
- "Publish dossier" button (
- Identity panel (
LilithProvenanceInspector— surface IDpersona-dossier-editor
States#
- Hydrated route — client component reaches
data-hydrated="true"after mount in the real browser - Seeded draft —
SARASWATI_PERSONA_DOSSIER_SEEDpopulates fields including persona idpersona-saraswati-anaya-veil - Validation pending —
validationAcknowledged === false - Validation acknowledged — pressing "Validate dossier" sets the flag (consumed by other UI sections)
- Voice build clear —
voiceProbeMode='clear' - Voice build public-figure match —
voiceProbeMode='public-figure-match'; probe rejection appears - Hand-off rule matched —
data-handoff-runtime-statereflects match;primaryMatch.scopepopulatesdata-handoff-runtime-scope - Hand-off rule not matched —
data-handoff-runtime-state="no-match";data-handoff-runtime-scope="none" - Publish blocked —
editorStatereports issues; publish button disabled - Publish ready — all required fields valid
- Published —
publishReceiptset; manifest textarea populated - Offline — client-only; works offline
Interactions#
Header#
- "Studio shell" link — href
/lilith-studio - "Validate dossier" button (
data-saraswati-persona-validate)- Function:
setValidationAcknowledged(true)
- Function:
Identity panel#
- Persona id input
- Display name input
- Backstory summary textarea
- Sophia citation ids input (comma-separated → list)
- Cultural review ref input
- Rights review ref input
- Voice signature ref input
- Avatar ref input
- Genre cell select
- Genre guardrail list — read-only per genre cell
Catalog policy panel#
- Release cadence select
- Track count input
- Remix rights mode select
- Distribution mode select
- Provenance required toggle
- Explicit content toggle
Voice signature build#
- Voice probe mode toggle (Clear / Public-figure match)
- Build voice signature button — submits
voiceBuildInputtobuildSaraswatiVoiceSignature - Voice receipt textarea (read-only,
aria-label="Voice signature build receipt")
Operator hand-off rules#
- "Add rule" button (
data-saraswati-persona-handoff-add) - Runtime prompt input (textarea / input)
- Runtime decision result block
- Each rule row:
- Remove icon button (
aria-label="Remove <label>") - Rule ID, Label, Trigger, Scope, Severity, SLA, Queue editable fields
- Remove icon button (
Validation#
- No-issues empty state (
data-saraswati-persona-no-issues) - Issue list (
data-saraswati-persona-issue-list) — per-issue detail rows
Publish#
- "Publish dossier" button (
data-saraswati-persona-publish, release button)- Function:
publishSaraswatiPersonaDossier(...) - Disabled when validation reports issues
- Function:
- Publish receipt textarea (read-only)
Provenance inspector#
-
LilithProvenanceInspector— read its own walkthrough
Data & contracts#
- Reads / writes: in-process via
@oshun/tenant-saraswati-stage:SARASWATI_PERSONA_DOSSIER_REQUIRED_FIELDS,SARASWATI_PERSONA_DOSSIER_SEED,SARASWATI_PERSONA_GENRE_CELLS,SARASWATI_VOICE_RIGHTS_OWNERSHIP_SUMMARY,SARASWATI_VOICE_SIGNATURE_BUILD_SEED,SARASWATI_VOICE_SIGNATURE_PUBLIC_FIGURE_MATCH_PROBE, plus the family of*Saraswati*mutators/getters - Realtime: none
- Caching: client bundle
- Auth/role check: inherited from
lilith-studio/layout.tsx, requiringadmin:*orstudio:editorial - Validation rules:
- Persona id must match
persona-saraswati-* - Display name needs at least two words
- Backstory needs at least 35 words, at least two
sophia:saraswati:*citations, and cultural/rights review refs - Voice signature must point to
voice-sig:consent-ledger:*; avatar must point toavatar:saraswati:* - Catalog policy requires a valid cadence, remix-rights mode, distribution mode, at least 12 debut tracks, and required provenance bundle
- At least two operator hand-off rules are required; each rule needs valid
handoff-*id, two-word label, specific trigger, supported scope/severity,lilith-*queue, and 1-60 minute SLA
- Persona id must match
Cross-references#
- Studio shell:
lilith-studio.md - Concert pipeline (consumes the persona):
lilith-studio-concerts.md - Sibling editors:
lilith-studio-asana.md,lilith-studio-avatar-costume.md,lilith-studio-music.md,lilith-studio-scenes.md,lilith-studio-provenance.md - Component source:
apps/oshun/web/src/app/lilith-studio/personas/SaraswatiPersonaDossierEditor.tsx - E2E/unit evidence:
apps/oshun/web/e2e/lilith-saraswati-persona-dossier-smoke.spec.tsapps/oshun/web/src/app/lilith-studio/personas/SaraswatiPersonaDossierEditor.test.tsx
Open questions / known gaps#
- Document current publish persistence —
publishSaraswatiPersonaDossierreturns an in-process receipt and does not write to a back-end in the current V3 tenant package - Document the full validation rules (which inputs gate publish)
- Verify the
voice-signaturepublic-figure match probe — it rejects impersonation by policy; cross-reference Lilith voice-quality policy (V1/features.md#lilith-persona-policy) - Cold offline behavior for
/lilith-studio/personasremains unproven beyond client-only implementation review