Oshun Platform · Features

Metis — Education and Tutoring

A focused page within the Oshun Platform Features documentation. The full map and every sibling page live in the Features hub.

19sections22 minread10tables

On this page

Release: V1.2. Metis is not part of V1.0. Everything on this page stays in the tree and stays worth building — the room has to be stocked and reviewed before it opens — but no V1.0 console may advertise, link to, count, or compose it. V1.0 opens Tara, Nyx, Arete, and Nisaba; see V1/BRAND.md.

Metis is the educational substrate of Oshun V1 — the domain that turns approved source material into grounded courses, runs an adaptive tutor loop, calibrates assessments with real psychometrics, and emits grades and integrity verdicts to institutional systems. It serves three audiences at once: the self-directed learner who wants a structured path through hard ideas, the teacher or institution that needs standards-conformant delivery and a defensible gradebook, and the platform operator who has to keep a high-risk bring-your-own-model surface safe. It sits in the same single Oshun shell as the contemplative domain (Tara — Rituals and Contemplative Practice), the goals domain (Arete — Goals, Habits, and Reflection), and the scholarly-study domain (Nisaba — Scholarly Study).

Among the V1 domains, Metis is one of the most heavily implemented at the library level: eleven canonical Zod contracts, real Item Response Theory, real Bayesian Knowledge Tracing and FSRS-5, a full LTI 1.3 / SCORM / OneRoster / QTI3 / Caliper / Open Badges integration layer, and a ~980-LOC tenant-model safety harness all exist on disk. Yet it is not a live launch surface. The domain registry marks Metis availability: 'planned', which means getAvailableDomains() filters it out of the shell. This page reads Metis as product and as code, and it is candid throughout about the gap between the roadmap intent ("launch-blocking") and the current launch state ("planned").

The completion state of every item lives in ../TODOS.md (bare §N references point there); cross-domain build ordering lives in ../DEPENDENCIES.md (deps§N). The hub feature list is ../features.md. Companion runtime views are Customer Domains and Cross-Domain Support.


What is real, what is planned#

Because this domain's docs have historically overstated launch readiness, it is worth front-loading the honest split before describing the parts.

Implemented (verified by reading code):

  • All eleven canonical contracts are real Zod schemas in libs/contracts/src/metis/index.ts, re-exported as a namespace (export * as MetisContracts from './metis', libs/contracts/src/index.ts:103).
  • The six-band mastery model with per-band evidence vectors and half-life decay (libs/metis/learning/src/mastery/).
  • The six-axis personalization manifold as a real schema (LearnerPersonalizationStateSchema, libs/contracts/src/metis/personalization.ts).
  • A typed institutional gradebook with correction events and role-redacted views (libs/contracts/src/metis/gradebook.ts and libs/metis/gradebook/src/emission.ts).
  • Real psychometrics: 1PL/2PL/3PL IRT with calibration and DIF monitoring (libs/metis/assessment); BKT, FSRS-5, and graph knowledge tracing (libs/metis/adaptive).
  • The six-core-discipline taxonomy as typed data with anchor mappings (libs/metis/learning/src/subject-taxonomy/).
  • Real standards plumbing — LTI 1.3 id_token/JWKS verification, SCORM-2004 RTE, OneRoster dry-run, QTI3 export/import, Caliper, Open Badges (libs/shared/inbound-integrations and libs/metis/integrations/src/standards/).
  • A full BYOM tenant-model safety harness with quarantine, kill-switch, fail-closed, and abuse monitoring (libs/shared/inbound-integrations/src/byom-model.ts).
  • The grounded-generation VerificationGate and generate-verify-refine loop (libs/metis/verification).
  • BFF routes for integrity adjudication/appeal/audit, tutor-session memory, and BYOM decisions (apps/oshun/bff/src/routes/).

