# Coverage

What's covered by the walkthrough, what's stub, what's deferred. Reflects the
state on the day this file was last updated — for live status, query
[`routes.csv`](./routes.csv).

## At a glance

| Bucket                                              | Count | Walkthrough status         |
| --------------------------------------------------- | ----- | -------------------------- |
| Total `page.tsx` files in `apps/oshun/web/src/app/` | 701   | —                          |
| **In V1 scope**                                     | 692   | **690 walked · 2 drafted** |
| **Out of V1** (V2/V3/V6/V7 prefixes)                | 9     | **9 walked (100%)**        |

> **2026-06-03 reconciliation pass.** An adversarial doc-vs-code audit across
> all 684 per-view files found the studio surface had drifted hard: every studio
> doc claimed `ShellLayout active="explore"` (all 483 pages use
> `active="studio"`), and ~470 studio domain-bridge/core docs described an
> obsolete flow-card/`FLOW_POLICY`/fixture template. The real components are
> live admin-scoped BFF **"Lane" consoles** (`GET /v1/admin/<domain>/<slug>`
> catalog + `POST .../<verb>`). All studio bodies were re-derived from current
> source; customer/operator/shell/journeys docs were reconciled (wired Lilith
> room buttons, real BFF reads, `proxy.ts` not `middleware.ts`, no operator-role
> gate, `/system/*` is anon, scene unlock server action, etc.); the 8
> previously-drafted routes were runtime-probed (Playwright, prod build + mock
> BFF — 12/12 render HTTP 200 with the right `<h1>`, 0 page errors) and promoted
> to walked. CSV is now 684 walked / 0 drafted. See
> `results/walkthrough-runtime-probe-2026-06-03.md`.

> **2026-06-04 comprehensive sweep.** A full executable Playwright probe of
> **all 684 routes** (real per-worker signed-in session, prod build + mock BFF)
> plus a fan-out adversarial doc-vs-code audit of every per-view file +
> `journeys/` + `shell/`. Runtime: **650/684 render cleanly first pass**; the 34
> non-passing were 5 real React #418 hydration mismatches
> (`/domains/nyx/{events,moon,solar}`, `/domains/tara/{analytics,collections}`)
> — **fixed** in app source and re-verified (`/domains` re-probe 55/55, 0 page
> errors) — plus 32 AAA-gated `/studio/isis/*` routes correctly hard-blocking
> under a contemplative session (§24.11, working as designed; content verified
> by the isis doc audit). Doc audit fixed a bounded set of real drift: 2
> fully-stale Tara TTS docs rewritten, 52 route-map off-by-one counts, 4
> `welcome/test-*` auth misclassifications, 3 isis selector errors, and ~20
> smaller endpoint/count/path/terminology corrections across customer, studio,
> operator, journeys, and shell. Probe tool:
> `scripts/walkthrough-probe-all.mjs`. See
> `results/walkthrough-comprehensive-sweep-2026-06-04.md`.

> **2026-07-16 Docs Center reconciliation.** The live app had reached 701
> `page.tsx` routes while `routes.csv` still held 692. Nine routes were absent
> from the matrix; seven also lacked per-view pages. All nine rows are now
> present, the seven missing pages are authored, and the two existing pages
> (`/lilith-studio/release`, `/tenant/invite`) are indexed. A generator unit
> test now compares every tracked `page.tsx` to each Next.js walkthrough matrix
> exactly, so this under-enumeration class fails before rendering.

There is no longer an "unconfirmed-v1" bucket. The 157 Bellona / Hathor / Neith
studio routes that were previously unconfirmed were **confirmed in-v1 on
2026-05-29** by the product owner (see the studio sub-area note below).

The **2026-06-02 coverage-gap sweep** closed 8 routes that recent feature work
had added without a CSV row or per-view file (the count grew 676 → 684): 4 in-v1
(`/nyx/sky-almanac` + `/studio/generation/{curated-cards,music,nyx-3d}`) and 4
out-of-v1 future-version surfaces (`/v6` + `/egbe-studio` for the **V6 Egbe**
domain, `/mawu-studio/{accessibility,localization}` for the **V7 Mawu** domain).
After the sweep the three sets are identical again: 684 app routes = 684 CSV
rows = 684 per-view files.

## Surface breakdown (V1 scope)

| Surface   | Routes | Folder       | Status                     |
| --------- | ------ | ------------ | -------------------------- |
| customer  | 187    | `customer/`  | **186 walked · 1 drafted** |
| studio    | 490    | `studio/`    | **490 walked (100%)**      |
| operator  | 13     | `operator/`  | **12 walked · 1 drafted**  |
| workspace | 2      | `workspace/` | **2 walked (100%)**        |

In-v1 totals only (692). The 9 out-of-v1 routes break down as **6 customer**
(`/v2`×4, `/v3/landing`, `/v6`) and **3 studio** (`/egbe-studio`,
`/mawu-studio/accessibility`, `/mawu-studio/localization`) — see the Out-of-V1
section below. Counting all scopes the surface totals are: customer 193, studio
493, operator 13, workspace 2 = 701.

## Customer domain breakdown

Counts below are the live `domain` tallies from `routes.csv` for
`surface == customer` (187 in-v1 + 6 out-of-v1 = 193 total customer routes).
They match the per-view files one-to-one. The folder column is where the
per-view files live; the CSV `domain` column is the grouping key.

| Domain (CSV)      | Routes | Folder                                  | Notes                                                                                                                          |
| ----------------- | ------ | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| arete             | 25     | `customer/04-arete/`                    | `/arete/*` (incl. `habits`, `habits/new`, `offerings`, `weekly`) + `/domains/arete/*`                                          |
| veritas           | 25     | `customer/05-veritas/`                  | `/veritas/*` (incl. dynamic source profiles) + `/domains/veritas/*`                                                            |
| nyx               | 25     | `customer/06-nyx/`                      | `/nyx` (incl. `events`, `observation`, `tonight`, `sky-almanac`) + `/domains/nyx/*`                                            |
| lilith            | 13     | `customer/10-lilith/`                   | `/lilith`, `/personas`, `/lilith-studio/*` (incl. `release`, `scene/new`, `tara`)                                              |
| nisaba            | 11     | `customer/07-nisaba/`                   | `/nisaba/*` (incl. `notebooks`, `notebook/new`)                                                                                |
| discovery         | 11     | `customer/02-home-discovery/`           | `/explore`, `/search`, `/library*` (incl. `collections`, `collections/new`), `/activity`, `/messages`, `/switcher`, `/events*` |
| tara              | 10     | `customer/03-tara/`                     | `/tara`, `/tara/sit/[id]` + `/domains/tara/*`                                                                                  |
| metis             | 11     | `customer/08-metis/`                    | `/metis/*` plus `/integrity/[verdictId]/appeal`                                                                                |
| account           | 10     | `customer/09-account/`                  | `/profile*`, `/billing*`, and `/settings`                                                                                      |
| onboarding-public | 10     | `customer/00-public/`, `01-onboarding/` | `/landing`, `/welcome*`, `/onboarding`, `/auth/verify-email`                                                                   |
| legal             | 8      | `customer/00-public/`                   | `/legal/*`                                                                                                                     |
| atelier           | 8      | `customer/11-atelier/`                  | `/atelier/*` (incl. `new`, `camera-obscura`)                                                                                   |
| system            | 7      | `customer/13-system/`                   | `/system/*`, `/status`, `/aaa-upgrade`                                                                                         |
| scene             | 3      | `customer/12-scene/`                    | `/scene/*`                                                                                                                     |
| device-shell      | 2      | `customer/02-home-discovery/`           | `/mobile`, `/tablet`                                                                                                           |
| home              | 1      | `customer/02-home-discovery/`           | `/` — the main entry                                                                                                           |
| sophia            | 1      | `customer/14-sophia/`                   | `/sophia` — grounded-only answer surface                                                                                       |
| shell-routing     | 3      | `customer/02-home-discovery/`           | `/assistant`, `/notifications`, and `/d/[domain]/[[...path]]`                                                                  |
| domains-other     | 1      | `customer/02-home-discovery/`           | `/domains/[domainId]` catch-all                                                                                                |
| library           | 1      | `customer/02-home-discovery/`           | `/share/[token]` recipient-side collection resolution                                                                          |
| onboarding-tenant | 1      | `customer/01-onboarding/`               | `/tenant/invite` signed-in tenant-invitation acceptance                                                                        |
| v2-knowledge      | 3      | `customer/00-public/`                   | `/v2/glossary`, `/v2/roadmap`, `/v2/wiki` — **out-of-v1**                                                                      |
| v2-shell          | 1      | `customer/00-public/`                   | `/v2` — **out-of-v1**                                                                                                          |
| v3-marketing      | 1      | `customer/00-public/`                   | `/v3/landing` — **out-of-v1**                                                                                                  |
| v6-steward        | 1      | `customer/00-public/`                   | `/v6` — Egbe Steward web app (V6 arc) — **out-of-v1**                                                                          |

**Account data-rights real-infra route journey (2026-06-25):** `/profile/data`
now exercises all three read lanes against authenticated dev BFF routes:
`/v1/data-rights/consent` is a real `customerConsentStateStore` projection
instead of a domain-stub fixture, while exports/deletions continue to use the
canonical stores. `profile-data-readback.spec.ts` covers consent transition
reflection, empty export/deletion state, seeded completed export and scheduled
deletion snapshots, anonymous redirect gating, the 50-row export cap, download
aria labeling, mobile 44 px controls/no horizontal overflow, and the shared axe
gate.

**Account persona voice real-infra route journey (2026-06-25):**
`/profile/persona` now consumes the real registry-derived `/v1/persona/voice`
contract instead of the stale fixture shape. The BFF projects voice-profile
metadata (`providerId`, `engineId`, `voiceProfileId`, locales,
watermark/disclosure requirements) and explicitly returns `previewUrl: null`
until preview media is a real registry asset. `profile-persona-readback.spec.ts`
covers no-consent empty state, real voice-consent grant, real persona selection
→ active voice readback, metadata/card rendering, anonymous redirect gating,
Data Rights handoff, mobile 44 px controls/no horizontal overflow, and the
shared axe gate.

**Account notifications real-projection route journey (2026-06-30):**
`/profile/notifications` now reads an authenticated `/v1/profile/notifications`
projection from the customer profile store, notification-preferences store, and
Telegram link store instead of the old guarded fixture.
`profile-notifications-index.spec.ts` plants the real access token for the
server-rendered BFF read, asserts the live summary and profile email, flips
`notifications.pushEnabled` through real `PATCH /v1/preferences` and verifies
the Push channel disables on reload, covers invalid-bearer fail-closed empty
copy, and retains footer, mobile, standalone-PWA, telemetry, anonymous-gate, and
real-service-worker offline replay coverage. BFF coverage in
`notifications-preferences-route.test.ts` proves auth gating and store-backed
projection.

**Account settings direct-route profile projection (2026-06-30):** `/settings`
now renders domain statistics and connected-service rows from the authenticated
profile projection instead of component-local demo arrays. `/v1/profile`
projects calendar services from `calendarOAuthConnectionStore` and notification
channels from `channelBindingsStore`, while the settings rail routes service
actions into `/profile?path=calendar` / `/profile?path=notifications` and domain
management into `/domains/<id>?origin=profile`. `profile-settings-flows.spec.ts`
seeds a verified channel through the real BFF channel-binding round trip,
asserts the projected connected state, and drives the service/domain management
navigations from direct `/settings`.

**Account Telegram live linked-state polling (2026-06-30):** `/profile/telegram`
now keeps the not-linked card live after the user opens the Telegram deep link.
The client state panel polls the authenticated `/v1/telegram/link` BFF read
while the page remains open and repaints to the linked card as soon as the real
`/telegram/webhook` `/start link-<nonce>` path completes the nonce.
`profile-telegram-bridge.spec.ts` verifies the browser stays on the same
`/profile/telegram` URL, the card moves from
`data-profile-telegram-live-status="watching"` to `"linked"`, and no generic
fallback token or reload is needed.

**Account memory BFF retry state (2026-06-30):** `/profile/memory` now
distinguishes an empty Iris review from an unavailable BFF read. A transient
review/consent failure keeps cached rows visible, renders
`data-profile-memory-bff-status` with a Retry Iris read action, and retries
against the live `/v1/iris/adapter/review` BFF path. The focused
`memory-edit-pause-forget.spec.ts` failure-mode leg proves cached-row
preservation, visible retry copy, and alert dismissal after the real BFF retry
succeeds.

