---
path: /studio/commenting-annotation-system
surface: studio
domain: collaboration
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/commenting-annotation-system/page.tsx
status: walked
last_walked:
  '2026-06-30 comment-threads real-BFF addendum — Playwright now covers the
  admin-scoped route render, real comment-thread catalog GET, default comments
  analyze POST/result, parent-chain depth semantics, repeated-mention dedupe,
  orphan detection, thread-resolution summary, quick-action targets, catalog
  loading/error state, malformed JSON client block, live BFF 400 detail,
  non-admin fail-closed, and anonymous redirect-before-render. Evidence:
  WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md "Studio commenting and
  annotation coverage"; spec:
  apps/oshun/web/e2e/studio-commenting-annotation-system.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'
---

# Studio · Commenting and Annotation System

## Purpose

Operate the commenting and annotation system as a live, admin-scoped BFF
console. The workspace (`StudioCommentingAnnotationSystemWorkspace`) wires a
single **Comment Thread Lane** to the real comment-thread analyzer via
`/v1/admin/studio/comment-threads`: it derives each comment's nesting depth from
the parent chain, extracts `@mention` tokens, detects orphaned comments (missing
parents), and reports thread resolution. This is a real domain computation, not
a simulation.

## Entry points

- **Studio root** (`/studio`) — discoverable as a collaboration workspace
- **Quick-action links** from sibling workspaces (file/media ingestion,
  review/approval, presence, real-time collaboration, activity/change feeds,
  notification center)
- **Direct URL / bookmark** — yes

## Layout regions

`page.tsx` mounts `ShellLayout active="studio"`, renders
`StudioCommentingAnnotationSystemWorkspace`, then a single `panel` containing 6
sibling `quickAction` links. There is no Route Map panel on this page.

- **Shell header** — from `ShellLayout`
- **Workspace `<h1>`** — "Studio Commenting & Annotation System"
  (`WorkspaceHeading`), followed by a `data-commenting-annotation-summary`
  paragraph describing the analysis
- **Comment Thread Lane** (`<h2>` `data-ct-lane-heading` "Comment Thread Lane")
  — the catalog/loading/unauthorized/error states, the analyze form, and the
  result
- **Quick-actions panel** — `panel` with 6 `quickAction` links to sibling
  workspaces (no self-link, no Route Map)

## States

- [x] **Loading** — `data-ct-loading` "Loading comment-thread analyzer…" while
      the GET catalog request is in flight (`outcome === null`)
- [x] **Unauthorized** — `data-ct-unauthorized` "Access restricted." on 401/403
      (admin scope required); shows the BFF message or "Studio admin scope
      required to analyze threads."
- [x] **Error** — `data-ct-error` "Could not load the comment-thread analyzer."
      on any non-OK catalog response or network failure
- [x] **Ready (form)** — catalog loaded; `data-ct-enums` shows mention syntax
      plus `{mentionSyntax}` and `{metrics.length} metrics`, and the
      `data-ct-form` form renders
- [x] **Result** — after a successful POST, `data-ct-result` renders the thread
      headline + per-comment table
- [x] **Analyze validation error** — `data-ct-analyze-error` for invalid JSON,
      network unavailable, or a non-200 POST (shows the POST `detail`)
- [x] **Anonymous user** — redirected to
      `/welcome?redirect=%2Fstudio%2Fcommenting-annotation-system` before the
      workspace root renders

## Interactions

### Comment Thread Lane form

- [x] **Comments** (`textarea` `data-ct-payload`, aria-label `comments json`) —
      JSON `{ comments[{ commentId, parentId, author, body, resolved }] }`;
      seeded with a default payload
- [x] **Analyze threads** (`button` `data-ct-submit`, `type="submit"`) —
      `submitAnalyze` parses the JSON (rejecting invalid JSON with
      `data-ct-analyze-error`) and POSTs to
      `/v1/admin/studio/comment-threads/analyze`
- [x] **Client-side malformed JSON block** — invalid JSON surfaces "Payload must
      be valid JSON." and does not send a POST
