library.mdlilith.mdatelier-image.mdatelier.md03-pwa-behavior.mdJourney flow#
Generated from the authored steps below — click a node to jump to that section.
A signed-in customer opens The Atelier index, walks into the Camera Obscura
(image room), writes a prompt, casts twelve specimens, picks one, saves the
plate to their notebook, and confirms it lands in /library with the room's
provenance intact. Exercises the V1 Atelier rooms as a slow, line-first,
provenance-shown studio surface for the consumer — separate from Yemaya Studio's
authoring tier and from the Living Scene card.
Personas#
- Contemplative customer — primary actor; treats the Atelier as a slow artisan workshop ("a small workshop attached to the reading desk"); reaches it via the Lilith index, the Atelier index card, or a saved link
- Returning customer with a previous kept plate — verifies that the saved artifact persists in the library and resumes at Camera Obscura; restoring a plate-specific prompt, seed, and style remains an explicit gap
- Customer with a Tara contemplative-arc workspace open — verifies that the Atelier composition surface respects the tone band and that the Provenance stripe shows the right Sophia source bindings
- AAA-tier customer — for whom the AAA Score Editor lives in Yemaya Studio, not the Atelier; this journey deliberately walks the contemplative-tier surface and notes the AAA hand-off as a fall-through
Pre-conditions#
- Customer signed in
/atelierand/atelier/imageare reachable (both auth-gated by middleware); the Lilith design system mounts the Atelier roomsgetAtelierIndex()andgetAtelierImage()return populated fixture data;/v1/atelier/castis a real fail-closed provider seam, while a dedicated/atelier/plates/*persistence API is not shipped- Library state is hydrated for the customer and synchronizes through the library client-state seam
- House rules govern every generative surface per the Atelier index: "Only from a line.", "Provenance shown.", "Slow by default."
Steps#
1. Open the Atelier index#
- Customer navigates to
/atelier(via the Lilith index section VIII card 41, the customer navLCustomerNav active="explore"shell, or a direct URL) - Page server-renders
apps/oshun/web/src/app/atelier/page.tsxwhich awaitsgetAtelierIndex()fromapps/oshun/web/src/lib/lilith-data/atelier-depth.tsand renders<AtelierIndex data> - Masthead reads "The atelier · est. 2026" with the kicker "Five rooms of making" and the title "The atelier."
- Five room cards render in an auto-fit room shelf: Camera Obscura, Foundry of Voices, Cinematheque, Forms, Stage of Motion
- Three house rules render below the rooms
- Verify:
customer/11-atelier/atelier.mdlayout regions, States. 2026-06-25 row-cell pass asserts the index root count attributes, all five room-card number/name/meta/engine/href cells, and all three house-rule title/description cells.
2. Walk into Camera Obscura#
- Customer taps the "X · Camera Obscura · image" card → navigates to
/atelier/image - Page server-renders
apps/oshun/web/src/app/atelier/image/page.tsxwhich awaitsgetAtelierImage()and renders<AtelierImage data> - Plate head reads "An image, drawn from a line." with right-aligned chips "Specimen 047", "Saved to notebook", "Plate finalised" (accent)
- Left rail shows the five-step
LAStepRailwithcurrent=3: A line, written / Reference, gathered / Twelve specimens / Plate kept · refined / Final · saved to notebook - Center column shows the prompt textarea seeded with "A monk, seated on a
stone bench, lit only by a high north window…", chips (Aspect 4:5, Plate
cream, Steps 38, Seed
0x4f2a · locked, Re-cast accent), and the 4×3 contact sheet of 12 selectable specimen buttons withp.07markedkept. - Right column shows Plate detail (
p.07), field rows (Engine / Aspect / Steps / Guidance / Seed / Style / Sources), a separator, thenProvenance · 3 sourceslisting the fixture provenance — currently Vermeer · light study, Hammershøi · interiors, Lilith · plate library - Verify:
customer/11-atelier/atelier-image.mdlayout, three-column body, Provenance lane. 2026-06-25 row-cell pass asserts the route source/specimen counts, plate-head chips, step-rail states, prompt chips, contact-sheet specimen states, selected plate field rows, and provenance source/kind cells.
3. Write the line (prompt-only entry)#
- Customer edits the prompt copy in
data-atelier-prompt-input; the browser-entered prompt is carried into Cast / Refine payloads. - House rule "Only from a line." enforces the prompt-only entry — no reference image input on this surface (Reference, gathered is its own step in the rail but the demo flow keeps the prompt as the single-source-of-truth)
- Customer adjusts the aspect chip and the style chip; the seed chip shows
lockedso subsequent casts vary the prompt against a stable seed (per the on-screen affordance "Lock seed · vary prompt"). The browser controls now update the prompt chips, plate detail fields, compare summary, and Cast/Refine payloads (atelier-image-to-library+atelier-plate-actions, 2026-06-26).
4. Cast twelve specimens#
- Customer taps "Cast twelve more" through
AtelierPlateActions mode="cast"; this POSTs/v1/atelier/cast. In local real-dev infra without Stability credentials, the seam fails closed with typed provider-not-configured state rather than fabricating a successful cast. The request body includes the edited prompt, selected specimen id, selected aspect, selected style, seed-lock state, andintent: cast. - The contact-sheet grid populates with 12 selectable specimen tiles; each contains a procedural SVG illustration.
- House rule "Slow by default." means the cast is deliberate — there is no auto-streaming spinner, no rapid-fire chrome
- As specimens settle, the customer reviews the grid
5. Pick the plate#
- Customer taps a specimen; the draft tile transitions to
data-atelier-specimen-status="selected"and exposesdata-atelier-specimen-selected="true". - The right column's Plate detail pane updates with the picked tile's plate
id (
Plate · p.03in the Playwright path) and the sameLFieldrows (Engine, Aspect 4:5, Steps 38, Guidance 6.4, Seed0x4f2a · locked, Style "Cormorant warmth", Sources "3 · cited") - Step rail advances to step 4 "Plate kept · refined" when the customer
selects a specimen (
atelier-image-to-library, 2026-06-26). - Provenance list is enumerated under the picked plate so the customer sees exactly which source images and which Lilith plate-library entries informed the cast — honoring house rule "Provenance shown."
6. Refine (optional)#
- Customer can tap "Refine · vary slightly"
(
AtelierPlateActions mode="refine") to nudge the picked plate; it POSTs/v1/atelier/castwithintent: refine, the edited prompt, selected specimen id, aspect, style, and seed-lock state. In local real-dev infra without Stability credentials, it fails closed with typed provider-not-configured state. - Customer can also tap "Lock seed · vary prompt" or "Compare side-by-side";
seed-lock toggles the chip/field/payload state and Compare opens a
kept-vs-active side-by-side panel (
atelier-image-to-library, 2026-06-26). - When the customer is satisfied with the kept plate they advance to step 7
7. Save plate to notebook#
- Customer taps "Save plate to notebook" through
AtelierPlateActions mode="save" - House rule "Slow by default." means the save is intentional, not auto-flushed — the customer chooses when to keep
- Save flow writes to the library store via
saveOshunWebLibraryItemwith a newWebLibrarySavedItemcarrying:kind: 'generated-artifact'domain: 'nisaba'(the current non-domain library fallback used by the save helper)resumePath: '/atelier/image'so the customer can return to Camera Obscura- kept-plate title, summary, format label, context, and resume action
- Step rail advances to step 5 "Final · saved to notebook" after the
explicit save action (
atelier-plate-actions, 2026-06-26). - Save result: "Saved to your library — find it under kept offerings."
- Telemetry:
atelier_plate_savedfires after the accepted save with room idcamera-obscura, prompt hash, seed0x4f2a, seed-lock state, and source-set size.
8. Confirm the plate landed in the library#
- Customer navigates to
/library?kind=generated-artifact(via the shellLibrarytab, theWEB_SHELL_ROUTE_PATHS.libraryroute) -
LibraryDashboardmounts; pre-hydration placeholder briefly shows; once hydrated the saved-items list includes the new plate row - Library kind filter: the kept plate surfaces under
generated-artifact. - Saved item card renders the plate signals (
ConfidenceBadge,LibraryGroundingBadge,ProvenanceBadge) — the provenance badge reflects the 3 sources from the Atelier - Customer sees the row's "Open in Atelier" resume action; clicking back to
a plate-specific variant is not yet parameterized because the saved row's
current
resumePathis/atelier/image. - Verify:
customer/02-home-discovery/library.mdSaved item row, filters, Storage write
9. Re-cast from the kept plate#
- Customer (later) returns from the library row; the room re-mounts with the saved plate selected and the prompt / seed / style pre-populated
- House rule "Provenance shown." holds — the 3-source list re-renders from the saved provenance, not refetched
- Customer can refine, cast again, or save a new variant; each variant becomes its own library item with attribution to the parent plate (per the lineage rule from Reshare, Lineage, and Remix Attribution)
Post-conditions#
- A new
WebLibrarySavedItemexists inuseOshunWebLibraryStorefor the customer; serialized tolocalStorage['oshun.library.collections.v1']via the dashboard's persistence pipeline - The saved row resumes at the unparameterized
/atelier/imageroute; no claim is made that it restores the selected plate, prompt, or parent lineage yet - The library row exposes the partial provenance badge and lineage note carried by the saved artifact; plate-specific room re-entry remains open
- Verified telemetry is
atelier_plate_saved; the broader room-enter/select/ re-entry trail is not presented as shipped instrumentation
Failure modes#
- Save/cast/refine/control action integrity — "Save plate to notebook",
"Cast twelve more", specimen tap-to-select, "Refine · vary slightly",
aspect/style choices, "Lock seed · vary prompt", and "Compare
side-by-side" are no longer inert: save writes a generated artifact to the
web library, cast/refine drive the real fail-closed
/v1/atelier/castseam with the browser-entered prompt, selected specimen, aspect, style, and seed-lock state, and Compare opens a kept-vs-active plate panel. - Provenance list empty — house rule "Provenance shown." is violated; the room must surface "no provenance recorded" rather than hiding the lane silently
-
getAtelierImage()5xx — no route-localerror.tsxexists; inherited app handling is the only current boundary - Offline cast — the entire view is static markup, so the room renders
offline; cast / save actions degrade per the offline pattern (queue or
disable with explanation per
shell/03-pwa-behavior.md) - AAA-tier customer expecting Yemaya Studio depth — the Atelier is the consumer tier; if AAA tier is the call site the room should offer "Open in Yemaya Studio" as a hand-off (verify whether the Atelier currently surfaces such an affordance)
- Library kind mapping wrong — if
platemaps tonotebookand the customer expects a dedicatedplatechip, the kind rail needs a new chip; otherwise the plate hides under a less-obvious filter - Prompt-only entry refused by Lilith pre-screen — the room must surface the rejection cleanly without leaking the rejection reason (per the broader Lilith pre-screen pattern)
- Mobile / narrow breakpoint —
/atelierand/atelier/imagenow use auto-fit grid tracks, andatelier-image-to-libraryverifies both routes at a 390 px viewport with no horizontal overflow and the image room stacked rail → composer → plate detail.
E2E coverage#
Spec: apps/oshun/web/e2e/atelier-image-to-library.spec.ts (12 tests)
Spec (wave-7, plate actions; deepened 2026-06-27):
apps/oshun/web/e2e/atelier-plate-actions.spec.ts
— the AtelierPlateActions island replaced the inert buttons: "Save plate to
notebook" now writes a generated-artifact row into the web library, reads the
persisted saved-items metadata back from the real BFF, renders the Library row's
partial provenance badge + lineage note, and hydrates the same provenance state
on a clean second-device /library?kind=generated-artifact load. "Cast twelve
more" POSTs /v1/atelier/cast — a real fail-closed Stability image seam that
returns 503 provider_not_configured without creds. The action spec also wires
"Refine · vary slightly" through the same real cast seam and asserts Cast/Refine
carry the browser-entered prompt, selected specimen, aspect, style, and
seed-lock state in the request payload. So save + cast + refine are driven
end-to-end (the deeper generation-success path stays env-cred-gated).
| Step | Test name | Covered? |
|---|---|---|
| 1 — /atelier masthead | step 1 masthead + "Five rooms of making" | ✓ |
| 1 — five room cards | step 1 five room cards with names and hrefs | ✓ |
| 1 — three house rules | step 1 three house rules below rooms grid | ✓ |
| 1/2 — mobile index + image-room stacking | mobile overflow/stacking test | ✓ |
| 2 — plate head + header chips | step 2 plate head renders | ✓ |
| 2 — left step rail (all five, current=3) | step 2 step rail | ✓ |
| 2/3/5/6 — editable prompt, controls, select, compare, rail | steps 2,3,5 prompt/select test | ✓ |
| 2 — right plate detail + provenance header | step 2 plate detail + Provenance | ✓ |
| 2 — Camera Obscura link to /atelier/image | step 2 Camera Obscura card link | ✓ |
| 4 — "Cast twelve more" button present + state/payload | step 4 cast/lock/compare buttons | ✓ |
| 6/7 — "Refine" + "Save plate to notebook" controls/rail | step 7 save + telemetry + refine seam | ✓ |
| 8 — saved plate visible in Library generated-artifact filter | atelier-plate-actions save + BFF hydrate |
✓ |
| 8 — Library provenance badge + lineage note read-back | atelier-plate-actions provenance read-back |
✓ |
| failure — Provenance sources all named (house rule II) | failure mode provenance sources | ✓ |
Not covered (and why):
- Step 9 (re-cast from the kept plate) — library resume currently returns to
/atelier/image; plate-specific query hydration and parent/variant lineage are not implemented.
Coverage depth: partial — see coverage.md. /atelier and
/atelier/image now have a client room island for the live step rail, editable
line, aspect/style/seed controls, specimen selection, compare panel, save,
atelier_plate_saved telemetry, and real cast/refine seam, while /atelier
remains a server-rendered room index. No longer a render-only specimen — the
prompt, controls, select, compare, save, cast, and refine interactions
transition real browser/BFF state. The save action now proves server read-back,
Library partial-provenance badge read-back, privacy-preserving telemetry, and a
clean second-device Library hydrate; only the deeper generation-success path
stays env-cred-gated.
Uncovered: plate-specific library resume / variant lineage, crisis-frame
suppression, AAA Studio handoff, and the cast success path (image bytes
returned), which is env-cred-gated behind Stability creds. The prompt edit,
controls, specimen selection, compare panel, save-to-library BFF sync, Library
provenance badge read-back, atelier_plate_saved telemetry, clean-device
library landing, cast seam, and refine seam interactions are now covered
end-to-end.
Per-view files touched by this journey#
customer/11-atelier/atelier.md— the index card row + house rulescustomer/11-atelier/atelier-image.md— the Camera Obscura room itselfcustomer/02-home-discovery/library.md— where the kept plate landscustomer/10-lilith/lilith.md— the Lilith index card 41 that links to the Ateliershell/03-pwa-behavior.md— offline behavior for the static room compositions
Cross-references#
- Feature spec:
- Living Scenes overview and Composition Surface and Cinematographic Technique Catalog — the broader generative-surface contract the Atelier consumes (the Atelier is the consumer-tier presentation; the authoring tier lives in Yemaya Studio)
- Reshare, Lineage, and Remix Attribution — applies to re-casts from a kept plate
- Related journeys:
scene-keep-and-share.md— the Atelier's kept-plate notion is the artisan cousin of the Living Scene's kept artifact; both honour the "keep is separate from share" gatefirst-time-anonymous-visitor.md— anonymous visitors do not reach the Atelier (signed-in only)
- Component sources:
apps/oshun/web/src/components/lilith/atelier.tsx(AtelierIndex,AtelierImage)apps/oshun/web/src/lib/lilith-data/atelier-depth.ts—getAtelierIndex,getAtelierImage, typesapps/oshun/web/src/components/library/LibraryDashboard.tsx— library landing for the kept plateapps/oshun/web/src/lib/library/webLibraryStore.ts—useOshunWebLibraryStore
Open questions / known gaps#
- Current save path —
AtelierPlateActionswrites the kept plate to the web library asgenerated-artifact; a future/atelier/plates/...BFF may supersede this local-library seam. - Library
kindtaxonomy — current implementation usesgenerated-artifact. - Confirm the responsive behaviour of
/atelierand/atelier/image— both now use auto-fit grids and are covered at 390 px byatelier-image-to-library. - Confirm whether tap-to-select on the specimen tiles is wired — draft
specimen buttons now update
data-atelier-selected-plateand are covered by Playwright. - Confirm the "Compare side-by-side" UX — it opens an inline kept-vs-active comparison panel in the center column.
- Document whether
Save plate to notebookhonors crisis-frame suppression (percrisis-aware-tone-policy.md) — kept plates generated during a crisis frame should default to private and not be shareable - Confirm the Atelier hand-off into Yemaya Studio for AAA tier — is there an "Open in Studio" affordance on the room, and which Yemaya Studio surface accepts the hand-off?