# V1 Documentation Audit — 2026-06-24

**Scope:** `V1/features.md` (6,252 lines) and `V1/ARCHITECTURE.md` (2,242
lines). **Method:** a 27-area, code-grounded audit. Each product area of both
documents was read against the _real_ implementation (the `libs/oshun/*` adapter
libs, the top-level domain monorepos under `libs/*`, the `apps/oshun/*`
surfaces, the BFF route registrars, and `libs/contracts`) and cross-checked
against the latest reality artifacts in `WALKTHROUGH/results/`
(`v1-completeness-audit-2026-06-22`, `v1-real-infra-run-2026-06-22`,
`v1-triage-2026-06-23`). Every finding below was confirmed by reading code, not
inferred from prose.

This document is the **review/audit ledger**. The corrections and enrichments it
catalogues were applied in the decomposed, refined pages under
[`V1/architecture/`](./architecture/README.md) and
[`V1/features/`](./features/README.md); the two monolithic files
([`features.md`](./features.md), [`ARCHITECTURE.md`](./ARCHITECTURE.md)) remain
as navigation hubs that preserve every heading anchor.

## Findings at a glance

| Finding type                                  | Count | Disposition in the refined pages |
| --------------------------------------------- | ----: | -------------------------------- |
| Inaccuracies (doc claim the code contradicts) |    79 | corrected to match code          |
| Internal / cross-doc contradictions           |    36 | reconciled                       |
| Staleness (dated facts, drifted counts/names) |    48 | refreshed to current state       |
| Enrichment gaps (real code under-described)   |   159 | added as new richer prose        |
| Code-verified grounding facts captured        |   448 | woven into the rewrites          |

> The audit also re-verified the prior remediation log
> ([`REMEDIATION_2026-06-12.md`](./REMEDIATION_2026-06-12.md)): the
> six-substrate count, the Aje glossary entry, and the Bellona/Hathor/Neith
> Studio-only rows are all confirmed correct against code.

## Executive summary — cross-cutting themes

1. **Stale dating.** Both docs carry `Date: 2026-05-11` and assert a workspace
   snapshot from that date. The codebase has moved on materially (new shell
   libs, a live `/domains/[domainId]` catch-all serving Nisaba and Metis, the
   2026-06-22/23 infra runs). The refined pages drop the absolute "as of"
   freezing and describe current behaviour.

2. **Route-prefix drift.** Several diagrams say the BFF exposes per-domain
   routes under `/api/oshun/domains/{...}`. The real canonical prefix is
   **`/v1/<domain>/*`** (e.g. `/v1/tara/sessions/:id/guidance`,
   `apps/oshun/bff/src/tara/ambient-audio-routes.ts`); `/api/oshun/domains/...`
   exists only for the Veritas retraction cascade. Corrected throughout.

3. **Domain tiering vs "first-class" framing.** Both docs present all six
   customer domains as co-equal and "first-class." The real
   `@oshun/domain-registry` (`libs/oshun/domain-registry/src/registry.ts`)
   encodes `DomainAvailability = 'active' | 'beta' | 'planned'`:
   **Tara/Veritas/Arete = active, Nyx/Nisaba = beta, Metis = planned**, and
   `getAvailableDomains()` excludes `planned`. The "Metis is launch-blocking"
   framing is in direct tension with its `planned` status; the refined pages
   state the tiering honestly.

4. **Provider-gated honesty (9 areas).** Generation
   (Civitai/ComfyUI/RunPod/LoRA), voice/music, 3D, and crypto-settlement
   features are partly **provider-gated or not-yet-wired** behind real fail-loud
   seams rather than fully shipped. The rewrites preserve and sharpen this
   candor ("planned / gated" beats "shipped") instead of over-claiming.

5. **Unanchored cross-references.** Many "See Living Scenes for the full
   surface" style pointers are bare prose with no `#anchor`. The decomposition
   replaces these with real relative links between the new pages.

6. **Contract surfaces are namespace re-exports, not per-domain dirs.** Some
   `libs/contracts/<domain>` directories are effectively empty (`.gitkeep`); the
   real contracts are re-exported as namespaces (e.g. `NisabaContracts`) from
   `@oshun/contracts` (`libs/contracts/src/index.ts`). Paths corrected.

## Per-area findings

### meta-glossary

**Real vs aspirational.** The glossary itself is real, well-grounded product
vocabulary — every named subsystem corresponds to a real lib or app I verified
by reading package.json. What is aspirational/over-flattened is the framing
language: the prose calls all six domains 'first-class' and implies parity,
while the code encodes a tiering (active/beta/planned) where Metis is 'planned'
(availability:'planned' at registry.ts:489) and is excluded from launch domain
config but kept visible in shell nav. The substrate naming is honest: the
top-level libs/{sophia,iris,psyche,lilith,isis} are sprawling multi-package
monorepos with NO root package.json (they are NOT '@oshun/\*' packages); the
actual V1-consumed implementations are the thin @oshun/<verb>-<substrate>
adapter libs under libs/oshun/, which both docs do correctly point at in the
mermaid sublabels. I could not find any fabricated subsystem — every glossary
name resolves to real code.

**Inaccuracies corrected**

- `features.md:268-269 / ARCHITECTURE.md:132-135 (V1 Product Promise) and features.md:21-22`
  — claim: _Treats all six domains (Tara, Arete, Veritas, Nyx, Nisaba, Metis) as
  co-equal 'first-class Oshun domains' with no tiering_ → **reality:**
  libs/oshun/domain-registry/src/registry.ts encodes
  DomainAvailability='active'|'beta'|'planned': tara=active(166),
  veritas=active(225), nyx=beta(290), arete=active(355), nisaba=beta(420),
  metis=planned(489). getAvailableDomains() filters out 'planned'
  (registry.ts:504), so Metis is NOT launch-enabled — the glossary's own note
  'Launch-blocking V1 scope' (features.md:52) and registry 'planned' status are
  in tension.
- `ARCHITECTURE.md:221 (High-Level Architecture mermaid: 'Routes /api/oshun/domains/{tara, arete, veritas, nyx, nisaba, metis}')`
  — claim: _The BFF exposes per-domain routes under /api/oshun/domains/{...}_ →
  **reality:** The real canonical BFF domain routes are mounted at
  /v1/<domain>/\* — e.g. apps/oshun/bff/src/tara/ambient-audio-routes.ts
  registers '/v1/tara/sessions/:sessionId/guidance'. A
  /api/oshun/domains/veritas/... path exists only for the veritas retraction
  cascade (server.ts:590); the generic per-domain prefix in code is
  /v1/<domain>, not /api/oshun/domains/<domain>.

**Contradictions reconciled**

- (features.md glossary (Metis 'Launch-blocking V1 scope', line 52) vs
  domain-registry code) features.md calls Metis 'Launch-blocking V1 scope' while
  libs/oshun/domain-registry/src/registry.ts:489 sets Metis
  availability:'planned' and the test (index.test.ts:103) asserts 'planned Metis
  in shell navigation without enabling it for launch configuration'. The product
  doc's 'launch-blocking' framing contradicts the code's
  'planned/not-launch-enabled' status.
- (ARCHITECTURE.md:202-204 vs ARCHITECTURE.md:230 mermaid) Prose says 'Metis is
  the only V1 domain with its own dedicated apps and microservice stack beneath
  apps/metis/' and lists apps/metis/{web,admin,api-gateway,worker}; the real
  apps/metis/ also contains a 'mobile' app (ls apps/metis -> admin api-gateway
  mobile web worker), which neither the prose nor the surface table at line 200
  enumerates.

**Staleness refreshed**

- `features.md:6 and ARCHITECTURE.md:7 (Date: 2026-05-11)` — Both docs are dated
  2026-05-11 and anchored to the workspace 'as of 2026-05-11'. The codebase has
  materially evolved since (e.g. /domains/[domainId] catch-all now serves
  nisaba+metis; shell-desktop & shell-achievements libs added; live triage
  findings dated 2026-06-23). Glossary counts and 'today' assertions are >6
  weeks stale.
- `features.md:98-102 (note that Bellona/Hathor/Neith were 'absent from the domain lists until the V1 route scope was reconciled (confirmed in-v1 2026-05-29)')`
  — Dated reconciliation note from 2026-05-29 left in the glossary; reads as a
  changelog artifact rather than current state.

_Captured 15 code-verified grounding facts for this area._

### surfaces

**Real vs aspirational.** Surfaces are overwhelmingly REAL, not aspirational.
Every app I checked has a package.json and substantial src/. The web app's PWA
stack (service worker, manifest, install/update logic) is implemented and
test-covered. The mobile apps are real Expo/Expo-Router projects with extensive
Maestro E2E and device-matrix scripts. The shell composition described in
ARCHITECTURE.md maps to real libs. The main documentation defects are STALENESS,
not fabrication: the doc's nisaba/metis-have-no-/domains-namespace claim has
been overtaken by the dynamic [domainId] route; and two real shell libs
(shell-desktop, shell-achievements) plus apps/oshun/content-service are
undocumented. The 'desktop' surface in particular (Electron-style
@oshun/shell-desktop with window-manager, tray-companion, protocol-handler,
update-manager, widget-engine, notification-bridge) is a whole surface class
neither doc mentions.

**Inaccuracies corrected**

- `features.md:318-319 ('Metis and Nisaba ship only at /<domain>/* today; their power-user surfaces are mounted inside the consumer hub rather than at a parallel namespace') and ARCHITECTURE.md:331-332 ('Nisaba and Metis do not yet ship parallel /domains/* namespaces; their deep tools are mounted inside the consumer hub')`
  — claim: _Nisaba and Metis have NO /domains/\* power-user namespace_ →
  **reality:** apps/oshun/web/src/app/domains/[domainId]/page.tsx serves all six
  domains including nisaba and metis (DOMAIN_META has nisaba+metis entries; uses
  isWebNavigableDomainId). apps/oshun/web/src/navigation/routes.ts:52-53 defines
  WEB_DOMAIN_IDS=['tara','veritas','nyx','arete','nisaba'] and
  WEB_NAVIGABLE_DOMAIN_IDS=[...WEB_DOMAIN_IDS,'metis'].
  DomainRouteExperience.tsx:66-67 explicitly lists 'nisaba','metis'. So
  /domains/nisaba and /domains/metis ARE reachable web routes (via catch-all,
  not static dirs).
- `ARCHITECTURE.md:354-365 (Shared Consumer Shell — libs/oshun/shell-*)` —
  claim: _The shared shell is 'Composed from' shell-core, shell-assistant,
  shell-routines, shell-wearable, navigation, design-tokens, ui — an
  exhaustive-looking list_ → **reality:** Two additional real shell libs exist
  and are omitted: libs/oshun/shell-desktop (@oshun/shell-desktop —
  desktop-engine, window-manager, tray-companion, protocol-handler,
  update-manager, widget-engine, notification-bridge, shortcut-manager) and
  libs/oshun/shell-achievements (@oshun/shell-achievements — achievement-engine,
  challenge-templates, social-accountability). Neither is mentioned in
  features.md or ARCHITECTURE.md (grep count 0).
- `ARCHITECTURE.md:327 ('Power-user deep tools at src/app/domains/{tara,arete,veritas,nyx}/*')`
  — claim: _The /domains/ namespace covers only tara, arete, veritas, nyx (four
  static dirs)_ → **reality:** The static dirs under
  apps/oshun/web/src/app/domains/ are arete, nyx, tara, veritas, PLUS [domainId]
  (dynamic catch-all) and layout.tsx. The dynamic route extends coverage to
  nisaba and metis, so the practical /domains/\* namespace is all six, not four.

**Contradictions reconciled**

- (features.md:318 vs features.md:300-307 / ARCHITECTURE.md:323-332)
  features.md:300-307 describes the dual-namespace pattern (/<domain> consumer
  hub + /domains/<domain>/\* power tools) as applying 'per domain', then
  features.md:318 carves out Nisaba+Metis as exceptions with no /domains
  namespace — but the code (routes.ts WEB_NAVIGABLE_DOMAIN_IDS, [domainId]
  catch-all) implements the dual namespace for nisaba and metis too, so the
  carve-out contradicts both the general pattern and reality.
- (ARCHITECTURE.md:204 vs reality) 'every other customer-facing domain renders
  through apps/oshun/web and apps/oshun/mobile' — accurate for web, but
  apps/metis/mobile also exists (a separate Metis mobile app), so Metis is not
  solely rendered through apps/oshun/mobile.

**Staleness refreshed**

- `ARCHITECTURE.md:188-200 (Surfaces table) and features.md Product Surfaces` —
  apps/oshun/content-service (package @oshun/content-service-app) is a real app
  surface absent from the surface table. apps/oshun/legal exists as a
  markdown-only surface (privacy-policy.md, terms-of-service.md, no
  package.json) — ARCHITECTURE.md:388 references apps/oshun/legal/ for the legal
  surface, which is correct, but it is a docs folder not an app.
- `ARCHITECTURE.md:343-352 (Customer Mobile) — '@oshun/shell-wearable' for wears/widgets/Live-Activity`
  — Accurate but partial: mobile E2E reality is Maestro-based
  (run-maestro-suite.sh, device-matrix) not the generic 'mobile E2E' the docs
  imply; admin-mobile is also a full Expo app (apps/oshun/admin-mobile,
  @oshun/admin-mobile, Expo Router app/(operator)/) which the surfaces narrative
  under-describes.

_Captured 17 code-verified grounding facts for this area._

### domain-tara

**Real vs aspirational.** Heavily REAL. The contract model is domain-specific,
not CRUD: per-mood recommendation slates with crisis-handoff superRefine rules,
breathwork cadences with inhale/hold/exhale seconds, lineage syncretism gates
requiring a comparative persona, a SessionState transition table, and a
ContinuationState with
programArc/teacherContinuity/themeContinuity/prerequisites. The domain adapter
and BFF layers are real and tested. ASPIRATIONAL / not verifiable in code: (1)
features.md:504 specifies a per-modality `drift_idle_seconds` threshold — the
SessionState `drifted` state and `driftDetectedAt` timestamp + a `drift`
event-type exist, but NO per-modality idle-seconds threshold constant exists in
the code I read; drift is modeled as an event, not a numeric per-modality
config. (2) Cross-device resume, watermarked download with attribution,
vibration-based pacing for hearing-impaired, and the full Living Scenes
'Contemplative Arc' card pacing-to-breath-cycle are spec-described and only
partially evidenced (companion components exist; full immersive arc runtime not
confirmed). (3) The audit (v1-completeness-audit-2026-06-22.md) rates
tara-daily-ritual / first-tara-sit / tara-to-nisaba-handoff as 'deep' coverage,
confirming the experiential spine is genuinely shipped, while several
cross-domain bridges remain unit-only.

**Inaccuracies corrected**

- `ARCHITECTURE.md:433 (Tara › Surfaces)` — claim: _Surfaces include
  `apps/oshun/mobile/.../tara/`_ → **reality:** The mobile app
  (apps/oshun/mobile/src) has NO `tara/` screen directory; it is organized by
  feature, and Tara appears as companion components (e.g.
  apps/oshun/mobile/src/components/TaraNyxPerspectiveCompanionCard.tsx,
  TaraVeritasSophiaCompanionCard.tsx) rather than a tara/ surface tree. The
  '.../tara/' path glob does not resolve to a real directory.
- `features.md:504 (Session state › drifted)` — claim: _drifted = 'idle beyond
  the per-modality `drift_idle_seconds` threshold'_ → **reality:** No
  `drift_idle_seconds` (or driftIdleSeconds/idleThreshold) identifier exists
  anywhere in libs/oshun/domain-tara/src or libs/contracts/src/tara. Drift is
  modeled as a RitualSessionEvent of type 'drift' that must transition into the
  'drifted' state (contracts index.ts:2390-2497) plus a nullable
  `driftDetectedAt` timestamp — there is no per-modality numeric idle threshold
  constant.

**Contradictions reconciled**

- (features.md:458 vs features.md:468-469 / code) features.md:458 lists the
  consumer hub as `/tara` only, but features.md:468 also references 'immersive
  session pages' and the real surface tree has `/tara/sit/[id]` for immersive
  sessions — the surface list at line 458 omits /tara/sit, which is the actual
  session page route.

**Staleness refreshed**

- `ARCHITECTURE.md:435-438` — The 'Key contracts (V1 must export)' list is
  accurate but understated/stale relative to reality: the real contracts file
  also exports TeacherProfile, the full canonical taxonomy datasets
  (TARA_MOOD_TAXONOMY, TARA_THEME_TAXONOMY, TARA_MODALITY_TAXONOMY,
  TARA_LINEAGE_TAXONOMY, TARA_CONTEXT_TAGS, TARA_DURATION_BUCKETS),
  BreathworkCadence, RitualSessionEvent, and Lilith tone-review schemas — none
  mentioned.

**Enrichment added (real code previously under-described)**

- The canonical taxonomy DATASETS (not just types) are exported as runtime
  constants — TARA_MOOD_TAXONOMY (12 entries with distressLevel +
  recommendationSlate + crisisHandoff), TARA_THEME_TAXONOMY (15 entries with
  compatibleMoods/defaultModalities), TARA_MODALITY_TAXONOMY (14 entries with
  family/requiresAudio/sensoryLoad/accessibilityFallback/contraindicationNotes/breathworkCadence),
  TARA_LINEAGE_TAXONOMY (8 lineages with real teachers like Buddhaghosa,
  Shantideva, Padmasambhava, Patanjali, Mirabai and scriptural citations like MN
  118, MN 10, Bodhicaryavatara). Docs describe the axes but not that these are
  shipped, validated reference datasets.
- The PlaybackRate contract (libs/contracts/src/tara/playback-rate.ts)
  implements the documented 0.85x-1.25x voice-speed policy as a real
  normalization function with PlaybackRateRangeError and a PlaybackRatePolicy
  {minRate, maxRate} — under-described as just 'voice speed' in features.md:536.
- The RitualSession state machine is a real transition table
  (SESSION_STATE_TRANSITIONS) with superRefine guards (e.g. drift events must
  enter 'drifted'); the audio-session-manager.ts (11KB) and audio-session.ts
  (22KB) implement the documented play/pause/scrub/mix/sleep-fade controls.
- ContinuationState's programArc has
  completedSessions/totalSessions/currentSessionIndex invariants and a
  prerequisite-blocking nextRecommendation — a richer model than
  features.md:507-508 conveys.
- Two separate library families back Tara: @tara/_ (content, config, api-client,
  monitoring, ui, features, analytics, database) and @oshun/meditation-_ (core,
  breathing, session, player, progress, timer, offline, analytics) — neither is
  named in the docs' package list.

_Captured 16 code-verified grounding facts for this area._

### domain-arete

**Real vs aspirational.** Heavily REAL and domain-specific. The streak treatment
is enforced by a status->treatment table with superRefine validation (e.g. done
requires 100% engagement, partial requires >0 and <100%, skip/decline require a
visible reason). evaluateAreteHabitRecovery (streak-recovery.ts:111) and
countMissedHabitWindows (371) are real recovery algorithms, not stubs;
ARETE_FRICTION_DESCRIPTORS and ARETE_INTERVENTION_DESCRIPTORS are full
taxonomies (friction-taxonomy.ts, versioned 1.0.0). ASPIRATIONAL / partial per
the audit: arete-create-habit, arete-living-offering-create,
weekly-review-arete, and arete-streak-recovery are all rated 'partial'
(v1-completeness-audit-2026-06-22.md) — wizard create POSTs the real BFF but
cross-device sync is uncovered; the living-offering intention capture is
hardcoded JSX (no real textarea); session->streak write and grace-window timing
remain. So the data model and core logic are real; some end-to-end
UI/persistence and the full Living Offerings render pipeline are still in
progress.

**Inaccuracies corrected**

- `ARCHITECTURE.md:452-453 (Arete › Key contracts)` — claim: _CheckIn statuses
  'done/partial/skip/decline/miss'_ → **reality:** CONFIRMED accurate —
  CheckInStatusSchema = ['done','partial','skip','decline','miss'] (contracts
  index.ts:10). (Listed here as a positive verification, not an error.)
- `ARCHITECTURE.md:451 (Arete › Surfaces)` — claim: _`apps/arete/*` for
  service-side persistence_ → **reality:** apps/arete exists with api/, mobile/,
  web/ subdirs — accurate. But the actual member-scoped persistence the audit
  exercises lives in the BFF stores
  (apps/oshun/bff/src/arete/arete-review-store.ts, arete-offering-store.ts,
  arete-coach-decision-store.ts) and client-side
  useAreteStore/localStorage['oshun.arete'], not solely apps/arete; the doc
  implies apps/arete is the persistence tier when much is BFF/local.

**Contradictions reconciled**

- (features.md:556 vs real surface tree) features.md:556 lists consumer Arete
  routes as coaching/goal/offering/patterns/plan/recovery/review/streak, but the
  real apps/oshun/web/src/app/arete tree ALSO contains habits/, offerings/
  (plural, distinct from singular 'offering'), and weekly/ — three routes not in
  the doc list — and uses 'offering' (singular) AND 'offerings' (plural) as
  separate directories.

**Staleness refreshed**

- `ARCHITECTURE.md:452-454` — Key-contracts list omits several real exported
  contracts: MissedDay, RecoveryRecord, Plan (with PlanCommitment), AreteMetric,
  MoodSnapshot, DeclaredCadence, HumaneStreakPolicy, and the
  CHECK_IN_STREAK_TREATMENT constant — all present in contracts index.ts but
  unlisted.
- `features.md:609-610 (Grace windows)` — features.md states a fixed '24 h grace
  on daily habits; 72 h grace on weekly cadence', but the code models grace as
  configurable per-habit via DeclaredCadence.graceWindowHours (0-168) and
  HumaneStreakPolicy.missGraceCadences — the hardcoded 24h/72h figures are spec
  defaults, not code constants; could be misread as fixed.

**Enrichment added (real code previously under-described)**

- The MissedDay, RecoveryRecord, and Plan contracts (with full superRefine
  invariants like 'logged-miss requires a visible reason and no-count
  treatment', 'recovery plans require recoveryRecordId') are entirely absent
  from both doc sections despite being central to the humane-recovery story.
- FrictionSignalKind enum has 11 values (time-of-day-mismatch,
  mood-incompatible-cadence, calendar-collision, cross-domain-cognitive-load,
  declared-sensitivity, location-friction, environment-unavailable, energy-drop,
  social-friction, streak-drift, over-scoped-plan) and InterventionKind has 9 —
  richer than features.md:623-628 conveys.
- The CoachingSummary contract has structured observedPatterns with kind enum
  (time-of-day, day-of-week, mood-correlation, habit-interaction, seasonality,
  location, post-event) and a supportBand (weak/moderate/strong) plus
  governance.memoryScope — the doc describes coaching summaries only
  narratively.
- WeeklyReviewSection has the exact celebrate/notice/choose/invite quadrants
  from features.md:643 as a real schema (WeeklyReviewSectionSchema), and
  WeeklyReview carries planAdjustments + nextPracticeRecommendations +
  crossDomainRefs — worth surfacing.
- Real BFF endpoints exist beyond what docs imply: /v1/arete/room,
  /v1/arete/habits (+ /:habitId/check-in), /v1/arete/offerings/keep,
  /v1/arete/offerings/sent, /v1/arete/review/close, /v1/arete/review/closed (per
  audit + AreteOfferingActions/AreteReviewClose components).
- The @arete/\* library family (12 packages: affirmations, ai-coach, balance,
  gamification, goals, habits, journal, seven-habits, time, vision, core,
  database) and a separate ai-coach package are not named in the docs.

_Captured 15 code-verified grounding facts for this area._

### domain-veritas

**Real vs aspirational.** REAL (verified by reading code): the full
source-quality composite (geometric weighted mean over 9 factors with
FACTOR_FLOOR=0.05, per-domain weight tables, hard overrides:
unattributed-capped-low, recent-retraction-drops-one-band within 12 months,
retracted-forces-contested; band thresholds composite>=82 high, >=60 mixed, >=35
low); the editorial state machine (TRANSITION_RULES with per-transition gates,
InMemoryTransitionLog, attemptTransition/replayHistory); attestor workflow
(audit/conflict/credential-verification/disagreement/expiry/probation/revocation
modules); counterclaim balance (DEFAULT_SURFACING_POLICY consensusThreshold
0.85, recencyWindowDays 365, 6 public-safety topics, 4-way surfacing decision);
topic-hub composer (6 sections, ranking weights); retraction-ux
(severityFromBandChange, 4 surface kinds, 3 severities, per-surface banner
builders); contradiction probe (Sophia client, triageThreshold 0.6); the cascade
executor emitting 'veritas.retraction.cascade.dispatched' consumed by the
worker. The canonical contracts are real and enforced. ASPIRATIONAL / not
grounded in this code: per-tenant composite tightening, drift re-computation on
a weekly cadence, credential round-trip proof artifacts, reader notification
quiet-hours integration, localized hub variants, and the 'downstream Metis
lessons re-validated' end-to-end runtime (the port exists; live wiring is at the
deployable boundary). The triage/audit notes confirm the customer-facing
retraction-cascade journey and evidence-trail are only 'partial' end-to-end in
e2e (fan-out, notebook/offering surfaces, per-user gating still undriven).

