# Cross-Cutting Concerns, the Pipeline & Localization

Most of V8's feature set is about _producing_ something — a ground truth solved,
a case proven, a suspect brought to life, a pack compiled into the shipping
game. This page is about the connective tissue: the single composition that runs
all of those subsystems in order, and the disciplines that wrap _every_ minted
case no matter which subsystem produced it. Ariadne's promise is not "infinite
content" — anyone can generate infinite text — it is **fairness you can trust,
reproducibly and within budget**. That promise only survives contact with a live
service if five things hold for every case: it reproduces bit-for-bit from a
seed, it is minted under a bounded bill, nothing unsafe or unfair can reach a
player, its display text can localize without ever touching the deduction logic,
and an operator can _see_ how it played. In V8 those are not slideware values —
they are small, real, tested TypeScript packages threaded through one
orchestrator.

The concrete surface is one composition and one spine. The composition is
`runPipeline` (`apps/v8/loom-service/src/pipeline.ts:127`), which ties **Clew →
Minos → Anansesɛm → Loom → Daedalus → Theseus** into a single mint-to-publish
call. The spine is `@yemaya/case-pipeline`
(`libs/yemaya/case-pipeline/src/index.ts`), which exports nine Stage-11
primitives — budget, journal, determinism, provenance, safety, HITL, multiplayer
arbitration, telemetry, and a load harness — plus the localization/accessibility
pass in `@yemaya/case-localization`. The case gates themselves are the shared
platform suite, `@oshun/v8-case-gates` (`libs/v8/case-gates`), composed on
`@oshun/content-release-gates` rather than forked. This is the feature-side view
of those cross-cutting concerns; the architecture companion is
[../architecture/oracle-director-cross-cutting-and-deployment.md](../architecture/oracle-director-cross-cutting-and-deployment.md),
and the hub for the whole set is [../V8_features.md](../V8_features.md).

## What ships, honestly

The cross-cutting spine is **real, and most of it is wired into the run-time
mint**. These suites run green here, against the actual code:
`case-pipeline/src/pipeline.test.ts` (21/21), the Loom service's §12.4
acceptance `apps/v8/loom-service/src/pipeline.test.ts` (5/5),
`case-localization` (8/8), `case-director` (33/33 across five files), the
platform `case-gates.spec.ts` (7/7), and the C2PA `case-bundle.spec.ts` (5/5).
The logic is domain-specific, not CRUD: an FNV-1a-64 reproducibility key over a
Map-aware canonical IR, a clamp-to-headroom budget that degrades instead of
overrunning, a three-tier mint governor, a fail-loud keyword safety scanner over
a curated lexicon, a leader-arbitrated co-op writeback, and a drift detector
over a real solve-rate/quality baseline.

Three honesty notes matter, in the same spirit as the rest of the V8 set.

- **Most of the spine is on the run-time path; two pieces are tested but not yet
  threaded.** `runPipeline` threads five primitives through every mint — the
  per-case **budget** (`reserve`/`spend` at each stage), the **journal** (a
  monotonic event per stage), **telemetry**, **provenance**, and the fail-loud
  **safety** gate. But the three-tier `BudgetGovernor` is exercised in tests
  (`pipeline.test.ts:83`) while `runPipeline` uses the per-case budget today,
  and the `reproduce` determinism check ships as a **CLI**
  (`apps/v8/loom-service/src/reproduce-cli.ts`) rather than inside the mint.
- **Localization, accessibility, HITL, and multiplayer arbitration are real
  libraries with their own green tests, not yet called from the runtime apps.**
  `@yemaya/case-localization` is implemented and tested but **unimported by
  `apps/v8`** — its live translator is the injected boundary, so V8 localization
  is a real-but-deferred motion, not a missing capability and not a fake one.
- **Where something needs money, a model, or a binary, it is a fail-loud seam,
  not a fabrication.** A missing safety scanner _refuses_ rather than passing
  content through unscanned (`safety.ts:48`); a non-source locale with no
  translator _refuses_ to emit untranslated text (`localize.ts:70`); an absent
  media provider in the bundle forge yields a `not-configured` slot, never a
  fabricated asset. Honest "planned/gated" beats fake "shipped."

## The end-to-end pipeline: one CaseSpec, eleven stages, eight gates

