---
path: /studio/hathor/narrative-structure-analysis
surface: studio
domain: hathor
auth: signed-in + studio entitlement
source: apps/oshun/web/src/app/studio/hathor/narrative-structure-analysis/page.tsx
status: walked
last_walked:
  '2026-07-04 focused real-dev-infra Playwright route walk — anonymous redirect,
  Hathor-admin Ink/Yarn/JSON catalog load, browser bearer propagation, exact
  seeded EMPTY_CHOICE, complete dialogue, NO_ENTRY_NODE, and CYCLE_DETECTED
  validation paths through the real BFF, client JSON/object validation, BFF
  malformed-node detail surfacing, malformed result/catalog fail-closed states,
  loading / 503 / non-admin / transport states, pending-submit lockout,
  route-map and quick-action contracts, mobile no-overflow / 44px targets,
  scoped axe, and direct BFF auth/schema gates. Evidence:
  apps/oshun/web/e2e/studio-hathor-narrative-structure-analysis.spec.ts and
  WALKTHROUGH/results/v1-real-infra-run-2026-06-22.md#280-2026-07-04-studio-hathor-narrative-structure-analysis-real-bff-coverage'
---

# Studio Hathor · Narrative Structure Analysis

## Purpose

Admin lane console for the `@hathor/narrative` export validators. The single
validate lane submits a dialogue tree and reports, per export format (Ink / Yarn
/ JSON), the structural blockers — a missing entry node, empty choice nodes
(Ink), reference cycles (Yarn) — so a designer can fix issues before exporting.
Admin-scoped and fail-closed.

## Entry points

- **Direct URL / bookmark** — `/studio/hathor/narrative-structure-analysis`;
  `alternates.canonical` is set.
- **Quick-action from siblings** — this page links to the Chronicle Parser lane.
- **Studio overview** — see
  [`../../studio-overview.md`](../../studio-overview.md).

## Layout regions

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

- **Workspace** (`StudioHathorNarrativeStructureAnalysisWorkspace`,
  `data-hathor-narrative-structure-analysis-workspace`):
  - `<h1>` `WorkspaceHeading` — "Hathor Narrative Structure Analysis Workspace"
  - Summary `<p data-hathor-narrative-structure-analysis-summary>`
  - The catalog state, then the dialogue form + per-format result list.
- **Route Map panel**
  (`<section data-hathor-narrative-structure-analysis-route-map>`,
  `<h2>Route Map</h2>`): 5 entries from
  `STUDIO_HATHOR_NARRATIVE_STRUCTURE_ANALYSIS_ROUTE_MAP` (path + purpose), with
  `data-hathor-nsa-route-count` and per-entry `data-route-path`.
- **Quick-action lane** `data-hathor-nsa-quick-actions`: Chronicle Parser, Back
  to Studio workspace index.

## States

- [x] **Loading** — `<p data-hathor-nsa-loading>` "Loading structure analyzer…";
      Playwright holds the catalog request before releasing it to a 503.
- [x] **Unauthorized** — `data-hathor-nsa-unauthorized` on 401/403
      (admin-scope), verified with a non-admin browser bearer forwarded to the
      real BFF.
- [x] **Error** — `data-hathor-nsa-error` on a non-OK catalog response,
      malformed catalog response, or network failure.
- [x] **Ready (form)** — `data-hathor-nsa-validate-form` exposes
      `data-hathor-nsa-form-state="idle"` and `aria-busy="false"` with the
      seeded dialogue textarea.
- [x] **Pending** — `data-hathor-nsa-form-state="pending"`, disabled
      textarea/button, `aria-busy="true"`, and button text "Analyzing…" while
      the POST is held.
- [x] **Result** — `data-hathor-nsa-format-list` of
      `data-hathor-nsa-format-item` rows, one per export format, with
      `data-format`, `data-warning-count`, and `data-warning-codes`, verified
      for EMPTY_CHOICE, all-ready, NO_ENTRY_NODE, and CYCLE_DETECTED outputs.
- [x] **Validation error** — `data-hathor-nsa-validate-error` for malformed
      JSON, non-object JSON, BFF invalid-dialogue detail, malformed 200 result,
      and transport failure.

## Interactions

- [x] **Catalog render** — `data-hathor-nsa-catalog` and
      `data-hathor-nsa-catalog-format` expose the Ink / Yarn / JSON formats
      returned by the real BFF.
- [x] **`data-hathor-nsa-dialogue`** (textarea, `aria-label="dialogue json"`) —
      edit the dialogue tree JSON
      (`{ entryNodeId?, nodes:[{ id, type, choices?:[{ targetNodeId }] }] }`);
      disabled during pending submit, 44px minimum target, and mobile
      no-overflow verified.
- [x] **`data-hathor-nsa-validate-submit`** ("Analyze export readiness") —
      parses the JSON and POSTs `{ dialogue }`; browser auth header and request
      body are captured while the same-origin call is forwarded to the real
      local BFF.
- [x] **Route Map entries** — verified against
      `STUDIO_HATHOR_NARRATIVE_STRUCTURE_ANALYSIS_ROUTE_MAP` (5 entries) by
      `data-hathor-nsa-route-count` and per-entry `data-route-path`.
- [x] **Quick-action links** — Chronicle Parser
      (`/studio/hathor/chronicle-parser`), Back to Studio (`/studio`), verified
      by `data-hathor-nsa-quick-action`.

## Data & contracts

- **Reads**: `GET /v1/admin/hathor/narrative-structure-analysis` (catalog:
  `formats`).
- **Writes**: `POST /v1/admin/hathor/narrative-structure-analysis/validate` with
  `{ dialogue }`.
- **Realtime**: none.
- **Caching**: client fetch on mount, `cache: 'no-store'`,
  `buildBffAuthHeaders()`, `AbortController` on unmount.
- **Auth**: admin-scoped, fail-closed (401/403 → unauthorized); route is behind
  the signed-in + studio proxy gate.
- **Real-infra E2E**:
  `apps/oshun/web/e2e/studio-hathor-narrative-structure-analysis.spec.ts`
  forwards browser catalog/validation calls to the real local BFF and separately
  asserts direct BFF unauthenticated, non-admin, invalid-dialogue, complete,
  missing-entry, empty-choice, and self-cycle gates.

## Cross-references

- Parent: [`../../studio-overview.md`](../../studio-overview.md)
- Component sources:
  - `apps/oshun/web/src/components/studio/StudioHathorNarrativeStructureAnalysisWorkspace.tsx`
  - `apps/oshun/web/src/components/studio/StudioHathorNarrativeStructureAnalysisRouteMap.ts`
- Real-infra Playwright:
  `apps/oshun/web/e2e/studio-hathor-narrative-structure-analysis.spec.ts`
- Siblings:
  [`./studio-hathor-chronicle-parser.md`](./studio-hathor-chronicle-parser.md),
  [`./studio-hathor-narrative-export.md`](./studio-hathor-narrative-export.md),
  [`./studio-hathor-dialogue-tree-authoring.md`](./studio-hathor-dialogue-tree-authoring.md)

## Open questions / known gaps

- [ ] Hathor is `unconfirmed-v1` per `WALKTHROUGH/matrix/routes.csv`; confirm
      whether the dedicated `/studio/hathor/*` admin lanes ship V1 or are
      internal-only.