- [x] **Live BFF invalid payload branch** — valid JSON with `comments: []`
      reaches the BFF and surfaces detail "comments must be a non-empty array"
- [x] **Parent-chain depth + mention semantics** — an edited payload proves
      depth `0 → 1 → 2`, repeated `@bob @bob` dedupes to one mention, and a
      missing parent renders `data-orphan="true"`

### Result

- [x] **Headline** (`data-ct-headline`) — renders
      `<data-ct-thread-count> threads`, `{resolvedThreadCount} resolved`,
      `<data-ct-orphan-count>`, and `<data-ct-mention-count>`
- [x] **Comments table** (`data-ct-comments`) — one `data-ct-comment-row` per
      comment with `data-comment-id`, `data-depth`, `data-orphan`, plus
      `data-ct-depth` / `data-ct-mentions` cells

### Quick actions

- [x] Open File and Media Ingestion workspace
- [x] Open Review and Approval Workflows workspace
- [x] Back to Presence and Cursor Systems workspace
- [x] Back to Real-Time Collaboration Substrate workspace
- [x] Back to Activity and Change Feeds workspace
- [x] Back to Notification Center workspace

## Data & contracts

- **GET catalog**: `/v1/admin/studio/comment-threads` — fetched on mount with
  `buildBffAuthHeaders()` and `cache: 'no-store'`; returns
  `{ mentionSyntax, metrics[] }`
- **POST verb**: `/v1/admin/studio/comment-threads/analyze` with body
  `{ comments[{ commentId, parentId, author, body, resolved }] }` →
  `{ result: { comments[], summary{ commentCount, threadCount, resolvedThreadCount, orphanCount, totalMentions } } }`
  (200) or a `detail` error
- **Realtime**: none — request/response only
- **Client fetch**: direct `fetch` with `cache: 'no-store'`; no client-side
  caching
- **Auth/role check**: admin-scoped, fail-closed at the BFF (`admin:*` |
  `admin:studio`; 401/403); reached through the signed-in + studio route gate

## Cross-references

- Parent: [`../studio-overview.md`](../studio-overview.md)
- Sibling:
  [`studio-presence-cursor-systems.md`](./studio-presence-cursor-systems.md),
  [`studio-real-time-collaboration-substrate.md`](./studio-real-time-collaboration-substrate.md),
  [`studio-review-approval-workflows.md`](./studio-review-approval-workflows.md)
- Component:
  `apps/oshun/web/src/components/studio/StudioCommentingAnnotationSystemWorkspace.tsx`
- BFF route: `apps/oshun/bff/src/routes/admin-studio-comment-threads.ts`
- BFF store: `apps/oshun/bff/src/studio/comment-thread-store.ts`

## E2E coverage

- [`apps/oshun/web/e2e/studio-commenting-annotation-system.spec.ts`](../../../apps/oshun/web/e2e/studio-commenting-annotation-system.spec.ts)
  — signed-in admin `/studio/commenting-annotation-system` render; real
  comment-thread catalog GET with admin bearer; default comments analyze POST
  through the live BFF; headline summary and `c1`-`c5` depth/mentions/orphan
  rows; edited-payload parent-chain depth, repeated-mention dedupe, and orphan
  proof; six sibling quick-action links; catalog loading/error; client-side
  malformed JSON zero-POST; live BFF 400 invalid-payload detail; non-admin 403
  fail-closed; anonymous redirect-before-render.
- [`apps/oshun/web/e2e/studio-route-render-smoke.spec.ts`](../../../apps/oshun/web/e2e/studio-route-render-smoke.spec.ts)
  — broad Studio route render and accessibility smoke coverage includes this
  route, but does not replace the focused real-BFF comment-thread spec above.

## Open questions / known gaps

- [ ] Confirm where annotations persist (postgres + ts_vector for search?) if
      the lane moves beyond a stateless analyze console
- [ ] Document how `@mention` extraction handles edge cases (punctuation,
      consecutive mentions, unknown users)
- [ ] Live screen-reader and touch-device manual passes remain outside the
      automated route spec
