These three features are V9's "Phase-2 delight & depth" layer
(V9_ARCHITECTURE.md §3 P2): the part that turns a correct, grounded lesson
into something a learner wants — an experience with an emotional shape, a way
for creators to author and share their own journeys, and a watch-don't-poke
explainer film when the learner would rather sit back. All three live in a
single library, @oshun/v9-theia (libs/v9/theia/src), alongside the
wonder-director itself; the package is named for Theia, the Titaness of sight
and the "wonder director" who orchestrates awe. The library is small and dense —
six source files, one ~9 KB spec — and every function in it composes a real
substrate: the live Atlas graph (@oshun/v9-atlas), the real Mnemosyne mastery
ladder (@mnemosyne/core), and the V9 contract vocabulary (@oshun/contracts).
What it does not do is fabricate the parts it cannot compute: the avatar/face
runtime, the headless widget browser, and the Manim renderer are all expressed
as typed, fail-loud boundaries that a real service plugs into. This is the
feature-side companion to the section hub —
../V9_features.md.
The through-line connecting the braid, the commons, and the films is the same idea Theia exists to serve: a lesson never dead-ends. The emotional arc closes on the next question; Agora lets a learner-turned-creator pin that next question into a publishable journey; and the explainer film is just another shareable social object minted from a verified lesson. Everything here is downstream of the Prometheus lesson forge and the Atlas, and gated by the same seven gates every lesson passes before a learner sees it.
What ships, honestly#
The logic in @oshun/v9-theia is real and tested — all six modules,
exercised by theia.spec.ts (the spec covers thread continuation, the emotional
arc, surprise-me, the widget verifier's ship/block/fail-loud paths, the Manim
self-repair loop, the HITL state machine + budget, Agora authoring + share
objects, and Chiron-full memory + personas). The functions are not CRUD: they
walk the real Atlas edge set, index into the real six-level Dreyfus mastery
ladder, parse outputs through the real V9ExplorableSchema, and compute real
sha256 provenance hashes.
What is boundary / injected (real interface, no production adapter wired in
this package): the HeadlessWidgetRunner that proves a generated widget reaches
its success state, the ManimRenderer that renders the film, and — for
Chiron-full — the embodied face + emotion-recognition runtime (Psyche). For the
Manim renderer specifically, the other half already exists: a genuine 436-line
Python render service at
services/metis/src/metis/media/manim_render_service.py invokes the manim CLI
in a sandboxed subprocess (rlimits, wall-clock timeout, session isolation) and
returns structured {syntax,runtime,timeout,unknown} failures whose data model
"mirrors the TS ManimRenderRequest contract" (manim_render_helpers.py). The
missing piece is the TS↔Python adapter; each half is real, the bridge is not yet
in code.
What is spec / aspirational at this seam: Agora's buildShareableObject
imports nothing from V7 Mawu distribution or Sekhmet safety — it builds
an OpenGraph-ready share descriptor with a templated metis.oshun/share/...
URL; the actual safety-gated publish ride is the design's promise, not this
function's behavior. And critically, no production code imports
@oshun/v9-theia yet — a repo-wide grep for the package turns up only its own
spec. The V9 experience layer ships its own
simpler thread and surprise-me (libs/v9/experience/src/lesson-player.ts reads
a precomputed thread.nextWonders off the lesson artifact;
wonder-front-door.ts does an adjacency-based "surprise me"). Theia is the
richer, graph-driven version of those ideas, fully built and tested, awaiting
wiring into the runtime. Where this page says "Theia threads across the Atlas,"
read it as "the tested library does this; the running player does not call it
yet." Honest "built-but-unwired" beats fake "shipped."
The soulful braid — Theia's emotional arc and thread continuation#
The "soulful braid" the design asks for — science set beside the human, awe set
beside understanding — is, at the code level, three small orchestration
functions in theia.ts.
Thread continuation (nextWonders)#
nextWonders(atlas, from, max = 3) answers "what better question does this
concept open?" by walking the real Atlas edge set in a fixed priority order
(theia.ts:17):
const THREAD_EDGE_PRIORITY = ['enables', 'bridges', 'specializes', 'related'];
Of the nine V9ConceptEdgeType values in the contract (prerequisite,
related, part_of, generalizes, specializes, enables, conflicts,
complements, bridges), the thread deliberately uses only four — and they are
the forward ones. It never threads back into a prerequisite (that is
remediation, not a next wonder), never offers a conflicts edge as a thread,
and prioritizes enables (this unlocks that) over bridges (a cross-axis jump)
over specializes over a loose related. The function throws on an unknown
source concept, dedups by target id, and slices to max. The spec pins the
priority behavior precisely: an enables edge to "Age of the universe" beats a
related edge to "Cosmic microwave background," so the Olbers'-paradox thread
proposes the age of the universe first (theia.spec.ts:59).
The bridges edge is where the braid lives structurally. The contract defines
it as "a cross-axis thread, e.g. cosmology ↔ deep-time" (concept-graph.ts:87),
and V9 organizes reality along seven wonder axes — cosmos, laws, mind,
meaning, deep-time, living-world, made-world (primitives.ts:42). A
bridges edge from a cosmos node to a meaning or mind node is the
"science next to the human" juxtaposition, and because bridges sits second in
the thread priority, Theia will surface it. What is not in this package is
the curated content that fills those bridge edges — the meditation session
beside the neuroscience-of-attention thread, the Hathor myth beside the
cosmology lesson, the Nisaba source text beside it. Those are design promises;
the structural seam (the bridge edge + its place in the thread priority) is what
ships today.
The emotional arc (orchestrateEmotionalArc)#
The arc tags a lesson's narrative beats with one of four emotions —
awe → curiosity → understanding → anticipation — by pattern (theia.ts:63):
the opening beat (or any /hook/i) is awe, a /why it matters|connect/i
beat is understanding, a /next question|the next/i beat is
anticipation, the last beat defaults to anticipation, and everything between
is curiosity.
This looks like a toy until you read what produces the beats. The Prometheus
planner emits exactly this phrasing (libs/v9/prometheus/src/plan.ts):
const beats = [
`Hook: ${input.wonder}`,
...claims.map((c, i) => `Establish[${i}]: ${c.text}`),
'Why it matters: connect the established facts back to the wonder.',
'The next question: open the thread to the next, better wonder.',
];
The arc's regexes are tuned to the forge's beat vocabulary: Hook: → awe,
Why it matters: connect → understanding, The next question: → anticipation.
So even though @oshun/v9-theia does not yet import the planner, the two were
written to compose — the arc is designed to run over a real Prometheus lesson
plan, opening on awe and closing on the next question. (The shared default
persona chiron:warm-generalist is the same constant on both sides — plan.ts
and Agora's toPrometheusDirectives — another deliberate alignment.)
Surprise me (surpriseMe)#
surpriseMe(atlas, masteryMap, max = 1) finds "a wonder you didn't know you
had, from the frontier of what you almost know." For every concept the learner
has not mastered but which has at least one prerequisite, it computes
readiness = masteredPrereqs / totalPrereqs, keeps the ones with
0 < readiness ≤ 1, sorts descending, and returns the top max. "Mastered"
here means the learner's level is ≥ intermediate —
MASTERED_FLOOR = MASTERY_LEVELS.indexOf('intermediate') (index 2 of the
six-level Dreyfus ladder
novice, beginner, intermediate, advanced, expert, master,
libs/mnemosyne/core/src/types.ts:154). The prerequisite set comes from the
real Atlas, which delegates closure to the Mnemosyne KnowledgeGraph rather
than reimplementing it (atlas-store.ts:146). The spec drives a learner who has
mastered "Light" toward "Olbers' paradox" at readiness === 1 — every
prerequisite satisfied, the highest-readiness unexplored frontier
(theia.spec.ts:75).
The Agora commons — author, then share#
Agora (agora.ts) is the creator loop: a learner or educator steers the forge
to author a guided journey, and the result becomes a shareable social object —
the free-tier growth lever the product analysis calls for.
Authoring a journey (GuidedJourneySpec → directives)#
A creator's choices are a GuidedJourneySpec:
{ creatorId, topic, tone, depth, audience }, where
tone ∈ {playful, rigorous, poetic, socratic},
depth ∈ {intro, standard, deep}, and
audience ∈ {kids, teens, adults, experts}. validateJourneySpec enforces two
real rules: a topic under three trimmed characters is rejected, and deep
depth for a kids audience is refused — a small but genuine
age-appropriateness guard at authoring time, before anything reaches the forge.
toPrometheusDirectives maps the authoring intent onto forge directives:
| Depth | maxConcepts |
targetSuccess |
|---|---|---|
intro |
3 | 0.80 |
standard |
6 | 0.75 |
deep |
12 | 0.70 |
The targetSuccess is a flow-band target, and note the direction: a deeper
journey aims at a lower predicted success rate (0.70), i.e. it is allowed to
be harder — that is the difficulty-in-the-flow-channel idea expressed as a
number. The personaHint maps tone to a Chiron persona ref (chiron:playful,
chiron:rigorous, chiron:poetic), with socratic collapsing to the warm
generalist (chiron:warm-generalist). Be precise about what this is: the
emitted PrometheusDirectives
({ topic, targetSuccess, maxConcepts, personaHint }) is not the same shape
as the forge's LessonPlanInput ({ wonder, conceptSet, groundTruth, ... }).
It is an authoring-intent object — a structural seam that a forge front-door
would consume to drive planning and ground-truth assembly — not a literal call
into planLesson. See the
Prometheus lesson forge for what the directives
would steer.
The shareable object (buildShareableObject)#
buildShareableObject mints a ShareableObject for either kind of social
artifact — explorable or explainer-film — carrying
{ kind, lessonId, conceptId, title, url, ogDescription }. The url is a
deterministic https://metis.oshun/share/<kind>/<encoded-lessonId> and the
ogDescription is a templated OpenGraph card line ("Explore … — a grounded,
interactive … from Metis"). This is honestly a descriptor builder: the
function produces the metadata an OG card or a deep link needs, and nothing
more. The module header describes publishing as riding "V7 Mawu distribution +
Sekhmet (the injected boundary)," but the code imports neither — the safety
review and the distribution ride are the design's promise, layered on by
governance and boundaries, not behavior in
this function.
On-demand explainer films — the Manim self-repair driver#
manim.ts is the precise-STEM explainer-film driver: a NotebookLM-style video
overview, but computed-correct, because it renders only from a verified
Kalika derivation, never from prose.
renderExplainerFilm(request, renderer?, options) takes a ManimRenderRequest
({ conceptId, title, derivation: string[] }) and:
- Fails loud with
ManimNotConfiguredErrorif no renderer is wired — it will not silently no-op. - Refuses an empty derivation — "refusing to render an explainer film from an empty (unverified) derivation." No verified math, no film. This is the anti-fabrication contract at the film boundary.
- Runs a self-repair loop up to
maxAttempts(default 3), passing the 1-basedattemptcount intorenderer.render(request, attempt)so a render service can see how many times it has failed and self-correct — the reliability pattern the 2026 Manim-from-LLM literature requires (V9_SOTA_RESEARCH.md§2). - On success, computes a C2PA content hash —
sha256over[conceptId, derivation, assetRef]— binding the film to the exact verified derivation that produced it, and returns{ rendered: true, film: { assetRef, attempts, c2paContentHash } }. - On exhaustion returns
{ rendered: false, attempts, lastError }— a structured failure, never a thrown crash mid-loop.
The spec exercises all four edges: retry-then-succeed (attempt 2 wins,
calls === 2), give-up-after-maxAttempts, refuse-empty-derivation, and
fail-loud-with-no-renderer (theia.spec.ts:127).
The ManimRenderer is the injected boundary, and its real counterpart already
exists in Python. ManimRenderService (manim_render_service.py) discovers a
manim binary (via PATH or the repo-local services/metis/.venv-manim), builds
a manim render argv (build_render_command), runs it in a forked subprocess
with CPU and address-space rlimits and a wall-clock ceiling
(with_timeout_ceiling), classifies any non-success into a structured
RenderError of kind syntax | runtime | timeout | unknown, and locates the
produced video artifact (locate_video_artifact) — even treating "returncode 0
but no artifact" as a failure ("the render lied about success"). The helpers
module states outright that RenderJob "mirrors the TS ManimRenderRequest
contract," so the two halves were co-designed. What is missing is the adapter
that implements the TS ManimRenderer interface by calling this service over
HTTP or subprocess; until it exists, renderExplainerFilm is real, the Python
renderer is real, but the end-to-end TS render is unwired.
A word on C2PA: the hash computed here is real and is the determinism/provenance
binding (gate G7) a C2PA manifest would carry, but this driver does not
sign a manifest — that cryptographic step is the V3 C2PA remainder. The
explorable provenance contract makes the distinction explicit: c2paSigned
defaults to false (explorable.ts:95) and only flips true once a real signer
runs.
Generative widgets — the same discipline, for ideas without a kernel#
For concepts with no computed kernel, Prometheus can generate a runnable web
widget; generative-widgets.ts is the verifier that decides whether it may
ship. verifyGenerativeWidget(spec, runner?) fails loud without a
HeadlessWidgetRunner, then runs the widget headlessly and blocks it unless
it both compiles and reaches its declared success state. Only on a
demonstrated success does it parse a real V9Explorable through
V9ExplorableSchema with kind: 'generative-widget',
successState.reachable: true (plus the runner's evidence string), a grounding
pin (sourceId: 'iris:widget-gen', credibility: 0.6), and a provenance block
(contentHash = sha256(code), c2paSigned: false). This is the contract's
bright line at work: reachable "is set true only after the success state was
actually demonstrated … never asserted blind" (explorable.ts:73), and
isV9ExplorableShippable returns exactly successState.reachable. A
generated-but-unverified widget never ships — and the HeadlessWidgetRunner has
no production implementation anywhere yet, so this verification logic is real
and tested but not yet running against a real browser. The explorable runtime
that hosts the shipped widget lives next door in
Chiron and Hephaestus.
Mid-pipeline control: HITL and the per-step budget#
hitl.ts is the human-in-the-loop control plane the forge runs under.
HitlSession is a real state machine over
running | paused | redirected | resumed | failed | recovered: you may pause
only from running/resumed; redirect(direction) only from paused and only
with a non-empty direction (this is regenerate-with-direction); resume from
paused/redirected; and recover only from failed, where
checkpoint-restore returns the latest HitlCheckpoint and replan returns
null (start the stage fresh). Illegal transitions throw rather than silently
passing. enforceStepBudget(spent, stepCap, requested) is the cost guard: it
rejects a negative request, allows a step only if spent + requested ≤ stepCap,
and reports the remaining budget. Together these are the seam the platform
Yemaya HITL fix plugs into — a pipeline that can be paused, steered, resumed,
budget-capped, and recovered from a checkpoint mid-flight.
Chiron-full: cross-session memory and grounded historical personas#
chiron-full.ts is the glue that complements the base Chiron persona library
(@oshun/v9-chiron: getChironPersona, integrity modes, delivery). It does two
things, both pure logic.
Cross-session memory. buildSessionMemory(traces) partitions the learner's
concept traces into struggledConcepts (mastery ≤ beginner) and
masteredConcepts (mastery ≥ advanced) — note these floors differ from
surprise-me's intermediate floor, because "open the session on it" and "ready
for the frontier" are different bars. chironOpeningLine(memory) then opens a
returning learner on what was tricky last time ("Last time, Tensor calculus
was tricky — want to revisit it before we go further?"), or acknowledges
progress, or falls back to a warm "What are you wondering about today?". This is
the Mnemosyne trace projected into Chiron's opening turn.
Grounded historical personas. buildHistoricalPersona enforces the
anti-fabrication and consent rules for "Chiron as a historical figure." It
throws UngroundedPersonaError if there is no Nisaba source pin (no
invented personal claims — the persona may say nothing the sources don't
ground), always attaches a reconstructionLabel ("Reconstruction of X,
bounded by historical sources — not the real person."), and refuses a
living-voice persona without a consent record (the V3 voice-clone registry /
Sekhmet gate). The embodied face and emotion recognition (Psyche) is the
provider-gated runtime remainder; this module ships the memory and
persona-safety logic only. The full mentor surface — voice, face, integrity
modes, Socratic dialogue — is documented in
Chiron and Hephaestus.
How it fits together#
The diagram below traces a creator's authoring choice through the forge and out to the two shareable artifacts, marking which seams are real-and-tested (solid) and which are injected boundaries (dashed):
The solid edges are the tested logic in @oshun/v9-theia; the dashed edges are
the three boundaries — the headless widget runner, the Manim render service
(real, but unbridged), and the Mawu/Sekhmet publish ride — that a running V9
supplies.
Related#
- Overview and the section hub ../V9_features.md
- Subsystem map and the seven gates — where G4 (solvability), G5 (delight), and G7 (provenance) bite on widgets and films
- Atlas and wonder resolution — the graph
nextWonders/surpriseMewalk, and thebridgesedge behind the braid - Prometheus lesson forge — what Agora's directives steer and the beats the emotional arc runs over
- Chiron and Hephaestus — the embodied mentor and the explorable runtime hosting verified widgets
- Threads and the mastery loop — the experience layer's own thread/surprise, and where Theia's graph-driven version would wire
- Governance and boundaries — Sekhmet safety, the V3 C2PA signer, and the voice-clone consent registry