Metis · Architecture

Subsystem Map & the New-vs-Composed Reuse Ledger

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

9sections17 minread1diagram2tables

On this page

V9 ("Metis — A Curious Ape's Guide to Reality") is built on a single architectural bet: it is a productization version, roughly ~20% net-new connective tissue over ~80% existing, verified capability (V9_ARCHITECTURE.md §10, line 332). That ratio is the whole justification for the version — it is why V9 can ship a grounded, gated learning experience without rebuilding a knowledge graph, a psychometrics engine, an ephemeris, a Friedmann cosmology solver, or a release-gate system. But a ratio asserted in prose is worthless; the only way to trust it is to read the import graph and see which substrates V9 actually composes versus which it merely names. This page is that audit. It maps the nine subsystems named in the architecture's "Subsystem → existing-code map" (V9_ARCHITECTURE.md §7) onto the twelve shipped libs/v9/* packages, then lays out the reuse ledger as a table of real, verified import edges — distinguishing what is genuinely imported, what is reached through a structural (duck-typed) adapter, and what is a deliberately-injected boundary that V9 does not import at all.

The map matters because the territory has drifted from the map. The §7 table lists nine subsystems (Atlas, Prometheus, Aletheia, Chiron, Hephaestus, Mnemosyne, Theia, Agora, Experience); the repository ships twelve V9 packages (ls libs/v9 returns exactly aletheia atlas chiron cross-cutting experience governance hephaestus lesson-explorables lesson-gates mnemosyne-glue prometheus theia), two of which (lesson-explorables, lesson-gates) are an earlier "ledger §J" generation that coexists with the newer "architecture §" generation, and two of which (cross-cutting, governance) implement the §9 cross-cutting and governance-plane concerns the §7 table never enumerates. Reading the code rather than the table also surfaces a real divergence in gate numbering between the two generations — and a subtler one between the architecture prose and the shipped Aletheia — and it confirms that the model plane and the embodiment runtimes (Iris, Nous, Psyche, Hathor) are typed seams, not dependencies. This is the orientation page for the section; the hub is ../V9_ARCHITECTURE.md, and the conceptual companion is ./overview.md.

What ships, honestly#

The net-new connective-tissue libraries are real and tested. All twelve libs/v9/* packages exist with @oshun/v9-* names, implementations, and sibling spec suites — 18 *.spec.ts files across libs/v9 (from aletheia.spec.ts through theia.spec.ts), plus libs/contracts/src/v9/__tests__/v9-contracts.spec.ts covering the three net-new contract families (concept-graph.ts, explorable.ts, lesson.ts). The Atlas store, wonder resolver, source adapters, the Prometheus forgeLesson pipeline, the Aletheia gate trio, the Hephaestus explorable runtime, and the Mnemosyne mastery glue are concrete TypeScript that composes the real substrates — not skeletons.

The composed substrates V9 actually imports are real and in-repo. A grep -a over libs/v9/**/*.ts (tests excluded; the -a matters — see the note below) resolves to eight reused packages, each with a verified package.json whose "name" field matches the import specifier exactly:

  • @mnemosyne/core — the workhorse, imported in 14 non-test files (atlas/atlas-store.ts, atlas/source-adapters.ts, atlas/wonder-resolution.ts, both experience view-models, both lesson-explorables engines, all three mnemosyne-glue modules, prometheus/pipeline.ts, theia/theia.ts, theia/chiron-full.ts, and cross-cutting/anti-metric.ts). Counting the spec suites too it is 18 — but the honest "code reuse" number is 14.
  • @sophia/semantic-search, @kalika/cosmology, @nyx/constants, @nyx/ephemeris, @kalika/symplectic, @oshun/content-release-gates, and @oshun/content-quality-judgeone importing file each, every one a real, load-bearing call into a verified engine. That focused fan-in is the ~80% made concrete: V9's leaves do not re-implement BM25, an ephemeris, a Friedmann solver, a symplectic integrator, or the release-gate machinery; they bind the one symbol they need and execute it.