Aspirational / not yet:

  • Metis is not a live shell surface. availability: 'planned' (libs/oshun/domain-registry/src/registry.ts:489) is filtered by getAvailableDomains() (registry.ts:503). The 2026-06-23 triage confirms the shell drops Metis to planned post-hydration (shell domain count 5→4). "Launch-blocking V1 scope" is a roadmap intent, not the current state.
  • The P95 ≤ 600 ms adaptive-loop latency budget is a spec assertion. There is a related budget-ceiling primitive in the verification lib (MODE_CEILINGS, checkBudgetCeilings in libs/metis/verification/src/hardening/budget-ceiling.js), but no runtime gate was found that enforces a 600 ms next-item ceiling on the live tutor loop.
  • Several cross-domain wirings the prose claims do not exist as files. Only aja, iris, isis, lilith, psyche, sophia, themis, and yemaya ship a *-canonical-wiring.ts under libs/metis/integrations/src/. There is no Tara, Nyx, Veritas, Nisaba, or Arete canonical wiring, despite the feature list naming them (features.md).
  • The headline BYOM ingest-to-course pipeline is graded "partial/uncovered" in the 2026-06-22 completeness audit. To be precise about the split: the BYOM contracts and gate primitives (byom.ts, byom-model.ts, the VerificationGate) are real on disk; what is partial is the end-to-end ingest-to-course wiring that would carry a member's uploaded material through validation into a live course.
  • There is no dedicated metis PostgreSQL database. docker/docker-compose.dev.yml's POSTGRES_MULTIPLE_DATABASES lists yemaya,lilith,isis,iris,sophia,hathor,bellona,calliope,tara,maat,nisaba,shakti,cybele,kalika,lakshmi,athena,oyametis is absent. Metis's storage strategy (shared oshun_dev vs. domain tables) is undocumented and is a genuine gap.

Where Metis lives in the product#

Consumer surfaces#

The consumer hub is /metis, with presentational depth under apps/oshun/web/src/app/metis/. The real route tree is larger than the four surfaces the feature list enumerates (features.md lists only /metis/assessment, /metis/byom, /metis/lesson, /metis/tutor). On disk the directory tree is:

Route Purpose
/metis Consumer hub landing
/metis/assessment Assessment delivery surface
/metis/byom Bring-your-own-material entry
/metis/lesson A single lesson
/metis/lessons Lesson list
/metis/tutor Tutor runtime
/metis/session A tutoring session
/metis/courses/new Course creation
/metis/ingest Source ingestion
/metis/upload File upload

The feature list's omission of /metis/lessons, /metis/session, /metis/ingest, /metis/upload, and /metis/courses/new is under-listing, not inaccuracy. The heavier study, mastery, and academic-integrity tools are mounted inside this consumer hub rather than a separate power-user namespace.

