---
path: /studio/aja/proportional-adaptation
surface: studio
domain: aja
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/aja/proportional-adaptation/page.tsx
status: walked + e2e-covered
last_walked:
  '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; body
  re-derived 2026-06-03 from current source (lane-console architecture);
  2026-07-02 studio-aja-retargeting-lane-consoles Playwright pass — live
  real-BFF catalog/action happy path, fail-closed auth/error states, client/BFF
  validation errors, mobile overflow, touch target, route-map, quick-action,
  breadcrumb, and direct BFF auth/schema gates.'
---

# Studio Aja · Proportional Adaptation

## Purpose

Admin lane console for proportional skeleton retargeting math. It wires the real
`@aja/proportional-adaptation` `compareLimbLengths` via
`/v1/admin/aja/proportional-adaptation`: enter source + target limb lengths and
the engine computes the per-limb scale ratio / difference / percentage between
the two rigs — the math that adapts a motion to a differently-proportioned
skeleton.

## Entry points

- **Direct URL / bookmark** — `/studio/aja/proportional-adaptation`; metadata
  sets `alternates.canonical`
- **Breadcrumb** — Studio → Aja Skeleton-to-Skeleton Retargeting → Proportional
  Adaptation
- **Linked from `/studio`** Domain-bridge studios section (Aja sub-area)
- **Quick action** — "Open Aja Skeleton-to-Skeleton Retargeting workspace"
  (`/studio/aja/skeleton-to-skeleton-retargeting`)

## Layout regions

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

- **Breadcrumb panel** (`data-aja-proportional-adaptation-breadcrumbs`) — nav
  Studio / Aja Skeleton-to-Skeleton Retargeting / Proportional Adaptation
  (current)
- **Workspace** `StudioAjaProportionalAdaptationWorkspace` — `<h1>` "Aja
  Proportional Adaptation Workspace" + summary
  (`data-aja-proportional-adaptation-summary`), the limb taxonomy line
  (`data-aja-pa-limbs`), then the compare form
- **Route Map panel** (`data-aja-proportional-adaptation-route-map`, `<h2>`) — 6
  entries from `STUDIO_AJA_PROPORTIONAL_ADAPTATION_ROUTE_MAP`
- **Quick-action lane** — `quickAction` links: skeleton-to-skeleton-retargeting,
  `/studio`

## States

- [x] **Loading** — `data-aja-pa-loading` "Loading limb taxonomy…" while
      `GET /v1/admin/aja/proportional-adaptation` is in flight
- [x] **Unauthorized (gated)** — `data-aja-pa-unauthorized` on 401/403; admin
      scope message ("Aja workspace scope required to view proportional
      adaptation.")
- [x] **Error** — `data-aja-pa-error` on non-OK / malformed / network failure
- [x] **Ready (form)** — `data-aja-pa-compare-form` once the catalog loads
- [x] **Result** — `data-aja-pa-result` (per-limb ratio + percent rows) after a
      successful POST; validation error in `data-aja-pa-compare-error`
- [x] **Responsive shell** — desktop/mobile layout keeps the compare form and
      `quickAction` anchors readable without horizontal overflow
- [x] **Empty** — N/A; limb taxonomy is constant

## Interactions

### Compare form

- [x] **Source limb lengths** (`<input data-aja-pa-field-source>`) — "limb:
      length, …" entries (≥1)
- [x] **Target limb lengths** (`<input data-aja-pa-field-target>`) — "limb:
      length, …" entries (≥1)
- [x] **"Compare proportions"** (`<button data-aja-pa-compare-submit>`) — POSTs
      `{ source, target }` to `/v1/admin/aja/proportional-adaptation/compare`

### Route Map panel

- [x] **6 entries** (`<article>` per `path` + `purpose`) — non-interactive

### Quick-action lane

- [x] **"Open Aja Skeleton-to-Skeleton Retargeting workspace"** →
      `/studio/aja/skeleton-to-skeleton-retargeting`
- [x] **"Back to Studio workspace index"** → `/studio`

## E2E coverage

`apps/oshun/web/e2e/studio-aja-retargeting-lane-consoles.spec.ts` covers this
route against the real Next shell and real BFF:

- live admin catalog load, breadcrumb panel, limb taxonomy, ready form,
  route-map count, quick-action hrefs, and 44 px submit target
- client-side empty-source guard with no `POST`
- BFF unknown-limb 400 `invalid_payload` surfaced in `data-aja-pa-compare-error`
- valid proportional output for left-arm scale-up, right-arm scale-down, and
  spine identity rows
- loading, unauthorized, and catalog error states fail closed with no
  form/result
- mobile viewport horizontal-overflow check
- direct BFF 401, wrong-scope 403, and invalid-payload 400 gates

## Data & contracts

- **Reads**: `GET /v1/admin/aja/proportional-adaptation` (catalog: `limbTypes`)
  on mount, `cache: 'no-store'`, `buildBffAuthHeaders()`
- **Writes**: `POST /v1/admin/aja/proportional-adaptation/compare`
- **Realtime**: none
- **Caching**: client fetch on mount (no-store); SSR shell
- **Auth/role check**: BFF endpoints admin-scoped, fail-closed (401/403 →
  unauthorized render); route gated signed-in + studio via the proxy

## Cross-references

- Parent: [`../../studio-overview.md`](../../studio-overview.md)
- Sibling routes:
  [`./studio-aja-skeleton-to-skeleton-retargeting.md`](./studio-aja-skeleton-to-skeleton-retargeting.md)
- Component sources:
  - `apps/oshun/web/src/components/studio/StudioAjaProportionalAdaptationWorkspace.tsx`
  - `apps/oshun/web/src/components/studio/StudioAjaProportionalAdaptationRouteMap.ts`

## Known downstream boundaries

- The lane computes the per-limb ratios; applying the proportional adaptation to
  an actual motion clip is not an in-page action.
- Browser E2E covers the BFF/catalog error path, not a separate service-worker
  offline mode.
