Prometheus is V9's lesson forge: the function that turns a learner's free-text
wonder — "how old is the universe?", "why is the night sky dark?" — into a
grounded, interactive, provenance-stamped V9LessonArtifact, with no human
authoring per lesson. Its governing discipline is three words, inherited from
V8's "propose/dispose" mystery generator and retargeted from fair mystery to
true explanation: solve-first, grounded, gated. The verified skeleton —
the grounded claims and the kernel-recomputed numbers — is built from the real
Atlas nodes before any prose exists, and the language model is constrained to
realize that skeleton rather than invent it ("the LLM never invents a fact or
a number", libs/v9/prometheus/src/ground-truth.ts:7). The whole pipeline is
one async function, forgeLesson (libs/v9/prometheus/src/pipeline.ts:111),
and it adds no new agent loop — it composes the already-shipped V9 packages
(Atlas resolve, the Nyx/Kalika kernels, Hephaestus explorables, the Mnemosyne
mastery loop, Aletheia + the seven contract gates) and treats the LLM writer as
an injected boundary, not a bespoke orchestrator
(libs/v9/prometheus/src/index.ts).
Why this shape? Because in V9 trustworthiness and cost are the same problem. A
lesson is a reproducible artifact with a hard split — a verified skeleton
that is authoritative and immutable once gated, and a regenerable surface (the
prose, the Socratic dialogue, the media) that can be re-skinned over the same
proven content. That split is encoded directly in the artifact as skeletonHash
vs surfaceHash, and it is what lets V9 gate a popular lesson once and serve it
many times, and swap a different teacher persona over identical verified truth.
This page is the deep, stage-by-stage companion to the forge summary in
./overview.md; the section hub is
../V9_ARCHITECTURE.md.
What ships, honestly#
The forge is real and end-to-end tested, but the monolith's nine-stage table
(../V9_ARCHITECTURE.md §3) is in places aspirational about who does the
work, so this section separates the three honesty tiers. Honest "planned/seam"
beats fake "shipped."
Implemented and tested (real today). forgeLesson composes Stages 0, 1, 2,
3, 5, 6, 7, and 8 end-to-end into a publishable artifact, and a single
end-to-end test forges "how old is the universe?" all the way through — real
~13.8 Gyr ground truth, all seven gates, determinism, the profile-class cache,
the block path, and the fail-loud path
(libs/v9/prometheus/src/pipeline.spec.ts). Stage 1 recomputes STEM values from
the genuine @kalika/cosmology Friedmann solver and @nyx/constants
(libs/v9/aletheia/src/kernel-evaluators.ts:33); Stage 6 drives the real
@mnemosyne/core FSRS engine
(libs/v9/mnemosyne-glue/src/mastery-feedback.ts:42); Stage 8 emits a
contract-validated V9LessonArtifact with deterministic hashes, an immutable
ledger entry, and a profile-class cache
(libs/v9/prometheus/src/compile.ts:152).
Spec-described / not wired into the forge. Two stages from the monolith
table are not executed inside forgeLesson. Stage 4 "Realize media" (Isis +
Euterpe + Psyche) is absent — the pipeline accepts media as a pre-built
V9Media input and defaults it to { visuals: [] }
(libs/v9/prometheus/src/pipeline.ts:213); Prometheus imports nothing from
libs/isis, DOMAINS/euterpe, or DOMAINS/psyche. Stage 9 "Deliver" is a
separate module, planLessonDelivery in @oshun/v9-chiron
(libs/v9/chiron/src/lesson-delivery.ts:59), not called by the forge. The
monolith also credits Stage 2 to a "Yemaya HTN planner" (reusing
libs/yemaya/agents/planning + libs/yemaya/autonomous-pipelines) and Stage
3 to libs/hathor/llm-npc + libs/iris/conversation-*; in the actual code
plan.ts is a self-contained deterministic decomposition that imports none of
Yemaya, and write.ts defines an injected writer interface that imports none
of Hathor or Iris. Those directories exist in the repo, but Prometheus does not
depend on them (its package.json lists only @oshun/contracts and the
v9-aletheia/atlas/hephaestus/mnemosyne-glue/lesson-gates packages). Treat
"HTN-planned on Yemaya, written by Hathor over Iris" as architectural framing,
not a wired call graph.
Provider-gated injected seams (fail-loud, not faked). Several inputs are
typed boundaries the forge injects rather than fakes: the LLM lesson writer
(the Iris boundary, Stage 3 — absent ⇒ LessonWriterNotConfiguredError,
libs/v9/prometheus/src/write.ts:37), the optional Nous dense embedder in
resolution, the LLM-as-judge quality panel for G5 (whose default is an
honest deterministic structural proxy, libs/v9/prometheus/src/gates.ts:77),
and the Metis curriculum-policy + Sekhmet age safety seams for G6. Two
further honesty notes: G7 verifies that the hashes and a ledger id are present
and well-shaped, not that real cryptographic C2PA signing occurred (the
explorable's c2paSigned defaults to false); and the supplied ledger/cache
implementations are InMemory* (libs/v9/prometheus/src/compile.ts:65, :86),
durable stores being the caller's to inject.
The forge contract: input, output, and the block rule#
Everything the forge needs arrives in one ForgeLessonInput
(libs/v9/prometheus/src/pipeline.ts:53). The required fields are the wonder,
the AtlasStore, the learnerProfileClass, a seed, a caller-supplied clock
(nowUnixMs, "no fabricated time"), a signedAtIso provenance timestamp, an
opaque runId (captured as [x] evidence, not part of the artifact), the
explorableBuilder, and the retrievalScore. Everything else is an optional
injected boundary or tuning input:
| Field | Stage | Role |
|---|---|---|
learnerMastery, embedder |
0 | mastery map to scope the frontier; optional Nous reranker |
claimTextByConcept |
1 | override a node's default claim sentence |
writer, misconceptionAnticipator |
3 | the Iris writer boundary; the G3 misconception pass |
explorableBuilder (required) |
5 | the Hephaestus binding for the chosen concept |
retrievalCard, retrievalScore, flowHistory |
6 | FSRS card + recall score + IRT history for the flow band |
qualityJudge, safetyOptions, humanReviewed, nextWonders |
7 | the G5/G6 seams and the Theia thread |
media, cache, ledger |
8 | pre-built media (Stage 4 is not run), durable stores |
The output is a ForgedLessonResult (pipeline.ts:96): always runId,
blocked, blockedGateIds, the seven gates, the aletheia report, and the
resolved conceptSet; and — only when every gate passed — the compiled
artifact, its cacheKey, and servedFromCache. The block rule is hard and
central: blockedGateIds is the list of gate ids whose verdict did not pass,
and if it is non-empty the forge returns early with blocked: true and no
artifact is compiled, delivered, or cached (pipeline.ts:232). A blocked
lesson never reaches Stage 8.
The flow, stage by stage#
Each stage takes the prior stage's typed artifact and produces the next; the verified skeleton from Stage 1 is the spine that every later stage references.
Stage 0 — resolve (Atlas)#
resolveWonder (libs/v9/atlas/src/wonder-resolution.ts:86) runs real Sophia
BM25 lexical retrieval over the Atlas node text, optionally blended 50/50
with an injected Nous dense embedder, picks the top candidate as the target,
then asks the real Mnemosyne engine for that target's prerequisite frontier
filtered by the learner's mastery (identifyKnowledgeGaps). The output is the
minimal teaching set in prerequisite order, then the target — cognitive-load
discipline, not the whole subtree. A wonder that matches nothing throws
WonderUnresolvedError rather than inventing a concept. The deep account is
./atlas-knowledge-graph.md.
Stage 1 — ground / solve-first (the verified skeleton)#
buildGroundTruth (libs/v9/prometheus/src/ground-truth.ts:43) walks the
resolved concept set and builds the authoritative skeleton from the grounded
Atlas nodes, never from the model. Each fact node with grounding pins
contributes a V9GroundedClaim carrying up to 16 of its Sophia pins, the node's
epistemicStatus, and truth: 'true' (ground-truth.ts:54). Each STEM
kernelRef on a node is recomputed through the kernel evaluator — compute,
don't assert — yielding a V9KernelResult with a contentHash over
[ref, params, value] and a parallel numericClaim for the G2 accuracy gate
(ground-truth.ts:64). The default evaluator is a registry of real in-repo
computations: kalika:cosmology#ageTodayGyr calls
ageTodayGyr(PLANCK_2018_COSMOLOGY), nyx:constants#speedOfLight returns the
real constant (libs/v9/aletheia/src/kernel-evaluators.ts:33). If no grounded
fact node is in scope, the stage throws "refusing to forge an ungrounded
lesson" (ground-truth.ts:86) — there is nothing to teach, so nothing is
fabricated.
Stage 2 — plan (deterministic HTN decomposition)#
planLesson (libs/v9/prometheus/src/plan.ts:35) decomposes the skeleton into
a LessonPlan deterministically — the same (skeleton, seed) always plans the
same lesson, which is half the determinism lever. The beat outline is
Hook → Establish[i] for each grounded claim → "Why it matters" → "The next question"
(plan.ts:39). The retrieval checkpoint is pinned to the most-credible
claim — the claim whose highest pin credibility is greatest
(assessmentClaimRef, plan.ts:47) — so the recall item probes the
best-supported fact. The explorable defaults to the last concept in the set (the
target), and the persona defaults to chiron:warm-generalist
(libs/v9/chiron/src/persona.ts:35). Despite the monolith's "Yemaya planner"
framing, this is a self-contained function; it is HTN in spirit (decompose a
goal into ordered beats), not a call into the Yemaya planning library.
Stage 3 — write (the injected Iris boundary)#
realizeNarrative (libs/v9/prometheus/src/write.ts:77) is where the LLM
enters — and where the forge refuses to fabricate. With no writer wired it
throws LessonWriterNotConfiguredError (write.ts:78) rather than emit a
hand-built lesson. The LessonWriter is a typed boundary:
write({ wonder, plan, groundTruth }) → LessonDraft. The realization is then
constrained to the grounded skeleton: every Socratic turn's claimRefs must
index a real claim, and an out-of-range ref throws (write.ts:87); a draft with
no beats is rejected. A misconception-anticipation pass (the G3 input)
merges the writer's flagged misconceptions with a default anticipator that flags
every non-established claim as misread-prone and pairs it with its grounded
correction (defaultMisconceptionAnticipator, write.ts:49), deduped by text
with every claimRef validated. The result is a V9Narrative whose every
assertion traces back to a verified claim.
Stage 4 — realize media (not run by the forge)#
The monolith assigns visuals (Isis), score (Euterpe), and the Chiron face/voice
(Psyche) to a Stage 4. In code the forge skips it: media is a pre-built input
defaulting to { visuals: [] } (pipeline.ts:213). Media generation is
therefore out-of-band today — the forge will carry and hash whatever media
you hand it (it feeds the surfaceHash), but it does not generate it.
Stage 5 — build explorable (Hephaestus)#
The forge calls the injected explorableBuilder(plan.explorableConceptId)
(pipeline.ts:147) to bind a manipulable surface to the chosen concept. The P1
builders are real computation: a Kalika orbit wrapping the velocity-Verlet
symplectic integrator, or a Nyx sky integrating the real Sun position. The load
-bearing field is the explorable's success state, whose reachable flag is
set true only when a kernel result or headless verifier actually demonstrated
it — never asserted blind. Stage 7's G4 verdict is computed from exactly these
explorables; see ./hephaestus-explorables.md.
Stage 6 — assess & schedule (the Mnemosyne loop)#
applyRetrievalCheckpoint (libs/v9/mnemosyne-glue/src/mastery-feedback.ts:42)
turns the retrievalScore into an FSRS review grade
(≥0.95 easy, ≥0.75 good, ≥0.5 hard, else again, mastery-feedback.ts:21),
runs the real @mnemosyne/core fsrsReview over the concept's trace card, and
schedules the next review at the forgetting frontier — the moment recall is
hardest-but-possible (the testing effect, knowledge-trace.ts:62). The forge
records the schedule (mnemo:<concept>:int<days>d, intervalDays,
nextReviewAtIso) and an assessment whose retrieval prompt is
Recall: <the central claim text> keyed to plan.assessmentClaimRef. If
flowHistory is supplied, tuneDifficultyToFlow
(libs/v9/mnemosyne-glue/src/flow-channel.ts:70) uses the IRT ability MLE to
recommend the next item's difficulty and classify it into Csíkszentmihályi's
channel (success probability in [0.6, 0.85] is flow); that channel is handed
to G3. The recall result also projects to a MasteryLevel that closes the loop
back to Atlas (buildAtlasMasteryMap, mastery-feedback.ts:73), so a mastered
concept drops out of the next wonder's frontier.
Stage 7 — gate (the seven contract verdicts)#
composeGates (libs/v9/prometheus/src/gates.ts:132) assembles the canonical
V9Gates from four real evaluations. G1 grounding, G2 accuracy, and G6
safety come from runAletheia, which runs the three in parallel
(libs/v9/aletheia/src/aletheia.ts:47): G1 blocks any claim without a pin of
credibility ≥ 0.5 (grounding-gate.ts:43); G2 recomputes every numeric claim
and blocks on an unknown kernel ref or a tolerance miss — "you cannot ship a
number you cannot reproduce" (accuracy-gate.ts:66); G6 requires an
epistemic-status label on every claim, applies the injected Metis/Sekhmet seams,
and forces a human-review checkpoint for the high-stakes disciplines religion,
psychology, and neuroscience (safety-gate.ts:19, :137). G3 pedagogy
(gates.ts:36) fails on a prerequisite-coverage gap, on zero anticipated
misconceptions, or on a difficulty out of the flow band. G4 completeness is
the Hephaestus DoD — ≥1 computed-kernel explorable that reached its success
state (evaluateExplorableDoD, explorable-runtime.ts:24). G5 quality
(gates.ts:88) thresholds a judge score at 0.7; the default judge is an honest
structural proxy that rewards ≥3 beats, ≥1 Socratic turn, ≥1 misconception, and
a "next question" beat (gates.ts:77) — a real LLM panel is the injected
qualityJudge. G7 provenance (gates.ts:105) checks the skeleton/surface/
cacheKey hashes are 64-hex and the ledger id is present.
On failure, Aletheia attaches a regenerate-with-direction routing label to
each failing gate — reground, regenerate-with-corrected-ground-truth,
re-scope, or block-or-escalate (libs/v9/aletheia/src/verdict.ts:11) — and
the forge returns those in the aletheia report. Note the honest boundary: the
forge computes and returns the routing, but does not itself run an
automated regenerate loop or HITL round; the caller acts on the actions. The
two-framing detail (this canonical G1–G7 vs the separate
@oshun/v9-lesson-gates suite, which Prometheus does not call) is in
./seven-gates-and-aletheia.md.
Stage 8 — compile & cache (only a passing lesson)#
compileLesson (libs/v9/prometheus/src/compile.ts:152) runs only when every
gate passed. It first checks the profile-class cache by
cacheKeyFor([...conceptSet].sort(), learnerProfileClass, seed) — a sha256 over
the order-independent concept set, the profile class, and the seed
(compile.ts:31); a hit returns the cached artifact with
servedFromCache: true and no recompilation. On a miss it stamps the C2PA
bundle — skeletonHash = sha256(groundTruth),
surfaceHash = sha256([narrative, media]), and a content-derived
ledgerEntryId (ledger:<cacheKey…>, not run-derived, so the same inputs
reproduce the same id) — then parses the result through V9LessonArtifactSchema
(lesson.ts:190), so the contract's own superRefine re-validates that every
claimRef indexes a real claim. The entry is appended to the immutable ledger
(which never overwrites, compile.ts:67) and cached. Back in the forge, a
defensive check asserts the contract's isV9LessonPublishable agrees with the
gate sum, throwing if they ever disagree (pipeline.ts:257). Because
previewProvenanceBundle is deterministic and called both for the G7 gate and
inside compile, G7 verifies exactly the bundle Stage 8 stamps. The full artifact
anatomy is in ./lesson-artifact.md.
Stage 9 — deliver (a separate Chiron module)#
Delivery is not part of forgeLesson. planLessonDelivery
(libs/v9/chiron/src/lesson-delivery.ts:59) turns a gated artifact into a
Chiron-fronted delivery plan under an integrity mode and a resolved delivery
tier, and it refuses to deliver an ungated lesson (UngatedLessonError,
:48) — nothing un-passed reaches a learner. The live voice/avatar runtimes are
themselves injected boundaries. See
./delivery-and-cross-cutting.md.
A worked forge: "how old is the universe?"#
The end-to-end test (libs/v9/prometheus/src/pipeline.spec.ts) is the honest
worked example, because it exercises the real composition rather than a
narration. An AtlasStore is seeded with one grounded STEM fact bound to the
real Kalika cosmology kernel (kalika:cosmology#ageTodayGyr, pinned to
Planck-2018) and a cosmology-basics prerequisite. The forge runs with
seed: 1234, a fixed clock, profile class curious-adult, a deterministic
stand-in writer (no live LLM in the test), the real
buildKalikaOrbitExplorable, a retrievalScore of 0.9, and a three-item flow
history. The assertions establish the contract end-to-end:
- A published, gated lesson.
blockedisfalse, all seven gates pass (isV9LessonPublishableis true), and the skeleton holds the recomputed value —groundTruth.computedValuescontains the age between 13.6 and 14.0 Gyr, produced by the Friedmann solver, never stored as the literal "13.8". - A real, reached explorable. The shipped explorable's
kindiscomputed-kerneland itssuccessState.reachableistrue(the symplectic integrator's energy drift was actually measured under tolerance). - Determinism. Two forges of the same inputs produce identical
skeletonHash,surfaceHash,cacheKey, and artifactid. - The cost lever. A second forge against the same cache returns
servedFromCache: truewith the same lesson id — gated once per profile class, served many times. - The block path. When the injected Sekhmet seam denies the content, G6
fails,
blockedistrue,blockedGateIdscontainsG6, theartifactis undefined, and the cache holds nothing — a blocked lesson is never cached. - Fail-loud. With
writer: undefined, the forge rejects withLessonWriterNotConfiguredErrorinstead of fabricating prose.
Failure modes, configuration, and determinism#
The forge is built to refuse rather than fabricate, and the refusals are
specific and code-located: an unresolvable wonder throws WonderUnresolvedError
(wonder-resolution.ts:56); nothing to ground throws "refusing to forge an
ungrounded lesson" (ground-truth.ts:86); a writer that cites a claim outside
range throws (write.ts:87); an unreproducible number blocks G2
(accuracy-gate.ts:66); an unreachable explorable blocks G4
(explorable-runtime.ts:33); any gate failure blocks the whole lesson with no
compile and no cache (pipeline.ts:232); and a contract/gate disagreement at
the finish line throws defensively (pipeline.ts:257).
Determinism is both a provenance and a cost lever, and it rests on three
explicit choices in ForgeLessonInput: a seed, a caller-supplied nowUnixMs
and signedAtIso (no clock is read inside the forge), and a profile-class
cache key rather than a learner id. Numeric tolerances are explicit rather than
implied — G2 defaults to a 1e-3 relative match while each V9KernelResult
carries its own 1e-6 tolerance (lesson.ts:51) — which is what makes "computed,
not asserted" a checkable property and not a slogan. Everything that could vary
by environment — the writer, the embedder, the quality judge, the safety policy,
the ledger, and the cache — is an injected boundary, so a forge is reproducible
exactly to the extent its caller wires deterministic seams.
Related#
- Section hub: ../V9_ARCHITECTURE.md; orientation in ./overview.md
- ./atlas-knowledge-graph.md — Stage 0 resolution and the knowledge spine
- ./hephaestus-explorables.md — Stage 5 and the G4 computed-kernel DoD
- ./seven-gates-and-aletheia.md — Stage 7 gate semantics and the two gate framings
- ./lesson-artifact.md — the Stage 8 delivery contract
- ./delivery-and-cross-cutting.md — Stage 9 delivery, governance, determinism, cost
- ./subsystem-map-and-reuse-ledger.md and ./six-layer-reuse-stack.md — the reuse accounting