A case is born from a `CaseSpec` and dies or ships at `decideRelease`. The whole
arc is one function — `runPipeline(spec, deps)` — and reading it is the fastest
way to understand how the subsystems compose. It runs, in order: **Clew**
(`generateCase` builds ground truth + derives clues), **Minos** (`verifyCase`
proves G1–G3 — uniqueness, deductive completeness, fair-play), **Anansesɛm**
(`realizeNarrative` writes the prose/dialogue surface), **Loom**
(`realizeAssets`, optional — a text-only degraded pack when no asset realizer is
injected), **Daedalus** (`compileCase` lowers the IR to V5 `FV5*` structs —
first a draft so Theseus has game data to play), **Theseus**
(`checkInGameSolvable` = G4; `judgeCase` is diagnostic), **G5 independently
calibrated human-aligned judge evidence**, then the inline **G6 safety** and
**G7 canon-consistency** checks, then **G8 preregistered human-quality launch
evidence**, then `decideRelease`. Only on an all-eight-green decision does
Daedalus **re-compile for publish** with the Python `validate-cold-cases.py`
build gate enforced, after which `recordProvenance` and the telemetry session
are written (`pipeline.ts:127`–`248`).

Two details make this a real composition rather than a call list. First, the
**budget is reserved and spent at the stages that cost** —
`reserve('tokens', 6000, 'clew')` then `spend('tokens', 4000, 'clew')` around
generation, `reserve('asset-jobs', 8, 'loom')` before realization
(`pipeline.ts:139`, `:162`) — so the bill is accounted per stage, not estimated
after the fact. Second, **G6 is fail-loud by composition**: `requireSafetyClear`
_throws_ on flagged or unscanned content, and the pipeline wraps it so any throw
simply leaves `g6 = false` and blocks publish (`pipeline.ts:199`–`205`) — a
refusal, never a silent pass.

```mermaid
flowchart TD
  SPEC["CaseSpec (seed, cell, difficulty)"] --> CLEW
  subgraph forge["runPipeline — apps/v8/loom-service/src/pipeline.ts"]
    direction TB
    CLEW["Clew · generateCase<br/>ground truth + clue derivation"]
    MINOS["Minos · verifyCase<br/>G1 uniqueness · G2 completeness · G3 fair-play"]
    ANAN["Anansesɛm · realizeNarrative<br/>prose · dialogue · banter"]
    LOOM["Loom · realizeAssets (optional)<br/>text-only degraded pack otherwise"]
    DRAFT["Daedalus · compileCase (DRAFT)<br/>FV5* structs · skip python gate"]
    THE["Theseus · G4 in-game solvable · diagnostic judge"]
    G5["G5 calibrated human-aligned judge evidence"]
    G67["G6 safety (fail-loud) · G7 canon"]
    G8["G8 preregistered human-quality launch evidence"]
    DEC{"decideRelease — all 8 green?"}
    PUB["Daedalus · compileCase (PUBLISH)<br/>v2 manifest + validate-cold-cases.py"]
    CLEW --> MINOS --> ANAN --> LOOM --> DRAFT --> THE --> G5 --> G67 --> G8 --> DEC
    DEC -- "no" --> BLK["422 + blockingReasons · nothing cached"]
    DEC -- "yes" --> PUB
  end
  PUB --> PROV["recordProvenance + telemetry session"]
  subgraph spine["@yemaya/case-pipeline — Stage-11 spine (wraps every stage)"]
    BUD["budget reserve/spend"]
    JRN["journal (monotonic seq)"]
    TEL["telemetry + drift"]
    SAFE["safety seam (G6)"]
    PROVX["provenance (C2PA)"]
  end
  forge --- BUD & JRN & TEL & SAFE & PROVX
```

### The Loom relay and the offline acceptance run

At run time the UE5 client never holds provider keys — it reaches the pipeline
through the **Loom relay** (`apps/v8/loom-service/src/server.ts:40`):
`POST /v8/cases/mint` runs `runPipeline` and returns the compiled pack _only_ if
all eight `ReleaseDecision` gates pass (HTTP 200 with the manifest, or 422 with
the blocking reasons; nothing is cached on a block). The decisive proof that
this composition is real and not aspirational is `buildOfflineDeps`
(`deps.ts:44`): the zero- credential path that wires the deterministic Clew
core, a text-only asset pack, the local `KeywordSafetyScanner`, a
`createCaseBudget` of 200k tokens / 50 asset- jobs, and an in-memory
`StageJournal` + `TelemetryAggregator`. The §12.4 acceptance test drives exactly
that — it mints case seed 5 and asserts `result.publish === true` with all of
G1–G8 green, **deterministically, with no provider keys**
(`pipeline.test.ts:28`). The production deps swap in a live LLM proposer, the
real Isis asset realizer, the V7 Sekhmet scanner, and canon-graph retrieval
behind the same interfaces.

## Trustworthy by construction: determinism, cost, governance

### Determinism and replay

