---
path: /compose
surface: mobile
domain: atelier
auth: anon (paid-tier framed in copy; no gate enforced in code)
source: apps/oshun/mobile/app/compose.tsx
status: drafted
last_walked: 'not yet walked'
---

# Compose (mobile studio — living-scenes composition)

## Purpose

Compose is a Yemaya living-scenes composition surface: a segment library, an
ordered timeline with per-segment transition-technique pickers and reorder
controls, a scrub preview, a Compose Assist suggestion inserter, a
reduced-motion technique summary, and an audit trail. It is a standalone stack
screen (not a tab) and is purely in-memory — no persistence or network.

## Entry points

- Direct route `/compose` (not declared in `_layout` Stack screens nor the tab
  bar; reachable by `router.push('/compose')` / deep link).
- No shell-nav tab or visible launcher found in the audited screens.

## Layout regions

- **Header (in-screen)**: kicker "Studio", title "Compose", meta
  (`mobile-compose-meta`: "Paid tier · N Segments · Ns").
- **Main** (vertical `ScrollView`, `mobile-compose-surface`): panels — Segment
  library (`mobile-compose-segment-library`), Timeline
  (`mobile-compose-timeline`), Scrub preview (`mobile-compose-preview`), Compose
  Assist (`mobile-compose-assist`), Reduced motion
  (`mobile-compose-reduced-motion`), Audit trail (`mobile-compose-audit-log`).
- **Footer / sticky bottom**: none (no tab bar on this stack route).

## States

- [ ] **Loading** — N/A: synchronous in-memory state from `INITIAL_SEGMENTS`.
- [ ] **Empty** — not reachable: starts with 3 frozen segments; no delete
      control.
- [ ] **Populated (short)** — 3+ segments; Accept suggestion appends more.
- [ ] **Populated (long)** — appended `seg-assist-N` segments grow the timeline.
- [ ] **Error** — N/A: no async paths.
- [ ] **Offline** — fully functional offline (no network).
- [ ] **Permissions-denied** — N/A: no device permissions.
- [ ] **Gated** — copy says "Paid tier" but no entitlement check is enforced
      here.
- [ ] **iOS vs Android** — light theme (`#f6f8fb`); no safe-area handling; this
      screen uses a light palette unlike the dark shell tabs.

## Interactions

- [ ] **Library item** (`mobile-compose-source-<segmentId>`, Pressable)
  - Function: `setPreviewSegmentId(segment.segmentId)`.
  - Accessibility: role button, label "Preview <id> from <sourceId>".
- [ ] **Timeline item** (`mobile-compose-segment-<segmentId>`, Pressable)
  - Function: tap → preview that segment; long-press → open the boundary
    Technique Picker + audit entry.
  - Gesture/touch: tap (preview) AND long-press (picker).
  - Accessibility: label "<id>, <duration>s, <technique>"; hint "Long press to
    open the boundary Technique Picker."
- [ ] **Move up** (`mobile-compose-move-up-<id>`, Pressable)
  - Function: `moveSegment(index, -1)` + audit. Disabled when `index === 0`.
  - Accessibility: role button, label "Move <id> up". Touch target 44×40.
- [ ] **Move down** (`mobile-compose-move-down-<id>`, Pressable)
  - Function: `moveSegment(index, 1)` + audit. Disabled at last index.
  - Accessibility: label "Move <id> down".
- [ ] **Technique pill** (`mobile-compose-technique-<id>-<techniqueId>`,
      Pressable)
  - Function: `setTechnique(segmentId, techniqueId)` (closes picker + audit).
    Options limited to `ALLOWED_TARA_TECHNIQUES`
    (`filterComposeAssistTechniqueSuggestions` for `tara-contemplative-arc`).
  - Accessibility: role button; label = technique label.
- [ ] **Accept suggestion** (`mobile-compose-assist-accept`, Pressable)
  - Function: `acceptSuggestion` — appends a `match-action` Compose Assist
    bridge segment, previews it, audits. accessibilityLabel "Accept Compose
    Assist suggestion".

## Data & contracts

- **Reads**: `@yemaya/living-scenes-runtime/compose-assist`
  (`V1_COMPOSITION_TECHNIQUE_IDS`, `filterComposeAssistTechniqueSuggestions`,
  `reducedMotionTechniqueFor`, `CompositionDraftSegment`).
- **Writes**: in-component state only (`segments`, `previewSegmentId`,
  `auditLog`, `activePickerSegmentId`). No persistence.
- **Realtime**: none.
- **Telemetry**: none wired.
- **Auth/role check**: none enforced (copy references paid tier only).

## Cross-references

- Tests: `apps/oshun/mobile/app/compose.test.tsx`.
- Runtime lib: `@yemaya/living-scenes-runtime/compose-assist`.
- Stack shell: not registered in `_layout.tsx` Stack screens (file-based route).

## Open questions / known gaps

- [ ] No entitlement gate despite "Paid tier" copy — confirm whether a paywall
      should guard `/compose`.
- [ ] No visible launcher/entry point in the audited shell — confirm how users
      reach `/compose`.
- [ ] No persistence/export of the composition — drafts are lost on unmount.