A real corruption discovered while auditing. atlas/atlas-store.ts contains two embedded NUL bytes, so file(1) reports it as data and a plain grep silently skips it as "binary." This is why a naïve grep -c for @mnemosyne/core undercounts to 13; grep -a (or reading the file) restores the true 14th importer. The import itself is valid TypeScript (import { KnowledgeGraph, … } from '@mnemosyne/core', lines 11–19); the NUL bytes are stray serialization debris in the source, not a logic defect — but they are exactly the kind of invisible artifact a careful audit exists to find.

Three honest qualifications about the reuse boundaries. First, the Sophia knowledge-graph merge is a structural adapter, not a direct importfromSophiaKnowledgeGraph (atlas/source-adapters.ts:163) accepts a locally-declared SophiaGraphStoreLike interface (source-adapters.ts:142); @sophia/knowledge-graph appears only in the module's doc comment (source-adapters.ts:9), never in an import. Sophia's BM25 retrieval, by contrast, is a real import (createBM25LexicalIndex from @sophia/semantic-search, wonder-resolution.ts:14). Second, the model plane and embodiment runtimes are injected boundaries: a grep -a for from '@iris, from '@nous, from '@psyche, or from '@hathor across all of libs/v9 returns nothing — Chiron's voice/face, the lesson writer, and the dense reranker are all typed seams that fail loud or degrade honestly when absent. Third, the consumer app (Layer 6) is the largest piece still mostly ahead of the code: libs/v9/experience ships the view-models the screens bind to (its index.ts:2 is literally "the consumer experience-layer view-models"), but the rendered consumer-first apps/metis/{web,mobile} is, per §7's own honesty note, "currently instructor/admin-shaped — the largest net-new build." Where this page says "view-models exist" it means exactly that, not "a shipped consumer surface."

The subsystem map: nine names, twelve packages#

The §7 table names nine subsystems. Eight resolve cleanly to a libs/v9/* package; the ninth ("Agora") is not a standalone library but a sub-module inside theia. Four shipped packages have no row in §7 at all. Here is the reconciled map, verified against ls libs/v9 and each package's src/:

§7 subsystem Shipped package(s) Status (verified)
Atlas @oshun/v9-atlas Real. Store + 3 source adapters + graph unifier + wonder resolver + grounding validator.
Prometheus @oshun/v9-prometheus Real. forgeLesson Stages 0–8 composed end-to-end (pipeline.ts, ground-truth/plan/write/gates/compile).
Aletheia @oshun/v9-aletheia Real. G1/G2/G6 gate trio (grounding/accuracy/safety-gate.ts) + kernel-evaluator registry.
Chiron @oshun/v9-chiron (+ theia/chiron-full.ts) Real persona + integrity-mode logic; live avatar/voice runtimes are injected boundaries.
Hephaestus @oshun/v9-hephaestus Real. Nyx-sky + Kalika-orbit explorables + evaluateExplorableDoD.
Mnemosyne @oshun/v9-mnemosyne-glue Real glue over the Mnemosyne FSRS/SM-2/IRT engines.
Theia @oshun/v9-theia P2 lib; also hosts Agora (agora.ts) and Chiron-full (chiron-full.ts).
Agora nonetheia/src/agora.ts Not a standalone package; a Theia sub-module ("creator authoring + shareable social objects").
Experience @oshun/v9-experience View-models only; the rendered consumer app is the largest net-new build.
(§9, unlisted) @oshun/v9-cross-cutting Real. determinism, cost-discipline, accessibility, champion-challenger, anti-metric, lms-interop, localization.
(governance, unlisted) @oshun/v9-governance Real. agent-family (AgentRun-envelope registration), gate-suite, iris-loop confirmation, entitlements.
(§J, unlisted) @oshun/v9-lesson-explorables, @oshun/v9-lesson-gates Real, earlier generation. The "no eighth loop" gate suite over the shared platform release gate.

The honest reading: the §7 map is a faithful sketch of the design, but it under-counts the shipped surface and omits the fact that two lesson pipelines and two seven-gate suites coexist. The lesson-explorables/lesson-gates pair descends from the V9 task ledger (V9_TODOS.md §J) and builds on the platform's shared @oshun/content-release-gates; the prometheus/aletheia/hephaestus trio descends from the architecture sections (§3–§5) and emits the V9LessonArtifact contract. They are not fully disjoint — prometheus/pipeline.ts:24 imports the LessonResponse type from @oshun/v9-lesson-explorables to drive its flow-channel tuning (the optional flowHistory input at pipeline.ts:82) — but they are two distinct realizations of "forge a gated lesson," and a reader should expect to encounter both. See ./prometheus-lesson-pipeline.md for the architecture-§ pipeline and ./lesson-artifact.md for the contract both ultimately serve.

The reuse ledger: what V9 actually imports#

This is the heart of the page — the ~80% composed claim, reduced to verified import edges. Each row names a reused substrate, the exact symbols V9 binds, and the consuming V9 file. Everything here was confirmed with grep -a over libs/v9/**/*.ts (tests excluded) and a package.json "name" check on each substrate.

