Metis · Architecture

The Seven Release Gates & Aletheia

A focused page within the Metis Architecture documentation. The full map and every sibling page live in the Architecture hub.

9sections15 minread1diagram2tables

On this page

V9 (Metis — "A Curious Ape's Guide to Reality") generates lessons, and the one thing a learning product cannot afford to generate is a confident falsehood. The seven release gates are the governance-plane answer: a generated lesson is publishable only when seven independent eval gates all pass, and a single failing gate stops the lesson cold — it is not delivered, not cached, and not shown. The gate verdicts are a real, strict contract (V9GatesSchema, libs/contracts/src/v9/lesson.ts:149), the pass rule is a single function (isV9LessonPublishable, lesson.ts:246 — "true only when all seven gates passed"), and the enforcement is wired into Stage 7 of the Prometheus pipeline, where forgeLesson returns early with blocked: true the moment any gate fails (libs/v9/prometheus/src/pipeline.ts:232). Aletheia is the subsystem that owns three of those seven gates — grounding (G1), accuracy (G2), and safety (G6) — and it is deliberately built as a thin policy layer over rails that already exist, not a new grounding engine.

The reason it works this way is a platform finding the architecture doc names directly (V9_ARCHITECTURE.md §5.1, finding F6): "grounding exists but is not a mandatory pass on generated content." Oshun already has retrieval, citation, a knowledge graph, and faithfulness evaluation in Sophia, and it already computes real physics in the Nyx/Kalika kernels. What was missing was not a grounding system but the act of making those rails a mandatory pass. Aletheia is exactly that act and nothing more: textual grounding still belongs to Sophia, numeric accuracy still belongs to Nyx/Kalika, and Aletheia owns only the "must pass or block" semantics plus the regenerate-with-direction routing on failure. This mirrors V8's Minos gate, which enforced the fairness validators rather than rebuilding them. This page is the deep companion to the section hub at ../V9_ARCHITECTURE.md; the architecture narrative and the gate table live in its §5.

What ships, honestly#

The gate logic is real, deterministic, CPU-only, and tested — it is not a mock. Aletheia's three gates each run real code: G1 filters claims by Sophia pin credibility and blocks the ungrounded (grounding-gate.ts:43); G2 recomputes every STEM value from the real @kalika/cosmology Friedmann solver and @nyx/constants, then matches it against the asserted number (accuracy-gate.ts:53, kernel-evaluators.ts:33); G6 requires an epistemic-status label on every claim and fails loud for high-stakes disciplines (safety-gate.ts:69). The Aletheia spec asserts domain correctness, not shape: the age of the universe must compute to ≈13.8 Gyr (aletheia.spec.ts:31), the speed of light must equal 299792458 exactly (:38), and a "6000-year-old universe" claim must be blocked (:93). The other four gates are equally real: G4 is the Hephaestus computed-explorable DoD (explorable-runtime.ts:24), G3/G5/G7 are evaluated in Prometheus (gates.ts), and the whole thing composes through a full end-to-end forgeLesson pipeline test that delivers, blocks, caches, and is deterministic across seeds (pipeline.spec.ts:108176).

What is a seam, not a fabrication: several of the richest checks are typed injection points that fail loud when unwired rather than faking a result. The Sophia entailment check (CitationVerifier), the Sophia contradiction pass (ContradictionChecker), the Metis curriculum-safety policy (CurriculumSafetyEvaluator), and the Sekhmet age gate (SekhmetAgeGate) are all interfaces (grounding-gate.ts:27, accuracy-gate.ts:29, safety-gate.ts:26, :41). When a high-stakes discipline has no policy wired, the safety gate blocks rather than passing ungated (safety-gate.ts:115) — fail-loud, not fail-open. A real DefaultCitationVerifier exists in libs/sophia/theory but is not wired into Aletheia by default; production wiring of these provider/model boundaries is deferred. What is spec-only / planned: the G5 "LLM-as-judge panel" and its correlation with the "Yemaya 76-validator suite" — only a deterministic structural quality default ships (gates.ts:77); and the G7 cryptographic C2PA signing of every asset — evaluateProvenance checks that the provenance hashes and ledger id are present and well-formed (gates.ts:105), but c2paSigned defaults to false on the explorable provenance (explorable.ts:95), so actual signing is the inherited discipline the bundle is shaped for, not a signature these libs produce.