## Studio sub-area breakdown

| Sub-area                 | Routes | Notes                                                                                                                          |
| ------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------ |
| aja                      | 98     | Studio bridge for Aja (embodied instr.)                                                                                        |
| isis                     | 88     | Governed generation control plane                                                                                              |
| yemaya                   | 79     | Rendering substrate bridge                                                                                                     |
| concordia-workbench      | 12     | Cross-domain editorial workbench                                                                                               |
| bellona                  | 82     | **In V1** (confirmed 2026-05-29; not yet in features.md)                                                                       |
| hathor                   | 74     | **In V1** (confirmed 2026-05-29; not yet in features.md)                                                                       |
| neith                    | 1      | **In V1** (confirmed 2026-05-29; not yet in features.md)                                                                       |
| tara                     | 2      |                                                                                                                                |
| generation               | 6      | `living-scene`, `generation-gallery`, `asset-preview-pipeline`, + `curated-cards`, `music`, `nyx-3d` (last 3 added 2026-06-02) |
| egbe (V6)                | 1      | `/egbe-studio` — **out-of-v1** V6 creator suite (added 2026-06-02)                                                             |
| mawu (V7)                | 2      | `/mawu-studio/{accessibility,localization}` — **out-of-v1** V7 (added 2026-06-02)                                              |
| (other studio sub-areas) | ~27    | One route each: design-language, color-system, typography, navigation-commands, etc.                                           |

Routes under `bellona`, `hathor`, `neith` were **confirmed in-v1 by the product
owner on 2026-05-29** and flipped from `unconfirmed-v1` → `in-v1` in
`routes.csv`. The corresponding domains do **not yet** appear in
`V1/features.md`'s "Customer-facing domains", "Platform substrates", or
"Cross-domain support" lists — that spec should be updated to name Bellona
(engine bridges / build pipeline), Hathor (narrative / world / lore), and Neith
(inverse modeling) so the feature map matches the confirmed route scope.

## Out-of-V1 (documented for completeness)

| Path prefix           | Routes | Folder                                         | Status               |
| --------------------- | ------ | ---------------------------------------------- | -------------------- |
| `/v2*`                | 4      | `customer/00-public/v2*.md`                    | **4 drafted (100%)** |
| `/v3*`                | 1      | `customer/00-public/v3-landing.md`             | **1 drafted (100%)** |
| `/v4*`                | 0      | (no routes under `apps/oshun/web/src/app/v4/`) | n/a                  |
| `/v6` (V6)            | 1      | `customer/00-public/v6.md`                     | **1 drafted (100%)** |
| `/egbe-studio` (V6)   | 1      | `studio/future/egbe-studio.md`                 | **1 drafted (100%)** |
| `/mawu-studio/*` (V7) | 2      | `studio/future/mawu-studio-*.md`               | **2 drafted (100%)** |

Routes under `/v2` and `/v3` are real, anon-readable surfaces that ship with V1
builds even though they are out of the V1 feature map. They are drafted in
`customer/00-public/` with `v1_scope: out-of-v1` declared in each frontmatter,
so the V1 audit scope remains explicit while the walkthrough surface stays
exhaustive.

The **V6/V7 future-version surfaces** (added in the 2026-06-02 sweep) follow the
same `v1_scope: out-of-v1` convention but are **signed-in** (not in
`PUBLIC_PATHS`, unlike anon `/v2`–`/v3`). `/v6` is the customer-facing **Egbe
Steward** web app (companion to the V6 mobile Steward App). `/egbe-studio` is
the V6 Egbe creator suite and `/mawu-studio/*` are the V7 Mawu studio surfaces;
both are `ShellLayout active="studio"` surfaces filed under a new
`studio/future/` folder (they live at top-level routes, not under `/studio/*`,
so they are classified `surface: studio` by their shell role rather than their
URL prefix). The Egbe domain (V6) and Mawu domain (V7) specs live at `V6/` and
`V7/`.

If `apps/oshun/web/src/app/v4/`, `/v5/`, or further version prefixes ever gain
routes, add them with the same `v1_scope: out-of-v1` flag — customer surfaces in
`customer/00-public/`, studio surfaces in `studio/future/`.

## Method

`routes.csv` was generated from `find apps/oshun/web/src/app -name page.tsx`
filtered and classified by:

- `route` — derived from the file path
- `v1_scope` — `out-of-v1` if the route is a future-version surface; otherwise
  `in-v1`. Future-version surfaces are identified by a `/vN` URL prefix (`/v2`,
  `/v3`, `/v6`, …) **or** by belonging to a post-V1 domain even when the URL is
  unprefixed — `/egbe-studio` (V6 Egbe domain) and `/mawu-studio/*` (V7 Mawu
  domain) are `out-of-v1` despite not starting with `/vN`. (Bellona / Hathor /
  Neith studio sub-areas were initially `unconfirmed-v1` because they weren't in
  `V1/features.md`; the product owner confirmed them in-v1 on 2026-05-29, so the
  `unconfirmed-v1` value is now retired and unused.)
- `surface` — `studio` / `operator` / `workspace` / `customer`, by URL prefix
  where one applies, else by the route's `ShellLayout active=` role (so the
  top-level `/egbe-studio` and `/mawu-studio/*` are `surface: studio` because
  they render `ShellLayout active="studio"`).
- `domain` — best-effort match against domain names and route grouping

If the classification is wrong, edit the CSV directly. The script that produced
it (`/tmp/classify-routes.py` from the inventory step) is non-authoritative —
the CSV is the truth.

## Status legend (for `status` column)

- `stub` — no walkthrough file written yet
- `drafted` — content written from code reading; not verified live
- `walked` — verified live against the running app on a known commit
- `stale` — code under `Source:` changed since `Last walked`

## What's done so far

**Scaffold + shell (session 1, 2026-05-24):**

- [x] `shell/01-app-shell.md` through `shell/06-keyboard-a11y.md` (6 docs)
- [x] One example per surface: `customer/02-home-discovery/home.md`,
      `customer/03-tara/tara.md`, `studio/studio-overview.md`,
      `operator/operator-overview.md`
- [x] One example journey: `journeys/install-as-pwa.md`

**Customer surface sweep (session 2, 2026-05-24):** all 147 customer routes
drafted (5 parallel agents). Coverage per folder:

- [x] `customer/00-public/` — 16 files (landing, welcome×7, legal×8)
- [x] `customer/01-onboarding/` — 1 file (`/onboarding`)
- [x] `customer/02-home-discovery/` — 12 files (home + explore + search +
      library + activity + messages + switcher + events + mobile + tablet +
      d-domain-path + domains-domainId)
- [x] `customer/03-tara/` — 9 files (tara + 8 `/domains/tara/*`)
- [x] `customer/04-arete/` — 21 files (9 polished + 12 namespace alternates)
- [x] `customer/05-veritas/` — 23 files (9 polished + 14 namespace alternates)
- [x] `customer/06-nyx/` — 21 files (1 hub + 20 `/domains/nyx/*`)
- [x] `customer/07-nisaba/` — 9 files
- [x] `customer/08-metis/` — 5 files
- [x] `customer/09-account/` — 4 files (profile + memory + safety +
      billing/crypto)
- [x] `customer/10-lilith/` — 9 files (lilith showcase + lilith-studio×8)
- [x] `customer/11-atelier/` — 6 files
- [x] `customer/12-scene/` — 3 files (scene + embed + report)
- [x] `customer/13-system/` — 7 files (system×5 + status + aaa-upgrade)

**Studio surface sweep (session 3, 2026-05-24):** all 325 remaining studio in-v1
routes drafted (7 parallel agents). Coverage per folder:

- [x] `studio/domain-bridges/aja/` — 98 files
- [x] `studio/domain-bridges/isis/` — 88 files (16 AAA-gated per
      `AAA_ONLY_STUDIO_ROUTES`)
- [x] `studio/domain-bridges/yemaya/` — 79 files (38 first-half + 40
      second-half; 1 genuinely-deep surface at `remote-actor-home-capture`, 1566
      LOC / 93 panels)
- [x] `studio/domain-bridges/tara/` — 2 files (tts-voice-consent +
      tts-voice-contract)
- [x] `studio/collaboration/concordia-workbench/` — 12 files (root + 11 case
      sub-surfaces; all share one workspace component dispatched via
      `initialSurface` prop)
- [x] `studio/collaboration/` — 6 files (presence, comments, realtime, reviews,
      notifications, activity-change-feeds)
- [x] `studio/design/` — 6 files (design-language, color-system, typography,
      spacing-layout, component-primitives, complex-interactions)
- [x] `studio/governance/` — 10 files (rbac, audit, retention, launch readiness,
      tenant isolation, security hardening, authentication, a11y governance,
      experimentation, i18n)
- [x] `studio/operations/` — 10 files (observability, perf budgets, backup,
      background jobs, resilience, quality, adoption, metrics, api-gateway-bff,
      sdk docs)
- [x] `studio/authoring/` — 11 files (authoring, compose, navigation, search,
      ingestion, multi-project, workspace switching, project obsidian,
      session/device, webhooks, cross-domain entity model)
- [x] `studio/generation/` — 3 files (generation, generation-gallery,
      asset-preview-pipeline)

**Operator surface sweep (session 4, 2026-05-24):** 5 remaining operator routes
drafted (orchestrator wrote inline; small enough to skip agents).

- [x] `operator/operator-admin.md` — `/operator/admin` (admin inbox: incidents,
      citation drift, tenant requests, support routing)
- [x] `operator/operator-admin-isis-provenance.md` —
      `/operator/admin/isis/provenance` (hash-chain ledger inspector +
      generated-artifact provenance)
- [x] `operator/operator-metis.md` — `/operator/metis` (institutional dashboard:
      lesson review queue, OneRoster sync, tutor telemetry, Themis flags)
- [x] `operator/operator-studio.md` — `/operator/studio` (editorial review queue
      and approval workspace)
- [x] `operator/operator-tenant.md` — `/operator/tenant` (tenant console:
      members, plans, sittings, last seen)

**Workspace surface sweep (session 5, 2026-05-24):** 2 remaining workspace
routes drafted (orchestrator wrote inline).

- [x] `workspace/workspace-catchall.md` — `/(workspace)/workspace/[[...path]]`
      (`MultiPanelWorkspace` — tabs / panels / side panel / search / content
      export / Iris mobile handoff; ~800+ LOC component)
- [x] `workspace/app-surface-catchall.md` — `/app/[surface]/[[...path]]`
      (server-redirect alias; maps
      `home|explore|activity|library|profile|search→explore` to canonical shell
      routes; everything else → `notFound()`)

**Unconfirmed-v1 studio sweep (session 6, 2026-05-24):** all 157 unconfirmed-v1
routes drafted (4 parallel agents).

- [x] `studio/domain-bridges/bellona/` — 82 files (41 + 41 alphabetical split).
      **Bellona has its own polycentric backbone**:
      `StudioBellonaBridgeProtocolAndSessionsWorkspace` (~4000 LOC),
      `StudioBellonaBlenderBridgeCommandsWorkspace`,
      `StudioBellonaBuildJobAuthoringWorkspace`, etc.; no
      Hathor-Economy-Modeling embed.
- [x] `studio/domain-bridges/hathor/` — 74 files (37 + 37).
      `StudioHathorEconomyModelingWorkspace` (~2756 LOC) is mounted natively at
      `/studio/hathor/economy-modeling` and embedded across ~265 confirmed-V1
      studio routes.
- [x] `studio/domain-bridges/neith/` — 1 file
      (`/studio/neith/inverse-modeling`). `StudioNeithInverseModelingWorkspace`
      has actual computed logic (RGBA reference-image feature extraction,
      terrain/vegetation/urban/noise parameter estimation, confidence scoring,
      export-manifest generation, plus real-BFF fit-quality evaluation).

**Full coverage: 701 / 701 (100%) — every page.tsx in apps/oshun/web/src/app has
a drafted walkthrough, including the 9 out-of-V1 surfaces (V2 / V3 closed out by
the 2026-05-26 audit sweep; the V6 / V7 future surfaces closed out by the
2026-06-02 sweep) and `/tara/sit/[id]` (closed out by the 2026-05-27 audit
sweep). The count was 676 through 2026-05-29; the 2026-06-02 sweep added 8
routes recent feature work had introduced (see "At a glance" and the session-9
entry below).**

