V1 Web PWA · Journey

Journey: Atelier · motion room → Cinematheque handoff

A source-reconciled journey record for V1 Web PWA — shipped behavior, state boundaries, failure modes, and the automation evidence available today.

automated · 1 spec verdict: partial· 2026-07-02
10sections6 minread

On this page
Journey at a glance
ActorsContemplative customerReturning makerAAA/studio-bound customer
Automation1 E2E spec(s) · verdict: partial· 2026-07-02

Journey flow#

Generated from the authored steps below — click a node to jump to that section.

flowchart TD s1["1. Open Stage of Motion"] s2["2. Inspect the stage viewport"] s3["3. Inspect the timeline and bake state"] s4["4. Review the kept take and downstream note"] s5["5. Use available actions"] s6["6. Edge-state checks"] s1 --> s2 --> s3 --> s4 --> s5 --> s6 click s1 href "#1-open-stage-of-motion" click s2 href "#2-inspect-the-stage-viewport" click s3 href "#3-inspect-the-timeline-and-bake-state" click s4 href "#4-review-the-kept-take-and-downstream-note" click s5 href "#5-use-available-actions" click s6 href "#6-edge-state-checks" s6 --> v(["verdict: partial"]) click v href "../results/atelier-motion-to-cinematheque.html" style v stroke:#d6a531,color:#d6a531

A signed-in customer opens the Stage of Motion room, reviews the rigged viewport, verifies the bake/timeline state for take 02, and sends the kept motion clip forward to Cinematheque. This covers the V1 Atelier motion surface as a deliberate read-only composition stage: the rendered timeline is inspectable but not yet editable, draft actions are honest placeholders, and the downstream handoff is a real route link. As of 2026-06-30 the handoff also carries an explicit URL-scoped context (shot=sh-03, take=take-02, voice=foundry-take-03, light=forms-cream-north) and Cinematheque renders that inbound context. This is intentionally not described as durable project persistence.

Personas#

  • Contemplative customer — primary actor; enters the Atelier from Explore or the Lilith index and wants to inspect a motion clip without entering Studio
  • Returning maker — checks which take is kept and whether the downstream room can continue from the motion plate
  • AAA/studio-bound customer — verifies that consumer Atelier stays a manuscript-style inspection room; production retargeting/new-take creation is not exposed here yet

Pre-conditions#

  • Customer signed in
  • /atelier/motion and /atelier/video are reachable behind the customer auth shell
  • getAtelierMotion() returns the populated fixture with five timeline tracks and three takes
  • The route has no local loading.tsx or error.tsx; those states are captured as inherited/absent rather than fabricated

Steps#

1. Open Stage of Motion#

  • Customer navigates directly to /atelier/motion or uses the Atelier index "XIV · Stage of Motion" card.
  • Page server-renders apps/oshun/web/src/app/atelier/motion/page.tsx, awaits getAtelierMotion(), and renders <AtelierMotion data>.
  • Route root exposes data-atelier-motion-page, data-atelier-motion-track-count="5", data-atelier-motion-take-count="3", data-atelier-motion-current-take="take 02", data-atelier-motion-current-frame="74", and data-atelier-motion-bake-progress="41".
  • Plate head reads "The atelier · stage of motion" and "A figure, set in motion." with chips "Take 02 · 06s", "Rig · 24 joints", and "Baking · 41%".
  • Step rail exposes all five steps with step 4 "Baking · keyframes" current and step 5 "Plate · clip kept" pending.

2. Inspect the stage viewport#

  • Center stage renders the 16:9 SVG viewport with perspective grid, rigged figure, onion-skin echo poses, IK markers, and labels STAGE · PERSP · 38 mm, f · 074 / 144, and RIG · 24 joints · IK on heels.
  • The viewport exposes current frame 074, total frames 144, and rig joints 24.
  • Viewport click is read-only: it does not rotate, scrub, navigate, or change the playhead attributes.

3. Inspect the timeline and bake state#

  • Timeline exposes data-atelier-motion-frame-count="144", data-atelier-motion-duration="06 s", and data-atelier-motion-frame-rate="24 fps".
  • Frame ruler renders 13 labels from 000 to 144.
  • Five fixture tracks render with exact names, curves, and key counts: Spine · root / ease / 7 keys; Head · pitch / ease / 5; Hand L · IK / step / 5; Hand R · IK / step / 5; Breath · param / sine / 7.
  • Frame 72 keyframes expose data-atelier-motion-keyframe-selected="true"; tracks without frame 72 expose no selected keyframe.
  • Playhead remains fixed at data-atelier-motion-playhead-frame="74" and data-atelier-motion-playhead-position="51" after ruler and keyframe clicks.
  • Bake card shows Rendering 41%, ETA 03:42, "Baking keys → motion clip · take 02", and "59 / 144 frames".