Two seven-gate framings — and which is canonical#

There is a real naming divergence worth internalizing before reading any gate code: there are two G1–G7 mnemonics in V9, both real, both running on the same shared platform release gate. Confusing them will make the code look contradictory when it is not.

The canonical numbering — the one this page, the architecture §5 table, the contract V9GatesSchema, and the Prometheus/Aletheia/Hephaestus composition all use — assigns the letters by kind of check:

Gate Meaning (canonical) Owner / evaluator Fail action
G1 Grounding Aletheia → Sophia pins (grounding-gate.ts) reground
G2 Accuracy Aletheia → Nyx/Kalika recompute (accuracy-gate.ts) regenerate-with-…-ground-truth
G3 Pedagogy Prometheus evaluatePedagogy (gates.ts:36) re-scope / re-plan
G4 Completeness Hephaestus DoD (explorable-runtime.ts:24) fix or remove explorable
G5 Quality Prometheus evaluateQuality (gates.ts:88) regenerate-with-direction
G6 Safety Aletheia → Metis/Sekhmet (safety-gate.ts) block-or-escalate
G7 Provenance Prometheus evaluateProvenance (gates.ts:105) block until signed

The second framing belongs to the @oshun/v9-lesson-gates suite, which uses a different order entirely (libs/v9/lesson-gates/src/index.ts): G1 truth, G2 grounding, G3 teachability, G4 safety, G5 explorable, G6 adaptive, G7 retrieval — verified by its own spec, which asserts the exact gate-id list ['g1:truth', 'g2:grounding', 'g3:teachability', 'g4:safety', 'g5:explorable', 'g6:adaptive', 'g7:retrieval'] (lesson-gates.spec.ts:30). Both are real, both register seven required gates on the shared @oshun/content-release-gates ReleaseGateService, and both express the same discipline. They differ in altitude: the canonical composition (composeGates) assembles in-process contract verdicts from the real evaluators, while @oshun/v9-lesson-gates is the suite registered on the platform gate service, with its checks expressed as gateFromEvalScore / gateFromManifestCheck / createGroundingGate over a flat lesson record. Note one consequence of that altitude difference: the lesson-gates suite's G1 reads a pre-stamped truth: 'true' | 'false' | 'unverified' field rather than recomputing it (index.ts:110), and its G2 grounding treats "a non-empty sourcePin string is present" as supported (index.ts:89). The live Sophia/Nyx/Kalika checks live in the Aletheia path; the lesson-gates suite is the platform-gate attestation that those verdicts were produced and that the lesson cleared all seven. The "no eighth loop" rule (V9 must not fork its own checker) is itself confirmed by confirmSevenGateSuite (libs/v9/governance/src/gate-suite.ts:27), which asserts gateCount === 7, usesPlatformReleaseGate: true, and bespokeChecker: false.

The gate verdict contract#

Every gate, in either framing, ultimately produces the same tiny contract shape — V9GateVerdict = { pass: boolean; evidence: string[] } (lesson.ts:141) — and the seven together are V9Gates (lesson.ts:149), a strict object keyed by the V9GateId enum 'G1' … 'G7' (lesson.ts:138). Strictness matters: a V9LessonArtifact cannot be constructed with a missing or extra gate. Publishability is a pure function over those seven verdicts — isV9LessonPublishable returns true only when [G1…G7].every(v => v.pass) (lesson.ts:246), and the pipeline re-checks it defensively after compilation, throwing if a "passing" lesson is somehow not publishable (pipeline.ts:257).

Internally, each Aletheia gate emits a richer AletheiaGateVerdict (libs/v9/aletheia/src/verdict.ts:18) carrying the gate id, pass, an evidence array, a blockers array, and an action — the AletheiaFailAction (verdict.ts:11), one of 'none' | 'reground' | 'regenerate-with-corrected-ground-truth' | 're-scope' | 'block-or-escalate'. The evidence/blockers split is deliberate: on pass, evidence is the positive proof (which pins grounded which claim, what each kernel computed); on fail, the verdict appends the blockers so the same array doubles as a failure explanation. The contract-facing V9GateVerdict keeps only { pass, evidence }runAletheia copies the blockers into evidence on failure so the artifact's gate block records why it failed without leaking the internal action enum (aletheia.ts:64).

