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,
and the hub for the whole set is ../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.
runPipelinethreads five primitives through every mint — the per-case budget (reserve/spendat each stage), the journal (a monotonic event per stage), telemetry, provenance, and the fail-loud safety gate. But the three-tierBudgetGovernoris exercised in tests (pipeline.test.ts:83) whilerunPipelineuses the per-case budget today, and thereproducedeterminism 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-localizationis implemented and tested but unimported byapps/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 anot-configuredslot, 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.
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: Maps become key-sorted [key, value]
pairs, Sets 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-compareIrs 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
GateDefinitions 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 →
assertReproduciblethrows with the first divergent IR path (determinism.ts:188); thereproduceCLI exits non-zero. - Mint budget exhausted → an over-ceiling
spendclamps to headroom rather than overrunning (budget.ts:114); theBudgetGovernordenies and names the blocking tier (:256). - Unscanned or flagged content →
requireSafetyClearthrows, leaving G6 red and blocking publish (safety.ts:48,pipeline.ts:199). - Untranslatable locale →
localizeStringsrefuses untranslated text when no translator is configured (localize.ts:70); a logic-touching localization tripsassertLocaleInvariant. - Competing co-op writebacks →
arbitrateWritebackcommits exactly the leader's outcome with a deterministic tiebreak (multiplayer.ts:38). - Any gate red →
decideReleaseblocks publish, the Loom relay returns 422 with the blocking reasons, and nothing is cached (server.ts:46).
Related#
- ./overview-and-player-promise.md — the product and the "fairness you can trust" promise these disciplines enforce.
- ./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 — the architecture companion: the cross-cutting spine, the Oracle, and the deployment shape in depth.
- The hub: ../V8_features.md.