V1 Web PWA · Surface walkthrough

Lilith Studio · Costume slot authoring

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked
8sections3 minread

On this page

Context. surface customer · domain lilith · route /lilith-studio/avatar-costume · auth signed-in + role:v1_editorial_producer (default) · source apps/oshun/web/src/app/lilith-studio/avatar-costume/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

Purpose#

Configure a body-safe avatar costume slot — pick a garment + palette + safety variant for a costume slot, generate a preview artifact, round-trip through V1 editorial approval, and release a versioned costume edition with provenance attached. The page (apps/oshun/web/src/app/lilith-studio/avatar-costume/page.tsx) returns <AvatarCostumeAuthoring /> 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) — "Avatar and costume" surface tab → "Open Avatar and costume" link
  • Direct URL / bookmark — yes (signed-in)

Layout regions#

AvatarCostumeAuthoring (apps/oshun/web/src/app/lilith-studio/avatar-costume/AvatarCostumeAuthoring.tsx):

  • Header: eyebrow "Lilith Studio / Avatar costume", title "Costume slot authoring", lede, two header actions — "Lilith shell" → /lilith-studio, "V1 asset library" → /studio/yemaya/asset-library
  • Three-panel grid:
    • Slot configuration panel (aria-label="Costume slot configuration"):
      • Costume slot <select> (data-lilith-costume-slot-select) — four options: Torso wrap, Lower drape, Headpiece, Hand prop
      • Garment <select> (data-lilith-costume-garment-select) — four options gated by slot: Tara practice shawl, Lotus walking sash, Moon crown, Practice mala
      • Palette <select> (data-lilith-costume-palette-select) — three options: Moss and gold, Lotus and silver, Night rose
      • Safety variant <select> (data-lilith-costume-safety-select) — three options: Body-safe fit, No face occlusion, Low-motion cloth
    • Preview panel (aria-label="Avatar costume preview"):
      • Avatar silhouette canvas (data-lilith-costume-preview-canvas) with head/body/slot sprites posed by slotId
      • Preview meta strip — garment label, palette label, safety label
      • Preview evidence: kicker "Preview artifact", preview:<slot>: <garment>:<palette> strong, provenance ID
    • Round trip controls panel (aria-label="Round trip controls"):
      • Stage list (data-lilith-costume-round-trip-list): three StageItems — Preview, Editorial, Release (active / done indicators)
      • Actions: "Generate preview" (data-lilith-costume-generate-preview, primary, only when roundTrip.canPreview), "Send for editorial review" (data-lilith-costume-submit-editorial), "Approve editorial" (data-lilith-costume-approve-editorial), "Release costume slot" (data-lilith-costume-release, release button)
  • Release evidence section (aria-label="Release evidence"):
    • Evidence grid: Palette (label · swatch), Policy tag (the safety variant's policyTag), Release status
    • Release manifest textarea (read-only, data-lilith-costume-release-manifest)
  • LilithProvenanceInspector — surface ID avatar-costume-authoring, asset list combines garments + palettes + safety variants

States#

  • Loading — client component; data-hydrated="false" until mount
  • Default draft — slot torso-wrap, garment tara-shawl, palette moss-gold, safety body-safe, stage draft
  • Stage progressiondraft → preview → editorial → approved → released (each button unlocks only at the prior stage)
  • Slot changedchangeSlot resets garment to the first matching slot and returns to draft
  • Garment / palette / safety changed — resets to draft
  • Releaseddata-release-edition-id="release:<slot>:<garment>"
  • Offline — client-only; no network; works offline

Interactions#

  • "Lilith shell" link — href /lilith-studio
  • "V1 asset library" link — href /studio/yemaya/asset-library

Slot configuration selects#

  • Costume slot select — sets slotId; calls changeSlot which also resets garment
  • Garment select — disabled options for non-matching slots; sets garment; resets draft
  • Palette select — sets palette; resets draft
  • Safety variant select — sets safety; resets draft

Round-trip buttons#

  • "Generate preview" button (primary)
    • Function: setStage('preview')
    • Disabled when stage !== 'draft'
  • "Send for editorial review" button
    • Function: setStage('editorial')
    • Disabled when stage !== 'preview'
  • "Approve editorial" button
    • Function: setStage('approved')
    • Disabled when stage !== 'editorial'
  • "Release costume slot" button (release button)
    • Function: setStage('released')
    • Disabled when stage !== 'approved'

Release evidence#

  • Release manifest textarea (read-only, aria-label="Avatar costume release manifest")

Provenance inspector#

  • LilithProvenanceInspector — read its own walkthrough

Data & contracts#

  • Reads: in-file constants AVATAR_COSTUME_SLOTS, AVATAR_COSTUME_GARMENTS, AVATAR_COSTUME_PALETTES, AVATAR_COSTUME_SAFETY_VARIANTS, AVATAR_COSTUME_PROVENANCE_ASSETS
  • Writes: client state only (no network in code)
  • Realtime: none
  • Caching: client bundle
  • Auth/role check: middleware enforces signed-in

Cross-references#

Open questions / known gaps#

  • Confirm whether release IDs persist to V1 release edition or stay in client state
  • Verify the body-persona safety policy contract — the policyTag strings (persona.body.safe-fit etc.) reference Lilith policy; cross- check with V1/features.md#lilith-persona-policy
  • Confirm whether the avatar silhouette previews actual garment art or is only a stub silhouette