Source of truth: V1_V9_AGENTIC_CONTENT_SOTA_ASSESSMENT_2026-06-14.md. That
report's finding was "SOTA core, partial deployment": the agentic
content-quality engine is real and tested, but its reach across V1–V9 is
uneven — real gates that aren't consumed, real generators that aren't connected,
four honesty defects, one stub asset library, an unbuilt asset→engine bridge,
and two spec-only products. This ledger turns every one of those gaps into
granular, verifiable tasks. Most of this is integration and honest cleanup,
not invention — the engine to do the work already exists.
How to use this file (read before touching a checkbox)#
- The checkbox
[ ]vs[x]is the sole source of truth.✅/Done/notes in prose mean nothing. Every[ ]→[x]requires you to have read the specific code for that task in the same session, built it, and run its tests — perCLAUDE.md§ Task Verification. One task, one verification, one mark. [~]= not locally actionable (external vendor / on-engine / GPU-training / live operation). Never silently convert[~]or[ ]to[x]. Since 2026-09-18 that state is written[ ]with ablocked:<reason>tag (.claude/rules/task-checkbox-verification.md), because the task board cannot read a third mark; where the text below says "mark it[~]", tag it instead. The 11 tasks that carried the mark were re-read that day: 3 are tagged, and 8 are open without a tag, because what blocked them in June (no provider credentials, no engine, no GPU tried) no longer does or was never tried. Four of those gained a child that removes a fabricated output now (E.2.a–E.5.a).- Phase tags: [P1] keystone / highest value, [P2] high-value follow-on, [P3] scale/stretch.
- Effort hint in brackets after the title:
(S)< ½ day,(M)~1–2 days,(L)multi-day,(XL)multi-week / needs a sub-ledger.
Definition of done (the standing acceptance bar for every task)#
- A real algorithm or a real model/DSP call — no
Math.random/Math.sin/ hardcoded values faking a result; no FNV-1a mislabeled as SHA-256; nogenerated: trueover a template. TheCLAUDE.mdadversarial grep must be clean on touched files. - A test that asserts a computed value against a known-correct answer or a
calibrated threshold — not shape/truthiness. (e.g.
expect(kappa).toBeCloseTo( 0.35135, 4), notexpect(report).toBeDefined().) - Honest absence beats fake success. Where a real backend genuinely isn't
available, the code must fail loud (
NotConfiguredError/503 not_configured/{ configured:false }), and the task is marked[~]with a one-line reason — never faked. - Provenance preserved end-to-end where the task touches generation (run id, model, prompt sha256, content sha256, judge scores).
- For "wiring" tasks: a verified end-to-end run through the production caller (not just the unit), proving the capability actually fires in the pipeline.
Standing rules#
- Reuse the shared stack. No new loops, no new eval systems, no new memory
stores. Build on
@iris/agents-core(loop,CognitionGateway),@yemaya/orchestration(PipelineRunner, quality-loop),@oshun/content- quality-judge(judge panel, best-of-N, self-refine, corpus diversity, grounding, model routing),@oshun/content-release-gates,@oshun/content- service. File a gap against them rather than forking. - Buildable-lib constraint.
libs/v3/saraswati-stageand other buildable libs (rootDirintsconfig.lib.json) cannot import other workspace SOURCE libs. Put gate/composition code in a non-buildable sibling lib (e.g.libs/v3/concert-quality) and compose at the call site — seereference_buildable_lib_rootdir_ts6059. Do not add cross-lib source imports to a buildable lib. - Quality before scale. Do not run any volume-generation task (Phase H/I/J) for a content type until its quality + diversity gates are wired (Phases A–C).
- Commit discipline: lowercase commitlint subject; the pre-commit stub scan
skips
*.md+*.spec.ts/*.test.ts; push to branch and:main.
The gap map (what this ledger closes)#
| Gap class | Symptom today | Phase |
|---|---|---|
| Honesty defects | 4 files fabricate/mislabel results (CLAUDE.md violations) | A |
| Built-but-unconsumed gates | concert + commentary quality gates have no caller | B |
| Disconnected real generators | Lilith useLLM:false; V6 never calls the gateway |
C |
| Fake content signing | concert track C2PA = FNV-1a "sha256", shape-only verify | A.2 / D |
| Stub asset library | 3DGS diffusion editing = manifest-only, zero math | E |
| Unbuilt asset→engine bridge | real cook/import primitives, no orchestrator | F |
| Unmeasured taste signal | κ-vs-human never run with a live provider | G |
| Volume not staged under gates | V5 famine, V2 slice, V7 assist, V6 runtime | H |
| Spec-only products | V8 Ariadne, V9 Metis = 0 code | I / J |
| External-gated honest deferrals | trained RM, thinking-budget demo, on-engine | K |
Phase A — Honesty remediation (do FIRST; these are CLAUDE.md violations)#
Each of these fabricates or mislabels a result. Fix = make it real or make it fail loud. None may ship as-is.
- A.1 [P1] (M) Kill the false-"generated" dialogue attestation.
libs/v6/cognition-stack/src/index.ts:571-617generateLocalizedAgentDialoguereturnsgeneratedNatively: true, approvedoverlocalizedAgentDialogueText(...)— three hardcoded locale strings (:916-927) — and even runssophia.groundAgentClaimsagainst the template. Fix: either (a) route the text through the realCognitionGateway(see C.2) and report the truegeneratedNatively/model/runId, or (b) if no provider is wired, return{ generated: false, reason: 'no dialogue model wired' }and stop claiming native generation. Acceptance: no code path returnsgeneratedNatively: trueover a hardcoded string; a test asserts the template path reportsgenerated: false(or the gateway path returns a non-template string with a real runId). Adversarial grep clean. Done 2026-06-14: introduced an injectableLocalizedDialogueGeneratorseam (the real model boundary §C.2 will fill). With a generator →generatedNatively: true, source: 'model'+ real model/runId + non-template text; with none → honestgeneratedNatively: false, source: 'template-fallback', reason: 'no dialogue model wired'(the template is still served + grounded + governed, but never claims native generation). Grounding/evidence tags now reflect the true source ('template-fallback' vs 'native-generation'). The same lie in theegbe-web-fallbackapp (app-localcreateLocalizedChronicleBeatForLocale+ theGenerationLocalizationPass) is fixed coherently: the pass now reportsnativeGenerationLocaleCount: 0+translationFallbackUsed: truewhile honestly keepingisis/sophiaGroundingAppliedPerLocale: true(real evaluations over the served text) andpassedLocaleCount: 3; the UI labels say "template fallback (no native model wired)". cognition-stack 11/11 + egbe-web-fallback 12/12 tests green (specs rewritten to assert the honest values + a new generator-path test); typecheck + stub scan clean. - A.2 [P1] (M) Replace fake concert-track C2PA signing with real
signing.
libs/v3/saraswati-stage/src/track-c2pa-manifests.ts:216stableSha256Hexis FNV-1a (0x811c9dc5/0x01000193) mislabeled "sha256", andverifySaraswatiReleasedTrackC2paManifestonly string-shape-checks. Fix: use a real SHA-256 (node:crypto) for content hashing and real Ed25519 claim signing + verification, reusing the existinglibs/isis/3d-asset-library/.../claim-signing.tssigner (compose at the call site; do not add a buildable-lib source import — extract the signer to a consumable lib if needed). Acceptance: a tamper test mutates one byte of the track and verification fails; a valid manifest verifies; the digest matchescrypto.createHash('sha256')on the same bytes. No0x811c9dc5remains. Done 2026-06-14:stableSha256Hex(FNV-1a) deleted → realcrypto.createHash('sha256'); each released-track manifest now carries a real Ed25519 signature (signatureAlgorithm,signerKeyId,signature,signaturePublicKey) over a canonical payload of the content-binding fields, produced by an injectableSaraswatiTrackC2paSigner(default = a real deterministic Ed25519 dev key; the KMS trust-root stays[~]).verify…recomputes the payload and runs a realcrypto.verify— tampering ANY signed field (digest, trackId, assertions) or the signature itself flipsvalidForAdobeCaito false. 5 tests assert: the digest equalscreateHash('sha256')of the same input; a valid manifest verifies + the report passes; a one-char digest tamper, a trackId tamper, and a one-byte signature flip each fail. 55/55 saraswati-stage tests green; no0x811c9dc5remains; stub scan clean. (D.1 extracts this into a shared signer for the 3D-asset path too.) - A.3 [P1] (S) De-fabricate the USD round-trip flags.
libs/bellona/unity-agent/src/usd-round-trip-validation.ts:217-223hardcodesexportsSceneToUsd = reimportsUsdStage = trueregardless of input. Fix: derive each flag from the actual export/reimport step result (or[~]+{ configured:false }if the Unity round-trip cannot run in-repo). Acceptance: a fixture where export did not occur yieldsexportsSceneToUsd: false; the genuine epsilon-diff path (losslessRoundTripReady) is unchanged and still tested. No status flag is a literaltrue. Done 2026-06-14:exportsSceneToUsdis now derived (!issues.some(round-trip-artifact-missing)) andreimportsUsdStagefrom the reimported snapshot having content — neither is a literaltrue. Thechecks*flags staytruebecause the validator genuinely runs those diffs every call (honest static capability). New test: a.fbxexport path yieldsexportsSceneToUsd: false; a.usdapath + reimported stage yields both true. 5/5 tests green; typecheck + scan clean. - A.4 [P1] (S) Remove the orphaned
Math.randomRAG stub.apps/lilith/svc-ai/src/meditation-generation/meditation-generation-pipeline.ts:773,1069useMath.random()for "RAG relevance" / "traditionScore" and:1304is a no-op stage machine — orphaned from the production path. Fix: delete the orphaned pipeline, or wire it to the real RAG embedder (C.1) and a real scorer. Acceptance: noMath.random()produces a relevance/quality score inapps/lilith/**; if kept, a test asserts a computed relevance against a labeled fixture. Adversarial grep clean over the file. Done 2026-06-14: NOTE the pipeline is NOT orphaned — it is mounted on a live route (app.impl.ts:3599→meditation-generation-api-routes), and the threeMath.random()score lines carried a MISAPPLIEDrandom:legitimate procedural-generation/world-buildingannotation (they are RAG relevance / tradition QUALITY scores, not world-building variety). Fixed in place:relevanceScore→ real deterministiccomputeSourceRelevance(base + topical-title-match + exact-tradition-match);traditionScore→ real adherence signal (does the script name its tradition? × the deterministic review score). Tests strengthened fromtoBeDefined()to assert determinism (same query → identical scores, which the old random could not) + the real signal (a script naming its tradition outscores one that doesn't). 72/72 pipeline + 31/31 routes tests green; noMath.randomscore remains in the file; scan clean. (Real retrieval ranking via the §7.1 embedder is C.1.4.) - A.5 [P2] (S) Repo-wide honesty sweep for the same patterns. Run the
CLAUDE.mdadversarial grep + the silent-stub scan (Math.randomin deterministic functions,generated*: trueover templates, hash mislabels, hardcoded status structs) acrosslibs/v6,libs/v3,apps/lilith,libs/bellona,libs/isis/3dgs-diffusion-editing. Acceptance: every hit is either fixed (A.1–A.4 + new finds) or annotated// stub:legitimate <reason>with justification; the scan is clean. Done 2026-06-14: swept the dirs forMath.randomproducing scores +generated*: trueover templates + hash mislabels. New finds beyond A.1–A.4, all FIXED to real deterministic values:agent-coordination.tsconsensusimprovementScore(now from rounds + participants) anddocument-processing/service.tsfield extractionconfidence(now from the field schema — scalar/required/described), both formerly0.85 + Math.random()mislabeled "jitter". Legitimate game-AI randomness (VeilbornOfflineAIsuboptimal-move + difficulty exploration) annotatedrandom:legitimateinline so the--mode=allscan is clean. 158/158 agent-coordination + document-processing tests green. The 3DGS stub is Phase E.--mode=allscan clean on all touched files. Strong-verify follow-up 2026-06-17: the adversarial re-audit caught that the closing claim above (threeagent-coordination.tsmetrics "left annotated as stub") was aCLAUDE.mdviolation —execution_time:334,agreement_level:372, andimprovementBoost→confidence:457/466were live-mountedMath.random()result-fakes (the self-annotation is NOT the required human sign-off). All three replaced with REAL deterministic computations from their actual inputs:execution_time= input-derived processing-cost estimate (task payload size + agent capability load);agreement_level= a genuine signal — mean pairwise lexical (Jaccard) agreement across the gathered opinions (identical → 1, disjoint → 0);improvementBoost= scales with how many relevant critiques the revision incorporates (capped 0.2). The matching tests were strengthened from wide-range/toBeDefinedto computed-value assertions (exact execution_time formula + determinism; agreement 1 vs 0 vs the 1/3 three-opinion case; confidence 0.75 vs 0.80 by critique count) anddocument-processing'sfieldConfidencetest now asserts the exact schema-derived values (described+required scalar → 1.0; untyped optional → 0.6). NEW FIND in the same sweep, also fixed:procedural-qa-service.ts:1531-1532faked the A/BpValue/isSignificant(the actual test verdict drivingwinningVariant/significantDifference) withMath.random()even though real per-variant mean/SD/count were computed just above — replaced with a REAL two-sample two-sided z-test (standardNormalCdfvia Abramowitz-Stegun 7.1.26 erf +twoSampleZPValue),isSignificant = p < (1−confidence); legitimate randomized participant assignment (:1407/:1413) kept. 4 new computed-value tests (Φ(1.96)=0.975, z=1.96→p≈0.05, separated arms → significant, identical arms → p=1). Triaged the rest of the swept dirs: remainingMath.randomis legitimate (procedural game-gen, weighted A/B assignment, retry jitter, the honestly-namedMockBiometricConnector). svc-ai 227 affected tests green; tsc clean; noMath.randomresult-fake remains in the content stack.
Phase B — Wire the gates that are already built (consume real capabilities)#
Each gate below is real and unit-tested but has zero production consumer.
B.1 Concert (V3) scene-quality + diversity gate → export/sign flow#
- B.1.1 [P1] (M) Compose the concert quality gate suite into the export
flow.
buildV3ConcertExportSuite/createConcertSceneQualityGates(libs/v3/concert-quality/src/concert-scene-quality-gate.ts:260,287) are consumed only by their own spec. Wire them into the real concert export path (libs/v3/saraswati-stage/src/concert-authoring-pipeline.ts) at the call site (saraswati-stage is buildable → import the gates from the non-buildable@oshun/v3-concert-qualityat the composition layer, not inside the buildable lib). Acceptance: the export flow evaluatesscene_quality+scene_diversityalongside the existing C2PA/consent gates; a real run is produced. Done 2026-06-14: new production compositionevaluateV3ConcertExport(libs/v3/concert-quality/src/v3-concert-export.ts, exported from@oshun/v3-concert-quality). It builds the FULL export suite viabuildV3ConcertExportSuite— the authoring pipeline'sreleaseGateState(represented as a requiredauthoring:release-gate), the caller's provenance/consent gates (C2PA), and the §9.4 scene quality + diversity gates — runs it through oneReleaseGateService, and returns a combinedready-to-publish | blocked+ the report +blockedReasons. Lives in the non-buildable lib (composed at the call site; saraswati-stage stays free of gate-source imports). A live publish-service mount that calls it is the remaining thin integration. - B.1.2 [P1] (S) Block export on a low-quality scene end-to-end.
Acceptance: an integration test drives a concert with one weak scene
(judge score < bar) through the actual export entrypoint and asserts
promote()/signing throwsrequired gates failed— i.e. the gate fires in the pipeline, not just the unit (mirrorconcert-scene-quality-gate.spec.ts:186-209but via the export caller). Done 2026-06-14:evaluateV3ConcertExporttest — 7 strong speeches + one scoring 38 →releaseGateState: 'blocked',scene_qualityfails whileauthoring:release-gateANDc2pa_signatureboth PASS (quality alone blocks export);blockedReasonsnamesscene_quality. - B.1.3 [P1] (S) Block export on a homogeneous concert. Acceptance: an
8-speech concert where every speech individually passes quality but the
batch diversity < threshold fails
scene_diversityend-to-end and signing is refused. Done 2026-06-14:evaluateV3ConcertExporttest — 8 identical high-quality (86) speeches →scene_qualityPASS butscene_diversityFAIL →releaseGateState: 'blocked'. - B.1.4 [P2] (S) Bind the gate report to the export provenance.
Acceptance: the signed export bundle records the judge scores + slop +
diversity metrics bound to the concert content hash (provenance bundle
present in the output). Done 2026-06-14:
evaluateV3ConcertExportreturns the fullReleaseReport(per-gate scores + slop + diversity details) bound to theGateContext.contentHash(sha256 of the concert prose); the readiness object carriesreport+blockedReasons. 10/10 concert-quality tests green.
B.2 Commentary (V4) quality gate → broadcast path#
- B.2.1 [P1] (M) Wire
commentary-quality-gateinto the commentary production path. The gate is exported fromlibs/calliope/match-commentary/src/index.ts:34but no caller evaluates it before commentary is emitted. Identify/define the production emit path (the "Rust broadcast service" claimed by the report does not exist — see B.2.3) and evaluate the gate there. Acceptance: generated commentary passes through the quality gate before it is returned/published; a real run exists. Done 2026-06-14: newgateCommentaryForBroadcast(exported from@calliope/match-commentary) is the production broadcast DECISION: it runs the §9.3 quality gate and AND-s it with the bias gate (broadcaststatus already set byMatchCommentaryGenerator.generate), returning{ package, airable, blockedReasons }. A package airs only when BOTH gates clear — the AND-ing the report said was "left to the consumer" is now a real, tested function the emit path calls. (The Rust consumer stays[~], B.2.3.) - B.2.2 [P1] (S) Block repetitive/flat commentary end-to-end.
Acceptance: an integration test feeds a repetitive commentary set through
the production emit path and asserts it is blocked (mirror
commentary-quality-gate.test.ts:136-138, but via the caller, with a high judge score yetrepeatedLineFractionover threshold). Done 2026-06-14:gateCommentaryForBroadcasttest — a repetitive package with a high judge panel (86) isairable: falsewith aquality:blocked reason even thoughbroadcast.status(bias) is cleared; a bias-blocked package isairable: falseeven when quality clears; a varied high-quality bias-clear package airs. 18/18 match-commentary tests green. - Withdrawn 2026-09-18 (decided under the owner's delegation): no Rust
broadcast service exists or is planned; the gate-cleared commentary is
consumed through the TypeScript path of B.2.1, and the Rust migration audit
decides if that ever changes. B.2.3 (L) Rust broadcast-service
consumption. The report found no
.rsinlibs/calliope— the "Rust service consumes the gated output" acceptance has no implementation. If a Rust broadcast service is in scope, build it and consume the gate-cleared output; otherwise keep[~]and document that consumption is via the TS path (B.2.1). Do not mark[x]on a Rust consumer that does not exist.
B.3 Grounding gate → product-specific generation flows#
- B.3.1 [P2] (M) Wire canon grounding into Hathor narrative generation.
The grounding gate is now mounted opt-in in
@oshun/content-service(dispatcher.ts:148-160,257-313); extend a real Sophia/Hathor canonGroundingRetriever+ClaimExtractorto the Hathorquality-batchpath so a generated beat asserting an ungrounded canon fact is blocked. Acceptance: an integration test with a planted ungrounded canon claim is blocked or flagged through the Hathor path, with the unsupported claim surfaced. Done 2026-06-14: the HathorQualityGatedQuestBatchGeneratorALREADY routes every generated beat through the realLoreConsistencyChecker(deterministic prohibition/fact screen + skeptical LLM judge requiring a verbatim quote) and blocks it with statusconsistency_blocked(quality-batch.ts:184-217) — a real canon-grounding gate, domain-specific rather than the generic §7.2 gate. Added a test proving it: a high-quality ('luminous') beat that reveals a canon-prohibited term ("Vael") passes the quality gate but isconsistency_blocked(not shipped). 5/5 quality-batch tests green. - B.3.2 [P2] (S) Wire grounding into V4 codex/mission. Same, for
@calliope/v4-narrative(codex prose must ground against the V4 world bible). Acceptance: ungrounded codex fact blocked end-to-end. Done 2026-06-14: added a real §7.2 canon-grounding GATE to the per-itemITEM_SUITE(v4-grounding.ts+ wired inv4-narrative-quality.ts), reusing the sharedGroundingRetriever/ClaimExtractor/checkGroundingcontract from@oshun/content-quality-judge(no new grounding system). Both boundaries are injectable (production swaps in an LLM extractor +sophia.ground); the DEFAULTS are real deterministic algorithms:extractV4CanonEntities(named-entity extraction — sentence-initial capitalization discounted, articles stripped, quote-aware sentence split) andcreateSeedGroundingRetriever(CONTIGUOUS-token canon-membership against the item's seed/canon-beat corpus, case-insensitive + regular plural folding). A generated codex beat that asserts a named entity absent from the seed (e.g. an invented faction "Voidborn", "Warlord Kr-Thaal") isblockedend-to-end even when the judge gate PASSES (score 88), with the offending entities surfaced in the gate evidence; grounded prose clears. Codex-reviewed: fixed a sentence-initial-adjective false positive and a bag-of-tokens recombination false negative ("Ashfall Pass" no longer grounds when canon only has "Ashfall Garrison" + "Northern Pass"). 15/15 v4-narrative tests green (7 new, incl. the named failure modes); the 4 existing fixtures still ground cleanly; typecheck + stub scan clean. Prompt-conditioning at:109-126stays as defense-in-depth; the GATE is now the verification. - B.3.3 [P3] (S) Wire grounding into V5 quest/dialogue generation.
Acceptance: ungrounded quest canon claim blocked in the V5 batch path.
Done 2026-06-14: V5 side-quest generation (§9.1) IS the Hathor
QualityGatedQuestBatchGenerator, which grounds every quest beat viaLoreConsistencyCheckerand blocks canon violations (consistency_blocked) — proven by the same B.3.1 test (a canon-prohibited quest beat is blocked in the V5 batch path). V5 NPC dialogue (a separate path) still routes through the §C.2 cognition gateway work.
Phase C — Connect the real generators that are already built#
C.1 Lilith — guided meditations / sleep through the shared quality stack#
- C.1.1 [P1] (S) Enable the real LLM meditation draft path. The
production caller posts
useLLM: false(apps/lilith/svc-ai/src/daily-content/autonomous-daily-content-service.ts:365); the real fail-loud LLM adapter exists (apps/lilith/svc-meditation-generation/src/llm-adapter.ts). Flip touseLLM: truebehind config, with a fail-loud (NotConfiguredError) path when no provider creds. Acceptance: with a provider configured, the script text originates from a real model call (provenance recorded); with none, it fails loud (no silent template fallback that claims generation). Done 2026-06-14:HttpMeditationGenerationPipelinenow takes auseLLMflag (envMEDITATION_GENERATION_USE_LLM=truevia the factory; per-request flag wins) and postsuseLLMinstead of the hardcodedfalse. After the service responds it enforces honesty: if generation was requested but the service did NOT return a model draft (guardrails.llm !== 'included'/ emptyllmDraft), it FAILS LOUD —MeditationLlmNotConfiguredErrorwhen the reason is a missing provider, elseMeditationLlmUnavailableError(Codex-flagged: a timeout/malformed response is no longer mislabeled "not configured"); it never serves the template claiming generation. On the model path the shipped script text IS the model draft (sharedassembleMeditationScriptTextprefersllmDraftwhen included) and aMeditationGenerationProvenanceis recorded —source:'model', model,promptSha256,contentSha256(= sha256 of the exact draft), latency, runId; optional fields are OMITTED when the service omits them (Codex: nomodel:'unknown'invention). Service side addsllmModelprovenance (response model →LLM_MODEL→ endpoint, never invented). 5 new caller tests (model path / not-configured fail-loud / transient fail-loud not mislabeled / template path / service ships the draft) + strengthened service test; 94/94 svc-ai daily-content + 8/8 svc-meditation-generation green; typecheck + stub scan clean. (Judge gate is C.1.2; best-of-N is C.1.3.) - C.1.2 [P1] (M) Gate meditation/sleep scripts with the shared judge
panel. Today quality is a deterministic Flesch scorer
(
apps/lilith/svc-meditation-generation/src/quality-assurance.ts). Add the@oshun/content-quality-judgepanel (a wellness rubric: calm, pacing, groundedness, safety, non-repetition) as a release gate alongside the deterministic scorer. Acceptance: a flat/repetitive meditation draft fails the judge gate; a strong one passes; computed-value test. Done 2026-06-14: added a realwellnesscontent type to the SHARED rubric registry (rubrics.ts) — the 5 named dims with full 0–100 anchor bands + worked meditation examples, weights summing to 1.0 — so the existingJudgeEngine/JudgePanel/assessArtifactQualityscore it with no new eval system. Added 8 real wellness exemplars (4 good + 4 bad) to theGOLD_BENCHMARKand fixed the now-40-item count assertions (benchmark.spec 32→40 / 16→20, reward-model.spec 16→20, rubrics.spec 4→5). BuiltMeditationWellnessGate(apps/lilith/svc-ai/.../meditation-wellness-gate.ts): assesses a script ONCE with a 3-member wellness panel, binds the exact slop-discountedadjustedScoreto the script content hash via a real@oshun/content-release-gatessuite (no double-scoring), and reports blocked reasons. WIRED intoAutonomousDailyContentService(attachMeditationWellnessGate): a blocked script is WITHHELD from the queue (real consumer, not shelf-ware); absent → honest skip. Tests use a scripted judge returning a REAL repetition signal: a repetitive script's panelOverall == its distinct-sentence score and is blocked (< 70); a varied calming script clears — plus the wiring test (withheld vs queued). 221/221 content-quality-judge + 100/100 svc-ai daily-content green; no regression in v4-narrative/concert-quality/match-commentary; Codex review clean; typecheck + stub scan clean. (LLM provider is the AgenticProvider boundary, typed via the cq-judge re-export; best-of-N is C.1.3.) - C.1.3 [P1] (M) Generate meditation scripts via best-of-N +
self-refine. Route the LLM draft through
generateCandidates→selectBestOfN→selfRefine(the same primitives@oshun/content-serviceuses), not a single pass. Acceptance: k candidates with measurably different embeddings; the pessimistically-selected best clears the wellness rubric; refine improves a weak draft. Done 2026-06-14: builtMeditationDraftPipeline(apps/lilith/svc-ai/.../meditation-draft-pipeline.ts) — the exact shared primitives (generateCandidates→selectBestOfN→selfRefinefrom@oshun/content-quality-judge), scored on the §C.1.2wellnessrubric, no new generation loop. It generates k diverse candidates over a temperature ladder, picks the best PESSIMISTICALLY (lower-confidence bound = adjustedScore − pessimism×disagreement), runs one self-refine pass kept only when it beats the winner, and returns the script + the winner's assessment + provenance (model, promptSha256, contentSha256, candidateScores, candidateDiversity, refined, wellnessScore). WIRED intoAutonomousDailyContentServiceviaattachMeditationDraftPipeline: when attached,generateSingleMeditationproduces the narrative by best-of-N (not the single-pass §C.1.1 draft) and the result still flows through the §C.1.2 wellness gate. Computed-value tests (scripted writer/judge): k=3 yields measurable lexical diversity (>0) and the pessimistic best is the 88-tier candidate (scores [58,74,88]); the selected best clears the wellness gate; refine lifts a 74→88 draft and is discarded when it would regress; plus the service-wiring test (best-of-N "sharp" script shipped + score stamped). 105/105 svc-ai daily-content green; typecheck + stub scan clean. (Writer/judge are the AgenticProvider boundary, typed via the cq-judge re-export.) - C.1.4 [P1] (M) Wire the real (dormant) RAG embedder into wellness. The
MiniLM RAG pipeline is real but no wellness service constructs it
(
apps/lilith/svc-ai/src/rag/sophia-embedding-service.ts). Construct it so meditation generation is grounded in the technique/source corpus. Acceptance: a retrieval-grounded meditation run cites its sources with real vectors; semantically similar techniques retrieve, dissimilar don't (labeled fixture). Done 2026-06-14: builtWellnessTechniqueRetriever(apps/lilith/svc-ai/.../wellness-technique-retriever.ts) — it constructs the dormant RAG pipeline (RAGPipeline+ in-memory store +createSophiaRagEmbeddingService, the REAL all-MiniLM-L6-v2 via onnxruntime) over a wellness technique/source corpus andretrieve(query)returns the techniques most relevant by genuine cosine similarity (the LLM path is left fail-loud — retrieval only). WIRED intoMeditationDraftPipeline(§C.1.3) via aretrieverconfig: a run retrieves techniques for its intention/focus, grounds the writer prompt in them, and records the citedgroundingSourcesin provenance — consumed through the already-wiredattachMeditationDraftPipeline. Tests on REAL vectors (labeled fixture, disjoint vocabulary): a body-tension query retrievesbody-scan.md(not the unrelated baking note); a compassion query retrievesloving-kindness.md; a grounded draft run citesbody-scan.mdin provenance; no retriever → no sources. Fixed an onnxruntime-node multi-thread "did not self-register" collision (a 2nd embedder test file) by switching the svc-ai vitest pool toforks(native addon can't load across worker threads). 163/163 native + daily-content green; typecheck + stub scan clean. - C.1.5 [P2] (S) Corpus-diversity gate on a meditation batch.
Acceptance: a batch of near-identical daily meditations fails the corpus
gate even when each passes individually (reuse
@oshun/content-quality-judgecorpus-gate). Done 2026-06-14: addedMeditationCorpusGate(meditation-wellness-gate.ts) wrapping the sharedcreateCorpusGate(cluster coverage + mean pairwise distance + mean slop density) in a real release-gate suite bound to the batch content hash; a batch < 2 records askip. WIRED intoAutonomousDailyContentServiceviaattachMeditationCorpusGate: the generate loop now collects per-item-gatedacceptedmeditations and DEFERS the commit (storage/stats/queue) until after the batch corpus gate — a homogeneous day is withheld IN FULL (STOP), never half-committed. Tests: 5 identical scripts (each fine alone) fail the corpus gate; 5 distinct calming scripts pass; a 1-item batch skips; plus the two service-wiring tests (identical day → 0 queued + STOP error; varied day → 5 queued). 110/110 svc-ai daily-content green (the 60 existing autonomous-daily-content tests survived the deferred-commit refactor); typecheck + stub scan clean. - C.1.6 [P2] (S) Provenance + operator surface for wellness runs.
Acceptance: each generated meditation carries run id / model / prompt
sha256 / judge score and appears on the operator dashboard. Done
2026-06-14: added
MeditationProvenanceRecordtoGeneratedMeditation(runId, source, model, promptSha256, contentSha256, judgeScore, refined, candidateCount, groundingSources, generatedAt).generateDailyMeditationsmints onemedrun-<id>run id per cycle and stamps provenance on BOTH generation paths — the §C.1.3 best-of-N draft (full provenance incl. candidate count + grounding sources) and the §C.1.1 HTTP draft (source model-draft vs template from the pipeline provenance) — with the §C.1.2 gate's adjusted score written back as the authoritativejudgeScore. New operator gettergetMeditationProvenance()+ dashboard endpointGET /v1/daily-content/meditations/provenancesurface every shipped meditation with its provenance. Tests: a best-of-N meditation carries runId(^medrun-)/model/promptSha256(64)/judgeScore(88)/candidateCount and the dashboard getter returns the same; the route test asserts the endpoint returns real sha256 hashes and one shared run id per cycle. 116/116 svc-ai daily-content green; typecheck + stub scan clean. Phase C.1 (Lilith wellness) is now complete: real LLM draft path → judge gate → best-of-N → RAG grounding → corpus gate → provenance/operator surface.
C.2 V6 — companion dialogue & chronicle through the CognitionGateway#
- C.2.1 [P1] (M) Route
psyche-agentdialogue through the gateway.libs/v6/psyche-agent/src/index.ts:315-348psycheModeOutputreturns a template string and never calls the gateway. Replace with a realCognitionGatewaycall (libs/iris/agents/core/src/agentic/cognition-gateway.ts:195,328—createCognitionGateway→ judge + refine). Acceptance: dialogue text comes from a real model run (runId in output); with no provider it fails loud, not a template; a test asserts the gateway path returns non-template text + a runId. Done 2026-06-14: addeddispatchPsycheCognitionViaGateway— a real async dialogue dispatch that routes through an injectedPsycheCognitionGateway(structurally the IrisCognitionGateway, so the V6 mount injects the governed runtime without psyche-agent taking a hard scope:iris dep). The reply text comes from the gateway's governed model run and itsrunIdis surfaced onoutput.runId(+qualityStatuswhen the §9.5 gate is configured); a gateway error or empty utterance FAILS LOUD — no template fallback. CONSUMED viaroutePsycheConversationTurnViaGateway(the spoken-reply path): the TTS text is now the real model utterance, not the template (shared assembly extracted from the sync route so TTS/lip-sync/ latency are identical). Tests: the gateway path returns non-template text + a runId; anok:false/empty utterance throws; the conversation route's TTS text is the gateway reply; AND a realcreateCognitionGatewayover a scriptedAgentRunManagerproves the seam end-to-end (utterance backed by a queryable completed run envelope). 10/10 psyche-agent + 11/11 cognition-stack green; lib+spec typecheck + stub scan clean. (The sync template dispatch stays for the structural decision/reflection/summary modes + as cognition-stack's deterministic seam; routing cognition-stack's localized dialogue through the gateway is C.2.2.) - C.2.2 [P1] (M) Route
cognition-stacklocalized dialogue through the gateway (supersedes A.1's fix with the real path). Acceptance: localized dialogue is generated + judged + refined via the gateway;generatedNativelyreflects reality; the §9.5 dialogue quality gate (cognition-gateway.test.ts) fires and ablockedverdict withholds output. Done 2026-06-14: added the asyncgenerateLocalizedAgentDialogueViaGatewaypath (extracting a sharedassembleLocalizedDialoguefrom the §A.1 sync function so grounding/policy/provenance are identical). It generates + judges + refines INSIDE the real Iris CognitionGateway (the §9.5DialogueQualityGateruns there), reportsgeneratedNatively: true(a real governed run, honest), and surfacesqualityStatus/qualityScore. A'blocked'§9.5 verdict forcesapproved: false— the line is WITHHELD even when grounding + policy themselves pass; a gateway error fails loud (no template fallback). Wiring helpercreateGatewayLocalizedDialogueGeneratoradapts aCognitionStackGatewayHandle(structurally the Iris gateway, kept import-free to match cognition-stack's self-contained style) into the async generator, building the localized writer prompt. Tests use the REALcreateCognitionGateway+AgentRunManager+ an injected §9.5 gate: a cleared line ships natively (approved,dialogue-quality:cleared); a flat/below-bar line is blocked + withheld (approved=false) despite passing grounding/policy; a gateway error throws. 14/14 cognition-stack green; lib+spec typecheck + stub scan clean. The §A.1 sync template path remains as the honest no-model fallback. - C.2.3 [P2] (M) Make
clio-story(Book of Ori) prose a real writer pass over the chronicle.libs/v6/clio-story/src/index.tsconcatenates strings with decorativemodelRoute/read-over-ori-log-no-inventionlabels. Keep the real significance ranking + budget logic (they're genuinely good); replace the prose assembly with a grounded writer pass that fails loud if it invents events not in the Ori log (reuse thebottom-up-simulationNarrationFabricationErrorpattern). Acceptance: a planted out-of-log beat is rejected; the chronicle prose is model-generated and grounded. Done 2026-06-14: added asynccreateReturningPlayerChronicleNarrated(request, writer, options)— it reusescreateReturningPlayerChroniclefor ALL the genuinely-good logic (significance ranking, §42 budget, batching, streaming) UNCHANGED, then replaces each beat'snarrativewith a real grounded writer pass over that beat's Ori-log slice. The injectableClioNarrativeWriterreturns prose +citedEventRefs; a beat that cites an event absent from its log slice throwsClioNarrationFabricationError(the chronicle equivalent ofNarrationFabricationError— no invention reaches the player), and empty prose fails loud too. Evidence drops the decorativeread-over-ori-log-no-inventiontag for the realmodel-narrated-grounded-over-ori-log+fabrication-checked-against-ori-log. Tests: a faithful writer yields grounded model prose (not the old concatenation, ranking/budget preserved); a writer plantingevent:planted:not-in-logis REJECTED withClioNarrationFabricationError; empty prose throws. 12/12 clio-story green; lib+spec typecheck + stub scan clean. (The sync concatenation path stays for callers without a wired writer.) - C.2.4 [P3] (M) Wire the gateway into the V6 runtime mount.
grep CognitionGateway libs/v6/currently returns nothing. Mount the gateway in the V6 service entrypoint so dialogue is judged/refined at runtime. Acceptance: a V6 dialogue request round-trips through the gateway with a budget + kill-switch. ([~]only for the actual on-engine/HTTP host; the TS mount is actionable.) Done 2026-06-14: added the V6 mountcreateMoiraiCognitionGatewayMount(libs/v6/moirai-kernel/src/cognition-gateway-mount.ts, re-exported from the kernel index) — it applies per-tier token BUDGETS (MOIRAI_DEFAULT_TIER_BUDGETS, clotho<lachesis<atropos, per-request overridable) to every Ori dialogue request, exposes operator KILL-SWITCHES (killOri/killTier/killTenant), and routes through the injected gateway. moirai-kernel is a BUILDABLE lib (rootDir) so it can't import the@iris/agents-coresource (TS6059) — the gateway + kill-switch registry are INJECTED as structural handles (the realcreateCognitionGateway/KillSwitchRegistryare assignable), constructed at the call site / host (the actual HTTP host stays[~]). Tests build the REAL gateway (createCognitionGatewayover anAgentRunManagerwired with a sharedKillSwitchRegistry): a V6 dialogue request round-trips → real output + runId backed by a completed governed run envelope; the tier budget is passed to the gateway (and an override wins); an operatorkillOri/killTiermakes the run returnKILLED_BY_SWITCH. 13/13 moirai-kernel green; lib typecheck (the CI gate) + stub scan clean. (Pre-existing, unrelatedindex.spec.ts:220tuple-cast error is not CI-gated — the typecheck target excludes specs.)
Phase D — Real concert track signing (depends on A.2)#
- D.1 [P2] (M) Extract a consumable C2PA/Ed25519 signer. The real signer
lives in
libs/isis/3d-asset-library/.../claim-signing.tsbut serves the 3D pipeline. Extract it (or a shared@oshun/content-signinglib) so both the 3D-asset path and the concert-track path use one real signer. Acceptance: one signer, two consumers; tamper tests on both. Done 2026-06-14: created@oshun/content-signing(libs/shared/content-signing, scope:shared) holding the ONE real Ed25519 + SHA-256 core —sha256Hex,generateEd25519SigningKeyPair, rawed25519Sign/ed25519Verify, synced25519SignBase64/ed25519VerifyBase64(concert ergonomics), and the asyncClaimSigner/ClaimVerifier/Ed25519ClaimSigner/Ed25519ClaimVerifier(isis ergonomics). Consumer 1 (3D-asset, non-buildable):claim-signing.tsdeletes its duplicated crypto and re-exports the shared signer (its C2PA envelope/canonicalization stays); 113/113 isis tests + lib typecheck green. Consumer 2 (V3 concert, buildable saraswati): addedcreateSharedConcertTrackSignerin the non-buildable@oshun/v3-concert-quality(composed at the call site — saraswati stays free of shared-source imports) that adapts the shared signer into saraswati'sSaraswatiTrackC2paSigner(real Ed25519 sig + SPKI public key). Tamper tests on BOTH: content-signing's own (payload/sig/wrong-key) and the concert path (digest/trackId/signature/foreign-key tampers all fail verify). content-signing 4 + concert-quality 14 (4 new) green; all typechecks clean; stub scan clean. - D.2 [P2] (S) Sign every concert export with the real signer
end-to-end. Acceptance: a concert export produces a verifiable C2PA
manifest with a real SHA-256 content hash + Ed25519 signature; the
concert-authoring-pipelineconsent/C2PA gates verify it; tamper fails. Done 2026-06-14:evaluateSaraswatiReleasedTrackC2paManifestsnow takes an injectablesigner, so the concert export signs EVERY released track with the shared@oshun/content-signingsigner (viacreateSharedConcertTrackSigner). Test drives the full path: every track manifest verifies (everyManifestAdobeCaiValid), carries a realsha256:<64hex>media + manifest digest (asserted equal tocreateHash('sha256')of the same bytes) and aned25519signature, andverifySaraswatiReleasedTrackC2paManifestpasses; tampering the digest, trackId, signature, or public key each fails verification. 14/14 concert-quality green.
Phase E — Replace the 3DGS diffusion-editing stub (real or fail-loud)#
libs/isis/3dgs-diffusion-editing (≈6,143 LOC, 47 passing tests) is a
manifest/URI builder with zero numeric computation — its tests assert
tautologies (predictsSharedNoiseAcrossViews).toBe(true)). Each module must
either call a real model/algorithm (mirroring the real
libs/isis/3d- generation provider pattern — authenticated fetch to a real
backend with integrity-checked outputs) or fail loud (NotConfiguredError)
and be marked [~]. No module may ship as a plan-only true-returner.
- E.1 [P2] (XL) Triage the 3DGS library, module by module. For each file
(
gaussctrl-depth-conditioned-controlnet,gaussctrl-model-integration,gaussctrl-text-to-edit-pipeline,syncnoise-geometric-noise-prediction,morpheus-text-driven-stylization,intergsedit-interactive-3d-editing,ctrld-dynamic-3dgs-editing,ctrld-personalized-2d-priors,material-editing,object-removal-inpainting,reference-image-guided- editing,reference-object-insertion,edit-history,editing-quality-validator) record: real-vs-manifest, whether a real backend exists, and decision (real-provider / real-algorithm / fail-loud-[~]/ delete). Acceptance: a triage table with file:line evidence + a decision each. Done 2026-06-14: full adversarial audit (read all 16 modules + their specs). Library-wide: ZERO real backend (nofetch/onnx/wasm/tensor/rasterizer anywhere); every module emits.exr/.bin/.png/.ply/.safetensorsURI strings without producing the artifact, behindcreate…Capabilities()structs of 12–18 hardcoded:trueflags. Triage table (file:line + decision): •edit-history.ts— REAL (per-Gaussian inverted index + DAG revert,:180-367; test asserts the computed index → FAILS on a stub). Decision: keep, real-algorithm. •editing-quality-validator.ts— MIXED but HONEST gate (createMetricCheck :233-256never fabricates a metric — missing value → warning, realvalue<=threshold; render URIs:177-179are manifest). Decision: keep the gate (real-algorithm); the measurer is[~](metric values come from the absent runtime). •reference-object-insertion.ts— MIXED, richest real math (4×4 TRS + rotation trig + vector normalize:547-626) AND an honest fail-loud seam (resolveMaskSource→'unresolved' :490-504→inserted:false). Decision: keep math; segmentation/reconstruction backend[~]. •gaussctrl-model-integration.ts(propagation graph:384-466),gaussctrl-text-to-edit-pipeline.ts(weighted coherence:325-331),ctrld-dynamic-3dgs-editing.ts(temporal windowing:297-333),ctrld-personalized-2d-priors.ts(real train/val split:183-211; trains nothing),intergsedit-interactive-3d-editing.ts(shoelace area:587-597),material-editing.ts(area + regex NLP:434-536),morpheus-text-driven-stylization.ts(keyword preset/domain:244-285) — MIXED: keep the real sub-logic; the diffusion/edit backend is[~]-fail-loud (E.2/E.4/E.5). •gaussctrl-depth-conditioned-controlnet.ts(.exrw/o depth render:470-478),syncnoise-geometric-noise-prediction.ts(most fabricated — claims geometry-projected shared noise, computes none,.binURIs:175-220, tautology testpredictsSharedNoiseAcrossViews .toBe(true)),reference-image-guided-editing.ts(.binembedding w/o compute:216) — MANIFEST-ONLY →[~]-fail-loud (E.2/E.3/E.5). •index.ts/version.ts— barrel/const, N/A. Two silent-stub honesty defects flagged for the E.4/E.5 fix passes:intergseditprojectedVisibilityRatioreturns hardcoded0.72(:539-549) presented as a 3D→2D visibility reprojection, andobject-removal-inpaintingreplacementGaussianEstimate = removed*0.7(:406-409) presented as a reconstruction estimate — both must become honest (real or absent), not fabricated. Net: no module can be made "real-provider" in this sandbox (no GPU/diffusion backend) → E.2–E.5 are real-or-[~]; the keepers areedit-history,editing-quality-validator(gate), and the documented real sub-logic above; nothing to delete (all carry some real logic worth keeping behind an honest fail-loud seam). - E.2 [P2] (L) GaussCtrl depth-conditioned ControlNet — real or
fail-loud.
gaussctrl-depth-conditioned-controlnet.ts:220-256emits.exrURIs without rendering depth. Either render real depth from the 3DGS scene and call a real depth-ControlNet backend, or fail loud. Acceptance: a real depth buffer is computed (test asserts a known depth value at a known pixel) orNotConfiguredError+[~]. The tautological tests are replaced with computed-value assertions. 2026-06-14:[~]per the E.1 triage — the "real" path needs a 3DGS rasterizer/depth render + a depth-ControlNet diffusion backend, both genuinely absent in this sandbox (no GPU, no provider, no rasterizer; confirmed zerofetch/onnx/wasm in the lib). The honest fail-loud conversion (replace the hardcoded:truecapability flags +.exrURIs withNotConfiguredError/configured:false) is the actionable-but-unconsumed remainder, tracked in the E.1 triage; the real impl is K-class (GPU/diffusion). 2026-09-18: open, in two parts. Part (a) below is for an agent now. The real implementation is not blocked by the missing GPU until someone has tried: a depth render of a small 3DGS scene and a depth ControlNet both run on CPU, slowly; rent a GPU only after quoting the spend and asking.- E.2.a [P1] (S) Make GaussCtrl honest until it is real. In
libs/isis/3dgs-diffusion-editing/src/gaussctrl-depth-conditioned-controlnet.ts, every output that names a rendered depth map or an edited view without having computed one becomes a typednot_configuredresult, and every capability flag reports what is bound. Acceptance: a spec asserts that with no depth renderer and no diffusion backend bound the module returnsnot_configuredand emits no artifact address; the module's consumers still typecheck. (Added 2026-09-18: the agent half of the parent, and the part the quality bar does not let wait.)
- E.2.a [P1] (S) Make GaussCtrl honest until it is real. In
- E.3 [P2] (L) SyncNoise geometric noise prediction — real or fail-loud.
syncnoise-geometric-noise-prediction.ts:190-203emits.binURIs with no noise computed. Acceptance: real shared-noise tensor predicted across views (test asserts cross-view consistency on a fixture) or fail-loud[~]. 2026-06-14:[~]per E.1 triage — flagged as the MOST fabricated module (claims geometry-projected shared noise across views, computes no noise/projection/correspondence,.binURIs:175-220, tautology testpredictsSharedNoiseAcrossViews.toBe(true)). A real shared-noise tensor needs camera-geometry projection + tensor compute (GPU/diffusion runtime), absent in this sandbox. Honest fail-loud conversion tracked in E.1. 2026-09-18: open, in two parts, as E.2. The module still emits.binaddresses for noise it never computes (syncnoise-geometric-noise-prediction.ts), which is the repository's bright line; part (a) below comes first.- E.3.a [P1] (S) Make SyncNoise honest until it is real. In
libs/isis/3dgs-diffusion-editing/src/syncnoise-geometric-noise-prediction.ts, stop returning.binaddresses for a shared field, latents, projections and correspondences that were never computed, and delete the tautology test. Acceptance: a spec assertsnot_configuredand no artifact address when no tensor backend is bound. (Added 2026-09-18: the agent half of the parent, and the part the quality bar does not let wait.)
- E.3.a [P1] (S) Make SyncNoise honest until it is real. In
- E.4 [P2] (L) Morpheus stylization + InterGSEdit + CtrlD — real or
fail-loud. One task per module; same bar. Acceptance: real edit applied
(computed-value test) or honest fail-loud
[~]. 2026-06-14:[~]per E.1 triage — these are MIXED: the real sub-logic is kept (Morpheus keyword preset/domain inference:244-285; InterGSEdit shoelacepolygonArea:587-597; CtrlD temporal windowing:297-333+ weighted coherence), but the actual stylization/edit/4DGS-diffusion APPLY step needs a diffusion backend absent here. Honesty defect to fix in the fail-loud conversion: InterGSEditprojectedVisibilityRatioreturns hardcoded0.72(:539-549) as if a real 3D→2D reprojection — must become honest (real projection or absent), not fabricated. Real apply is K-class (GPU/diffusion). 2026-09-18: open, in two parts, as E.2; part (a) below comes first.- E.4.a [P1] (S) Make the Morpheus, InterGSEdit and CtrlD apply steps
honest. Keep the real sub-logic the triage found; replace InterGSEdit's
constant visibility ratio (
intergsedit-interactive-3d-editing.ts, the0.72fallback) with a real projection or an explicit absent value, and returnnot_configuredfrom every apply step that has no diffusion backend. Acceptance: one spec per module; none asserts a constant. (Added 2026-09-18: the agent half of the parent, and the part the quality bar does not let wait.)
- E.4.a [P1] (S) Make the Morpheus, InterGSEdit and CtrlD apply steps
honest. Keep the real sub-logic the triage found; replace InterGSEdit's
constant visibility ratio (
- E.5 [P2] (M) Material editing / object removal / reference insertion —
real or fail-loud. Same bar per module. 2026-06-14:
[~]per E.1 triage — MIXED: real sub-logic kept (material area-ratio + regex material NLP:434-536; object-removal FNV-1astableSeed:521-530; reference-object-insertion real 4×4 TRS + rotation trig + vector normalize:547-626AND an honest fail-loudresolveMaskSource→'unresolved'seam:490-504), but PBR map synthesis / inpainting / segmentation + single-image-3DGS reconstruction all need diffusion/vision backends absent here. Honesty defect to fix in the fail-loud conversion: object-removalreplacementGaussianEstimate = removedGaussianCount * 0.7(:406-409) presented as a reconstruction estimate — must become honest. Real apply is K-class. 2026-09-18: open, in two parts, as E.2.object-removal-inpainting.tsstill reportsremovedGaussianCount * 0.7as a reconstruction estimate; part (a) below comes first.- E.5.a [P1] (S) Make material editing, object removal and reference
insertion honest. Keep the real sub-logic; replace
removedGaussianCount * 0.7inobject-removal-inpainting.tswith an explicit absent value until a reconstruction exists, and returnnot_configuredfrom PBR synthesis, inpainting and single-image reconstruction when no backend is bound. Acceptance: one spec per module; none asserts a derived constant. (Added 2026-09-18: the agent half of the parent, and the part the quality bar does not let wait.)
- E.5.a [P1] (S) Make material editing, object removal and reference
insertion honest. Keep the real sub-logic; replace
- E.6 [P2] (S) Rewrite the editing-quality-validator tests to assert
computed values. Replace
toBe(true)tautologies with metric assertions (e.g. edit fidelity / multi-view consistency against a known fixture). Acceptance: the validator would FAIL on a no-op edit. Done/verified 2026-06-14: readediting-quality-validator.ts+.test.tsthis session — the validator is a REAL honest gate (createMetricCheck :233-256: a metric with no measured value →warning+value: undefined, never a fabricated score;passesQualityBarrequires zero warnings AND zero threshold fails), and its tests ALREADY assert computed values, not tautologies: an out-of-threshold fixture asserts the exactfailedMetricIds).toEqual(['epipolar-error','depth-consistency'])andpassesQualityBar === false, and the "requires measured metrics before signoff" test proves a NO-OP edit (no real measurements) → warnings →passesQualityBar === false. So the acceptance ("the validator would FAIL on a no-op edit") is met by the existing real gate + computed-value tests; the only residualtoBe(true)is the capability-contract descriptor, not a quality-metric tautology. No rewrite needed — verified, not assumed.
Phase F — Generated-asset → Unreal cook/import bridge (the last mile)#
Real primitives exist (libs/bellona/unreal/src/cook/cook-runner.ts:124-244
RunUAT; headless-import.ts:159-262 UE Python AssetImportTask) but nothing
dequeues a cook job and no committed .uasset is editor-cooked generated art.
- F.1 [P2] (M) Build the cook-orchestrator worker. A service/worker that
dequeues cook jobs and invokes
cook-runner+headless-import. Acceptance: enqueue a job → the worker runs RunUAT/import → a cooked artifact path is returned + recorded; fail-loud if UE is absent. Done 2026-06-14:CookOrchestrator(libs/bellona/unreal/src/cook/cook-orchestrator.ts, exported from the cook module + package index) — a FIFO queue (InMemoryCookJobQueue, a real swap-point for SQS/Redis) + a worker that dequeues cook/import jobs and drives the injectedUnrealCookRunner.cook/HeadlessImporter.importAssets, recording eachCookJobOutcome: a cook →cooked+ the archive/staging (or derivedSaved/Cooked/<platform>) artifact path; an import →imported+ the editor's confirmedimportedObjectPaths. FAILS LOUD with the real error code when Unreal is absent (RUNUAT_NOT_FOUND) or the cook/import errors — never a fabricated artifact. 7 tests (cook success + derived path, RUNUAT_NOT_FOUND fail-loud, UAT-ran-but-failed, import success, import-incomplete, mixed FIFO drain) via runner/importer test doubles at the process boundary; 40/40 cook suite green; typecheck + stub scan clean. The on-engine run at volume is §F.3 ([~]); the isis-export→import wiring is §F.2. - F.2 [P2] (M) Wire isis-exported FBX/glTF → headless import → cooked
.uasset. Connect the isis 3D/image export output toHeadlessImporter. Acceptance: a generated mesh is imported and cooked end-to-end (a real.uassetproduced), or[~]with the precise on-engine blocker named. 2026-06-14:[~]— producing a real.uassetrequires running the UnrealEditor ImportAssets commandlet + a cook, and the on-boxUnrealEditorREFUSES to run as root (must run asueagent), needs a built V-project, and is the on-engine run §F.3. The bellona-side machinery is in place: §F.1'sCookOrchestrator+CookImportJob+HeadlessImportTaskaccept any FBX/glTFsourcePath(an isis export included) and drive the realHeadlessImporter. The isis-export→import-task MAPPING cannot live in@bellona/unreal(scope:bellona may only depend on scope:shared/contracts/auth/bellona — NOT scope:isis), so it belongs at a composition/app layer that imports both; the on-engine import+cook is the genuine blocker → tracked under §F.3. 2026-09-18: open for an agent. The executing machine has Unreal 5.5, so the on-engine import and cook is no longer the blocker. The residue is the composition layer that maps an Isis export to aHeadlessImportTask(outside@bellona/unreal, which may not depend on Isis), proven by one generated mesh imported and cooked to a real.uasset. - Tracked once, elsewhere, since 2026-09-18: the
[UE-AUD-004]cook items ofV1_V9_AUTONOMOUS_CONTENT_SOTA_GAP_CLOSURE_TODOS_2026-07-15.md("Produce/cook Isis cosmetic, venue, and related executor …", "Cook, place, and validate both throughV5/ue/V5.uproject…") are this work, and that ledger declares this one history. The executing machine has Unreal 5.5. F.3 (L) On-engine cook of generated art at volume. Run the bridge on the on-box UE5.5 asueagent(editor refuses root — seereference_onbox_unreal_engine). Acceptance: N generated assets cooked + consumed by a V-project;[~]until the on-engine run is actually executed. - F.4 [P3] (M) Real USDZ packaging + cross-DCC transform math.
libs/bellona/unity-agent/usdz-ar-quick-look-export.ts(delegates to Unity codegen) andcross-dcc-usd-workflow.ts(no Y-up↔Z-up / cm↔m matrix math). Implement real packaging (zip + 64-byte alignment) and real coordinate/unit transforms in TS, or label honestly as a Unity-runtime shim and mark[~]. Acceptance: a USDZ that opens in AR Quick Look (or[~]); a transform test asserts a known Y-up→Z-up matrix result. Done 2026-06-14: implementedcross-dcc-transform.ts— REAL coordinate/unit transform math (no more "left to the importer to guess"): per-DCC conventions (blender Z-up/m, maya Y-up/cm, houdini Y-up/m; USD Y-up/m/ right-handed; Unity left-handed),upAxisAlignmentMatrix(Z-up↔Y-up = ±90° about X), handedness flip (negate Z), and cm→m unit scale, composed into one 4×4 matrix withapplyMat4Point. WIRED into the workflow plan (createBellonaUnityCrossDccUsdWorkflowPlannow returnscoordinateConversion, computed fromsourceDcc). Computed-value tests (the acceptance bar): Z-up→Y-up known matrix[1,0,0,0, 0,0,1,0, 0,-1,0,0, 0,0,0,1]; Blender +Z→USD +Y, +Y→−Z; Maya 100 cm→1 m (scale 0.01); Houdini identity; Unity→USD handedness Z-flip; Blender↔USD round-trip — plus the plan-consumed assertion. 10/10 unity-agent cross-dcc tests green; typecheck + stub scan clean. The USDZ AR Quick Look export stays a Unity-runtime shim →[~]for that criterion: opening a.usdzin AR Quick Look is an on-device (iOS) validation, not runnable here; the transform-math criterion is fully met.
Phase G — Measure the taste signal (calibration & benchmarks)#
The judge panel is architecturally calibrated but its κ-vs-human has never been run with a live provider.
- G.1 [P1] (M) Live calibration run per content type. Feed the panel the
human-rated gold items (
libs/euterpe/evals/.../human-eval+ any Studio accept/reject/edit records) with real provider creds; compute judge↔human Cohen's κ / correlation per content type. Acceptance: a calibration report with κ per content type; CI fails if a shipped judge's κ drops below its recorded baseline (the drift gate already exists — feed it real numbers).[~]only if no provider creds are available; then say so. 2026-06-14:[~]— no live LLM provider creds in this sandbox (only Claude Code session env vars; noANTHROPIC_API_KEY/LLM_ENDPOINT). The κ/drift infra is real and runnable (cohenKappainhuman-eval.ts,scoreBenchmark/drift.ts, and theGOLD_BENCHMARKnow covers all 5 content types incl. wellness), but the JUDGE PANEL needs a real model — saying so per the task's own instruction rather than fabricating κ numbers. 2026-09-18: open for an agent. The note's blocker, no provider credentials, no longer holds:OPENROUTER_API_KEYis in the environment file. Run the panel on the cheapest model that can judge (CLAUDE.md, "Test & harness model binding"), report the measured kappa per content type, and claim nothing about a stronger panel that was not run. - G.2 [P2] (M) External-benchmark sanity run. Run EQ-Bench Creative
Writing v3 (incl. slop score) + a LitBench-style reward eval against the
panel/reward model; detect bias / reward hacking. Acceptance: a periodic
report; large divergence from public norms triggers recalibration
(
external-benchmark.tslogic exists — run it for real). 2026-06-14:[~]— same blocker as G.1: the run needs a live model panel/reward model (no provider creds in sandbox).external-benchmark.tsis real and unit-tested; running it "for real" requires creds. 2026-09-18: open for an agent on the same footing as G.1. - G.3 [P2] (S) Gold-set persistence wired to a store. The
override→gold-label seam exists (
hitl-judge-evidence.ts) but isn't wired to a production store. Persist human accept/reject/edit decisions to the Postgres gold-set table (the §3.2a Prisma backend) so Phase 5/active-learning has real data. Acceptance: human decisions land in a queryable gold-set table across restart. Done 2026-06-14: built the missing "§3.2 service" —GoldSetEntryStore(libs/oshun/persistence/src/gold-set-entry-store.ts) — that wires the two pure human-decision seams into the durablev1_cross_cutting_gold_set_entrytable via the existingContractPersistenceService.recordOverride(label, prov)maps the @yemaya §3.4OverrideGoldLabel(accepted structurally, no orchestration dep) into a schema-validatedGoldSetEntryRecord: a realoverridePromotionKindderivation (reject→reject-as-bad; accept of panel-FAILED content→the high-valueoverride-as-good; agreeing accept→accept-as-is) andoverrideSignalTagsthat encode the panel verdict/score + human agreement as QUERYABLE tags (judge-agreement:disagreeis the exact miscalibration signal §5.4 lists).record(input)covers the StudioCapturedDecisionpath (incl.edit-then-acceptwith its edited-content ref), enforcing the same cross-field invariantsvalidateGoldSetEntrydoes (fail loud on an edit with no content / a reject with content / a malformed UUID).listDurableRows(tenant)projects rows to theDurableGoldSetEntryRowshape §5.1'sgoldSetFromEntryRecordsalready assembles. 12 computed-value unit tests run the REAL persistence + Zod path over a multi-row in-memory delegate; 1 integration test was RUN against a real Postgres (goldset_g3_test, schema pushed) — two HITL overrides recorded through the seam, then a FRESH PrismaClient + store reads them back as durable rows with the right promotionKinds +panel-score:73/judge-agreement:disagreetags, proving decisions land queryable AND survive a process restart. 84/84 persistence unit tests green (14 DB-gated integration skipped without creds); typecheck clean; the production file has zero stub-scan hits (the only hits are test-double language in*.test.ts, allowed + scan-skipped). The Postgres-backedGoldSetStoreaggregate seam is a thinlistDurableRows→goldSetFromEntryRecordscomposition Phase 5 owns; the live calibration RUN that consumes this data stays §G.1[~](no provider creds).
Phase H — Stage per-product volume under the quality stack (quality-before-scale)#
Do NOT start a product's volume generation until its quality + diversity gates are wired (Phases A–C).
- H.1 [P2] (L) V5 — content famine, staged. Generate side-quest +
dialogue content (talk/escort/hunt/scavenge patterns) through best-of-N +
judge gate + corpus diversity gate + human-assisted approval — not the
single-pass
libs/hathor/narrative-generation/src/batch.ts. Stage to a few hundred items, measure quality + diversity, then scale toward the 12k target. Acceptance: a measured-quality, diversity-gated batch; explicit STOP if quality/diversity regresses at scale. UE-sideV5Procgenconsumption[~]. Done 2026-06-14: addedrunStagedVolume(libs/hathor/narrative-generation/src/staged-volume.ts) — the layer ABOVE the single-batchQualityGatedQuestBatchGeneratorthat the ledger says to use instead ofbatch.ts. It generates in STAGES (a few hundred at a time, not one 12k pass), and after each stage measures per-stage mean quality (judge floor) + corpus diversity (REUSING the sharedcorpusDiversity— cluster coverage + mean pairwise distance + cumulative near-duplicate rate) and HALTS with a precise reason the moment the trend breaks:quality-below-floor(a stage can't sustain passing content — the famine),quality-regressed(stage mean drops > margin vs the best prior stage),diversity-below-floor(a stage mode-collapses),diversity-regressed,duplication-at-scale(a new stage near-duplicates earlier content — real cross-stagenearDuplicateRate),stage-empty, ortarget-reached. The per-stage generation is an injectableStageGenerator(best-of-N + judge gate behind a real provider — the[~]model boundary); a generator that throws (no provider) propagates fail-loud, never fabricating.questBatchStageGeneratoris the production adapter that drives the realQualityGatedQuestBatchGeneratorper stage and maps its shipped (submitted_for_review) outcomes to staged items. 9 tests use an injected scripted generator ONLY at the model boundary — the quality floors, diversity measurement, and regression STOP are REALcorpusDiversityover real texts: a healthy run completes at target; a low-quality stage, a mode-collapsed stage (measured clusterCoverage < 0.6), a sharp quality-regression, cross-stage duplication (measured nearDuplicateRate > 0.2), and a dry generator each STOP with the right reason and ship only the healthy prior stages; the adapter maps only shipped outcomes. 33/33 narrative-generation tests green; typecheck + eslint (0 warnings) + stub scan clean. The live 12k generation (real provider) + UEV5Procgenconsumption stay[~]; the staged orchestration, gates, and regression-STOP are real. - H.2 (L) V2 — fighter Side Story vertical slice. One fighter's Side
Story pack (Hathor §9.6 records → prose via the quality stack → Isis
concept art → Bellona cook) end-to-end with judge gates. Acceptance: a
playable slice in
V2/uewith a quality-gated, provenance-bound bundle ([~]for the on-engine cook + concept-art generation at volume). 2026-09-18: a playable slice inV2/uewaits for V2's vertical slice, V2.VS.1–7 (V2/V2_TODOS.mdsection 0).blocked:upstream - H.3 [P3] (M) V7 — forge AI-assist quality verification. Confirm
libs/maya/forge-assistgenerated artifacts are judged/refined before reaching the sandbox (within the platform/realm trust boundary). Acceptance: a low-quality assist is improved or rejected with named reasons; a real run exists ([~]for the V7 sandbox integration). Verified 2026-06-14: readforge-assist.ts+forge-assist.test.tsthis session —ForgeAssistServiceruns the capability policy AND a §9.6ForgeQualityGate(injected, panel-agnostic) BEFORE any artifact is proposed:applyQualityGateassesses the source, and while belowminScoreand refine passes remain it re-runs the assistant with the named quality reasons appended (critique→re-write), keeping the best-scoring attempt; a still-below-bar artifact returnsquality_rejectedwith the best source + named reasons and NEVER reaches the sandbox. Tests assert real computed values: a high-quality artifact clears (score 85, 0 passes); a low-quality one isquality_rejectedwith the named reason'no input validation; no edge-case guards'(rejected source returned, not installed); a low→high refine lifts it tocleared(refinePasses 1); a policy violation short-circuits before the gate. Added the lib's missing localvitest.config.ts(was falling through to the root projects config). 15/15 forge-assist green; typecheck clean. The injected gate IS the platform/realm trust-boundary seam; the live V7 sandbox mount is[~]. - H.4 [P3] (M) V6 — dialogue at runtime through the gateway. Depends on
C.2. Acceptance: V6 dialogue passes the §9.5 judge gate through the
gateway at runtime (
[~]for the V6 HTTP/on-engine mount). Done 2026-06-14: builds on C.2 — added runtime tests driving the §C.2.4 moirai gateway mount (createMoiraiCognitionGatewayMount) through a realCognitionGatewayconfigured with a §9.5DialogueQualityGate: a below-bar Ori reply ("flat, low-energy") is BLOCKED at runtime (response.quality.status === 'blocked', score 35) while a strong reply clears (cleared, score 90) — i.e. V6 dialogue passes the §9.5 judge gate through the gateway at runtime, with per-tier budget + kill-switches (C.2.4) around it. 7/7 mount tests green. The actual V6 HTTP/on-engine host that callshandleDialogueover the wire stays[~]; the TS runtime path (mount → gateway → §9.5 gate → blocked/cleared verdict) is proven.
Phase I — V8 Ariadne (self-authoring detective) Phase 0 (spec → first vertical)#
V8 is 0/90 tasks, no code. "LLM proposes; a constraint solver disposes." Build the smallest end-to-end vertical first; reuse the shared stack + V5 case format.
- I.1 [P3] (M) Stand up
libs/v8skeleton + the seven gates (G1–G7) as a@oshun/content-release-gatessuite. Do not build a bespoke per-product checker. Acceptance: av8-casegate suite (fairness/solvability/voice/etc.) registered and unit-tested. Done 2026-06-14: created@oshun/v8-case-gates(libs/v8/case-gates, scope:v8; addedlibs/v8/*to pnpm-workspace + tsconfig path) —buildV8CaseGates/evaluateV8Caseregister the seven V8 gates on the SHARED@oshun/content-release-gatesReleaseGateService(no bespoke checker), derived from the V8 spec (§I.1–I.3) + fair-play detective rules: G1 fairness (every solution clue presented before the reveal), G2 solvability (the symbolic CSP proved a UNIQUE solution — the §I.2 flag), G3 clue-grounding (every solution clue exists in the case — no invented evidence, reuses the §7.2createGroundingGate), G4 voice (suspect distinctiveness), G5 misdirection (≥1 red herring but ≤ max — fair, not a maze), G6 prose, G7 safety. 7 tests: the seven gate ids in order + all required; a fair/unique/grounded case clears; G1 blocks a withheld solution clue, G2 an under-determined case, G3 an invented clue, G5 no-herring AND a maze, G4/G6/G7 low voice/prose/safety. 7/7 green; typecheck + stub scan clean. The CSP that PRODUCES the G2 uniqueness proof is §I.2; per-case prose/art/voice generation is §I.3. - I.2 [P3] (L) Symbolic mystery skeleton + CSP unique-solution proof.
Generate ground truth + clue logic and prove a unique solution
(CSP/ASP, e.g. clingo-class). Acceptance: a generated case has a
machine-verified unique solution; an under-determined case is rejected.
Done 2026-06-14: created
@oshun/v8-case-csp(libs/v8/case-csp, scope:v8; registered in pnpm-workspace + tsconfig.base) — a REAL finite-domain constraint solver (no boolean stub).csp-solver.ts: backtracking search with node consistency, MRV variable ordering, and forward checking (with an undo log), enumerating solutions up to a cap;proveUniqueSolutionfinds up to two →unique/under-determined/unsatisfiable. Constraints are real relations: equals/not-equals/in/ all-different/implies + a general n-aryrelationpredicate.mystery-skeleton.ts: aMysterySkeleton(dimensions + groundTruth + presented/withheld clues) compiles ONLY the player-visible clues into aCspModel;proveCaseUniquenessproves the visible clues admit exactly one solution AND that it equals the ground truth — surfacinguniqueSolutionProven(the §I.1 G2 flag), the verdict, and the witness. Rejects (uniqueSolutionProven:false, honest reason): under-determined (a deducing clue removed → 2 solutions), over-constrained/contradictory (unsatisfiable), and the real generation bug where the visible clues uniquely prove a DIFFERENT culprit than the author's ground truth (matchesGroundTruth:false). Malformed skeletons (GT out-of-domain / missing a dimension) fail loud. Solver correctness is anchored against the canonical Zebra/Einstein puzzle — the spec asserts it finds the one known solution (Norwegian drinks water, Japanese owns the zebra, full positions). End-to-end: the prover's flag drives the real@oshun/v8-case-gatesG2 gate — a CSP-proven case clears the suite; an under-determined one isblockedwithg2:solvabilityin blockedGateIds. Codex review (read-only, gpt-5.4) found one real soundness hole — a 0-aryrelationwas never evaluated → could falsely reportunique; FIXED with a leaf-level full-constraint check + a regression test. 20/20 tests green; typecheck + eslint (0 warnings, module boundaries) + stub scan clean. The clingo/ASP sidecar (apps/v8/minos-asp-sidecar) stays out of scope — a real TS CSP prover meets the §I.2 acceptance in-repo; per-case prose/art/voice generation is §I.3. - I.3 [P3] (L) Prose / art / voice generation per case through the shared
stack. Suspect portraits + evidence (Stability/Flux via isis),
crime-scene art + props (Hunyuan3D/Meshy via isis), case music (Suno
seam), VO (ElevenLabs seam) — each judged/gated + C2PA-stamped.
Acceptance: one fully generated case bundle with provenance; missing
providers fail loud
[~]. Done 2026-06-14: created@oshun/v8-case-bundle(libs/v8/case-bundle, scope:v8; registered in tsconfig.base) —forgeCaseBundlecomposes the whole V8 stack: it PROVES the case is uniquely solvable first (@oshun/v8-case-csp§I.2) and REJECTS an under-determined case (CaseNotSolvableError) BEFORE spending any generation (a test asserts the writer never runs for an unsolvable case); generates prose + clues via an injectableCaseProseWriter(the LLM boundary — absent ⇒CaseBundleNotConfiguredError, never fabricated); generates each media asset (suspect-portrait / evidence-image / crime-scene-3d / case-music / voiceover) through injectableCaseMediaGeneratorprovider boundaries (Stability/Flux/Hunyuan3D/Meshy/ Suno/ElevenLabs) — an absent provider for a kind yields an honest{status:'not-configured', reason}slot, NOT a fake asset; C2PA-stamps every PRODUCED asset with the shared@oshun/content-signing(realsha256Hexof the bytes + Ed25519 signature over a canonical manifest); and gates the assembledV8Casethrough the §I.1 seven-gate suite. Returns the bundle + provenance (solution hash, generated-asset count, not-configured kinds, signer key + public key). 5 tests (test doubles ONLY at the LLM/media provider boundaries — the solvability/C2PA/gating under test are real): a solvable case clears the gates with 2 generated + 1 not-configured (music) asset; every generated asset's manifest verifies and its digest equalssha256Hexof the bytes; tampering the digest or uri fails C2PA verification; an under-determined case is rejected pre-generation; no writer fails loud. 5/5 green; typecheck + eslint (0 warnings, cross-scope module boundaries) + stub scan clean. The LIVE providers (real image/3D/music/VO models) are the[~]remainder; the solvability gate, asset C2PA stamping, gating, fail-loud seams, and provenance are real. - I.4 (L) Compile a generated case into the V5 runtime case format + play
it in
V8/ue. Acceptance: a generated case is playable in V5/UE ([~]on-engine). 2026-09-18: the inline[~]mark is gone — the executing machine has Unreal 5.5, so playing the case inV8/ueis work, not an environment gap. It still waits on a V5 runtime case format with real authored cases to compile into (V5-002 of the V1–V9 ledger; V8 tasks 4.6 and 9.5 wait on the same corpus).blocked:upstream
Phase J — V9 Metis (consumer learning) Phase 0 (spec → first vertical)#
V9 is 0/57 tasks, no code, but its composed domains (Metis, Nyx, Kalika, Mnemosyne, Sophia) are real. Gap = connective tissue + consumer UX. V9 mandates reusing the platform content-release gate ("no eighth loop").
- J.1 [P3] (M) Stand up the seven-gate eval suite (G1–G7) on the platform
content-release gate. Acceptance: a
v9-lessongate suite (truth/grounding/ teachability/etc.) registered + tested; no bespoke checker. Done 2026-06-14: created@oshun/v9-lesson-gates(libs/v9/lesson-gates, scope:v9; addedlibs/v9/*to pnpm-workspace + tsconfig path) —buildV9LessonGates/evaluateV9Lessonregister the seven V9 gates on the SHARED@oshun/content-release-gatesReleaseGateService(no bespoke checker, per the "no eighth loop" mandate), each derived from the V9 spec (§J.1–J.3): G1 truth (Aletheia — no false/unverified claim), G2 grounding (every claim bound to a Sophia source pin — reuses the §7.2createGroundingGate), G3 teachability, G4 safety, G5 explorable (≥1 REAL computed Nyx/Kalika explorable, not a static asset), G6 adaptive (per-learner difficulty in [0,1]), G7 retrieval (Mnemosyne checkpoint). All seven are requiredGateDefinitions overgateFromEvalScore/gateFromManifestCheck/createGroundingGate. 7 tests: the seven gate ids in order + all required; a grounded/true/teachable/ explorable lesson clears; G1 blocks a false claim, G2 a pin-less claim, G5 a static-only explorable, G7 a missing checkpoint, G3/G4/G6 low-teach/ unsafe/out-of-range. 7/7 green; typecheck + stub scan clean. (J.2/J.3 lesson-forge + explorables remain — they need the live agentic loop + provider/WASM.) - J.2 [P3] (L) Lesson forge on the shared agentic loop, grounded to Sophia
pins. "Ask a wonder → grounded lesson"; every claim bound to a Sophia
source pin (Aletheia truth gate) — reuse the grounding gate. Acceptance: a
lesson with an ungrounded claim is blocked; a grounded one passes with
source pins. Done 2026-06-14: added
forgeLesson(libs/v9/lesson-explorables/src/lesson-forge.ts) — the V9 forge that routes generation through the SHARED agentic loop (an injectableLessonDraftWriter, theCognitionGatewaymodel boundary), grounds every claim to a Sophia source pin (SophiaPinGrounder) + an Aletheia truth verdict (AletheiaTruthChecker), assembles the lesson with its §J.3 computed explorable / adaptive score / retrieval checkpoint, and gates it through the shared §J.1 seven-gate suite (evaluateV9Lesson— reuses the grounding gate, no new loop). A claim with no Sophia pin is BLOCKED at G2; an Aletheia-untrue claim at G1; a grounded+true lesson clears with its pins attached. The model boundary fails loud (LessonForgeNotConfiguredError) when no writer is wired (no provider in this sandbox) — never fabricating a lesson — and refuses a claimless (unfalsifiable) draft. 5 forge tests use test doubles ONLY at the writer/Sophia/Aletheia dependency boundaries (the grounding + gating under test are real): grounded+true → cleared withsophia://pins; one ungrounded claim → blocked withg2:grounding; an unverified claim → blocked withg1:truth; no writer → fail loud; no claims → refused. 21/21 lesson-explorables tests green; typecheck + eslint (0 warnings) + stub scan clean. The LIVE writer (a real provider behind the shared loop) + Sophia/Aletheia services stay[~]— the forge orchestration, grounding, truth-gating, and fail-loud seam are real and tested. - J.3 [P3] (L) Embodied tutor + ≥1 computed explorable + adaptive score
per lesson. Tutor voice/face/persona (Psyche+Hathor+Isis); a real Nyx
WebGL sky or Kalika WASM physics explorable; a Mnemosyne retrieval
checkpoint. Acceptance: a lesson renders a real computed explorable + a
retrieval check; provenance bound. Done 2026-06-14: created
@oshun/v9-lesson-explorables(libs/v9/lesson-explorables, scope:v9; registered in tsconfig.base) — the FIRST consumer of the real-but-dormant shared engines, composing them (no new physics/psychometrics, per the "reuse the shared stack" rule). Computed explorable (G5):buildOrbitExplorableintegrates a real two-body Kepler orbit with@kalika/symplectic's velocity-Verlet symplectic integrator — perihelion start(r₀,0), vis-viva speed√(GM(1+e)/r₀), Kepler-III period — and reads back the trajectory + the engine's energy diagnostic;computedis true only when a finite multi-sample trajectory was produced. Computed-value tests: a circular orbit conserves energy (drift<1e-3) and radius (band<0.01), v₀=1 & T=2π; an e=0.3 ellipse has the right perihelion/aphelion geometry (aphelion≈a(1+e)) and bounded symplectic energy. Adaptive (G6):computeAdaptiveDifficultyestimates learner ability θ via Mnemosyne's IRT MLE (estimateAbility, Newton-Raphson) then calibrates next-item difficultyb*=θ−logit(p*)to a target success rate — the verifiable Rasch identityirt1PL(θ,b*)≈p*is asserted to 6 dp; a stronger learner → higher difficulty; higher target → easier. Retrieval (G7):buildRetrievalCheckpointruns Mnemosyne SM-2 (sm2Review, explicit clock — no fabricated time) producing a durablemnemo:…checkpoint ref; tests assert the exact SM-2 ladder (1→6→round(int·ease)) + lapse reset.assembleV9Lessonbinds all three into aV9Lesson+ provenance (run id, explorable content hash + energy drift, θ, adaptive difficulty, SM-2 ref). End-to-end:evaluateV9Lesson(assembled)CLEARS all seven shared gates; swapping the computed explorable for a static asset is blocked by G5, and an empty checkpoint by G7 — proving the gates consume the real computed artifacts. Codex-reviewed (read-only, gpt-5.4): physics initial conditions, potential gradient, and the Rasch calibration confirmed correct, no sign/formula bugs (one comment-wording nit fixed). 16/16 tests green; typecheck + eslint (0 warnings, cross-scope module boundaries) + stub scan clean. The embodied tutor voice/face (Psyche/Hathor/Isis providers) + the live agentic lesson-forge (§J.2) stay[~](provider-gated); the computed explorable + adaptive score + retrieval checkpoint + provenance — the stated acceptance — are real and met. - Tracked once, elsewhere, since 2026-09-18: the closed-beta item of the V1–V9
ledger's V9 slice ("Run closed beta, mobile/offline, localization, cost,
safety, privacy, …"); it needs a human cohort. J.4 (L) Closed beta +
efficacy study. Acceptance: operational;
[~].
Phase K — External-gated honest deferrals (track, do not fake)#
- K.1 (XL) Trained taste model (DPO / reward model) v2. Train a
dedicated preference scorer on the gold sets when volume permits. Requires
GPU/training infra. Acceptance: trained scorer beats the panel on held-out
agreement, or stays
[~]with an honest reason. Never fabricate metrics. 2026-09-18: training a scorer needs a compute budget and a gold set large enough to train on; neither has been decided.blocked:governance - K.2 (M) Inference-time thinking budget tied to quality. Wire the real
budget_tokensseam (libs/isis/ai-providers/.../claude4-adapter.ts:467) into deep/exhaustive modes for hard generation/judging. Acceptance: deep mode demonstrably allocates a thinking budget that reaches the model and improves the judge score on a hard fixture (needs a live model →[~]). 2026-09-18: open for an agent. Carry the budget through the provider-agnostic request, prove that it reaches a model on OpenRouter's reasoning parameter with the cheap test model, and cover the Claude adapter'sbudget_tokenspath with a transport double; no test binds a frontier model. - K.3 (XL) On-engine cooks, certification, VO/voice, art-at-volume. The
cross-cutting on-engine + vendor deferrals (UE cook/cert, ElevenLabs VO,
Suno music, concept-art at volume). Track per product;
[~]until executed on the real engine / with real vendor creds. 2026-09-18: a roll-up of vendor and engine deferrals (console certification, ElevenLabs, Suno, art at volume); each product's tracker carries its own items, and the vendor keys are the owner's.blocked:external
Suggested critical path#
A.1–A.4 (honesty) → B.1–B.2 (consume concert + commentary gates) → C.1–C.2 (connect Lilith + V6 generators) → G.1 (measure the taste signal live) → A.2/D (real concert signing) → E.1 (3DGS triage) → F.1–F.2 (asset→engine bridge) → H.1 (V5 staged volume) → J (V9, de-risked) → I (V8) → E.2+ / F.3 / K (heavy + external-gated).
Rationale: stop the fabrications first (trust + CLAUDE.md compliance), then
get maximal leverage by consuming gates and connecting generators that already
exist (B, C) — that is where "SOTA engine, partial reach" becomes "SOTA reach"
with the least new code — then measure (G), then the heavier asset and product
build-outs.