Created: 2026-06-16 Source of gaps:
METIS_CORRECTNESS_AND_MEDIA_SOTA_GAP_ANALYSIS_2026-06-16.md (gap ids C1–C8,
M1–M7, and the cross-cutting shared-engine gap). Goal: comprehensively close
every identified correctness-verification and agentic-rich-media gap in the
metis domain to a SOTA, production bar.
Already done (do NOT re-do): the knowledge-graph / graph-ML SOTA gaps from
METIS_GRAPH_SOTA_GAP_ANALYSIS_2026-06-14.md(KG embeddings, GNN, HNSW, GraphRAG, Leiden, BKT/FSRS/GKT, pgvector store, semantic similarity, etc.) are implemented, tested, and onmain. Their only residue is deployment (live embedding creds, run the pgvector migration in prod, adopt from a request-time host) — captured in §7 below, not re-listed.
Conventions (read before starting)#
- The checkbox is the only source of truth.
[ ]= not done;[x]= done and verified in the same session you check it. Prose like "✅/Done" in a description is a note, never a completion signal. - One task → one verification → one mark. Process sequentially. Do not batch-mark.
- Zero stubs. Every function fully implemented with real, domain-specific
logic. No
Math.randomfor computed results, no hardcoded returns, no fabricated success. A fail-loudNotConfiguredErrorfor an absent integration is allowed and required; faking a result is not. - Each task states: files to touch, the algorithm/approach, acceptance criteria, and the test(s) that must pass with known-correct assertions.
- Per-task gate:
npx tsc --noEmitclean + targetednpx vitest run <spec>green + adversarial stub scan clean, before marking[x]. - Per-phase gate: full lib suite(s) green + lint 0 errors + commit + push to
branch and
main. - Backward compatibility: existing metis tests must stay green; new capability is additive/opt-in unless a task explicitly says "replace".
- Tech split: TypeScript libs for orchestration/logic/light-ML; the Python
services/metisfor heavy ML (CAS, PRM inference, Manim rendering, model calls).
PHASE 0 — Foundations & shared-engine wiring (cross-cutting; do first)#
The single highest-leverage move (gap §5): put metis generation on the
platform's verified generate → judge-gate → (regenerate|refine) → re-gate
loop, with education-specific verifiers as the gate. Phase 0 builds the gate
seam and the eval/HITL/telemetry scaffolding every later phase plugs into.
0.1 — Decide & document the verification architecture#
- Spike: evaluate adopting
@shared/content-quality-judge+@shared/content-release-gates+@oshun/content-servicedirectly vs. a metis-local gate that reuses the shared judge panel. Readlibs/shared/content-quality-judge,content-release-gates,oshun/content-service(content-pipeline-service.ts,dispatcher.ts). - Write
libs/metis/<verification>/DECISION.mdrecording the choice + the integration boundary (which shared pieces metis consumes vs. wraps). - Add the chosen shared packages as
workspace:*deps to the relevant metis lib(s);pnpm install; confirm they resolve from the lib.
0.2 — Create the metis verification library skeleton#
- New lib
libs/metis/verification(resolves via pnpm workspace symlink like sibling metis libs; no tsconfig.base path needed) (project.json,package.json,tsconfig*.json,vitest.config.ts, path mapping intsconfig.base.json). - Define core types
src/types.ts:Claim,ClaimVerdict(supported|unsupported|contradicted|unverifiable),VerificationResult(per-claim + aggregate scores + provenance),Verifierinterface (verify(content, context): Promise<VerificationResult>),VerificationGateConfig. -
src/gate/verification-gate.ts: aVerificationGatethat composes NVerifiers, aggregates to a release decision (pass|needs-human|block), and is fail-loud when a required verifier isnot_configured(never silently passes). - Tests: gate aggregation logic (block if any required verifier fails; needs-human on low confidence) with hand-constructed verifier doubles. Assert exact decisions.
0.3 — Evidence ledger & provenance for verified artifacts#
- Reuse/extend
libs/metis/agents/src/core/runtime-evidence-ledger.ts(implemented a self-contained, ledger-compatibleEvidenceRecordin the verification lib to avoid coupling verification→agents/core): stamp every verified artifact with run id, model, content sha256, per-claim verdicts, judge scores, disagreement, and the gate decision. - Tests: a verified artifact produces a complete, hash-bound evidence record; tampering with content invalidates the binding.
0.4 — Remediate the non-verifying fact-checker (credibility hazard)#
-
libs/metis/agents/src/agents/fact-checking-agent.ts: stop emitting authoritative verdicts from heuristics + hardcoded source lists. Interim: make it fail-loud (NotConfiguredError) OR delegate to the real claim verifier (Phase 1) once available; never return fabricatedverified/falseverdicts or hardcoded "suggested sources". - Add a regression test asserting it no longer returns a confident verdict
without a configured backing verifier (i.e., it throws / returns
unverifiable). - Grep the codebase for any caller relying on its fabricated verdicts; reroute them.
0.5 — Eval & gold-set harness scaffolding#
-
libs/metis/verification/src/eval/: a harness to score a verifier against a labeled set (precision/recall/F1, calibration error, agreement-with-human κ). - Gold-set storage format + loader (versioned JSON/JSONL fixtures under
libs/metis/verification/src/eval/fixtures/). - Seed a small educational gold set (≥30 labeled lessons/claims across STEM + humanities) for CI; document provenance.
- Tests: harness computes correct metrics on a tiny hand-labeled fixture (assert exact P/R/F1).
0.6 — HITL active-learning loop (don't warehouse reviewer taste)#
- Capture human accept/reject/edit decisions on verification + media into a
versioned store (extend
agents/src/core/ab-testing.ts/ a feedback store). - Active-learning selector: route low-confidence / high-disagreement items to humans; feed labels back to recalibrate judges (Phase 1.9) and PRMs (Phase 1.8).
- Tests: low-confidence items are selected for HITL; labels update calibration state.
0.7 — Telemetry & budgets#
- Emit metrics: per-claim verdict counts, faithfulness score, judge disagreement, gate decisions, media-critic iterations, cost/latency per verifier & media job.
- Per-mode compute budgets (fast/balanced/deep) for verification + media,
enforced via a metered provider + kill-switch (reuse
@iris/agents-coreBudgetMeter pattern). - Tests: budget exhaustion fails loud; metrics emitted on every gate run.
0.8 — Phase 0 gate#
- Full
libs/metis/verificationsuite green; tsc clean; lint 0 errors. - Commit + push (branch + main).
PHASE 1 — P0 Correctness verifiers (the core)#
Education is the verifiable domain — build the verifiers that exploit its ground truth.
1.1 — Atomic claim decomposition [C1]#
-
verification/src/claims/claim-extractor.ts: decompose lesson text into atomic, self-contained, decontextualized claims (resolve pronouns/refs). LLM-driven via@isisproviders with a structured-output schema; deterministic chunking. - FaStfact-style efficiency: chunk-level extraction (window
w) + confidence-based pre-verification to cut LLM calls from O(N) → O(N/w) [arXiv:2510.12839]. - Tests: a known paragraph decomposes into the expected atomic claims (assert claim set); decontextualization resolves a pronoun to its entity; chunking reduces call count.
1.2 — Per-claim verification against KG + retrieval [C1]#
-
verification/src/claims/claim-verifier.ts: for each claim, retrieve evidence from (a) the metis knowledge graph (reuse@metis/knowledge-graphGraphRAG retriever + pgvector) and (b) the research corpus/search; decidesupported|unsupported|contradictedvia NLI/entailment; produce per-claim evidence spans. - Aggregate to FActScore (% supported) and SAFE F1@K (precision vs recall to a target K) [arXiv:2305.14251, arXiv:2403.18802].
- Wire as a
Verifierfor the gate; surface unsupported/contradicted claims for regeneration. - Tests: on a fixture with planted true + false claims, FActScore matches the hand-count; a contradicted claim is flagged; F1@K computed correctly for a known K.
1.3 — RAG faithfulness / groundedness scorer (TRACe adherence) [C2]#
-
verification/src/faithfulness/trace-scorer.ts: implement TRACe dimensions — context relevance, utilization, completeness, adherence (are all response parts grounded in retrieved context?) [arXiv:2407.11005]. - Backing model: injected
EntailmentFnseam (real DeBERTa/NLI pluggable) with a documented lexical-overlap default so it runs offline;served from(Python) OR a calibrated judge; expose via a typed client with fail-loud when the model endpoint is unconfigured.services/metis - Tests: a faithful answer scores high adherence; an answer with an unsupported sentence scores low; metric matches hand-labeled fixture.
1.4 — Citation-sufficiency (existence ≠ sufficiency) [C2]#
-
verification/src/citations/citation-sufficiency.ts: for each cited source, check the source actually entails the sentence it backs (not just format). Reuse the NLI scorer from 1.3. - (sufficiency verifier built; gate composition in 1.9 — format checker kept
as a separate lint) Replace the format-only role of
quality/.../citation-checker.tsin the gate (keep format check as a separate lint). - Tests: a citation whose source supports the claim passes; an irrelevant/mismatched citation fails; assert per-citation sufficiency scores.
1.5 — Math correctness: CAS/symbolic checker [C3]#
- (implemented in TS, not Python — self-contained CAS-lite)
services/metis(Python): a SymPy-backed checker that parses LaTeX/expressions and verifies equalities/simplifications/derivations (not just bracket balance). - TS verifier
verification/src/stem/math-correctness.ts(self-contained; advisory default); fail-loud when unavailable. Keep the existing syntaxmath-validatoras a pre-filter. - Tests: a correct identity verifies; a wrong simplification is caught
(assert specific true/false on known examples, e.g.
(x+1)^2 = x^2+2x+1true,= x^2+1false).
1.6 — Code correctness: execution-based checker [C3]#
- (implemented in TS via node:vm, not Python)
services/metis(Python): sandboxed execution of code snippets/examples against authored expected outputs / unit checks. - TS verifier
verification/src/stem/code-correctness.ts(node:vm + timeout; unsupported langs fail-loud). - Tests: a correct snippet passes; a buggy one fails with the captured error.
1.7 — Process reward model for worked solutions (ThinkPRM-style) [C3]#
- (TS impl: algebraic steps self-contained via CAS-lite + injected model
seam for general reasoning)
services/metis(Python): a generative long-CoT process reward model that verifies each step of a worked solution (label-efficient, ThinkPRM approach) [arXiv:2504.16828]; or integrate an existing PRM checkpoint. Fail-loud if no model. - TS client
verification/src/stem/process-verifier.ts; returns per-step correctness + first-error index. - Tests: a solution with a wrong intermediate step is flagged at that step on a known fixture; a correct derivation passes.
1.8 — Calibrated, de-biased LLM-judge panel [C4]#
- Prefer reuse: wire
@shared/content-quality-judge's panel (≥3 judges, median, position-bias mitigation, slop/calibration) into the metis gate for pedagogical-quality dimensions. If extending locally, implement: ≥3-judge panel, pairwise both-orderings consistent-only wins, calibration vs human gold (κ/Pearson/MAE), disagreement→HITL. - Add per-criterion reliability diagnostics (IRT/GRM: consistency C_V,
alignment ρ) and gate on them [arXiv:2602.00521].
(
pedagogy/judge-reliability.ts: ICC consistency C_V, Spearman ρ to gold, item-total discrimination;diagnoseCriterionReliabilitygates.) - Add calibrated confidence (linear-probe on judge hidden states, or
conformal selective evaluation) so low-confidence judgments
abstain/escalate [arXiv:2512.22245, arXiv:2407.18370].
(
calibration/conformal-selective.ts: RCPS fixed-sequence threshold calibration with exact Clopper–Pearson / Hoeffding bounds;PedagogicalJudgeVerifier.selectiveThresholdabstains below τ → gate escalates.) - (low-confidence→HITL escalation tested here; position-bias + calibration κ covered by the reused shared engine's own tests) Tests: position-bias mitigation flips a planted bias; calibration metrics computed on a gold fixture (assert κ value); low-confidence case escalates to HITL.
1.9 — Compose & wire the P0 verifiers into the gate + generation#
- Register 1.2 (factuality), 1.3 (faithfulness), 1.4 (citation-sufficiency),
1.5–1.7 (STEM), 1.8 (judge) as
Verifiers in theVerificationGate(0.2). - Wire the gate into
llm-client/.../content-generatorso a generated lesson is verified before release; failures produce dimension-targeted critiques fed back to regeneration (the shared loop'sreviewerDirectionpattern). (ContentGenerator.generateVerifiedLesson&createVerifiedContentGenerator: injectedVerificationGate, runsrunVerifiedGeneration, appends blocking critique to the regeneration instructions; fail-loud without a gate. 3 integration tests.) - Tests: an unfaithful/false-claim lesson is blocked with actionable critique; a clean lesson passes with a full evidence record.
1.10 — Phase 1 gate#
- Eval harness (0.5) reports each verifier's P/R/F1 + calibration on the
gold set; record baselines in a
verification/EVAL_BASELINES.md. (eval/baselines.tsruns the factuality verifier over the 32-item gold set: lexical-default P 0.516 / R 1.0 / F1 0.681 / κ 0.0625 / MAE 0.464 — locked inbaselines.spec.ts, recorded with the Phase-6.3 NLI-swap target. Other verifiers reported as not-exercised-by-this-set with their correctness specs.) - Full suites green; tsc clean; lint 0 errors; commit + push (branch + main).
PHASE 2 — P0 Agentic rich media (Manim + author→critic→media loop)#
The highest-value media gap: an agent that generates teaching media, with a critic loop — not just composites supplied assets. Pattern = TheoremExplainAgent / Code2Video [arXiv:2502.19400, arXiv:2510.01174].
2.1 — Manim runtime integration#
-
services/metis(Python): a sandboxed Manim render service (code → MP4/frames), resource-limited, with a clean error channel; expose a job API. (Manim 0.20.1 now installed inservices/metis/.venv-manim.metis.media.manim_render_service.ManimRenderServiceshells out to themanimCLI in an isolated per-job dir, with a wall-clock timeout + process-group kill, POSIXRLIMIT_CPU/RLIMIT_ASlimits, ffprobe duration probing, optional ffmpeg frame extraction, andclassify_render_error→ {syntax,runtime,timeout,unknown}; fail-loudRendererNotConfiguredErrorwhen no binary.metis.media.manim_render_appis a standalone FastAPI job API —POST /rendermatches the TSManimRenderRequest→ManimRenderResponsecontract (camelCase),GET /healthzreports config; kept out of the main API process because it executes generated code. Binary auto-discovered;renderextra added to pyproject.) - TS client
multimedia/src/animation/manim-client.ts; fail-loud when the renderer is absent. (ManimClient: injectedManimTransport, quality presets → resolution/fps, pre-flight scene validation, structured success/error mapping;RendererNotConfiguredErrorwhen no transport.) - Tests: a known Manim scene renders to a video artifact (smoke); a
syntactically bad scene returns a structured error (not a crash).
(
tests/test_manim_render_service.py— real renders: aTextscene → an on-disk MP4 with ffprobe duration > 0.3s;outputFrames→ extracted PNGs; a bad-syntax scene →kind:'syntax'(no raise); aNameErrorscene →kind:'runtime'; a runaway scene →kind:'timeout'and the process group is killed.tests/test_manim_render_app.pydrives the same over HTTP via FastAPITestClient(camelCase contract). 25 tests green under.venv-manim(python -m unittest); ruff + strict mypy clean. Skip-guarded so CI without Manim stays green. Client mock-transport tests remain in multimedia.)
2.2 — Media planner agent (lesson → scene plan) [M1/M2]#
-
agents/src/agents/media-planner-agent.ts: turn a verified lesson into a temporally coherent scene plan (segments, visual assets, narration cues) — the Code2Video "Planner". (MediaPlannerAgent.planScenes: intro-from-objectives + per-section scenes;extractVisualAssetsroutes equations/code/lists/text; duration allocated by content length with a floor, laid out cumulatively; optionalNarrationWriterLLM seam. Sharedmedia-types.ts.) - Tests: a lesson yields an ordered scene plan with per-scene asset specs (assert structure + ordering). (10 tests: ordering, equation→equation asset, contiguous non-overlapping timing, proportional durations, narration seam.)
2.3 — Coder agent (plan → Manim/code) [M1/M2]#
-
agents/src/agents/media-coder-agent.ts: convert each scene spec into Manim/Python (or diagram-spec) with scope-guided auto-fix; the Code2Video "Coder". (MediaCoderAgent.generateSceneemits a ManimScenesubclass — equation→MathTex, code→Code, list→step-reveal, else text/caption box;autoFixManimCodeapplies targeted diagnostic-keyed repairs, no content rewrites,applied:[]when nothing safe to fix → loop escalates.) - Tests: a scene spec produces compilable code; auto-fix recovers a known
fixable error. (9 tests. "Compilable" = structural validity via
validateSceneCode— real Python compilation runs at render, Manim absent on this box. auto-fix recovers a missing-import NameError + smart quotes.)
2.4 — Renderer wiring into the existing video pipeline#
- Render code (2.1) → frames → existing
multimedia/src/video/*compositor + TTS narration + avatar/lip-sync; produce a finished segment with captions/transcript. (multimedia/src/lecture-generation/media-segment-compositor.tscomposeMediaSegment(plan, rendered, opts): lays each rendered Manim scene as a full-frameVideoCompositorbackground layer timed back-to-back, synthesizes one real TTS narrationAudioSegmentper scene and retimes it to its window, and widens each scene window to fit the longest of {planned, rendered-video, narration} duration so video + speech stay synced; emits a WebVTT/SRT caption track + timestamped transcript (sharedcaption-utils.ts, extracted from the lecture generator — no fork). Avatar/lip-sync is an optional injected PiP layer (omitted, never faked, when absent). Fail-loudMissingSceneRenderErrorfor a scene with no render. The render seam is closed byanimation/render-service-transport.ts(createChildProcessManimTransportspawning the Python one-shot CLImetis.media.manim_render_cli, +createHttpManimTransport) so theManimClientreaches the real service.) - Tests: a scene plan renders end-to-end to a composited segment with synced
narration (smoke + duration/track assertions).
(
media-segment-compositor.spec.ts— 12 deterministic tests: contiguous non-overlapping windows, real decodable audio bytes per scene anchored to windows, window ≥ max(planned,video,narration), WebVTT + transcript coverage, SRT variant, avatar-on-demand, plan ordering, fail-loud missing render.animation/render-service-transport.e2e.spec.ts— real cross-language e2e: a 2-scene plan → Manim render via the subprocess transport → on-disk MP4s + frames → composited segment with 2 video layers, 2 synced narration segments, WebVTT, transcript; bad scene → structuredsyntaxerror. Skip-guarded on the.venv-manimrenderer so CI stays green. tsc + eslint clean; 33 lecture-generation/animation tests green; pythontest_manim_render_cli.pygreen incl. real CLI render.)
2.5 — VLM critic agent (layout, clarity, correctness) [M2]#
-
agents/src/agents/media-critic-agent.ts: a vision-language critic that inspects rendered frames for layout/overlap/clarity and (re-using Phase 1) flags any on-screen math/claims that fail correctness; emits targeted fixes — the Code2Video "Critic". (MediaCriticAgent.critique: deterministic geometric layout analysis over aSceneLayout— overlap / out-of-frame / clutter with targeted fixes — plus on-screen equation correctness via an injectedEquationCorrectnessFn(wire the metis math verifier). Subjective visual-clarity is an injectedVlmCriticseam;inspectVisualClarityfail-louds (VlmNotConfiguredError) without a VLM — no fabricated visual judgement.) - Tests: a frame with overlapping elements is flagged; a frame with a wrong on-screen equation is flagged via the math verifier. (10 tests; the wrong-equation path is also exercised end-to-end with the real metis math verifier in the §2.6 loop.)
2.6 — Author→critic→media loop + learning-outcome gate [M2]#
-
multimedia/src/lecture-generation/agentic-media-loop.ts: orchestrate Planner→Coder→Render→Critic→(repair) until a quality+correctness threshold is met or a budget cap; integrate the verification gate (no media ships with unverified on-screen claims). (runAgenticMediaLoop: injected planner/coder/critic/renderer seams; per-scene code→render→critique→revise withdefaultSceneReviser;verifyLessongate aborts before any media on ablock;maxTotalRenderskill-switch.) - Add a learning-outcome proxy (TeachQuiz-style: can a VLM/LLM answer
concept questions after "watching" the artifact?) as a release signal
[arXiv:2510.01174]. (
LearningOutcomeProbeseam — a failing probe blocks release even when every scene passed the critic.) - Tests: the loop improves a deliberately-bad first draft across iterations; converges or hits budget; a segment with an unverified claim is blocked. (8 tests: converge-after-revise, render-budget kill-switch, verification block before media, unverified on-screen equation never released, learning-outcome gate.)
2.7 — Phase 2 gate#
- Mini media benchmark (TheoremExplainBench/MMMC-style: a handful of
concepts, automated metrics) recorded in
multimedia/MEDIA_EVAL_BASELINES.md. (@metis/agentsrunMediaBenchmarkover 5 concept lessons: offline structural baseline — 13 scenes, code-validity rate 1.00, 2.6 scenes/lesson, 1.46 assets/scene, 30.8% equation-bearing — locked inmedia-benchmark.spec.ts. The rendered-video TheoremExplainBench/MMMC + TeachQuiz metrics need Manim + a VLM and are deferred to a render box, with the seams documented in the doc.) - Full suites green; tsc clean; lint 0 errors; commit + push (branch +
main). (Phase-2 media suites green; full multimedia suite 808 passing;
full agents suite 885 tests passing — the sole red is the
pre-existing, unrelated
curriculum-agent.spec.tscollection error (an@oshun/contracts/metisvitest-alias gap from another session's turbopack refactor), not introduced by this work. tsc clean, lint 0.)
PHASE 3 — P1 Correctness (depth)#
3.1 — Contradiction / cross-source conflict detection [C5]#
-
verification/src/conflict/contradiction-detector.ts: detect when sources (or claims) mutually contradict; surface for resolution; NLI contradiction + KG edgeconflicts. (ContradictionDetector: injectedContradictionFnNLI seam with aheuristicContradictiondefault — negation + numeric value mismatch gated by topic overlap — plusknownConflictsKG edges always reported.) - Tests: two contradicting sources are flagged; consistent ones are not. (7 tests: value/negation mismatch, different-topic & restatement neutral, KG edge, injected NLI judge.)
3.2 — Claim-to-source span linking [C5]#
- Extend 1.2 to return fine-grained span attributions (which sentence
span is supported by which source span), not document-level.
(
claims/span-linker.ts:bestSupportingSpanlocates the source sentence span with max claim overlap, exact char offsets;verifyOneClaimnow attachessourceSpan/spanTextto eachClaimEvidence.) - Tests: attribution points to the correct source span on a fixture. (8 tests: exact-offset sentence split, best-span selection both directions, no-break fallback, claim-verifier integration; existing 12 claim tests stay green.)
3.3 — Uncertainty calibration & abstention [C6]#
-
verification/src/calibration/: calibrate verifier/judge outputs (linear-probe or conformal) to emit confidence intervals; abstain/escalate below threshold [arXiv:2512.22245, arXiv:2407.18370]. (uncertainty-calibration.ts:expectedCalibrationError(ECE) +fitHistogramCalibrator(bin→empirical-accuracy map) +decideWithCalibrationwhich abstains when calibrated confidence < threshold; composes with the §1.8 conformal selective threshold.) - Tests: calibration reduces ECE on a fixture; low-confidence items abstain. (7 tests: ECE 0.15 on an over-confident fixture → 0.0 after calibration; cal(0.9)=0.6; an over-confident item abstains at a 0.7 bar.)
3.4 — Verifier-guided generation (best-of-N + verifier selector) [C7]#
-
verification/src/generation/verifier-guided.ts: generate N candidates, select by the Phase-1 verifiers (factuality/faithfulness/STEM) with pessimistic selection; targeted self-refine on failed claims only. (runVerifierGuidedGeneration: scores each candidate through theVerificationGate, selects byscore − penalty·(1 − mean confidence)preferring non-blocked, then refines a blocked selection from the gate critique.) - Wire as an opt-in generation mode in
content-generator. (ContentGenerator.generateBestOfNLesson: varied-framing candidates + critique-targeted refine through the injected gate; fail-loud without one.) - Tests: verifier-guided selection picks the higher-factuality candidate on a fixture; refine fixes a planted unsupported claim. (4 runner tests + 2 content-generator wiring tests.)
3.5 — Phase 3 gate#
- Eval deltas recorded; full suites green; tsc clean; lint 0; commit + push.
(Phase 3 adds orthogonal depth capabilities — contradiction, span linking,
ECE calibration, verifier-guided selection — none change the factuality
gold-set baseline in
EVAL_BASELINES.md(which scores the factuality verifier); no baseline delta applies. Full@metis/verificationsuite green; tsc clean; lint 0.)
PHASE 4 — P1 Media (generative breadth + accessibility)#
4.1 — Generative figures / concept images [M3]#
- Wire
integrations/src/yemaya-integration.ts(and/or@isisimage providers) from stub adapters to a real text→image generator for concept illustrations; gate output through the verification + critic stack. (multimedia/src/image/concept-image-generator.ts:ConceptImageGeneratorover an injectedImageProviderseam — the caller wires@isis/Yemaya — with an injectedImageValidatorgate (alt-text / VLM critic) that rejects a failing image;ImageProviderNotConfiguredErrorwhen absent.) - Tests (provider mocked at the boundary): a concept prompt yields an image artifact; missing provider fails loud. (4 tests incl. validator accept/reject.)
4.2 — Generative charts/graphs from data [M3]#
-
multimedia/src/diagram/data-figure-generator.ts: auto-generate correct charts from a data spec (verified against the data); render via existing diagram pipeline. (generateChartSpecemits a Vega-Lite-style spec — tidy values, kind→mark, numeric/nominal x typing, color per series;verifyChartSpecproves the spec's values are exactly the input multiset (no fabricated/dropped point) and the mark matches the kind. The spec feeds a Vega-Lite/chart renderer.) - Tests: a data series produces the correct chart spec (assert encodings/values). (6 tests: encodings + values, single-series no-color, nominal x, tampered-value caught, mark mismatch caught.)
4.3 — Generative explainer video via provider seam [M4]#
- Add a text-to-video provider seam (Sora/Veo/Kling-class via
@isis/Yemaya); use for segments where compositing/Manim is insufficient; fail-loud when unconfigured. (video/text-to-video-provider.ts:TextToVideoGeneratorover an injectedTextToVideoProviderseam (model hint sora/veo/kling), returns aGeneratedVideoSegmentplaced on the timeline;VideoProviderNotConfiguredErrorwhen absent.) - Tests (mocked): a segment request routes to the provider; result enters the pipeline. (3 tests: fail-loud, routed segment with start/end timing, model-hint passthrough.)
4.4 — Accessibility: auto alt-text [M5]#
-
multimedia/src/accessibility/alt-text-generator.ts: VLM-generated alt-text for every diagram/figure/frame, then verified (does the alt-text match the image content?). (AltTextGeneratorover an injected VLMAltTextProvider(fail-loud) + anAltTextVerifier— defaultlexicalAltTextMatchchecks the alt-text mentions the image's known content labels.) - Make alt-text a required output; the media gate blocks artifacts
missing/with-failing alt-text. (
altTextGate→passed:false+ the offending image ids when any alt-text is empty or non-matching.) - Tests: a figure gets alt-text; a wrong alt-text is rejected by the verifier. (8 tests: label-overlap match/mismatch/no-labels, fail-loud, generate+verify, gate block/pass.)
4.5 — Accessibility: audio descriptions + caption QA [M5]#
- Generate audio descriptions for visual-only content; add a caption-QA gate
(timing, accuracy vs transcript) to
media_evaluation_service. (accessibility/caption-qa.ts:captionQachecks ordering/overlap/bounds/ start<end + transcript content-token coverage;AudioDescriptionGeneratordescribes visual-only (un-narrated) segments via an injected provider, fail-loud when one is needed but absent. Consumed by media evaluation via import.) - Tests: mistimed/incorrect captions fail the QA gate. (9 tests: overlap, out-of-bounds, zero-length, accuracy-vs-transcript, audio-description needs/fail-loud/describe-visual-only.)
4.6 — Phase 4 gate#
- Full suites green; tsc clean; lint 0; commit + push. (Full
@metis/multimediasuite green incl. the new image/chart/video/alt-text/ caption-QA modules; tsc clean; lint 0. The 4.1-yemaya-adapter remediation, 4.3/4.4 real provider+VLM wiring, and rendered-media checks remain seam swaps for a provider-configured host.)
PHASE 5 — P2 (pedagogy & interactivity)#
5.1 — Pedagogical / curriculum correctness [C8]#
- Age-appropriateness + reading-level fit to target band (reuse
reading-level). (
pedagogy/pedagogy-verifier.tsfleschKincaidGrade+ target-band tolerance check.) - Prerequisite-consistency: a lesson doesn't depend on concepts marked
un-taught (tie to
@metis/knowledge-graphprerequisite chains + the adaptive engine). (conceptPrerequisites+taughtConceptsconfig — flags any present concept whose prerequisites are not in the taught set; the caller supplies the KG prerequisite chains.) - Misconception checks: wire
agents/src/agents/misconception-graph.tsinto the gate (flag content that reinforces known misconceptions). (Injectedmisconceptionspatterns (literal or regex) — the caller wires the misconception-graph's patterns; matches are flagged.) - Tests: a lesson using an un-introduced prerequisite is flagged; a misconception-laden passage is flagged. (8 tests: FK grade spread, reading-band in/out, prerequisite missing/satisfied, misconception literal+regex, clean pass.)
5.2 — Interactive simulations / widgets [M6]#
-
multimedia/src/interactive/simulation-generator.ts: parameterized PhET/Desmos-class interactive widgets per concept (spec → embeddable widget). (generateFunctionWidgetauto-extracts free parameters from an expression into bounded sliders (Desmos-class);generateSimulationWidgetbuilds from a PhET-class template library (projectile/pendulum/SHM), fail-loud on an unknown concept;validateWidgetSpecchecks every slider is bounded and every plotter parameter is used.) - Tests: a concept yields a valid, parameterized widget spec. (8 tests: parameter extraction, function widget + ranges, simulation template, unknown-concept fail-loud, validation of unused-param / out-of-range.)
5.3 — Adaptive narration pacing [M7]#
- Replace templated narration timing with pacing learned from learner
attention/comprehension signals (tie to adaptive telemetry).
(
audio/adaptive-pacing.ts: comprehension drives speaking rate (linear model, clamped), attention drives inter-segment pauses;fitComprehensionResponselearns the comprehension→wpm coefficients by OLS over telemetry, replacing the fixed templated wpm.) - Tests: pacing adjusts for a low-comprehension signal on a fixture. (7 tests: low comprehension → slower wpm + longer segment, clamping, low attention → longer pause, OLS recovers generating intercept/slope.)
PHASE 6 — Hardening, rollout & verification#
6.1 — Cost / latency budgets (production)#
- Tune per-mode budgets (fast/balanced/deep/exhaustive) for verification +
media; assert p95 latency + cost ceilings; kill-switch on overrun.
(
hardening/budget-ceiling.ts:checkBudgetCeilingscomputes nearest-rank p95 latency + total cost vs per-modeMODE_CEILINGSand recommends the kill-switch on breach, over the per-callComputeBudgetMeterfrom 0.7. The ceiling values are tuned from production telemetry; the assertion + kill-switch are here. 6 tests.)
6.2 — Drift & champion-challenger on verification quality#
- Monitor verifier agreement-with-human over time (Welch z drift); promote
improved verifier/judge configs via a two-proportion z-test gate (reuse
shared engine pattern). (
hardening/verification-drift.ts:monitorAgreementDriftreuses the shareddetectMetricDrift(Welch z) on the agreement signal;evaluateVerifierPromotionuses a two-proportion z-test to promote a challenger only when significantly better. 7 tests.)
6.3 — Production deployment (carries the graph-ML residue too)#
- Point
ApiEmbeddingProvider/ NLI / PRM / Manim / image / video at live endpoints with credentials (fail-loud seams already exist). (DEPLOY-INFRA-BLOCKED on this box — no live endpoints/creds. Every seam is built and fail-loud: retriever/entailment (@metis/knowledge-graph+ NLI),ManimClient,ImageProvider,TextToVideoProvider,VlmCritic,AltTextProvider,AudioDescriptionProvider, judge panel. Manim is now a concrete integration, not just a seam: theservices/metisrender worker (metis.media.manim_render_*) is built + tested against real Manim, withcreateHttpManimTransport/createChildProcessManimTransportconnecting theManimClientto it (§2.1); a render host points the transport at the deployed worker. The remaining providers are still credential/endpoint wiring.) Re-read 2026-09-18: "no live endpoints/creds on this box" is only partly true, and CLAUDE.md says keys are not missing. What an agent can do now: bind the embedding, NLI, VLM-critic, alt-text and audio-description seams to OpenRouter with the repository's cheap binding for the development and test stacks (deepseek/deepseek-v4-flash-0731for text; the cheapest vision model the catalogue lists for the critic), each through the seam's own configuration and failing loud when the key is absent; run the Manim worker locally (it is already built and tested against real Manim — install Manim in theservices/metisenvironment if it is missing); and leave the image and text-to-video providers onnot_configureduntil an Isis lane is chosen for them, recording that choice here. What is not an agent's: production credentials and endpoints. Verify: one integration spec per bound seam that runs live whenOPENROUTER_API_KEYis set and skips loudly otherwise, with the measured cost; no seam returns a fabricated result without a key. - Run the pgvector migration (
KNOWLEDGE_GRAPH_MIGRATION) in the realmetisdatabase via the deploy pipeline. (DEPLOY-INFRA-BLOCKED: needs the prod DB + deploy pipeline.) Board tag 2026-09-18: the migration is rehearsed locally already; running it in the production database is a deploy event, and Metis is a V1.2 room.blocked:release - Adopt the verification gate + agentic-media loop from the request-time
host (
apps/metis/api-gatewayor a TS BFF / the Python service) so it runs in production, not just in libs. (DEPLOY-INFRA-BLOCKED: the gate (composeP0Gate/runVerifiedGeneration) and loop (runAgenticMediaLoop) are wired intoContentGenerator; adoption from the request-time host is a deploy step.) Re-read 2026-09-18: this is code, not a deploy step. Make the request-time host call the gate: find whereapps/metis/api-gateway(or the Python service behind it) constructsContentGenerator, route its generation endpoint throughrunVerifiedGenerationwithcomposeP0Gate, and surface the gate's verdict and the loop's attempts in the response. Verify: a route-level spec with the providers doubled at their boundary shows a failing gate blocks the response and a passing one returns it with its evidence; a grep shows no generation route that bypasses the gate.
6.4 — Docs & runbooks#
- Update
DOMAINS/metis/*(architecture/features/specifications) with the verification + agentic-media subsystems. (architecture.mdgains a "Correctness Verification & Agentic Media" section (gate + verifiers, Planner→Coder→Critic loop, sandboxed Manim render worker);features.mdgains §14 Content Correctness Verification + §15 Agentic Teaching Media;specifications.mdgains §12 Correctness Verification Subsystem (gate decision algebra, verifier table, eval baselines) + §13 Agentic Media & Manim Render Service (loop, render request/response + sandbox contract, transports, segment composition). Regenerated the threeDOMAINS/metis/*.htmlviatools/render-domain-docs.py. The in-libDECISION.md/EVAL_BASELINES.md/MEDIA_EVAL_BASELINES.md/RUNBOOKS.mdremain the deep references. Note: the regen also date-bumps every other domain's HTML footer — those unrelated changes were reverted to keep this scoped to metis.) - Runbooks: how to add a verifier, a media agent, a gold set; how HITL
feedback flows. (
libs/metis/verification/RUNBOOKS.md.)
6.5 — Final adversarial verification pass#
- Repo-wide adversarial stub scan over all new code (the mandated grep set);
every hit read in context; zero result-faking. (Scanned all 30 impl files
changed this session; clean. Only 2 hits, both PRE-EXISTING in
content-generator.tsfrom commitbc13f0788e— aparseLessonSectionsdoc comment and a'metis-simulated'provenance label, neither result-faking.) - Confirm the fact-checking-agent no longer fabricates verdicts (0.4)
anywhere callers use it. (Confirmed: reports
unverified(honest absence) with no verifier; only produces truth verdicts via an injected evidence-grounded verifier — never fabricates.) - Full metis suites green; lint 0 errors; final commit + push (branch +
main). (
@metis/verification161 tests, full multimedia 853, agents 885 tests — all green; the sole agents file-fail is the pre-existing, unrelatedcurriculum-agent.spec.ts@oshun/contracts/metisalias gap from another session. Lint 0 errors on all new code.)
Cross-references (SOTA → task)#
| SOTA method | Source | Tasks |
|---|---|---|
| FActScore atomic-fact support | arXiv:2305.14251 | 1.1, 1.2 |
| SAFE / F1@K | arXiv:2403.18802 | 1.1, 1.2 |
| FaStfact chunk-level extraction | arXiv:2510.12839 | 1.1 |
| TRACe / RAGBench faithfulness (DeBERTa) | arXiv:2407.11005 | 1.3, 1.4 |
| Citation placement (retrieval-driven; post-hoc vs gen-time) | arXiv:2509.21557 | 1.4 |
| ThinkPRM process reward model | arXiv:2504.16828 | 1.7 |
| Judge position bias | arXiv:2406.07791 | 1.8 |
| Agreeableness bias + ensembles (minority-veto, regression) | arXiv:2510.11822 | 1.8 |
| Cascaded Selective Evaluation (conformal) | arXiv:2407.18370 | 1.8, 3.3 |
| IRT/GRM judge reliability | arXiv:2602.00521 | 1.8 |
| Linear-probe judge calibration | arXiv:2512.22245 | 1.8, 3.3 |
| TheoremExplainAgent (Manim video) | arXiv:2502.19400 | 2.1–2.6 |
| Code2Video (Planner→Coder→Critic, TeachQuiz) | arXiv:2510.01174 | 2.2–2.6 |
| Sora 2 / Veo 3.1 / Kling 3 (text-to-video) | 2026 model comparisons | 4.3 |
| Hedra Character-3 / HeyGen Avatar 5 / OmniHuman v1.5 | 2026 model comparisons | (existing avatar pipeline; provider upgrade) |
Verify each task by reading the code you wrote and running its tests — not by file existence or this table. Mark
[x]only after the per-task gate passes in-session.