4. Review the kept take and downstream note#

  • Clip panel shows take 02 metadata: length 06.000 s, 144 frames at 24 fps, 24 joints with IK heels, live actor source, clamped bezier curves, loop state, and usd · alembic · glb format.
  • Three take rows render from fixture data: take 01 archived, take 02 kept and selected, take 03 draft.
  • Compose downstream panel names Cinematheque (sh 03), foundry voice take 03, and forms light cream-north.
  • The panel exposes the machine-readable handoff attributes: data-atelier-motion-handoff-source="motion", data-atelier-motion-handoff-state="url-context", data-atelier-motion-handoff-shot="sh 03", data-atelier-motion-handoff-take="take 02", data-atelier-motion-handoff-voice="foundry · take 03", and data-atelier-motion-handoff-light="forms · cream-north".

5. Use available actions#

  • "New take" and "Re-target rig" render as disabled-placeholder LBtn controls with aria-disabled="true", data-placeholder="true", and the placeholder tooltip; clicking them leaves the customer on /atelier/motion.
  • "Open in Cinematheque" is a real primary link with the handoff URL: /atelier/video?from=motion&shot=sh-03&take=take-02&voice=foundry-take-03&light=forms-cream-north.
  • Activating the link navigates to /atelier/video, where Cinematheque renders "The atelier · cinematheque" and "A short film, storyboarded."
  • Cinematheque renders the inbound "Motion handoff" context panel with target shot sh 03, motion take take 02, voice foundry · take 03, and light forms · cream-north.

6. Edge-state checks#

  • At 390 px width, the layout stacks rail → stage/timeline/bake → clip/takes without horizontal overflow.
  • Under reduced motion, the motion page subtree exposes zero animations; the onion-skin and bake state remain static values.
  • After the route has loaded, browser offline mode leaves the stage SVG, playhead, and route root visible.

Post-conditions#

  • Customer can inspect the kept motion take and understand that take 02 is the current downstream clip.
  • Customer can route to Cinematheque through the primary action, carrying the URL-scoped motion context into the receiving page.
  • No fake mutation is implied for new-take, retarget, timeline scrub, or viewport rotation; each unbuilt interaction is captured as read-only or placeholder.

Failure modes#

  • Timeline misread — selected frame 72 accents and fixed f.074 playhead are asserted from DOM attributes, not inferred from text alone.
  • False affordance — placeholder buttons expose disabled semantics and do not navigate.
  • Mobile overflow — 390 px browser check fails if the desktop grid leaks horizontally.
  • Offline after load — static route markup remains visible after the browser context goes offline.
  • Route-local load/error — no local loading.tsx or error.tsx exists yet; inherited app behavior is not a substitute for a room-specific state.
  • URL-scoped handoff — navigation to /atelier/video carries target shot, take, voice, and light context, and Cinematheque renders the inbound panel from that context.
  • Durable project-state handoff — no persisted project-level object is stored yet; the current handoff is URL context only.

Data & contracts#

  • Route: apps/oshun/web/src/app/atelier/motion/page.tsx
  • Component: apps/oshun/web/src/components/lilith/atelier.tsx (AtelierMotion)
  • Data: apps/oshun/web/src/lib/lilith-data/atelier-depth.ts (getAtelierMotionFixture())
  • Downstream route: apps/oshun/web/src/app/atelier/video/page.tsx
  • Downstream query contract: from=motion&shot=sh-03&take=take-02&voice=foundry-take-03&light=forms-cream-north
  • Writes: none in the current customer surface
  • Realtime: none

E2E coverage#

Spec: apps/oshun/web/e2e/atelier-motion-to-cinematheque.spec.ts (4 tests)

Coverage depth: deep for the shipped static/read-only route contract. The spec runs through authenticated real dev infra, verifies the rendered fixture shape, drives available action semantics, proves the /atelier/video handoff plus inbound URL context, and covers mobile, reduced-motion, and offline-stable loaded markup. Remaining gaps are product work: route-local loading/error boundaries, a real new-take or retarget workflow, and a persisted project-state bridge into Cinematheque.

Per-view files touched#

Cross-references#

Open questions / known gaps#

  • Add route-local loading and error states for both sides of the handoff
  • Decide whether new-take and rig-retarget workflows belong in the consumer room or only in the authoring studio
  • Replace URL-only context with a persisted project reference before describing the handoff as durable