**Coverage-gap audit sweep (session 8, 2026-05-29):** a route-inventory diff
(`find apps/oshun/web/src/app -name page.tsx` vs `routes.csv` vs per-view
`path:` frontmatter) surfaced **32 real V1 routes that had no CSV row and no
per-view file** — they had been missed by the original sweeps. All 32 were
authored from the live code (6 parallel agents), added to `routes.csv`, and
verified to exist with substantive pages. After this sweep the three sets are
identical: 676 app routes = 676 CSV rows = 676 per-view files, zero gaps in
either direction. The 32 closed routes:

- [x] **arete (4):** `/arete/habits`, `/arete/habits/new`, `/arete/offerings`,
      `/arete/weekly` (last is a 308 redirect to `/arete/review`)
- [x] **metis (5):** `/metis/courses/new`, `/metis/ingest`, `/metis/lessons`,
      `/metis/session`, `/metis/upload` (last is a query-preserving 308 redirect
      to `/metis/byom`)
- [x] **nyx (3):** `/nyx/events`, `/nyx/observation`, `/nyx/tonight`
- [x] **nisaba (2):** `/nisaba/notebooks`, `/nisaba/notebook/new`
- [x] **account (5):** `/billing`, `/profile/data`, `/profile/notifications`,
      `/profile/persona`, `/profile/telegram`
- [x] **atelier (2):** `/atelier/new`, `/atelier/camera-obscura`
- [x] **lilith (2):** `/lilith-studio/scene/new`, `/lilith-studio/tara`
- [x] **veritas (1):** `/veritas/evidence`
- [x] **sophia (1):** `/sophia` — new `customer/14-sophia/` folder (first
      customer-facing Sophia surface)
- [x] **discovery (3):** `/events`, `/library/collections`,
      `/library/collections/new`
- [x] **operator (4):** `/operator/audit`, `/operator/incidents`,
      `/operator/sso`, `/operator/tenants`

**Coverage-gap audit sweep (session 9, 2026-06-02):** the same route-inventory
diff (`find apps/oshun/web/src/app -name page.tsx` vs `routes.csv` source column
vs per-view `source:` frontmatter) surfaced **8 routes that recent feature work
had added with no CSV row and no per-view file**. All 8 were authored from the
live component code, added to `routes.csv`, and the three sets re-verified
identical (684 = 684 = 684, zero gaps either direction). The 8 closed routes:

- [x] **nyx (1, in-v1):** `/nyx/sky-almanac` — power-user depth page; SSR fetch
      of `/v1/nyx/sky-almanac` (computed by `@oshun/domain-nyx`), honest
      unavailable state with no fabricated astronomy →
      `customer/06-nyx/nyx-sky-almanac.md`
- [x] **studio/generation (3, in-v1):** `/studio/generation/curated-cards`
      (§24.6 six curated cards), `/studio/generation/music` (§24.6/§24.8 music),
      `/studio/generation/nyx-3d` (§24.6/§24.8 3D sky briefing) — all
      fail-closed 503 until a provider is configured →
      `studio/generation/studio-generation-{curated-cards,music,nyx-3d}.md`
- [x] **V6 (2, out-of-v1):** `/v6` (Egbe Steward web app →
      `customer/00-public/v6.md`) and `/egbe-studio` (Egbe creator suite →
      `studio/future/egbe-studio.md`)
- [x] **V7 (2, out-of-v1):** `/mawu-studio/accessibility`,
      `/mawu-studio/localization` (Mawu studio →
      `studio/future/mawu-studio-*.md`)

This added the `studio/future/` folder (out-of-v1 studio surfaces filed by shell
role, since they live at top-level routes rather than under `/studio/*`), the
`v6-steward`, `egbe`, and `mawu` domain keys, and a `generation` studio sub-area
row. The V6 (`egbe`) and V7 (`mawu`) domains should be added to `V1/features.md`
only if/when they are pulled into V1 scope; today they are explicitly
`out-of-v1`.

**Journeys sweep (session 7, 2026-05-24):** 23 cross-view journeys drafted (4
parallel agents) + journey index. Total 24 journey files. See
[`../journeys/README.md`](../journeys/README.md) for the bucket map. Buckets
covered:

- [x] First-time + PWA infrastructure (5): first-time-anonymous-visitor,
      first-tara-sit, install-as-pwa, offline-first-time-use, pwa-update-flow
- [x] Customer domain entries (6): tara-daily-ritual, arete-create-habit,
      veritas-evidence-trail, nyx-tonight-observation, nisaba-scholarly-read,
      metis-lesson-completion
- [x] Cross-domain bridges (4): tara-to-nisaba-handoff, nyx-to-tara-bridge,
      veritas-to-nisaba-deeper, arete-streak-recovery
- [x] Lilith policy (1): crisis-aware-tone-policy
- [x] Operator + studio + cross-surface (6): editorial-review-approval,
      incident-triage, citation-drift-resolution, tenant-onboard,
      user-flag-to-review (blocked), sophia-grounded-answer
- [x] Workspace shell (1): multi-device-workspace-handoff (added to README
      bucket map in the 2026-05-26 audit sweep — file existed but was not
      indexed)
- [x] `journeys/README.md` — bucket map + cross-cutting findings + add-a-journey
      guide

**Profile safety route journey (2026-06-25):** `/profile/safety` is now
walkthrough-documented as a real BFF-backed safety record surface. The
`profile-safety-crisis-recovery` spec signs in a unique member, verifies the
live no-frame empty state, activates a crisis frame through the real operator
BFF route, waits for Redis-worker durable projection, then drives the browser
readback, stillness, re-entry, check-ins, resource visibility, anonymous gate,
and axe pass without mocking `/v1/safety/crisis-frames/mine`. The 2026-06-30
timeline addendum renders the full live BFF `frames[]` projection as an
expandable cross-surface crisis-frame timeline covering assistant, Iris, Lilith
video, Psyche, and Tara markers. The 2026-06-30 resource addendum verifies the
surfaced `us-988` link target and `lilith_safety_resource_opened` telemetry from
the same live safety record.

**Phase 2 architectural decisions (2026-05-24):**

- [x] **P2.1** — `studio` shell tab added; 488 studio routes flipped from
      `active="explore"` → `active="studio"`. Studio now has its own first-class
      sidebar entry, shortcut `6`.
- [x] **P2.2** — 11 admin bypass routes (8 Isis sub-routes + 2 cross-product + 1
      voice-abuse) canonicalized: wrapped in `AdminShell` with session check; 3
      new workspaces (`isis`, `messaging`, `tenant-console`) added to
      `OSHUN_ADMIN_WORKSPACE_MODEL`.