Aletheia — the three gates it owns#

runAletheia (libs/v9/aletheia/src/aletheia.ts:47) runs G1, G2, and G6 concurrently with Promise.all, then aggregates: pass = G1.pass && G2.pass && G6.pass (aletheia.ts:54), and actions is the de-duplicated set of fail actions across the failed gates (aletheia.ts:55) — so a lesson that fails both grounding and accuracy surfaces ['reground', 'regenerate-with-corrected-ground-truth'] for the regenerate-with-direction router, with no duplicate noise.

G1 — Grounding (every claim binds to a credible Sophia pin)#

evaluateGrounding (grounding-gate.ts:43) walks each AletheiaClaim and keeps only the pins whose credibility clears minCredibility (default 0.5, grounding-gate.ts:47). A claim with zero credible pins is a blocker — "ungrounded claim … (no pin ≥ 0.5 credibility)" — and the gate's action is reground (grounding-gate.ts:85). Two further blocks layer on top: a claim the Metis evidence bundle marked supportStatus: 'unsupported' is rejected even if a pin is present (grounding-gate.ts:59), and, when the optional CitationVerifier entailment seam is wired, a claim that no pin actually entails is blocked with "not entailed by any pin (Sophia citation check)" (grounding-gate.ts:6372). That last check is the Sophia boundary: Aletheia does not retrieve or rank — it asks an injected verifier whether each pin supports the claim text. The V9SophiaPin contract (primitives.ts:127) carries pinId, sourceId, an optional locator and quote, and the credibility score in [0,1] that G1 thresholds on. Aletheia must not reimplement RAG; G1 is the policy that makes Sophia's existing rail a hard pass.

G2 — Accuracy (recompute the number; block what you cannot reproduce)#

G2 is the one part of Aletheia with no home in Sophia — Sophia retrieves text; it does not solve an ODE or evaluate an ephemeris. evaluateAccuracy (accuracy-gate.ts:53) takes each NumericClaim (a ref, optional params, and the assertedValue the generated text claims) and recomputes it through the kernel registry. The registry (kernel-evaluators.ts:33) is the binding from a string ref to a real in-repo computation — no value is stored:

Kernel ref Real computation Unit
kalika:cosmology#ageTodayGyr ageTodayGyr(PLANCK_2018_COSMOLOGY) (Friedmann integral) Gyr
kalika:cosmology#hubble0 PLANCK_2018_COSMOLOGY.hubble0 km/s/Mpc
kalika:cosmology#lookbackTimeGyr lookbackTimeGyr(…, z) (Simpson integration over expansion history) Gyr
kalika:cosmology#hubbleParameter hubbleParameter(…, z) = H0 · E(z) km/s/Mpc
nyx:constants#speedOfLight SPEED_OF_LIGHT = 299_792_458 m/s
nyx:constants#speedOfLightKmS SPEED_OF_LIGHT_KM = 299_792.458 km/s

The cosmology values are not literals: ageTodayGyr (friedmann.ts:138) Simpson-integrates 1 / (a · E(a)) over 4096 sub-intervals against the frozen PLANCK_2018_COSMOLOGY parameters (hubble0: 67.66, omegaMatter: 0.3111, omegaLambda: 0.6889, friedmann.ts:39), which is why the spec can assert the result lands between 13.6 and 14.0 Gyr. For each claim the gate computes the relative error |asserted − computed| / max(|computed|, 1e-12) and matches it against a tolerance (per-claim tolerance, else default 1e-3, accuracy-gate.ts:58, :80). Two failure modes both block with action regenerate-with-corrected-ground-truth: an unknown kernel ref ("cannot recompute … unknown kernel ref"), and a tolerance miss ("value mismatch … text asserts X, ref computes Y") — the architecture's one-line rule, "you cannot ship a number you cannot reproduce." An optional ContradictionChecker seam runs a Sophia-grounded contradiction pass over the claim text on top (accuracy-gate.ts:103). The spec proves the teeth: asserting a 6000-year-old universe against kalika:cosmology#ageTodayGyr is blocked (aletheia.spec.ts:93).

