---
path: /studio/aja/medical-rehabilitation-pipeline
surface: studio
domain: aja
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/aja/medical-rehabilitation-pipeline/page.tsx
status: walked + e2e-covered
last_walked:
  '2026-07-04 focused real-dev-infra Playwright route walk — anonymous redirect,
  Aja-admin analyzer catalog, exact out-of-range and clean rehab motions through
  the real BFF, local/BFF validation, malformed/transport failures, loading/403/
  503/malformed catalog states, pending controls, route-map + quick-action
  affordances, mobile/touch/axe, and direct BFF auth/schema gates. Evidence:
  WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md §285.'
---

# Studio Aja · Medical/Rehabilitation Pipeline

## Purpose

Leaf lane console that wires the real `@aja/motion-quality` `analyzeJointAngles`
range-of-motion safety check. Each joint orientation in the submitted motion is
compared against the anatomical per-axis angle limits; any angle past a limit is
recorded as a violation with its severity in degrees. The lane returns the
score, violation list, clean-frame percentage, and the clean/problematic joints.

## Entry points

- **Direct URL / bookmark** — `/studio/aja/medical-rehabilitation-pipeline`.
- **Studio nav** — Domain-bridge studios section of `/studio`.
- **Sibling quick-action** — "Open Aja Sports Pipeline workspace"
  (`/studio/aja/sports-pipeline`); also linked from the film-vfx-pipeline page.

## Layout regions

`page.tsx` renders inside `<ShellLayout active="studio">`:

- **Workspace** `<StudioAjaMedicalRehabilitationPipelineWorkspace />`:
  - `<h1>` "Aja Medical/Rehabilitation Pipeline Workspace" + summary
    (`data-aja-medical-rehabilitation-pipeline-summary`).
  - Embodied-instruction panel `<StudioAjaMetisEmbodiedInstructionPanel>`
    (domain `rehabilitation`, prefix `aja-medical-rehabilitation-pipeline`).
  - Range-of-Motion Operations Lane
    (`data-aja-medical-rehabilitation-pipeline-operations-lane`, `<h2>`) — the
    form; includes `data-aja-rehab-check-summary` (catalog `summary`).
- **Route Map panel** (`data-aja-medical-rehabilitation-pipeline-route-map`,
  `<h2>` "Route Map"): 5 entries exposed with
  `data-aja-medical-rehabilitation-pipeline-route-map-entry` / `data-route-path`
  — primary, scenes, exports, revisions, governance.
- **Quick-action lane**
  (`data-aja-medical-rehabilitation-pipeline-quick-actions`): two
  `Link.quickAction` anchors. No breadcrumb panel.

## States

The lane fetches `GET /v1/admin/aja/medical-rehabilitation-pipeline` on mount.

- [x] **Loading** — `data-aja-rehab-loading` "Loading range-of-motion check...".
- [x] **Unauthorized** — `data-aja-rehab-unauthorized` (401/403; default "Aja
      workspace scope required to run the range-of-motion check.").
- [x] **Error** — `data-aja-rehab-error`.
- [x] **Ready (form)** — `data-aja-rehab-form`, catalog attributes
      (`data-aja-rehab-check`, default severity threshold, report count/report
      spans), and idle submit state.
- [x] **Result** — `data-aja-rehab-result` with stable score / violation-count /
      clean-frame-percent attributes, `data-aja-rehab-headline` (ROM score ·
      violations · clean-frame %), typed `data-aja-rehab-violation-row`
      attributes, `data-aja-rehab-clean`, and `data-aja-rehab-problematic`.
- [x] **Validation error** — `data-aja-rehab-analyze-error` (e.g. "Provide at
      least one joint id." / "Frames must be valid JSON.").

## Interactions

### Range-of-motion form (`data-aja-rehab-form`)

- [x] **Joint ids** — input `data-aja-rehab-joints` (default `LeftLeg`).
- [x] **Frames (JSON `{ rotations: { jointId: { w, x, y, z } } }`)** — textarea
      `data-aja-rehab-frames`.
- [x] **Check range of motion** — submit `data-aja-rehab-submit`; fires
      `POST /v1/admin/aja/medical-rehabilitation-pipeline/analyze` with
      `{ joints, frames }`; locked with
      `data-aja-rehab-submit-state="analyzing"` while the real request is
      pending.

### Route Map

- [x] **Route entries** (5) — non-interactive listing with exact path ordering.

### Quick-action lane

- [x] **"Open Aja Sports Pipeline workspace"** → `/studio/aja/sports-pipeline`
- [x] **"Back to Studio workspace index"** → `/studio`

## Data & contracts

- **Reads**: `GET /v1/admin/aja/medical-rehabilitation-pipeline` (catalog:
  `check`, `summary`, `defaultSeverityThreshold`, `reports`); client fails
  closed unless the expected `joint-angle-range-of-motion` check and all six
  report keys are present.
- **Writes**: `POST /v1/admin/aja/medical-rehabilitation-pipeline/analyze` →
  `{ score, violationCount, cleanFramePercent, cleanJoints, problematicJoints, violations }`;
  client fails closed unless the result and each violation row have the expected
  typed fields.
- **Realtime**: none.
- **Caching**: client fetch on mount (`cache: 'no-store'`); SSR shell.
- **Auth/role check**: BFF endpoint admin-scoped + fail-closed; route gated
  signed-in + studio via proxy.

## Cross-references

- Parent: [`../../studio-overview.md`](../../studio-overview.md)
- Sibling (linked from):
  [`./studio-aja-film-vfx-pipeline.md`](./studio-aja-film-vfx-pipeline.md)
- Component sources:
  - `apps/oshun/web/src/components/studio/StudioAjaMedicalRehabilitationPipelineWorkspace.tsx`
  - `apps/oshun/web/src/components/studio/StudioAjaMedicalRehabilitationPipelineRouteMap.ts`

## Verification evidence

- `apps/oshun/web/e2e/studio-aja-medical-rehabilitation-pipeline.spec.ts` runs
  against the real Next Studio shell and local BFF, forwarding browser bearer
  auth rather than mocking the range-of-motion contract.
- The spec covers anonymous redirect, Aja-admin catalog load, exact default
  out-of-range `LeftLeg` violation, edited clean no-violation result, local
  validation with no POST, BFF missing-joint validation detail, malformed
  result, transport failure, loading / 503 / malformed / non-admin states,
  pending form locking, mobile no-overflow + 44px controls, scoped axe, and
  direct BFF 401/403/400/200 gates.

## Open questions / known gaps

- [ ] Route Map lists `scenes`/`exports`/`revisions`/`governance` child routes
      that are not yet implemented as pages.