**Inaccuracies corrected**

- `features.md:949-960 (Veritas editorial state machine States) and ARCHITECTURE.md:479-482 / mermaid 489-527`
  — claim: _States are named verifying_sources, awaiting_attestation,
  contradicts_existing, counterclaim_pending (snake_case)._ → **reality:** The
  implemented VeritasEditorialState union
  (libs/oshun/domain-veritas/src/editorial/state-machine.ts:1-13) uses
  hyphenated kebab-case:
  'verifying-sources','awaiting-attestation','contradicts-existing','counterclaim-pending','in-review'.
  No snake_case state exists in code.
- `features.md:961-964 (Transitions, 'golden path')` — claim:
  _'verifying_sources -> awaiting_attestation -> published is the golden path.'_
  → **reality:** The code has no direct awaiting-attestation -> published edge.
  attemptTransition routes awaiting-attestation --attestation-collected-->
  approved, then approved --publish--> published (or via scheduled).
  state-machine.ts TRANSITION_RULES lines 77-121 show the real path goes through
  'approved'/'scheduled'.
- `ARCHITECTURE.md:464-466 (Veritas Contracts bullet)` — claim: _'workspace also
  wires a standalone libs/contracts/veritas package for consumers that import
  Veritas types without pulling the rest of @oshun/contracts.'_ → **reality:**
  libs/contracts/veritas/ contains ONLY a .gitkeep file (no package.json, no
  src, no exports). It is not a wired package. Veritas types are imported as
  '@oshun/contracts/veritas' which resolves to libs/contracts/src/veritas via
  the path map, not a standalone package.
- `ARCHITECTURE.md:496 (mermaid edge 'verifying_sources --> in_review: sources clean') and 493/497-499`
  — claim: _Mermaid shows verifying_sources -> in_review on clean sources, and
  awaiting_attestation -> in_review._ → **reality:** In the implemented state
  machine, verifying-sources --sources-verified--> awaiting-attestation
  (state-machine.ts:71-76), and awaiting-attestation --attestation-collected-->
  approved (not in-review). The mermaid's verification branches feed in-review;
  the code feeds approved. The diagram is illustrative spec, not the implemented
  graph.
- `features.md:722-724 (Source schema 'type')` — claim: _Source type enum lists
  peer-review/primary/secondary/press-release/opinion/social/government/NGO._ →
  **reality:** SourceKindSchema (contracts/src/veritas/index.ts:10-26) is a
  superset of 15 kinds; beyond those 8 it also includes
  'wire','dataset','court-record','transcript','image','video','audio'.
  ARCHITECTURE.md:469-470 correctly hedges with '⊇' but features.md presents the
  8 as the list.

**Contradictions reconciled**

- (features.md:949-967 vs ARCHITECTURE.md:489-527 (mermaid)) features.md lists
  the post-publish states as published/retracted/corrected with retracted firing
  'full cascade' and corrected being 'banner only, no full cascade'. The
  ARCHITECTURE mermaid adds
  'archived','scheduled','rejected','approved','in_review' transitions not
  enumerated in features.md's States list, and shows corrected --> published
  ('continues live') which features.md does not state. The two descriptions of
  the lifecycle graph diverge in both node set and edges.
- (features.md state names vs ARCHITECTURE state names vs contracts
  StoryEditorialStateSchema) Both docs use snake_case state IDs that contradict
  the actual kebab-case code identifiers; additionally the contracts
  StoryEditorialStateSchema (contracts:79-87) uses a THIRD, shorter vocabulary
  ('draft','review','published','updated','corrected','retracted','archived')
  with no verification states at all — three different state vocabularies for
  the same lifecycle.

**Staleness refreshed**

- `features.md:664-667 (Veritas presentational surfaces)` — The list of
  /veritas/\* subroutes omits /veritas/evidence, which exists as a real route
  directory (apps/oshun/web/src/app/veritas/evidence). The documented set
  (claim, counterclaims, mobile, provenance, retraction, source, story, topic)
  matches dirs that exist but is incomplete.
- `features.md:743 / ARCHITECTURE.md:525 ('downstream Metis lessons re-validated')`
  — The cascade contract distinguishes downstreamMetisPackageIds AND
  downstreamMetisLessonIds (RetractionCascadeSchema, contracts:566-567), and
  re-grounding jobs split action 're-ground' vs 'metis-revalidate'. The docs say
  'lessons re-validated' but the schema also tracks Metis package fan-out —
  underdescribed.

**Enrichment added (real code previously under-described)**

- The two-tier adapter architecture is undocumented: domain-veritas ships BOTH a
  presentational article-feed adapter (types.ts: VeritasApiAdapter with
  getTrendingArticles/getTopClaims/getClaimDetail; VeritasVerdict 8-value enum
  verified/likely_true/disputed/misleading/mostly_false/false/unverifiable/unverified;
  VeritasCredibilityTier) AND the canonical editorial model. Docs only describe
  the canonical side.
- The shell read-adapter role model is undocumented:
  VERITAS_ADAPTER_READ_CAPABILITIES (10 capabilities) and
  VERITAS_ADAPTER_ROLE_CAPABILITIES gating shell vs admin vs assistant
  (adapter.ts:81-164) — a real RBAC surface absent from the docs.
- The cascade event contract is undocumented:
  VERITAS_RETRACTION_CASCADE_DISPATCHED_EVENT='veritas.retraction.cascade.dispatched',
  the persistence-backed re-grounders (SOPHIA_GROUNDED_ANSWER_STORE_KEY,
  METIS_LESSON_SOURCES_STORE_KEY), and
  createPersistenceBackedSophiaReGrounder/MetisRevalidator
  (veritas-cascade-worker index).
- Source-quality determinism details (geometric mean, 9th factor 'independence'
  and 'cross_corroboration' as a count not a rating, hard-override labels) are
  richer than the prose — concrete constants like the band thresholds,
  FACTOR_FLOOR, and corroborationFactor curve could anchor the rewrite.
- The richer contracts vocabulary is under-surfaced: ClaimClass has 9 values
  (incl. 'causal','interpretation','comparison','legal'), EvidenceStance has 5
  (incl. 'contextualizes'), EvidenceLocatorGranularity has 8
  (document..timestamp), RetractionState has 4
  (active/under-review/retracted/superseded) — none enumerated in the docs.

_Captured 16 code-verified grounding facts for this area._

### domain-nyx

**Real vs aspirational.** The astronomy CORE is unambiguously REAL —
ephemeris.test.ts asserts toJulianDay(2000-01-01T12Z)===2451545.0,
sun.eclipticLongitude≈199.909, moon.eclipticLongitude≈133.1627,
moonIllumination≈0.6786, all known-correct Meeus values; this is not a stub by
any diagnostic. The contract model is the richest in the repo. ASPIRATIONAL /
partial per the audit: nyx-event-calendar-sync-reminder is 'partial' — two-way
provider sync is mocked at the boundary and reminder dispatch/delivery +
observation-log back-link remain; nyx-tonight-observation is 'partial' (local
persistence done, BFF/cross-device sync + KPI increment remain);
nyx-to-tara-bridge is URL-only telemetry. So: real ephemeris + real contracts +
real local persistence, plus the real admin calendar connector runtime now boots
seeded env descriptors and fails closed when Google credentials are absent, but
live external data-source ingestion (actual NASA/IMO/NOAA fetches) and real
calendar-provider OAuth/webhook sync are seam-mocked / fail-loud rather than
fully wired — which is the honest state, not a fabrication.

**Inaccuracies corrected**

- `ARCHITECTURE.md:537-540 (Nyx › Key contracts)` — claim: _`SkyEvent` ...
  `ObservationWindow`, `ObservationQualityBand`, `PredictionSourceRef`,
  `CalendarSyncEntry`_ → **reality:** CONFIRMED accurate — all five exist in
  libs/contracts/src/nyx/index.ts (SkyEventSchema:442,
  ObservationWindowSchema:197, ObservationQualityBandSchema:56,
  PredictionSourceRefSchema:165, CalendarSyncEntrySchema:557). Positive
  verification.
- `ARCHITECTURE.md:536 (Nyx › Surfaces)` — claim: _Surfaces — ..., mobile event
  cards_ → **reality:** The mobile app (apps/oshun/mobile/src) has no nyx/
  screen directory; Nyx appears only as cross-domain companion components (e.g.
  TaraNyxPerspectiveCompanionCard.tsx). 'mobile event cards' as a dedicated Nyx
  surface is not evidenced as a directory tree.

**Contradictions reconciled**

- (features.md:990-995 vs real surface tree) features.md:990 lists the Nyx
  consumer hub as `/nyx` and power tools under /domains/nyx/_, but the real
  apps/oshun/web/src/app/nyx tree also contains first-class consumer routes
  events/, observation/, sky-almanac/, tonight/ — none of which appear in the
  features.md consumer surface description (which jumps straight to
  /domains/nyx/_). The doc undercounts the consumer Nyx surface.

**Staleness refreshed**

- `features.md:1029-1031 & ARCHITECTURE.md:541-542 (Prediction sources)` — Docs
  list NASA JPL / IMO / IERS / NOAA SWPC / weather / Bortle, but the real
  PredictionSourceKindSchema has 11 kinds and also includes
  nasa-jpl-small-body-db, tle-provider, minor-planet-center,
  usno-astronomical-applications, and gaia-catalog — five sources the docs omit.
- `features.md:1034 (Calendar providers)` — features.md lists 'Google, Apple,
  Outlook' but CalendarProviderSchema is ['google','apple','outlook','ics-file']
  — the ics-file provider (with its own externalCalendarId-null special case) is
  omitted.

**Enrichment added (real code previously under-described)**

- The ENTIRE ephemeris engine (libs/oshun/domain-nyx/src/ephemeris.ts, 19.7KB)
  is undescribed in both doc sections: real functions toJulianDay,
  julianCenturies, sunPosition, moonPosition, moonIllumination, computeNightSky,
  greenwichMeanSiderealTime, localSiderealTime, equatorialToHorizontal,
  riseTransitSet, computeTonight — a genuine Meeus-based astronomy core that is
  the most impressive real asset here.
- 41 'depth' page modules under domain-nyx/src/depth (lunar-phase-calendar,
  twilight-schedule, solar-season-markers, object-transit, moon-phase-detail,
  equation-of-time, zodiac-position, moon-distance, sun-distance, lunar-nodes,
  planetary-hours, daylight-extremes, chart-angles, solar-terms,
  astronomical-night, horizon-point, solar/lunar-horizon-points, solar-noon,
  twilight-phase-now) — these power the /domains/nyx/\* deep tools and are
  entirely unmentioned.
- The LoggedObservation contract (the observe-loop: user reports what they
  actually saw with site conditions, equipment, quality rating, attachments,
  sharedScope) is a substantial real contract absent from both doc sections —
  features.md describes save/follow/remind but not ground-truth logging.
- The 11 per-family detail schemas (MeteorShowerEventDetails with
  iauCode/peakZenithalHourlyRate, EclipseEventDetails with
  sarosSeries/gamma/contactTimes, AuroraEventDetails with kpIndexMin/Max +
  geomagneticStormLevel g1-g5, SatellitePassEventDetails with noradId,
  SupermoonEventDetails with perigeeDistanceKm, etc.) — far richer than the
  event-taxonomy bullet in features.md:1016-1021.
- The predictionSourceFamilySupport mapping (which source kinds can back which
  event families, with superRefine enforcement that an event must carry a
  supporting source) is a real domain-correctness rule worth documenting.
- The libs/nyx library tree (~30 subdirs incl. catalogs/, constellations/,
  coordinates/, orbital/, positional/, realtime/, renderer/, sky-clock/,
  time-travel/, client-python/) and the @nyx ephemeris consumed by V9 (per repo
  memory) are unmentioned.

_Captured 15 code-verified grounding facts for this area._

### domain-nisaba

**Real vs aspirational.** REAL: the canonical Nisaba contracts
(contracts/src/nisaba/index.ts) are fully implemented zod schemas with
cross-field superRefine — Passage (with CanonicalReference scheme
cts/osis/sefaria/library-of-congress/custom, segments, sourceLineage,
concept/lexicon/morphology bindings), Manuscript (siglum, repository, IIIF
digitization status, witness model), Edition (critical apparatus with
ApparatusEntry witnessManuscriptIds validated against edition manuscriptIds),
Translation (translationMode
literal/formal-equivalence/dynamic/commentarial/adaptive, distinct source/target
language enforced), LexiconEntry (lemma/senses/glosses/roots), MorphologyEntry
(PartOfSpeech 12 values, MorphologyFeature 14 values, parsing method),
Annotation, ConceptGraphNode (10 kinds), ConceptGraphEdge (9 relations,
high-confidence requires evidence), Notebook, StudyPlan (9 step kinds, ordered
steps), Citation (6 styles incl. sbl/cts), ScholarProfile (credential kinds,
reviewAuthority gating). The domain adapter, concept-graph linkages (real,
delegates to @oshun/navigation shared concept graph), domain-recommendations,
and @nisaba/study-plans re-export are real. The @nisaba/languages engine
(transliteration, tokenization, 30+ script handlers like
SyriacScriptHandler/SumerianCuneiformHandler/EgyptianHieroglyphicHandler) is
real and substantial. ASPIRATIONAL / unverified: external-source binding to
Sefaria/CDLI/IIIF endpoints via the named env vars (the env vars DO NOT EXIST in
code — only conceptual references to CDLI/Oracc ATF and IIIF manifest linking
exist inside @nisaba/languages and @nisaba/criticism); scholar/expert
entitlement-gated reading mode runtime; durable annotation re-anchoring across
edition revisions; the source-lifecycle invalidation cascade firing
edition-update notices on notebooks (the contracts model it; runtime wiring
unverified). Per the 2026-06-23 triage, nisaba is 'disconnected' in the hydrated
shell and the e2e journeys (nisaba-notebook-capture-and-cite,
nisaba-scholarly-read) run on stub workspace APIs / render-only scholar
apparatus.

**Inaccuracies corrected**

- `ARCHITECTURE.md:556-557 (Nisaba External sources)` — claim: _'configured via
  NISABA_SEFARIA_API_URL, NISABA_CDLI_API_URL, NISABA_IIIF_BASE_URL'._ →
  **reality:** Grep across the entire repo (--include='\*.ts') returns ZERO
  occurrences of NISABA_SEFARIA_API_URL, NISABA_CDLI_API_URL, or
  NISABA_IIIF_BASE_URL. These env var names are fabricated/aspirational. Only
  conceptual CDLI/Oracc/IIIF references exist in @nisaba/languages (cuneiform
  ATF) and @nisaba/criticism (iiif-linking.ts).
- `features.md:1065-1068 (Nisaba power-user surface)` — claim: _'Nisaba also
  ships a /domains/nisaba power-user surface: DomainRouteExperience mounts
  NisabaSurface there.'_ → **reality:** There is NO literal
  apps/oshun/web/src/app/domains/nisaba/ directory (unlike veritas, which has
  one). The Nisaba power-user surface is served only via the dynamic catch-all
  route apps/oshun/web/src/app/domains/[domainId]/page.tsx +
  components/domains/NisabaSurface.tsx. The claim is functionally true (the path
  resolves) but the phrasing implies a dedicated route folder that does not
  exist.
- `features.md:1062-1064 (Nisaba presentational subroutes)` — claim: _Lists
  /nisaba/{compare,daily,graph,lexicon,manuscript,notebook,plan,scholar}._ →
  **reality:** A /nisaba/notebooks route ALSO exists (plural) alongside
  /nisaba/notebook (singular) — apps/oshun/web/src/app/nisaba/ contains both
  notebook and notebooks directories; the doc lists only the singular.

**Contradictions reconciled**

- (features.md:1062-1064 vs apps/oshun/web/src/app/nisaba/ directory)
  features.md enumerates the Nisaba consumer subroutes
  (compare/daily/graph/lexicon/manuscript/notebook/plan/scholar) but the actual
  route folder also contains a /nisaba/notebooks (plural) directory not present
  in the doc's list; the doc and filesystem disagree on the notebook(s) surface.
- (features.md:1114-1119 (Nisaba concept-graph edge labels) vs contracts
  ConceptGraphEdgeSchema relation enum) Internal/cross-source mismatch: the
  prose's edge label set (refers-to, derives-from, comparative-to, lineage-of)
  is incompatible with the canonical schema's 9-value relation enum; a reader
  following the doc would expect edge relations that the contract rejects.

**Staleness refreshed**

- `ARCHITECTURE.md:553-555 (Key contracts list)` — Accurate as far as it goes
  but stale-by-omission: the canonical schema also defines PassageSegment,
  ApparatusEntry, LexiconSense, NotebookItem, StudyPlanStep, TextRangeSelector,
  CanonicalReference, and helper functions (isPublishedPassage,
  conceptEdgeRequiresEvidence, scholarCanVerifyCitations) — the 'Key contracts'
  enumerates the top-level types but the rewrite should note the nested schemas.
- `features.md:1114-1119 (Concept graph edges)` — features.md says Nisaba
  contributes edges refers-to/derives-from/comparative-to/lineage-of. The actual
  ConceptGraphEdgeSchema relation enum (contracts:604-614) is
  broader-than/narrower-than/related-to/influences/contrasts-with/translation-equivalent/ritualizes/comments-on/shares-source-lineage
  — NONE of the four doc-named edge labels match the implemented enum. The doc's
  edge vocabulary is illustrative, not the code's.

**Enrichment added (real code previously under-described)**

- The @nisaba/languages polyglot philology engine is almost entirely absent from
  the V1 docs: 30+ script/language packages (hebrew, aramaic, syriac, arabic,
  ethiopic, phoenician, samaritan, ugaritic, cuneiform,
  egyptian-hieroglyphic/hieratic/demotic, ancient-greek, latin, coptic,
  devanagari, grantha, kharoshthi, linear-b, old-church-slavonic, old-persian,
  pali, prakrit, runic, tamil-brahmi, tibetan, classical-chinese, avestan) plus
  transliteration + tokenization + a lexicon module, exporting concrete script
  handlers (SyriacScriptHandler, SumerianCuneiformHandler,
  EgyptianHieroglyphicHandler, ArabicScriptHandler, etc.). This is the richest
  real Nisaba code and the docs barely mention 'morphology lookup'.
- The libs/nisaba sub-package collection (~23 packages: annotations, assistant,
  canon, comparative, corpora, criticism, editions, geotemporal, languages,
  paleography, philology, schemas, standards, study-plans, translations,
  workspace, database, cross-domain, mobile, core, client, api-client) is
  undescribed as an architecture. @nisaba/criticism ships real IIIF manifest
  linking (iiif-linking.ts: IIIFLinkRegistry, IIIFManifestRef).
- The shell adapter's search model is undocumented: NisabaSearchMode =
  fulltext|lemma|morphology|semantic|regex|proximity, NisabaSearchEntityKind =
  passage|source|concept|notebook|collection (types.ts:71-93) — a real
  multi-mode philological search surface.
- Cross-domain wiring is real and underdescribed: concept-graph-linkages.ts
  delegates to @oshun/navigation (buildOshunSharedConceptGraphThread,
  inferOshunSharedConceptIds) with a NISABA_CONCEPT_ID_ALIASES map mapping
  nisaba concepts to shared concept ids (focus-protection, honest-reflection);
  domain-recommendations.ts builds cross-domain recs with reasons
  'shared_concept_graph'|'source_study'.
- The contracts' canonical-reference scheme set
  (cts/osis/sefaria/library-of-congress/custom) and citation styles
  (chicago/mla/apa/sbl/cts/custom) are concrete and quotable but absent from the
  prose.

_Captured 17 code-verified grounding facts for this area._

### domain-metis

**Real vs aspirational.** This area is far MORE implemented than typical Oshun
domain docs imply, but the docs also over-state launch-readiness. IMPLEMENTED
(verified by reading code): all 11 canonical contracts in
libs/contracts/src/metis/index.ts (LearningSourceBundle@251, GroundingPack@461,
CourseBuild@643, LessonAssetBundle@978, PublicationPackage@1226,
TutorPersonaProfile@1425, TutorSessionMemory@1605, LearningObjectiveMap@1706,
AssessmentEvidencePack@1845, LearningTelemetryStatement@2020,
AcademicIntegrityVerdict@2061) re-exported as MetisContracts namespace; the
6-band mastery model + half-life decay
(libs/metis/learning/src/mastery/{evidence-requirements,decay,transitions}.ts);
the 6-axis personalization manifold as a real Zod
LearnerPersonalizationStateSchema (libs/contracts/src/metis/personalization.ts);
GradebookEntry + correction events + role-redacted views
(libs/contracts/src/metis/gradebook.ts + libs/metis/gradebook/src/emission.ts);
real IRT (1PL/2PL/3PL model family, calibration, DIF monitoring) in
libs/metis/assessment; BKT/FSRS-5/graph-knowledge-tracing in
libs/metis/adaptive; the six-core-discipline taxonomy
(libs/metis/learning/src/subject-taxonomy); real LTI-1.3 id_token/JWKS
verification, SCORM-2004 RTE, OneRoster dry-run, QTI3 export/import, Caliper,
Open Badges (libs/shared/inbound-integrations +
libs/metis/integrations/src/standards/institutional-delivery.ts); a full
BYOM-model safety harness with quarantine/kill-switch/fail-closed/abuse-monitor
(libs/shared/inbound-integrations/src/byom-model.ts); the Themis
academic-integrity module with the exact 10-signal taxonomy; BFF routes for
integrity adjudication/appeal/audit, tutor-session-memory, byom-decision.
ASPIRATIONAL / NOT-YET: Metis availability is 'planned' in the domain registry
so it is filtered out of getAvailableDomains() — i.e. not actually live despite
'launch-blocking' framing; the P95<=600ms adaptive-loop latency budget is a spec
assertion with no enforcing runtime gate found; several cross-domain wirings the
doc claims (Tara/Nyx/Veritas/Nisaba/Arete) have no \*-canonical-wiring.ts file
(only aja/iris/isis/lilith/psyche/sophia/themis/yemaya exist); the BYOM headline
ingest-to-course pipeline is graded 'partial/uncovered' in the 2026-06-22
completeness audit. I could not find a dedicated metis PostgreSQL database.

**Inaccuracies corrected**

- `features.md:1530 (BYOM safety surface)` — claim: _BYOM model calls run
  through `@oshun/inbound-integrations/byom.ts` in a per-tenant sandbox_ →
  **reality:** byom.ts is the bring-your-own-MATERIAL ingestion connector
  framework (file/url/feed/lms-import sources). The tenant-provided-MODEL
  endpoint safety harness (sandbox, quarantine, kill-switch, policy interlock,
  abuse monitor, fail-closed) is a SEPARATE file:
  libs/shared/inbound-integrations/src/byom-model.ts (class ByomModelFramework).
  The doc cites the wrong file.
- `features.md:1490 and 1300-1301 (verdict classes: 'policy_violation','severe_violation')`
  — claim: _Verdict classes are clear / inconclusive / policy_violation /
  severe_violation_ → **reality:** The real AcademicIntegrityVerdict enum
  (libs/contracts/src/metis/index.ts:2063-2066) uses
  'clear','inconclusive','violation','severe'. The gradebook enum
  (gradebook.ts:44-50) uses
  'clear','inconclusive','violation','severe','pending'. The doc's '\_violation'
  long forms do not match the shipped enum literals.
- `features.md:1198 and 1199-1202 ('Admin Metis dashboards', 'admin')` — claim:
  _Admin Metis dashboards / admin review surfaces_ → **reality:** The shipped
  review surface route is /operator/metis
  (apps/oshun/web/src/app/operator/metis/page.tsx) and the BFF route prefix is
  /metis/integrity under operator scope; there is no /admin/metis route in
  apps/oshun/web. (apps/metis/admin app exists separately but the consumer-shell
  review UI is /operator/metis.)