The /domains/metis vs /metis/* split#

There is a real disagreement between the registry and the shipped web routes that the feature list notes but does not reconcile. features.md states "Metis does not yet ship a /domains/metis/* power-user namespace" — true at the web-app level, since there is no apps/oshun/web/src/app/domains/metis directory. But the domain registry declares route: '/domains/metis' and 'bff-base-path': '/api/oshun/domains/metis' with launch.defaultPath: '/courses' (registry.ts:425, 435, 448). The registered route family (/domains/metis) and the shipped consumer routes (/metis/*) diverge; the /domains/metis route is declared metadata that the consumer shell does not yet materialize. This is consistent with the domain still being planned.

Operator review surface#

The shipped review surface is /operator/metis (apps/oshun/web/src/app/operator/metis/page.tsx), not an /admin/metis route. The feature list's reference to "Admin Metis dashboards" (features.md) maps to two distinct things: (1) the consumer-shell review UI at /operator/metis, fed by BFF routes prefixed /metis/integrity under operator scope, and (2) the standalone apps/metis/admin application (62 .ts/.tsx files). There is no /admin/metis route inside apps/oshun/web.

Standalone Metis apps#

All five apps/metis/* subdirectories exist — correcting an earlier ARCHITECTURE snapshot that doubted mobile: web (93 ts/tsx files), admin (62), api-gateway (29), worker (21), and mobile (6).

Registry metadata#

The Metis entry in libs/oshun/domain-registry/src/registry.ts:422-490:

Field Value
id metis
route /domains/metis
bff-base-path /api/oshun/domains/metis
deep-link-prefix oshun://metis
auth scopes course:read, course:write, tutor:session, assessment:submit
step-up actions submit-assessment, publish-course-package, connect-lms
launch.defaultPath /courses
launch.quickActionPath /tutoring
accentColor #2563EB
icon graduation-cap
availability planned

Subject-matter focus: the six core disciplines as code#

Metis's curriculum is deliberately weighted toward the six disciplines that converge on the human mind, meaning, belief, behavior, culture, and our place in the cosmos — philosophy, religion, psychology, neuroscience, anthropology, and astronomy. STEM and other fields are first-class supporting subjects, taught where they illuminate the core six.

What the prose does not say is that this taxonomy is codified typed data, not just editorial intent. In libs/metis/learning/src/subject-taxonomy/subject-taxonomy.ts:

ts
type CoreMetisDiscipline =
  | 'philosophy'
  | 'religion'
  | 'psychology'
  | 'neuroscience'
  | 'anthropology'
  | 'astronomy';

type MetisSubjectRole = 'core_headline' | 'supporting_scaffold';

SUPPORTING_METIS_SUBJECTS enumerates the scaffolding fields (mathematics, physics, biology, chemistry, computing, history, arts, languages, social_studies). Each LearningSubjectDefinition carries a headlineAllowed flag and a scaffoldingOnlyByDefault flag, so the "supporting, not headline" policy is enforceable rather than advisory. A SUPPORTING_TO_CORE_ANCHOR map records the convergence rule literally — e.g. cosmology → astronomy, culture → anthropology — and there are typed structures for per-discipline CurriculumSeedPack (subfield ontology, prerequisite graph, canonical reading list, misconception bank, worked-example library), DisciplineSafetyPolicy (stance, required labels, prohibited patterns such as 'astrology as science', abstention rules), ReviewerPoolRequirement (quorum and credential rules), and ReleaseGateCoverageRequirement (per-discipline gold-set counts).


Canonical contracts#

The eleven named contracts are not interface sketches — they are runtime-validating Zod schemas in libs/contracts/src/metis/index.ts, each with superRefine cross-field invariants, exported through the MetisContracts namespace.

Contract Schema symbol Line
Learning source bundle LearningSourceBundleSchema 251
Grounding pack GroundingPackSchema 461
Course build CourseBuildSchema 643
Lesson asset bundle LessonAssetBundleSchema 978
Publication package PublicationPackageSchema 1226
Tutor persona profile TutorPersonaProfileSchema 1425
Tutor session memory TutorSessionMemorySchema 1605
Learning objective map LearningObjectiveMapSchema 1706
Assessment evidence pack AssessmentEvidencePackSchema 1845
Learning telemetry statement LearningTelemetryStatementSchema 2020
Academic integrity verdict AcademicIntegrityVerdictSchema 2151

These contracts span the whole pipeline: source → grounding → course → lesson asset → publication for the authoring path, tutor persona → session memory for the runtime, and objective map → evidence pack → telemetry → integrity verdict for the assessment and oversight path. The invariants are real — for example, the telemetry statement (LearningTelemetryStatementSchema) rejects a statement whose stored timestamp precedes its timestamp, and rejects an LRS-exportable statement with a null authority.


The library landscape#

The @metis/* libraries are substantial. Approximate non-test LOC:

Library Path ~LOC Role
@metis/agents libs/metis/agents 23.3K Agent runtime, orchestration, verifiers
@metis/knowledge-graph libs/metis/knowledge-graph 19.2K KG construction and GraphRAG retrieval
@metis/integrations libs/metis/integrations 18.5K Standards and cross-domain wirings
@metis/assessment libs/metis/assessment 12.4K IRT, DIF, adaptive item selection
@metis/adaptive libs/metis/adaptive 8.5K BKT / FSRS-5 / graph knowledge tracing
@metis/core libs/metis/core 6.1K Core domain types
@metis/learning libs/metis/learning 5.5K Mastery bands, decay, subject taxonomy
@metis/tutoring libs/metis/tutoring 4.3K Hint ladder, tutor modes
@metis/course libs/metis/course 4.2K Course build
@metis/verification libs/metis/verification 4.1K Grounded-generation gate
@metis/discovery libs/metis/discovery 1.5K Browse / recommend backing
@metis/gradebook libs/metis/gradebook 0.85K Gradebook emission

The ARCHITECTURE.md domain-library enumeration is stale: it omits gradebook, discovery, and verification, all of which exist on disk.

The thin domain facade#

The V1 adapter-consolidation target tracked by TODOS §1.3 (per ARCHITECTURE.md) already exists, so the "target / tracked" framing reads as not-yet-done when the facade is in fact present. libs/oshun/domain-metis/src/index.ts is one line (export * from './adapter') and adapter.ts is six lines that re-export @metis/api-client and alias createMetisAdapter → createMetisDomainAdapter and createMetisReadAdapterRegistry → createMetisDomainReadAdapterRegistry. The substantive adapter is libs/metis/api-client/src/adapter.ts (1,111 LOC).


Tutor runtime modes#

The tutor supports Socratic, direct-explanation, scaffolded-hints, worked-example, practice, and review modes, plus a switching policy (learner-initiated, teacher-policy-initiated, or performance-triggered — struggle escalates scaffolding; mastery advances to the next skill — with every switch logged in tutor session memory).

The hint ladder is concrete#

The feature list says "per-hint cost tracked" but omits the actual ladder. In libs/metis/tutoring/src/hints/hints.ts the levels are an ordered enum with fixed reveal percentages:

HintLevel Value Reveal % Description
SUBTLE 1 0.1 A gentle nudge in the right direction
DIRECT 2 0.3 Specific guidance about the concept or approach
WORKED_EXAMPLE 3 0.7 A similar problem solved step-by-step
ANSWER_REVEAL 4 1.0 The complete solution with explanation

HINT_REVEAL_PERCENTAGES quantifies how much of the answer each rung exposes, so the "cost against assessment evidence" the prose mentions has a real numeric basis: a learner who needs ANSWER_REVEAL consumed a full reveal, which is what the evidence pack records. There is also a HintCategory axis (CONCEPTUAL, PROCEDURAL, STRATEGIC, FACTUAL, METACOGNITIVE).

Two distinct integrity-mode vocabularies#

The feature list presents a single five-mode integrity vocabulary, but the code actually has two that coexist and must not be conflated:

  • The assessment-mode vocabulary (GradebookAssessmentMode, gradebook.ts:25-31, mirrored at index.ts:2145): assessed, formative, practice, exam, collaborative. These describe an assignment's help policy.
  • The tutor-session integrity mode (TutorSessionMemoryGovernanceStateSchema, index.ts:1557): teach, hint, practice, do-not-complete-for-me. These describe what the tutor is allowed to do in a session. The session governance state also carries oversightContext (independent / minor-supervised / managed-program) and oversightRoles (teacher / guardian / institution).

The feature list shows only the five-mode set; both vocabularies are real.


Academic integrity: the Themis adjudicator#

Integrity adjudication routes through Themis via the AcademicIntegrityVerdict contract. The detection-signal taxonomy in the code is exactly the ten signals the prose lists (index.ts:2073-2082):

paste_external, offplatform_search, response_pattern_anomaly, generated_text_classifier, tutor_output_in_submission, pace_anomaly, device_fingerprint_change, proctor_observation, peer_collaboration_breach, teacher_flag.

Each AcademicIntegrityDetectionSignal carries a confidence ∈ [0,1], an observedAt timestamp, a summary, and evidenceExcerptIds. A separate AcademicIntegrityClassifierOutput records a modelVersion, a label (human_likely / ai_likely / mixed / copied / unknown), a score, a threshold, and a calibratedAt timestamp.

Verdict classes — correcting the feature list#

The feature list (features.md, 1490) names verdict classes policy_violation and severe_violation. The shipped enum literals are different. AcademicIntegrityVerdictClassSchema (index.ts:2062-2066) is:

text
clear | inconclusive | violation | severe

The gradebook's GradebookIntegrityVerdictSchema (gradebook.ts:44-50) adds a fifth value for in-flight rows:

text
clear | inconclusive | violation | severe | pending

The doc's _violation long forms do not match either enum. Verdict decisions map to a recommended action drawn from none, educator_review, learner_warning, score_hold, submission_reject, institution_escalation (AcademicIntegrityDecisionSchema), each carrying an AcademicIntegrityAppealPath (appealAllowed, appealBy, appealRoute, institutionalPolicyUrl). Evidence excerpts carry a redactionState of none / learner_safe / operator_only.

Integrity BFF routes#

The operator-scoped adjudication surface is wired (apps/oshun/bff/src/routes/metis-integrity.ts):

  • POST {prefix}/metis/integrity — adjudicate
  • POST {prefix}/metis/integrity/:verdictId/appeal — open an appeal
  • GET {prefix}/metis/integrity/:verdictId/audit — fetch the audit record
  • GET {prefix}/metis/integrity/appeals/:appealId — appeals workspace
  • a POST appeals workspace handler

Mastery model and item calibration#

Mastery is a banded state per (learner, objective) pair, not a single scalar. The bands are codified verbatim in libs/metis/learning/src/mastery/evidence-requirements.ts and mirrored as GradebookMasteryBandSchema (gradebook.ts:34-41):

text
unintroduced → introduced → developing → approaching → mastered → maintaining

Per-band evidence requirements#

PLATFORM_BAND_REQUIREMENTS declares, for each band, a minimum evidence vector — the transition fires only when all components are met; otherwise the learner stays at the lower band rather than silently advancing:

Band min items min hard items min distinct contexts max recency (days) prerequisite floor
unintroduced 0 0 0 365 unintroduced
introduced 1 0 1 60 unintroduced
developing 3 0 2 30 introduced
approaching 6 1 3 21 developing
mastered 10 3 4 14 approaching
maintaining 14 4 5 30 mastered

evaluateEvidence() returns a list of explicit failures (item-count-below-floor, hard-items-below-floor, distinct-contexts-below-floor, recency-window-too-wide, prerequisite-band-floor-not-met) so an unmet transition is auditable.

Decay#

Demotion is allowed and half-life-based. decay.ts exposes an ObjectiveHalfLife metadata shape (masteryHalfLifeDays, maintainingHalfLifeMultiplier) and an evaluateDecay() function that demotes mastered to approaching when the half-life elapses; entering maintaining — which is only reached after a stable re-check — multiplies the half-life by maintainingHalfLifeMultiplier to slow decay further. Per-tenant overrides can tighten band thresholds but never loosen below the published platform minimum.

IRT is real#

Item calibration uses genuine Item Response Theory in libs/metis/assessment/src/irt-models/irt-models.ts:

  • IRTModelFamily = 1PL / 2PL / 3PL.
  • IRTParameters = { discrimination, difficulty, guessing } — the standard a / b / c triple, with documented ranges (discrimination 0.5–2.5, difficulty −3.0 to 3.0, guessing 0.0–0.35).
  • IRT_BOUNDS and MLE_DEFAULTS constants, plus resolveIRTParametersForModel and isIRTRecalibrationDue.

Differential Item Functioning is monitored by monitorDifferentialItemFunctioning (assessment/src/analytics/analytics.ts:263), and next-item selection lives in assessment/src/generation/adaptive-selector.ts.

On "CAT-aligned assessment" (features.md): the adaptive selector is IRT-information-gain based, not a separately-named Computerized Adaptive Testing module. There is no discrete CAT library; cite the IRT selector, not a CAT feature class.

Knowledge tracing#

libs/metis/adaptive/src/path/ ships three real tracers plus a unifier:

  • bkt.ts — Bayesian Knowledge Tracing with Baum-Welch EM parameter learning.
  • fsrs.ts — the FSRS-5 difficulty/stability/retrievability spaced-repetition model.
  • graph-knowledge-tracing.ts — a Nakagawa-style graph tracer.
  • adaptive-knowledge-engine.ts — a unified engine combining BKT, GKT, and FSRS.

The personalization manifold#

Adaptation is multi-dimensional, and the manifold is a real schema — LearnerPersonalizationStateSchema in libs/contracts/src/metis/personalization.ts — keyed per (learner, course) with a semantic version (regex /^\d+\.\d+\.\d+$/) and a previousVersion for rollback. It has exactly six axes, each with a PersonalizationAxisControl (pinned, loosened, reset, lastChangedAt, rationale) that backs the learner-profile "how we're teaching you" surface:

Axis Shape
pace itemsPerSession (1–60), targetSecondsPerItem (10–1200), breakIntervalItems (1–20)
modality read-first / watch-first / practice-first / dialogue-first
prerequisitePath intensity (minimal / scenic) and recap boolean
scaffoldDensity hintLadderDepth (0–8), workedExamplesPerArc (0–20)
framingRegister socratic / direct / narrative / formal-proof
culturalFrame declaredFrames (≤8 labels) and pedagogicallyPermissive boolean

The superRefine enforces that previousVersion never equals version, so a rollback always points at a distinct prior state. The scaffoldDensity.hintLadderDepth bound (0–8) ties directly to the four-rung hint ladder above — depth controls how far the tutor is allowed to climb before stopping.


The adaptive loop#

The tutor runs a tight cycle every item: present → collect response and telemetry → build an AssessmentEvidencePack → update mastery (writing a MasteryTransition if the band changes) → update per-item personalization axes → run an integrity scan over the turn → select the next item from the item bank, knowledge graph, and manifold → emit telemetry to xAPI / cmi5 / Caliper. Failure of any step is logged but does not block the next item; failure rates feed operator drift dashboards.

  • Latency budget — spec, not enforced gate. The doc asserts P95 ≤ 600 ms from response to next item, degrading to a "loading next item" UX under backpressure. The verification lib has a generic budget-ceiling primitive (MODE_CEILINGS / checkBudgetCeilings), but no runtime gate enforcing the 600 ms next-item ceiling on the live loop was found. Treat the 600 ms figure as a design target.
  • Replayability. Any item turn is reconstructible from the persisted evidence pack, the prior mastery state, and the personalization vector at the time of the turn.
  • Cross-domain hooks — partly wired. The prose cites Tara recovery rituals on frustration signals, Arete plan re-scope on drift, and Sophia grounding for any educational claim. Of these, only Sophia has a canonical wiring file (sophia-canonical-wiring.ts); the Tara and Arete hooks are described as intent, with no *-canonical-wiring.ts backing.

The grounded-generation gate (@metis/verification)#

This library is the concrete enforcement the docs only gesture at abstractly when they say generation is "grounded." libs/metis/verification/src/index.ts exports:

  • VerificationGate / createVerificationGate — the gate runtime.
  • composeP0Gate(cfg) — assembles a P0 generation gate from a retriever, an entailment judge, a pedagogical judge panel, and a step verifier.
  • runVerifiedGeneration and runVerifierGuidedGeneration — the generate → verify → refine loop that re-prompts until the gate passes.
  • PedagogicalJudgeVerifier / createPedagogicalJudgeVerifier with PanelScore, ScorablePanel, and JudgeVerifierConfig types — the judge-panel scorer.
  • Hardening (MODE_CEILINGS, checkBudgetCeilings), provenance (EvidenceRecord), and an eval harness (scoreVerifier, cohenKappa, parseGoldSet, loadGoldSet).

This is the machinery behind the feature list's "synthetic/fabricated research blocking, claim extraction, verifier orchestration, adjudication."


The knowledge graph (@metis/knowledge-graph)#

The KG promotion is far richer than the one bullet in the feature list. The library is ~19.2K LOC across 75 files and ships construction (an entity-relation-extractor with cycle and orphan detection), a GraphRagRetriever with a defaultCommunitySummarizer, multi-hop expansion, a pgvector seed step, and a governance filter, plus GNN and temporal modules and a GraphRagBenchmarkSuite for GraphRAG-style benchmarking. Retrieval integration, governance, and persistence end-to-end specs exist alongside the implementations. For the platform-wide view of how this connects to search and recommendations, see Search, Discovery, Recommendations, and Knowledge Graph.

The lighter @metis/discovery library backs the browse/recommend surfaces the feature list mentions but never attributes to a lib: it ships a SearchableObjectCatalog, a SignalStore with typed SignalCategory / SignalType definitions, an EvidenceGroundingState, and recommendation candidate sourcing — the data layer behind course browse and "why this is recommended."


Standards, rostering, and institutional delivery#

The standards layer is real, not a wrapper. libs/metis/integrations/src/standards/institutional-delivery.ts defines LmsStandard (xapi, cmi5, … qti_3, caliper, clr, open_badges) and exports working functions: exchangeLtiLaunchToken, createLtiDeepLinkResource, dryRunOneRosterImport, mapLearnerActivityToXapi, createScormFallbackManifest, exportQti3Item, importQti3Item, mapLearnerActivityToCaliper, issueOpenBadgeCredential, plus requiredMetisV1Standards() and validateInteropMatrix() for the per-LMS interop matrix.

The lower-level protocol verification lives in libs/shared/inbound-integrations:

Capability File Symbols
LTI 1.3 lti-verification.ts VerifyLtiIdTokenInput, LtiJwks, buildLtiAuthenticationRequestUrl, generateLtiLoginState, InMemoryLtiLoginStateStore
SCORM 2004 RTE scorm-2004-rte.ts Scorm2004RuntimeApi, SCORM2004_ERROR
OneRoster oneroster.ts ONEROSTER_RESOURCE_TYPES, dry-run / sync
Identity identity.ts SAML 2.0 / OIDC / SCIM 2.0 provisioning

On the feature list's identity bullet: SCIM 2.0 / SAML 2.0 / OIDC plumbing is real in identity.ts. The Metis V1 launch locales (which gate multilingual content) are OSHUN_LAUNCH_LOCALES (libs/oshun/i18n/src/index.ts:26): en-US, es-US, fr-FR, de-DE, ar, he, ja-JP, pt-BR (eight, including two RTL).


The institutional gradebook contract#

Grades, mastery, completion, and integrity verdicts flow back to institutional gradebooks through GradebookEntrySchema (gradebook.ts:121), keyed per (learner, assignment, attempt):

Field Type / values
id, version stable idempotent ID and positive integer version
learnerId, assignmentId, attempt, courseId identity
score, scoreScale numeric and {minimum, maximum, scaleKind}
scoreBasis rubric / irt_derived / completion / attempt_count / mixed
masteryBandAtEmission one of the six bands
assessmentMode assessed / formative / practice / exam / collaborative
integrityVerdict clear / inconclusive / violation / severe / pending
emissionTrigger assignment_completion / mastery_transition / integrity_verdict_change / manual_recompute
correctsVersion, correctionReason back-link for revisions
visibility, tenantBinding per-role rules and tenant/policy binding

The superRefine invariants are meaningful: a completion-basis entry must use a pass_fail scale; a correctsVersion must point at a strictly earlier version and carry a correctionReason; a severe integrity verdict must include an evidencePackRef. Late revisions (e.g. a post-appeal correction) emit a gradebook.correction event (GradebookCorrectionEventSchema, type: 'gradebook.correction') carrying the prior version reference, while the LMS only ever receives the latest version.

Rights and visibility — a worked example#

The "rights and visibility" bullet is concretely implemented. gradebook.ts ships DEFAULT_VISIBILITY_RULES for learner / teacher / guardian / institutional_admin and a viewGradebookEntryForRole() function (gradebook.ts:276) that redacts a row per role — each GradebookVisibilityRule declares canSeeScore, canSeeIntegrityVerdict, and canFollowEvidencePack. emission.ts defaults a new entry's visibility to DEFAULT_VISIBILITY_RULES when none is supplied, so an evidence pack is followable only by an operator with the right scope.


BYOM: two different things, and the safety harness#

The feature list conflates two separate frameworks under "BYOM." They are different files with different purposes.

  1. Bring-your-own-material ingestionlibs/shared/inbound-integrations/src/byom.ts — the connector framework for file / URL / feed / LMS-import source bundles. This is the "ingest-to-course" path.
  2. Bring-your-own-model safety harnesslibs/shared/inbound-integrations/src/byom-model.ts — the ~980-LOC ByomModelFramework class that sandboxes tenant-provided model endpoints.

Correcting features.md: the doc says BYOM model calls run through @oshun/inbound-integrations/byom.ts in a per-tenant sandbox. That cites the wrong filebyom.ts is the material-ingestion connector; the model endpoint sandbox, quarantine, kill-switch, policy interlock, abuse monitor, and fail-closed behavior all live in the separate byom-model.ts.

The model safety harness primitives#

byom-model.ts exposes concrete, testable primitives worth documenting:

  • ByomEndpointStatus — including active, quarantined, fail_closed_killed, and fail_closed_quarantined.
  • ByomKillSwitchSourceplatform_operator | tenant_operator. Platform operators can disable any endpoint on safety/compliance/billing grounds; tenant operators can disable their own. Disabled endpoints fail closed (no fallback to a default model unless tenant policy explicitly opts in).
  • ByomPolicyInterlock — every call still passes through the Lilith tone, Isis governance, and Sophia grounding gates; tenant policy can only tighten beyond the platform minimum, never bypass it.
  • ByomAbuseMonitor, DEFAULT_BYOM_ABUSE_THRESHOLDS, and HIGH_RISK_TAGS — per-tenant abuse-pattern detection (anomalous rates, content categories, targeting). A flag flips the endpoint to quarantined and routes to both tenant and platform operators.
  • ByomTimeoutError — a hard per-call timeout; on timeout the call resolves to fail_closed_killed.
  • MemoryByomAuditStream — a tenant-scoped audit stream; cross-tenant aggregation is impossible by design.

The admin decision lifecycle is wired at apps/oshun/bff/src/routes/admin-metis-byom-decision.ts: an admin-scoped route accepts a decision of approve / request_changes / reject, recording the canonical action as an admin.metis_byom.decision.<decision> audit event.


Cross-domain wirings — claimed vs. present#

The feature list (features.md) names cross-domain Metis flows from Tara, Arete, Veritas, Nyx, Nisaba, Aja, Sophia, Isis, Lilith, Iris, Psyche, Yemaya, and Themis. On disk, libs/metis/integrations/src/ ships exactly eight *-canonical-wiring.ts files:

Wiring present Wiring claimed but absent
aja, iris, isis, lilith, psyche, sophia, themis, yemaya tara, nyx, veritas, nisaba, arete

The present wirings connect Metis to embodied instruction (Persona, Avatar, and Voice Packs), memory and continuity (Iris Memory and Identity), generation control (Isis Generation Control), pedagogical tone (Lilith Persona Policy), real-time tutoring (Psyche Real-Time Runtime), grounding (Sophia Grounding), academic integrity (Themis), and rendering (Output Gallery, Lineage, Branch, and Replay). The five named-but-absent wirings are aspirational.

Additional Metis BFF routes#

Beyond integrity and gradebook, the BFF (apps/oshun/bff/src/routes/) ships:

  • metis-tutor-memory.tsPOST/GET {prefix}/metis/tutor-session-memories and GET …/:sessionId (record a turn, list memories, fetch one session).
  • metis-search-seeds.ts — discovery seed surface.
  • assistant-metis-handoff.ts — the assistant → Metis handoff.
  • metis.ts — the base domain route.

Living Scenes integration#

Metis ships Lesson Visualizer Living Scenes bound to a lesson's knowledge-graph anchor set. The "what if X?" branch is constrained to what-ifs the KG supports, with graceful fallback when a cue exits the manifold. Themis academic-integrity gates block visualizations on active assessments. Tenant standards bindings (Common Core, IB, NGSS) are honored where wired. Student-generated lesson visualizers default to tenant_internal_only share scope under tenant policy. See Living Scenes — Concept and Customer Promise and Domain Templates and the Scene Score Editor for the full template.


Tests#

The intended coverage (from features.md) spans: mastery-transition determinism (same evidence vector → same band; decay against synthetic timelines); personalization-axis update cadence (per-item / per-session / per-arc signals apply at the right cadence without bleeding); adaptive-loop latency (P95 next-item ≤ 600 ms with backpressure UX — a target, see the latency note above); the Themis severity → action map round-tripping every (mode, severity-band, tenant-policy) tuple including appeals; BYOM sandbox isolation (no cross-tenant leakage, kill-switch ≤ 5 s, quarantined endpoints fail closed); and gradebook emission (per-LMS interop fixtures, correction cascade, idempotency, late-grade replay). The verification, gradebook, assessment, and adaptive libraries carry real .spec.ts suites against these behaviors; end-to-end interop and latency gates remain partly aspirational.