Context. surface operator · domain operator (studio — editorial review queue and approval workspace) · route /operator/studio · auth signed-in · source apps/oshun/web/src/app/operator/studio/page.tsx
Last walked. 2026-06-29 operator-studio route-DOM addendum — Playwright now covers the shipped /operator/studio queue rows, selected TR-047 artifact pane, waveform/transcript, review notes, citation statuses, decision-row entry point, static queue-row boundary, and anonymous redirect-before-render. Evidence: WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md §222; spec: apps/oshun/web/e2e/operator-studio-surface.spec.ts. 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#
The editorial review queue and approval workspace. Three-column register layout:
review queue (left), the artifact under review (center), and an approval /
annotation pane (right). Robots-noindex. Backed by getStudioReview() and
rendered by StudioReview (line 42 of the 665-LOC
apps/oshun/web/src/components/lilith/operator.tsx).
Entry points#
- From
/operator(index) — operator-surface card - Profile menu → Operator → Studio
- Direct URL — session-gated only (
proxy.tsredirects sessionless →/welcome?redirect=); no operator-role gate in the proxy - From
/operator/admininbox detail — editorial INC links here with the artifact code preselected - Studio editorial workflow notification — push/email handoff
Layout regions#
StudioReview uses Lilith primitives (LGraphPaper, LOperatorBar, LCode,
LChip, LEyebrow, L, SERIF_L, SANS_L).
- Top:
LOperatorBar— product="Lilith Studio", section="Editorial", breadcrumb="Tara · Path IV › Session 03 · review" (the›isCRUMB_SEP = ' › ', operator.tsx:38/48; the inner dots are literal) - Main 3-column grid (300px / 1fr / 320px;
data-operator-studio-layout):- Queue column (300px):
- Eyebrow accent "In review · 7" (derived from
data.queue.length) - List of review items — each row has:
LCodeartifact code (e.g.,TR-047)- Status code (e.g.,
s3, uppercase, tracked-out, muted) - Italic Garamond 14 title (e.g., "On the illusion of a separate self")
LEyebrowbyline (e.g., teacher name)- Stable attributes:
data-operator-studio-queue-row,data-artifact-code,data-review-status, anddata-selected - Selected row paints with
r.hereflag (accent border + bg). Today these rows are static orientation rows: they have pointer styling but no link/button/tabindex/selection handler.
- Eyebrow accent "In review · 7" (derived from
- Artefact column (1fr) — bordered card, padded 28:
- Top band (flex space-between):
- Left:
LCode"TR-047 · Tara · Path IV · §03" (data-operator-studio-artifact-code) - Title (Garamond 26 medium, italic ref): "On the illusion of a separate
self" (
data-operator-studio-artifact-title) - Eyebrow byline: "Saro Imani · 12:00 · v3 · uploaded 14:22"
- Right: chip row —
LChip"Audio · 12:03",LChip"Transcript",LChip accent"Confidence · strong"
- Left:
- Player band (
data-operator-studio-waveform): paper-background card with a 600×48 SVG waveform,aria-hidden="true", 120 deterministic rects via sin/cos seeding, and static time labels0:00,2:14 · current marker, and12:03 - Transcript (
data-operator-studio-transcript): four visible timecode passages at 00:00, 00:42, 02:14, and 03:08 StudioReviewDecisionRowfor artifactTR-047
- Top band (flex space-between):
- Detail column (320px):
- Review notes: four rows with author/role/mark attributes
- Source citations: three rows with citation code and status attributes
- Queue column (300px):
States#
- Loading —
getStudioReview()server-side; no route-localloading.tsx - Anonymous user — redirected to
/welcome?redirect=byproxy.ts - Signed-in user — renders (session-gated only; no operator-role gate in the proxy)
- Queue with selection — TR-047 selected row is painted and exposes
data-selected="true"; the artefact/detail panes render TR-047 - Empty queue — copy / empty state (verify)
- Audio-bearing artefact — waveform and transcript region are visible; there are no real play/pause/scrub controls yet
- Text-only artefact — player likely hidden / replaced
- Confidence levels — shipped fixture renders
Confidence · strong; partial/weak variants are not present in this route fixture -
getStudioReview()fails — no local routeerror.tsxexists underapps/oshun/web/src/app/operator - Audio player offline — disabled with explanation (verify)
Interactions#
Queue column#
- Each queue row — renders the seven fixture artifacts with stable code,
status, title, byline, selected-state attributes, and ≥44px row height
- Keyboard: no row exposes link/button/
tabindex; arrow-key navigation is not wired today - SR: no explicit row role/name is wired today; rows remain plain text
- Selected:
r.here === truepaints TR-047 with accent border - Static boundary: clicking TR-048 does not change selection or the artifact pane
- Keyboard: no row exposes link/button/
-
LCode(artefact code) — non-interactive - Status label — non-interactive text label (
in review,changes,sources,audio,copy,fact-check,queued)
Artefact column#
-
LCodeheader "TR-047 · Tara · Path IV · §03" — non-interactive - Chip row —
Audio · 12:03,Transcript,Confidence · strongare visual labels, not filters/actions - Waveform SVG —
aria-hidden="true"; 120 rects; non-interactive visual - Audio player controls — no real play/pause/scrub/volume control is wired; only the static waveform and time labels are present
- Transcript — four static timecoded paragraphs are visible
- Decision row —
StudioReviewDecisionRowexposes Mark for revoice, Adjust pacing, Re-cite source, Request changes, and Approve · publish 06:00 controls
Detail column (right pane)#
- Review notes — four note rows render M. Doss / Editor at 00:42, A.
Patel / Theology at 02:14, R. Lee / Audio at 03:08, and Lilith / Auto at
— - Source citations —
SN 22.59verified,MN 22pending, andHarris, S.verified render as static citation rows - History view — no separate review-history timeline is present beyond notes/citations and the local decision row
Data & contracts#
- Reads:
getStudioReview()from@/lib/lilith-data/operator-depthreturningStudioReviewData(queue withc/s/t/by/herefields, etc.). NOTE: this is a static in-process fixture (returnsgetStudioReviewFixture()directly), not a BFF call — the module is headed "fixture today, BFF tomorrow" - Writes:
StudioReviewDecisionRowstores annotation toggles, approve, and request-changes verdict locally inlocalStorageunderoshun.studio.review.decision.v1.<artifactId>, and its approve/request- changes branches create and patch admin release streams through the BFF. The returned release-stream id/status are persisted for reload durability, and the correspondingadmin.editorial_release_stream.*audit events are covered in the editorial journey specs. - Realtime: review-state changes from other operators — Psyche channel (verify)
- Caching: server-rendered; no SW caching
- Auth/role check: session-gated only (
proxy.tsredirects sessionless →/welcome?redirect=); no operator-role gate in the proxy
Cross-references#
- Parent:
operator-overview.md - Sibling operator routes:
- Customer-side Tara:
../customer/03-tara/tara.md - Studio (editorial workspace):
../studio/studio-overview.md - Component source:
apps/oshun/web/src/components/lilith/operator.tsx(line 42:StudioReview) - Feature spec:
V1/features.md - Architecture:
V1/ARCHITECTURE.md
E2E coverage#
apps/oshun/web/e2e/operator-studio-surface.spec.ts— signed-in/operator/studiorender; operator bar and breadcrumb; all seven queue rows with code/status/title/byline/selected attributes and ≥44px row height; static queue-row boundary; TR-047 artifact code/title/byline/chips; waveformaria-hidden+ 120 rects + static time labels; transcript timecodes/copy; decision-row control entry point; four note rows; three citation rows/statuses; anonymous redirect-before-render.apps/oshun/web/e2e/editorial-release-streams.spec.ts— deeperStudioReviewDecisionRowlocal approve/request-changes branches and reload durability, plus the release-stream BFF API/audit path and invalid-mutation guards.
Open questions / known gaps#
- Walk the detail column (lines after the artefact column) to enumerate the approval action set and annotation UI
- Confirm the relationship between this surface and
/studio/review-approval-workflows— they are distinct surfaces today:/operator/studiois the static editorial review queue with a localStorage-backedStudioReviewDecisionRow;/studio/review-approval-workflowsis a stateless admin-scoped approval-gate evaluator backed by/v1/admin/studio/approval-workflow - Document audio player controls — none are wired on this surface today; only the static waveform and time labels render
- Verify keyboard navigation in the queue — no row-level link/button/tabindex or arrow-key navigation is wired today
- An operator-role gate appears absent —
proxy.tsonly redirects sessionless users to/welcome; no role check in the proxy or page component (possible gap vs intended scope)