- `ARCHITECTURE.md:561-563 / features.md:1169 ('Launch-blocking V1 scope')` —
  claim: _Metis is launch-blocking V1 scope (implying active launch surface)_ →
  **reality:** libs/oshun/domain-registry/src/registry.ts:489 sets Metis
  `availability: 'planned'`, and getAvailableDomains() (registry.ts:504) filters
  out 'planned' domains. The 2026-06-23 triage confirms the shell drops Metis to
  `planned` post-hydration (shellDomainCount 5->4). 'Launch-blocking' is a
  roadmap intent, not current launch state.
- `features.md:1162-1164 (Surfaces list)` — claim: _Presentational depth at
  `/metis/assessment`, `/metis/byom`, `/metis/lesson`, `/metis/tutor`_ →
  **reality:** Those four exist, but the real route set is larger and the doc
  omits several shipped routes: /metis/lessons, /metis/session, /metis/ingest,
  /metis/upload, /metis/courses/new (all under apps/oshun/web/src/app/metis/).
  Under-listing, not wrong.

**Contradictions reconciled**

- (features.md:1162-1165 vs libs/oshun/domain-registry/src/registry.ts:425)
  features.md states 'Metis does not yet ship a `/domains/metis/*` power-user
  namespace' (true at the web-app level — no
  apps/oshun/web/src/app/domains/metis dir), but the domain registry declares
  `route: '/domains/metis'` and `bff-base-path: '/api/oshun/domains/metis'` with
  launch.defaultPath '/courses'. The registered route and the shipped consumer
  routes (/metis/\*) disagree, and the doc only notes the absence without
  reconciling the registry's declared /domains/metis route.
- (features.md (5 assessment/integrity modes) vs
  libs/contracts/src/metis/index.ts:1557) features.md:1292 declares integrity
  MODE declarations as assessed/formative/practice/exam/collaborative (these 5
  DO appear in gradebook.ts GradebookAssessmentMode). But the TutorSessionMemory
  contract's `integrityMode` enum (index.ts:1557) is a different 4-value set:
  'teach','hint','practice','do-not-complete-for-me'. Two distinct
  integrity-mode vocabularies coexist; the doc presents only the 5-mode one.

**Staleness refreshed**

- `ARCHITECTURE.md:572 (Domain libraries list)` — The libs/metis library list is
  stale/incomplete: it omits three real dirs that exist on disk — `gradebook`
  (@metis/gradebook), `discovery` (@metis/discovery), and `verification`
  (@metis/verification). It lists `api-client` location separately at line 569
  but not in the domain-libraries enumeration.
- `ARCHITECTURE.md:569-570 (Adapter consolidation)` — Says the V1 target is
  consolidation under `libs/oshun/domain-metis/` tracked by TODOS §1.3. That
  facade already exists (libs/oshun/domain-metis/src/adapter.ts re-exports
  @metis/api-client as createMetisDomainAdapter), so the 'target/tracked'
  framing reads as not-yet-done when the thin facade is in fact present.
- `features.md:1244-1250 (standards list mentions 'CAT-aligned assessment', 'SCIM 2.0')`
  — SCIM 2.0 / SAML 2.0 / OIDC identity plumbing is in
  libs/shared/inbound-integrations/src/identity.ts (real), but 'CAT-aligned
  assessment' maps only loosely — the real adaptive selector is
  IRT-information-gain based (assessment/src/generation/adaptive-selector.ts);
  there is no separately-named CAT module. Verify before citing CAT as a
  discrete feature.

**Enrichment added (real code previously under-described)**

- The `@metis/verification` library (libs/metis/verification, 4K LOC) is
  entirely undescribed: it ships a real VerificationGate, composeP0Gate (P0
  generation gate), runVerifiedGeneration (generate-verify-refine loop), and a
  judge-verifier panel scorer — this is the concrete grounded-generation
  enforcement the docs only gesture at abstractly.
- The `@metis/discovery` library (libs/metis/discovery, ~1.5K LOC) is
  unmentioned — it presumably backs browse/recommend surfaces the doc lists as
  features but never attributes to a lib.
- The six-core-discipline taxonomy is implemented as real typed data
  (libs/metis/learning/src/subject-taxonomy/subject-taxonomy.ts:
  CoreMetisDiscipline =
  philosophy|religion|psychology|neuroscience|anthropology|astronomy;
  SUPPORTING_METIS_SUBJECTS; MetisSubjectRole
  'core_headline'|'supporting_scaffold'; SUPPORTING_TO_CORE_ANCHOR map). The doc
  describes this in prose but doesn't note it is a codified taxonomy with anchor
  mappings.
- The knowledge-graph promotion is far richer than described:
  libs/metis/knowledge-graph (19K LOC, 75 files) ships construction
  (entity-relation-extractor, cycle/orphan detection), a GraphRagRetriever with
  defaultCommunitySummarizer + multi-hop expansion + pgvector seed + governance
  filter, GNN, temporal, and a GraphRagBenchmarkSuite. Worth a dedicated page.
- The hint ladder is concretely implemented
  (libs/metis/tutoring/src/hints/hints.ts): HintLevel
  SUBTLE/DIRECT/WORKED_EXAMPLE/ANSWER_REVEAL with HINT_REVEAL_PERCENTAGES
  {0.1,0.3,0.7,1.0} and per-hint cost — the doc says 'per-hint cost tracked' but
  omits the actual ladder constants.
- The BYOM-model safety harness exposes concrete primitives worth documenting:
  ByomEndpointStatus including
  'quarantined'/'fail_closed_killed'/'fail_closed_quarantined',
  ByomKillSwitchSource 'platform_operator'|'tenant_operator',
  DEFAULT_BYOM_ABUSE_THRESHOLDS, HIGH_RISK_TAGS, ByomPolicyInterlock
  (Lilith/Isis/Sophia gates), MemoryByomAuditStream.
- No dedicated `metis` PostgreSQL database exists in
  docker/docker-compose.dev.yml POSTGRES_MULTIPLE_DATABASES
  (yemaya,lilith,isis,iris,sophia,hathor,bellona,calliope,tara,maat,nisaba,shakti,cybele,kalika,lakshmi,athena,oya).
  Metis storage strategy (oshun_dev vs domain tables) is undocumented and a real
  gap.
- The gradebook role-redaction logic (viewGradebookEntryForRole in
  gradebook.ts:276) and DEFAULT_VISIBILITY_RULES
  (learner/teacher/guardian/institutional_admin) are real and concretely
  implement the doc's 'rights and visibility' bullet — could be surfaced as a
  worked example.

_Captured 20 code-verified grounding facts for this area._

### substrate-sophia

**Real vs aspirational.** REAL and shipping: the live `/v1/sophia/answer`
extractive grounded-answer composer (deterministic, per-claim `retrieved` label,
abstain/ungrounded/partial/grounded states, never fabricates citations) and the
`/v1/sophia/sources/grounding` credibility engine over @sophia/research-engine
source-scoring (domain-tier 40% / recency 20% / citations 20% / peer-review
20%). REAL but UNWIRED to the live path: the BM25 engine in
`libs/sophia/semantic-search`, the FactCheckLoop and ContradictionLoop classes
in `libs/sophia/verification` (full implementations with termination states,
counterclaim records, resolution actions), and the entire
`@oshun/evidence-sophia` adapter (real types + builders, but
`SophiaEvidenceAdapter` is an interface with no concrete @sophia/\* binding in
V1). ASPIRATIONAL / spec-only: the six-stage ingestion pipeline
(parse→chunk→enrich→embed→index→quality-eval) as a single orchestrated flow, the
per-source-type SourceAdapter set (PDF/HTML/RSS/YouTube/IIIF/API/LMS/BYOM),
Qdrant/Elasticsearch/Neo4j multi-store indexing, mandatory human checkpoints,
the operator workbench, and the downstream invalidation cascade — these are
described as concrete but the live BFF only retrieves over the in-process Nisaba
public-domain corpus. The live answer path uses Jaccard token overlap, NOT BM25,
despite BM25 being the doc's headline lexical method and existing in the repo. I
could not find evidence the contradiction loop, fact-check loop, or
evidence-pack assembly run on any live customer answer; grep shows they are
imported nowhere under apps/oshun/bff/src.

**Inaccuracies corrected**

- `features.md:2863 (Retrieval Methods: 'lexical (BM25)')` — claim: _Lexical
  retrieval is BM25._ → **reality:** A real BM25 exists at
  `libs/sophia/semantic-search/src/bm25/bm25.ts` (BM25Config k1/b, field
  weights, IDF), but the LIVE grounded-answer path does NOT use it —
  `apps/oshun/bff/src/sophia/answer-composer.ts` ranks citations by Jaccard
  token-set overlap (`lexicalOverlap`), and the BFF search route uses a
  hand-weighted lexical scorer (`apps/oshun/bff/src/search/ranking.ts`). BM25 is
  unwired in V1's customer flow.
- `features.md:2876-2891 (Fact-Check Loop) and 2893-2906 (Contradiction Loop)` —
  claim: _Fact-check and contradiction loops gate high-stakes claims with
  latency budgets and counterclaim records on live output._ → **reality:**
  `FactCheckLoop` and `runContradictionLoop` are fully implemented in
  `libs/sophia/verification/src/{fact-check-loop,contradiction}/` but
  `grep -rln 'contradiction-loop|fact-check-loop' apps/oshun/bff/src` returns
  nothing — neither runs on any live customer answer. The live
  `/v1/sophia/answer` composer emits one `retrieved` claim per passage and never
  invokes either loop.
- `ARCHITECTURE.md:670 (sequence diagram: Retriever 'pgvector · Qdrant') and features.md:3040 (Index: 'pgvector primary, Qdrant…Elasticsearch…Neo4j')`
  — claim: _Live retrieval fans out across pgvector + Qdrant (+ Elasticsearch +
  Neo4j)._ → **reality:** The live `/v1/sophia/answer` retrieves over the
  in-process Nisaba public-domain corpus via the `searchLibrary` adapter (see
  grounding-service.ts header and v1-real-infra-run-2026-06-22.md §24). No
  Qdrant/Elasticsearch/Neo4j store is in the live answer path.
- `ARCHITECTURE.md:681 (diagram: 'LLM synthesize answer with retrieval-vs-synthesis labels')`
  — claim: _The grounded synthesis step is an LLM that labels retrieval vs
  synthesis._ → **reality:** The DEFAULT live path is non-LLM:
  `composeExtractiveAnswer` produces a deterministic extractive answer with all
  claims labeled `retrieved` (never `synthesized`/`model-only`). An LLM
  abstractive layer exists only when OSHUN_LLM_API_BASE/\_KEY/\_MODEL are set,
  and it fails soft back to the extractive composer (domain-stubs.ts ~417-449).
  The diagram presents LLM synthesis as the primary branch.

**Contradictions reconciled**

- (features.md:2851-2853 / ARCHITECTURE.md:681 vs
  apps/oshun/bff/src/sophia/answer-composer.ts) Docs frame the grounded answer
  as prompt+LLM synthesis producing retrieval-vs-synthesis-labeled claims; the
  live default is a no-LLM extractive composer whose claims are ALL `retrieved`
  by construction (the `synthesized`/`model-only` labels exist in the type
  `SophiaClaimLabel` but the live composer never produces them).
- (features.md:2935 ('citation integrity 100%, contradiction backlog zero…') vs
  live path) The publication gate criteria assume a contradiction backlog and
  unsupported-claim backlog computed by the loops; those loops do not run on the
  live customer path, so the gate as described is aspirational, not enforced on
  `/v1/sophia/answer`.

**Staleness refreshed**

- `ARCHITECTURE.md:643` — Lists `apps/sophia/*` as service backing. The shipping
  V1 customer grounding surface is in `apps/oshun/bff/src/sophia/` and
  `apps/oshun/bff/src/routes/{sophia.ts,domain-stubs.ts}`; the doc points
  readers at a separate sophia app rather than the BFF routes that actually
  serve grounded answers.
- `ARCHITECTURE.md:640-642` — Names adapter files `evidence-model.ts`,
  `source-lifecycle.ts`, `educational-claim-grounding.ts`,
  `canonical-adapter.ts` (all present and correct) but omits `source-set.ts` and
  `types.ts` which carry the bulk of the real
  source-set/freshness/rights/retraction contracts.

**Enrichment added (real code previously under-described)**

- The real `SOPHIA_GROUNDING_FLOOR = 0.5` corroboration floor and its rationale
  (domain reputation alone is insufficient: 0.95\*0.4=0.38 < 0.5) is a concrete,
  shipping behavior the docs do not mention.
- The extractive composer's honest design note — that it uses verbatim passage
  summaries because research-engine `extractFactsFromText` returns [] on short
  Nisaba summaries (would falsely yield `ungrounded`) — is real engineering the
  docs omit.
- The grounding-state thresholds are concrete and undocumented: ≥3 citations →
  `grounded`, 1-2 → `partial`, 0 with non-empty query → `ungrounded`, 0 with
  empty query → `abstained` (answer-composer.ts:121-122, 80-81).
- The real source-scoring weights (`scoreSource`: 40/20/20/20
  domain/recency/citations/peer-review) and `calculateAverageSourceScore`
  confidence are shipping but not surfaced in the docs.
- `@oshun/evidence-sophia` exports a real role-based read-adapter registry
  (`grounding`/`review`/`admin` with per-role capability lists
  `SOPHIA_EVIDENCE_ADAPTER_ROLE_CAPABILITIES`) — a concrete RBAC-on-evidence
  model the docs describe only abstractly as 'Customer/Admin surfaces'.
- Real source-set lifecycle primitives exist
  (`evaluateSophiaSourceSetReadiness`, `computeSophiaSourceSetHash` via @noble
  sha256, `planSophiaSourceLifecycleInvalidation`,
  `materializeSophiaSourceSetArtifacts`) with freshness/rights/retraction
  blockers — richer than the doc's prose.
- The optional LLM abstractive enhancement (OSHUN_LLM_API_BASE/\_KEY/\_MODEL,
  fail-soft to extractive) is a real, undocumented configuration seam.

_Captured 17 code-verified grounding facts for this area._

### substrate-iris

**Real vs aspirational.** Overwhelmingly REAL. The `MemoryEntry` contract is a
shipping Zod schema with immutable-revision-then-tombstone lifecycle
(`revisionId`/`previousRevisionId`, lifecycle
`draft|active|paused|superseded|tombstoned`). The `RecallPipeline` class
implements the documented deterministic pipeline (tenant boundary → scope
reachability → crisis gate → sensitive-category gate → relevance scoring →
conflict/freshness → audit) with the documented per-surface budgets (assistant
12, shell 3, notebook 999, admin 100) — these constants match
features.md:2029-2031 closely. The admin-inspection state machine's states and
transitions are an EXACT match to features.md:2139-2153. Consent ledger
(append-only, fingerprinted), data-rights (delete soft/hard, export, access;
DSAR), privacy suppression, conflict resolution (most-recent-wins, user-stated >
inferred), multi-actor masking, and ContinuationToken contract all exist as real
modules. ASPIRATIONAL/divergent: the exact scope NAMES and body-type union in
the docs do not match the code; the relevance ranker uses Jaccard token
similarity (`jaccardSemantic`) not true semantic embeddings; the customer memory
UX at `apps/oshun/web/src/app/profile/memory/` exists but is partial per the
completeness audit (memory-edit-pause-forget is 'partial'). FSRS is not an Iris
feature.

**Inaccuracies corrected**

- `ARCHITECTURE.md:752-753 and features.md:1973 ('scope — one of profile | session | notebook | operator-copilot | tenant')`
  — claim: _MemoryScope has exactly five values:
  profile/session/notebook/operator-copilot/tenant._ → **reality:** The
  canonical contract `MemoryScopeKeySchema`
  (libs/contracts/src/iris/entry.ts:15-45) is a discriminated union of EIGHT
  kinds: profile, session, scene, pose, notebook, crisis, operator-copilot,
  tenant. The adapter's `IrisMemoryScope` (memory-model.ts:91-235) has ELEVEN:
  assistant_profile, session, scene, pose, conversation, domain, cross_domain,
  notebook, operator_copilot, tenant, admin_review. The doc undercounts and uses
  different names (e.g. `profile` vs `assistant_profile`).
- `features.md:1979 ('origin — user-stated | user-confirmed | model-inferred | promoted-from-session | imported')`
  — claim: _Origin enum includes `promoted-from-session`._ → **reality:**
  `MemoryOriginSchema` (entry.ts:81-88) values are: `user-stated`,
  `user-confirmed`, `model-inferred`, `operator-copilot`,
  `summarized-from-session`, `imported`. The doc's `promoted-from-session` is
  named `summarized-from-session` in code, and the doc omits the real
  `operator-copilot` origin.
- `features.md:1975-1976 ('body — typed payload: Fact, Preference, Goal, Boundary, Relationship, Schedule, LineageDeclaration, Sensitivity')`
  — claim: _`body` is a typed payload discriminated union of those 8 kinds._ →
  **reality:** In the real schema `body` is `z.string().min(1).max(4000)`
  (entry.ts:170) — plain text, not a typed union. The taxonomy that IS modeled
  is `MemoryCategorySchema` (entry.ts:48-78, ~28 values incl.
  fact/preference/goal/relationship/commitment/identity plus sensitive
  categories), which is a different field than `body`.
- `features.md:1980 ('lifecycle — active | tombstoned | summarized | superseded | paused')`
  — claim: _Lifecycle includes `summarized`._ → **reality:**
  `MemoryLifecycleSchema` (entry.ts:91-97) =
  `draft | active | paused | superseded | tombstoned`. There is no `summarized`
  lifecycle; the doc lists `summarized` and omits `draft`.
- `features.md:1987-1988 ('suppression[] — crisis-frame / user-mute / tenant-policy-mute / category-revoked')`
  — claim: _Suppression markers are an array with those four reasons._ →
  **reality:** `MemorySuppressionSchema` (entry.ts:124-129) is a single nullable
  object (not an array), with reason enum
  `crisis-frame | user-pause | sensitive-category | tenant-quarantine`. Names
  differ (`user-mute`→`user-pause`, `tenant-policy-mute`→`tenant-quarantine`,
  `category-revoked`→`sensitive-category`) and cardinality differs (nullable
  single, not `[]`).
- `features.md (Iris section, 1837-2183) — FSRS focus` — claim: _(Implied by
  audit focus) Iris memory decay/scheduling uses FSRS._ → **reality:** FSRS is
  NOT used by Iris. Real FSRS v4 lives in
  `libs/mnemosyne/core/src/memory-science.ts` (FSRSParameters, FSRSReviewResult,
  calculateRetention). memory-iris decay is usage-weighted (recall pipeline
  `DEFAULT_WEIGHTS` recency 0.4/semantic 0.35/referenceCount 0.15/origin 0.1);
  the only `stability`/`fsrs` strings in memory-iris are unrelated (sort
  stability, a status literal). The Iris features doc itself never claims FSRS —
  accurate by omission.

**Contradictions reconciled**

- (features.md:1973 (5 scopes) vs features.md:2005-2007 +
  libs/contracts/src/iris/entry.ts) The MemoryEntry-contract subsection lists 5
  scopes, but the recall-resolution algorithm (same doc, 2005-2014) and the real
  `MemoryScopeKeySchema` both rely on scene/crisis scopes the 5-item list omits;
  the doc is internally inconsistent about how many scopes exist.
- (ARCHITECTURE.md:792 ('score recency · semantic · referenceCount · origin') vs
  features.md:2017-2021) Both describe the ranker, and the code
  (`RecallPipeline.DEFAULT_WEIGHTS`) matches the four-factor blend — but
  'semantic-similarity' is implemented as Jaccard token overlap
  (`jaccardSemantic`), not embeddings; neither doc flags this approximation.

**Staleness refreshed**

- `features.md:1989-1991 (`multiActor[]` 'masked actor refs are listed here' as array)`
  — Real `multiActor` is a single nullable `MultiActorSchema` object
  (entry.ts:180), not an array —
  `{actorHandle, relationshipNote(max 500), sensitiveInteraction}`.
- `ARCHITECTURE.md:754 (`ConsentRecord` 'per-category, per-scope; timestamp, actor, prior state, new state, reason code')`
  — The shipping consent primitive is `ConsentEntrySchema` (entry.ts:100-105)
  `{category, grantedAt, revokedAt, source: inline-prompt|settings-toggle|dsar-import}`
  plus a separate append-only `IrisConsentLedger`/`IrisConsentEvent`
  (consent-ledger.ts) — richer and differently-shaped than the doc's 'prior
  state/new state/reason code' description.

**Enrichment added (real code previously under-described)**

- The canonical contract carries a `crisis` scope kind and `scene`/`pose` scopes
  (V3 embodied memory) that the V1 docs' 5-scope list entirely omits — real and
  undocumented here.
- The real recall pipeline emits a `RecallAuditEnvelope` with
  `suppressionCounts` keyed by reason (`tenant-mismatch`, `scope-mismatch`,
  etc.) — a concrete audit shape the docs describe only as 'suppressed entries
  (count only)'.
- `MemoryCategorySchema` has ~28 values including a precise SENSITIVE_CATEGORIES
  set (19 categories: medical, mental_health, substance_use, sexuality,
  gender_identity, religion_user_redacted, abuse_history, immigration_status,
  financial_distress, relationship_violence, legal_jeopardy, plus
  pose_alignment/biometric/spiritual/safety) — far more concrete than
  features.md:1900-1902's prose list.
- Real per-scope policy metadata in `memory-model.ts` (requiredConsents,
  optOutCategories, canonicalTiers, adminReviewable, requiresGovernanceReview,
  allowedConsumers per scope) is a rich governance model the docs don't surface.
- `IrisDataRightsRequestKind = delete|export|access` with delete payload
  supporting soft/hard mode + consent-ledger purge + retention grace window
  (data-rights.ts) — concrete DSAR mechanics beyond the doc's 'export/delete'
  bullets.
- The append-only consent ledger with event fingerprinting
  (`computeIrisConsentEventFingerprint`, IRIS_CONSENT_EVENT_RECORD_VERSION) is
  real and undocumented.
- Continuity lives in two places: the canonical `ContinuationTokenSchema` in
  `libs/contracts/src/iris/continuation.ts` AND `memory-iris/src/continuity/` +
  `mobile-handoff.ts` — the doc's `ContinuationToken` shape
  `{userId,scopeKey,surfaceContext,anchorRef,posture,lastUpdatedAt}` should be
  checked field-by-field against the real schema.

_Captured 17 code-verified grounding facts for this area._

### substrate-psyche