G6 — Safety (labels, policy, age, and a human in the loop)#

evaluateSafety (safety-gate.ts:69) enforces four things in order. First, every claim must carry an epistemic-status label — one of established, contested, one-tradition, frontier (primitives.ts:114) — so an established fact and a frontier speculation are never presented identically; an unlabeled claim blocks (safety-gate.ts:78). Second, the Metis per-discipline curriculum-safety policy runs through the injected CurriculumSafetyEvaluator; a blocked/abstainRequired/correctionRequired verdict blocks, with block-or-escalate routing (safety-gate.ts:88114). Third, the Sekhmet age/sensitivity gate (safety-gate.ts:122). Fourth, high-stakes disciplines — enumerated as religion, psychology, neuroscience (HIGH_STAKES_DISCIPLINES, safety-gate.ts:19; note the code uses neuroscience as the architecture's "health-adjacent" stand-in) — additionally require a recorded human-review checkpoint, blocking with block-or-escalate when humanReviewed is not set (safety-gate.ts:137). The fail-loud invariant is the important one: a high-stakes discipline with no curriculum policy wired does not auto-publish — it blocks (safety-gate.ts:95, :115). Absence of a safety integration is treated as unsafe, not as "clear."

The other four gates (Prometheus + Hephaestus)#

The remaining four canonical gates are assembled by composeGates (gates.ts:132), which folds Aletheia's three contract verdicts together with the explorable DoD and three Prometheus evaluations into a single V9Gates.

  • G3 PedagogyevaluatePedagogy (gates.ts:36) blocks on a prerequisite-coverage gap (a needed, not-yet-mastered prerequisite that is missing from the concept set, computed from atlas.prerequisitesOf), on zero anticipated misconceptions ("G3 requires misconception coverage"), and on a difficulty that falls outside the flow band. The flow signal comes from @oshun/v9-mnemosyne-glue: tuneDifficultyToFlow (flow-channel.ts:70) classifies the next item's success probability under the Mnemosyne IRT model into 'boredom' | 'flow' | 'anxiety', with the band default 0.6 < p < 0.85 (flow-channel.ts:28); only 'flow' clears the gate.
  • G4 CompletenessevaluateExplorableDoD (explorable-runtime.ts:24) enforces the V9 Definition of Done: a lesson must ship ≥1 computed-kernel explorable whose success state was demonstrably reached. Reachability is not asserted blind — the V9ExplorableSuccessState.reachable flag (explorable.ts:68) is set true only after the kernel output or headless verifier demonstrated the predicate, and isV9ExplorableShippable (explorable.ts:128) gates on exactly that. A generated-but-unverified explorable never ships.
  • G5 QualityevaluateQuality (gates.ts:88) scores the narrative against a 0.7 threshold. The shipped defaultQualityJudge (gates.ts:77) is a deterministic structural proxy (rewarding ≥3 beats, ≥1 Socratic turn, ≥1 misconception, a forward-looking "next question"), with the LLM-as-judge panel left as the injectable QualityJudge boundary. The architecture's panel and Yemaya-validator correlation are the planned realization of this seam.
  • G7 ProvenanceevaluateProvenance (gates.ts:105) checks that the skeletonHash, surfaceHash, and cacheKey are well-formed 64-char hex digests and the ledgerEntryId is present. Seed-reproducibility is real and enforced by the deterministic pipeline (same (inputs, seed) ⇒ identical hashes, pipeline.spec.ts:136); cryptographic C2PA signing of assets is the inherited discipline, not produced here.

How a gate failure stops a lesson#

Stage 7 of the Prometheus forge is where the gates bite. After grounding, planning, writing, explorable-building, and scheduling, forgeLesson calls runAletheia over the verified skeleton (pipeline.ts:181), evaluates pedagogy, quality, and provenance, composes the seven verdicts, and computes blockedGateIds = ALL_GATE_IDS.filter(id => !gates[id].pass) (pipeline.ts:232). If that list is non-empty, the function returns immediately with blocked: true and the failing ids — before Stage 8 — so no artifact is compiled, no C2PA bundle is minted, nothing is cached, and nothing is delivered (pipeline.ts:235). Only a clean sweep reaches compileLesson. The spec proves the block path end-to-end: with Sekhmet denying, the lesson is blocked on G6 and never cached (pipeline.spec.ts:155), and a missing writer boundary fails loud rather than fabricating narrative (:176).

flowchart TD A[Stage 1-6: verified skeleton + narrative + explorable] --> G{Stage 7: gates} G --> AL[runAletheia: G1 grounding, G2 accuracy, G6 safety] G --> H[Hephaestus DoD: G4 completeness] G --> P[Prometheus: G3 pedagogy, G5 quality, G7 provenance] AL --> C[composeGates -> V9Gates] H --> C P --> C C --> Q{all seven pass?} Q -- no --> B[return blocked:true + blockedGateIds<br/>no compile, no cache, no delivery] Q -- yes --> S[Stage 8: compile, C2PA bundle, ledger, profile-class cache] S --> D[V9LessonArtifact delivered]

Reused substrate — what Aletheia must not reimplement#

The gates are a composition, not a rebuild — which is the whole point of the "thin policy layer" thesis. G1 leans on Sophia for retrieval, citation, the knowledge graph, and faithfulness (libs/sophia/*, including libs/sophia/semantic-search and the real DefaultCitationVerifier in libs/sophia/theory). G2 leans on the Kalika cosmology kernels (libs/kalika/cosmology, the Friedmann/Simpson solver) and the Nyx physical constants (libs/nyx/constants). G3's flow band reuses the Mnemosyne IRT model via @oshun/v9-mnemosyne-glue. And every gate, in both framings, runs on the shared @oshun/content-release-gates ReleaseGateService (release-gates.ts:103) — the same promotion gate every other Oshun product uses, with its gateFromEvalScore / gateFromManifestCheck builders and the createGroundingGate from @oshun/content-quality-judge (content-quality-judge/src/grounding-gate.ts:84). Aletheia's contribution is the semantics: the "every claim must have ≥1 credible pin" invariant, the "recompute or block" rule, the "label every claim and gate the high-stakes" rule, and the regenerate-with-direction routing. For the full reuse picture see ./six-layer-reuse-stack.md and ./subsystem-map-and-reuse-ledger.md.

Configuration & edge cases#

  • Thresholds are explicit, not magic. G1 minCredibility defaults to 0.5 (grounding-gate.ts:47); G2 default tolerance is 1e-3 per claim (accuracy-gate.ts:58) — note the contract V9KernelResult.tolerance defaults tighter at 1e-6 (lesson.ts:51), so a stored ground-truth value is bound more strictly than the text-vs-kernel match; G3's flow band is (0.6, 0.85) (flow-channel.ts:28); G5's quality threshold is 0.7; the @oshun/v9-lesson-gates suite uses minTeachability: 70 and minSafety: 90 (lesson-gates/src/index.ts:106).
  • Unknown kernel ref ⇒ block, not skip. G2 records a computedValue: null check and a blocker; it never silently passes a number it cannot reproduce (accuracy-gate.ts:66).
  • Missing seam ⇒ fail loud where it matters. A high-stakes discipline with no curriculum policy blocks (safety-gate.ts:115); a non-high-stakes discipline with no policy simply proceeds with labels-only checks. The humanReviewed flag must be explicitly true to clear a high-stakes lesson.
  • Empty inputs. G1 over an empty claim set passes vacuously (no ungrounded claim exists), but the contract guarantees a lesson has ≥1 grounded claim (V9GroundTruthSchema, lesson.ts:58) and ≥1 explorable (lesson.ts:209), so a real lesson never reaches the gates empty.
  • Determinism. Gate evaluation reads only the skeleton, narrative, and injected seams — there is no Math.random, no wall clock inside the gates (the clock is the caller-supplied nowUnixMs/signedAtIso, pipeline.ts:58), which is what lets the pipeline assert identical hashes across two forges of the same seed.