- [x] **P2.3** — Namespace direction resolved as intentional
      consumer-vs-power-user split (see cross-cutting finding #1 below). Spec
      updates: `V1/features.md` per-domain "Surfaces" callouts +
      `V1/ARCHITECTURE.md` Customer Web section now name both namespaces with
      their audiences. No redirects, no route deletions.
- [x] **P2.4** — Customer-side session-to-role wiring shipped (pure helper at
      `lib/customer-role.ts` + server reader at
      `lib/server/customer-session.ts`); `/lilith-studio` page now gates on
      `studio:editorial` scope and renders a denial UI for non-editorial
      visitors.

**Remaining qualitative work:**

- Walking — 699 of 701 files are `status: walked`. The two pages authored from
  code during the 2026-07-16 reconciliation are still `drafted`:
  `/operator/autonomy` and `/veritas/source/[sourceId]`. Their per-view files
  name the exact runtime, mobile, accessibility, and failure-state checks still
  required before promotion.
- V1-scope decisions — RESOLVED 2026-05-29. Bellona / Hathor / Neith were
  confirmed in-v1 by the product owner and flipped from `unconfirmed-v1` →
  `in-v1`. Follow-up: add these three domains to `V1/features.md` so the feature
  map names them (the walkthroughs already document the surfaces).
- Walkability blocked journeys — `first-tara-sit` (step 4, TaraRoom ghost
  button) and `user-flag-to-review` (step 1, no customer flag affordance exists)
  can't currently be walked end-to-end. These are load-bearing for V1 UAT.
- P2.3 follow-up: per-view walkthrough files that framed `/<domain>/*` and
  `/domains/<domain>/*` as "polished vs internal" (vs the now-canonical
  "consumer hub vs power-user deep tools" framing) can be re-read against the
  new spec when each domain is walked live.

## Customer sweep — cross-cutting findings

Surfaced by the parallel agents during the customer sweep. These are issues in
the underlying code that surfaced through the walkthrough, not walkthrough
quality issues; recorded here so the next walker has them in mind.

1. **Two parallel UI namespaces per domain — RESOLVED as intentional audience
   split (P2 Decision 3, 2026-05-24).** `/<domain>/*` is the **consumer hub +
   depth** (Lilith-design-system rooms, presentational, first-read customers).
   `/domains/<domain>/*` is the **power-user deep tools** layer (heavier client
   workspaces, scholars, customer-mode operators, editorial / curation roles).
   Both are V1; not deprecation candidates for each other. Metis and Nisaba do
   not yet ship a `/domains/*` namespace — their deep tools mount inside the
   consumer hub. The canonical contract is in `V1/features.md` and
   `V1/ARCHITECTURE.md` (Customer Web section). Per-view files that previously
   framed one as polished and the other as "internal" or "pre-V1" should be
   re-read against this split; that backlog is tracked but not blocking.
2. **Ghost buttons — placeholder state now honest at the primitive level (P3,
   2026-05-25).** The polished depth surfaces (Arete approve/skip, Veritas
   read-once/re-open, Atelier bake/mix/cast, etc.) still ship action-shaped UI
   without `onClick` handlers — wiring each surface requires new BFF endpoints
   and state stores that are out of scope for one session. As an interim fix,
   `LBtn` in `apps/oshun/web/src/design-system/lilith/primitives.tsx` now
   detects placeholder state (no `onClick`, no `href`) and renders the button
   with `aria-disabled="true"`, `data-placeholder="true"`,
   `cursor: not-allowed`, reduced opacity, and a "No handler wired —
   placeholder" tooltip. Screen readers announce the disabled state; sighted
   users see the dimmed treatment. Future codemods can locate the remaining
   unwired buttons via the `data-placeholder` attribute. Wiring a call site
   automatically removes the placeholder treatment as soon as `onClick` or
   `href` is passed.
3. **Anon-readable test/QA harnesses — GATED (P3, 2026-05-25).** The four
   `/welcome/test-{achievements,assistant,routines,wearable}` harnesses already
   carried `robots: noindex` metadata, but were still rendered to any signed-in
   user in production. Each layout now wraps its children with `TestHarnessGate`
   (`apps/oshun/web/src/components/welcome/TestHarnessGate.tsx`), which calls
   `notFound()` when `NODE_ENV === 'production'` unless an operator explicitly
   sets `OSHUN_ENABLE_TEST_HARNESSES=true`. In non-prod builds the gate renders
   a visible amber "internal use only — SIMULATED\_\*" banner above the harness
   content. Layout metadata also adds `noarchive` + `nosnippet` on top of the
   existing `noindex/nofollow`. 4 tests at `TestHarnessGate.test.tsx` cover the
   dev-build pass-through, the production deny-by-default, the explicit
   override, and the non-literal-`true` reject case (any value other than
   `'true'` is rejected).
4. **Hard-coded literals in production paths — TIGHTENED (P3, 2026-05-25).**
   - `/explore` and `/search` no longer carry a literal `Bearer dev.…` token.
     The header is built via `resolveBffAuthToken()` in
     `apps/oshun/web/src/lib/bff-auth.ts`, which prefers the real session token
     (set by `AuthProvider`) and falls back to the dev token **only** when
     `process.env.NODE_ENV !== 'production'`. Production builds either send the
     real token or omit `Authorization` entirely (the BFF then rejects the
     request) — there is no production code path that emits the dev token.
   - `/domains/veritas/topics/[topicId]` previously routed any unknown `topicId`
     to renewable-energy silently. `getTopicKey()` now returns `null` for
     unknown topicIds and `VeritasTopicHubWorkspace` renders a dedicated
     `VeritasTopicNotFoundPanel` (lists the known hubs: renewable-energy,
     quantum-computing) instead of substituting content. Hub landing
     (`/domains/veritas/topics`, no topicId) still defaults to renewable-energy
     — that is the intentional curated landing view. 3 tests at
     `VeritasTopicHubWorkspace.test.tsx` cover the unknown-id not-found path,
     the Back-button callback, and the no-topicId hub landing.
5. **Scene password leak — FULLY RESOLVED (P1.3 + P3, 2026-05-25).** P1.3
   replaced the GET-with-password URL pattern with a POST server action that
   stored the password in an HttpOnly path-scoped cookie. P3 closes the
   remaining gap: the action now exchanges the password for a short-lived
   BFF-issued unlock token via
   `POST /v1/living-scenes/public/<shortCode>/unlock-token`. The cookie stores
   the **token**, not the password; the scene page sends the token via
   `Authorization: Bearer …` on revalidation; the BFF verifies the HMAC-signed,
   shortCode-scoped, 4h-TTL token without re-reading the password. Token sign /
   verify lives in `apps/oshun/bff/src/living-scenes/scene-unlock-token.ts` with
   7 unit tests, the route is exercised by the existing living-scenes route
   suite (one new integration case covering wrong-password rejection, token
   mint, token revalidation, and cross-scene token rejection). The embed
   endpoint still calls `fetchPublicLivingScene` without an unlock token —
   password-protected scenes deliberately surface a retired tile in embed.
6. **`LCustomerNav active` inconsistency — RESOLVED (P3, 2026-05-25).** The
   original concern (Veritas hub mounted `active="explore"` while depth views
   mounted `active="library"`) is gone: the Veritas hub (`/veritas/page.tsx`) no
   longer uses `LCustomerNav` at all — it renders `VeritasRoom` directly. The
   remaining `LCustomerNav` usages in the Veritas family (`/veritas/mobile`,
   `components/lilith/veritas.tsx`) both declare `active="library"`, so the
   active state is now consistent across the surface. A grep across the codebase
   shows the only `LCustomerNav active="explore"` consumers are the V2 shell
   surfaces (`V2ShellSurface`, `V2KnowledgeSurface`), which is correct — V2 is
   the knowledge/explore-anchored shell.
7. **Two observation-log routes — RESOLVED via H1 disambiguation + cross-link
   (P3, 2026-05-25).** `/domains/nyx/observation-log` is the canonical recording
   / management surface (six tabs incl. New Entry, Equipment, Conditions) and
   now reads `Observation Log · session list`.
   `/domains/nyx/observation-log-deep` is the read-side analytics complement
   (five view modes incl. calendar, map, equipment-grouped) and now reads
   `Observation Log · analytic views`. Both subtitles cross-link to the other so
   the IA split is visible from either entry point. No route merger needed — the
   surfaces have distinct purposes.
8. **Lilith Studio role gating — RESOLVED at the route level (P3, 2026-05-25).**
   `/lilith-studio` and the seven authoring sub-routes (`scenes`,
   `avatar-costume`, `personas`, `music`, `asana`, `provenance`, `concerts`) are
   now gated through `apps/oshun/web/src/app/lilith-studio/layout.tsx`, which
   reads the customer session, calls `deriveCustomerRoleFromScopes` /
   `hasLilithStudioAccess`, and substitutes `LilithStudioAccessDenied` for the
   authoring shell when access is missing. Prior to this fix only the root page
   was gated; the seven sub-routes mounted their editors to any signed-in
   customer. `data-v1-editorial-role` remains as a visual attribute for UI
   styling but no longer carries the access decision. The BFF is still the
   authoritative enforcement boundary on the data path; this layout closes the
   client-visible leak.
9. **Coach BFF endpoint shipped — framework selector now honoured (P3 follow-up,
   2026-05-25).** `/domains/arete/coach` no longer composes responses inline.
   The keyword router + template registry moved to
   `apps/oshun/bff/src/arete/coach-responses.ts` and is exposed via
   `POST /v1/arete/coach/responses`. The framework selector (CBT / ACT / Stoic /
   Reflective / general) is now a real input parameter — the composer returns
   framework-specific responses for the same prompt (CBT separates
   situation/thought/feeling; Stoic invokes the dichotomy of control; ACT pivots
   on values; etc.). The customer maps its `CoachMode` to the BFF framework,
   with `reflection → reflective` and the conversation-scoping modes (`goals`,
   `habits`, `motivation`) falling back to `general`. A local-fallback template
   preserves the coach's response if the BFF call drops, so the customer never
   sees a blank reply. The Sophia-grounded retrieval-augmented composer is the
   next swap behind the same `POST /v1/arete/coach/responses` contract.
10. **Nyx `/domains/nyx/renderer` and `/domains/nyx/widgets` — GATED AS OPERATOR
    PREVIEWS (P3, 2026-05-25).** Both routes render substantive interactive
    components (`NyxSkyRenderer` ~1809 LOC, `NyxDashboardWidgets` ~1262 LOC) but
    have **zero inbound links** from any customer surface — they are orphan
    specimen pages. Each route now has a `layout.tsx` wrapping its children with
    `OperatorPreviewSurfaceGate` (calls `notFound()` in production unless
    `OSHUN_ENABLE_OPERATOR_PREVIEWS=true`; in non-prod renders a teal "preview
    surface — no customer entrypoint" banner). Layout metadata adds `noindex` +
    `nofollow` + `noarchive` + `nosnippet`. 4 tests at
    `OperatorPreviewSurfaceGate.test.tsx` cover the dev-build pass-through,
    production deny-by-default, explicit override, and non-literal-`true`
    reject. The walkthrough split into primitives vs surfaces is no longer
    necessary; the gate marks these explicitly out-of-customer-scope at the
    route level.

## Studio sweep — cross-cutting findings

Surfaced by the 7 parallel agents during the studio sweep. Same caveat: these
are code-state findings, not walkthrough quality issues. Several are
load-bearing for release planning.

1. **`StudioHathorEconomyModelingWorkspace` backbone — IA contract codified via
   lane card (P3, 2026-05-25).** 192 sibling wrapper components plus 44 Hathor
   wrappers previously each mounted the canonical ~2,756-LOC Economy Modeling
   workspace under a route-specific H1, so a single page render instantiated the
   same workspace 4–7 times with independent client state. All 236 sibling
   embeds now mount a thin `StudioHathorEconomyModelingLaneCard` (capability
   summary + link to `/studio/hathor/economy-modeling`). The canonical workspace
   renders only at its own page, ending the duplicate-mount pattern.
   Route-specific concerns (subject identity, LoRA epoch sliders, mesh topology,
   retention TTL, voice picker, asset marketplace UI, character variants, CRDT
   replicas) remain to be authored per-wrapper as separate work; the lane card
   unblocks that authoring by removing the misleading "the workspace is already
   wired here" appearance.
2. **Composite routes Hathor instances — collapsed by lane card (P3,
   2026-05-25).** The transitive composition that mounted ~15+ Hathor instances
   on `/studio/isis/workflows` (via `workflows` → `workflow- registry` →
   `output-registry` → 5 lanes...) no longer compounds — each layer now mounts
   the lane card, so a single workspace ever renders the canonical Economy
   Modeling surface. Bundle size and hydration cost drop accordingly; duplicate
   a11y controls on the canonical surface are no longer mirrored across the
   page.
3. **AAA gate leaks via embedding — PLUGGED (P3, 2026-05-25).** The route-level
   middleware in `libs/isis/entitlements/src/studio-boundary.ts` gates direct
   navigation to AAA-only routes, but cannot see inside a non-AAA hub that
   embeds the same AAA workspace component as a lane.
   `<AaaGate routeSegment="…">` wraps each leak site and applies the same tier
   check that the middleware applies to the dedicated route. After this sweep:
   - Four sites already wrapped pre-existing `gpu-worker` embeds:
     `StudioIsisJobEnvelopeWorkspace`, `StudioIsisWorkflowRegistryWorkspace`,
     `StudioIsisWebWorkspace`, `StudioIsisOutputRegistryWorkspace`.
   - **`StudioIsisAiVideoWorkspace` now wraps both `animatediff-lightning` and
     `rife-interpolation`** (the remaining unprotected embeds found via a
     directed scan of `AAA_ONLY_STUDIO_ROUTES` workspace components against
     their non-AAA-route embed sites).
   - Test infrastructure: `src/__tests__/setup.tsx` now mocks `server-only`,
     `next/headers`, `@/lib/server/studio-entitlement` (defaulting tests to
     `aaa-creator` tier), and the `@/components/studio/AaaGate` component
     (passes children through synchronously). The earlier import failures
     blocked all 5 sites' tests from running; they now pass.
   - Embeds within AAA-only parent components (e.g.,
     `StudioIsisComfyuiNodesWorkspace` embedding `Florence2`,
     `StudioIsisComfyuiSdkWorkspace` embedding `ComfyuiNodes`) are deliberately
     not wrapped — the parent route is already gated, so the child cannot be
     reached without AAA tier.
   - `comfyui-integration` (mentioned in the original finding) does not
     currently import any AAA-only workspace component; the prior lane-card
     sweep already replaced its inline embed with a navigation link.
4. **Aja workspace pattern lattice — duplicate mounts resolved (P3,
   2026-05-25).** 60+ Aja workspaces still follow one of three patterns: (A)
   thin h1 + Hathor; (B) capability grid + Hathor; (C) composite with 4–5
   embedded sibling Aja workspaces. The duplicate-mount consequence (4–7 Hathor
   renders per page with independent state) is resolved by finding #1 — Hathor
   is no longer rendered transitively. The lattice itself remains as IA
   structure; collapsing patterns A/B/C into one canonical shape is a separate
   authoring concern.
5. **Mixed casing on studio identifiers — RESOLVED (P3, 2026-05-25).** Three
   patterns had drifted from the rest of the studio PascalCase convention
   (initialisms get only the first letter capitalized). All three are now
   normalized across components, route maps, test files, page imports, and
   walkthrough docs:
   - `CRDTSync` → `CrdtSync` (Yemaya; one workspace + one route map + tests;
     route segment `crdt-sync` unchanged)
   - `AIContentGeneration` → `AiContentGeneration` (Yemaya; one workspace
     - one route map + tests; route segment `ai-content-generation` unchanged)
   - `TypeScriptSdk` → `TypescriptSdk` (Aja, Bellona, Hathor; three workspaces +
     three route maps + tests; route segment `typescript-sdk` unchanged)
     `DaVinciIntegration` is preserved — "Da Vinci" is a two-word proper noun
     and its current PascalCase mapping matches the `da-vinci-integration` route
     segment.
6. **One genuinely deep Yemaya surface.**
   `/studio/yemaya/remote-actor-home-capture` is 1566 LOC / 93 panel components
   integrating `@yemaya/remote-film-capture`. The exception that proves the
   rule.
7. **Self-links in related-workspace panels — RESOLVED (P3, 2026-05-25).** The
   finding was filed as "breadcrumb cycles" but the underlying defect was in the
   per-page related-workspaces panel: 122 studio pages (`/studio/aja/*`,
   `/studio/isis/*`, `/studio/yemaya/*`, `/studio/bellona/*`,
   `/studio/hathor/*`) each listed their own route as the first quickAction
   Link, creating a no-op "open the page you're on" action. Reciprocal links to
   sibling workspaces (e.g., Avatar Library → Avatar Integration → Avatar
   Library) are intentional and remain. The actual breadcrumbs
   (`Studio / Aja / X`) were already correct.
8. **Aja API Endpoints lane-mount duplication — RESOLVED (P3, 2026-05-25).** The
   1399-LOC `StudioAjaApiEndpointsWorkspace` (35 workflows, force-failure
   toggles, contract diagnostics) was embedded as a full-workspace lane in four
   aggregator hubs (`/studio/aja/docs`, `/studio/aja/motion-integration`,
   `/studio/aja/motion-pipeline-sdk`, `/studio/aja/motion-pipeline-sdk-python`)
   — each embed mounted independent client state, so toggling a workflow in one
   embed did not affect the others, and operators saw the same controls in
   multiple places. All four embeds now mount a thin
   `<StudioAjaApiEndpointsLaneCard />` (capability summary + link to the
   canonical surface). The original finding referenced `/studio/aja/cli` but
   `cli` no longer embeds API Endpoints today — `cli` mounts only the CLI
   command surface and SDK lanes. The canonical workspace surface remains at
   `/studio/aja/api-endpoints`.
9. **`active="explore"` wrong for every studio route — RESOLVED (P3,
   2026-05-25).** The original concern was that every studio `page.tsx` mounted
   `ShellLayout active="explore"`, leaving Studio without its own dedicated nav
   state. A repo-wide grep confirms this is no longer true: all 480 studio
   `page.tsx` files now declare `active="studio"`, zero declare
   `active="explore"`. The `studio` shell-route is a first-class member of
   `WebShellRoute` and the customer sidebar (with shortcut key `6`); the
   original lane-card sweep flipped every studio route to `active="studio"`. No
   code change needed; finding marked resolved as already-fixed.
10. **`/studio/compose` and `/studio/generation/living-scene` — NOINDEX-TAGGED
    (P3, 2026-05-25).** Both routes are intentionally reachable without a
    session (per `PUBLIC_PATHS` in `proxy.ts`): `/studio/compose` ships built-in
    fixtures with no user-state writes; `/studio/generation/living-scene`
    exposes only approved templates and enforces tier + tenant policy via
    headers. They are not marketing surfaces, though — the canonical funnel for
    search indexing is `/welcome` and the per-domain landing pages. Both routes
    now export
    `robots: { index: false, follow: false, noarchive: true, nosnippet: true, googleBot: { index: false, follow: false } }`
    in their `metadata` so a crawler that discovers them via an inbound link
    does not index them. 2 tests at
    `src/__tests__/anon-studio-route-metadata.test.ts` assert the literal
    noindex block is present in each route's source (source-text assertion,
    since both pages have client-side imports that vitest's resolver cannot
    follow without the Next.js build).
11. **Concordia workbench uses one workspace for 12 routes** dispatched via an
    `initialSurface` prop. Walkthrough files link back to the parent rather than
    duplicating the shared Interactions surface.
12. **Studio workspace persistence — V1 foundation shipped (P3, 2026-05-25).**
    Adds a typed `useStudioWorkspacePersistence` hook at
    `apps/oshun/web/src/lib/studio-workspace-persistence.ts` that mirrors
    `useState<T>` but persists across reloads via localStorage, with a versioned
    key (`oshun.studio-workspace.<workspaceId>.v<n>`), a debounced save (250ms
    default), an `isValid` type-guard for crash-safe hydration, and a
    `schemaVersion` bump that discards incompatible persisted shapes.

    Canonical wiring lives on `StudioHathorEconomyModelingWorkspace` for the
    workspace's `density` + `viewportMode` shell state — operator choices now
    survive page reloads. 6 hook tests cover defaults, persistence, hydration,
    invalid-state fallback, schema-version bumping, and debounce coalescing.

    The localStorage backend is intentional V1 scope. **The BFF endpoint pair
    has now shipped (P3 follow-up, 2026-05-25):**
    - `GET /v1/studio/workspaces/:workspaceId/state` returns the caller's
      persisted state for a given workspace (404 when none stored).
    - `POST /v1/studio/workspaces/:workspaceId/state` upserts state for the
      caller. Payload: `{ schemaVersion: integer >= 1, stateJson: string }`
      (opaque JSON; client owns the shape). 32 KiB cap; `workspaceId` must match
      `/^[a-z][a-z0-9-]+$/`.
    - `studioWorkspaceStateStore` in
      `apps/oshun/bff/src/studio/ workspace-state-store.ts` keys per
      `(userId, workspaceId)` so two operators on the same browser cannot read
      each other's drafts.
    - 8 route tests cover auth, GET/POST roundtrip, cross-user isolation,
      invalid payload, invalid workspaceId, oversized state, and upsert.
    - **Hook swap shipped (P3 follow-up, 2026-05-25):**
      `useStudioWorkspacePersistence` is now local-first + BFF-authoritative-
      on-newer. Hydration: localStorage envelope `{ state, updatedAtIso }` first
      (sync, no flash), then async BFF GET — adopts the BFF copy iff its
      `updatedAtIso` is strictly newer. Saves: debounced dual-write to
      localStorage + `POST` to the BFF. Legacy raw-state localStorage entries
      (the V1 shape) are still accepted; they're treated as epoch-0 so the next
      save or BFF load supersedes them. BFF errors, 401s, and 404s are swallowed
      silently so the hook degrades to localStorage-only when offline / signed
      out / no remote state yet. The call signature
      `[T, Dispatch<SetStateAction<T>>]` is unchanged — every existing caller
      (currently `StudioHathorEconomyModelingWorkspace`) keeps working without
      modification. 11 hook tests: 7 cover the localStorage path
      (`bffSyncEnabled: false`), 4 cover the BFF path (BFF-newer adopt,
      BFF-older keep-local, BFF-404 keep-local, POST-on-change).

    Other studio workspaces opt in by adopting the hook with their own
    `workspaceId` + `defaultState` + `isValid` guard. Larger / more complex
    state (saved filters, draft text, multi-tab cursor positions) can use the
    same hook with a richer `T`.

13. **Studio page-boundary telemetry — FOUNDATION SHIPPED (P3, 2026-05-25).**
    Adds three new event types to `OshunEventPayloadMap` in
    `libs/oshun/analytics/src/types.ts`: `studio_workspace_mounted`,
    `studio_workspace_unmounted`, `studio_workspace_interaction`. The reusable
    helper at `apps/oshun/web/src/analytics/studioWorkspaceMountTelemetry.ts`
    exposes `emitStudioWorkspaceMount`, `emitStudioWorkspaceUnmount`,
    `emitStudioWorkspaceInteraction`, each typed against the new payload
    entries.

    Canonical wiring lives on the two highest-traffic studio surfaces:
    `StudioHathorEconomyModelingWorkspace` (the canonical Hathor lane-card
    target) and `StudioAjaApiEndpointsWorkspace` (the canonical Aja API contract
    surface). Both fire `_mounted` on mount and `_unmounted` on unmount with a
    `durationMs` payload.

    Per-workspace opt-in is the extension pattern — future studio routes call
    `emitStudioWorkspaceMount({ workspaceId, surface })` from their own mount
    effect. The `data-*` attributes remain as Playwright test hooks; this is the
    additive analytics signal.

    The stdout-info shim stays as a dev-time signal. **The BFF ingest sink has
    now shipped (P3 follow-up, 2026-05-25):**
    - `POST /v1/studio/telemetry/workspace-events` accepts batches of up to 100
      events. Payload: `{ events: StudioWorkspaceTelemetryEvent[] }`.
      Validation: known kinds only, well-formed ISO `occurredAt`, workspaceId
      pattern, surface pattern, `durationMs` only on `_unmounted`, `action` only
      on `_interaction`. The whole batch fails on the first invalid event
      (client should never silently drop signals).
    - `studioWorkspaceTelemetrySink` keeps an in-memory buffer (10k-event
      capacity, oldest-dropped overflow). Each accepted event is stamped with
      the authenticated `userId` and a server-side `receivedAtIso`.
    - The customer-web `studioWorkspaceMountTelemetry.ts` helper now has a
      second `bffSink` alongside the existing stdout sink. Events queue
      client-side and flush every 2s, on `pagehide`, or when the queue hits 25
      entries. Network failures are swallowed silently so a hiccup never breaks
      a render path.
    - 9 BFF route tests (auth, valid batch persist, empty batch ok, oversize
      batch 413, unknown kind, durationMs-on-mounted reject, missing-action
      reject, userId stamping) + 1 web-side batch-flush test (verifies fetch is
      called with the queued events when the 2s window elapses).
    - **Forwarder hook shipped (P3 follow-up, 2026-05-25):**
      `studioWorkspaceTelemetrySink.setForwarder(fn)` installs a pluggable
      callback that's invoked once per accepted batch with the records that were
      just appended. Production wires it to an OpenTelemetry collector or
      warehouse pipeline; the default is null (no-op) so the sink stays useful
      as a standalone in-memory buffer in dev/test. The sink swallows both
      synchronous throws and async rejections from the forwarder so a
      misconfigured collector can never break ingest — records are buffered
      regardless. 3 additional route tests cover forwarder-invocation,
      sync-error-swallow, and async-rejection- swallow; the OpenTelemetry SDK
      wiring itself is deployment work (env var + SDK init + collector URL),
      kept out of application code.

## Unconfirmed-v1 sweep — cross-cutting findings

Surfaced by the 4 parallel agents during the Bellona / Hathor / Neith sweep.
Each finding has direct V1-decision-making implications.

1. **`StudioHathorEconomyModelingWorkspace` — DECISION: wrappers are breadcrumb
   / IA only (P3, 2026-05-25).** The canonical ~2,756-LOC component lives at
   `/studio/hathor/economy-modeling`
   (`apps/oshun/web/src/app/studio/hathor/economy-modeling/page.tsx`). 236
   sibling components across Hathor / Aja / Bellona / Isis / Yemaya that
   previously embedded the full workspace now mount a thin
   `StudioHathorEconomyModelingLaneCard` (link to the canonical surface). The IA
   contract is now explicit: each wrapper is a breadcrumb / navigation surface,
   not a re-render of the same workspace with independent state. Wrappers may
   still author route-specific concerns (NPC memory, safety, scenarios,
   screenplays, validation, SDK, etc.) as first-class panels — that authoring is
   unblocked by the lane card removing the misleading "Economy Modeling is
   already wired here" appearance.
2. **Bellona is structurally different from Aja/Isis/Yemaya.** It does NOT embed
   `StudioHathorEconomyModelingWorkspace`. Instead it has its own polycentric
   backbone: `Studio BellonaBridgeProtocolAndSessionsWorkspace` (~4,000 LOC,
   embedded by adapters/bridge-core/event-handlers/event-publisher), plus
   bespoke per-engine bridges (`StudioBellonaBlenderBridgeCommandsWorkspace`,
   `StudioBellonaGodotBridgeCommandsWorkspace`), build-pipeline workspaces
   (`StudioBellonaBuildJobAuthoringWorkspace`,
   `StudioBellonaBuildQueueTrackingWorkspace`,
   `StudioBellonaContentAddressableBuildCacheWorkspace`), and heavy first-class
   workspaces for CliSurfaces, Client, CrossDomainAssetIngestion,
   EngineSynchronization, ExportPipeline, FormatRegistry, DaVinciIntegration,
   gameplay-runtime sub-systems, and a TypeScript SDK lane embedded inside
   Client.
3. **Bellona has three structural patterns**:
   - **Breadcrumbed aggregator** — imports a route-map module
   - **No-breadcrumb single workspace** — inline `_ROUTE_MAP`
   - **Meta-aggregator** (`/studio/bellona/interchange`,
     `/studio/bellona/metahuman`) embedding sibling lane workspaces
4. **Hathor has triple-to-sevenfold nesting in aggregators**: `pre-production`
   (3 lanes), `simulation` (4 lanes), `simulation-worker` (2 lanes),
   `sophia-integration` (3 lanes), `theory` (4 lanes), `validation` (4 lanes),
   `workbench` (7 lanes), `world-api` (2 lanes). Almost every lane component
   itself embeds Economy Modeling, so a single workbench page render mounts
   Economy Modeling 4–7 times with independent client state.
5. **Four bespoke Hathor workspaces — SAVED-VIEW + WIZARD HALVES COMPLETE (P3,
   2026-05-26).** The four bespoke Hathor authoring workspaces
   (`quest-authoring`, `story-graph-authoring`, `timeline-modeling`,
   `world-configuration`, ~15,250 LOC combined) DO NOT embed Economy Modeling;
   they carry bespoke client state for wizard / realtime / saved-view actions.
   The realtime half still needs a WebSocket / SSE story — a substantial
   follow-up. **The saved-view half is done across all four surfaces** (see
   below) and **the wizard half BFF endpoint pairs are now live for all four:**
   - `GET/POST /v1/studio/hathor/quest-authoring/records` + `DELETE …/:questId`
     — full QuestAuthoringRecord contract validation, 9 route tests.
   - `GET/POST /v1/studio/hathor/story-graph-authoring/records` +
     `DELETE …/:graphId` — full StoryGraphAuthoringRecord contract validation, 9
     route tests.
   - `GET/POST /v1/studio/hathor/timeline-modeling/records` +
     `DELETE …/:timelineId` — TimelineRecord plus nested validation of
     `timeline[]` (chronology entries with ISO timestamps), `diagnostics`
     (chronologyConflicts/causalityGaps/publicationRiskScore), and
     `relatedEntities[]` (entityType + state enums); arrays capped at 200. 10
     route tests.
   - `GET/POST /v1/studio/hathor/world-configuration/records` +
     `DELETE …/:recordId` — WorldConfigurationRecord keyed by recordId so one
     user can hold multiple records sharing a `worldId` across the three scopes
     (cosmology/geography/society). 11 route tests.
   - All four stores key per `(userId, recordId)` so two operators on the same
     browser cannot read each other's drafts. 39 BFF route tests in total across
     the four endpoint pairs.
   - **Wizard consumer swaps complete across all four workspaces (P3,
     2026-05-26):** each workspace now mounts → `GET` its records endpoint
     (falls back to its `INITIAL_*_RECORDS` seed on empty / 401 / offline /
     network failure so a fresh or signed-out operator still sees a populated
     workspace) and wizard create/edit submits fire a best-effort `POST` with
     `keepalive: true` (silent on failure; local state stays the source of truth
     for the session). The timeline-modeling edit branch was refactored to
     compute `editedRecord` outside the `setRecords` callback so both local
     state and the BFF POST see the same final value, including prepended
     `timeline[]` history entries and clamped
     `diagnostics.publicationRiskScore`. The quest-authoring edit branch had a
     parallel refactor for `finalRecord` to include the existing
     `streamState/streamLagMs/reconnectCount24h`. Stream-state mutations
     (live/paused/reconnecting + lag ticks) intentionally stay client-only since
     they tick on runtime telemetry rather than operator intent. 74 workspace
     tests pass across the four surfaces.

   **The saved-view half across all four surfaces:** each uses
   `useStudioWorkspacePersistence` with its own shell-state shape + `isValid`
   type-guard, persisting operator preferences (density, viewport mode,
   viewport-sync, command-strip visibility, policy-error visualisation where
   applicable, high-contrast where applicable) local-first via localStorage with
   BFF-authoritative-on-newer sync via
   `/v1/studio/workspaces/{hathor-quest-authoring,hathor-story-graph-authoring,hathor-timeline-modeling,hathor-world-configuration}/state`.
   Operator role + permission tier stay session-scoped (they come from the auth
   context once the BFF wiring lands). 74 tests pass across the four workspaces
   (18+18+18+20). Several callback-form `setX(prev => ...)` usages converted to
   direct-value form along the way; for timeline-modeling, two telemetry
   side-effects moved out of the setter callback into the click handler body.

   **Data Retention & Lifecycle Controls real-infra route journey
   (2026-06-30):** `/studio/data-retention-lifecycle-controls` now has focused
   Playwright coverage against the real dev BFF for the Studio governance
   lifecycle classifier: admin catalog load, seeded retain/archive/purge/hold
   classification, edited unknown-class safe-retain issue, legal-hold
   precedence, client-only malformed JSON rejection with no evaluate POST, live
   BFF invalid-payload details, network-unreachable classify failure, catalog
   loading/error, native pending submit disablement, non-admin fail-closed
   state, anonymous redirect, flat quick-action affordances, automated 44px
   checks, and the shared axe gate. This verifies another V1 Studio governance
   lane-console surface; the broader V1 walkthrough/E2E task remains open.

   **Concordia Workbench real-infra route journey (2026-06-30):**
   `/studio/concordia-workbench` now has focused Playwright coverage for the
   live Agreement Frontier lane against the real dev BFF plus the seeded
   Concordia workbench shell. The spec verifies admin catalog load, default
   Pareto compute, edited duplicate-option and missing-utility BFF 400 details,
   client-only malformed JSON rejection with no compute POST,
   network-unreachable compute failure, catalog loading/error, native pending
   submit disablement, non-admin fail-closed state, route-map and quick-action
   affordances, all 11 seeded surface renderers, viewer privacy projection, case
   switching, audit recording, direct `/cases/:caseId/frontier` subroute
   selection, anonymous redirect-before-render, and the existing shared-axe
   accessibility smoke. The case bundle remains seeded in-memory until the
   production Concordia adapter lands, so adapter-offline and future production
   adapter behavior remain open.

   **Isis Video Production Workflows real-infra route journey (2026-06-30):**
   `/studio/isis/video-production-workflows` now has focused Playwright coverage
   against the real dev BFF for the `@isis/workflows` workflow schema validator:
   production hard-block for signed-in direct navigation without the lane
   bypass, localhost E2E lane navigation, admin catalog load, required-field
   rendering, default valid workflow header, edited missing-section and
   bad-`schema_version` schema errors, client-only malformed JSON rejection with
   no validate POST, live BFF `invalid_workflow` detail, network-unreachable
   validate failure, catalog loading/error, native pending submit disablement,
   non-admin fail-closed state, anonymous redirect, route-map / quick-action
   affordances, automated 44px checks, and the shared axe gate. This verifies
   another Isis lane-console surface; the broader V1 walkthrough/E2E task
   remains open.

   **Isis Model Registry real-infra route journey (2026-07-01):**
   `/studio/isis/model-registry` now has focused Playwright coverage against the
   real dev BFF for the managed-model browser: Studio-boundary hard-block,
   localhost E2E lane navigation, seeded default safe catalog, search /
   asset-type / commercial-use / NSFW filter re-queries, cursor pagination
   through the live BFF, catalog loading/empty/error/malformed states, non-admin
   fail-closed state, anonymous redirect, route-map / quick-action affordances,
   automated 44px filter/toggle/load-more/link checks, and the shared axe gate.
   This verifies another Isis model-governance surface; the broader V1
   walkthrough/E2E task remains open.

   **Isis Budget Management real-infra route journey (2026-07-01):**
   `/studio/isis/budget-management` now has focused Playwright coverage against
   the real dev BFF for the `@isis/runpod-surface` cost-quota evaluator:
   Studio-boundary hard-block, localhost E2E lane navigation, live seeded tenant
   verdicts (`ok`, `alert`, `kill-switch-armed`, `over-cap`), status-count
   rollup, status-filter narrowing with local persistence, loading/service-
   failure / malformed / filtered-empty / network-failure states, route-map /
   quick-action affordances, automated 44px select/link checks, non-admin
   fail-closed state, anonymous redirect, and the shared axe gate. This verifies
   another Isis GPU spend-governance surface; the broader V1 walkthrough/E2E
   task remains open.

   **Isis Cost Tracking real-infra route journey (2026-07-01):**
   `/studio/isis/cost-tracking` now has focused Playwright coverage against the
   real dev BFF for the `@isis/token-budget` LLM cost ledger: Studio-boundary
   hard-block, localhost E2E lane navigation, live pricing/rollup catalog load,
   valid `claude-3.5-sonnet` usage recording with exact `$0.0180` cost,
   duplicate-record and unknown-model rejection, client token-count validation,
   native pending submit disablement, loading/service- failure /
   malformed-catalog / malformed-record / network-failure states, route-map /
   quick-action affordances, automated 44px form/link checks, non-admin
   fail-closed state, anonymous redirect, and the shared axe gate. This verifies
   another Isis LLM spend-governance surface; the broader V1 walkthrough/E2E
   task remains open.

   **Isis Resource Recommendations real-infra route journey (2026-07-01):**
   `/studio/isis/resource-recommendations` now has focused Playwright coverage
   against the real dev BFF for the `@isis/resource-recommendations` fallback
   selector: Studio-boundary hard-block, localhost E2E lane navigation, live
   fallback chain/reason catalog load, seeded recommendation rendering, valid
   downgrade recommendation write/readback, cheapest-model no-downgrade
   recommendation, duplicate-id and off-chain-model rejection, client
   validation, native pending submit disablement, loading/service-failure /
   malformed-catalog / malformed-record / network-failure states, route-map /
   quick-action affordances, automated 44px form/link checks, non-admin
   fail-closed state, anonymous redirect, and the shared axe gate. This verifies
   another Isis LLM spend-reduction surface; the broader V1 walkthrough/E2E task
   remains open.

   **Isis Creator Monetization real-infra route journey (2026-07-01):**
   `/studio/isis/creator-monetization` now has focused Playwright coverage
   against the real dev BFF for the `@isis/3d-marketplace-ops` collaborator
   payout-split planner: Studio-boundary hard-block, localhost E2E lane
   navigation, live role/status catalog load, valid 100% split write/readback,
   manual-review marketplace-terms warning, blocked under-allocation warning,
   live BFF `invalid_payload` rejection for unknown roles, client malformed /
   non-array JSON validation, native pending submit disablement,
   loading/service-failure / malformed-catalog / malformed-plan /
   network-failure states, route-map / quick-action affordances, automated 44px
   textarea/button/link checks, non-admin fail-closed state, anonymous redirect,
   and the shared axe gate. This verifies another Isis marketplace
   revenue-governance surface; the broader V1 walkthrough/E2E task remains open.

   **Isis RIFE Interpolation real-infra route journey (2026-07-01):**
   `/studio/isis/rife-interpolation` now has focused Playwright coverage against
   the real dev BFF for the `@isis/video-enhancement` RIFE frame-interpolation
   planner: Studio-boundary hard-block, localhost E2E lane navigation, live
   source/target fps catalog load, exact 24→48 and 24→120 plan write/readback,
   unsupported 30→48 plan failure, live BFF `invalid_payload` rejection for too
   few source frames, client frame-count validation, native pending submit
   disablement, loading/service-failure / malformed-catalog / malformed-plan /
   network-failure states, route-map / quick-action affordances, automated 44px
   select/input/button/link checks, non-admin fail-closed state, anonymous
   redirect, and the shared axe gate. This verifies another Isis generated-video
   planning surface; the broader V1 walkthrough/E2E task remains open.

   **Isis Job Submission real-infra route journey (2026-07-01):**
   `/studio/isis/job-submission` now has focused Playwright coverage against the
   real dev BFF for the `@isis/job-envelope` submission builder: Studio-boundary
   hard-block, localhost E2E lane navigation, real generation-type / priority
   catalog load, valid `music-generation` envelope build, pending submit
   disablement, client-only malformed JSON rejection, live BFF `invalid_payload`
   and strict enum validation issue rendering, catalog loading/error/malformed
   states, non-admin fail-closed state, anonymous redirect, route-map /
   quick-action affordances, automated 44px form/link checks, and the shared axe
   gate. This verifies another Isis job-governance surface; the broader V1
   walkthrough/E2E task remains open.

   **Isis Job Envelope real-infra route journey (2026-07-01):**
   `/studio/isis/job-envelope` now has focused Playwright coverage against the
   real dev BFF for the `@isis/job-envelope` field-normalization/coercion lane:
   Studio-boundary hard-block, localhost E2E lane navigation, live
   field/vocabulary catalog load, alias-heavy normalize POST, unresolved-token
   rendering without fabricated canonical values, loading/service-failure /
   malformed-catalog / malformed-normalization / network-failure states,
   embedded job-pipeline lane shells, AAA embed-gate, route-map / quick-action
   affordances, automated 44px form/link checks, non-admin fail-closed state,
   anonymous redirect, and the shared axe gate. This verifies the coercion layer
   between job submission and job queue operations; the broader V1
   walkthrough/E2E task remains open.

   **Isis Job Management real-infra route journey (2026-07-01):**
   `/studio/isis/job-management` now has focused Playwright coverage against the
   real dev BFF for the generation job queue: Studio-boundary hard-block,
   localhost E2E lane navigation, live queue seeding through
   `/v1/generation/jobs`, status / kind / job-id filters, selected job
   request/error detail, process-queue POST with `{ max: 25 }`, fail-closed
   `provider_not_configured` rendering, failed-job retry back to queued,
   loading/empty/error/malformed states, non-admin fail-closed state, anonymous
   redirect, route-map / quick-action affordances, automated 44px
   filter/button/row/link checks, and the shared axe gate. This verifies the
   Isis job-queue operations surface that follows envelope validation; the
   broader V1 walkthrough/E2E task remains open.

   **Workbench World Editor real-infra route journey (2026-06-25):**
   `/studio/hathor/workbench-world-editor` now has focused Playwright coverage
   against the real dev BFF for the CGI scene validator: admin catalog load,
   issue-type / coordinate enum rendering, seeded missing-location verdict,
   clean export-ready verdict, BFF schema-validation detail, client-side
   malformed JSON rejection with no validate POST, native pending submit
   disablement, non-admin fail-closed state, route-map / quick-action
   affordances, mobile 44px controls, and the shared axe gate. This verifies one
   Hathor §34 surface; the broader 74-surface Hathor task remains open.

   **Workbench Worlds real-infra route journey (2026-06-29):**
   `/studio/hathor/workbench-worlds` now has focused Playwright coverage against
   the real dev BFF for the `@hathor/domain-models` region geography scorer:
   admin catalog load, seeded temperate-forest analysis, edited
   volcanic-wasteland analysis, client-only malformed JSON rejection with no
   analyze POST, live BFF terrain validation detail, catalog loading/error,
   native pending submit disablement, non-admin fail-closed state, anonymous
   redirect, route-map / quick-action affordances, automated 44px checks, and
   the shared axe gate. This verifies another Hathor workbench surface; the
   broader 74-surface Hathor task remains open.

   **Workbench Timeline real-infra route journey (2026-06-29):**
   `/studio/hathor/workbench-timeline` now has focused Playwright coverage
   against the real dev BFF for the `@hathor/timeline` scene-order packet
   validator: admin catalog load, seeded blocking story-order plus causal
   dependency verdict, edited clean export-ready packet, warning-only uncovered
   world-state tag, client-only malformed/primitive JSON rejection with no
   validate POST, live BFF empty-scenes validation detail, catalog
   loading/error, native pending submit disablement, non-admin fail-closed
   state, anonymous redirect, route-map / quick-action affordances, automated
   44px checks, and the shared axe gate. This verifies another Hathor workbench
   surface; the broader 74-surface Hathor task remains open.

   **Economy Simulation real-infra route journey (2026-06-29):**
   `/studio/hathor/economy-simulation` now has focused Playwright coverage
   against the real dev BFF for the `@hathor/domain-models` market-pricing
   model: admin catalog load, seeded luxury/rare elastic pricing, edited
   land/common scarce pricing, zero-ratio maximum-scarcity pricing, client-only
   numeric rejection with no price POST, live BFF unknown-category validation
   detail, catalog loading/error, native pending submit disablement, non-admin
   fail-closed state, anonymous redirect, route-map / quick-action affordances,
   automated 44px checks, and the shared axe gate. This verifies another Hathor
   economy surface; the broader 74-surface Hathor task remains open.

   **Lore Validation Timeline real-infra route journey (2026-06-29):**
   `/studio/hathor/lore-validation-timeline` now has focused Playwright coverage
   against the real dev BFF for the `@hathor/validation` TimelineValidator:
   admin catalog load, seeded `TIMELINE_ORDER_VIOLATION`, opt-in
   `TIMELINE_GAP_DETECTED`, client-only malformed/empty/threshold validation
   rejection with no validate POST, live BFF `invalid_event` detail, catalog
   loading/error, native pending submit disablement, non-admin fail-closed
   state, anonymous redirect, route-map / quick-action affordances, automated
   44px checks, and the shared axe gate. This verifies another Hathor
   lane-console surface; the broader 74-surface Hathor task remains open.

   **Lore Validation Causality real-infra route journey (2026-06-29):**
   `/studio/hathor/lore-validation-causality` now has focused Playwright
   coverage against the real dev BFF for the `@hathor/validation`
   CausalityValidator: admin catalog load, seeded `CAUSALITY_CYCLE_DETECTED`,
   opt-in `CAUSALITY_ORPHAN_EFFECT` / `CAUSALITY_DANGLING_CAUSE`, client-only
   malformed/empty validation rejection with no validate POST, live BFF
   `invalid_event` detail, catalog loading/error, native pending submit
   disablement, non-admin fail-closed state, anonymous redirect, route-map /
   quick-action affordances, automated 44px checks, and the shared axe gate.
   This verifies another Hathor lane-console surface; the broader 74-surface
   Hathor task remains open.

   **Lore Validation Taxonomy real-infra route journey (2026-06-29):**
   `/studio/hathor/lore-validation-taxonomy` now has focused Playwright coverage
   against the real dev BFF for the `@hathor/validation` TaxonomyValidator:
   admin catalog load, seeded `TAXONOMY_CYCLE_DETECTED`, edited
   `TAXONOMY_INVALID_TYPE`, clean age → epoch hierarchy,
   `TAXONOMY_HIERARCHY_VIOLATION` warning, client-only malformed/empty
   validation rejection with no validate POST, live BFF `invalid_era` detail,
   catalog loading/error, native pending submit disablement, non-admin
   fail-closed state, anonymous redirect, route-map / quick-action affordances,
   automated 44px checks, and the shared axe gate. This verifies another Hathor
   lane-console surface; the broader 74-surface Hathor task remains open.

   **Lore Validation Contradictions real-infra route journey (2026-06-29):**
   `/studio/hathor/lore-validation-contradictions` now has focused Playwright
   coverage against the real dev BFF for the `@hathor/validation` contradiction
   detector: admin catalog load, seeded `CONTRADICTION_TEMPORAL`, edited
   clean-event payload, client-only malformed/empty validation rejection with no
   detect POST, live BFF `invalid_event` detail, catalog loading/error, native
   pending submit disablement, non-admin fail-closed state, anonymous redirect,
   route-map / quick-action affordances, automated 44px checks, and the shared
   axe gate. This verifies another Hathor lane-console surface; the broader
   74-surface Hathor task remains open.

   **Hathor Validation aggregator real-infra route journey (2026-06-29):**
   `/studio/hathor/validation` now has focused Playwright coverage against the
   real dev BFFs for every embedded validation lane: Unified Validation
   Dashboard, Timeline, Causality, and Taxonomy. The route-level spec verifies
   all embedded catalog GETs, seeded and clean unified-dashboard suite POSTs,
   seeded embedded Timeline/Causality/Taxonomy POSTs, dashboard client-only
   malformed/non-array/empty zero-POST validation, dashboard catalog-failure
   isolation while sibling lanes remain ready, non-admin fail-closed state
   across every embedded lane, anonymous redirect, route-map / quick-action
   affordances including the Contradictions link, automated 44px checks, and the
   shared axe gate. This verifies the Hathor validation hub surface; the broader
   74-surface Hathor task remains open.

   **Unified Validation Dashboard real-infra route journey (2026-06-29):**
   `/studio/hathor/unified-validation-dashboard` now has focused standalone
   Playwright coverage against the real dev BFF for the combined
   `@hathor/validation` suite: admin catalog load, seeded inconsistent
   Timeline/Causality verdicts, edited clean overall verdict, client-only
   malformed/non-array/empty validation rejection with no validate POST, live
   BFF `invalid_event` detail, catalog loading/error, native pending submit
   disablement, non-admin fail-closed state, anonymous redirect, route-map /
   quick-action affordances, automated 44px checks, and the shared axe gate.
   This verifies the dashboard as its own V1 Studio route in addition to the
   embedded validation hub coverage; the broader 74-surface Hathor task remains
   open.

6. **Neith has genuine domain logic.** `StudioNeithInverseModelingWorkspace` now
   mounts the V1 reference-inversion lane backed by `neith-inverse-modeling.ts`:
   decoded RGBA payload validation, feature extraction (`mean`, `contrast`,
   `edgeEnergy`, `entropy`, `warmBias`), terrain/vegetation/urban/noise
   parameter estimates, confidence scoring, and export-manifest output. The same
   route also keeps the admin-scoped live BFF fit-quality evaluator for
   residual/RMSE/MAE/R² verification.
7. **Bridge-command routes near-identical — TEMPLATED (P3, 2026-05-25).** The
   four bridge-command lanes (`blender-`, `godot-`, `unity-`,
   `unreal-bridge-commands`) previously each inlined a near-identical 24-line
   route-map constant and a 30-line cross-link panel that differed only by
   engine name. They now mount a single shared `BridgeCommandsPageScaffold` from
   `apps/oshun/web/src/components/studio/bridgeCommands/bridgeCommandsTemplate.tsx`
   that takes `{ engine, Workspace }` and renders the canonical 6-entry route
   map plus the cross-link panel (with the current engine filtered out, so no
   self-link). Adding a fifth engine is now a 2-line entry in
   `BRIDGE_COMMAND_ENGINES` plus a thin `page.tsx`. 9-test contract suite at
   `bridgeCommandsTemplate.test.tsx` asserts: 4 engines with matching slug/route
   pairs, every route map is exactly 6 entries rooted at the canonical path, and
   every page renders sibling cross-links but never a self-link.
8. **visionOS Features and Meta Quest Features — TEMPLATED (P3, 2026-05-25).**
   The two XR-features lanes (`visionos-features`, `meta-quest-features`) shared
   an identical 5-entry route map (feature → artifact → rollout) inlined in each
   page. They now mount a single shared `XrFeaturesPageScaffold` from
   `apps/oshun/web/src/components/studio/xrFeatures/xrFeaturesTemplate.tsx` that
   takes `{ platform, Workspace }` and renders the canonical route map plus the
   cross-link panel (sibling platform + XR Platform Support + Shared XR
   Capabilities + Virtual Production ICVFX, with the current platform filtered
   out so no page self-links). Adding a third XR platform is a 2-line entry in
   `XR_FEATURE_PLATFORMS` plus a thin `page.tsx`. 5-test contract suite at
   `xrFeaturesTemplate.test.tsx` asserts the platform set, per-platform 5-entry
   route map shape, and sibling-cross-link/no-self-link guarantees.
9. **Pervasive copy-paste artefacts in Bellona — RESOLVED (P3, 2026-05-25).**
   The 10 short-name lanes (`audio`, `bridge-core`, `database`, `davinci`,
   `event-handlers`, `event-publisher`, `gameplay-systems`, `godot`, `houdini`,
   `client`) previously each shipped a route map of five fictional
   `/lane/<entity>/[id]` nested URLs that have no corresponding `page.tsx` in
   the app router. Each lane now declares an explicit alias relationship via the
   `role` field on its route map:
   - 8 lanes are `alias` surfaces (route map: 1 `alias` + 1 `canonical-target`
     [+ optional `related-peer` for godot and houdini]).
   - `gameplay-systems` is a `hub-alias` (route map: 1 `hub-alias` + 5
     `canonical-target` lanes for the gameplay-runtime cluster).
   - Page-level: every lane renders a
     `Studio / Bellona / <Canonical> / <Lane> (alias)` breadcrumb and an
     IA-contract panel showing the alias → canonical link with role badges.
   - 21-test contract suite at `StudioBellonaAliasContracts.test.ts` asserts:
     each alias declares the correct self-path, every canonical target is a real
     flat /studio/bellona/<lane> path, no fictional nested URLs appear, and the
     alias-lane set is unique. Replaces the 10 stale per-lane route-map tests
     that asserted the now-deleted nested URLs.
10. **Breadcrumb IA inconsistency in Hathor — RESOLVED (P3, 2026-05-25).** The
    four simulation routes (`simulation`, `simulation-worker`,
    `simulation-physics`, `simulation-state-persistence`) now share a single
    declarative IA contract via the `role` field on their route-map entries:
    - `/studio/hathor/simulation` is the **aggregator** for the cluster. Its
      route map lists every sibling lane via the real flat
      `/studio/hathor/<lane>` path (no more fictional `/simulation/worker/[id]`
      nested URLs); the page renders an aggregator breadcrumb and quick-action
      links to all six sibling lanes.
    - The other three routes mark themselves as `self`, point back at
      `/studio/hathor/simulation` as `parent-aggregator`, and list the other
      lanes as `peer-lane` entries. Each page now shows a consistent
      `Studio / Hathor / Simulation / <lane>` breadcrumb (previously
      `simulation-physics` and `simulation-state-persistence` had none).
    - The 16-test contract suite asserts cluster invariants (aggregator
      singularity, parent-points-back, no fictional nested URLs) so drift
      triggers a CI fail. If a fifth simulation lane is added, the canonical
      sibling set lives in
      `StudioHathorSimulationClusterIa.test.ts:EXPECTED_SIBLINGS`.
11. **Hathor world-configuration → Bellona cross-domain link — STRUCTURED (P3,
    2026-05-25).** The world-configuration page previously rendered a single
    quick-action linking to Bellona C++ SDK with no in-domain Hathor peers
    (anomalous because every other Hathor `world-*` lane cross-links to
    in-domain peers like `world-api`, `world-version-branching`,
    `geography-modeling`). The IA contract is now explicit via three labelled
    panels:
    - **Related Hathor world lanes** — 6 in-domain peers (`world-api`,
      `world-version-branching`, `geography-modeling`, `location-modeling`,
      `culture-modeling`, `faction-modeling`).
    - **Downstream engine integration** — cross-domain Bellona consumers
      (`/studio/bellona/cpp-sdk` and
      `/studio/bellona/lore-to-engine-compilation`), each link is suffixed
      `(downstream consumer)` so it doesn't read as a peer. Preserves the
      original C++ SDK link instead of dropping it (world configuration data
      really does compile via the C++ SDK).
    - **Back to Studio** — index back-link in its own panel.
    - 2 tests at `StudioHathorWorldConfigurationPage.test.tsx` assert: the
      in-domain panel has the 6 expected Hathor lanes in order; cross-domain
      links are confined to the labelled downstream panel and never bleed into
      the in-domain panel.

## Audit sweep (2026-05-26)

Comprehensive completeness audit. Goal: ensure every `page.tsx` in
`apps/oshun/web/src/app/` has a drafted walkthrough and every walkthrough file
passes its own conventions. Findings + fixes:

1. **5 out-of-V1 stub rows drafted.** `/v2`, `/v2/wiki`, `/v2/glossary`,
   `/v2/roadmap`, `/v3/landing` had `status=stub` in `routes.csv` and no
   walkthrough file. Drafted in `customer/00-public/` with `v1_scope: out-of-v1`
   in frontmatter; CSV rows updated to `status=drafted` and `domain`
   reclassified from `unclassified` to `v2-shell` / `v2-knowledge` /
   `v3-marketing`.
2. **1 invalid YAML frontmatter.**
   `studio/domain-bridges/isis/studio-isis-video-generation.md` carried an
   unquoted backtick-colon sequence in its `auth:` value
   (`note: \`video-generation\` is not in …`) that broke YAML parsing. Quoted
   the value.
3. **2 broken relative `.md` links.** `journeys/nisaba-scholarly-read.md` linked
   `./nisaba.md` (file lives at `../customer/07-nisaba/nisaba.md`);
   `studio/governance/studio-accessibility-governance.md` linked
   `../operations/studio-experimentation-feature-flags.md` (file lives in the
   same `governance/` folder). Both fixed.
4. **1 unlisted journey.** `journeys/multi-device-workspace-handoff.md` existed
   since 2026-05-24 but was never added to `journeys/README.md`'s bucket map.
   Added under a new "Workspace shell (1)" bucket. Journey-file count is now 24
   (23 journeys + index), matching the file listing on disk.
5. **Final integrity check (all clean):** 643 CSV rows / 643 per-view files / 0
   YAML errors / 0 missing source files on disk / 0 status mismatches with CSV /
   0 missing required sections / 0 broken relative `.md` links across 3,814
   links.

## Audit sweep (2026-05-27)

Second comprehensive completeness audit. Goal: exhaustive flow + global-chrome
coverage to match the 100% per-view coverage achieved in the 2026-05-26 sweep.
Findings + fixes:

1. **1 page.tsx file with no walkthrough.** `/tara/sit/[id]` was added to the
   app router by
   `f96ca1dd85 feat(shared): wire tara begin sitting to /tara/sit/[id] player`
   after the 2026-05-26 sweep closed. Drafted in
   `customer/03-tara/tara-sit-id.md` (302 lines) covering the `TaraSitPlayer`
   client component (timer / drift detection / completion threshold / reflection
   capture / cross-domain step-out). Routes.csv row added; customer count 147 →
   148, V1 count 481 → 482.

2. **24 missing journey files.** The 23-journey sweep from 2026-05-24 covered
   the per-domain entries + first-time/PWA infra + cross-domain bridges + the
   Lilith policy + operator/studio + workspace shell. The 2026-05-27 audit
   identified 24 additional end-to-end flows that were either explicitly named
   in `V1/features.md` / `V1/ARCHITECTURE.md` or implied by per-view files
   without a journey to land on. Drafted (file → bucket):
   - **First-time + PWA infrastructure**: `onboarding-ten-steps`
   - **Customer-domain follow-ons**: `arete-living-offering-create`,
     `weekly-review-arete`, `veritas-retraction-cascade-customer-view`,
     `metis-byom-ingest-to-course`
   - **Discovery, messages, library**:
     `messages-center-deliver-and-unsubscribe`,
     `messages-quiet-hours-and-channel-binding`,
     `library-save-collection-share`, `search-explore-deep-read-library-save`,
     `nyx-event-calendar-sync-reminder`, `nisaba-notebook-capture-and-cite`
   - **Account, billing, identity**: `account-deletion-and-dsar`,
     `memory-edit-pause-forget`, `sign-up-and-pay-crypto`,
     `aaa-upgrade-entitlement-bounce`
   - **Scene + atelier authoring**: `scene-keep-and-share`,
     `public-scene-abuse-report`, `scene-public-viewer-anonymous`,
     `atelier-image-to-library`, `lilith-studio-tara-scene-publish`
   - **Agentic pipelines**: `agentic-pipeline-customer-invocation` (single
     template walking any of the six Cross-Domain Autonomous Pipelines)
   - **Assistant, operator, tenant — extended**:
     `assistant-handoff-context-carry`, `tenant-bulk-member-invite-scim`,
     `tenant-audit-log-investigation`

   Total journey files: **48** (47 journeys + 1 README), up from 24. All new
   journeys are grounded in real BFF routes, components, and contract types;
   each documents missing endpoints as Open questions rather than fabricating.
   (Subsequent second-pass audit added 5 more, bringing the journey total to 52
   journeys + 1 README = 53 files — see the second-pass section below.)

3. **8 missing shell-chrome files.** The 6-file shell/ folder from 2026-05-24
   covered app-shell / routing / PWA / auth / notifications / a11y. The audit
   identified 8 additional cross-cutting concerns referenced from per-view files
   or present in shell-level code without a documenting walkthrough. Drafted:
   - `shell/07-trust-safety.md` — flag button, crisis cascade, `/profile/safety`
     audit log, recovery substrate
   - `shell/08-telemetry-analytics.md` — `OshunEventPayloadMap` taxonomy,
     transports (stdoutSink / BFF / observability triad), cookie-consent gating,
     forbidden patterns
   - `shell/09-i18n-locale-time.md` — 8-locale matrix, `useLocaleStore`,
     hard-coded `<html lang>` drift, DST/timezone formatting, hreflang, RTL
   - `shell/10-feature-flags-experimentation.md` — flag registry, kill switches
     vs experiments, RuntimeConfigProvider, exposure telemetry
   - `shell/11-design-system-tokens.md` — Lilith `L` tokens, font stacks,
     primitives (LBtn/LChip/LDots/…), shells (LWebShell/LCustomerNav),
     cream-paper/dark-paper themes, forced-colors fallback
   - `shell/12-overlays-and-panels.md` — command palette, universal search,
     assistant dock + panel, What's New, quick-actions, widget sidebar,
     dialog/modal/sheet, focus management, z-index stacking
   - `shell/13-domain-launch-runtime.md` — domain switcher, startup gate,
     transition, degradation, outage banner, error boundary, active-execution
     status bar, launch-failure telemetry
   - `shell/14-performance-web-vitals.md` — critical-route budgets,
     `nisabaViewPerformanceBudgets`, lighthouse config, web vitals (LCP / INP /
     CLS / TTFB / FCP), CI gating, bundle budgets, escape hatches

   Total shell files: **14**, up from 6.

4. **Final integrity check (all clean):** 644 CSV rows / 644 per-view files / 0
   YAML errors / 0 missing source files on disk / 0 status mismatches with CSV /
   0 missing required sections / 0 broken relative `.md` links across 3,427
   actual links (the 3 "broken" hits in the link-validator are template examples
   inside `00-conventions.md`'s per-view file template code block, not literal
   cross-references). 47 journey files / 14 shell files (counts later updated to
   52 + 1 README and same 14 shell — see second-pass section). Every journey
   - shell file's internal `.md` links resolve.

## Audit sweep (2026-05-27, second pass)

Cross-referenced `V1/features.md` and `V1/ARCHITECTURE.md` against the 47
existing journeys to find any **multi-step user flow / lifecycle / cross-domain
handoff** named in the spec but not landed in a journey file. 5 genuine gaps
identified; 5 new journey files drafted and indexed:

- **`telegram-bot-assistant-delivery.md`** — bound Telegram user sends text /
  voice note → BFF webhook (`apps/oshun/bff/src/telegram/webhook.ts`,
  `routes/telegram.ts`) → Sophia-grounded composer
  (`libs/oshun/messaging-channels/src/telegram/sophia-grounder.ts`) → reply with
  disclosure footer + optional TTS audio. Delivery-side counterpart to
  `messages-quiet-hours-and-channel-binding.md`. Five concrete TBDs flagged:
  voice STT is stubbed (`webhook.ts:67-71`), TTS-back not wired, no per-user
  account binding lookup, no outbound delivery to `api.telegram.org`, no crisis
  scan on voice transcripts.
- **`themis-assessment-appeal.md`** — Themis academic-integrity verdict →
  student opens appeal → tenant teacher reviews in `/operator/metis` → override
  / upheld → student notified → audit chain captured. Anchored on
  `libs/metis/integrations/src/themis-canonical-wiring.ts`
  (`adjudicateAcademicIntegrity`, `openAcademicIntegrityAppeal`,
  `resolveAppealCase`, `captureAcademicIntegrityAuditRecord`) and the
  `libs/contracts/src/metis/index.ts` Themis verdict schemas. Customer-facing
  appeal BFF surface is **TBD** — flagged in Open questions; no `themis` or
  `appeal` handlers exist under `apps/oshun/bff/src/`.
- **`persona-voice-avatar-approval-workflow.md`** — creator proposes new persona
  in `/lilith-studio/personas` → Lilith quality eval → voice-quality + avatar
  reviewer checks → operator-studio publish gate → deployed to session-selection
  picker → eventual deprecation / supersession. Grounded on
  `SaraswatiPersonaDossierEditor.tsx`, `AvatarCostumeAuthoring.tsx`,
  `libs/oshun/persona-registry/src/lifecycle.ts` (canonical event set with
  `requiredActors` + `PersonaLifecycleRollbackPlan` invariants), and the
  `POST /v1/admin/personas/:personaId/publish` route family verified against
  `admin-persona-governance-route.test.ts`. Multiple TBDs flagged (rehearsal
  runner BFF, customer session-selection picker, retirement-recovery flow, audit
  dedup).
- **`psyche-tutor-live-session-to-graded-record.md`** — `/metis/tutor` → Psyche
  real-time envelope → transcript auto-persists → Iris memory bridge
  (`apps/oshun/bff/src/routes/assistant-metis-handoff.ts`) → adaptive-loop
  mastery update (`libs/metis/tutoring/src/loop/adaptive-loop.ts` 8-step, 600 ms
  P95) → optional `/operator/metis` review lane → optional Nisaba scholarly
  handoff. Distinct from `metis-lesson-completion.md` (quiz / assessment path).
  Live-voice toggle, transcript persistence endpoint (`tutor-session-memories`
  declared in `metis/api-client/src/adapter.ts:243` but absent from BFF routes),
  Psyche transport (WebRTC / WS / SSE), and operator tutor-session review lane
  are all **TBD**.
- **`tenant-sso-config-saml-oidc-claim-mapping.md`** — tenant admin uploads SAML
  metadata XML / OIDC discovery URL → maps external claims onto tenant role
  templates → sets MFA / IP allowlist / device-posture policy → test sign-in →
  enable. **Setup-side** of `tenant-bulk-member-invite-scim.md` Step 5
  (consumption-side). Found in `libs/oshun/tenant-console/src/identity/`
  (`sso.ts` — `SsoConnection`, `SsoClaimMapping`, `processSsoLogin`, five typed
  error codes, four claim transforms; `federation-and-auth-policy.ts` —
  `TenantAuthPolicy`, `evaluateAuthChallenge`, `ipMatchesCidr` IPv4-only). The
  configuration UI lives in `apps/oshun/tenant-admin/src/app/identity/page.tsx`,
  **not** `/operator/tenant` — discrepancy flagged. Full BFF write surface
  (`/v1/admin/tenants/:id/sso/*`) is **TBD**.

Journey README bucket map updated to add the 5 new entries under their
respective buckets: `telegram-bot-assistant-delivery` → Discovery (7 total);
`psyche-tutor-live-session-to-graded-record` → Customer-domain follow-ons (5
total); `tenant-sso-config-saml-oidc-claim-mapping` → Assistant/operator/tenant
extended (4 total); `themis-assessment-appeal` +
`persona-voice-avatar-approval-workflow` → Operator + studio + cross-surface (8
total).

**Final integrity check (all clean):** 644 CSV rows / 644 per-view files / 0
YAML errors / 0 missing source files / 0 status mismatches with CSV / 0 broken
relative `.md` links (excluding the 3 known template examples in
`00-conventions.md` documented above). **52 journey files + 1 README = 53
files** in `journeys/`. **14 shell files** in `shell/`. Coverage matrix is
exhaustive for V1 PWA flows / journeys / global chrome documented in the V1
spec.

## Maintenance

- When a new route lands, append a row to `routes.csv` (`stub`) and create the
  corresponding file in the right folder.
- When a route is removed, mark its CSV row `status=removed` and move the file
  under `archive/` (don't delete — old PRs may still reference it).
- When `Source:` code changes, set status of that file's CSV row to `stale`.
- A future enhancement: a CI check that diff-compares the CSV against
  `find apps/oshun/web/src/app -name page.tsx` and fails on drift, plus the YAML
  / link integrity checks the 2026-05-26 audit ran by hand.
