# Journey Walkthrough Results — Oshun V1 PWA

Per-journey Playwright walk results. Every current V1 PWA journey has a matching
`<journey-slug>.md` file under this directory. Additional dated sweep and
quality reports remain alongside those 58 journey results.

This page is a cumulative record. Counts inside dated sections describe that
specific run; the **Journey result ledger** and **Summary** below reconcile the
current 58-journey set. The generated
[Docs Center journey registry](../../docs-center/journeys/index.html) uses these
conservative ledger markers for status and the matched result files for dates
and evidence links.

## Sweep reports

- [`playwright-flow-sweep-2026-06-02.md`](./playwright-flow-sweep-2026-06-02.md)
  — executes the repo's **behavioural E2E suite** (601 spec files) against a
  live prod build + BFF. Non-studio: 320✓ / 345✗ / 2 skip; studio: systemic
  placeholder-session redirect (root-caused, not real bugs). Real findings: WCAG
  color-contrast violations, 3 duplicate-DOM defects, and, at the time, a
  missing `user-flag-to-review` customer affordance (superseded by the
  2026-06-24 moderation read-back addendum). Stricter, behavioural complement to
  the render-level 2026-05-29 re-walk below.

## 2026-05-29 comprehensive re-walk (Claude Opus 4.8)

All **53 journeys** re-walked with Playwright against a fresh Next.js 16.2.6
production build (`next start -p 3010`) and the BFF in **mock-adapter mode**
(`USE_MOCK_ADAPTERS=true`, the canonical local-dev domain-data path — without it
the home-widget endpoints 503/500 because the real adapters fetch downstream
microservices that don't exist as runnable apps here). Auth was driven via the
real `/api/auth/signup` path on `localhost:3010` (the dev seed endpoint is
disabled under `next start`'s `NODE_ENV=production`).

**Headline: the web app works.** Every customer/studio/operator surface renders
with a proper single `<h1>`, every domain hub + sub-route resolves (no broken
in-app links after the fixes below), the cross-domain bridges are present, and
every BFF-backed view loads real (mock) data — the transient client 401s
self-heal via the api-client's token-refresh retry. The prior walk's
blocked/failed verdicts were all from before the goal-2/3/4 rebuilds.

**Bugs found and fixed this pass (frontend):**

- `useBrowserSearchParams` read `window.location.search` in its state
  initializer → React hydration text mismatch (error 418) on every
  query-param-driven view (e.g. `/onboarding?step=memory`, 8 errors across the
  onboarding deep-links). Fixed: start empty on server + first client render,
  sync in the effect.
- Home "Begin daily breath ritual" (`lilith/rooms`) and the 5 `ActivityFeed`
  fallback rows linked to non-existent `/domains/<x>/<leaf>` routes (404).
  Repointed to the canonical `buildHydratedWebDomainRoutePath` / hub form.
- `/aaa-upgrade` "Continue in Yemaya Studio" and the lilith-studio access-denied
  "Request operator access" CTAs pointed at dead routes (`/welcome/yemaya`,
  `/profile/operator-access`, both 404). Repointed to `/studio` and `/profile`.
- Hardened two SSR-unsafe render-time `new Date()` usages on `/profile`
  (`ProfileSettingsPanel` relative time, `PreferencesSection` date/time
  previews).

**`/profile` hydration mismatch — FIXED.** The residual was a
`useSyncExternalStore` server-snapshot bug: all eight profile stores passed the
_live_ client `getSnapshot` as their `getServerSnapshot`, so by hydration time
the client store held the real user (the auth/profile fetch had populated it)
while the server rendered the seed default — e.g. the avatar initials hydrated
as "HW" on the client vs "AO" on the server. Fixed in `profile/store.ts` by
giving each store a stable seed snapshot (captured once at module load) as its
`getServerSnapshot`, so client hydration matches the SSR seed and then updates
to real data post-mount. Verified gone across multiple runs on the prod build;
real profile data still renders. (Two render-time `new Date()` usages on
`/profile` were also hardened earlier — ProfileSettingsPanel relative time +
PreferencesSection date previews.) See
`agentic-pipeline-customer-invocation.md`.

**Still needs real downstream systems / external choices** (not frontend bugs):
crypto settlement, IdP SAML/OIDC, real audio/generation runtimes, live Telegram
bot, agent orchestrator, SCIM — surfaced as reachable stubs. See
[`external-dependencies/`](./external-dependencies/README.md). Per-journey files
below carry the verdict + evidence for each of the 53.

### Follow-up issue-fix pass (deeper root-cause fixes)

A second pass fixed the genuine issues behind the few remaining non-clean lines:

- **Catch-all `Cache-Control` overriding auth `no-store`** (`next.config.mjs`).
  A `source: '/:path*'` rule applied
  `public, max-age=0, s-maxage=3600, stale-while-revalidate=86400` to **every**
  route — including `/api/auth/*` and gated pages — overriding the auth
  handlers' `no-store`. That let a shared CDN cache per-user auth/session
  responses (`s-maxage`) and the browser serve a stale anonymous `/` →
  `/welcome` redirect (SWR), bouncing freshly signed-in users back to `/welcome`
  on navigation (the real cause of the `first-time-anonymous-visitor` Step-9
  "bounce"). Removed the blanket `Cache-Control` (kept CSP + HSTS); static
  assets keep their explicit rules. Verified: `/api/auth/session` → `no-store`,
  `/welcome` → `private,no-store`, and `first-time-anonymous-visitor` now passes
  **10/10** across repeated runs.
- **Refresh-token rotation race** (`bff/src/auth/customer-auth-store.ts`).
  Concurrent refreshes (multi-tab / retried / nav-interrupted) re-presented the
  just-rotated token and tripped reuse-detection, **revoking the whole
  session**. Added a rotation **grace window**
  (`OSHUN_AUTH_REFRESH_ROTATION_GRACE_MS`, default 30s): a just-rotated token is
  accepted while the session is live; genuine later reuse still revokes
  (security preserved). Verified: 5 concurrent refreshes keep the session alive;
  after-grace reuse revokes (unit tests).
- **Sophia answer field-name** (`bff/src/routes/domain-stubs.ts`) — the endpoint
  now accepts `q` / `question` / `query` and echoes whichever is sent.
- **Walker URL corrections** — the placeholder-id and route-group-notation
  scripts now navigate real routes, so the sweep reflects the app, not the test.
- **Home telemetry "gap" withdrawn** — home is instrumented via 52
  `data-home-continuation-*` actions + `HomeContinuationTelemetryBridge`; the
  prior "Bug #7" was an attribute-name mismatch, not a missing-analytics bug.

### Final full-suite re-run (confirmation sweep)

After the fixes above, the full suite of **52 journey scripts** was re-run
end-to-end against the prod build + mock-adapter BFF. Result:

| Metric                                              | Count  |
| --------------------------------------------------- | ------ |
| Journeys swept                                      | 52     |
| Clean pass (renders, 0 persistent fails, 0 errors)  | **50** |
| Step failures                                       | **0**  |
| Page errors (hydration / uncaught JS) — whole suite | **0**  |
| Product regressions                                 | **0**  |

The 2 remaining non-clean lines are verified non-bugs:

- `install-as-pwa` `{401,503}` — auth-mount race during the journey's own
  mid-walk signup (home-data fetches fire before auth settles, then self-heal);
  all flagged endpoints return 200 with a valid token (confirmed).
- `public-scene-abuse-report` POST 404 — needs a seeded share (test-data gap);
  the endpoint correctly 404s an unknown shortCode.

The `/profile` hydration mismatch is confirmed fixed (0 page errors across the
sweep + dedicated prod runs).

## Run context

- **Branch**: `oshun-lt-2-hetzner`
- **Worktree**: `/mnt/volume300/workspace/oshun-lt-2`
- **Web app**: `http://127.0.0.1:3010` (Next prod build, `next start -p 3010`)
- **BFF**: `http://127.0.0.1:4010` (`tsx watch src/server.ts`)
- **Infra**: `docker compose -f docker/docker-compose.dev.yml up -d`
- **Driver**: Playwright chromium (headless), driven ad-hoc per journey
- **Screenshots**: `/tmp/claude-oshun-lt-2-screenshots/<journey>/<step>.png`
- **Logs**: `/tmp/claude-oshun-lt-2-logs/{web,bff,build}.log`

## Status legend

- `[ ]` — not yet attempted
- `[~]` — partially walked (blocked mid-flow, see notes in file)
- `[x]` — walked end-to-end, all steps verified passing
- `[F]` — failed (the journey itself does not work; bug captured in file)
- `[B]` — blocked by prerequisite (e.g., feature not implemented, env missing)
- `[s]` — skipped (out of scope for this pass; reason in file)

## Journey result ledger (58)

### Anonymous + onboarding (6)

- [~] [first-time-anonymous-visitor](./first-time-anonymous-visitor.md) — real
  Mailpit verify-link flow now covers signup-browser and fresh-browser session
  handoff with HttpOnly cookies; `email-verify-roundtrip` also covers safe
  `next`, unsafe fallback, and a 44 px Continue target on the verify-email
  landing page. Residual gaps are OG/Twitter image handlers, `?reauth=1`, and
  onboarding-abandon resume.
- [~] [install-as-pwa](./install-as-pwa.md) — _re-walked_ in goal-4: SW now
  registers (scope `/`, `installing: true` then `active` after a beat), manifest
  serves 200 with `theme_color: #f1ebdd` (Lilith cream, was navy), sw.js
  serves 200. The four runtime caches (`oshun-static-v4`, `oshun-media-v4`,
  `oshun-bff-v4`, `oshun-runtime-v4`) materialize on first visit. CC-BUG-C is
  confirmed fixed. Residual: the relaunch-cookie nav refresh still doesn't fire
  on every navigation; needs a follow-up to call `cookies.set` after
  `router.replace` rather than only on first paint.
- [~] [scene-public-viewer-anonymous](./scene-public-viewer-anonymous.md) —
  tombstone+embed verified after fixing P0 `'use server'` bug in
  `unlock-actions.ts`; password/playable branches need a seeded share. The
  former double `| OSHUN` title suffix is fixed.
- [~] [public-scene-abuse-report](./public-scene-abuse-report.md) — anonymous
  report form posts to the real BFF, live reports surface in the operator inbox,
  admin resolve/dismiss verbs persist, and the operator takedown cascade is
  covered at the real-BFF level; remaining gaps are the public-report detail UI
  action surface, actor restriction, brigade clustering, and signed-in reporter
  status.
- [~] [sign-up-and-pay-crypto](./sign-up-and-pay-crypto.md) — `/billing` added
  in `71e53603dd`; `/v1/payments/methods`, `/v1/payments/invoices`,
  `/v1/payments/crypto/quote`, and `/v1/entitlements/aaa` were added in
  `03d45f0ad7`. Real BFF-issued BTC and USDC/Base paywalls now cover disclosure
  version, trust-gated address reveal, copy/QR/address, issued-paywall support
  actions, signed settlement webhook, entitlement read-back, stale-address
  removal, and idempotent webhook re-delivery; external wallet/provider and
  oracle/receipt legs remain outside local infrastructure.
- [x] [onboarding-ten-steps](./onboarding-ten-steps.md) — deep-links,
      abandon/resume, skip/edit/revisit, sensitive-context reconciliation,
      first-run target weighting, online Finish failure, and browser-offline
      service-worker Background Sync replay are now covered over real dev infra

### Tara (3)

- [~] [first-tara-sit](./first-tara-sit.md) — happy path reaches player; player
  and both Home and the player expose their proper `<h1>`; Tara data renders
  through the BFF mock adapters. Audio completion/reflection remains outside the
  headless walk.
- [~] [tara-daily-ritual](./tara-daily-ritual.md) — `/tara` and `/arete` render
  with proper `<h1>` elements and BFF mock-adapter data; the historic heading
  and endpoint failures are resolved.
- [~] [tara-to-nisaba-handoff](./tara-to-nisaba-handoff.md) — bridge link added
  in `860a554b4e` (Nāgārjuna passage cue on /tara); full sit-completion handoff
  still depends on the audio-completion flow (not exercisable headless)

### Arete (4)

- [~] [arete-create-habit](./arete-create-habit.md) — `/arete/habits` rebuilt in
  `3f130c64f1` as a real Lilith phone-shell list with `keptToday/totalDaily`
  chip, "the promise" copy, per-habit streak counts, and a "propose a habit"
  CTA; `/arete/habits/new` is a real form posting to `POST /v1/arete/habits`
  with `awaiting-coach-approval` accepted state.
- [~] [arete-streak-recovery](./arete-streak-recovery.md) — humane tone copy
  verified (5 recovery matches, 0 shaming); `/v1/arete/streak` BFF endpoint
  added in `03d45f0ad7`
- [~] [arete-living-offering-create](./arete-living-offering-create.md) —
  `/arete/offerings` + `/atelier/new` pages added in `03d45f0ad7`;
  `/v1/arete/offerings` + `/v1/atelier/jobs` + `/v1/atelier/scenes` BFF
  endpoints added in same commit; 2026-06-26 coverage now drives
  `/arete/offering` keep/send through the live BFF and proves the signed-in
  `/arete/offerings` gallery reads the member-scoped draft/sent rows back with
  private intention previews.
- [~] [weekly-review-arete](./weekly-review-arete.md) — `/arete/review` renders
  its own `<h1>` with Save as private letter / Close the week actions; the
  cookie banner no longer hijacks the page heading, and `/arete/weekly`
  redirects to the canonical review route.

### Nyx (3)

- [~] [nyx-tonight-observation](./nyx-tonight-observation.md) — `/nyx/tonight`
  rebuilt in `9ba3d0823d` with a highlighted lead-event block + observation-
  order timeline; `/nyx/observation` is a real client form posting to a new
  `POST /v1/nyx/observations` endpoint with `observation_target_missing` 422
  branch.
- [~] [nyx-to-tara-bridge](./nyx-to-tara-bridge.md) — deep evidence now proves
  one deterministic fixed-event card → Tara timer → generic Nyx suggestion path.
  The `/nyx` hub's conditional Tara slot has no data producer, the card drops
  event identity from its href, telemetry remains DOM metadata, audio is wired
  to an unproxied metadata-shaped endpoint, completion is browser-local, and the
  200 BFF recommendation route targets only Nisaba or Metis.
- [~] [nyx-event-calendar-sync-reminder](./nyx-event-calendar-sync-reminder.md)
  — deep evidence now separates the dynamic agenda and whole-feed ICS, fixed
  rich catalog and single-event ICS, browser/process action-preference mirror,
  durable assistant/member reminder, Profile provider export, opt-in in-app
  worker, injected service-worker payload, and observation stores. These are
  useful shipped seams, but ids do not converge, detail actions do not create
  durable reminders, exported/worker URLs are invalid, warm taps do not
  navigate, and the 35 named cases do not form one reminder-to-observation
  receipt.

### Nisaba (2)

- [~] [nisaba-notebook-capture-and-cite](./nisaba-notebook-capture-and-cite.md)
  — deep evidence now covers the owner-scoped BFF snapshot and the Studio study
  service's Nisaba-native Postgres notebooks/cards, anchor validation, rights-
  gated publication/export, restart continuity, synchronized annotation items,
  erasure, local notes, six client formats, and fixture exports. It remains
  partial because the clients/stores do not converge, legacy links ignore ids,
  local notes and citations are browser-derived, cross-store writes are not
  atomic, Studio card append does not authorize the target notebook, and the
  separate Studio records lack an account export/erasure path.
- [~] [nisaba-scholarly-read](./nisaba-scholarly-read.md) — deep evidence now
  separates the real Epictetus search/detail path, the identity-aligned daily
  Dhammapada room and annotation count, the room's mismatched save id, and the
  static Marcus Aurelius depth pages. It remains partial because the named cases
  do not join one passage to an annotation, notebook, plan, reload, or
  subject-partitioned offline record.

### Metis (2)

- [~] [metis-lesson-completion](./metis-lesson-completion.md) — 36 Playwright
  cases combining browser and API evidence deeply cover the dev/test backlog
  fixture, schoolroom entry, shared authored reader, local quiz and assessment
  replay, durability-bound Themis/gradebook ledger, tutor specimen, Nisaba
  links, and a separate acknowledgement-bound tutor-memory read. Course/lesson
  ids remain unresolved, production backlog is unavailable, and no
  account-scoped completion, server assessment read-back, tutor delivery,
  library save, or Home/schoolroom progress join exists.
- [~] [metis-byom-ingest-to-course](./metis-byom-ingest-to-course.md) — deep
  coverage proves the query-preserving alias, deterministic text outline, honest
  URL/PDF pending records, durability-bound and privacy-composed ingest/admin
  records, and an owner-scoped draft proposal. Those remain three independent
  stored seams: no runtime path joins an ingest job to safety/Sophia approval, a
  promoted `CourseBuild`, or downstream lesson/tutor/assessment reads.

### Veritas + Sophia (4)

- [~] [sophia-grounded-answer](./sophia-grounded-answer.md) — `/sophia` rebuilt
  in `8ad5d6a4df` as a real ask-and-answer surface — single textarea, POST to
  `/v1/sophia/answer`, witness-anchored result card with citation weight +
  source kind chips. Real-BFF Playwright now covers grounded, cautious/partial,
  and no-source abstention envelopes.
- [~] [veritas-evidence-trail](./veritas-evidence-trail.md) —
  `/veritas/evidence` rebuilt in `8ad5d6a4df` as a real two-pane view (drift
  cases vs retractions) with resolution-state colour coding and cascade-reason
  chips.
- [~] [veritas-to-nisaba-deeper](./veritas-to-nisaba-deeper.md) — bridge link
  added in `860a554b4e` (case-study notebook cue on /veritas evidence rail)
- [~]
  [veritas-retraction-cascade-customer-view](./veritas-retraction-cascade-customer-view.md)
  — `/veritas/retraction` renders the soft-correction view; browser coverage now
  follows Library and Nisaba disclosures while real-BFF coverage proves source
  retract → durable cascade → Sophia re-grounding. Persisted notebook
  acknowledgement and remaining customer fan-out stay open.

### Atelier / Scene / Lilith Studio (5)

- [~] [atelier-image-to-library](./atelier-image-to-library.md) — /atelier
  five-room hub renders; `/atelier/camera-obscura` rebuilt in `8ad5d6a4df` as a
  live job queue with running/queued/done/failed state colouring; ATELIER\_
  JOBS_FIXTURE has two named jobs.
- [~] [scene-keep-and-share](./scene-keep-and-share.md) — public share, viewer,
  embed/oEmbed copy, password gates, download-grant integrity, tenant/Lilith
  gates, idempotent retry, and operator takedown-cascade consequences are now
  covered against real dev infra; persisted customer share/revoke management UI
  remains the main shipped-surface gap.
- [~] [lilith-studio-tara-scene-publish](./lilith-studio-tara-scene-publish.md)
  — _re-walked_ in goal-4: `/lilith-studio/scene/new` is reachable and POSTs to
  `/v1/lilith-studio/scenes` with the authoring-state response. Auth-gating
  still bounces to /welcome without a real session, but the page itself is no
  longer a 404. `/lilith-studio/tara` rebuilt in `8ad5d6a4df` as a read-only
  mirror of /v1/tara/{today,sittings,ritual}; `/lilith-studio/scene/new` posts
  to a new `POST /v1/lilith-studio/scenes` distinct from the user-facing
  /atelier endpoint (carries pathId + sessionIndex for course-content
  authoring).
- [~] [atelier-video-render-queue](./atelier-video-render-queue.md) — deep
  real-dev-infrastructure coverage verifies the authenticated read-only
  Cinematheque room, twelve-shot storyboard, three-row fixture queue, selected
  `sh 06` state, disabled Cut placeholder, reduced motion, offline-after-load
  stability, and 390 px layout without horizontal overflow. Live render jobs,
  queue mutation, and the Cut destination remain product gaps.
- [~] [atelier-motion-to-cinematheque](./atelier-motion-to-cinematheque.md) —
  deep real-dev-infrastructure coverage verifies the authenticated read-only
  motion room, timeline/take fixtures, disabled draft actions, URL-scoped
  handoff to Cinematheque, inbound context rendering, reduced motion,
  offline-after-load stability, and 390 px layout without overflow. Motion
  authoring and durable project transfer remain product gaps.

### Library + Search (2)

- [~] [library-save-collection-share](./library-save-collection-share.md) —
  /library renders with proper h1; `/library/collections` rebuilt in
  `8ad5d6a4df` as a real list (LIBRARY_COLLECTIONS_FIXTURE now has two named
  collections); `/library/collections/new` is a real form posting to
  `POST /v1/library/collections` with seed-item-id parsing.
- [~]
  [search-explore-deep-read-library-save](./search-explore-deep-read-library-save.md)
  — /search + /explore both render with proper h1; real BFF `/v1/search` results
  drive saved/recent search memory, recent-query suggestions, Nisaba passage
  click-through into the exact non-daily passage reader (`nisaba-passage-speech`
  id/reference/source/title/body + compare/support rails), Veritas claim
  click-through into the claim-detail evidence workspace, Veritas story
  click-through into the story timeline workspace, Tara practice click-through
  into the immersive session player, Nyx sky-event click-through into the
  canonical event-detail workspace, Metis course click-through into the active
  study destination preview, and search-result save → saved-items BFF →
  cache-free `/library` hydrate → Nisaba resume URL + exact passage workspace; a
  live-BFF `403 domain_scope_missing` now drives the visible fetch-failure error
  state with stale rows cleared and same-query Retry reissue; the long
  `/search?q=a` list now restores Browser Back scroll position after opening the
  Nisaba deep-read; the search-save → Nisaba in-domain unsave/resave path now
  proves the saved-items BFF keeps exactly one `nisaba:nisaba-passage-speech`
  row. Remaining gaps are broader non-Nisaba save-producer sync and remaining
  object-template save/resume permutations beyond the clicked destination
  surfaces.

### Assistant / Agents / Memory (5)

- [~]
  [agentic-pipeline-customer-invocation](./agentic-pipeline-customer-invocation.md)
  — `/v1/agents` + `/v1/orchestrator` BFF endpoints added in `03d45f0ad7`
- [~] [assistant-handoff-context-carry](./assistant-handoff-context-carry.md) —
  `/v1/assistant/context` BFF endpoint added in `03d45f0ad7`; 2026-06-24
  `assistant-session-bff` now proves route-level handoff sanitization by
  accepting a customer Veritas context and dropping a mismatched admin artifact
  before continuity merge; 2026-06-26 extends that real-BFF spec to prove
  consented profile + notebook Iris recall is returned in
  `response.memoryRecall` and folded into the assistant answer text; the browser
  continuity spec now also verifies the null-artifact `/explore` handoff renders
  `Artifact: no current artifact` instead of an empty or misleading artifact
  chip, and verifies the `/search` entity-mismatch branch posts `entity: null`
  with `artifact.metadata.entitySanitization='entity-shell-mismatch'` while the
  panel shows `Entity: removed (shell mismatch)` without the dropped admin
  label; it also verifies Tara→Veritas domain-shortcut navigation depth by
  preserving `origin=explore&stack=tara` through the real session-create
  payload, assistant continuity rail, and return links; it now verifies a live
  Nisaba notebook handoff stamps `artifact.metadata.notebookId`, recalls
  consented profile + notebook Iris memory through the real assistant message
  route, and renders the mounted transcript's `Remembered context:` profile /
  notebook copy with `Memory: profile`; 2026-06-26 also closes the
  browser-visible grounding inspect branch by sending a live Veritas assistant
  message, asserting the real BFF `response.grounding` envelope, and clicking
  `Inspect evidence` into the shared Veritas inspection overlay with
  source/citation/support-count read-back.
- [~] [memory-edit-pause-forget](./memory-edit-pause-forget.md) — page fixed in
  `adae8117dd`; `/v1/memory` BFF endpoint added in `03d45f0ad7`
- [~] [crisis-aware-tone-policy](./crisis-aware-tone-policy.md) —
  `/v1/safety/crisis-resources` BFF endpoint added in `03d45f0ad7` (returns
  Befrienders / Crisis Text Line resources)
- [~] [citation-drift-resolution](./citation-drift-resolution.md) —
  `/v1/veritas/drift` BFF endpoint added in `03d45f0ad7`

### Persona / Psyche (2)

- [~]
  [persona-voice-avatar-approval-workflow](./persona-voice-avatar-approval-workflow.md)
  — `/profile/persona` rebuilt in `9ba3d0823d` with three voice rows (Warm
  cream, Evening tea, Bright stone), provider + approval-state chips, inline
  audio previews; PERSONA_VOICE_FIXTURE now carries `activeVoiceId` so the
  active row is highlighted.
- [~]
  [psyche-tutor-live-session-to-graded-record](./psyche-tutor-live-session-to-graded-record.md)
  — `/metis/session` rebuilt in `8ad5d6a4df` to pick the highest-priority lesson
  (assessmentReady wins) as the lead and queue the next two; total estimated
  minutes in the masthead.

### Messaging / Telegram (3)

- [~] [telegram-bot-assistant-delivery](./telegram-bot-assistant-delivery.md) —
  `telegram-webhook-delivery` drives the real BFF webhook: secret gate,
  rate-limit trigger, slash commands, crisis persona swap, grounded real-source
  answer, honest abstention, fail-closed grounder throw paths, fail-closed voice
  STT, successful voice-transcript crisis interrupt, Postgres-backed audit-sink
  persistence, membership and callback branches; `/profile/telegram` supplies
  the linked/unlinked management panel, including client-side expired deep-link
  disablement and refresh recovery.
- [x]
  [messages-center-deliver-and-unsubscribe](./messages-center-deliver-and-unsubscribe.md)
  — deep real-BFF, live-browser, and focused durability proof covers the awaited
  dispatch seam, policy gates, restart-safe inbox/follow/read/archive, shell
  projection, exact-pair suppression, durable delayed work, manual replay,
  continuity export, and exact-subject erasure. Automatic scheduling,
  multi-writer arbitration, upstream production, and external provider delivery
  remain explicitly outside the result.
- [~]
  [messages-quiet-hours-and-channel-binding](./messages-quiet-hours-and-channel-binding.md)
  — deep control-plane proof covers the four-channel/five-category read-only
  summary, mutable quiet-hours/domain editor, non-production email/SMS/WhatsApp
  preview-code lifecycle, Telegram HMAC seam, and durable message-center
  delay/replay/safety/erasure branches. Required binding and Telegram user-state
  writes add restart, rollback, exact-subject fencing, export/erasure, and
  adjacent-user proof; durable device tokens join session export/erasure. The
  result separates the independently durable master, preference, binding,
  reminder, message-center, and Telegram snapshots from automatic replay,
  production `missing-config` code delivery, identity convergence, push-selected
  automatic reminder producers, independently supplied manual recipients, the
  static revoke phrase, and absent profile-bound provider/ cascade evidence.

### Resilience / PWA (3)

- [~] [multi-device-workspace-handoff](./multi-device-workspace-handoff.md) —
  deep evidence covers the workspace packet, local capture, per-user BFF
  mailbox, native Home consumer, responsive web restoration, and independent
  profile sync. The result remains partial because capture is not delivery
  acknowledgment, `/v1/devices` is an unjoined registration inventory, Library
  uses a fixture card, expiry is unenforced, and mobile return stops at an
  assistant prompt instead of reaching web.
- [~] [offline-first-time-use](./offline-first-time-use.md) — _re-walked_ in
  goal-4: the four runtime caches (`oshun-static-v4`, `oshun-media-v4`,
  `oshun-bff-v4`, `oshun-runtime-v4`) materialize on first visit to /welcome, so
  the offline shell foundation is there. Later real-infra Playwright coverage
  drives cached shell navigation, false-online `/healthz` failures, deep-route
  offline fallback controls, local offline library edits, and the real `sw.js`
  IndexedDB background-sync queue replaying an Arete check-in through the live
  BFF after an offline reload; the PWA update prompt now also renders the
  pending service-worker queue count and held-write copy, and
  `offline-shell-routes` proves auth/session endpoints remain network-only under
  the real service worker even when matching cache-poison responses exist. The
  same spec now proves a truly uncached deep route receives a successful
  real-service-worker document response from the cached shell and hydrates the
  retry/cached-route fallback controls from that service-worker marker,
  including the durable Cache Storage target marker used after hydration; it
  also drives profile Active devices refresh while offline and asserts the exact
  network-only denial copy, plus fresh/expired Nisaba 24-hour offline BFF cache
  response behavior under the real service worker. `nisaba-split-view` now also
  drives the live lexicon/morphology inspector offline and asserts cached term
  forms remain visible while the online-only lookup shows "Available when
  online."
- [x] [pwa-update-flow](./pwa-update-flow.md) — _re-walked_ in goal-4: `<h1>` on
      `/` is "Good afternoon, there. Recover the shape of the day." (the proper
      hero greeting, was misattributed to PwaUpdatePrompt copy in earlier
      walks); `PwaUpdatePrompt.tsx` uses `<h2>`, not `<h1>`, so it cannot hijack
      a hero heading. Later real-infra Playwright coverage now drives the staged
      update prompt, apply→`controllerchange`, two open tabs reloading exactly
      once while preserving their own URLs, standalone cold-start relaunch with
      an active worker and no update prompt, an Arete in-flight BFF check-in
      that refetches as done after refresh, raw service-worker queued-write
      replay, real `sw.js` stale-cache purge, queued-write update-prompt note,
      and reduced-motion spinner behavior. Remaining PWA-update telemetry is now
      covered by `pwa_update_applied` for Refresh-now and silent cold-start
      paths plus `pwa_sync_queued` for the real pending service-worker queue
      row.

### Account / Identity (2)

- [~] [aaa-upgrade-entitlement-bounce](./aaa-upgrade-entitlement-bounce.md) —
  `/v1/entitlements/aaa` BFF endpoint added in `03d45f0ad7`; `/aaa-upgrade` page
  is the redirect-to-Yemaya-Studio surface (intended, not a bug)
- [~] [account-deletion-and-dsar](./account-deletion-and-dsar.md) —
  `/profile/data` rebuilt in `9ba3d0823d` with live consents (three rows), prior
  exports (sha256 + bytesEncoded), pending deletions; pulls from new
  `/v1/data-rights/{consent,exports,deletions}` BFF endpoints.

### Trust + Safety (2)

- [~] [user-flag-to-review](./user-flag-to-review.md) — flag flow exists on
  Veritas / Nisaba / Tara surfaces; `/v1/user-reports` now routes submitted
  reports into the admin moderation `userReports` queue and the focused browser
  E2E reads the live `cust-ur-*` record back. The same real-BFF spec now covers
  moderator decision, audit-search read-back, and reporter-scoped receipt
  updates, then opens `/profile/safety` to verify the browser-visible submitted
  report receipt row and `/messages` to verify the in-app decision notification,
  Safety Center deep-link follow, and clicked receipt. Actor suspension,
  second-reviewer signoff, external push/email delivery, appeal, crisis/severity
  classification, brigade rate-limits, and remaining origin surfaces stay open.
- [~] [incident-triage](./incident-triage.md) — `/operator/incidents` rebuilt in
  `9ba3d0823d` with a real two-lane table (open vs recently-closed),
  severity-coloured chips (p0 red → p3 soft), MONO_L uppercase mitigation state;
  INCIDENTS_FIXTURE filled with two named incidents.

### Tenant admin (7)

- [~] [tenant-onboard](./tenant-onboard.md) — `/v1/tenants` and
  `POST /v1/tenants/onboard` were added in `03d45f0ad7`; tenant CRUD UI lives in
  the separate `apps/oshun/tenant-admin` application.
- [~] [tenant-bulk-member-invite-scim](./tenant-bulk-member-invite-scim.md) —
  `/operator/tenants` rebuilt in `9ba3d0823d` with a real roster sorted by
  memberCount; TENANTS_FIXTURE filled with House + Oxbow Foundation + Redbird
  Institute (184 + 41 members), plan tier displayed. Real-BFF/Postgres
  Playwright now covers SCIM Users lifecycle, SCIM Groups membership sync, and
  SCIM Bulk request sequencing, with SCIM audit events read back through the
  real admin audit-log API.
- [~] [tenant-bulk-operations-export](./tenant-bulk-operations-export.md) —
  dedicated V1 admin bulk operations/export journey added. The real-BFF spec
  covers platform scope gates, users bulk-operation
  validate/dry-run/stage/commit with real row-level commit outcomes,
  entitlements bulk-operation commit into `/v1/profile` plan read-back, rosters
  bulk-operation commit into `/v1/admin/lms/oneroster` read-back, unsupported
  content commit failure without false `committedAt`, validation-error blocking,
  per-operator isolation, content JSON export manifest creation/read/verify,
  persona-assignment commit into `/v1/personas/active`, export matrix failures,
  and audit-search read-back. Tenant/operator upload-preview UI, CSV parsing,
  residency metadata integration, retention/release handoff, and real commit
  executors for content and taxonomy beyond loud failure remain open.
- [~]
  [tenant-integrations-api-keys-webhooks](./tenant-integrations-api-keys-webhooks.md)
  — dedicated V1 section 20.6 journey added for tenant/operator integration
  management. The real-BFF spec now covers platform-admin scope gates, API key
  create/rotate/revoke with raw-token non-leakage, downstream `x-oshun-api-key`
  tenant-resource auth with tenant/scope/IP/revoked boundaries and `lastUsedAt`
  read-back, webhook create/signed sandbox simulator/inactive fail-closed
  simulator, outbound dispatch handoff, partner receipt
  retry/dead-letter/success outcomes, non-sandbox simulator rejection, connector
  upgrade, real connector health probes, malformed payload rejection, and
  audit-search read-back. Tenant-admin UI controls and autonomous outbound
  retry/replay workers remain open.
- [x] [tenant-oneroster-roster-sync](./tenant-oneroster-roster-sync.md) —
      dedicated journey added for the V1 OneRoster leg. The real-BFF spec now
      covers tenant-console-scoped dry-run, conflict reporting, apply commit,
      list read-back, periodic SIS pull reconciliation, duplicate commit/pull
      rejection, malformed payload rejection, and conflict fail-closed behavior,
      including `tenant.oneroster.commit.applied`,
      `tenant.oneroster.pull.reconciled`, and
      `tenant.oneroster.pull.conflicts_detected` audit-log read-back plus
      duplicate/conflict no-phantom-audit guards. `/operator/lms` now covers the
      dedicated operator diff table through real
      `/v1/admin/lms/oneroster/preview`, including clean diff rows, blocked
      conflict rows, and no-mutation read-back.
- [~]
  [tenant-sso-config-saml-oidc-claim-mapping](./tenant-sso-config-saml-oidc-claim-mapping.md)
  — `/operator/sso` now renders live `ssoConnectionStore` cards seeded by real
  admin SSO writes; active/pending colour coding, IdP metadata URL, and
  last-sync timestamp are covered without the retired static SSO fixture. The
  browser editor also persists every claim slot and transform picker value
  through the live admin SSO BFF, and the browser Test action renders reachable
  plus fail-closed probe verdicts from the real admin SSO BFF.
- [~] [tenant-audit-log-investigation](./tenant-audit-log-investigation.md) —
  `/operator/audit` rebuilt in `9ba3d0823d` as a real table (when/actor/
  action/target) sorted newest first; AUDIT_FIXTURE has three events spanning
  incident.acknowledge, sso.connection.activated, tenant.member.added.

### Editorial / Themis (2)

- [~] [editorial-review-approval](./editorial-review-approval.md) —
  `/lilith-studio` gates correctly and `/operator/admin` renders the review
  queue. Current specs cover the audited decision panel and release-stream API;
  the author-side submit/publish leg remains partial.
- [~] [themis-assessment-appeal](./themis-assessment-appeal.md) — real
  `/v1/metis/integrity/*` appeal route + resolve/adjudicate HTTP coverage now
  drives filed appeal, operator resolve, teacher overturn, teacher uphold, audit
  read-back, validation/scope failure gates, and customer
  `/v1/metis/assessment-submissions` submit→Themis adjudication→appeal handoff,
  learner-safe audit rationale/evidence/classifier detail, and `/operator/metis`
  live appeal queue/read/outcome-decision UI, upheld-without-client-
  `teacherOverride`, `/messages` decision notification read/follow/mark-read
  coverage, and terminal gradebook correction read-back; no current
  `themis-assessment-appeal` gaps remain tracked

### Platform integrations (1)

- [x] [lms-connectors-operator](./lms-connectors-operator.md) — deep E2E
      coverage verifies tenant/platform scope gates, descriptor validation,
      managed connector lifecycle, environment override/restore, secret-free
      read-back, fail-closed LTI launch, the live `/operator/lms` roster, and
      the OneRoster preview table.

## Summary

- Total: 58
- Walked: 4 (`onboarding-ten-steps`, `pwa-update-flow`,
  `tenant-oneroster-roster-sync`, and `lms-connectors-operator`)
- Partial: 54 (after goal-3 + goal-4 — every surface renders, every `/v1/*`
  endpoint returns a typed shape with real fixtures, every form POSTs to a real
  BFF endpoint with 422 + 202 branches, and the four formerly-blocked PWA/Studio
  journeys reclassify to `[~]` after goal-4 re-walk)
- Failed: 0
- Blocked: 0 (the previously-blocked `install-as-pwa`, `pwa-update-flow`,
  `offline-first-time-use`, `lilith-studio-tara-scene-publish` were all
  re-walked in goal-4 and confirmed unblocked; the live downstream flows that
  depended on real systems are now noted inline rather than carrying a separate
  `[B]` marker)
- Skipped: 0
- Remaining: 0

## External-dependency decision records

Goals 5–7 opened seven runbooks for work that then required either an external
service choice or a canonical contract decision. They remain under
[`external-dependencies/`](./external-dependencies/README.md) as dated decision
records:

- External runtime/provider work: `crypto-merchant-settlement`,
  `real-sit-audio-cdn`
- Contract decisions now implemented in `libs/contracts`:
  `nyx-logged-observation-contract`, `library-collection-contract`,
  `atelier-scene-contract`, `studio-scene-contract`,
  `metis-course-proposal-contract`

The index distinguishes historical closure context from current gaps; it no
longer presents the five shipped contracts as absent.

## Goal-3 build-out summary

Following the goal-2 stub-coverage pass, every previously-stub sub-route page
was rebuilt as a real Lilith-design-system surface fed by the BFF. Highlights:

- **Server-side BFF helper** — `apps/oshun/web/src/lib/server/bff-fetch.ts`
  forwards the `oshun-session` / `__session` cookie from the RSC request, caches
  at 60s revalidate, and returns `null` on failure so callers fall back to
  fixture data without crashing the route.
- **Real list and form views** — every sub-route now renders the cream-paper,
  terracotta-accent masthead pattern with live BFF data: `/arete/habits` (list +
  check-in chips), `/arete/habits/new` (proposal form), `/arete/offerings`
  (drafts + sent), `/nyx/tonight` (timeline with accent lead),
  `/nyx/observation` (POST log form), `/nyx/events` + `/events` (cross-domain
  agenda + ICS subscribe), `/profile/{data,notifications,persona,telegram}`,
  `/operator/{incidents,audit,sso,tenants}` (real tables with severity color
  coding), `/metis/{lessons,session,ingest,courses/new}`, `/veritas/evidence`
  (drift + retraction two-pane), `/sophia` (witness-anchored answer),
  `/nisaba/{notebooks,notebook/new}`, `/atelier/{camera-obscura,new}`,
  `/library/collections/{,new}`, and `/lilith-studio/{tara,scene/new}`.
- **New write endpoints** in `apps/oshun/bff/src/routes/domain-stubs.ts` with
  422 validation branches and 202 accepted state: `POST /v1/arete/habits`,
  `POST /v1/nyx/observations`, `POST /v1/metis/courses`,
  `POST /v1/library/collections`, `POST /v1/atelier/scenes`,
  `POST /v1/lilith-studio/scenes`.
- **Enriched fixtures** — `INCIDENTS_FIXTURE`, `AUDIT_FIXTURE`, `SSO_FIXTURE`,
  `TENANTS_FIXTURE`, `LIBRARY_ITEMS_FIXTURE`, `LIBRARY_COLLECTIONS_FIXTURE`,
  `ATELIER_JOBS_FIXTURE`, `ATELIER_SCENES_FIXTURE`, `PERSONA_VOICE_FIXTURE` all
  now contain realistic rows so the new pages render with meaningful content out
  of the box.
- **Alias cleanups** — `/arete/weekly` → 301 to `/arete/review`; `/metis/upload`
  → 308 to `/metis/byom`.
- **Prod build unblocked** — `node:crypto` was finally severed from the client
  bundle (`@noble/hashes/sha2` in `provenance-bundle-helpers.ts` plus a
  `webpack.NormalModuleReplacementPlugin` backstop for any remaining workspace
  lib that gets pulled in via a barrel re-export). `pnpm build` emits
  `.next/BUILD_ID` for all 700+ routes.
- **Build noise** — removed the Next-15-only `typedRoutes` + `turbopack`
  top-level keys from the Next-14 config; suppressed the onnxruntime-web
  "Critical dependency" warning narrowly via `config.ignoreWarnings`.
- **CC-BUG-E remediated** — in-memory dev customer-auth store now defaults
  `emailVerified: false` so it mirrors production; tests can opt back in with
  `OSHUN_DEV_AUTO_VERIFY_EMAIL=true` or `NODE_ENV=test`.

## Goal-4 + 5 build-out summary

Followup work after goal-3 to close the remaining gaps the previous "what's
left" audit named:

- **bffGet cookie names corrected** —
  `apps/oshun/web/src/lib/server/bff-fetch.ts` was forwarding `oshun_session`
  (underscore) which the Next.js proxy never sets. Replaced with
  `oshun-session` + the `__session` Vercel-style fallback, matching
  `apps/oshun/web/src/proxy.ts`.
- **Mobile responsive** — appended a single `@media (max-width: 720px)` block to
  `globals.css` that targets React's serialized inline `grid-template-columns`
  strings so all 27 new sub-route pages collapse to single column on phones with
  reduced padding; zero source edits to the pages themselves.
- **Accessibility pass** — every toggle group (cadence/conditions/source-
  kind/visibility/scene-kind) now wraps in `role="radiogroup"` + `aria-label`;
  every accepted-state success card carries `role="status"` and
  `aria-live="polite"`; toggle buttons have focus-visible terracotta outlines.
- **CSRF token + cookie pair** — new `GET /v1/csrf` mints a 64-char hex token in
  `oshun-csrf` cookie (Path=/, SameSite=Lax, Secure-when-https); `csrfGuard`
  preHandler chained after `originGuard` on every state-changing POST rejects
  403 `csrf_token_invalid` on missing/mismatched tokens. Client cache in
  `apps/oshun/web/src/lib/csrf.ts` does the handshake once with single-flight
  inflight handling. All 8 new client forms updated to send the token. The
  earlier origin-only check stays as the floor.
- **File-backed persistence** — the in-memory store from goal-3 (which wiped on
  BFF restart) now writes to a single JSON snapshot at
  `${HOME}/.oshun-dev/domain-stubs-store.json` (or `OSHUN_DEV_STUBS_STORE_PATH`)
  via atomic rename. `NODE_ENV=test` falls back to pure in-memory. Real Prisma
  persistence stays a follow-up because the canonical AreteHabit schema carries
  tenant + tombstone + audit semantics that would force a `prisma migrate dev`
  run against the shared dev database, risky for parallel worktrees.
- **`node:crypto` → `@noble/hashes` in client-transpiled libs** — migrated
  `lora-manager.ts`, `evidence-sophia/source-{set,lifecycle}.ts`,
  `messaging-channels/telegram/security.ts` (HMAC + timing-safe equal +
  base64url all rewritten), `privacy/export.ts`,
  `platform-foundations/oauth.ts`, `persistence/migration-plan.ts`. The other
  ~810 importers are server-only; the `NormalModuleReplacementPlugin` backstop
  in `next.config.mjs` still covers them. Also bulk-fixed
  `ignoreDeprecations: "6.0" → "5.0"` across 128 lib + V4 + tools tsconfigs.
- **Dev-session bypass** — `POST /api/dev/seed-session` provisions a real
  signed-in session for Playwright tests; sets both `oshun-session` and
  `oshun-access` cookies. Disabled in production. Verified end-to-end: seeded
  session, then walked /, /tara, /arete/habits, /nyx/tonight, /profile/data —
  all return 200 with the correct h1, no /welcome bounce, no reauth loop.
- **Test coverage** — 54 vitest specs for the goal-3 BFF surface
  (`domain-stubs-route.test.ts` + `domain-stubs-store.test.ts`): GET shape
  contracts, POST 422/202 branches, meaningful fixture content, CSRF guard
  cases, file-backed round-trip + rehydrate, corrupt-snapshot recovery.
- **Tracker housekeeping** — the four formerly-blocked PWA/studio journeys
  reclassified `[B]` → `[~]` after goal-4 re-walk; blocked count now 0.

## Goal-2 build-out summary

Commits `03d45f0ad7` (BFF + pages) and `e25187874a` plus the build-fix sequence
brought every previously-blocked journey to "partial" by adding:

- **~40 BFF stub endpoints** in `apps/oshun/bff/src/routes/domain-stubs.ts` —
  every `/v1/*` URL referenced by a journey spec now returns a typed JSON shape
  derived from the same fixtures the customer surfaces use
- **27 sub-route stub pages** under `apps/oshun/web/src/app/` — Arete
  habits/offerings/weekly, Nyx tonight/observation/events, Nisaba
  notebooks/notebook-new, Metis lessons/session/upload/ingest/courses-new,
  Veritas evidence, Sophia, Atelier rooms + new, Library collections, Profile
  data/notifications/persona/telegram, Operator incidents/audit/sso/tenants,
  Lilith-Studio tara/scene-new — each renders with a proper h1 and related-route
  navigation
- **Trimmed barrels**: `@oshun/memory-iris` (multi-actor),
  `@yemaya/living-scenes-runtime` (cue-privacy / personal-artifacts / envelope),
  `@yemaya/remote-film-capture` (56 cross-domain integration files) —
  server-only modules importing `node:crypto`, `onnxruntime-web`, or
  `@aja/* @aphrodite/* @maya/* @isis/* @bellona/* @oya/* @uzume/* @calliope/* @hathor/* @iris/*`
  shim packages no longer get pulled into client bundles via barrel re-exports
- **Webpack aliases**: `onnxruntime-web → dist/ort.min.js` (browser CommonJS
  bundle) so SSR doesn't choke on the `.mjs` entry that declares
  `import { createRequire } from "module"` at top level

## Goal-2 conclusion (historical)

At the end of goal 2, the web app's customer surfaces rendered correctly in
development after the fixes listed below. The remaining gaps at that checkpoint
were feature or external-runtime work rather than broken routing.

**Now works that didn't before**

- Anonymous funnel: `/` → `/welcome` → signup → `/onboarding` → `/` and `/tara`
- All 9 domain hubs render with proper `<h1>` for screen readers (`/`, `/tara`,
  `/arete`, `/veritas`, `/nyx`, `/nisaba`, `/metis`, `/atelier`, `/lilith`)
- `/tara/sit/<id>` player has h1 = sitting title (was missing)
- `/welcome` mode tabs are real `[role="tablist"]` with arrow-key nav
- `/landing` pricing CTAs deep-link to
  `/welcome?mode=signup&entry=marketing-landing&tier=…`
- Tara → Nisaba, Veritas → Nisaba, Nyx → Tara cross-domain bridges, including
  Nyx event-detail → Tara start telemetry
- `/scene/<id>` tombstone + embed surface (P0 `'use server'` bug fixed)
- `/scene/*` titles single-suffix " | OSHUN" (was double)
- `/profile/memory` no longer crashes the dev server (`node:crypto` bundling
  fixed)
- `/billing` index page exists (was 404)
- PWA Service Worker registers + activates (install handler precache no longer
  fails on `/`'s 307 redirect)
- PWA manifest theme/bg color matches Lilith cream (#f1ebdd)
- Hydration is clean — no more 100+ console errors per render from the
  cookie-icon className mismatch
- BFF feature-flag rate limit no longer trips on normal browsing
- All public OpenGraph / Twitter card / JSON-LD metadata correct
- Sign-up API works, sets 3 cookies, navigates to /onboarding
- `/search?q=meditation` returns 13 results
- `/library` renders 10 items
- `/arete/streak` Lilith tone copy verified (recovery framing, no shaming)
- `/operator/admin` renders grounded-answer review queue

**Needed deeper feature implementation, not surface fixes**

- The new sub-route pages render real data from the BFF, but the deepest write
  flows still depend on real downstream systems: crypto invoice settlement
  events, SCIM provisioning sync, agent orchestrator job execution, real audio
  for sit completion, real ONNX models for fine-detail matting, real Telegram
  bot for the link round-trip. The BFF surfaces them as 202-accepted stubs.
- The four formerly blocked journeys — `install-as-pwa`, `pwa-update-flow`,
  `offline-first-time-use`, and `lilith-studio-tara-scene-publish` — were
  re-walked after CC-BUG-C and the studio editor route were fixed. They are now
  `[x]` or `[~]`; none remains blocked on the original failure.
- Tenant admin (SCIM, SSO, audit) — lives in `apps/oshun/tenant-admin` per the
  product architecture, outside the main customer shell.

**Walker artifacts (not bugs)**

- "Cookies after accept (0)" — consent stores in localStorage, not cookies;
  persistence verified working
- "Banner reappears after reload" — old walker selector matched any "Accept"
  button; with proper selector the banner stays dismissed
- Mid-test "reauth=1" ejection — Playwright test-race when BFF restarts during a
  long walk wipes in-memory sessions; verified with API signup that real
  sessions survive

## Cross-cutting findings (apply to many journeys)

These bugs were surfaced by journey 1 but affect most signed-in journeys —
re-tested journeys do not need to re-document them, just cross-link:

- **CC-BUG-A (P0)** — _fixed_ in `a2908f1c89` + `3f130c64f1`. Prod `pnpm build`
  now succeeds end-to-end and emits `.next/BUILD_ID` for all 700+ routes. Root
  causes resolved: (1) `libs/contracts/src/common/provenance-bundle-helpers.ts`
  swapped `createHash('sha256')` for `@noble/hashes/sha2` so the contracts
  barrel no longer drags `node:crypto` into the client bundle; (2)
  `next.config.mjs` installs a `webpack.NormalModuleReplacementPlugin` that
  remaps any remaining `node:*` URL-scheme imports to a Proxy-backed CommonJS
  stub (`apps/oshun/web/src/lib/server/node-crypto-stub.cjs`) — this is the
  backstop for every other workspace lib that gets pulled into the client bundle
  via a barrel re-export; (3) `tsconfig.base.json` +
  `apps/oshun/web/tsconfig.json` `ignoreDeprecations: "5.0"` (the "6.0" value
  would only be accepted by TS 6).
- **CC-BUG-B (P0)** — _fixed_ in `adae8117dd`. Hydration mismatch came from the
  workspace-hoisted lucide-react v0.344 (trailing-space className) being used by
  webpack SSR while client used the local v0.469. Added a webpack
  `resolve.alias` so both passes resolve to the app-local copy.
- **CC-BUG-C (P0)** — _fixed_ in `adae8117dd`. SW now installs + activates. Root
  cause was two bugs: `sw.js` install handler called `cache.addAll(['/' ...])`
  and `/` returned 307 → addAll rejected → SW went `redundant`; AND
  `PwaBootstrap.useEffect` only registered when
  `document.readyState === 'complete'` but post-hydration it's `interactive`.
  Removed `/` from precache and broadened the readyState check to
  `!== 'loading'`.
- **CC-BUG-D (P1)** — _by design / transient_. Re-investigated: BFF accepts its
  dev tokens correctly (`/v1/profile` returns 200 with valid Bearer token). The
  401s in walks were initial-mount races (page fires the fetch before
  AuthContext populates the token; React Query retries successfully on the
  second attempt). Not a real bug; pages do see empty-shell flash briefly before
  populated.
- **CC-BUG-E (P1)** — _addressed_ in this turn. The in-memory dev customer-auth
  store no longer hard-codes `emailVerified: true` at signup. The default flips
  to `false` so the dev store mirrors production; integration tests that need
  the legacy auto-verify behavior can set `OSHUN_DEV_AUTO_VERIFY_EMAIL=true` (or
  rely on the automatic exemption when `NODE_ENV=test`). See
  `apps/oshun/bff/src/auth/customer-auth-store.ts` `signUp(…)`.
- **CC-BUG-F (P2)** — _fixed_ in `adae8117dd`. BFF `/v1/feature-flags/evaluate`
  budget lifted from 60/min to 600/min so normal signed-in browsing doesn't trip
  the abuse-protection limiter.
- **CC-BUG-G (P0)** — _fixed_ in `adae8117dd`. `libs/oshun/memory-iris`
  barrel-re-exported `multi-actor/namespace` which imports `node:crypto`; any
  client bundle that touched `@oshun/memory-iris` (including `/profile/memory`)
  blew up. Removed multi-actor from the barrel.
- **CC-BUG-H (P1)** — _fixed_ in `adae8117dd`. Domain hub pages (`/tara`,
  `/arete`, `/nyx`, `/nisaba`, `/metis`, `/atelier`, `/lilith`) and the Tara sit
  player rendered their primary display text as styled `<div>`s instead of
  `<h1>` — a11y regression. `LDisplay` and `LMasthead` now default to rendering
  as `<h1>` (with `as` / `titleAs` overrides for nested displays); `/nisaba` and
  `/metis` inline display divs converted to `<h1>` too.
- **CC-BUG-I (P2)** — _fixed_ in `adae8117dd`. `/scene/*` titles double-suffixed
  " | OSHUN | OSHUN" because page metadata returned strings already ending in "
  | OSHUN" while the root layout's title template wrapped them again.
- **CC-BUG-J (P1)** — _fixed_ in `860a554b4e`. Cross-domain bridges
  (Tara→Nisaba, Veritas→Nisaba, Nyx→Tara) were missing from the hub pages. Added
  optional `nisabaPassageCue` / `nisabaDeepReadCue` / `taraGroundingCue` slots
  to the data contracts + render bridges in `rooms.tsx`.
- **CC-BUG-K (P1)** — _fixed_ in `860a554b4e`. `/landing` pricing CTAs now
  deep-link to `/welcome?mode=signup&entry=marketing-landing&tier=…` instead of
  bare `/welcome` (per-tier funnel attribution).
- **CC-BUG-L (P2)** — _fixed_ in `860a554b4e`. Manifest theme + bg color was
  dark navy (#020617); fixed to cream (#f1ebdd) so standalone PWA splash matches
  the Lilith design system.
- **CC-BUG-M (P1)** — _fixed_ in `ead9a957f7`. `WelcomeAuthPanel` mode buttons
  now have proper `[role="tablist"]` / `[role="tab"]` / `aria-selected` /
  arrow-key navigation.

## Method

For each journey I:

1. Read `WALKTHROUGH/journeys/<journey>.md` for steps + per-view file refs
2. Drive Playwright (chromium, headless by default) through each step
3. Capture a screenshot per major step into the screenshots dir
4. Mark each numbered step pass/fail with observed behavior and the actual URL,
   selector, telemetry event seen vs. expected
5. Note any divergence from the spec — wrong copy, missing CTA, broken link,
   crashed page, unimplemented feature, accessibility gap
6. Update the status checkbox in this README

A journey is only `[x]` walked when every numbered step verified. Anything short
of that gets `[~]`, `[F]`, or `[B]` with the specific failure.