The reproducibility contract is that the same `(seed, canon, model-versions)`
reproduces a case **bit-for-bit at the IR level**. This is both a provenance
guarantee and a cost lever — a popular case is minted and gated once, then
served from cache many times. `canonicalize` (`determinism.ts:36`) produces a
structurally-stable, JSON-safe view: `Map`s become key-sorted `[key, value]`
pairs, `Set`s sort, object keys sort, and the wall-clock `VOLATILE_KEYS`
(`createdAt`/`updatedAt`/`analyzedAt`/`atIso`) are dropped — so timestamp noise
is excluded from the IR identity. `reproKeyOf` (`:119`) folds the seed, the
provider-sorted model versions, and the canon hash into an **FNV-1a-64** key
(`fnv1a64`, `:99`). The teeth are in `assertReproducible` (`:188`): it
re-`compareIr`s two runs and **throws with the first divergent IR path** (e.g.
`clues[0][1].description`) if they disagree — a real replay-failure signal, not
a swallowed boolean. That assertion ships as the `reproduce` CLI, which
regenerates a case twice and exits non-zero on divergence
(`reproduce-cli.ts:52`).

### Cost discipline and the three-tier governor

`createCaseBudget` (`budget.ts:170`) implements the contracts' `CaseBudget`
surface over `@yemaya/budget-management`'s `ComputeBudgetManager`, tracking two
resources — `tokens` and `asset-jobs`. Its load-bearing invariant is **no silent
overrun**: `reserve` (`:78`) is a soft hold computed against
`ceiling − committed − heldTotal`, so two stages reserving in parallel cannot
jointly over-commit, and `spend` (`:104`) **clamps the commit to remaining
headroom** — an over-budget spend records only what fits and tags the commit
`(clamped from N)`. Over budget means upstream _degrades_ (fewer bespoke
assets), never a quiet overshoot. Above per-case budgets sits the
`BudgetGovernor` (`:215`), which enforces **per-case ∧ per-player ∧ global**
ceilings at once: `authorize` (`:242`) admits a spend only if it fits all three
and names the first failing tier, and `throttle(playerId)` (`:290`) answers
whether the Oracle may admit one more mint under the player+global envelopes —
the exact signal the mint-ahead queue honours. The governor is tested
(`pipeline.test.ts:83` drives a spend that fits per-case but blows the global
ceiling, and a throttle that refuses minting two jobs with one left); the honest
note is that `runPipeline` uses the per-case budget today, with the three-tier
envelope as the production wrap.

### Governance and safety: two gate framings, one fail-loud seam