**Real vs aspirational.** Almost entirely REAL at the contract/logic layer.
Every doc claim I checked maps to an exported symbol or constant in
`libs/oshun/embodiment-psyche/src`: the event-type list
(PSYCHE_V1_SESSION_EVENT_TYPES, 15 entries, exact match), latency targets
(PSYCHE_VOICE_FIRST_AUDIO_LATENCY_TARGETS p50=500/p95=900/p99=1500;
PSYCHE_FIRST_TOKEN_LATENCY_TARGETS p50=350/p95=700;
PSYCHE_AVATAR_FRAME_LATENCY_TARGETS p50=80;
PSYCHE_ASR_FINAL_TEXT_LATENCY_TARGETS p50=150 — all exact), the
avatar+voice→voice→text fallback chain (PSYCHE_FALLBACK_MODES), the 180ms
partial-TTS fade-out default, the 200ms thinking-indicator deadline, and the
crisis-frame triple action (break-persona/halt-synthesis/suspend-memory-writes).
The pieces that are SPEC-ONLY (aspirational) are the live wire/transport binding
and the actual provider integration: this library is deliberately pure data +
pure functions with NO IO, NO rendering, NO transport (it says so in its own
fileoverview comments). The real-time service that consumes these contracts
lives under `services/psyche/*`, `apps/psyche/*` (only `admin` present), and
`infrastructure/psyche/*` — those dirs exist with substantive content but I did
not exercise them. The completeness audit rates the
`psyche-tutor-live-session-to-graded-record` walkthrough as 'partial'
(live-voice envelope, library write, operator review lane noted as 'unbuilt
surfaces'), confirming the runtime UI/transport is less mature than the contract
layer. So: contract+logic layer = real and rich; end-to-end live voice/avatar
session = partially built/aspirational.

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md:807-808 (§ Psyche · Adapter)` — claim: _Adapter file is
  `libs/oshun/embodiment-psyche/src/adapter.ts` (+ avatar-sync.ts,
  backpressure.ts, crisis-frame.ts)_ → **reality:** All four files exist, but
  this list materially undersells the library: the canonical entry is
  `canonical-adapter.ts` (factory `createCanonicalPsycheEmbodimentAdapter`), and
  the session machinery lives in session-envelope.ts, session-events.ts,
  reconnect-behavior.ts, transcript-sync.ts, multimodal-state.ts,
  latency-dashboard.ts, fallback-routing.ts, provider-failover.ts,
  session-audit.ts, session-diagnostics.ts, emotion-modulation.ts,
  screen-context.ts, quality-thresholds.ts, voice-orchestration.ts (23 modules
  in index.ts). Not strictly wrong, but incomplete enough to mislead.

**Contradictions reconciled**

- (features.md:2200-2203 vs libs/oshun/embodiment-psyche/src/session-events.ts)
  features.md lists the canonical V1 event types (text-token-stream,
  asr-partial, asr-final, tts-chunk, avatar-frame, viseme-stream,
  expression-update, turn-complete, interruption, reconnect, transcript-sync,
  error, kill-switch, fallback-engaged, policy-intervention). Code
  PSYCHE*V1_SESSION_EVENT_TYPES matches this exactly. NOTE the doc omits the
  SERVER turn events `turn-start`/`turn-end` (PSYCHE_SERVER_TURN_EVENT_KINDS)
  and the legacy dotted protocol family
  (turn.claim/grant/yield/interrupt/barge-in/timeout, stream.*, reconnect.\_,
  session.\*) which also exist — not a contradiction but an under-description
  gap.

**Enrichment added (real code previously under-described)**

- The server-mediated turn-taking STATE MACHINE is fully implemented
  (createPsycheServerTurnState / applyPsycheServerTurnCommand with turn-start,
  turn-end, interruption, system-initiated-barge-in commands;
  PsycheServerTurnPhase = idle/active/interrupted/complete). Docs describe turn
  semantics narratively but never name this reducer or its phases.
- The full DUAL event taxonomy: docs only show the 15 V1 wire event types, but
  code also ships the legacy dotted protocol (PSYCHE_LEGACY_SESSION_EVENT_KINDS:
  turn.claim/grant/yield/interrupt/barge-in/timeout +
  stream.audio.frame/transcript.partial|final/avatar.frame/tool.call|result +
  reconnect.attempt/success/failed/handoff +
  session.state-changed/error/heartbeat) plus server turn-start/turn-end. The
  discriminated union PsycheSessionEvent covers all of them.
- Concrete phoneme→viseme mapping: PSYCHE_AVATAR_VISEME_TABLE maps 39 ARPABET
  phonemes into 11 visemes (PSYCHE_AVATAR_VISEMES:
  rest/ah/ee/oh/oo/mb/fv/ss/th/eh/ay), with interpolatePsycheAvatarPose and
  assessPsycheAvatarAlignment drift detection. Docs say 'lip-sync' and 'viseme
  alignment' abstractly without naming the table.
- Backpressure admission control: decidePsycheSessionAdmission,
  planPsycheBackpressureShed (PSYCHE_BACKPRESSURE_SHED_ACTIONS), and provider
  backpressure throttle/thinking-indicator/fallback plans with
  PSYCHE_PROVIDER_BACKPRESSURE_DEFAULT_POLICY (thinkingIndicatorDeadlineMs:200).
  Docs mention back-pressure but not admission/shed mechanics.
- Session envelope is a rich validated record: lifecycle states with
  PSYCHE_SESSION_LIFECYCLE_TRANSITIONS graph, fingerprinting
  (computePsycheSessionEnvelopeFingerprint), modality negotiation
  (negotiatePsycheSessionModalities), persona-switch planning
  (planPsycheSessionPersonaSwitch), entitlement classes
  (PSYCHE_SESSION_ENTITLEMENTS), transport tiers, latency budgets — all worth
  surfacing.
- Crisis-frame continuity (crisis-frame.ts) is a first-class implemented module
  producing policy-intervention event + persona.break + lilith.intervention
  audit events and a synthesis-halt plan; ARCHITECTURE mentions crisis-frame.ts
  but features.md § Continuity Tests only describes it narratively.
- Living Scenes integration events (events/scene-events.ts, frame-stream.ts,
  cue-plan-replay.ts) are implemented; docs reference them but the frame-stream
  backpressure channel is real code.

_Captured 18 code-verified grounding facts for this area._

### substrate-lilith

**Real vs aspirational.** The policy LIBRARY is overwhelmingly REAL and
domain-specific: deterministic detectors with regex phrase catalogs, versioned
policy sets, validated taxonomies, and eval suites (eval-tone-quality,
eval-crisis-handling, eval-clone-abuse-resistance, eval-spiritual-boundary,
eval-unsafe-claim, eval-regression-blockers). Verbatim matches: TONE_BAND_IDS (8
bands, exact order contemplative-strict→urgent-safe),
LILITH_UNSAFE_CLAIM_CLASSES (9 classes, exact), LILITH_CRISIS_TYPES (13
signals), LINEAGE_PERSONA_ROLES (7 roles, exact), OSHUN_LAUNCH_LOCALES (8
locales en-US/es-US/fr-FR/de-DE/ar/he/ja-JP/pt-BR, exact), STILLNESS_WINDOW
floor 3min/default 10min, 24h+7d check-ins. The canonical adapter binds a
defense-in-depth crisis analyzer by default (the validated 13-rule catalog) that
can only escalate severity — a real no-bypass guarantee, not a stub.
ASPIRATIONAL / thin parts: the ENFORCEMENT WIRING into every surface is partial
— the completeness audit rates `crisis-aware-tone-policy` and
`arete-living-offering-create` (Lilith crisis pre-screen) as 'partial', and the
triage audit confirms the customer Lilith explore surface (LilithExplore in
customer-shell.tsx:132) is imported by NO route. The ARCHITECTURE 'enforced on
every assistant turn / Living Scenes render / Tara invitation' is the design
intent; the policy CATALOGS and DETECTORS are real, but full runtime fan-out
across all surfaces is not uniformly proven. I could not verify the live
cloned-voice provenance pipeline or the operator override governance UI
end-to-end (catalog logic exists; runtime/UI wiring less so).

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md:821-823 (§ Lilith · Adapter)` — claim: _Adapter is
  `libs/oshun/persona-policy-lilith/src/adapter.ts` (+
  contemplative-tone-policy.ts, assistant-persona-binding.ts,
  content-qa-hooks.ts)_ → **reality:** All four exist, but this lists 3 of ~30
  modules and omits the largest/most important policy files:
  crisis-behavior-policy.ts (68KB), unsafe-claim-policy.ts (65KB),
  voice-policy.ts (62KB), spiritual-boundary-policy.ts (43KB), policy-model.ts
  (38KB), surface-policy-binding.ts (34KB), teacher-safety-policy.ts (32KB),
  generation-gentleness-floor.ts (33KB), crisis-recovery/, sacred-symbols/,
  tone-bands/. The canonical entry is canonical-adapter.ts
  (createCanonicalLilithPersonaPolicyAdapter). The cited list materially
  understates the substrate.

**Contradictions reconciled**

- (features.md:2291-2293 vs ARCHITECTURE.md:816-817 and
  apps/oshun/web/src/app/lilith/page.tsx) features.md says 'The public-facing
  /lilith route is the design-system showcase; the operator-facing /lilith admin
  workspace is the in-world Lilith operations console.' Code confirms:
  apps/oshun/web/src/app/lilith/page.tsx IS the design-system showcase ('the
  whole design system reads as one page', 57-card catalog). But
  ARCHITECTURE.md:816-817 separately notes 'distinct from the Lilith meditation
  app elsewhere in the monorepo' (apps/lilith/, which is a full meditation
  product: bff, svc-ai, mobile, desktop). The two docs are consistent but a
  reader can easily conflate the THREE distinct things: (a) the persona-policy
  substrate lib, (b) the /lilith design-system showcase route, (c) the
  apps/lilith meditation app. The naming overload is a real source of confusion
  the rewrite should call out explicitly.

**Staleness refreshed**

- `V1/features.md:2352-2356 (§ Crisis-Aware Behavior · Signal taxonomy)` — The
  prose signal taxonomy ('suicidal ideation (active, passive, planned),
  self-harm (active, ideation)...child-protection signals') does not map 1:1 to
  the code enum LILITH_CRISIS_TYPES (suicide-ideation, active-self-harm,
  acute-panic, dissociation, trauma-resurfacing, substance-crisis,
  interpersonal-violence, violence-toward-others, abuse-disclosure,
  eating-disorder, child-safety, psychosis-adjacent, acute-grief — 13 entries).
  Code uses 'child-safety' (not 'child-protection'), 'psychosis-adjacent' (not
  'psychotic-symptom indicators'), and adds 'trauma-resurfacing' and
  'acute-grief' not in the doc; the doc's sub-qualifiers
  (active/passive/planned) are not separate enum members. Worth reconciling the
  doc to the canonical 13-type enum.

**Enrichment added (real code previously under-described)**

- The defense-in-depth crisis guarantee is a concrete, testable mechanism the
  docs only state abstractly: createCanonicalLilithPersonaPolicyAdapter binds
  createLilithCrisisSafetyAnalyzer (the validated 13-rule catalog) ON BY DEFAULT
  and merges via mergeLilithSafetyAnalyses always taking the MORE SEVERE signal
  — so an always-'safe' injected backend can never silently bypass the crisis
  catalog. This is the real teeth behind features.md:2368-2369 'No-bypass
  guarantees' and deserves explicit documentation.
- Tone-band catalog is fully data-modeled: tone-bands/catalog.ts has
  TONE_BAND_IDS (8) and TONE_BANDS: ToneBandCap[] with per-band ordered
  position + caps; the features.md per-band capability table
  (motion/audacity/share/generation-tier) maps to real ToneBandCap records.
- Sacred-symbol / lineage binding (sacred-symbols/lineage-binding.ts):
  LINEAGE_PERSONA_ROLES enum (the canonical 7-role taxonomy), LineageBinding
  attestation logic, comparative-only mixing gate — the doc's 'Cultural and
  lineage sensitivity policy' (2574-2601) is backed by real validators.
- Crisis-recovery layer (crisis-recovery/): stillness-window.ts
  (STILLNESS_WINDOW_DEFAULT_SECONDS=600, floor never < 3min, extension ceiling),
  reentry-flow.ts, check-ins.ts (CHECK_IN_KINDS ['24h','7d'],
  CHECK_IN_DELAY_SECONDS), reframe-protection.ts (extends rather than re-fires
  within window/24h), incident-record.ts, locales.ts — the entire features.md
  crisis recovery journey (2636-2682) is implemented as modules, not just prose.
- Unsafe-claim engine: LILITH_UNSAFE_CLAIM_CLASSES (9 classes) +
  LILITH_UNSAFE_CLAIM_CLASS_TAXONOMY with per-class detectionPhrases and default
  responses; voice-policy abuse patterns (LILITH_VOICE_ABUSE_PATTERNS),
  watermark algorithms, cloned-voice consent statuses (signed/revoked/expired),
  provenance requirements — far richer than the doc's bullets convey.
- Operator override governance (operator-override-governance.ts), tenant policy
  constraints (tenant-policy-constraints.ts: tenant cannot loosen / can
  tighten), policy versioning (policy-versioning.ts), moderation queue binding,
  persona-release-metadata + lifecycle — all real modules the docs describe only
  narratively.
- Surface-policy-binding.ts binds policy to named consumers (assistant + domain
  consumers + admin/studio/support) — this is the concrete 'wiring points'
  (features.md:2449-2452) that the doc lists as prose.

_Captured 18 code-verified grounding facts for this area._

### substrate-isis

**Real vs aspirational.** REAL (verified by reading code): the entire
`generation-control-isis` contract/spec layer — workflow-template registry
(state machine draft->...; id/version/param patterns), model registry (license
ids, type->format maps, size caps, state transitions), provider registry,
environment-promotion state machine (`canPromoteEnvironment`, per-env gates, min
bakeoff hours, artefact admissibility), release-gate model
(`evaluateReleaseGate`, regression-gate, safety floor 0.9, quality/watermark
floors, human-review triggers), `CanonicalProvenanceBundle` (full field set
incl. aggregate ed25519/ecdsa-p256 signature, claims, lineage, watermark
attestation, retention/license stamps), per-family failover policy with circuit
breaker + retry/backoff, civitai intake spec + review pipeline
(`decideIntakeAdmission`, `admitCivitaiImportedModelAtRuntime`),
comfyui-governance, and the fail-closed
`evaluateIsisDispatch`/`dispatchGuardedGeneration` seam — all are real, typed,
and unit-tested. The contracts
`WorkflowTemplate`/`ModelCard`/`ModelVersion`/`ProvenanceBundle` exist as Zod
schemas in `libs/contracts/src/common/`. `apps/isis/*` services exist (cli,
generation-api, gpu-worker, output-registry, web, workflow-registry).
ASPIRATIONAL / boundary-gated: the actual provider execution. The dispatch route
ships a fail-closed `notConfiguredProviderExecutor` by default; the source
comments themselves state the audit found the gate had 'zero importers' before
this seam was added, and the real ComfyUI/RunPod client is swapped in only 'at
the app boundary'/'at deploy time with a live key'. So 'every render passes
through Isis release-gate machinery' is structurally enforced in-repo, but the
end-to-end live generation depends on deploy creds and is not exercised in
default e2e (provenance/ledger assertions run only behind
`OSHUN_ISIS_PROVENANCE_LEDGER_FIXTURE=clean` +
`OSHUN_ENABLE_TEST_HARNESSES=true`, per the audits). The operator 'release-gate
dashboard' surface is data-modeled (`admin-view-models.ts`) but I did not verify
a rendered admin UI.

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md:887-889 (Isis Contracts)` — claim: _Contracts:
  `WorkflowTemplate`, `ModelCard`, `ModelVersion`, `ProvenanceBundle` (consent
  ID, prompt, model, watermark hash, timestamp, invoking user, tenant)._ →
  **reality:** Two distinct contract families exist and the doc conflates them.
  The Zod contracts
  `WorkflowTemplate`/`ModelCard`/`ModelVersion`/`ProvenanceBundle` live in
  `libs/contracts/src/common/{workflow-template,model-card,model-version,provenance-bundle}.ts`.
  The `generation-control-isis` adapter lib does NOT export those names — it
  exports `Canonical`-prefixed variants (`CanonicalProvenanceBundle` in
  provenance-bundle-schema.ts:271, plus canonical workflow-template/model
  registry specs). The doc lists the contract names under the Isis adapter
  bullet without noting the adapter uses the canonical-prefixed variants.
- `V1/features.md:3195-3197 (`ProvenanceBundle` schema field list)` — claim:
  _every generation emits a bundle carrying consent ID, prompt, model, workflow
  class, watermark hash, timestamp, invoking user, and tenant._ → **reality:**
  The real `CanonicalProvenanceBundle` (provenance-bundle-schema.ts:271-297) is
  materially richer and does not have a top-level
  `prompt`/`consentId`/`invokingUser`/`tenant` field by those names. It carries:
  `specVersion, bundleId, outputId, outputKind, outputHash{algorithm,value}, sizeBytes, productionContext (workflowTemplateId, workflowVersion, modelId, modelVersion, providerFamily, providerEndpointId, generationType, seed, deterministicReplayable, modifierModelIds), actors[], claims[], lineage[], watermark, releaseGateEvidence[], humanReviewTriggers[], retention, license, aggregateSignature{ed25519|ecdsa-p256}`.
  Consent/prompt/user/tenant are modeled via `actors[]` and `claims[]`, not flat
  fields — the doc's flat field list is an oversimplification.

**Contradictions reconciled**

- (V1/features.md:3219-3221 & V1/ARCHITECTURE.md:1582-1585 (tier names) vs
  libs/isis/entitlements/src/generation-tier.ts:23-28) Both docs declare the
  four 'canonical' tier names are `Customer`, `Curated-Creator`, `AAA-Creator`,
  `Operator`, used 'verbatim'. The real `GenerationTier` union is
  `'operator-admin' | 'aaa-creator' | 'curated-creator' | 'contemplative'`. Two
  of four names diverge: `Customer` is `contemplative` in code, `Operator` is
  `operator-admin`. The 'used verbatim' claim is false against the
  implementation.

**Staleness refreshed**

- `V1/features.md:3144-3145 & 3218 (provider stack list)` — The doc enumerates
  'Civitai, ComfyUI on RunPod, voice/music/3D providers' generically. The
  actually-wired V1 providers are specific and env-gated at the BFF: Stability
  SD3.5 (image), ElevenLabs (voice/TTS), Suno (music), fal.ai-hosted LTX-Video
  (video). RunPod/ComfyUI are the operator execution substrate but no live
  ComfyUI/RunPod client is wired by default (fail-closed
  `notConfiguredProviderExecutor`). The generic phrasing is not wrong but is
  stale relative to the concrete provider set now in code.

**Enrichment added (real code previously under-described)**

- The audit-driven fail-closed enforcement seam (`dispatch-guard.ts`
  `evaluateIsisDispatch` / `generation-dispatcher.ts`
  `dispatchGuardedGeneration`) and its concrete BFF route
  `POST /v1/isis/generate` are the single in-repo mechanism that makes 'Isis is
  the only path' literally true — yet neither the dispatch guard nor the route
  is named anywhere in features.md/ARCHITECTURE.md. The ARCHITECTURE mermaid
  shows the flow conceptually but not the actual enforcement entry point.
- The provider-failover lib models a real circuit breaker (states
  closed/open/half-open, `CANONICAL_PER_FAMILY_FAILOVER_POLICIES`,
  `assessProviderFailover`, `computeRetryBackoffMs`,
  `CANONICAL_FALLBACK_FAMILY_ORDER` per-family degradation). features.md
  describes failover/fallback in prose but never mentions the per-family
  circuit-breaker model or degraded-modes taxonomy that exists in code.
- The environment-promotion lib encodes concrete operational constants absent
  from docs: `CANONICAL_ENVIRONMENT_MIN_BAKEOFF_HOURS`, artefact-environment
  admissibility matrix, and `CANONICAL_ENVIRONMENT_ORDER`
  development->staging->production (+`test`). The doc's 'dev->staging->prod'
  omits the `test` environment that exists in `IsisControlPlaneEnvironment`.
- The release-gate model exposes named floors that would enrich docs:
  `CANONICAL_SAFETY_SCORE_FLOOR = 0.9`, per-output-type
  `CANONICAL_QUALITY_AGGREGATE_FLOOR` and `CANONICAL_WATERMARK_COVERAGE_FLOOR`,
  plus a `CanonicalReleaseGateStatus` of pass/review/block/not-applicable. The
  docs say 'safety/quality drop > MDE blocks' but never surface these concrete
  floors.
- The `apps/oshun/web/src/app/studio/isis/*` legacy provider-machinery route
  tree is now hard-blocked (404) for all segments:
  `STUDIO_ISIS_ALLOWED_ROUTE_SEGMENTS = Object.freeze([])` at
  libs/isis/entitlements/src/studio-boundary.ts:60, and the real customer
  inspector home moved to `/studio/generation-gallery`. The docs still reference
  the old surface boundaries without noting this migration (per
  v1-triage-2026-06-23).

_Captured 18 code-verified grounding facts for this area._

### search-discovery

**Real vs aspirational.** This is the most aspirational of the three areas
relative to what the docs imply. ASPIRATIONAL (built-but-retired, not on the
live path): the entire signal taxonomy/aggregation/decay,
collaborative-filtering + content-similarity + concept-graph + editorial +
cross-domain-bridge candidate generators, the feature-rich ranker with reason
taxonomy and coherence constraints, A/B experimentation framework with
ramp/canary, cold-start, and the concept-graph substrate — all exist in
`libs/oshun/search-discovery` with tests but are explicitly NOT adopted in V1
(the lib's own banner says so, citing the repo's honesty rules: adopting it
would require inventing DiscoveryObject signals the live data doesn't carry).
REAL and shipping: a deterministic lexical search ranker
(`apps/oshun/bff/src/search/ranking.ts` — title/summary exact+token weights,
per-kind boosts, domain-intent boost/penalty) over feed highlights + curated
seeds + the member's real saved objects; cross-domain recommendations
(`recommendations.ts` + `recommendations/scoring.ts`) with a 9-value reason
taxonomy and recency/engagement dimension maps; recommendation feedback
(`POST /v1/recommendations/feedback`, signals hide/less/more); search telemetry;
and the offline-eval gate
(NDCG@10/MAP@10/recall@100/coverage/diversity/serendipity) which IS mounted from
the retired lib. The concept-graph 'Neo4j-backed' substrate
(ARCHITECTURE.md:1641-1643) is not in the live search/recommendation path;
concept-graph code is only in the retired lib + a sophia read adapter.

**Inaccuracies corrected**

- `features.md:3541-3552 (Ranker Features: 'signal scores… persona/tone fit, evidence integrity (Veritas), grounding state (Sophia), entitlement class' + reason taxonomy 'because you saved X… fresh in your concept graph')`
  — claim: _The V1 ranker scores signal/persona/evidence/grounding/entitlement
  features and emits the rich reason taxonomy._ → **reality:** That ranker is in
  `libs/oshun/search-discovery/src/ranker/` but is RETIRED FROM V1
  (index.ts:1-15: the live paths 'do NOT adopt this library… the ranker scores
  DiscoveryObject features the live candidates do not carry'). The live search
  ranker (`apps/oshun/bff/src/search/ranking.ts`) scores only lexical
  title/summary match + per-kind boosts + a 6-domain intent boost/penalty — no
  persona/evidence/grounding/entitlement features.
- `features.md:3563-3574 (Online Experimentation: A/B framework, MDE, ramp 1/5/25/50/100%, canary, kill-switch)`
  — claim: _V1 ships an online A/B experimentation framework with ramp and
  canary._ → **reality:** `ab-framework.ts` and `canary.ts` exist in
  `libs/oshun/search-discovery/src/experiments/` but that library is retired
  from V1 scope and nothing in apps imports the experiments module. No live A/B
  framework is wired into `/v1/search` or `/v1/recommendations`.
- `ARCHITECTURE.md:1641-1643 (Knowledge graph: 'Neo4j-backed graph + Postgres references… Promotion paths route through Sophia evaluation')`
  — claim: _Search/discovery uses a live Neo4j concept-graph with
  Sophia-evaluated promotion._ → **reality:**
  `grep -rln 'neo4j|concept-graph' apps/oshun/bff/src` finds only
  `adapters/sophia-read-adapters.ts` (the Sophia evidence read adapter), not the
  search/recommendation routes. The concept-graph candidate generator lives in
  the retired `libs/oshun/search-discovery/src/concept-graph/`; it does not feed
  live search/recommendations.
- `features.md:3530-3531 (Candidate Generation: 'Concept-graph candidates: traversal… passage → concept → ritual → teacher') and 3525-3539`
  — claim: _Live candidate generation includes collaborative-filtering,
  content-similarity, concept-graph, and cross-domain-bridge candidates._ →
  **reality:** Live `/v1/recommendations` (recommendations.ts) generates
  candidates ONLY by calling the 6 domain adapters' own recommendation methods
  (getRecommendedSessions/getTrendingArticles/getNightlyHighlights/getActiveGoals/getDailyPassage+workspace/getRecommendedCourses).
  There is no CF/embedding/concept-graph/bridge generation in the live path;
  those generators are in the retired lib.

**Contradictions reconciled**

- (ARCHITECTURE.md:1635-1651 (presents search/discovery/KG/recommendations as
  shipping with the search-discovery capabilities) vs
  libs/oshun/search-discovery/src/index.ts:1-15) ARCHITECTURE.md describes the
  full stack as a live capability; the implementing library explicitly states it
  is retired from V1 and the live paths keep their own simpler ranking. The
  architecture page never tells the reader the rich library is unadopted.
- (features.md:3563-3618 (experimentation + offline/online evaluation as one
  shipping suite) vs reality) Only the OFFLINE eval gate is wired live
  (`POST /v1/search/offline-eval`); the online experiment
  metrics/guardrails/significance machinery is in the retired lib and not
  mounted. The doc presents offline and online evaluation as a unified shipping
  surface.

**Staleness refreshed**

- `ARCHITECTURE.md:1637-1640 ('Universal search at apps/oshun/web/src/app/search/page.tsx')`
  — The path exists (a 901-byte page.tsx) but per
  v1-completeness-audit-2026-06-22.md the
  `search-explore-deep-read-library-save` journey is 'partial'; the page is thin
  and the rich object-class universal search the doc lists
  (rituals/passages/claims/sources/notebooks/collections/programs/sky
  events/courses/lessons/artifacts) is served by the lexical BFF route, not a
  dedicated per-class index.
- `features.md:3468-3484 (Searchable Object Catalog: per-class lexical+embedding+facet+freshness indices)`
  — The catalog/index-engine lives in the retired
  `libs/oshun/search-discovery/src/catalog/`; the live search has no per-class
  embedding index — it is lexical over aggregated feed/seed/user-object
  candidates. The catalog spec is stale relative to what ships.

**Enrichment added (real code previously under-described)**

- The live search ranker's actual weights are concrete and undocumented:
  titleExact 40, summaryExact 24, titleToken 8, summaryToken 3,
  domainIntentBoost 10, domainIntentMismatchPenalty 4, plus a per-kind
  kindBoosts table (continue 14, course/lesson 11, etc.) —
  `apps/oshun/bff/src/search/ranking.ts:38-65`.
- The live recommendation reason taxonomy is a real 9-value enum
  (`RecommendationReason`: trending, personalized, time_based, goal_based,
  popular, new_content, streak_support, editorial) with RECENCY_SCORES and
  ENGAGEMENT_SCORES dimension maps — narrower and different from the doc's
  free-text 'because you saved X' taxonomy.
- The live recommendation feedback endpoint `POST /v1/recommendations/feedback`
  (signals hide/less/more, cross-domain telemetry) is real and undocumented in
  the search/discovery section.
- Search results merge THREE candidate pools the docs don't describe: domain
  feed highlights/continue items, curated universal-search seeds
  (`selectUniversalSearchSeeds`), and the member's real saved objects
  (`collectUserObjectCandidates` — saved items/collections/notebooks/habits).
- Real domain-intent routing in search (`resolveDomainIntent`): tokens like
  'course'/'ritual'/'passage'/'claim'/'sky' map queries to a domain and boost
  that domain — a concrete relevance feature.
- The offline-eval release gate that IS live (`buildSearchReleaseGateSummary`
  over NDCG@10/MAP@10/recall@100/coverage/diversity/serendipity with MDE-ratio
  drift checks) is real and should be documented as the one adopted piece of the
  retired lib.
- Partial-failure envelopes + per-domain status (ok/degraded/forbidden) on
  search/recommendations responses are a real resilience feature the docs omit.

_Captured 16 code-verified grounding facts for this area._

### generation-pipeline

**Real vs aspirational.** REAL: deterministic tier resolver
(`resolveGenerationTier`, `TIER_ALLOWLISTS`, `checkSurfaceAccess`) with 4
tiers + 28 surfaces; output-gallery
lineage/branch-replay/compare-grid/bulk-actions (`buildCompareGrid`,
`planBranch`, `validateBranchDelta`); music-generation guardrails + watermark +
provenance; the provider adapter library at
`libs/isis/ai-providers/src/providers/*` (civitai, comfy, comfy-cloud, three-d,
tts, music-generation, video-generation, instantid, ip-adapter, etc.); the
audio-generation provider set (suno-provider.ts, udio-provider.ts,
self-hosted.ts, sfx-provider.ts, music-generator.ts). The BFF executors
(image/narration/music/video/caption-dub/accessibility-pass/explainer/sky-briefing/curated)
are real and route through release measurements. PROVIDER-GATED / ASPIRATIONAL:
every live provider call is env-gated and fail-closed by design — image needs
`OSHUN_STABILITY_*`, voice needs `OSHUN_ELEVENLABS_API_KEY` +
`OSHUN_ELEVENLABS_VOICE_ID`, music needs `OSHUN_SUNO_API_KEY`, video needs the
fal.ai key; with no key the resolver returns `null` and the job fails closed
(`provider_not_configured`). The HTTP paths to Stability/ElevenLabs/Suno/LTX are
'exercised at deploy time with a live key' per their own source comments — not
in default CI. LoRA training, model merging, gaussian-splatting, 3D pipelines
exist as data-models/surfaces (`@isis/lora-training-surface`,
`@isis/runpod-surface`) but I did not verify live training execution. I could
not confirm any rendered AAA Yemaya Studio graph editor;
`apps/yemaya/studio-{web,desktop}` exist and studio-web imports
`@oshun/render-farm`.

**Inaccuracies corrected**

- `V1/features.md:3219-3222 & 3230 (`Customer` tier name)` — claim: _The four
  canonical tier names — `Customer`, `Curated-Creator`, `AAA-Creator`, and
  `Operator` — are the single canonical generation-tier taxonomy for V1, used
  verbatim._ → **reality:** The implemented `GenerationTier` union
  (libs/isis/entitlements/src/generation-tier.ts:23-28) is
  `'operator-admin' | 'aaa-creator' | 'curated-creator' | 'contemplative'`.
  `Customer` is `contemplative`; `Operator` is `operator-admin`. Two of four
  'verbatim' names do not match code.
- `V1/features.md:3386 (music provider list)` — claim: _Music-generation
  provider abstraction (MusicGen, Suno, Udio, Stable-Audio, custom-on-Comfy)._ →
  **reality:** libs/isis/audio-generation/src/generation/ has suno-provider.ts,
  udio-provider.ts, self-hosted.ts, sfx-provider.ts, music-generator.ts — no
  MusicGen or Stable-Audio named provider file. The realtime music path
  (apps/oshun/bff/src/generation/realtime-music-provider-env.ts) wires Google
  Magenta RT (`MagentaRtProvider` from `@euterpe/providers`), which the doc's
  list omits. The BFF batch music path (music-provider-env.ts) wires ONLY Suno
  today (`SunoProvider`, `OSHUN_SUNO_API_KEY`); Udio exists as an adapter but is
  not BFF-wired.
- `V1/features.md:3409-3411 (3D provider abstraction) and ARCHITECTURE flow 1614`
  — claim: _Provider // ComfyUI · ElevenLabs · Suno is the execution provider
  for the request flow._ → **reality:** The video path actually uses
  fal.ai-hosted LTX-Video (`LTXProvider` from
  `@isis/ai-providers/providers/video-generation`,
  apps/oshun/bff/src/generation/video-provider-env.ts:29), and image uses
  Stability SD3.5 (`StabilityProvider`), not ComfyUI directly. ComfyUI/RunPod
  are the operator substrate but the live customer-facing executors call hosted
  HTTP providers (Stability/ElevenLabs/Suno/fal.ai), so the mermaid's provider
  label is incomplete.

**Contradictions reconciled**

- (V1/DEPENDENCIES.md:261-262 (Suno + Udio music) vs
  apps/oshun/bff/src/generation/music-provider-env.ts) DEPENDENCIES lists Suno
  AND Udio music adapters as V1-used. The udio-provider.ts adapter file exists,
  but the BFF music executor env resolver wires ONLY Suno (`SunoProvider`,
  `OSHUN_SUNO_API_KEY`, `OSHUN_SUNO_MODEL_VERSION`). Udio is library-present but
  not customer-path-wired — the docs imply parity that the BFF wiring does not
  have.

**Staleness refreshed**

- `V1/DEPENDENCIES.md:260 (ElevenLabs adapter path)` — Doc cites adapter at
  `libs/isis/ai-providers/src/providers/tts/elevenlabs-provider.ts`; the
  providers dir confirms a `tts` subdir exists, but I did not verify that exact
  filename — the BFF imports voice via `narration-provider-env.ts` resolving
  ElevenLabs from env. Worth re-verifying the exact path during rewrite.
- `V1/features.md:3235 & 3240 (studio surface paths)` —
  `apps/oshun/web/src/app/studio/` exists with real `generation`,
  `generation-gallery`, and a now-hard-blocked legacy `isis` dir;
  `apps/yemaya/studio-web` and `studio-desktop` exist. The doc paths resolve,
  but the AAA-tier `studio/isis/*` customer routes are now 404-hard-blocked
  (studio-boundary allowlist emptied) — the 'AAA-tier routes return disclosure +
  Yemaya signup gate' claim at features.md:3252 is partly stale (legacy isis
  segments hard-block 404, not CTA).

**Enrichment added (real code previously under-described)**

- `@oshun/render-farm` (libs/oshun/render-farm) is entirely undocumented in V1
  docs despite being a real lib imported by `apps/yemaya/studio-web`
  (vite/vitest config). It provides render-farm scheduling primitives: priority
  queues, worker-node capability matching, GPU requirement matching, dependency
  execution, preemption, checkpoint/resume, cloud-burst, cost estimation,
  dashboard snapshots (exports RenderJob, RenderAssignment, RenderCheckpoint,
  RenderCloudBurstPlan, RenderCostEstimate, PreemptionDecision, etc.). This is
  the AAA-tier execution scheduler the docs gesture at but never name.
- `@oshun/creative-orchestrator` (libs/oshun/creative-orchestrator) is
  undocumented in V1 docs but is a real, BFF-wired lib
  (apps/oshun/bff/src/agentic/creative-generator-tools.ts,
  agentic-governance-gate.ts; libs/yemaya/orchestration + agents). It implements
  a real LLM planner (`decomposeBrief` -> schema-validated `CreativePlan` DAG
  via `@oshun/ai/agent-loop`), governed routing
  (`routePlan`/`CreativeOrchestrator` + `BudgetGovernanceGate`), and a Reflexion
  critique->revise loop (`reviseArtifact`), with fail-loud-when-no-provider. The
  contemplative/curated 'send-to-editorial' and autonomous generation pipeline
  depend on this — it deserves a page.
- The realtime/streaming music path (`MagentaRtProvider` over
  `@euterpe/providers`, on-device runtime, frame-by-frame socket streaming) at
  apps/oshun/bff/src/generation/realtime-music-route.ts +
  realtime-music-provider-env.ts is a distinct generation mode (live streaming
  vs batch submit->poll) not described in features.md's music section.
- The tier system exposes 28 concrete named surfaces (`GenerationSurface` enum:
  graph-editor, civitai-search, civitai-lora-hash-picker, lora-trainer,
  model-merger, model-comparison, runpod-region-selector, gpu-worker,
  multi-gpu-orchestration, gaussian-splatting, auto-rigging, topaz, rife,
  animatediff, voice-cloning-tool, music-generation, 3d-generation,
  runpod-dashboard, intake-review-queue, lora-training-queue,
  output-gallery-admin, comfyui-node-registry, audit-trail, curated-image,
  curated-living-scene, curated-voice-clip, curated-workflow-pick,
  curated-asset-search) with explicit per-tier `TIER_ALLOWLISTS`. The docs
  describe surfaces in prose but never enumerate this canonical surface
  vocabulary — a high-value enrichment.
- output-gallery compare-grid supports typed `DiffMetric` per asset class with
  `buildCompareGrid`, and branch-replay enforces
  `ParameterAllowedRange`/`validateBranchDelta`/`planBranch`
  (libs/isis/output-gallery/src/). The docs describe compare/branch in prose but
  the real typed contracts (and that branch is range-validated, not free-form)
  would enrich the gallery page.
- The concrete env var contract for live generation is undocumented:
  `OSHUN_STABILITY_MODEL` (default `sd3.5-large`), `OSHUN_ELEVENLABS_API_KEY` +
  `OSHUN_ELEVENLABS_VOICE_ID`, `OSHUN_SUNO_API_KEY` + `OSHUN_SUNO_MODEL_VERSION`
  (v3|v3.5|v4|v5). These are the real deploy-time toggles that flip a surface
  from fail-closed to live.

_Captured 18 code-verified grounding facts for this area._

### aje-crypto

**Real vs aspirational.** IMPLEMENTED and real: the five new Aje chain modules
(monero/litecoin/ton/ergo/tron) each have real RPC clients, real chain-valid
address derivation (verified TRON keccak256+base58check, Ergo secp256k1 P2PK,
Litecoin BIP84, TON v4r2 StateInit, Monero subaddress), confirmation policies,
e2e tests against regtest/testnet/stagenet/sandbox, and trust-tier disclosure
(tron/ton). The bridge's CONFIRMATION_POLICY (32 assets with per-tier depths,
Solana commitment sentinels -1/-2), RAIL_REGISTRY (A/B/C tier +
native/decentralized-issuer/central-issuer-with-freeze classes + English
disclosure copy + acknowledgement gate gateInvoiceCreation), Ed25519
ReceiptSigner with deterministic canonical JSON + Monero proof + verification
snippet, oracle-aggregator (price-feed/tor-egress/rate-lock), cold-spend-queue
(queue/sweep-policy/hw-signing-fixture/audit-attestation), and entitlement-bus
emitter+topics are all genuine, non-stub code. The BFF actually consumes the
bridge (listSupportedAssets, ReceiptSigner, V1PaymentAsset, quote-builder,
settlement-route, invoice-store). ASPIRATIONAL / not-wired: (1) The bridge
declares @aje/chains, @aje/oracles, @aje/payments, @aje/wallets,
@oshun/event-bus, @oshun/audit-platform, @oshun/identity as dependencies but
src/ imports NONE of them — the 'bridge' reimplements its own AjeInvoiceStatus
vocabulary and never calls Aje. (2) Live wallet/merchant settlement is
unexercisable headless — the sign-up-and-pay-crypto walkthrough is 'pass
(surfaces) / partial (settlement)' and depends on a documented external merchant
integration (BTCPay/OpenNode); BFF server.ts:930 has only a comment placeholder
for the real provisioner. (3) The 'identical schema to the fiat adapter' claim
is unverified/false: libs/shared/inbound-integrations/src/payment.ts uses a
connector-capability model with
PaymentStatus=requires_action|authorized|captured|refunded|failed, which shares
no schema with the bridge's PaymentBusEvent topics. (4) Self-hosted nodes,
cold/air-gapped signing station, hardware co-signers, multisig vaults, and Tor
egress are policy/spec described in code comments and types but are operational
concerns not provable in-repo. I could not verify any running node or live
settlement.

**Inaccuracies corrected**

- `ARCHITECTURE.md:1898 (state-mapper row)` — claim: _state-mapper maps Aje's
  InvoiceStatus (draft, sent, viewed, partial, paid, overdue, cancelled,
  refunded) and ConfirmationStatus (pending, confirming, confirmed, failed,
  finalized) onto the V1 events._ → **reality:** The bridge's actual
  src/state-mapper.ts does NOT consume Aje's types. It defines its own
  AJE_INVOICE_STATUSES = [draft, pending, paid, partial, refunded, expired,
  cancelled] (no 'sent'/'viewed'/'overdue'; adds 'pending'/'expired') and
  AJE_CONFIRMATION_STATUSES = [unconfirmed, confirmed, finalized] (NOT
  pending/confirming/confirmed/failed/finalized). Aje's real
  InvoiceStatus/ConfirmationStatus do match the doc
  (libs/aje/payments/src/merchant/types.ts:24-38) but the bridge never imports
  them.
- `ARCHITECTURE.md:1850-1851, 1893, features.md:5437` — claim: _the bridge 'maps
  Aje's merchant invoice contracts' / 'maps Aje's Invoice / PaymentConfirmation
  / Refund state machine' onto the V1 bus, depending on @aje/\* libraries._ →
  **reality:** libs/oshun/payments-bridge/src/ contains ZERO `from '@aje`
  imports (grep returns nothing). The package.json lists @aje/chains,
  @aje/oracles, @aje/payments, @aje/wallets as deps but no source file uses
  them. The bridge is functionally standalone — it reimplements the model rather
  than adapting Aje.
- `ARCHITECTURE.md:1898, 1905, features.md:5579` — claim: _src/webhook-router.ts
  forwards Aje invoice-state transitions onto libs/shared/event-bus topics
  payment.invoice.confirmed, payment.invoice.settled, payment.refund.broadcast
  with 'identical schema to the fiat-rail adapter's emissions in
  libs/shared/inbound-integrations/src/payment.ts'._ → **reality:** No
  webhook-router.ts file exists. The real module is src/entitlement-bus/
  (emitter.ts + topics.ts). The emitter takes an injected `publish` fn and never
  imports @oshun/event-bus. The fiat payment.ts
  (libs/shared/inbound-integrations/src/payment.ts exists) defines a connector
  model with PaymentStatus=requires_action|authorized|captured|refunded|failed —
  it does not emit the bridge's PaymentBusEvent topics, so the schemas are not
  identical.
- `ARCHITECTURE.md:1904, features.md:5617` — claim: _src/crisis-suppression.ts
  is the 'Single source of truth' that 'gates every invoice-creation path
  regardless of which chain is requested.'_ → **reality:** No
  src/crisis-suppression.ts exists in payments-bridge. Crisis suppression is
  implemented only in src/customer-surface/telegram-bot-router.ts
  (routeUpgradeCryptoCommand returns {action:'suppress', reason:'crisis-active'}
  when crisisState==='active'). It gates the Telegram /upgrade command, NOT
  'every invoice-creation path.' (A separate unrelated crisis-suppression lives
  in the BFF at apps/oshun/bff/src/safety/.)
- `ARCHITECTURE.md:1899` — claim: _src/trust-tier-disclosure/ is a directory._ →
  **reality:** It is a single flat file src/trust-tier-disclosure.ts
  (RAIL_REGISTRY + gateInvoiceCreation). Conversely the docs list
  src/oracle-aggregator.ts, src/cold-spend-queue.ts, src/receipt-signer.ts as
  flat files but each is actually a directory (oracle-aggregator/,
  cold-spend-queue/, receipt-signer/).
- `ARCHITECTURE.md:1903` — claim: _src/telegram-handoff.ts renders BOLT11/Monero
  subaddresses/Solana Pay URLs/TON @wallet deep links._ → **reality:** No
  telegram-handoff.ts exists. Telegram handling lives in
  src/customer-surface/telegram-bot-router.ts (and asset-chain-filter.ts).
  QR/paywall rendering is in customer-surface/qr-matrix.ts, qr-svg.ts,
  paywall-spec.ts.
- `ARCHITECTURE.md:1902, features.md:5575` — claim: _the Monero payment-proof
  tuple is (txid, tx_key, address) — a 3-tuple attached to the receipt._ →
  **reality:** The real type MoneroPaymentProof (receipt-signer/types.ts:33) is
  only { txKey, address } — a 2-tuple. txId is a separate top-level
  ReceiptPayload field, not part of the proof tuple.
- `ARCHITECTURE.md:1898` — claim: _the bridge emits events
  payment.invoice.confirmed, payment.invoice.settled, payment.refund.broadcast._
  → **reality:** The state-mapper's V1_PAYMENT_EVENT_TYPES are
  payment.invoice.settled, payment.invoice.underpaid, payment.invoice.expired,
  payment.refund.broadcast — it never emits payment.invoice.confirmed (that
  topic exists only in the separate entitlement-bus/topics.ts). There is an
  internal inconsistency between the two modules' event vocabularies.

**Contradictions reconciled**

- (ARCHITECTURE.md:1898 (state-mapper) vs ARCHITECTURE.md:1905 / 1898 (event
  topics)) The state-mapper row lists emitted events as
  confirmed/settled/refund.broadcast, but mirrors the code's own internal split:
  real state-mapper.ts emits settled/underpaid/expired/refund.broadcast while
  entitlement-bus/topics.ts defines confirmed/settled/refund.broadcast. The doc
  conflates two distinct, non-aligned event vocabularies that the code itself
  does not reconcile.
- (features.md:5443 / ARCHITECTURE.md:898 ('library-only, consumed via the
  bridge') vs reality of bridge dependencies) Both docs frame Aje as a library
  consumed through payments-bridge, but the bridge does not import Aje at all.
  The 'Aje stays library-only, consumed through this bridge' narrative implies a
  consumption path that the code does not contain.
- (features.md:5562-5568 (invoice lifecycle:
  created→seen→confirmed→settled→entitlement_granted with
  expired/overpaid/underpaid/refunded) vs state-mapper.ts) The docs describe a
  5-stage lifecycle with seen/confirmed/entitlement_granted stages and an
  explicit 'overpaid' terminal state. The real AjeInvoiceStatus has no 'seen' or
  'overpaid'; overpayment is not a modeled terminal state in state-mapper.ts
  (only partial→underpaid is). The lifecycle string is aspirational.

**Staleness refreshed**

- `libs/oshun/payments-bridge/src/entitlement-bus/topics.ts:6` — Doc-comment
  says 'thirteen crypto rails' but the PaymentRail union actually lists 14
  crypto-\* rails (crypto-cardano included). Off by one.
- `ARCHITECTURE.md:911-912 / features.md:5435-5436` — Doc states @aje/chains
  already covers Avalanche and zkSync, but libs/aje/chains only has dirs for
  abstraction, cardano, ergo, litecoin, monero, solana, ton, tron — no Avalanche
  or zkSync chain dirs exist as separate modules (they may live only in
  chains/src/). Verify the 'already provides' table against chains/src/ contents
  before re-asserting Avalanche/zkSync.
- `ARCHITECTURE.md:923-925` — The bridge module description (entitlement bus,
  receipt signing, cold-spend refund queue, Telegram @wallet handoff) predates
  the much larger real surface — it omits admin-surface (explorer-urls,
  invoice-timeline, node-health-panel, refund-initiation), security-gates
  (build-time-invariants, chaos-tester, disclosure-audit, node-health-probes,
  tabletop), and customer-surface QR generation. The brief 'thin and
  Oshun-aware' framing is stale.

**Enrichment added (real code previously under-described)**

- The bridge's security-gates/ module (build-time-invariants.ts,
  chaos-tester.ts, disclosure-audit.ts, node-health-probes.ts, tabletop.ts) is
  real and undocumented — these implement build-time invariant scanning,
  chaos/tabletop testing, and node-health probing that the docs only allude to
  as 'tests cover'.
- The admin-surface/ module (explorer-urls.ts, invoice-timeline.ts,
  node-health-panel.ts, refund-initiation.ts, invariant-guards.ts) implements
  the admin billing surface for crypto — entirely real code, not described in
  the architecture's bridge table.
- customer-surface QR generation is a real, from-scratch implementation
  (qr-matrix.ts, qr-svg.ts, qr-format-bits.test.ts) — the docs mention QR via
  @aje/payments/merchant but the bridge ships its own QR matrix/SVG encoder.
  Worth documenting as a real V1 artifact.
- The receipt-signer ships a real verificationSnippet (curl/shell a customer
  runs to verify on-chain) and locale-tax.ts (tax breakdown reused from fiat
  receipt formatting) — concrete, customer-facing features the docs
  underspecify.
- reminder-cadence.ts in customer-surface implements the 7d/24h/1h
  renewal-invoice reminder cadence described at features.md:5582-5585 — real
  code backing the doc claim, worth cross-linking.
- The billing-aje-bridge in @oshun/billing-support (billing-aje-bridge.ts) is
  the actual entitlement linkage: it collapses 6 EntitlementClass values
  (free/starter/plus/pro/scholar/institutional) onto 3 OshunEntitlementTier
  values (free/pro/premium) and advances the subscription state machine
  (trial/active/grace/restored/past-due/paused/canceled/lapsed) from an
  AjePaymentSettlement {status:'confirmed'|'failed'|'refunded'}. This concrete
  entitlement bridge mechanic is absent from the docs, which describe
  entitlement granting only abstractly.
- The BFF integration (apps/oshun/bff/src/payments/: quote-builder,
  invoice-store, settlement-route, payments-composition) is the real consumer
  that wires the bridge — undocumented in the architecture, which implies apps
  consume Aje 'through this bridge' without naming the BFF layer.

_Captured 18 code-verified grounding facts for this area._

### cross-domain

**Real vs aspirational.** The persona-registry is genuinely, deeply implemented
— far beyond a contract skeleton. It has a PersonaRecord registry with
deterministic fingerprinting, a roles/catalog.ts with all 7 canonical roles
(teacher, coach, explainer, steward, comparative, narrator, assistant) each with
capability ceilings, AvatarPack + VoiceProfile contracts, a ConsentLedger, and
~14 named eval modules (eval-lipsync-alignment, eval-coherence,
eval-deceptive-realism-risk, eval-impersonation-risk,
eval-cloned-voice-red-team, eval-disclosure-visibility, eval-expression-quality,
eval-multimodal-identity-coherence, eval-style-consistency-drift) plus drift
detectors and e2e signoff tests. The five files ARCH names
(realism-impersonation-thresholds.ts, voice-provider-abstraction.ts,
avatar-pack.ts, watermark-provenance.ts, launch-multimodal-assignments.ts) all
EXIST. requireC2paManifest is a real policy input. The Aja adapter, Yemaya SDK,
and the four other subsystems' library trees are real. What is ASPIRATIONAL /
unverified by me: actual avatar RENDERING / lip-sync against ground-truth video,
real cloned-voice TTS output (provider-side modules under
libs/isis/ai-providers/src/providers/tts/elevenlabs-provider.ts and
libs/isis/audio-generation/src/voice/elevenlabs-client.ts exist but I did not
exercise them), and whether bellona/hathor/neith's many sub-libs are uniformly
production-grade vs. partially scaffolded (out of scope to fully verify here).
The completeness audit (2026-06-22) marks persona-voice-avatar-approval-workflow
as PARTIAL — registry lifecycle/signoff is covered but full
deprecate/retire/recovery and consumer-picker round-trip are thinner.

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md §Persona/Avatar/Voice ~1948 'Contracts: Persona, VoiceProfile, AvatarPack (with consent / lineage / lifecycle metadata). … every published persona binds a ConsentRecord'`
  — claim: _named contracts are Persona / VoiceProfile / AvatarPack, and
  personas bind a ConsentRecord_ → **reality:** VoiceProfile
  (voice-profile.ts:195) and AvatarPack (avatar-pack.ts:150) exist in
  persona-registry. A `Persona` type exists but in
  libs/contracts/src/common/persona.ts:802 (z.infer of PersonaSchema); the
  registry's own record type is PersonaRecord (index.ts:158), NOT `Persona`.
  There is NO type named `ConsentRecord` anywhere in persona-registry — the
  consent primitive is `ConsentLedger` (consent-ledger.ts:113). Minor but the
  ARCH names two types (Persona-as-registry-record, ConsentRecord) that don't
  match the code's PersonaRecord / ConsentLedger.

**Staleness refreshed**

- `V1/ARCHITECTURE.md §Cross-Domain Support table ~940 (Yemaya row)` — Yemaya
  adapter cell says '(used through libs/yemaya/sdk and BFF route)'.
  libs/yemaya/sdk exists, but libs/yemaya is now a very large multi-package
  domain (40+ top-level module dirs incl. case-\* pipeline, comfyui-integration,
  asset-generation, av-sync) — the single-line 'rendering substrate' description
  undersells its current scope. Not wrong, but stale-thin.

**Enrichment added (real code previously under-described)**

- The persona-registry's ~14 eval suites (eval-lipsync-alignment,
  eval-coherence, eval-deceptive-realism-risk, eval-impersonation-risk,
  eval-cloned-voice-red-team, eval-disclosure-visibility,
  eval-expression-quality, eval-multimodal-identity-coherence,
  eval-style-consistency-drift) are real modules; features.md §Evaluation Suites
  describes them in prose but doesn't note they are individually implemented +
  tested.
- ConsentLedger (consent-ledger.ts) with append/verify operations is the real
  consent primitive — docs say 'consent records' generically.
- launch-roster.ts, launch-family-signoff.ts, launch-multimodal-assignments.ts,
  launch-persona-config.ts implement the actual launch cast assembly — richer
  than 'release signoff' prose.
- disclosure-axis-drift-detector.ts, disclosure-visibility-measurement.ts,
  token-time-disclosure-filter.ts implement the 'disclosure visibility ≥ N
  time-on-screen' trust gate concretely.
- prompt-impersonation-detection.ts implements the 'prompt-time
  impersonation-attempt detection' trust gate.
- The persona-registry is dependency-free by design (index.ts comment: does NOT
  import @oshun/persona-policy-lilith; uses an opaque policyPackReference the
  caller resolves) — an architectural fact worth documenting.
- Themis/Bellona/Hathor/Neith are each multi-package COLLECTIONS (40/38/18/20
  sub-libs respectively under distinct npm scopes like @themis/\*) — the docs'
  single-line adapter rows understate that each is a domain tree, not one
  library.
- Voice provider modules:
  libs/isis/ai-providers/src/providers/tts/elevenlabs-provider.ts and
  libs/isis/audio-generation/src/voice/elevenlabs-client.ts back the 'ElevenLabs
  swappable' claim — real provider integration files exist.

_Captured 14 code-verified grounding facts for this area._

### content-authoring

**Real vs aspirational.** Strongly implemented at the CONTRACT/LOGIC layer.
`@oshun/studio-authoring` is real, non-stub, domain-specific code: editorial
lifecycle is a true 12-state machine with a TRANSITIONS table and gate-checking
(tryEditorialAdvance returns transition-not-allowed / unsatisfied-gates),
versioning has validateVersionChain with five issue kinds, taxonomy has
add/merge/split/deprecate/reparent operations with contest status, localization
has translation-memory + glossary + do-not-translate + stale-detection via
sourceHash. The web workspace genuinely consumes the library. What is
ASPIRATIONAL / unverified by me: real-time co-editing with CRDT/presence (the
lib has a collaboration/ module but I did not confirm a running CRDT substrate
vs. contract types); actual MinIO/S3-backed asset storage with binary blobs
(asset-metadata/ is metadata logic, not a storage service); persistence to a
database (the lib is pure functions, timestamps are inputs). The completeness
audit (2026-06-22) flags `editorial-review-approval` as a partial walkthrough
whose spec drives the INCIDENT decision panel (INC-2041) rather than the
editorial artifact lifecycle — i.e. the e2e coverage for the editorial flow is
weaker than the lib implies.

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md §Oshun Studio ~1972` — claim: _'Studio is a subroute under
  apps/oshun/web/src/app/studio/ (no separate app)'_ → **reality:** Accurate as
  stated. The studio/ route dir exists with ~55 subroutes including authoring/,
  commenting-annotation-system/, real-time-collaboration-substrate/, bellona/,
  hathor/, neith/. No contradiction — recording as VERIFIED-correct, not an
  inaccuracy.
- `V1/ARCHITECTURE.md §Oshun Studio ~1990 'Asset and media library — backed by MinIO/S3'`
  — claim: _asset library is backed by MinIO/S3 with provenance bundles
  travelling with every asset_ → **reality:**
  libs/oshun/studio-authoring/src/asset-metadata/ implements
  metadata/rights/provenance/analytics LOGIC only (metadata.ts,
  approval-queue.ts, bulk-upload.ts, exif-and-presets.ts, analytics.ts) — pure
  functions with no MinIO/S3 client. MinIO is a docker-compose dev dependency at
  the infra level; the binding of this lib to object storage is not in this
  library. Storage backing is real at infra level but NOT in the authoring lib.

**Contradictions reconciled**

- (V1/ARCHITECTURE.md editorial-lifecycle mermaid vs
  libs/oshun/studio-authoring/src/editorial-lifecycle/lifecycle.ts
  EDITORIAL_LIFECYCLE_STATES) The ARCH mermaid diagram uses states 'rejected'
  and 'retracted'; the code enum uses neither — it uses 'changes-requested' (not
  'rejected') and 'takedown' (not 'retracted'). features.md's 12-state list
  matches the code; the ARCH diagram does not.
- (V1/features.md §Editorial Calendar 1646 vs V1/ARCHITECTURE.md §Editorial
  lifecycle 1985) features.md asserts a 'full twelve-state set' (idea…takedown)
  while ARCH presents a 7-state 'core editorial subset' with different terminal
  names (retracted/rejected). features.md explicitly notes this is an
  intentional subset, so it is a documented contradiction, but the ARCH subset
  names diverge from the canonical code names.

**Staleness refreshed**

- `V1/ARCHITECTURE.md §Oshun Studio editorial lifecycle list ~1985` —
  ARCHITECTURE lists the lifecycle as 'draft → in-review → approved → scheduled
  → published → archived → retracted' (7 states, with 'retracted'), while
  features.md (1646) and the actual code (EDITORIAL_LIFECYCLE_STATES in
  editorial-lifecycle/lifecycle.ts) define a 12-state set: idea, draft,
  in-review, changes-requested, approved, scheduled, published, updated,
  deprecated, sunset, archived, takedown. The code has NO 'retracted' state and
  NO 'rejected' state in the array (the mermaid diagram uses
  'rejected'/'retracted' which do not exist as code enum members). features.md
  already calls out the discrepancy in prose but the ARCH mermaid uses
  non-existent state names.

**Enrichment added (real code previously under-described)**

- features.md/ARCH do not name the actual backing library
  `@oshun/studio-authoring` or its 9 subdomain modules — a rewrite could cite
  the real exported symbols (STUDIO_CREATOR_ROLES, EDITORIAL_LIFECYCLE_STATES,
  AI_ASSIST_PANELS, TAXONOMY_OBJECT_KINDS).
- The real ROLE_PERMISSION_MATRIX (10 permissions: edit-draft, request-review,
  review, approve-publish, schedule-publish, unpublish, translate,
  curate-taxonomy, manage-assets, mint-certification) mapped per-role is
  implemented but undescribed in docs.
- The recurrence engine (editorial-lifecycle/recurrence.ts) literally encodes
  'daily Veritas briefings, daily Tara passages, weekly Arete reflections,
  nightly Nyx highlights' as cadence logic — docs mention these as examples but
  don't note the recurrence primitive exists.
- The §3 agentic content pipeline (@oshun/content-service with HTTP routes POST
  /v1/content/briefs, GET /v1/content/runs/:id, POST
  /v1/content/runs/:id/replay, GET /v1/operator/runs) is a real deployable
  service that the Content Authoring docs never connect to the authoring surface
  — an enrichment opportunity to show the generate→gate→author handoff.
- ai-assist.ts encodes AiAssistGovernance (tonePolicyId, evidencePackId,
  releaseGateIds, piiRedactionRequired, attributionRequired) — the concrete
  governance binding shape is richer than the prose 'governed by
  Sophia/Isis/Lilith'.

_Captured 15 code-verified grounding facts for this area._

### customer-curation

**Real vs aspirational.** The curation LOGIC is real and non-stub. Collections
module defines 6 collection kinds (notebook, collection, study-queue,
ritual-set, reading-list, saved-search) each with kind-specific fields
(study-queue masteryTarget familiar|developing|proficient|master + perDayCap;
ritual-set cadenceLocalTime + cadenceDaysOfWeek mask; reading-list
targetFinishUnixSeconds; saved-search queryText + filter AST). Smart-collections
has
validateSmartCollectionRules/evaluateSmartCollection/materializeSmartCollectionForOwner.
Annotations implement real selector-chain recovery (TextQuoteSelector
exact/prefix/suffix + TextPositionSelector) with JSON/Markdown/CSV export.
Sharing has SHARE_VISIBILITY [private, named-users, link, public-profile] ×
SHARE_PERMISSION [view, comment, copy] with viewer-resolution logic.
version-awareness has evaluateStaleness + computePassageDiff +
buildVersionAwarenessReport. What is ASPIRATIONAL relative to the lib: actual DB
persistence, tombstone deletion propagation, audit-logging, cross-device
progress sync, and the Iris MemoryScope binding are all asserted in ARCH but
live OUTSIDE this pure library (or are infra-level). The completeness audit
(2026-06-22) marks library-save-collection-share and scene-keep-and-share as
PARTIAL walkthrough journeys, consistent with the lib being contract-complete
but the end-to-end persisted flow being thinner.

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md §Customer Curation ~1671 'Per-domain notebook/collection tables persist through @oshun/persistence and inherit tombstone semantics; deletion propagates and audit-logs'`
  — claim: _customer-curation persists through @oshun/persistence with tombstone
  deletion + audit-log_ → **reality:** libs/oshun/customer-curation/package.json
  declares ONLY devDependencies (typescript, vitest) — no @oshun/persistence
  dependency. No source file in src/ imports @oshun/persistence, references
  'tombstone', or audit-logs. The library is pure data+functions. The
  persistence/tombstone behaviour, if it exists, is in @oshun/persistence (which
  does exist as a lib) wired elsewhere — NOT in customer-curation.
- `V1/ARCHITECTURE.md §Customer Curation ~1666 'Personal notebooks — primary substrate is Nisaba's notebook schema (Notebook contract) extended for cross-domain captures'`
  — claim: _customer-curation notebooks are built on Nisaba's Notebook contract_
  → **reality:** The Notebook contract DOES exist
  (libs/contracts/src/common/notebook.ts: NotebookKind, NotebookDomain,
  NotebookStatus, NotebookVisibility schemas) but customer-curation's
  collections/collections.ts defines its OWN NotebookCollection (extends
  CollectionBase, kind:'notebook', layout: linear|kanban|grid) and does NOT
  import the contracts Notebook schema. The claimed substrate relationship is
  not realized in this library's code.

**Contradictions reconciled**

- (V1/features.md §Customer Curation 1770-1793 vs V1/ARCHITECTURE.md §Customer
  Curation 1652-1683) features.md frames curation as self-contained customer
  surfaces (notebooks, collections, smart collections, sharing, annotations,
  share cards, version-awareness) — which matches the pure
  @oshun/customer-curation library. ARCHITECTURE adds platform-integration
  claims (persistence/tombstone, Nisaba Notebook substrate, Iris MemoryScope)
  that the library does not implement. Not a direct logical contradiction, but
  the two docs describe different layers and ARCH over-attributes integration to
  this surface.

**Staleness refreshed**

- `V1/ARCHITECTURE.md §Customer Curation ~1683` — Iris MemoryScope claim says
  notebook scope sits 'alongside profile/session/operator-copilot/tenant' (4
  peers). The actual IrisMemoryScope type
  (libs/oshun/memory-iris/src/types.ts:45) has 12 values: assistant_profile,
  session, scene, pose, conversation, domain, cross_domain, notebook,
  operator_copilot, tenant, admin_review — and it is 'assistant_profile' not
  'profile', 'operator_copilot' not 'operator-copilot'. The claim is
  directionally correct (notebook IS a first-class scope) but the enumerated
  peer list is incomplete and the names are stylized differently from code.

**Enrichment added (real code previously under-described)**

- features.md/ARCH never name the backing library `@oshun/customer-curation` or
  its 6 modules; a rewrite can cite real exports.
- The 7 collection KINDS with their kind-specific schema fields (study-queue
  masteryTarget bands + perDayCap, ritual-set cadenceDaysOfWeek 0-6 mask +
  cadenceLocalTime HH:MM, reading-list targetFinishUnixSeconds, saved-search
  filter AST) are richer than the prose 'study queues, ritual sets, reading
  lists, saved searches'.
- Smart-collections rule engine (SmartCollectionPredicate,
  SmartCollectionRuleGroup, validateSmartCollectionRules → typed validation
  errors, materializeSmartCollectionForOwner) is real but the docs only say
  'smart collections (rule-based)'.
- Annotation selector-chain model (W3C/Hypothes.is TextQuoteSelector
  exact/prefix/suffix + TextPositionSelector, ANNOTATION_SURFACES =
  nisaba.edition, veritas.story, metis.lesson, tara.transcript, ANNOTATION_KINDS
  = highlight, note, thread-comment, citation, exports JSON/Markdown/CSV) is far
  more concrete than 'highlights, threaded notes, citations'.
- share-cards module implements real oEmbed (renderOEmbed → OEmbedResponse) and
  renderShareCardHtml with
  ProvenanceBlock/GroundingBlock/SyntheticIndicatorBlock + validateShareCard —
  the docs say 'embeddable share cards … with provenance, grounding, and
  synthetic indicators preserved' but don't note the oEmbed/HTML rendering is
  implemented.
- version-awareness computePassageDiff + evaluateStaleness (using
  CustomerSavedRef) backs the 'this passage was updated since you saved it —
  show diff' feature concretely.

_Captured 13 code-verified grounding facts for this area._

### living-scenes-core

**Real vs aspirational.** Strongly implemented as deterministic, pure decision
logic — NOT as a running video renderer. The Conductor (conductor.ts) is a real
segment-slot state machine (pending→pre-warming→ready→streaming→done) with
lookahead-bounded pre-warm, backpressure truncation to lookahead=1, carry-state
handoff, and reconnect planning — but it explicitly notes 'Actual GPU dispatch
lives outside this module.' The Blend Kernel (transitions.ts) owns typed
transition contracts + parameter range validation + a continuity scorecard gate,
but states 'Implementations of the actual DSP / shader code live downstream.'
The compatibility scorer is real (7 dimensions, dice-coefficient grounding
overlap, hard-incompatible policy gate) but uses exact-string equality for
style/motion anchors (styleAnchorId===… → 1 else 0.35), NOT the CLIP-embedding
distance the doc describes. The 12-technique catalog, per-template allowlists,
tone-gating with crisis-collapse, compose-assist (AgentRun budgets, gold-set
precision/recall, tier caps free=6seg/90s, paid=24seg/8min), template fixture
eval-gates (min 30 fixtures, per-template pass-rate thresholds) are all fully
real and tested. The aspirational layer is everything pixel/frame-level: actual
latent video generation, optical-flow warps, FVD computation, GPU determinism —
all modeled as score inputs the pure functions consume, never computed here.

**Inaccuracies corrected**

- `features.md:3655 (Scene Score Schema, Segment fields)` — claim: _Each Segment
  is
  `{intent, public_redacted_intent, duration_band, style_anchor, motion_descriptor, audio_role, narration_script_pin, sophia_grounding_pin, lilith_tone_band, persona_binding, transition_in, transition_out, accessibility_role}`_
  → **reality:** The real SegmentSpec
  (libs/contracts/src/living-scene/score.ts:47-60 and
  libs/yemaya/living-scenes-runtime/src/score/score-schema.ts) is
  `{segmentId, kind, displayName, durationSeconds, tone, workflowClassId, parameters, inboundCarryState}`.
  None of the doc's 13 named fields exist verbatim; intent lives on the Score
  (ScoreIntentLayer), not the Segment; transitions are not stored on segments;
  grounding/persona/accessibility are not Segment fields.
- `features.md:3893-3894 (compatibility scorer style-anchor distance)` — claim:
  _Style-anchor distance — CLIP-embedding distance between the outgoing
  Segment's terminal style anchor and the incoming Segment's opening anchor_ →
  **reality:** The real scorer
  (libs/yemaya/blend-kernel/src/compatibility/scorer.ts:75-77) uses exact-ID
  equality, not CLIP embedding distance: `styleScore` returns 1 if styleAnchorId
  matches else 0.35. Motion (line 79-81) is likewise exact-equality (1 vs 0.5).
  The doc overstates an embedding-based metric that is not implemented in this
  pure module.
- `ARCHITECTURE.md:1328-1330 (AAA Scene Score Editor location)` — claim: _the
  AAA-Creator-tier and operator surface inside Yemaya Studio
  (apps/yemaya/studio-{web,desktop}); it does not appear on the contemplative
  product_ → **reality:** Partly accurate:
  apps/yemaya/studio-web/src/score-editor/ScoreEditorPage.tsx and
  apps/yemaya/studio-desktop/src/renderer/pages/ScoreEditorPage.tsx DO exist.
  But a second Scene/Tara editor also lives on the Oshun web app at
  apps/oshun/web/src/app/lilith-studio/scenes/TaraSceneEditor.tsx and
  /lilith-studio/scene/new — a 'Lilith Studio' surface on the contemplative
  product, which complicates the 'does not appear on the contemplative product
  under any entitlement' claim.

**Contradictions reconciled**

- (features.md technique allowlists (3963-3983) vs the two code allowlists)
  There are TWO per-template technique allowlists in code that must be kept in
  sync: libs/yemaya/blend-kernel/src/catalog/cinematographic-catalog.ts
  (per-technique `templateAllowlist[]`) and
  libs/yemaya/living-scenes-runtime/src/compose-assist/compose-assist.ts
  `TEMPLATE_TECHNIQUE_ALLOWLISTS`. I verified they currently AGREE for all 5
  templates, but they are duplicated source-of-truth that can drift; the docs
  describe only one conceptual allowlist.

**Staleness refreshed**

- `features.md:3641-3643, 4035, ARCHITECTURE.md:1311-1313` — Template IDs in
  prose are friendly names (Tara Contemplative Arcs, Nyx Sky Briefings, etc.);
  the canonical machine IDs are `tara-contemplative-arc`, `nyx-sky-briefing`,
  `veritas-grounded-explainer`, `metis-lesson-visualizer`,
  `arete-living-offering`
  (libs/isis/workflow-classes/src/living-scene/template-catalog.ts:9-15). Docs
  never surface the canonical IDs.
- `features.md:3656-3657 (transition kinds list)` — Doc lists 5 transition specs
  (latent-warm-start, optical-flow-morph, color-LUT-match, audio-crossfade,
  narrative-pivot). The real TRANSITION_KINDS array
  (libs/yemaya/blend-kernel/src/transitions.ts:13-23) has 9: those 5 plus
  motion-descriptor-handoff, motion-descriptor-reset, audio-level-jump,
  variable-rate-sequencer. The doc's list is stale/incomplete.

**Enrichment added (real code previously under-described)**

- The Conductor's real state machine is undocumented: SegmentRenderState enum
  (pending/pre-warming/ready/streaming/done/aborted), planPreWarm window
  `[playheadIdx+1, playheadIdx+minLookaheadSegments]` truncated to 1 under
  backpressure, advancePlayhead carry-state propagation, planReconnect
  resumability (conductor.ts:16-209). RenderEnvelope.minLookaheadSegments is a
  literal union 2|3|4 with a ≥2 release-gate invariant (deepParseScore in
  score.ts:165-167).
- The RenderEnvelope schema is far richer than 'engine version + model hashes'
  prose: it pins widthPx (literal 1080|1440|1920|2560|3840), heightPx, fps
  (literal 24|30|60), maxBitrateKbps, gpuClass (literal
  rtx-4090|a100-40gb|a100-80gb|h100-80gb), minLookaheadSegments
  (score.ts:88-107). Worth a full field table.
- The CarryState protocol is a concrete schema: {clipAnchorAssetId,
  lastFrameConditioningHash (32+ hex chars), motionDescriptor (≤120), lutId,
  audioTailDescriptor} (score.ts:38-44) — the doc's 'CLIP-style style anchor,
  last-frame conditioning, motion-vector descriptor, color-LUT alignment, audio
  tail' maps almost 1:1 but the doc never gives the field names/constraints.
- The 9 Scene events on the Psyche envelope
  (libs/oshun/embodiment-psyche/src/events/scene-events.ts:
  scene.segment-start/-end, transition-start/-end, live-direction-applied,
  policy-intervention, crisis-frame, fallback-engaged) plus monotonic-sequence +
  trace-id verification (verifyEventStream) are entirely absent from the docs —
  this is the real Live Direction Channel telemetry surface.
- Each catalog technique ships concrete evalThresholds
  (maxFvd/maxFlicker/maxColorJump/maxMotionVectorDelta/minNarrationAlignment)
  and a provenanceTag regex `technique:[a-z0-9-]+`; the
  cinematographic-catalog.ts has these per-entry numbers (e.g. match-cut maxFvd
  0.3, smash-cut maxFvd 0.5). The docs describe thresholds qualitatively but
  never give the catalog's actual numbers.
- Transition parameter validation ranges are real and specific
  (latent-warm-start bridgeSteps[2,12], optical-flow-morph
  morphFrames[1,48]/warpStrength[0,1], audio-crossfade fadeMs[50,8000] with
  linear|equal-power|log curve, variable-rate-sequencer rate[0.25,4]) —
  transitions.ts:106-222. Undocumented.
- Compose-assist tier caps and continuity promotion gate: free=6 segments/90s,
  paid=24 segments/8min, aaa=full editor (compose-assist.ts:447-452); promotion
  requires continuityPreScore ≥ 0.85 (compose-assist.ts:585, 688). The doc
  states the seg/duration caps but not the 0.85 promotion threshold or the AAA
  routesToStudioEditor flag.

_Captured 18 code-verified grounding facts for this area._

### living-scenes-gov

**Real vs aspirational.** More fully real than most V1 areas because governance
is decision logic, not media rendering. GENUINELY implemented and tested:
PSE/strobe detector (pse-strobe-detector.ts — real Harding flash-rate analysis,
LUMINANCE_FLASH_DELTA 0.1, DARK_THRESHOLD 0.8, RED_FLASH_DELTA 0.2, >3
flashes/sec hazard, non-overridable safe=false gate); C2PA Ed25519
signer/verifier (ed25519-signer.ts — real @noble/curves ed25519, 32-byte keys,
tamper-evident; the file's header notes the audit found the prior signature was
faked and this is the genuine fix); spread-spectrum audio watermark
(audio-watermark/dsp.ts — xorshift32 PN sequence, chip embed/extract by
correlation, wrong key recovers ≈0); shareability matrix (shareability/matrix.ts
— 9 components, 4 reach levels, min-reach, crisis→private-only precedence);
intent redaction (cue-privacy/intent-redaction.ts — 8 Lilith categories as real
regexes + SHA-256 private-intent hash via @noble/hashes + a precision/recall
corpus evaluator); takedown dispositions (7 kinds, structured
DispositionImpact); determinism harness (per-node frame SHA-256,
mismatch-tolerance gate); backend resolver (chained-clip vs phase-176-nous with
a hard contemplative-never-phase-176 guard); channel-robustness eval (7
channels, ≥1-signal-survival pass). ASPIRATIONAL / fail-loud seams: the
redaction classifier header says 'Real-world deployment will swap in a
model-backed classifier with the same signature'; the crisis classifier model is
'downstream'; actual pixel-level luminance/motion caps, real channel
transcoding, and real C2PA-into-MP4 muxing are upstream. The redaction regexes
are deterministic pattern-matchers, robust for the test taxonomy but not an ML
classifier.

**Inaccuracies corrected**

- `features.md:4316-4317 (Shareability per-component grants)` — claim: _each
  component is tagged `shareable | tenant_internal_only | private_only` (three
  levels)_ → **reality:** The real matrix uses FOUR reach levels
  (shareability/matrix.ts:27-33 REACH_LEVELS): private-only, link-with-password,
  tenant-internal, public — ordered 0..3 with min-reach resolution. The doc
  omits link-with-password (which IS a documented share-time privacy level
  elsewhere at features.md:4247, so the docs are internally inconsistent about
  the level set).
- `features.md:4163-4164 (PSE detector standard)` — claim: _PSE-safe thresholds
  per ITU-R BT.1702-2 / W3C WCAG flash guidelines_ → **reality:** The real
  detector (safety/pse-strobe-detector.ts:9-17) cites 'WCAG 2.3.1 / the Harding
  criteria' and implements that: general flash = opposing luminance transitions
  with swing ≥0.1 and darker side <0.8; red flash on saturated-red fraction
  (delta 0.2); >3 flashes in any 1s window is a hazard. ITU-R BT.1702-2 is NOT
  referenced in code; the doc's standard citation is partly
  aspirational/imprecise.
- `ARCHITECTURE.md:1334 (ProvenanceBundle per artifact)` — claim: _a
  `ProvenanceBundle` per artifact_ → **reality:** The LS runtime does NOT export
  a single `ProvenanceBundle` type; provenance is split into separate modules
  (provenance/visible/visible-mark.ts, audio-watermark/, c2pa/,
  channel-robustness/). A `ProvenanceBundle` symbol exists only in unrelated
  libs/shared/audit-platform. The architecture's named single bundle type is not
  the LS implementation shape.

**Contradictions reconciled**

- (i18n OSHUN_LAUNCH_LOCALES vs LS V1_LAUNCH_LOCALES) The platform launch-locale
  list (8 locales: en-US/es-US/fr-FR/de-DE/ar/he/ja-JP/pt-BR) and the
  Living-Scenes locale-parity list (10 locales: includes en-GB, es-ES, es-419,
  ar-EG, he-IL) are different sets with different region tags. Cue-policy/crisis
  'locale parity across V1 launch locales' (features.md:4476-4477) is therefore
  ambiguous about which set it must hold over.
- (features.md:4316 (3-level component grant) vs features.md:4247 (4
  share-privacy levels) vs code) features.md describes shareability components
  with 3 reach tags but the same doc lists 4 share privacy levels (private link,
  link with password, public — plus tenant) and code (matrix.ts) uses 4 reach
  levels. The doc is internally inconsistent about how many reach levels exist;
  code is the 4-level authority.

**Staleness refreshed**

- `features.md:4226, 4243, 4266, ARCHITECTURE.md:1335 (attestation URL)` — Docs
  write the attestation page as the literal `oshun.app/scene/<id>`. The real
  visible-mark builder (provenance/visible/visible-mark.ts:72-78) constructs
  `${origin}/scene/${encodeURIComponent(shortCode)}` from a short-code, not an
  artifact `<id>`, and origin is injected (no hardcoded oshun.app). Minor: the
  resolver key is the short-code, not the id.
- `features.md:4476, 4023, 4462 + many ('V1 launch locales')` — Docs reference
  'V1 launch locales' without enumerating, and the codebase has TWO DIFFERENT
  launch-locale sets that disagree: OSHUN_LAUNCH_LOCALES
  (libs/oshun/i18n/src/index.ts:26-35) = en-US, es-US, fr-FR, de-DE, ar, he,
  ja-JP, pt-BR (8); but the LS locale-parity module V1_LAUNCH_LOCALES
  (libs/isis/workflow-classes/src/living-scene/locale-parity.ts:13-24) = en-US,
  en-GB, es-ES, es-419, fr-FR, de-DE, pt-BR, ja-JP, ar-EG, he-IL (10). The
  rewrite must pick one and flag the divergence.

**Enrichment added (real code previously under-described)**

- The PSE detector's exact constants and algorithm are absent from docs but are
  the load-bearing safety contract: LUMINANCE_FLASH_DELTA=0.1,
  DARK_THRESHOLD=0.8, RED_FLASH_DELTA=0.2, FLASH_LIMIT_PER_SECOND=3; returns
  {safe, maxGeneralFlashesPerSecond, maxRedFlashesPerSecond, hazards};
  safe=false is a HARD non-overridable block (pse-strobe-detector.ts).
- The C2PA implementation specifics: createEd25519C2paSigner takes a 32-byte
  privateKey + signerKeyId, exposes signerKeyId/publicKeyHex/sign/verify;
  createEd25519C2paVerifier verifies from a published public-key hex
  (ed25519-signer.ts). The doc says 'C2PA Content Credentials signed sidecar'
  but never that it's real Ed25519/EdDSA over @noble/curves and tamper-evident.
- The audio-watermark is a real DSP: deterministic xorshift32 PN sequence
  (key=seed), ±1 chips spread across 128-sample blocks (DEFAULT_CHIP_LENGTH=128)
  at gain 0.08, extraction by per-block correlation; wrong PN key recovers ≈0
  (audio-watermark/dsp.ts). Doc just says 'spread-spectrum embed' without the
  recoverable/keyed-correlation guarantee.
- The shareability matrix's resolution algorithm: 9 components (voice, likeness,
  persona, source, music, intent, tenant-policy, lilith-policy, crisis-state), 4
  ordered reach levels, resolves to the MINIMUM reach across components,
  crisis-state (label !== 'safe') forces private-only with hard precedence; ALL
  9 components must be present or it throws missing-grants (matrix.ts:88-116).
  The deciding-components list is returned. Doc describes the concept but not
  the present-all-9 requirement or the verdict shape.
- The redaction taxonomy is concrete: 8 LILITH_REDACTION_CATEGORIES
  (named-person, deceased, medical-condition, abuse-disclosure,
  location-of-safety, minor-identity, financial-account, legal-status) each with
  a real regex + replacement token, plus evaluateCorpus computing per-category +
  macro precision/recall (intent-redaction.ts). buildIntentLayers SHA-256-hashes
  `intentId\0privateText` for privateIntentHash. Doc lists some categories
  prose-only and omits minor-identity/financial-account/legal-status and the
  hash construction.
- 7 takedown dispositions (takedown/dispositions.ts DISPOSITION_KINDS) each
  producing a DispositionImpact with playback state
  (unchanged|voice-muted-with-banner|pause-with-banner|quarantined-until-rerender|hard-deleted-tombstoned),
  rerenderOption, sharedLinkState (banner-only|invalidated|tombstoned), and
  concrete bannerCopy strings. Doc narrates these but never gives the structured
  impact enum the UI consumes.
- Backend resolver hard guard: contemplative tier NEVER resolves to
  phase-176-nous even if the workflow class declares it; higher tiers pick
  highest BACKEND_QUALITY_RANK that the SLO can serve AND the
  phase176FeatureFlag enables (backend-resolver.ts). EntitlementTier enum =
  contemplative, curated-creator, aaa-creator, operator-admin. Doc describes the
  bridge but not the 4-tier enum or the rank-based selector.
- Crisis-frame cascade
  (libs/oshun/trust-safety/src/crisis/crisis-frame-cascade.ts): a single
  lilith.crisis_frame.activated event fans out to 5 surfaces
  (CRISIS_FRAME_SURFACES = psyche, lilith-video, tara, iris, assistant);
  crisis-frame-worker.ts binds the real Redis bus. This cross-surface
  propagation (Iris memory-write suspend + Tara scheduling + video policy) is
  exactly the doc's mid-stream crisis frame but the doc never names the event
  constant or the 5-surface fan-out.
- Personal-artifacts constants: LIVING_SCENE_SHARE_PRIVACY_LEVELS,
  LIVING_SCENE_RETENTION_POLICIES = 30-day|1-year|indefinite,
  LIVING_SCENE_RENDITIONS = full-motion|reduced-motion,
  PUBLIC_VIEWER_TOMBSTONE_COPY = 'This offering has been retired.',
  LIVING_SCENE_DEFAULT_ROBOTS_META = 'noindex, nofollow, noarchive',
  LIVING_SCENE_REVOCATION_SLA_SECONDS = 60 (personal-artifacts.ts:29-46). Docs
  mention these qualitatively but the concrete 60s SLA and exact
  robots/tombstone strings are richer.

_Captured 16 code-verified grounding facts for this area._

### agentic-studio

**Real vs aspirational.** Overwhelmingly REAL, not aspirational — unusual for
this doc set. Every major subsystem the prose enumerates has a corresponding
implemented module with value-tested behavior (e.g. champion-challenger uses a
genuine Abramowitz-Stegun normal-SF z-test, not a toy; the egress guard has real
RFC-1918/loopback/link-local SSRF CIDR checks; the grant resolver has a
documented specificity ordering
per-run>per-pipeline-instance>per-session>per-user>per-tenant). The data/logic
plane is production-quality pure-TS. What is genuinely thinner than the prose
implies: (1) the persistence/runtime is in-memory — AgentRegistry is a `Map`,
the BFF run-lifecycle store is an in-process store, ARCHITECTURE's 'durable jobs
through @oshun/queue' is not wired into agentic-studio (no `@oshun/queue` import
there). (2) 'Replay and time-travel debugging', 'streaming progress', operator
dashboard _UI_ are data/query layers (`dashboard-query.ts`, `replay.ts`,
`streaming-progress.ts`) — there is no rich admin React dashboard page; admin
exposes only API routes + tenant-admin has a single `agents/page.tsx`. (3) Tool
grants/capability modifiers are declared/validated but actual tool _execution_
(the real `web.fetch`, `sophia.ground` etc.) is injected at the app boundary and
fail-closed by default. So: the governance/orchestration brain is real and
tested; the 'autonomous content gets produced end-to-end through real providers'
story is seam-and-fail-loud, not wired to live providers. The reality audits
(v1-completeness/v1-triage/v1-real-infra 2026-06-22/23) do not call out
agentic-studio specifically; the only related item is the e2e walkthrough
`agentic-pipeline-customer-invocation` (classified 'deep', noted creds-bound
tool DAG).

**Inaccuracies corrected**

- `features.md:4890 (Cross-domain pipeline pattern reference)` — claim:
  _'Pipelines live in `libs/oshun/agent-pipelines/` and are registered through
  the Agent Registry release-gate path.'_ → **reality:** The real pipeline SPECS
  (VERITAS_STORY_DRAFTING, METIS_COURSE_FROM_BYOM, TARA_SEASONAL_PROGRAM,
  NYX_EVENT_EXPLAINER_SET, ARETE_WEEKLY_REVIEW_DRAFT,
  NISABA_EDITION_STUDY_GUIDE, VERITAS_WEEKLY_BRIEFING_PACK) are defined in
  `libs/oshun/agentic-studio/src/pipelines/v1-pipelines.ts` (and
  PipelineRegistry in `pipeline-registry.ts`). `libs/oshun/agent-pipelines/src/`
  is only a 4-file re-export shim that imports these from
  `@oshun/agentic-studio` (see its `src/pipelines/index.ts` and
  `src/grants/resolver.ts`). The docs point readers to the wrong package for the
  implementation.
- `ARCHITECTURE.md:1476 (Multi-agent plans bullet)` — claim: _Operator dashboard
  for replay and audit lives at `apps/oshun/admin/src/.../agents/`._ →
  **reality:** No `agents/` directory exists under `apps/oshun/admin/src/app`.
  The admin agentic surface is
  `apps/oshun/admin/src/app/api/admin/agentic-operations/` (API routes:
  kill-switches, snapshot, gold-sets/promote, champion-challengers/rollout) —
  not a `.../agents/` page. The only agent _page_ is
  `apps/oshun/tenant-admin/src/app/agents/page.tsx`. The path glob in the doc
  does not resolve.
- `ARCHITECTURE.md:1473 (Job orchestration bullet)` — claim: _'Job orchestration
  — durable jobs through `@oshun/queue` with priority classes, replay, DLQ, SLA
  monitor.'_ → **reality:** `@oshun/agentic-studio` does not import
  `@oshun/queue` (grep of its src returns nothing). The queue lib is
  `libs/shared/queue`; agentic-studio's runs (`runs/dispatcher.ts`,
  `runs/orchestrator.ts`, `runs/checkpoint.ts`, `runs/replay.ts`) are
  in-process/pure-function logic with no `@oshun/queue` binding, no DLQ, and no
  SLA monitor in this lib. The durability/DLQ/priority-class claim is
  aspirational at the agentic-studio layer.
- `ARCHITECTURE.md:1480 (Budgets bullet)` — claim: _'cost-tracking integrated
  with `libs/metis/cost-tracking` patterns.'_ → **reality:**
  `libs/metis/cost-tracking` exists, but agentic-studio's budget module
  (`src/budgets/budgets.ts`) is self-contained
  (BUDGET_CATEGORIES/BUDGET_SCOPES/checkBudget/consumeBudget) and does not
  import or integrate metis cost-tracking — the phrasing 'integrated with'
  overstates an actual code dependency that is not present.

**Contradictions reconciled**

- (features.md §Cross-Domain Autonomous Pipelines (4726) vs §Cross-domain
  pipeline pattern reference (4893)) The first list names 'Veritas weekly
  briefing pack' while the pattern reference names a separate operator-only
  'veritas.story_drafting' pipeline. The code has BOTH
  (`VERITAS_WEEKLY_BRIEFING_PACK` creator-tier and `VERITAS_STORY_DRAFTING`
  platform-operator-tier), so the doc is not wrong, but the prose never
  reconciles that these are two distinct Veritas pipelines — a reader could
  conflate them. v1-pipelines.ts itself flags the overlap in a comment.
- (features.md tool count vs code) features.md's Tool catalog bullets enumerate
  the tools but present them as the '17-ish' bulleted entries; the real
  `V1_TOOL_IDS` is exactly 21 (incl. generate.image/video/audio as 3 separate,
  memory.read/write as 2, calendar.read/write as 2). Not a contradiction in
  substance — both agree on the tools — but the doc's bullet grouping obscures
  the precise count of 21 catalog entries.

**Staleness refreshed**

- `ARCHITECTURE.md:1494-1518 (AgentRun lifecycle mermaid)` — The state-machine
  diagram uses statuses `pending`, `planning`, `executing` which do NOT exist in
  the real `RUN_STATUSES` enum (`runs/agent-run.ts`): the actual states are
  queued, starting, running, paused, awaiting_approval, awaiting_tool,
  awaiting_branch_selection, cancelled, killed, failed, completed. The diagram
  is a simplified/aspirational model, not the implemented enum (e.g. it omits
  paused, awaiting_tool, awaiting_branch_selection, cancelled, and has no
  `planning`/`executing` states in code).
- `features.md:4798 (agent.terminate tool outcome)` — The doc says
  agent.terminate returns a structured outcome
  `completed | failed | declined | killed`. The implemented terminal status set
  (`TERMINAL_STATUSES`) is completed, failed, cancelled, killed — there is no
  `declined` status (run-controls has `cancel`/`kill`, not `decline`). Minor
  outcome-vocabulary drift between doc and code.

**Enrichment added (real code previously under-described)**

- `libs/oshun/creative-orchestrator` (Phase-3 autonomous creative orchestrator:
  `decomposeBrief`->schema-validated CreativePlan DAG,
  `routePlan`/`CreativeOrchestrator`/`orchestrateBrief` governed dispatch,
  `reviseArtifact` Reflexion critique->revise loop, `createContentEvalCritic`,
  `createYemayaAgentGenerator`, `createMetisNarrator`,
  `BudgetGovernanceGate`/`ALLOW_ALL_GATE`, built on `@oshun/ai/agent-loop`'s
  runStructuredOutput/runReflexion) is fully real with 58 passing tests but is
  NOT mentioned anywhere in features.md or ARCHITECTURE.md. This is the actual
  brief->produced-content engine and deserves a documented page.
- The real runtime governance seam
  (`admitToolCall`/`dispatchGuardedToolCall`/`runGuardedToolPlan` in
  runs/executor.ts + runs/dispatcher.ts) and its mounting in the BFF
  (`POST /v1/agentic/runs/execute`, fail-closed 503 when no tools configured,
  server-authoritative tenant/actor from auth claim, S7 scope-checks, S8
  server-side kill-switch target metadata, S9 run-ownership 409) is the concrete
  enforcement story the docs gesture at abstractly but never name. Worth a page.
- The `agentic-studio` capability-audit / agent-memory / adversarial-tests
  modules (ADVERSARIAL_TEST_KINDS: prompt-injection, tool-call-exfiltration,
  scope-escalation, sandbox-escape, persona-bypass, source-fabrication) are
  implemented and could be surfaced as the concrete security-test catalog.
- The mode profiles carry concrete declared numbers (fast: maxCostUnits 50 / p95
  1500ms / minEval 0.6; balanced 500/10000/0.7; deep 5000/120000/0.8 multiAgent;
  exhaustive 50000/1800000/0.85; rehearsal-dry-run hasExternalSideEffects=false)
  plus `checkModeCompliance` and `applyOverride` (tighten-only,
  cost-raise-rejected) — the docs describe modes qualitatively but omit these
  real thresholds.
- Pipeline scheduling:
  `nextFireFor`/`PipelineSchedule`/`buildPipelineObservabilityReport`/`detectPipelineDeviation`/`effectivePipelineForTenant`/`TenantPipelineCustomization`
  exist (in pipelines/observability.ts + pipeline-registry.ts) — the doc's
  'Tenant-scoped pipeline scheduling' line has real backing symbols worth
  naming.
- `surfaceDeprecations` + per-tool semver dependency resolution
  (`resolveToolDependencies` with a real ^/~/>=/<= matcher) in
  contracts/agent/tools.ts back the doc's 'tool versioning / deprecations
  surfaced at registry-review time' claim concretely.

_Captured 18 code-verified grounding facts for this area._

### admin-tenant

**Real vs aspirational.** Overwhelmingly implemented. Every named Admin/Tenant
capability maps to real code: SSO claim-mapping + JIT + IdP/SP flows
(processSsoLogin), SCIM 2.0 create/replace/patch/delete + OneRoster
class/enrollment resources (applyScimSync, computeRosterDiff), cross-tenant
federation (canFederateAuth), per-tenant auth policy with
MFA/step-up/IP-allowlist/device-posture (evaluateAuthChallenge), custom-role
diff with risk scoring + reviewer-signoff threshold + a genuine role test
harness (diffTemplateAgainstCanonical, runDryRun/DryRunAction/DryRunResult),
hash-chained tamper-evident audit with tenant isolation
(AuditLogRecord.priorDigest, applyAuditFilter), bulk import/export dry-run +
residency violation counting + JSON/CSV/OneRoster/xAPI/Caliper formats, API-key
auth (scopes/expiry/IP/revocation), outbound webhook topic-pattern matching +
retry/dead-letter, multi-channel notification fabric, role-aware help search,
and a status page with component health + incident updates + postmortems. The
realism caveats are at the runtime boundary: SSO/SCIM are deterministic pure
functions (no live SAML/OIDC parser in the lib — the OIDC live-login runtime
fails closed 503 when oidcClientId/oidcJwksUrl absent, per the sso.ts comment),
and the completeness audit notes the tenant-admin SSO config UI
(metadata-XML/OIDC-discovery parse, full transform matrix, auth-policy panel,
sandbox-probe verdicts) is only partially covered end-to-end. Nothing in this
area reads as fabricated.

**Inaccuracies corrected**

- `ARCHITECTURE.md:379` — claim: _Oshun Tenant Console at
  apps/oshun/tenant-admin (standalone Next app; TODOS § 20)_ → **reality:**
  Correct that the app is apps/oshun/tenant-admin, but the doc omits that
  essentially ALL tenant-console domain logic lives in the library
  libs/oshun/tenant-console (9 modules); the app is a thin Next rendering layer
  that imports
  applyScimSync/processSsoLogin/canFederateAuth/computeRosterDiff/evaluateAuthChallenge
  from @oshun/tenant-console. Not wrong, but under-attributed.
- `features.md:5161-5162` — claim: _Multi-channel notification fabric — in-app,
  push, email, SMS, voice, and webhook_ → **reality:** Matches tenant-console
  NOTIFICATION_CHANNELS = ['in-app','push','email','sms','voice','webhook']
  (notifications.ts) — accurate; flagged only to confirm the 'voice' channel is
  a real enum member, not aspirational.

**Staleness refreshed**

- `features.md:5148` — Inbound connectors list says 'LMS connectors (LTI 1.3,
  LTI Advantage, SCORM ...), calendar providers (Google, Apple, Outlook),
  identity providers, payment providers, telemetry sinks, BYOM ingest endpoints,
  and Slack/Teams-style notification sinks'. The real connector-registry
  CONNECTOR_KINDS enum is
  ['lms','calendar','identity','payment','telemetry','byom-ingest','slack','teams']
  (no separate SCORM/LTI-Advantage discrimination at the registry level — those
  are LMS sub-flavors, not distinct kinds). Doc over-enumerates relative to the
  code's coarser taxonomy.

**Enrichment added (real code previously under-described)**

- Roles module ships a real dry-run role test harness (runDryRun,
  DryRunAction{action,scope}, DryRunResult with unexpectedEscalations) plus a
  recertification state machine (ASSIGNMENT_STATES
  ['pending','active','expired','recertified','revoked'], transitionAssignment)
  and a reviewer-signoff threshold (REVIEWER_SIGNOFF_THRESHOLD=6, risk weights
  GRANT=3/SCOPE_WIDEN=4/REVOKE=1/SCOPE_NARROW=1) — the doc mentions the harness
  generically but never surfaces these concrete primitives.
- Audit explorer is hash-chained for tamper-evidence
  (AuditLogRecord.contentDigest + priorDigest forming a per-tenant chain) and
  viewer-scoped via ExplorerViewer {role:'platform-operator'|'tenant-admin',
  tenantId}; the doc says 'tamper-evident storage' abstractly but omits the
  hash-chain mechanism.
- developer-portal exports a real OpenAPI 3.1 generator (openapi-builder.ts with
  zodToOpenApiSchema), an integration certification suite
  (CERTIFICATION_CHECK_KINDS incl.
  'auth-token-rotation','webhook-signature-verification'), a code-example
  generator, and a sandbox-tenant policy — underdescribed in the Integrations
  section which only says 'integration certification flows'.
- admin app has concrete BFF API routes
  (api/admin/{signin,signout,search,notifications,bulk-operations,integrations/api-keys,integrations/snapshot,agentic-operations/kill-switches,agentic-operations/snapshot,editorial/release-streams})
  — the architecture section describes the admin app but never enumerates its
  server route surface.
- bulk-export support matrix is per-resource-kind
  (content/rosters/users→json/csv/oneroster; audit→json/csv/xapi/caliper;
  rights/metis→json/csv) via BULK_EXPORT_FORMAT_SUPPORT — a real constraint
  table the doc flattens into 'format options (JSON, CSV, OneRoster, xAPI,
  Caliper)'.

_Captured 18 code-verified grounding facts for this area._

### governance

**Real vs aspirational.** Largely implemented as deterministic
policy/state-machine logic. Real and verified: the full policy category enums,
SLA budgets keyed by severity (P0 triage 5min/action 15min, P1 30min/2h, P2
8h/48h, P3 weekly) with minReviewerTier gates, appealable vs non-appealable
decision taxonomy + two-reviewer signoff, the crisis-frame cascade that
publishes lilith.crisis_frame.activated and fans out to
psyche/lilith-video/tara/iris/assistant (with crisis-frame-worker.ts binding a
real Redis bus — matching ARCHITECTURE's sequence diagram), retention constants
(raw-chat 30d, billing/audit 7y = 365\*7, summarized-profile durable),
soft-delete default 30d with tombstones, DSAR state machine
(received→identity-verified→scope-determined→in-execution→completed/rejected/restored),
residency routing with cross-region-blocked verdicts + log segregation,
regulatory regime mapping (EU→GDPR, US→CCPA/CPRA/FERPA/COPPA, etc.), and the
billing-aje-bridge wiring settled crypto payments into subscription state. The
honest boundary: these are pure-function cores; the actual enforcement (real
classifiers, live audit-platform persistence, real DSAR fan-out across domains)
is the runtime's job and lives partly elsewhere (Iris owns consent/memory,
@oshun/audit-platform owns immutable storage per the arch). Crisis-frame domain
stays free of @oshun/event-bus (ports only) by design. Nothing reads as
result-faking.

**Inaccuracies corrected**

- `ARCHITECTURE.md:1838 / 1828` — claim: _V1 adds five new chain modules
  (libs/aje/chains/{monero,litecoin,ton,ergo,tron}/)_ → **reality:**
  libs/aje/chains/ contains monero, litecoin, ton, ergo, tron AND cardano,
  solana, abstraction (8 dirs, not 5). The five named all exist with real
  non-test source files (monero 12, ton 8, ergo 7, tron 7, litecoin 5), but the
  'five new' count is stale relative to the actual chain set.
- `ARCHITECTURE.md:1761` — claim: _Consent and memory ownership belong to Iris
  (@oshun/memory-iris). Every consent change emits a ConsentRecord event_ →
  **reality:** Partially true but split: a full consent taxonomy + ConsentRecord
  type ALSO lives in libs/oshun/privacy/src/consent/consent.ts
  (CONSENT_FAMILIES, MEMORY_SCOPES, per-family purpose enums). The arch
  attributes consent solely to Iris and omits the privacy lib's own consent
  core.

**Contradictions reconciled**

- (features.md:5371-5380 (Support/Billing) vs ARCHITECTURE.md:1823-1833
  (Billing)) features.md says fiat 'via Stripe-class providers and Telegram
  Payments is V1.x optional ... via the
  libs/shared/inbound-integrations/src/payment.ts adapter'; ARCHITECTURE.md says
  crypto is via the Aje domain (libs/aje/) plus libs/oshun/payments-bridge/.
  Both paths exist in code (payment.ts and payments-bridge both present), but
  the billing IMPLEMENTATION that the governance area grounds against is
  libs/oshun/billing-support with a billing-aje-bridge.ts — neither doc names
  billing-support, so the reader cannot find the actual
  entitlement/dunning/metered code from either prose.

**Staleness refreshed**

- `ARCHITECTURE.md:1816-1818` — Support section says 'SLA is monitored by
  libs/shared/queue/src/sla-monitor.ts patterns' and SupportCase contract is
  'V1/TODOS.md § 1.2' — but the concrete support-case state machine
  (CASE_ROUTING_QUEUES=['general','billing','technical','safety','privacy','institutional','crisis'],
  CASE_STATES) lives implemented in
  libs/oshun/billing-support/src/support-cases/support-cases.ts, which the arch
  never names.
- `task grounding list` — libs/maat is listed as grounding code for governance,
  but it is the @maat/\* Ghana B2B intelligence product
  (ghana-data-protection-compliance-engine, regulatory-filing-automation, ESG
  reporting) — unrelated to Oshun V1 governance. Any future doc should NOT cite
  libs/maat as the Oshun review/T&S/privacy/billing implementation.

**Enrichment added (real code previously under-described)**

- The crisis-frame cascade is a concrete, named exit-criterion implementation:
  LILITH_CRISIS_FRAME_ACTIVATED_EVENT='lilith.crisis_frame.activated',
  CRISIS_FRAME_SURFACES=['psyche','lilith-video','tara','iris','assistant'], a
  port-based emitter + crisis-frame-worker.ts binding the real Redis bus.
  ARCHITECTURE has the sequence diagram but doesn't cite the actual
  symbols/file.
- Severity SLA budgets are real constants with reviewer-tier gates
  (SLA_BY_SEVERITY: P0 crisis-trained + requiresParallelIncident +
  requiresPostIncidentReview; P1 senior; P2/P3 standard) — features.md describes
  the SLAs in prose but the machine-readable SlaBudget shape
  (triageBudgetSeconds/actionBudgetSeconds/minReviewerTier/weeklyAggregateOnly)
  is undescribed.
- billing-support/billing-aje-bridge.ts collapses six EntitlementClasses
  (free/starter/plus/pro/scholar/institutional) onto three canonical
  OshunEntitlementTier values (free/pro/premium) via TIER_BY_CLASS, and advances
  subscription state from a settled Aje payment — a real single-source-of-truth
  fix the docs omit entirely.
- privacy retention is a concrete table (RETENTION_DAYS: raw-chat 30,
  summarized-profile durable, billing 365*7, audit 365*7, generated-artifact
  per-artifact-policy) and SOFT_DELETE_DEFAULT_SECONDS=30\*86400 with
  validateSoftDeleteWindow bounds — features.md states the same numbers in prose
  but not the enforcing constants.
- compliance regimesFor() maps regions to regimes (EU→GDPR, UK→GDPR+UK-DPA-2018,
  US→CCPA+CPRA+US-State-Privacy+FERPA+COPPA, CA→PIPEDA, BR→LGPD) — a real lookup
  the doc flattens into a regulatory list. FERPA/COPPA appear in code but not in
  the features.md compliance bullet.
- metered billing
  METERED_DIMENSIONS=['agentic-cost-units','voice-seconds','avatar-seconds','storage-bytes-hours','gpu-minutes']
  — the doc lists voice/avatar/storage but not gpu-minutes or the
  agentic-cost-units unit name.

_Captured 17 code-verified grounding facts for this area._

### messaging

**Real vs aspirational.** Implemented to an unusually high degree. Verified
real: the dispatcher enforces
TIERS=['contemplative','curated-creator','aaa-creator','operator-admin'] so no
AAA/operator intent reaches a channel; provider-config-env.ts includes a channel
in the live config ONLY when every credential is present (else
deliverDispatchedMessage reports 'missing-config' — explicit fail-loud, never a
fabricated send); the SMTP transport speaks the real protocol and returns
{ok:false} on any non-2xx; the Web Push transport is verified byte-for-byte
against the RFC 8291 Appendix A known-answer test; Telegram initData
verification uses real HMAC-SHA256 with the 'WebAppData' key derivation; all 9
documented bot commands (/start /menu /today /save /sources /voice /quiet /stop
/help) are implemented in telegram/bot.ts; all 7 mini-app surfaces
(Tara/Sophia/Veritas/Nyx/Arete/Nisaba/Illustration) exist in surface-data.ts;
the boundary layer emits a full ChannelAuditEnvelope (channelId, recipientId,
intentClass, persona, policyHash, provenanceBundleId, residencyTag,
retentionClass, disclosureVerificationResult). The honest aspirational edge: per
the completeness audit, end-to-end OUTBOUND Telegram delivery in the BFF e2e is
noted 'unimplemented' (the policy core and grounding are real; the live send
loop is the gap), and WhatsApp/SMS/payment transports are pure planners whose
actual provider HTTP calls require real credentials. Nothing in this area is a
result-faking stub.

**Inaccuracies corrected**

- `ARCHITECTURE.md:2047-2049` — claim: _Email, push, SMS — adapters in
  libs/shared/inbound-integrations/ outbound side_ → **reality:** The real
  email/push/SMS messaging adapters live in
  libs/oshun/messaging-channels/src/{email,push,sms} + transports.ts (SendGrid,
  SMTP, Twilio, FCM/APNs/Expo, Web Push). libs/shared/inbound-integrations is
  the INBOUND connector + payment.ts side. The arch points the reader to the
  wrong library for outbound messaging adapters.
- `features.md:5941-5943` — claim: _Push adapter covering FCM (Android/web) and
  APNs (iOS)_ → **reality:** Understated: the real push surface also covers Expo
  push (push-expo channel + sendPushViaExpo) and W3C Web Push for PWAs
  (push-webpush channel + a full RFC 8030/8291/8292 web-push-transport.ts).
  PushPlatform enum is ['fcm-android','fcm-web','apns-ios'] in push/index.ts but
  CHANNEL_IDS additionally has 'push-expo' and 'push-webpush'.
- `features.md:5939` — claim: _Email adapter with per-tenant DKIM/SPF/DMARC_ →
  **reality:** The registry channel id is 'email-ses' but the actual transports
  are sendEmailViaSendgrid (SendGrid HTTPS API) and sendEmailViaSmtp (a
  hand-written RFC 5321 SMTP client, also documented as usable for AWS SES SMTP
  / Postmark / Mailpit). There is no dedicated SES API transport; 'email-ses' is
  a naming artifact, and DKIM/SPF/DMARC are deploy-config concerns, not code in
  the lib.

**Staleness refreshed**

- `features.md:5775` — Prose says 'SMS (Twilio)' and 'push (FCM/APNs)' as the
  canonical set; code has broadened to also include Expo push + Web Push
  (push-expo, push-webpush) and an injectable transport abstraction — the doc's
  channel list is narrower than CHANNEL_IDS (12 entries).
- `completeness-audit line 250` — Audit note: 'telegram-bot-assistant-delivery
  ... outbound telegram delivery (unimplemented)' and 'doc stale: voice STT now
  fail-closed, not stub' — the voice-STT path was upgraded from a stub to a real
  fail-closed seam; any doc calling Telegram voice STT a stub is stale.

**Enrichment added (real code previously under-described)**

- The channel registry encodes a rich per-channel policy matrix the docs only
  summarize: CHANNEL_IDS (12),
  CAPABILITY_KINDS=['text','rich-cards','inline-buttons','voice','files','payments','miniapp'],
  COST_CLASSES=['free','low','metered','high'],
  RESIDENCY_PROFILES=['global','eu-only','us-only','apac-only','self-hosted'],
  CONSENT_PROFILES=['platform-tos-implied','verified-opt-in-required','double-opt-in-required'],
  RETENTION_PROFILES=['channel-default','short-30d','standard-365d','long-3y','indefinite'].
- The dispatcher's tier/intent model (TIERS,
  INTENT_KINDS=['transactional-receipt','crisis-hotline','reminder','session-notification','newsletter','engagement-recap'],
  ContentVariant with requiredCapability + disclosureCopy + provenanceFooter) is
  the concrete enforcement of 'tier-aware routing' — undescribed in the prose.
- The ChannelBoundary + ChannelAuditEnvelope shapes
  (ContentClass=['transactional','grounded-answer','ritual-reminder','editorial-briefing','identity-verification','billing','crisis'];
  MemoryIngestionDecision gating durable Iris writes) are the real 'channel
  boundary' implementation the doc describes only narratively.
- provider-config-env.ts is the credential→transport seam with explicit
  fail-loud 'missing-config' (no faked sends) — a key safety property absent
  from the docs.
- Real RFC-grade transports deserve their own callout: SMTP (RFC 5321,
  dot-stuffing, STARTTLS, AUTH), Web Push (RFC 8030/8291/8188/8292, @noble
  curves/ciphers/hashes, VAPID ES256 JWT, verified against RFC 8291 Appendix A),
  HTTP/2 fetch (createHttp2TransportFetch) — none named in the docs.
- V3 cross-domain integration: v3-deep-links.ts
  (V3_SHARE_LINK_CANONICAL_HOST='app.oshun.com', custom scheme 'oshun://v3',
  V3_MESSAGING_SHARE_CHANNELS=['telegram','whatsapp','push','email','sms',...])
  and v3-session-reminders.ts (30-minute pre-session reminder window) wire V3
  programming into messaging — entirely absent from this doc area.
- customer-message-center exports a real inbox substrate:
  CUSTOMER_MESSAGE_CHANNELS=['in-app','email','push','sms','voice'],
  CUSTOMER_MESSAGE_CATEGORIES (10, incl.
  onboarding/milestone/reengagement/incident),
  CUSTOMER_MESSAGE_RECEIPT_STAGES=['queued','sent','delivered','opened','clicked','failed','bounced','suppressed']
  — the doc mentions a 'customer-visible message center' but not this state
  model.

_Captured 18 code-verified grounding facts for this area._

### foundations

**Real vs aspirational.** This area is overwhelmingly IMPLEMENTED, not
aspirational. Contracts, persistence drift/index/migration/tombstone tests, the
OAuth 2.1/PKCE module, the role/scope model, the partial-failure envelope
contract, the durable queue + DLQ + SLA monitor, the topic-registry +
outbound-delivery + webhook-simulator event-bus, the inbound
LMS/OneRoster/Identity/Calendar/Payment/Telemetry/BYOM/Notification/Health
connectors, the data-residency enforcer/home-zone/traffic-shaping, the
idempotency middleware, and the audit-platform hash-chain all exist as real code
with tests. The mermaid BFF request-lifecycle and Veritas-retraction-cascade
diagrams describe a real composition
(idempotency→tenant→residency→Zod→adapter→event-bus→audit) that matches the
building blocks present, though I did not trace an end-to-end BFF route proving
every middleware fires in exactly that order in production wiring. The 'Redis
Streams' label is the only outright wrong technical claim I confirmed. The OAuth
module is contracts/state-machine level (token types, PKCE patterns, scopes) — I
confirmed PKCE validation patterns and refresh/revocation surface but did not
verify a live authorization-server deployment.

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md:1127 (Asynchronous) and :1164 (Veritas cascade diagram participant 'Event Bus (Redis Streams)')`
  — claim: _Event bus runs 'over Redis Streams'_ → **reality:**
  libs/shared/event-bus/src/event-bus.ts header + impl: it uses ioredis Redis
  pub/sub for fan-out, a TTL-bounded key as the replay source, a sorted set
  ('scheduled') for delay/nack, lists+hashes for the dead-letter, and
  per-(eventId,group) 'SET NX' claim keys to emulate consumer groups. There is
  NO use of XADD/XREAD/XREADGROUP/XGROUP — it is explicitly NOT native Redis
  Streams. The doc states 'Redis Streams' twice.
- `V1/ARCHITECTURE.md:967` — claim: _Common contracts live under
  libs/contracts/src/common/ (≈265 files; ...)_ → **reality:**
  libs/contracts/src/common contains 285 files total (161 non-spec
  implementation .ts files plus their .spec.ts/.test.ts). The '≈265' is
  stale/low.

**Staleness refreshed**

- `V1/ARCHITECTURE.md:967` — '≈265 files' for common contracts is stale; actual
  is 285 files (161 implementation modules).
- `V1/ARCHITECTURE.md:1050 (inbound connector table) vs source` — Doc maps LMS
  telemetry to 'telemetry.ts' (xAPI/cmi5/Caliper) — real, but the table omits
  real sibling modules now present: lti-verification.ts, scorm-rte.ts AND
  scorm-2004-rte.ts (two SCORM RTE modules), byom-model.ts (separate from
  byom.ts), and calendar-google-transport.ts. The 9-row table under-counts the
  15 exported connector modules.
- `V1/features.md:6050-6053 / ARCHITECTURE.md security role list` — Role names
  in prose ('support', 'admin leadership') differ from the code's
  CANONICAL_ROLES which has 10 entries: customer, creator, support-agent,
  reviewer, moderator, privacy-operator, model-operator, persona-operator,
  tenant-admin, admin-leadership. Docs describe ~8 and use looser names
  ('support' vs 'support-agent'); 'creator' and 'tenant-admin' as distinct
  canonical roles are not surfaced in the role-model prose.

**Enrichment added (real code previously under-described)**

- The real partial-failure envelope is a first-class Zod CONTRACT at
  libs/contracts/src/common/partial-failure-envelope.ts
  (PartialFailureEnvelopeSchema, PartialFailureError {domain,stage?,message},
  createPartialFailureEnvelopeSchema generic factory,
  buildPartialFailureEnvelope, with cross-field refinements: partial=true
  requires >=1 error, partial=false requires empty errors). ARCHITECTURE.md:1011
  describes the shape informally but does not cite the contract/factory — strong
  enrichment opportunity.
- The platform-foundations library exposes 9 distinct subsystems via index.ts
  (service-discovery, public-api, shared-contracts, role-model, step-up,
  secrets, configs, rollback, abuse-controls) — the docs scatter these but never
  present the @oshun/platform-foundations package as the single home with these
  9 named exports.
- auth-primitives is richer than documented: api-key.ts, jwt.ts,
  oauth-client.ts, oauth-revoke.ts, token-refresh.ts, token-audit, totp.ts
  (TOTP/step-up), platform-roles, tenant-isolation, password.ts — the doc only
  mentions 'JWT and session primitives'.
- audit-platform is a very large real substrate (~70 modules incl.
  hash-chain.ts, schema-versioning, retention, escalation-rules,
  compliance-attestation, watermark-verification, synthetic-media-labeling,
  voice-likeness-consent, provenance-bundle-validation) — the doc reduces it to
  one sentence (:1061).
- The contracts index uses namespace re-exports beyond the three the doc cites
  (NisabaContracts/MetisContracts/VeritasContracts): the real index.ts also
  namespaces V3Contracts, V6Contracts, V9Contracts, and LivingSceneContracts
  (with explicit aliasing to avoid collisions, e.g. LivingSceneScoreSchema).
  Underdescribed.
- gRPC/proto is real: libs/proto has buf.work.yaml, generated/, and ~25 proto
  domain dirs (agent, ai, asset, auth, bridge, generation3d, hathor, isis,
  sophia, splatting, rendering, etc.) — the doc (:1075) only names
  Psyche/Isis/Sophia.

_Captured 15 code-verified grounding facts for this area._

### platform-quality

**Real vs aspirational.** Mostly IMPLEMENTED. The i18n catalog, analytics
taxonomies/manifests, design tokens, UI component library, and design-language
audit modules are all real, sizeable, tested code — not spec-only. What is
genuinely aspirational/operational (not verifiable as code here): the launch
operational drills (rollback/residency/DSAR/red-team), pen-test signoff,
runbooks, and beta/GA go-no-go in features.md 6198-6252 and ARCHITECTURE Launch
Readiness — these are process gates, and several launch-readiness _manifests_
exist in analytics (v1-33-launch-gate-signoff, v1-launch-readiness-manifest,
v1-security-readiness-manifest) but I did not confirm the drills were actually
executed. The design-token 'cream-paper + terracotta' framing is the one clearly
inverted claim. I did not run Playwright/Lighthouse/axe; I verified the budget
files and CI-coverage manifests exist but not that they currently pass. The
default theme in code is oshunThemes.dark, which the design docs do not mention.

**Inaccuracies corrected**

- `V1/ARCHITECTURE.md:2105-2108 (Design System)` — claim: _'Design tokens —
  single source at libs/oshun/design-tokens/. The canonical surface is
  cream-paper + terracotta; the Lilith register (translated contemplative
  variants) is applied at the persona-policy boundary'_ → **reality:**
  libs/oshun/design-tokens/src/tokens.ts: the CANONICAL token color scales are
  ink, fog (neutrals), aqua, amber (brand), success, danger — a cool dark
  blue/teal + gold system; defaultOshunTheme = oshunThemes.dark.
  'cream-paper-and-ink' + terracotta domain hues (tara #5A7A3F, veritas #9A3E1C,
  nisaba #C89657) appear only inside the LILITH REGISTER block (~line
  1103-1125), explicitly the 'manuscript palette' mapped at that boundary. So
  the doc has it inverted: cream-paper+terracotta is the Lilith register, NOT
  the canonical surface.
- `V1/ARCHITECTURE.md:2141 / :2215 (Performance budgets, 'INP ≤ 200ms')` —
  claim: _Lighthouse budget enforces INP ≤ 200ms_ → **reality:**
  apps/oshun/web/lighthouse-budget.json uses metric 'max-potential-fid' budget
  200 (and FCP 1800, LCP 2500, CLS 0.1, TBT 250, speed-index 3000). It does not
  encode INP (Lighthouse budgets.json has no INP timing metric); the doc's 'INP'
  is the conceptual target but the file uses the FID proxy.

**Contradictions reconciled**

- (V1/ARCHITECTURE.md:2164 vs libs/oshun/i18n) ARCHITECTURE says UI localization
  is 'next-intl for web/admin; mobile localizes through Expo's i18n flow' and
  does not mention the @oshun/i18n shared catalog at all. features.md:2679 DOES
  correctly point to OSHUN_LAUNCH_LOCALES in libs/oshun/i18n/src/index.ts
  consumed via apps/oshun/web/src/i18n/config.ts. The ARCHITECTURE
  Content/Localization section omits the real @oshun/i18n CUSTOMER_MESSAGES
  catalog + translate()/resolveFallbackChain layer that sits under next-intl —
  an internal under-description rather than a hard contradiction, but the two
  docs describe localization at different layers.

**Staleness refreshed**

- `V1/ARCHITECTURE.md:2141, :2215` — 'INP ≤ 200ms' vs the actual
  lighthouse-budget.json key 'max-potential-fid: 200' (FID, the older proxy).
  LCP 2.5s and CLS 0.1 match; FID/INP wording is stale.
- `V1/ARCHITECTURE.md:2106 'cream-paper + terracotta'` — Describes the Lilith
  register as the canonical V1 surface; current canonical tokens are the dark
  ink/fog + aqua/amber system with defaultOshunTheme=dark.

**Enrichment added (real code previously under-described)**

- libs/oshun/analytics is far richer than either doc conveys. Real exported,
  named manifests not surfaced in docs: OSHUN_V1_EVALUATION_SCOPES (12 scopes:
  grounded_answers, citation_integrity, assistant_quality, assistant_safety,
  search_quality, recommendation_quality, persona_quality, voice_quality,
  avatar_quality, metis_pedagogy, generation_quality,
  generated_artifact_quality), OSHUN_V1_EVALUATION_PIPELINE_STAGES (7 stages),
  OSHUN_V1_BENCHMARK_DATASETS, OSHUN_V1_PROMOTION_THRESHOLDS,
  OSHUN_V1_REGRESSION_BLOCKING_RULES, plus an experimentation-manifest
  (ExperimentDefinition with arms/successMetrics/guardrails/allocationStrategy).
  The docs describe these conceptually but never name the concrete
  schema/constants.
- The customer event taxonomy is concrete and named:
  OSHUN_V1_CUSTOMER_EVENT_FAMILIES (18 families: lifecycle, auth, onboarding,
  profile, navigation, continuity, engagement, value_action, search,
  recommendation, notification, study, performance, error, privacy, commerce,
  accessibility, preferences), OSHUN_V1_CUSTOMER_EVENT_NAMESPACES (7: oshun,
  tara, veritas, nyx, arete, nisaba, metis), OSHUN_V1_CUSTOMER_EVENT_TAXONOMY
  (full event definitions with legacyNames migration),
  OSHUN_V1_CANONICAL_KPI_EVENT_NAMES + resolveLegacyEventName(). Docs only say
  'customer event taxonomy for activation, retention...'.
- The i18n library exports a fully concrete API the docs don't name:
  OSHUN_LAUNCH_LOCALES (8), OSHUN_LAUNCH_LANGUAGE_PREFERENCES,
  RTL_LOCALES={ar,he}, LOCALE_EXPANSION_BUDGET (per-locale ratios, de-DE 1.4
  widest, ja-JP 0.7), CUSTOMER_MESSAGES catalog of ~29 keys translated in all 8
  locales,
  translate()/resolveFallbackChain()/findFallbackGaps()/formatForLocale(). The
  'externalized strings' claim under-sells a complete working catalog with
  critical-message-prefix detection and fallback telemetry events.
- libs/oshun/design-language ships real audit modules (component-catalog with
  OSHUN_COMPONENT_CATALOG + OSHUN_REQUIRED_COMPONENT_REQUIREMENTS coverage
  check, scorecards, ergonomics, responsive-system, surface-language,
  voice-and-tone, ai-disclosure-copy, failure-copy, visual-qa, completion-audit)
  — none named in the docs.
- libs/oshun/ui ships ~21 concrete components (ActionSheet, Badge, Banner,
  BottomNav, BottomSheet, Box, Button, Card, Chip, CommandPalette,
  DomainSwitcher, EmptyState, ErrorState, IconButton, ListRow, Modal, Stack,
  StatTile, Text, Toast, TopBar) plus motion/ and theme/ subpackages and
  accessibility-snapshots.test.tsx — the 'component library' claim doesn't
  enumerate the real surface.
- analytics also carries V3-era budget manifests
  (v3-ue-desktop/mobile/vr-fps-budget, pixel-streaming-rtt, voice-latency,
  cold-join, music-sync-drift, etc.) mixed into the same package — worth noting
  these are present even if out of V1 design-system scope.

_Captured 15 code-verified grounding facts for this area._
