---
path: /studio/aja/physics-cleanup
surface: studio
domain: aja
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/aja/physics-cleanup/page.tsx
status: walked + e2e-covered
last_walked:
  '2026-07-02 cleanup-lane console addendum — Playwright real-dev-infra coverage
  now proves signed-in render, route-map contract, quick-action href order,
  ready segment-mass catalog, 44 px submit target, invalid-pose client guard
  with no POST, real BFF center-of-mass result, fail-closed
  loading/unauthorized/malformed-catalog states, mobile no-overflow, and direct
  BFF 401/403/400/200 gates. Spec:
  apps/oshun/web/e2e/studio-aja-cleanup-lane-consoles.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; body
  re-derived 2026-06-03 from current source (lane-console architecture)'
---

# Aja Physics Cleanup

## Purpose

Admin lane console wired to the real `@aja/motion-processing`
`calculateCenterOfMass` via `/v1/admin/aja/physics-cleanup`: from a pose it
computes the mass-weighted body center-of-mass trajectory using the segment-mass
model — the signal that drives balance correction and COM smoothing. The
operator enters one frame of "joint:x,y,z" segments.

## Entry points

- **Direct URL** — `/studio/aja/physics-cleanup` (signed-in + studio
  entitlement)
- **Sibling quick-actions from this page** — Foot Sliding Correction, Back to
  Studio

## Layout regions

`page.tsx` mounts `ShellLayout` with `active="studio"` and renders three panels.

- **Workspace panel** (`data-aja-physics-cleanup-workspace`):
  - `<h1>` "Aja Physics Cleanup Workspace" (via `WorkspaceHeading`)
  - `<p data-aja-physics-cleanup-summary>` — "Compute the mass-weighted body
    center-of-mass from a pose — the trajectory that drives balance correction
    and center-of-mass smoothing."
  - `data-aja-pc-mass-model` (segment-mass model: joints / total mass /
    fallback)
    - the center-of-mass form
- **Route Map panel** (`data-aja-physics-cleanup-route-map`): `<h2>` "Route Map"
  - one `<article>` per `STUDIO_AJA_PHYSICS_CLEANUP_ROUTE_MAP` entry (5 entries)
- **Quick actions panel**: `.quickAction` `<Link>`s — see Interactions

## States

- [x] **Loading** — `data-aja-pc-loading` "Loading segment-mass model…"
- [x] **Unauthorized** — on 401/403, `data-aja-pc-unauthorized` ("Access
      restricted." + reason, default "Aja workspace scope required to view
      physics cleanup.")
- [x] **Error** — non-OK / malformed / unreachable → `data-aja-pc-error`
- [x] **Ready (form)** — catalog present: `data-aja-pc-mass-model` + the COM
      form
- [x] **Result** — `data-aja-pc-result` `data-aja-pc-com` "center of mass: (x,
      y, z)"
- [x] **Validation error** — `data-aja-pc-com-error` 'Pose must contain at least
      one "joint:x,y,z" entry.'

## Interactions

### Center-of-mass form (`data-aja-pc-com-form`)

- [x] **Pose ("joint:x,y,z; joint:x,y,z")** — `input data-aja-pc-field-pose`
- [x] **Compute center of mass** — `button data-aja-pc-com-submit`; parses the
      pose into named joints, then POSTs to
      `/v1/admin/aja/physics-cleanup/center-of-mass` with
      `{ frames: [{ joints }] }` → `{ com }`

### Route Map panel (`data-aja-physics-cleanup-route-map`)

Non-interactive `<article>` blocks from `STUDIO_AJA_PHYSICS_CLEANUP_ROUTE_MAP`
(5 entries): `/studio/aja/physics-cleanup` plus `…/scenes/[sceneId]`,
`…/exports/[exportId]`, `…/revisions/[revisionId]`, `…/governance/[policyId]`.

### Quick actions panel

- [x] **Open Aja Foot Sliding Correction workspace** →
      `/studio/aja/foot-sliding-correction`
- [x] **Back to Studio workspace index** → `/studio`

## E2E coverage

- [`apps/oshun/web/e2e/studio-aja-cleanup-lane-consoles.spec.ts`](../../../../apps/oshun/web/e2e/studio-aja-cleanup-lane-consoles.spec.ts)
  covers signed-in shell render, ready segment-mass catalog (`22` joints, total
  mass `1.020`), invalid-pose client guard with no `POST`, real BFF
  mass-weighted COM output (`(8.0000, 0.0000, 0.0000)` for Hips + Head),
  route-map count, exact quick-action hrefs, 44 px submit target, loading /
  unauthorized / malformed-catalog fail-closed states, mobile no-overflow, and
  direct BFF auth/schema/happy-path gates.

## Data & contracts

- **Reads**: `GET /v1/admin/aja/physics-cleanup` (catalog: `entries`,
  `totalMass`, `fallbackMass`) on mount via `buildBffAuthHeaders()`,
  `cache: 'no-store'`
- **Writes**: `POST …/center-of-mass` → `{ com }` (frameCount, trajectory)
- **Realtime**: none
- **Caching**: client fetch on mount (no-store); SSR shell only
- **Auth**: BFF endpoints admin-scoped + fail-closed (401/403 → unauthorized
  render); the route is signed-in + studio (proxy gate)

## Cross-references

- Parent: [`../../studio-overview.md`](../../studio-overview.md)
- Component sources:
  - `apps/oshun/web/src/components/studio/StudioAjaPhysicsCleanupWorkspace.tsx`
  - `apps/oshun/web/src/components/studio/StudioAjaPhysicsCleanupRouteMap.ts`
- Sibling from quick-actions: `/studio/aja/foot-sliding-correction`

## Known downstream boundaries

- Route-map sub-routes are descriptive contracts; implementation status of those
  child pages is tracked separately from this leaf console.
- Studio entitlement / proxy policy remains a shell-auth boundary outside this
  lane console.