Reused substrate Symbol(s) bound Consumed by (file:line) Kind
@mnemosyne/core KnowledgeGraph (+ KGNode/KGEdge/KGNodeId/MasteryLevel types); the engine methods identifyKnowledgeGaps, topologicalSort, getPrerequisites; sm2Review, irt1PL/irt2PL, estimateAbility, MASTERY_LEVELS 14 files incl. atlas/atlas-store.ts:11, atlas/wonder-resolution.ts:15, mnemosyne-glue/*, lesson-explorables/* Real import
@sophia/semantic-search createBM25LexicalIndex atlas/wonder-resolution.ts:14 Real import
@kalika/cosmology PLANCK_2018_COSMOLOGY, ageTodayGyr, lookbackTimeGyr, hubbleParameter (one import, four symbols) aletheia/kernel-evaluators.ts:11 Real import
@nyx/constants SPEED_OF_LIGHT, SPEED_OF_LIGHT_KM aletheia/kernel-evaluators.ts:10 Real import
@nyx/ephemeris calculateSunPosition, dateToJd hephaestus/nyx-sky-explorable.ts:13 Real import
@kalika/symplectic integrateCanonical, analyzeEnergyBehavior (+ PhaseState/SeparableHamiltonianSystem types) — velocity-Verlet lesson-explorables/orbit-explorable.ts:16 Real import
@oshun/content-release-gates ReleaseGateService, gateFromEvalScore, gateFromManifestCheck, GateDefinition lesson-gates/index.ts:24 Real import
@oshun/content-quality-judge createGroundingGate, ClaimExtractor, GroundingRetriever lesson-gates/index.ts:31 Real import
@sophia/knowledge-graph getAllNodes()/getAllEdges() shape only atlas/source-adapters.ts:142 (SophiaGraphStoreLike) Structural adapter
Iris / Nous (model plane) LessonWriter, WonderEmbedder, MisconceptionAnticipator, QualityJudge prometheus/write.ts, atlas/wonder-resolution.ts:21, prometheus/gates.ts:72 Injected boundary
Psyche / Hathor (embodiment) ChironPersona.voicePackRef ('psyche:voice/…' ref string), ChironPersonality facets chiron/persona.ts:21, theia/chiron-full.ts Injected boundary

Three kinds, three meanings. A real import is the genuine article: the symbol is pulled from a verified in-repo package and executed — and crucially, many of the @mnemosyne/core bindings are not free functions but engine methods. atlas-store.ts imports the KnowledgeGraph class and calls .topologicalSort(), .getPrerequisites(), and (via wonder-resolution.ts:142) .identifyKnowledgeGaps() on a projection of the Atlas — Atlas deliberately does not reimplement closure/topo-sort/gap-analysis; it projects its edges into the Mnemosyne engine and reads the answer back (atlas-store.ts:113, toMnemosyneGraph). A structural adapter is reuse-by-shape — fromSophiaKnowledgeGraph(store, defaults) takes anything matching SophiaGraphStoreLike (getAllNodes()/getAllEdges()), so V9 composes Sophia's KG without a compile-time edge to it; the cost is that a shape change in Sophia is not caught by V9's type-checker, only at runtime in unifyAtlas (atlas/graph-unifier.ts:96). An injected boundary is a typed seam the caller must fill: the lesson writer, the dense reranker, the misconception anticipator, and the LLM quality judge are all interfaces, and even the persona's voice is a psyche:voice/… reference string rather than an import — when one is absent the system fails loud or degrades honestly rather than fabricating output (see the failure-modes section). This three-way split is the precise, defensible version of §10's "20% new over 80% composed": the 80% is the real-import column, the seams are where the model plane plugs in, and the structural adapter is the one place reuse is by convention rather than by import.

How composition works in practice — a worked trace#

The cleanest way to see the reuse is to follow one wonder through prometheus/pipeline.ts's forgeLesson (pipeline.ts:111), noting which substrate each stage borrows. The pipeline is explicitly staged in its header comment as 0 → 1 → 2 → 3 → 5 → 6 → 7 → 8 (there is no Stage 4 — the misconception pass is folded into the Stage-3 write), and each stage is a function call into a composed engine:

flowchart TD W["wonder: free text"] --> S0 subgraph Atlas["@oshun/v9-atlas"] S0["Stage 0 — resolveWonder()"] end subgraph Sophia["@sophia/semantic-search"] BM25["createBM25LexicalIndex()"] end subgraph Mnemo["@mnemosyne/core"] KG["KnowledgeGraph.identifyKnowledgeGaps()"] end S0 --> BM25 S0 --> KG S0 --> S1["Stage 1 — buildGroundTruth (verified skeleton)"] S1 --> S2["Stage 2 — planLesson (HTN)"] S2 --> S3["Stage 3 — realizeNarrative (injected Iris writer + misconception pass)"] S3 --> S5["Stage 5 — explorableBuilder"] subgraph Heph["@oshun/v9-hephaestus"] DOD["evaluateExplorableDoD (G4)"] end S5 --> DOD S5 --> S6["Stage 6 — applyRetrievalCheckpoint (Mnemosyne)"] S6 --> S7["Stage 7 — runAletheia + composeGates"] subgraph Aleth["@oshun/v9-aletheia"] KER["kernel recompute: @kalika/cosmology, @nyx/constants"] end S7 --> KER S7 --> GATE{"all 7 gates pass?"} GATE -- no --> BLOCK["BLOCKED — not delivered, not cached (pipeline.ts:235)"] GATE -- yes --> S8["Stage 8 — compileLesson (C2PA, ledger, cache)"] S8 --> ART["V9LessonArtifact"]

Concretely: Stage 0 (resolveWonder, wonder-resolution.ts:86) builds a BM25 index over every Atlas node's text (label + aka + discipline + wonderAxis, wonder-resolution.ts:63) via @sophia/semantic-search, then — if a dense embedder (the Nous seam) is injected — blends it 50/50 with BM25 over all nodes (wonder-resolution.ts:108–119, denseWeight default 0.5), so a wonder with no lexical overlap ("the beginning of everything") can still reach the right concept by cosine similarity. It projects the Atlas onto a real @mnemosyne/core KnowledgeGraph (toMnemosyneGraph) and calls identifyKnowledgeGaps to scope the prerequisite frontier to the learner's mastery (masteryFloor default 'intermediate', topK default 5), returning the gap set in prerequisite order plus the target. Stage 1 (buildGroundTruth) is the "solve-first" verified skeleton — the immutable, gated truth. Stage 2 (planLesson) is the HTN plan. Stage 3 (realizeNarrative) realizes that skeleton through the injected LessonWriter (Iris) and an optional MisconceptionAnticipator. Stage 5 binds one Hephaestus explorable for the chosen concept. Stage 6 assesses and schedules through the Mnemosyne glue (applyRetrievalCheckpointintervalDays/nextReviewAtIso). Stage 7 runs Aletheia (runAletheia, aletheia.ts:47), which recomputes every STEM value from the real @kalika/cosmology Friedmann solver and @nyx/constants (kernel-evaluators.ts) and, via composeGates (gates.ts:132), folds in the Hephaestus computed-explorable Definition-of-Done (G4) plus three Prometheus-owned checks (G3 pedagogy, G5 quality, G7 provenance). Only if all seven gates pass does Stage 8 compile the immutable, C2PA-stamped V9LessonArtifact and cache it by (conceptSet, profileClass, seed) (compile.ts:31, concept order made irrelevant by a .sort()); a blocked lesson short-circuits at pipeline.ts:235 and is "not delivered, not cached." The deeper treatment of each stage lives in ./prometheus-lesson-pipeline.md; ./atlas-knowledge-graph.md covers the resolve step, ./hephaestus-explorables.md the explorable DoD, and ./seven-gates-and-aletheia.md the Stage-7 gate.

Inside the three Prometheus-owned gates#

The worked trace glosses Stage 7's non-Aletheia gates; the audit should not, because "composed, not forked" has to hold inside each gate too:

  • G3 pedagogy (gates.ts:36, evaluatePedagogy) makes three real checks: every un-mastered prerequisite of the target (from the Atlas, via Mnemosyne prerequisitesOf) must be in the concept set; the narrative must anticipate ≥1 misconception; and, if a flow channel was computed, the difficulty must sit in the 'flow' band (not 'boredom'/'anxiety'). Any failure is a blocker string, not a soft warning.
  • G5 quality (gates.ts:88) takes an injected QualityJudge (the LLM-judge boundary). When none is supplied it falls back to a deterministic structural score (defaultQualityJudge, gates.ts:77): +0.4 for ≥3 beats, +0.3 for ≥1 Socratic turn, +0.2 for ≥1 misconception, +0.1 for a "next question" hook, threshold 0.7. That is a documented approximation, not a fabricated score — it never claims an LLM rated the lesson when one did not.
  • G7 provenance (gates.ts:105, evaluateProvenance) checks that skeletonHash, surfaceHash, and cacheKey are each 64-hex (HEX64 = /^[a-f0-9]{64}$/, gates.ts:103) and that a ledgerEntryId is present — the concrete enforcement of the determinism invariant.

Two gate generations — an honest divergence#

Because two lesson pipelines coexist, two seven-gate suites coexist, and their G-numbering does not agree. This is the kind of map-vs-territory detail a subsystem audit exists to surface.

The architecture-§ suite (prometheus/gates.ts composeGates, emitting the contract V9Gates from libs/contracts/src/v9/lesson.ts:149) numbers them: G1 Grounding, G2 Accuracy, G3 Pedagogy, G4 Completeness (explorable DoD), G5 Quality, G6 Safety, G7 Provenance — with G1/G2/G6 owned by Aletheia, G4 by Hephaestus, and G3/G5/G7 computed in Prometheus (gates.ts:143–149). This matches the §5 gate table exactly.

The ledger-§J suite (lesson-gates/index.ts buildV9LessonGates, index.ts:102) numbers them differently: G1 truth, G2 grounding, G3 teachability, G4 safety, G5 explorable, G6 adaptive, G7 retrieval — built as real GateDefinitions and registered into the shared @oshun/content-release-gates service (registerSuite(V9_LESSON_GATE_SUITE_ID, …), index.ts:192). Both suites are real, both are seven required gates, both block on failure; they simply assign different letters to different checks. When you read "G4" in a V9 source file, check which generation you are in.

There is a quieter divergence even within the architecture-§ generation: §5.1 of V9_ARCHITECTURE.md says "G1/G2 (owned by Aletheia)," but the shipped aletheia.ts (runAletheia, lines 47–68) actually owns three gates — it runs evaluateGrounding (G1), evaluateAccuracy (G2), and evaluateSafety (G6) and exposes gateVerdicts.{G1,G2,G6}. The code is the source of truth: Aletheia is the G1/G2/G6 trio, and the §5.1 prose simply predates the safety gate moving in. The unifying principle survives both divergences — "no eighth loop," every lesson gated by the same platform release-gate machinery rather than a bespoke per-product checker — and it is documented from both angles in ./seven-gates-and-aletheia.md.

The injected-boundary discipline#

The reason V9 can claim a clean reuse ratio and remain honest is that it never fakes the parts it cannot compute deterministically. The model plane (Iris orchestration, Nous inference) and the embodiment plane (Psyche voice/face, Hathor personality) are represented as typed interfaces the caller injects, and their absence is a loud failure or an honest degradation, never a silent fabrication:

  • resolveWonder throws WonderUnresolvedError (wonder-resolution.ts:56, also thrown at lines 93/130/133) when a wonder matches no Atlas concept — it never invents a concept to satisfy the query.
  • The Atlas store rejects an ungrounded fact node or a kernel-less STEM node at insert time: addNode (atlas-store.ts:61) parses through V9ConceptNodeSchema.parse (atlas-store.ts:62), and assertAtlasGrounded (grounding-validator.ts:57) throws on any violation, naming every offending node id — "the invariant is a gate, not a warning."
  • The dense reranker (WonderEmbedder), the lesson writer (LessonWriter), the misconception anticipator, and the LLM quality judge are optional/injected; when no embedder is supplied, resolution falls back to BM25-only (wonder-resolution.ts:122) rather than pretending to do semantic recall, and when no LLM judge is supplied G5 uses the documented structural score.
  • The teacher persona is the same discipline applied to embodiment. The shipped WARM_GENERALIST_PERSONA (chiron/persona.ts:35) carries synthetic: true and a disclosureLabel ("AI teacher (synthetic voice). Reconstructions are labeled."), and its voice is a voicePackRef: 'psyche:voice/chiron-warm-en' string — a reference the embodiment runtime resolves, never an imported Psyche module. And Chiron's integrity logic is real, not cosmetic: resolveTutorAction (chiron/integrity-modes.ts:44) maps a 'do-not-complete-for-me' mode to a 'refuse' action, so the tutor will not do a learner's graded work for them.

This is the same fail-loud / inject-the-boundary pattern the rest of the portfolio uses, and it is what makes the reuse ledger trustworthy: a seam is visibly a seam.

Edge cases & failure modes#

  • Ungrounded node — rejected at the door by V9ConceptNodeSchema; a candidate set can be pre-screened with validateConceptNodes (grounding-validator.ts:28), and a built Atlas asserted with assertAtlasGrounded (:57, throws, listing every violating node id).
  • Unresolvable wonderWonderUnresolvedError; the front door must handle it as "I don't have a thread for that yet," never as a fabricated lesson. Note the three distinct throw sites (empty Atlas, zero scored candidates, missing target) collapse to the same honest error.
  • Cyclic prerequisite graphorderByPrerequisite (wonder-resolution.ts:153) wraps KnowledgeGraph.topologicalSort() in a try/catch; on the cycle throw it falls back to the given order (wonder-resolution.ts:159–161) rather than crashing the resolve.
  • Blocked lesson — any failed gate short-circuits before Stage 8; the result carries blocked: true and blockedGateIds, and the artifact is neither returned nor cached (pipeline.ts:235). A defensive isV9LessonPublishable re-check (pipeline.ts:257, contract at lesson.ts:246) throws if the contract's own publishability ever disagreed with the gate sum.
  • Structural-adapter drift — because the Sophia KG merge is duck-typed (SophiaGraphStoreLike), a breaking change to Sophia's GraphStore shape is not caught by V9's type-checker; it surfaces at runtime in unifyAtlas (graph-unifier.ts:96). This is the one reuse edge without a compile-time guarantee, and the price of merging a graph V9 does not import.
  • Determinism & cost — the artifact is seed-reproducible: same (inputs, seed) ⇒ same skeletonHash/surfaceHash/cacheKey and the same deterministic ledgerEntryId (derived from the content hash, compile.ts:117, not the run). The cache key sorts its concept set (compile.ts:36), so concept order never splits the cache, and the generation ledger is append-only/immutable (InMemoryGenerationLedger.append refuses to overwrite, compile.ts:68). Determinism is therefore both a provenance lever (G7) and a cost lever: a popular lesson is gated once and servedFromCache thereafter.
  • Binary-grep blind spot — as flagged above, atlas-store.ts's two NUL bytes make plain grep skip it; any tooling that audits this codebase by line-grep (including this page's own reuse counts) must use grep -a or it will silently undercount the Mnemosyne fan-in by one.

Connections to neighbouring systems#

This page is the index; each subsystem has its own deep page. The reuse stack itself — the six layers from platform up to experience — is ./six-layer-reuse-stack.md. The knowledge spine and its three source adapters are ./atlas-knowledge-graph.md. The forge that composes everything is ./prometheus-lesson-pipeline.md, emitting the contract documented in ./lesson-artifact.md. The computed-kernel explorables are ./hephaestus-explorables.md, the gate plane is ./seven-gates-and-aletheia.md, and the cross-cutting and governance libraries (cross-cutting, governance) that §7 omits are covered in ./delivery-and-cross-cutting.md. For the narrative overview of why V9 is a productization version at all, start at ./overview.md.