# V8 Architecture — Ariadne: The Self-Authoring Detective Universe

Status: technical design for V8. Date: 2026-06-04. Pairs with `V8_features.md`
(product), `V8_GAP_ANALYSIS.md` (what's missing), `V8_SOTA_RESEARCH.md`
(external grounding), `V8_TODOS.md` (execution backlog). Cross-ref convention:
`features§"<anchor>"` → `V8_features.md`; `sota§N` → `V8_SOTA_RESEARCH.md`;
`gap§N` → `V8_GAP_ANALYSIS.md`; `v5§…` → V5 docs/source.

---

> **This architecture reference has been decomposed into focused pages under
> [`architecture/`](./architecture/README.md).** This file remains the canonical
> hub (every section heading is preserved, so existing `arch§"…"` anchors keep
> resolving); the in-depth, code-grounded companion pages live under
> [`architecture/`](./architecture/README.md). Start at the
> [architecture page index](./architecture/README.md). The product feature map
> is in [`V8_features.md`](./V8_features.md) /
> [`features/`](./features/README.md).

## 1. Architectural thesis

> **The LLM proposes; a constraint solver disposes.** A fair, solvable mystery
> has a _symbolic skeleton_ (ground truth + clue logic + uniqueness proof) that
> must be verifiable, and an _experienced surface_ (prose, dialogue, art, voice)
> that LLM agents realize from that skeleton. V8 keeps these two layers strictly
> separated. The skeleton is authoritative and machine-checked; the surface is
> generated, graded, and regenerated on failure.

This is the single decision that makes everything else fall out. It directly
implements the solve-first, constraint-verified approach from `sota§1` and
avoids the freestyle-LLM failure mode (rambling, contradictions, unsolvable
"gotchas").

V8 runs as a backend service ("the Loom service", a new app under `apps/v8/`)
that the V5/V6 UE5 client reaches **only through a relay** (never direct
provider calls — `sota§4`, UnrealGenAISupport's explicit production warning).
Output lands in V5's _existing_ authored case format, so the shipping game is
unchanged.

---

## 2. Pipeline overview (the eleven stages)

```
 ┌────────────────────────────── Ariadne / the Loom service (apps/v8) ─────────────────────────────┐
 │                                                                                                   │
 │  0 SEED ───► 1 GROUND TRUTH ───► 2 CLUE DERIVATION ───► 3 VERIFY ──(fail→repair)──┐               │
 │  Oracle/      Clew (solve-first)   Clew (backward)        Minos (CSP/ASP+fairplay) │               │
 │  Showrunner   + Palimpsest canon   derive clues+herrings  unique-solution proof    │               │
 │                                                                          (pass)    ▼               │
 │  4 COMPILE-IR ───► 5 NARRATIVE REALIZE ───► 6 ASSET REALIZE ───► 7 EVAL ──(fail→repair/HITL)──┐    │
 │  MysterySession IR  Anansesɛm writers'room   Loom→Isis jobs       Theseus solve + judge       │    │
 │  (validator schema) (CreativeAgents)         + Ori suspects       8-dim + safety(Sekhmet)     │    │
 │                                                                                     (pass)     ▼    │
 │  8 COMPILE-GAME ───► 9 PUBLISH/DELIVER ───────────────────────────────────────► 10 DIRECT       │    │
 │  Daedalus: FV5* +     Daedalus relay: stream pack+assets to UE5;                  Oracle: place   │    │
 │  cold_cases_manifest  ACE/Inworld live interrogation at runtime                   in open world  │    │
 │                                                                                                   │
 │  11 CROSS-CUTTING: budget · HITL · provenance(C2PA) · determinism/replay · canon write-back ·     │
 │     multiplayer sync · localization · accessibility · telemetry/evals                             │
 └───────────────────────────────────────────────────────────────────────────────────────────────────┘
```

Stages 0–8 are offline (case minted ahead of need or on commission); stage 9–10
include the runtime path (live interrogation, on-demand minting). The pipeline
is a yemaya `StateGraph`/`WorkflowBuilder` graph (`gap§1C`) with conditional
repair edges.

---

## 3. The canonical data contracts

V8 introduces **three** intermediate representations and compiles to **one**
existing target. Keeping these explicit is what lets independent agents/teams
work in parallel.

### 3.1 `CaseSpec` (input to the pipeline) — new, `libs/yemaya/case-engine`

```ts
interface CaseSpec {
  caseId: string; // deterministic from seed
  seed: number; // reproducibility (sota: determinism)
  cell: EV5Cell; // 'Period'(Vice Squad) | 'Urban' | … (mirror V5 enum)
  era: string; // '1947-LA' etc — selects canon slice
  difficulty: 'intro' | 'standard' | 'hard' | 'fiendish';
  targetSuspects: number; // 3..7
  targetClues: number; // derived band per difficulty
  themeTags: string[]; // 'arson','warehouse-district',...
  castConstraints?: {
    // canon reuse
    requiredCharacterIds?: string[]; // recurring NPCs / prior-case figures
    requiredLocationIds?: string[];
    priorOutcomeHooks?: string[]; // e.g. wrongful-conviction from case #7
  };
  lengthMinutesVO: number; // maps to FV5ColdCasePackDefinition.VoiceOverMinutes
  commissionedBy?: string; // player/creator id (Commission Studio)
}
```

### 3.2 `CaseGroundTruth` (Stage 1–3 internal) — new, `libs/yemaya/case-engine`

The symbolic skeleton. **Never shown to the player.** This is the constraint
network from `sota§1` (EXAG backward-generation + CSP).

```ts
interface CaseGroundTruth {
  victim: CharacterRef;
  culprit: CharacterRef;                 // the unique answer
  means: { weaponId: string; access: AccessFact[] };
  motive: { kind: 'financial'|'revenge'|'jealousy'|'cover-up'|…; evidenceVars: string[] };
  opportunity: { windowStart: TimeFix; windowEnd: TimeFix; place: LocationId };
  timeline: TimelineEvent[];             // every character's movements; conflict-detected
  facts: GroundTruthFact[];              // atomic propositions (who/where/when/what)
  alibis: Alibi[];                       // innocents verifiable; culprit's has a flaw
  constraints: ConstraintClause[];       // CSP/ASP clauses linking facts→suspects
}
```

### 3.3 `MysterySession` IR (Stage 2 output, Stage 3 gate input) — **EXISTING**

The pipeline's pivot point is the _existing_ validator schema, so the existing
Knox/Van-Dine checker grades V8 output unchanged
(`libs/yemaya/agents/src/quality-assurance/mystery-fairness-validator.ts:508`):

```ts
interface MysterySession {
  // existing — DO NOT redefine; import it
  clues: Map<ClueId, Clue>; // Clue{ type, visibility, importance,
  //   introducedAt, pointsTo[], eliminates[],
  //   isRedHerring, redHerringFairness }
  solutions: Map<SolutionId, Solution>; // Solution{ culprit, method, motive,
  //   requiredClues[], deductionPath[] }
  characters: Map<string, MysteryCharacter>;
  timeline: StoryTimeline;
  config: MysteryFairnessConfig;
}
```

Clew's job is to _produce_ a `MysterySession`; today only validators consume one
(`gap§1A`). The `Solution.deductionPath` IS Ariadne's thread (the _Clew_).

### 3.4 Compile target (Stage 8) — **EXISTING** V5 structs + manifest

Daedalus emits exactly what V5's human Case Author tool emits, so cases drop
into the shipping game (`gap§1B`):

- `FV5MindPalaceEvidenceNode` (`V5MindPalaceTypes.h:33`) ← each `Clue`
- `FV5MindPalaceDeductionEdge` (`:72`) ← each `deductionPath` step (sets
  `Kind=Authored`-equivalent `Generated`, `Confidence`, `bCrossEra`)
- `FV5MindPalaceAccusationOutcome` (`:117`) ← culprit + each plausible-wrong
  accusation (`Rating`, `OutcomeBranch`)
- `FV5ColdCasePackDefinition` (`V5DetectiveColdCasesTypes.h:17`) ← the pack
  header
- `cold_cases_manifest.json` (`schemaVersion:1`,
  `packs[].mindPalace.{evidenceNodeIds[],deductionPairIds[]}`) validated by
  `V5/tools/cold-cases/validate-cold-cases.py` — V8 adds a `generatedBy`,
  `seed`, `provenanceC2PA`, and `assetManifestId` field (schemaVersion bump to
  2, backward-compatible).

---

## 4. Subsystem designs

### 4.1 Clew — Generative Case Engine (`libs/yemaya/case-engine`)

**Stage 1 (ground truth, solve-first).** A `Truth-Weaver` `CreativeAgent` +
symbolic builder. Procedure (EXAG, `sota§1`):

1. Pick victim/culprit/means/motive/opportunity from the canon slice
   (Palimpsest) under `CaseSpec` constraints. LLM proposes a _dramatically
   interesting_ configuration; the builder commits it as `GroundTruthFact`s.
2. Generate every character's `timeline`; run **conflict detection** (no person
   in two places at once; culprit present at scene in the window).
3. Emit `constraints: ConstraintClause[]` — the CSP/ASP encoding where the
   culprit variable is the unknown.

**Stage 2 (clue derivation, backward).** A `Clue-Smith` agent + derivation pass:

1. For each `GroundTruthFact` that distinguishes the culprit, derive one or more
   `Clue`s (physical/forensic/testimony/timeline-inconsistency/relationship),
   each with `pointsTo[]`/`eliminates[]` set to solution variables — the _clue
   inventory tied to solution variables_ (`sota§1`).
2. Generate **red herrings**: each must be _fairly refutable_ — there must exist
   an available clue that eliminates it (`redHerringFairness`). Uniqueness
   enforcement = generate contradictory evidence that rules out every
   non-culprit.
3. Set `visibility`/`introducedAt` to stage revelation (fair gradual
   disclosure).
4. Assemble the `MysterySession` IR (§3.3).

Implements `CreativeAgent` base (`base-creative.ts:140`), uses
`llmProvider.complete()`; structured output validated against the IR schema.

### 4.2 Minos — Solvability & Fair-Play Verifier (`libs/yemaya/case-verifier`)

The gate. Three checks, all must pass:

1. **Formal uniqueness (CSP/ASP).** Compile `MysterySession` +
   `CaseGroundTruth.constraints` into a constraint program (use `clingo`/ASP or
   a TS CSP lib via a sidecar) and prove: with only player-available clues
   (`visibility ≠ withheld`), the culprit is the **only** satisfying model. If a
   second suspect satisfies → fail (under-constrained). If zero satisfy → fail
   (over-constrained/unsolvable). (`sota§1`, AAAI-2007 unique-solution
   guarantee.)
2. **Deductive completeness.** Every step in `Solution.deductionPath` is
   supported by clues introduced before it (no forward references; no external
   knowledge).
3. **Fair-play.** Run the existing `analyzeFairness(sessionId)` (Knox/Van-Dine,
   `mystery-fairness-validator.ts:1825`) and
   `investigation-mechanic-balance-analyzer`. Require
   `rating ∈ {exemplary, fair}` and zero `broken`/`unfair` violations.

**Repair loop:** on failure, return the specific violation set to Clew, which
regenerates _only_ the offending clues/herrings (critique-revise, `sota§2`).
Bounded retries (default 3) then escalate to HITL (yemaya `hitl`).

### 4.3 Palimpsest — Canon & Continuity Graph (`libs/yemaya/canon-graph`)

- A knowledge graph (people, places, factions, timelines, prior-case outcomes,
  open threads) persisted in Postgres + pgvector (already in docker infra) with
  a graph overlay (Neo4j optional profile already exists).
- **SCORE-style** dynamic state tracking + hierarchical prior-case summaries +
  hybrid (TF-IDF + embedding) retrieval (`sota§3`).
- Reuses/absorbs the existing `libs/yemaya/canon-enforcement` lib.
- Every stage that generates reads a retrieved canon context; Stage 11 writes
  the case outcome back (the world remembers — `features§"3"`).

### 4.4 Anansesɛm — Writers' Room (`libs/yemaya/case-writers-room`)

The narrative realization DAG, built on yemaya `WorkflowBuilder`/`StateGraph`:
`Showrunner → {StoryDirector, CharacterWriter, DialogueWriter, Cinematographer, SoundDesigner} → Integrator`.
Realizes the verified skeleton into: scene descriptions, interrogation dialogue
trees (with V5's 12 facial-tell beats), partner banter, briefings, era voice.
All grounded by the Palimpsest canon graph (`@yemaya/canon-graph` — hybrid
TF-IDF + feature-hashing-embedding retrieval over the canon graph's nodes, with
1-hop sub-graph continuity-constraint grounding; the "graph-RAG" of `sota§3`) so
it cannot contradict canon. Reuses the existing `CreativeAgent` specialists
(`gap§1C`); promotes the integration adapters from type-stubs to live calls.

### 4.5 Loom — Asset Realization Fabric (`libs/yemaya/case-assets`)

Per-case asset plan → Isis jobs via `IsisClient.submitBatch()` /
`submitAndWait()` (`libs/isis/client`): | Asset | Provider (existing) | Bind to
| |---|---|---| | Crime-scene env + 3D props | Hunyuan3D/Meshy (3d) |
`FSoftObjectPath` in evidence nodes / level | | Suspect portraits, MetaHuman
params | Stability/Flux (image) | character cards | | Document/photo evidence |
Stability (image) | `FV5MindPalaceEvidenceNode.Image` | | Case music + stings |
Suno (music) | pack audio | | **Full VO for every line** | ElevenLabs (tts) |
`VoiceLineCount`/`VoiceOverMinutes` | | Flashback/CCTV clips (opt) | LTX (video)
| cutscene refs | **Retrieve-then-generate** (`sota§2`, RPGAgent): reuse
cached/library assets via semantic tags before minting new ones (cost control).
Results → asset manifest (URLs/ids from `JobOutput.files[].url`).

### 4.6 Ori-Detective — Living Suspects (`libs/yemaya/case-suspects` + V6 bridge)

Each suspect gets a V6 **Ori** (memory stream / reflection / planning, `sota§2`
Generative Agents) seeded with the case ground truth (what they know, hide, lie
about). At runtime, Hathor `DialogueGenerator.generateResponse()` + NVIDIA
ACE/Inworld drive live, lip-synced interrogation (`sota§4`). The Ori enforces
alibi consistency and _fair_ lying (every lie catchable by a clue the game
gives). Innocents and the culprit share the same machinery — only their
ground-truth facts differ.

### 4.7 Daedalus — Case Compiler & Runtime Bridge (`apps/v8/daedalus` + UE plugin)

- **Compiler (Stage 8):** `MysterySession` + asset manifest → `FV5*` structs →
  `cold_cases_manifest.json` pack; runs `validate-cold-cases.py` as a build
  gate.
- **Runtime relay (Stage 9):** new BFF routes (`/v8/cases/*`) the UE5 client
  calls to request/stream cases on demand. The client never holds provider keys
  (`sota§4`). A thin UE5 plugin (`V8/ue/Plugins/V8_Ariadne_CaseClient`)
  following the UnrealGenAISupport async-delegate pattern fetches packs + asset
  bundles and registers them with the existing cold-cases plugin.
- **Live interrogation transport:** ACE/Inworld session brokering, audio +
  viseme stream to MetaHuman (Audio2Face/NeuroSync).

### 4.8 Theseus — Automated Playtester & Eval (`libs/yemaya/case-eval`)

- **Solver agent:** an autonomous LLM detective (`sota§1`, Digital Detectives)
  that plays the _compiled_ case against V5's data model — collects clues,
  attempts deductions on the actual `FV5MindPalaceDeductionEdge` set, makes an
  accusation. Must reach the intended culprit via a `Brilliant`-eligible path.
  This is the end-to-end solvability proof in _game data_, not just the IR.
- **Judge panel:** LLM-as-judge 8-dimension rubric (coherence, surprise,
  fairness-feel, pacing, character, prose, voice-fit, difficulty-accuracy),
  PCA-aggregated (`sota§5`). Threshold-gated.
- **Difficulty calibration:** vary solver "skill" to estimate solve-rate; map to
  `CaseSpec.difficulty`; feed back to Oracle's player model.

### 4.9 Oracle — Open-World Case Director (`libs/yemaya/case-director`)

Drama/experience manager (`sota§1` drama mgr): maintains a player model (skill,
pacing, preferences, open canon threads), decides which minted cases surface on
the Bureau Case Board, which seed as ambient open-world mysteries, and when.
Owns the mint-ahead queue (keep N cases warm per player/cell) within budget.

---

## 5. Cross-cutting concerns (Stage 11)

- **Budget/cost:** every stage reports tokens/job-cost to yemaya
  `budget-management`; Oracle throttles mint rate; Loom prefers
  retrieve-over-mint. Hard ceiling per case; over-budget → degrade (fewer
  bespoke assets) not fail.
- **HITL:** yemaya `hitl` review queue for: repair-loop escalations,
  commissioned cases, flagged content. Reviewers see the ground truth + Minos
  report.
- **Provenance:** every generated asset C2PA-signed (V3 `C2PA_EVERY_EXPORT.md`);
  manifest records `seed`, model versions, provider job ids.
- **Safety:** V7 **Sekhmet** scans all generated text/art/audio before publish
  (CSAM/abuse/defamation/IP); Oracle won't surface unscanned cases.
- **Determinism/replay:** `(seed, model-versions, canon-snapshot-hash)` fully
  determines a case; the pipeline journals each stage for audit and
  reproduction.
- **Multiplayer canon:** co-op cases share one canon snapshot; outcome
  write-back is leader-arbitrated through V5 online services.
- **Localization/accessibility:** VO + text generated per locale (extend V6/V7
  loc); accessibility pass (captions, colorblind-safe evidence cues, difficulty
  assists) per V6 accessibility.
- **Telemetry/evals:** case solve-rates, accusation-rating distributions,
  abandon-points stream to Maat-style dashboards; adversarial case-quality eval
  gates run in CI (extend V7 `ADVERSARIAL_EVAL_GATES.md`).

---

## 6. Deployment shape

- New app `apps/v8/loom-service` (the orchestrator BFF; TS/Nest, reuses yemaya
  agents) + `apps/v8/daedalus-compiler` (case→V5 build) + a `clingo`/ASP sidecar
  for Minos.
- New libs under `libs/yemaya/`: `case-engine` (Clew), `case-verifier` (Minos),
  `canon-graph` (Palimpsest), `case-writers-room` (Anansesɛm), `case-assets`
  (Loom), `case-suspects` (Ori-Detective), `case-eval` (Theseus),
  `case-director` (Oracle), `case-contracts` (shared types + the V5 compile
  target schema).
- New UE plugin `V8/ue/Plugins/V8_Ariadne_CaseClient` (runtime fetch +
  ACE/Inworld interrogation), depending only on
  V5MindPalace/V5DetectiveColdCases modules.
- Infra: Postgres+pgvector (have), Redis event bus (have), object store for
  generated assets (MinIO have / S3 prod), optional Neo4j (have, profile).
- Models: Claude/GPT for agents (have via isis/lilith providers); ACE/Inworld
  for runtime NPCs (new creds: `OSHUN_INWORLD_*` / `OSHUN_NVIDIA_ACE_*`).

All of section 6 is enumerated as tasks in `V8_TODOS.md`.