V8 has **two distinct gate contracts**. The runtime Loom pipeline uses the
eight-gate `ReleaseDecision`, ordered by the _pipeline stage_ that produces each
verdict (Minos uniqueness → … → Sekhmet safety → canon → preregistered
human-quality launch evidence). The **platform suite** `@oshun/v8-case-gates` is
a different numbering, ordered by _kind of check_, and registers seven real
`GateDefinition`s on the shared `@oshun/content-release-gates` service —
**composed, not forked**. `buildV8CaseGates` (`case-gates/src/index.ts:99`)
builds G1 fair-play, G2 solvability, G3 clue-grounding (which _reuses_ the
shared `@oshun/content-quality-judge` `createGroundingGate` so "every cited clue
exists" is the same grounding machine the rest of the platform uses), G4 voice-
distinctiveness, G5 bounded misdirection, G6 prose, and G7 safety;
`evaluateV8Case` (`:183`) returns `cleared` only when all seven pass. That suite
earns its keep in the C2PA bundle forge (`@oshun/v8-case-bundle`), which proves
uniqueness _before any generation_ (throwing `CaseNotSolvableError`),
Ed25519-signs every produced asset through the shared `@oshun/content-signing`
signer, and runs the assembled case through `evaluateV8Case`.

The safety seam itself is the clearest expression of "fail loud beats fake
success." `requireSafetyClear` (`safety.ts:48`) **throws in two cases** — when
no scanner is configured (refusing unscanned content) _and_ when the scanner
reports flags. The offline `KeywordSafetyScanner` (`:123`) is a genuine
word-boundary scan over a curated abuse / hate-slur / real-person-defamation /
self-harm / doxxing lexicon (`:82`), never always-clear; production routes the
same seam to V7 Sekhmet's multimodal classifiers.

### HITL, provenance, and multiplayer canon

Three more disciplines round out the governance envelope. **HITL** —
`InMemoryHitlQueue` (`hitl.ts:61`) — is a real pending/resolved queue for the
three escalation reasons (`repair-escalation`, `commissioned`,
`flagged-content`), each item carrying the hidden `CaseGroundTruth` and the
Minos verifier-report id so a reviewer sees what the machine saw. **Provenance**
— `recordProvenance` (`provenance.ts`) — binds a published case to its repro key
and captures _every_ asset's claim handle, generator, digest, `hashScope`, and
signed state from the manifest (not a sample), with minted/reused counts. Loom's
current locator digest remains explicitly unsigned until a downstream byte
signer upgrades it; `runPipeline` records that honest boundary on every mint.
**Multiplayer canon** — `arbitrateWriteback` (`multiplayer.ts:38`) — resolves
competing co-op outcomes: the **session leader's** proposal wins, with a
deterministic seq-then-`playerId` tiebreak so the committed canon is
reproducible regardless of network arrival order.

## Localization and accessibility (real, deferred from the run time)

Localization in V8 has one non-negotiable rule: **the deduction logic is locale-
invariant.** `localizeStrings` (`localize.ts:63`) translates only display
strings — each carrying a stable id from the writers' room — and never the
symbolic IR (clue logic, solution, constraints), so a case solves identically in
every locale. The source locale (`en-US`) is the identity; any other locale
**requires a translator and refuses** to emit untranslated text claiming to be
localized (`:70`) — the fail-loud seam where a live MT/LLM provider plugs in,
with a real deterministic `PseudoLocaleTranslator` (`:36`) covering the offline
i18n path. `assertLocaleInvariant` (`:84`) throws if two bundles cover different
string-id sets — i.e. if localization dropped or invented a string, which would
mean it touched the logic.

The accessibility pass derives everything from real case structure, never
invented: `generateCaptions` (`accessibility.ts:27`) emits a speaker-tagged,
sequence-ordered caption per VO line; `assignEvidenceCues` (`:68`) gives each
clue category a distinct **shape + fill pattern** so evidence is distinguishable
without colour; `generateHints` (`:87`) builds **progressive** hints straight
from the solution's deduction path — each level reveals exactly one more step —
so a stuck player is helped without being handed the answer; and
`dyslexiaFriendly` (`:103`) segments at clause boundaries without changing the
words. The honest boundary, stated plainly: `@yemaya/case-localization` is green
(8/8) but **unimported by `apps/v8`** — it is a real library not yet on the
runtime path, and the live translator is the injected provider boundary. This is
the same "deliberately deferred motion" posture V9 takes with its own P3
localization.

## Observability: journal, telemetry, drift, load

An operator's view of V8 is built from three real primitives. The **journal**
(`StageJournal.emit`, `journal.ts:88`) writes each stage transition to both a
durable `JournalStore` and a live `EventBus`, stamping a strictly-increasing
`seq` per `(caseId, seed)` run; `replayRun` (`:122`) returns the run in `seq`
order for audit. The in-memory default satisfies both interfaces; Postgres +
Redis are the production swaps. **Telemetry** (`TelemetryAggregator`,
`telemetry.ts:63`) records how shipped cases actually play — solve-rate, the
Brilliant/Good/Doubtful/Wrong rating distribution, a weighted mean-quality, and
a ten-bucket abandon-point histogram — and `driftAlert` (`:136`) fires when
solve- rate or mean quality regress past a tolerance below a baseline, so a bad
cohort of generated cases is caught before it spreads; `runPipeline` records a
session per mint (`pipeline.ts:248`). The companion **load harness**
`mintThroughput` (`loadtest.ts:67`) measures sustained cases/second at real
concurrency against a **monotonic** clock — it _refuses_ to fall back to
wall-clock `Date.now` (`:42`–`51`) — and throws if a `minCasesPerSecond` SLA is
missed.

## How a case refuses to ship

The whole layer is built to _refuse_ rather than fabricate, each refusal
specific and located:

- **Non-deterministic regeneration** → `assertReproducible` throws with the
  first divergent IR path (`determinism.ts:188`); the `reproduce` CLI exits
  non-zero.
- **Mint budget exhausted** → an over-ceiling `spend` clamps to headroom rather
  than overrunning (`budget.ts:114`); the `BudgetGovernor` denies and names the
  blocking tier (`:256`).
- **Unscanned or flagged content** → `requireSafetyClear` throws, leaving G6 red
  and blocking publish (`safety.ts:48`, `pipeline.ts:199`).
- **Untranslatable locale** → `localizeStrings` refuses untranslated text when
  no translator is configured (`localize.ts:70`); a logic-touching localization
  trips `assertLocaleInvariant`.
- **Competing co-op writebacks** → `arbitrateWriteback` commits exactly the
  leader's outcome with a deterministic tiebreak (`multiplayer.ts:38`).
- **Any gate red** → `decideRelease` blocks publish, the Loom relay returns 422
  with the blocking reasons, and **nothing is cached** (`server.ts:46`).

## Related

- [./overview-and-player-promise.md](./overview-and-player-promise.md) — the
  product and the "fairness you can trust" promise these disciplines enforce.
- [./delivery-direction-and-operations.md](./delivery-direction-and-operations.md)
  — Daedalus, Theseus, and the Oracle: the subsystems whose verdicts and specs
  this pipeline threads, gate by gate.
- [../architecture/oracle-director-cross-cutting-and-deployment.md](../architecture/oracle-director-cross-cutting-and-deployment.md)
  — the architecture companion: the cross-cutting spine, the Oracle, and the
  deployment shape in depth.
- The hub: [../V8_features.md](../V8_features.md).
