The six customer-facing domains — Tara, Arete, Veritas, Nyx, Nisaba, Metis — are the experiences members actually open: contemplative ritual, humane habit coaching, grounded news, sky-watching, scholarly reading, and structured learning. Each is a self-contained vertical with its own Zod contracts, a typed read adapter consumed by the shell/admin/assistant, a BFF route prefix, and a web surface tree, yet all six share one registry, one persistence boundary, and one set of platform substrates (Sophia, Iris, Lilith, Psyche, Isis). This page is the architectural reference for those six verticals; it sits below the High-Level Architecture and beside Product Surfaces, and it deliberately separates what is genuinely shipped from what is spec-described, provider-gated, or planned.
Shared Anatomy of a Domain#
Every V1 domain follows the same physical layout, so the architecture is predictable across all six:
| Layer | Convention |
|---|---|
| Contracts | libs/contracts/src/<domain>/ — Zod schemas, cross-field superRefine guards, and spec tests |
| Domain adapter | libs/oshun/domain-<domain>/src/ — typed read adapter and domain logic the shell/admin consume |
| BFF route | apps/oshun/bff/src/routes/<domain>.ts plus read-adapters in apps/oshun/bff/src/adapters/ |
| Web surface | apps/oshun/web/src/app/<domain>/ (consumer hub) plus a power-user domains/<domain>/ namespace |
| Persistence | @oshun/persistence for durable data; BFF member stores and client localStorage['oshun.<domain>'] for the hydrated shell |
| Registry | one entry in libs/oshun/domain-registry/src/registry.ts (the source of truth) |
The contracts are the contract: they are not anemic CRUD types but
domain-specific schemas that encode the rules of the domain directly in
superRefine blocks (a completed ritual must have ≥ 80 % audio completion; a
done check-in must be exactly 100 % engagement; a high-confidence concept edge
must cite evidence). That is what keeps the adapters, BFF, and surfaces honest:
an invalid state cannot be constructed.
Domain Registry#
The single source of truth lives at
libs/oshun/domain-registry/src/registry.ts, keyed by OSHUN_DOMAIN_IDS. Each
entry declares the BFF base path, deep-link prefix, notification channel, and
the assistant context key the shell threads into Iris:
| Domain | BFF base path | Deep-link prefix | Notification channel | Assistant context key |
|---|---|---|---|---|
| Tara | /api/oshun/domains/tara |
oshun://tara |
oshun.tara.rituals |
taraRitualContext |
| Veritas | /api/oshun/domains/veritas |
oshun://veritas |
oshun.veritas.claim-updates |
veritasEvidenceContext |
| Nyx | /api/oshun/domains/nyx |
oshun://nyx |
oshun.nyx.sky-events |
nyxObservationContext |
| Arete | /api/oshun/domains/arete |
oshun://arete |
oshun.arete.accountability |
areteCoachingContext |
| Nisaba | /api/oshun/domains/nisaba |
oshun://nisaba |
oshun.nisaba.study |
nisabaStudyContext |
| Metis | /api/oshun/domains/metis |
oshun://metis |
oshun.metis.learning |
metisLearningContext |
OSHUN_SHELL_PRIMARY_DOMAIN = 'tara' fixes the shell's home ordering, and
libs/oshun/domain-registry/src/guards.ts validates cross-domain references at
boundary entry. Each entry also carries an availability field that gates
whether the domain is exposed in getAvailableDomains(). This matters: Tara,
Arete, Veritas, Nyx, and Nisaba are live, but Metis is registered with
availability: 'planned' (registry.ts:489), so it is filtered out of the
launchable set even though its contracts and libraries are extensively built.
Publishing the companion ownership matrix at docs/oshun/ownership-matrix.md is
a tracked V1 deliverable under §1.1; until it lands, the registry above is the
source of truth for per-domain ownership.
Tara — Rituals, Breathwork, and Contemplative Continuity#
Purpose: rituals, practices, breathwork, meditation, teachers, and
contemplative continuity. Tara is the experiential and thematic center of V1 —
the registry's primary domain — and its contracts are among the richest in the
repo. libs/contracts/src/tara/index.ts alone is 2,688 lines (re-exported
via export * from './tara' at libs/contracts/src/index.ts:25).
Packages#
- Contracts —
libs/contracts/src/tara/(re-exported from@oshun/contracts). - Domain adapter —
libs/oshun/domain-tara/src/is a ~50-file library, not a thin wrapper:adapter.tsandcanonical-adapter.ts(read adapters), the play/pause/scrub/mix/sleep-fade runtime inaudio-session.ts(22 KB) andaudio-session-manager.ts(11 KB),ritual-scheduling.ts(16 KB),ritual-assembly.ts(14 KB),ritual-model.ts(17 KB),practice-models.ts(24 KB), andtypes.ts(35 KB). Itsindex.tsalso re-exports the cross-domain relationship moduleslilith-ritual-tone-review,lilith-mood-crisis-handoff,arete-relationship,nisaba-relationship,nyx-relationship, andmetis-relationship. - Two supporting library families back Tara beyond the domain adapter: the
@tara/*family (@tara/content,@tara/config,@tara/api-client,@tara/monitoring,@tara/ui,@tara/features,@tara/analytics,@tara/database) and the@oshun/meditation-*family (@oshun/meditation-core,-breathing,-session,-player,-progress,-timer,-offline,-analytics). - BFF — routing at
apps/oshun/bff/src/routes/tara.tsplus read adapters inapps/oshun/bff/src/adapters/tara-read-adapters.ts. - Surfaces — the consumer hub is
apps/oshun/web/src/app/tara/page.tsx, and the immersive session page isapps/oshun/web/src/app/tara/sit/[id]/(the/tara/sitroute is the actual session surface — easy to omit from a hub-only list). The power-user namespaceapps/oshun/web/src/app/domains/tara/shipsanalytics,collections,courses/[id],programs,search,sounds, andteachers/[id]. On mobile, there is notara/screen directory — the mobile app (apps/oshun/mobile/src) is organized by feature, and Tara appears as companion components such asTaraNyxPerspectiveCompanionCard.tsx,TaraVeritasSophiaCompanionCard.tsx,TaraNisabaPassageCompanionCard.tsx, andTaraAreteNextStepCompanionCard.tsxrather than a dedicated surface tree.
The canonical taxonomies are shipped, validated datasets#
The most important Tara fact the prior docs underplayed: the taxonomy axes are not just types — they are runtime reference datasets with real values that the schemas validate against.
| Dataset | Entries | What each entry carries |
|---|---|---|
TARA_MOOD_TAXONOMY |
12 | distressLevel, recommendationSlate, and a crisisHandoff { required, reason } gate |
TARA_THEME_TAXONOMY |
15 | compatibleMoods, defaultModalities |
TARA_MODALITY_TAXONOMY |
14 | family, requiresAudio, sensoryLoad, accessibilityFallback, contraindicationNotes, breathworkCadence |
TARA_LINEAGE_TAXONOMY |
8 | real teachers, scriptural citations, and syncretism gates |
TARA_CONTEXT_TAGS |
— | situational tags (e.g. waking, commuting, before-sleep) |
TARA_DURATION_BUCKETS |
5 | min/max minutes plus recommendation cadence (below) |
The MoodTaxonomySchema enum is exactly twelve values: anxious,
scattered, restless, heavy, low, neutral, curious, joyful,
agitated, grieving, fearful, peaceful. Each TARA_MOOD_TAXONOMY entry
binds a distressLevel and a recommendationSlate to that mood, and the
high-distress moods carry a real crisis hand-off — e.g. agitated is
distressLevel: 'high' with
crisisHandoff: { required: true, reason: 'Agitated high-distress mood should route through crisis-aware safety review.' }.
This is the seam through which Tara hands a struggling member to
Lilith via the lilith-mood-crisis-handoff module —
the data model enforces that distress is never silently ignored.
The LineageTaxonomyIdSchema enumerates eight contemplative lineages —
secular-breath-awareness, theravada-anapanasati, mahayana-bodhicitta,
vajrayana-tara-devotion, yogic-pranayama, bhakti-devotional-prayer,
advaita-self-inquiry, comparative-contemplative-study — and the dataset
attaches real teachers and scriptural references to each: Buddhaghosa
(Visuddhimagga) and Gautama Buddha for Theravada with citations MN 118
(Anapanasati Sutta) and MN 10 (Satipatthana Sutta); Shantideva
(Bodhicaryavatara) for Mahayana; Padmasambhava for Vajrayana; Patanjali for
yogic; Mirabai for bhakti. Each lineage also carries a syncretism block
(allowsCrossLineage, comparativePersonaRequired, disclosureLabel), so a
practice that crosses lineages is gated on a comparative persona and a
disclosure label — the schema makes uncritical syncretism a validation error.
Breathwork cadences are typed, not prose#
The 14-value ModalityTaxonomySchema includes four breathwork modalities
(breathwork-box, breathwork-4-7-8, breathwork-coherent,
breathwork-alternate-nostril) and three sound modalities
(sound-singing-bowl, sound-drone, sound-mantra). Each breathwork modality
in TARA_MODALITY_TAXONOMY carries a concrete BreathworkCadence:
| Modality | inhale | hold | exhale | hold | Cycle |
|---|---|---|---|---|---|
breathwork-box |
4 s | 4 s | 4 s | 4 s | "Four equal phases: inhale, hold, exhale, hold." |
breathwork-4-7-8 |
4 s | 7 s | 8 s | 0 s | "Inhale four, hold seven, exhale eight with no final hold." |
breathwork-coherent |
5 s | 0 s | 5 s | 0 s | "Even five-second inhale and five-second exhale." |
BreathworkCadenceSchema bounds each phase to 0–60 s, so the pacing is part of
the contract. Every breathwork modality also declares contraindicationNotes
(e.g. "Avoid long holds for dizziness, panic spikes, or respiratory strain") and
an accessibilityFallback (haptic pacing and count transcript) — pacing is
delivered to hearing-impaired members via vibration, which
TaraContentAccessibility.vibrationPacingAvailable flags per-practice.
Duration buckets carry a recommendation-cadence policy#
TARA_DURATION_BUCKETS defines five buckets with a built-in anti-spam policy —
minimumHoursBetweenRecommendations — so micro practices can be re-offered
quickly while a retreat is not pushed again for a week:
| Bucket | Minutes | Min hours between recommendations |
|---|---|---|
micro |
0–2 | 0.5 |
short |
3–10 | 8 |
standard |
11–25 | 12 |
long |
26–60 | 72 |
retreat |
61+ (no max) | 168 |
The session is a real state machine#
SessionStateSchema is an 8-state enum — not-started, started, paused,
drifted, resumed, abandoned, completed, partially-completed — and the
contract ships a real transition table, SESSION_STATE_TRANSITIONS, that the
RitualSession schema enforces through validateSessionTimeline:
const SESSION_STATE_TRANSITIONS = {
'not-started': ['started'],
started: [
'paused',
'drifted',
'abandoned',
'completed',
'partially-completed',
],
paused: ['drifted', 'resumed', 'abandoned'],
drifted: ['resumed', 'abandoned'],
resumed: [
'paused',
'drifted',
'abandoned',
'completed',
'partially-completed',
],
abandoned: ['resumed'],
completed: [],
'partially-completed': [],
};
Each RitualSessionEvent (type start/pause/drift/abandon/edit/…)
carries priorState and newState, and superRefine enforces both that the
event sequence is contiguous (each event's priorState equals the prior event's
newState) and that each event type lands in the right state — a drift
event must enter the drifted state (index.ts:2494). The RitualSession
also enforces domain invariants: a completed/partially-completed session
requires ≥ 80 % audioCompletionPercent and a completedAt; a
partially-completed session must stay below 100 %; an abandoned session
requires abandonedAt.
Drift accuracy note. The companion spec (features.md) describes
driftedas "idle beyond the per-modalitydrift_idle_secondsthreshold." In code there is nodrift_idle_seconds(ordriftIdleSeconds,idleThreshold) constant anywhere inlibs/oshun/domain-tara/srcorlibs/contracts/src/tara. Drift is modeled as aRitualSessionEventof type'drift'that must transition into thedriftedstate, plus a nullabledriftDetectedAttimestamp on the session. There is no numeric per-modality idle threshold — drift is an event, not a tuned scalar.
The domain adapter's types.ts does ship two real lifecycle constants:
TARA_SESSION_CHECKPOINT_THRESHOLD_PERCENT = 5 (checkpoints once 5 % of audio
has played) and TARA_SESSION_RECENT_COMPLETION_WINDOW_HOURS = 12 (what counts
as a recent completion for resume/recommendation).
Continuation is richer than "next up"#
ContinuationState is the spine of Tara's "pick up where you left off" promise.
Its programArc carries completedSessions/totalSessions/
currentSessionIndex with invariants (completedSessions cannot exceed
totalSessions; currentSessionIndex cannot exceed totalSessions). It tracks
per-theme themeContinuity depth (introductory/developing/deepening), and
its nextRecommendation is prerequisite-blocked: if
prerequisitesSatisfied is false, the blockedPrerequisiteIds must reference
actually unsatisfied prerequisites, and a satisfied recommendation cannot carry
blocked ids. A governance { memoryScope, consentRecordId } block ties the
continuation to a consent record, so resume is consent-aware by construction.
Playback rate is a real normalization function#
libs/contracts/src/tara/playback-rate.ts implements the documented
"0.85×–1.25× voice speed" as an actual contract, not a slider hint. The default
QUALITY_PRESERVING_PLAYBACK_RATE_POLICY is
{ minRate: 0.85, maxRate: 1.25, step: 0.05, decimalPlaces: 2, preservePitch: true },
and normalizePlaybackRate() snaps to the step grid, clamps to the range, and
throws a PlaybackRateRangeError for out-of-range or non-finite input. The
narrow range exists because, as the file documents, "breath cues, room tone, and
vocal formants degrade quickly outside this narrow range."
TeacherProfile#
TeacherProfileSchema carries id (slug), displayName, biography,
lineage, roles (one or more of teacher/breath-guide/narrator/
scholar/reviewer), credentialSummary, localeCoverage, a
rights: TaraContentRights block (license/consent/attribution), and an
accessibility { voiceDescription, transcriptVoiceName } block.
Cross-domain hooks#
Tara's cross-domain hooks span Nisaba passage companions, Arete next steps, Nyx
perspective prompts, Veritas/Sophia explanatory notes, assistant follow-ups,
Lilith contemplative tone gating, and Living Scenes Contemplative-Arc cards. The
Living Scenes contracts exist at
libs/contracts/src/living-scene/{index.ts,score.ts, technique.ts} (see
Living Scenes); companion components are in place, but the
full immersive Contemplative-Arc runtime that paces card transitions to breath
cycles is partially evidenced rather than fully confirmed. Per the V1
completeness audit (v1-completeness-audit-2026-06-22.md), the
tara-daily-ritual, first-tara-sit, and tara-to-nisaba-handoff journeys are
rated deep coverage — the experiential spine is genuinely shipped — while
several cross-domain bridges remain unit-only. Cross-device resume and
watermarked downloads with attribution are spec-described and only partially
evidenced.
Arete — Goals, Habits, and Humane Streak Coaching#
Purpose: goals, habits, routines, journaling, weekly review, and humane
streak/recovery coaching. Arete's design thesis is anti-shame: missing a day is
modeled, named, and recoverable — never a silent zero. The contracts
(libs/contracts/src/arete/index.ts, 1,207 lines, re-exported via
export * from './arete' at libs/contracts/src/index.ts:22) encode that
thesis directly.
Packages#
- Contracts —
libs/contracts/src/arete/. - Domain adapter —
libs/oshun/domain-arete/src/. The two load-bearing modules arestreak-recovery.ts(21 KB), which exports the real recovery algorithmsevaluateAreteHabitRecovery(:111),applyAreteHabitRecoveryCompletion(:317),countMissedHabitWindows(:371), andARETE_HUMANE_STREAK_POLICY(:86); andfriction-taxonomy.ts, which exportsARETE_FRICTION_TAXONOMY_VERSION = '1.0.0',ARETE_FRICTION_DESCRIPTORS,ARETE_INTERVENTION_DESCRIPTORS,buildAreteInterventionRecommendations, andsummarizeAreteFrictionLogs. - Library family —
@arete/*(12 packages:@arete/affirmations,@arete/ai-coach,@arete/balance,@arete/gamification,@arete/goals,@arete/habits,@arete/journal,@arete/seven-habits,@arete/time,@arete/vision,@arete/core,@arete/database, plus@arete/api-client). - Service tier —
apps/arete/{api,mobile,web}exists, but the member-scoped persistence the audit exercises actually lives in BFF stores (apps/oshun/bff/src/arete/arete-review-store.ts,arete-offering-store.ts,arete-coach-decision-store.ts) and client-sideuseAreteStore/localStorage['oshun.arete']— not solely inapps/arete. - BFF —
apps/oshun/bff/src/routes/arete.tsexposes/v1/arete/room,/v1/arete/habits(and/:habitId/check-in),/v1/arete/offerings/keep,/v1/arete/offerings/sent,/v1/arete/review/close, and/v1/arete/review/closed. - Surfaces —
apps/oshun/web/src/app/arete/shipscoaching,goal,habits,offering(singular),offerings(plural — a distinct directory),patterns,plan,recovery,review,streak, andweekly; the power-user namespaceapps/oshun/web/src/app/domains/arete/addsaffirmations,balance,coach,gamification,goals,habits,journal,plan-review,progress,seven-habits,time, andvision.
Check-in status drives streak treatment#
CheckInStatusSchema is exactly
['done', 'partial', 'skip', 'decline', 'miss'], and each status maps to a
streak treatment through the real CHECK_IN_STREAK_TREATMENT table (plus the
helpers getCheckInStreakTreatment and isEngagedCheckInStatus):
| Status | Streak treatment | superRefine invariant |
|---|---|---|
done |
engaged |
requires engagementPercent === 100 |
partial |
engaged |
requires engagementPercent > 0 && < 100 |
skip |
grace |
requires 0 % and a visible statusReason |
decline |
grace |
requires 0 % and a visible statusReason |
miss |
no-count |
requires 0 % |
That done/partial/skip/decline/miss list in the architecture index is
confirmed accurate against the code. The point of the table is that skip and
decline preserve the streak via grace and require an honest reason — a
member who consciously skips is never punished, but the system records why.
Grace is configurable, not a fixed 24h/72h#
The companion spec describes "24 h grace on daily habits; 72 h grace on weekly
cadence." Those are spec defaults, not code constants. In the contract,
grace is modeled per-habit: DeclaredCadence.graceWindowHours is an integer
0–168, and HumaneStreakPolicy carries skipPreservesStreak,
declinePreservesStreak, missGraceCadences (0–30),
recoveryPromptAfterMisses, and a visualLanguage of no-shame/neutral. The
24/72 figures should be read as defaults a habit may carry, not hardcoded gates.
The streak, missed-day, and recovery model#
The humane-recovery story rests on three contracts the prior docs omitted:
StreakVisualState=steady|grace|drift|recovery|paused— the visible state a streak presents.MissedDay(withMissedDayDisposition=within-grace|logged-miss|recovered|excused) —superRefineenforces that alogged-misscarries a visible reason andno-counttreatment.RecoveryRecordandPlan(withPlanCommitment) — recovery plans require arecoveryRecordId, so a recovery is always backed by a real record.
Other real contracts the index list omits: AreteMetric, MoodSnapshot,
DeclaredCadence, HumaneStreakPolicy, and the CHECK_IN_STREAK_TREATMENT
constant itself.
Friction signals and interventions are full taxonomies#
FrictionSignalKindSchema has 11 values — time-of-day-mismatch,
mood-incompatible-cadence, calendar-collision,
cross-domain-cognitive-load, declared-sensitivity, location-friction,
environment-unavailable, energy-drop, social-friction, streak-drift,
over-scoped-plan. InterventionKindSchema has 9 values —
notification-retiming, plan-rescope, alternative-habit,
accountability-check-in, breathwork-insert, tara-ritual-surfacing,
weekly-review-prompt, routine-substitution, goal-criteria-clarification.
The tara-ritual-surfacing intervention is the explicit bridge from a habit
friction into a Tara practice — coaching can prescribe a contemplative reset.
CoachingSummary and WeeklyReview are structured, not narrative#
CoachingSummary carries structured observedPatterns with a kind enum
(time-of-day, day-of-week, mood-correlation, habit-interaction,
seasonality, location, post-event), a supportBand
(weak/moderate/strong), and a governance.memoryScope — the coach's
observations are typed signals, not free text. WeeklyReview ships the exact
celebrate / notice / choose / invite quadrants as a real schema
(WeeklyReviewSectionSchema), and the review carries planAdjustments,
nextPracticeRecommendations, and crossDomainRefs.
Living Offerings#
Arete hosts Living Offerings — 4–8 min Living Scenes tuned to a stated
intention, watermarked, kept in a personal gallery with opt-in share. Per the
2026-06-22 audit, arete-create-habit, arete-living-offering-create,
weekly-review-arete, and arete-streak-recovery are all rated partial.
The wizard create flow POSTs the real BFF (commit 65e3f609e0, "test(arete):
persist habit wizard creations"), but cross-device sync is uncovered, the
living-offering intention capture is still hardcoded JSX rather than a real
textarea, and the session→streak write plus grace-window timing remain in
progress. The data model and core logic are real; some end-to-end UI/persistence
and the full Living-Offerings render pipeline are not yet wired.
Veritas — Grounded Stories, Claims, and Retraction Cascades#
Purpose: grounded stories, claims, sources, evidence, counterclaims, topic hubs, timelines, explainers, and trust/confidence display. Every Veritas claim is grounded through Sophia, and retractions cascade into both Veritas surfaces and Sophia evidence packs.
Packages and the two-tier adapter#
The canonical domain is @oshun/domain-veritas at libs/oshun/domain-veritas,
with the cascade worker at @oshun/veritas-cascade-worker. (Note:
libs/veritas is a separate collection of ~66 sub-libs — agents-*,
fact-checking, bias-detection, claims, knowledge-graph,
headline-service — not the canonical domain.) libs/contracts/veritas/
contains only a .gitkeep — it is not a wired package; Veritas types are
imported as @oshun/contracts/veritas, which the path map resolves to
libs/contracts/src/veritas.
Veritas ships two adapters, which the prior docs collapsed into one:
- A presentational article-feed adapter in
libs/oshun/domain-veritas/src/types.ts—VeritasApiAdapterwithgetTrendingArticles,getTopClaims,getClaimDetail,saveArticle/unsaveArticle,followTopic/unfollowTopic, andgetHealth. Its presentational types includeVeritasVerdict(8 values:verified,likely_true,disputed,misleading,mostly_false,false,unverifiable,unverified),VeritasCredibilityTier(high/medium/low/unknown), andVeritasClaimType(7 values). - The canonical editorial model (state machine, source quality, counterclaim balance, retraction cascade) described below.
The read adapter enforces a real RBAC surface
(libs/oshun/domain-veritas/src/adapter.ts:81):
VERITAS_ADAPTER_READ_CAPABILITIES has 10 entries — contract_descriptor,
metadata, availability, home_cards, continue_items, search, launch,
saved_articles, trending_topics, bridge_contexts — gated per role (shell
| admin | assistant) via VERITAS_ADAPTER_ROLE_CAPABILITIES.
Surfaces — apps/oshun/web/src/app/veritas/ ships claim, counterclaims,
evidence, mobile, provenance, retraction, source, story, and
topic; the power-user namespace apps/oshun/web/src/app/domains/veritas/ adds
articles, bias, claims/[claimId], fact-check, headlines,
knowledge-graph, newsletter, nlp, research, story/[id], and
topics/[topicId]. The /veritas/evidence route is real and easy to miss from
a hub-only list.
Source quality is a deterministic composite#
Source carries a SourceKind that is a superset of 15 kinds (the prior
list of 8 was a subset): peer-review, primary, secondary, press-release,
opinion, social, government, ngo, plus wire, dataset,
court-record, transcript, image, video, audio. Source quality is a
geometric weighted mean over per-domain factor tables
(source-quality/composite.ts), with FACTOR_FLOOR = 0.05 so no single factor
can zero out the score, and a bandFromComposite step:
| Composite | Band |
|---|---|
| ≥ 82 | high |
| ≥ 60 | mixed |
| ≥ 35 | low |
| else | low |
Three hard overrides sit on top of the composite: unattributed-capped-low,
recent-retraction-drops-one-band (within ≤ 12 months), and
retracted-forces-contested. SourceQualityBandSchema is
['high', 'mixed', 'low', 'contested']; ClaimConfidenceBandSchema runs
well-supported → supported → emerging → contested → unsupported →
retracted.
The editorial state machine (kebab-case, in code)#
The implemented VeritasEditorialState union
(libs/oshun/domain-veritas/src/editorial/state-machine.ts:1-13) is all
kebab-case, not snake_case: draft, in-review, verifying-sources,
awaiting-attestation, contradicts-existing, counterclaim-pending,
approved, scheduled, published, archived, corrected, retracted.
TRANSITION_RULES pairs each (from, event) with gate functions —
requireRationale, requireReviewer, requireOccurredAt, requireSources,
requireSourcesVerified, requireAttestations, requireContradictions,
requireOpenContradictionsResolved, requireCounterclaims,
requireCascadeScope.
The real path differs from the illustrative mermaid in the hub:
verifying-sources --sources-verified--> awaiting-attestation, then
awaiting-attestation --attestation-collected--> approved, then
approved --publish--> published (or via scheduled). There is no
direct awaiting-attestation → published edge and no edge feeding back into
in-review from the verification states — those branches in the diagram are
spec illustration. Note also that the contracts carry a third, shorter state
vocabulary for the presentational story: StoryEditorialStateSchema
(libs/contracts/src/veritas/index.ts:79) is
['draft', 'review', 'published', 'updated', 'corrected', 'retracted', 'archived']
— no verification states at all. Three vocabularies describe the same lifecycle
at different layers; the kebab-case state machine is the authoritative one for
editorial flow.
Counterclaim balance, topic hubs, retraction UX#
- Counterclaim surfacing (
counterclaim/surface.ts):DEFAULT_SURFACING_POLICYhastenantBandFloor: 'mixed',consensusThreshold: 0.85,recencyWindowDays: 365, and sixpublicSafetyTopics(public-health,product-safety,biosecurity,aviation-safety,nuclear-safety,natural-disaster-response). The decision is a 4-way union:co-equal|minority-view-expand|mandatory-surface|suppress. - Topic hubs (
topic-hub/composer.ts):composeTopicHubarranges six sections —TOPIC_HUB_SECTIONS = ['latest', 'key-facts', 'under-dispute', 'corrections', 'background', 'timeline']— usingDEFAULT_RANKING_WEIGHTS. - Retraction UX (
retraction-ux/banner.ts):RetractionSurfaceKindis'story-page'|'saved-claim'|'notebook'|'living-offering';RetractionSeverityis'silent'|'banner-only'|'notification-included';severityFromBandChange()derives severity from the band delta; and per-surface buildersbuildStoryPageBanner,buildSavedClaimBanner, andbuildNotebookNoticeproduce the banners. - Contradiction probe (
contradiction/probe.ts):DEFAULT_PROBE_OPTIONShastriageThreshold: 0.6;ContradictionTriggerisnew-claim-published|source-update|attestor-disagreement|operator-flag|cadence-sweep|on-refresh; it consumes aSophiaEvidencePackfrom@oshun/evidence-sophia.
The retraction cascade#
The cascade is the customer-facing payoff: when a story is retracted, the
RetractionCascade (contracts/src/veritas/index.ts:549) tracks
affectedStoryIds, affectedClaimIds, affectedExplainerIds,
affectedEvidencePackIds, plus both downstreamMetisPackageIds and
downstreamMetisLessonIds — Metis fan-out is tracked at two granularities,
not just "lessons." Its reGroundingJobs carry an action enum
(RetractionCascadeJobActionSchema = ['re-ground', 'metis-revalidate']), and a
superRefine forces Metis-lesson jobs to 'metis-revalidate'.
Execution emits a real event:
VERITAS_RETRACTION_CASCADE_DISPATCHED_EVENT = 'veritas.retraction.cascade.dispatched'
(retraction-cascade-execution.ts:37). The @oshun/veritas-cascade-worker
subscribes to the IEventBus from @oshun/event-bus via
subscribeRetractionCascadeWorker and re-grounds downstream artifacts using
persistence-backed re-grounders — createPersistenceBackedSophiaReGrounder
(keyed by SOPHIA_GROUNDED_ANSWER_STORE_KEY /
SOPHIA_REGROUNDING_VERDICT_STORE_KEY) and
createPersistenceBackedMetisRevalidator (keyed by
METIS_LESSON_SOURCES_STORE_KEY / METIS_REVALIDATION_VERDICT_STORE_KEY).
Honest state. The canonical contracts, state machine, source-quality composite, counterclaim balance, topic-hub composer, retraction-UX builders, contradiction probe, and cascade executor/worker are all real and enforced. The cascade's end-to-end customer journey (fan-out across notebook and Living-Offering surfaces, per-user gating, the live "downstream Metis lessons re-validated" wiring) is rated partial in e2e — the ports exist but live wiring sits at the deployable boundary. Per-tenant composite tightening, weekly drift re-computation, reader-notification quiet hours, and localized hub variants are spec-only.
Nyx — Sky Events, Observation Windows, and Awe#
Purpose: sky events, observation windows, awe-and-perspective, and calendar integration. Nyx's astronomy core is the most impressive genuinely real asset of the six domains, validated against known Meeus values.
Packages#
- Contracts —
libs/contracts/src/nyx/(re-exported viaexport * from './nyx'). - Domain adapter —
libs/oshun/domain-nyx/src/, anchored by the ephemeris engineephemeris.ts(19.7 KB) and adepth/directory of 41 files (20 depth modules, tests, and a depth-page). - Library tree —
libs/nyx/*(~30 subdirs incl.catalogs/,constellations/,coordinates/,orbital/,positional/,realtime/,renderer/,sky-clock/,time-travel/,client-python/,ephemeris/,mythology/). The@nyxephemeris is also consumed by V9. - BFF —
apps/oshun/bff/src/routes/nyx.tsexposes the adapter endpoints under/v1/nyx/adapter/{capabilities,availability,home-cards,continue-items, search,launch,nightly-highlights,object-search,saved-objects,event-reminders, observation-logs,bridge-moments}, plusnyx-3d-route.ts,nyx-reminder-bridge.ts, andnyx-member-stores.ts. - Surfaces — the consumer hub
apps/oshun/web/src/app/nyx/ships theNyxRoom(page.tsx) and first-class consumer routesevents/,observation/,sky-almanac/, andtonight/(these are not just power tools). The power-user namespaceapps/oshun/web/src/app/domains/nyx/addsanalysis,catalogs,coordinates,events/[eventId],learning,moon,neo,observation-log,observation-log-deep,renderer,satellites,sky-conditions,solar,solar-system,sonification,star-chart,telescope,time-travel, andwidgets. On mobile, there is nonyx/screen directory — Nyx appears only as cross-domain companion components (e.g.TaraNyxPerspectiveCompanionCard.tsx).
The ephemeris engine is real Meeus astronomy#
ephemeris.ts exports toJulianDay, julianCenturies, sunPosition,
moonPosition, moonIllumination, computeNightSky,
greenwichMeanSiderealTime, localSiderealTime, equatorialToHorizontal,
riseTransitSet (using a STANDARD_ALTITUDE constant), and computeTonight.
This is not a stub by any diagnostic — ephemeris.test.ts asserts known-correct
Meeus values:
| Assertion | Expected |
|---|---|
toJulianDay(2000-01-01T12:00Z) (J2000.0 epoch) |
2451545.0 |
sun.eclipticLongitude |
≈ 199.909° |
sun.declination |
≈ -7.78507° |
moon.eclipticLongitude |
≈ 133.1627° |
moon.distance |
≈ 368409.7 km |
moonIllumination.illuminatedFraction |
≈ 0.6786 |
The 20 depth/ modules — lunar-phase-calendar, twilight-schedule,
solar-season-markers, object-transit, moon-phase-detail,
equation-of-time, zodiac-position, moon-distance, sun-distance,
lunar-nodes, planetary-hours, daylight-extremes, chart-angles,
solar-terms, astronomical-night, horizon-point, solar-horizon-points,
lunar-horizon-points, solar-noon, twilight-phase-now — power the
/domains/nyx/* deep tools off this engine.
Event taxonomy and per-family detail schemas#
SkyEventFamilySchema has 11 families (meteor-shower, eclipse,
conjunction, occultation, transit, comet, aurora, satellite-pass,
supermoon, seasonal-marker, deep-sky-peak); SkyEventTypeSchema
enumerates 27 types (meteor-shower-peak; solar/lunar eclipses
partial/total/annular/penumbral; planet-planet/planet-moon/planet-star
conjunctions; mercury/venus/exoplanet transits; aurora-forecast; iss-pass;
supermoon; march/september equinoxes; june/december solstices; cross-quarter;
deep-sky-peak). Each family has a typed detail schema, e.g.:
MeteorShowerEventDetails:iauCode(regex/^[A-Z0-9]{3}$/),peakZenithalHourlyRate(int 1–1000),radiant.AuroraEventDetails:hemispheres(north/south),kpIndexMin/Max(0–9),geomagneticStormLevel(g1–g5),validForecastHours≤ 168.EclipseEventDetails:sarosSeries,gamma, contact times.SatellitePassEventDetails:noradId.SupermoonEventDetails:perigeeDistanceKm.
A predictionSourceFamilySupport mapping (with superRefine enforcement) ties
which source kinds can back which event families — an event must carry a
supporting source.
Prediction sources and calendar providers#
PredictionSourceKindSchema has 11 kinds, five more than the prior docs
listed: nasa-jpl-horizons, nasa-jpl-small-body-db, imo-meteor-calendar,
iers-bulletin-a, noaa-swpc-geomagnetic-forecast, weather-provider,
bortle-light-pollution-atlas, tle-provider, minor-planet-center,
usno-astronomical-applications, gaia-catalog. CalendarProviderSchema is
['google', 'apple', 'outlook', 'ics-file'] — the ics-file provider (with its
own externalCalendarId-null special case) is real. ReminderCadenceSchema is
['peak-only', 'evening-of', 'week-before', 'none'].
Observation quality and the observe-loop#
ObservationQualityBandSchema is
['excellent', 'good', 'fair', 'poor', 'not-visible'], and excellent is gated
by superRefine: bortleClass ≤ 4, cloudCover ≤ 25 %, twilight in
astronomical/night. Beyond saving/following/reminding, Nyx ships a real
LoggedObservation contract (index.ts:784) — the ground-truth loop where
a member reports what they actually saw: site, skyCondition
(bortle/seeing/transparency/weather/cloud/moon %), equipment, qualityRating,
attachments, sharedScope (private/household/public), and
sourceClient. The key contracts SkyEvent, ObservationWindow,
ObservationQualityBand, PredictionSourceRef, and CalendarSyncEntry all
exist and are confirmed accurate.
Honest state. The astronomy core, the full contract model, and local persistence (
useNyxStore/localStorage['oshun.nyx']) are real. Per the 2026-06-22 audit,nyx-event-calendar-sync-reminderis partial — two-way provider sync is mocked at the boundary and reminder dispatch/delivery remain.nyx-tonight-observationis now deep for shipped local/dev infra: the browser journey proves local-first observation save,/v1/nyx/observationsPOST/GET read-back after local storage clear, Home Nyx support-card read-back, current-week KPI increment, and the observation-log versus telescope-control equipment boundary. Live external data-source ingestion (actual NASA/IMO/NOAA fetches) and real calendar-provider OAuth sync are seam-mocked / fail-loud, which is the honest state, not a fabrication.
Nisaba — Scholarly Passages, Editions, and Polyglot Philology#
Purpose: scholarly passages, sources, manuscripts, editions, translations, lexicon and morphology, concept graph, notebooks, and study plans. Nisaba pairs a fully specified canonical contract layer with the richest real philology code in the repo — but its hydrated shell is the least connected of the six.
Packages#
- Contracts —
libs/contracts/src/nisaba/(re-exported as theNisabaContractsnamespace). Fully implemented Zod schemas with cross-fieldsuperRefine. - Domain adapter —
@oshun/domain-nisabaatlibs/oshun/domain-nisabais a thin shell adapter; the deep substrate is the contracts plus thelibs/nisaba/*collection. libs/nisaba/*is ~23 sub-packages:@nisaba/annotations,@nisaba/assistant,@nisaba/canon,@nisaba/comparative,@nisaba/corpora,@nisaba/criticism,@nisaba/editions,@nisaba/geotemporal,@nisaba/languages,@nisaba/paleography,@nisaba/philology,@nisaba/schemas,@nisaba/standards,@nisaba/study-plans,@nisaba/translations,@nisaba/workspace,@nisaba/database,@nisaba/cross-domain,@nisaba/mobile,@nisaba/core,@nisaba/client,@nisaba/api-client.- Surfaces —
apps/oshun/web/src/app/nisaba/shipscompare,daily,graph,lexicon,manuscript,notebook(singular),notebooks(plural — a distinct directory),plan, andscholar. There is no literalapps/oshun/web/src/app/domains/nisaba/directory (unlike Veritas): the power-user surface is served via the dynamic catch-all routeapps/oshun/web/src/app/domains/[domainId]/page.tsxmountingcomponents/domains/NisabaSurface.tsx.
The canonical contracts#
NisabaScriptSchema covers latin, greek, hebrew, arabic, devanagari,
pali-sinhala, coptic, cuneiform, tibetan, chinese, japanese,
syriac, ethiopic, other (and TextDirectionSchema includes
boustrophedon). The core schemas encode scholarly correctness in
superRefine:
| Contract | Key fields / invariant |
|---|---|
Passage |
CanonicalReference (scheme cts/osis/sefaria/library-of-congress/custom), segments, sourceLineage, concept/lexicon/morphology bindings |
Manuscript |
siglum, repository.shelfmark, dateRange, material (papyrus/parchment/paper/stone/clay/metal/digital), digitization.status requires imageManifestUrl when iiif/digitized |
Edition |
editionType (critical/diplomatic/reader/digital/facsimile); apparatus: ApparatusEntry[] whose witnessManuscriptIds are validated to be declared in edition.manuscriptIds |
Translation |
translationMode (literal/formal-equivalence/dynamic/commentarial/adaptive); superRefine enforces sourceLanguage !== targetLanguage |
LexiconEntry |
lemma, senses, glosses, roots |
MorphologyEntry |
PartOfSpeech (12 values), MorphologyFeature (14 values: case/number/gender/person/tense/aspect/mood/voice/state/degree/stem/root/prefix/suffix), parsing method |
ConceptGraphNode |
kind (10): term/deity/place/person/textual-theme/ritual-practice/cosmology/historical-event/school/manuscript-family |
ConceptGraphEdge |
relation (9, below); high-confidence edges require evidencePassageIds or citationIds |
StudyPlan |
StudyPlanStep.kind (9): read-passage/compare-translation/view-manuscript/lexicon-review/morphology-review/concept-map/annotation/reflection/assessment; steps strictly ordered |
ScholarProfile |
reviewAuthority { canApproveEditions, canApproveTranslations, canVerifyCitations, maxReviewRisk }; scholarCanVerifyCitations() requires ≥ 1 verified credential |
CitationStyleSchema is ['chicago', 'mla', 'apa', 'sbl', 'cts', 'custom'] and
RightsStatusSchema is
['public-domain', 'open-license', 'licensed', 'restricted', 'unknown']. The
schema also defines nested types the index list elides — PassageSegment,
ApparatusEntry, LexiconSense, NotebookItem, StudyPlanStep,
TextRangeSelector, CanonicalReference — plus helpers isPublishedPassage,
conceptEdgeRequiresEvidence, and scholarCanVerifyCitations.
Edge-label correction. Earlier revisions of the companion spec described Nisaba concept edges as
refers-to/derives-from/comparative-to/lineage-of(since corrected there too). None of those four match the implemented enum. The realConceptGraphEdgeSchema.relation(contracts:604-614) isbroader-than,narrower-than,related-to,influences,contrasts-with,translation-equivalent,ritualizes,comments-on,shares-source-lineage. A reader following the doc's vocabulary would write edges the contract rejects.
@nisaba/languages — the polyglot philology engine#
The richest real Nisaba code is the @nisaba/languages engine, barely
acknowledged in the prior docs. Its src holds 30+ script/language subdirs
(hebrew, aramaic, syriac, arabic, ethiopic, phoenician, samaritan,
ugaritic, cuneiform, egyptian-hieroglyphic/hieratic/demotic,
ancient-greek, latin, coptic, devanagari, grantha, kharoshthi,
linear-b, old-church-slavonic, old-persian, pali, prakrit, runic,
tamil-brahmi, tibetan, classical-chinese, avestan, …) plus
transliteration, tokenization, and a lexicon module. It exports concrete
script handlers — ImperialAramaicScriptHandler,
BiblicalAramaicScriptHandler, SyriacScriptHandler, ArabicScriptHandler,
EthiopicScriptHandler, SamaritanScriptHandler, UgariticScriptHandler,
SumerianCuneiformHandler,
EgyptianHieroglyphicHandler/HieraticHandler/DemoticHandler — far beyond
the "morphology lookup" the docs gesture at. @nisaba/criticism ships real IIIF
manifest linking (iiif-linking.ts: IIIFLinkRegistry, IIIFManifestRef).
Search modes and cross-domain wiring#
The shell adapter's NisabaApiAdapter (libs/oshun/domain-nisaba/src/types.ts)
exposes getDailyPassage, getContinueReading, getSavedPassages,
save/unsavePassage, getStudyReminders, setStudyReminder,
toggleStudyReminder, getConceptThreads, getWorkspaceEntries,
searchLibrary, and getHealth. Its search is multi-mode:
NisabaSearchMode = fulltext | lemma | morphology | semantic | regex | proximity
over
NisabaSearchEntityKind = passage | source | concept | notebook | collection,
and NisabaResearchType is CRITICAL_EDITION | TRANSLATION |
COMPARATIVE_STUDY | PHILOLOGICAL_ANALYSIS | MANUSCRIPT_SURVEY.
Cross-domain wiring is real: concept-graph-linkages.ts delegates to the shared
@oshun/navigation concept graph (buildOshunSharedConceptGraphThread,
inferOshunSharedConceptIds) through a NISABA_CONCEPT_ID_ALIASES map —
'concept-attention' → 'focus-protection',
'nisaba-concept-detachment' → 'honest-reflection',
'nisaba-concept-nonreaction' → 'honest-reflection' — and
domain-recommendations.ts builds cross-domain recs with reasons
'shared_concept_graph' | 'source_study'. @nisaba/study-plans is
re-exported from domain-nisaba/src/study-plans.ts (createNisabaStudyPlan,
recordNisabaLearnerProgress, sequenceNisabaStudyResources,
NisabaCompletionForecast, NisabaStudyPlanCadence/Difficulty/Objective).
External-source configuration. The Nisaba external-source endpoints are configured via env vars
NISABA_SEFARIA_API_URL,NISABA_CDLI_API_URL, andNISABA_IIIF_BASE_URL, present in.env.example(lines 102-104:https://www.sefaria.org/api, the CDLI API, and a local IIIF base). Conceptual CDLI/Oracc ATF and IIIF handling also exists inside@nisaba/languages(cuneiform ATF) and@nisaba/criticism(iiif-linking.ts).
Honest state. The canonical contracts, the
@nisaba/languagesengine, the shared concept-graph linkages, and@nisaba/study-plansare real. Per the 2026-06-23 triage, Nisaba is disconnected in the hydrated shell (with Metisplanned, the post-hydrationshellDomainCountdrops to 4); the e2enisaba-scholarly-readruns on a stub workspace API with render-only scholar apparatus, andnisaba-notebook-capture-and-citehas the Sophia stable-ID round-trip stubbed. Scholar entitlement-gated reading mode, durable annotation re-anchoring across edition revisions, and the source-lifecycle invalidation cascade are contract-modeled but runtime-unverified.
Metis — Courses, Tutoring, and Adaptive Learning#
Purpose: the educational substrate — courses, tutoring, BYOM study,
assessments, knowledge-graph promotion, and standards-based institutional
delivery. Metis is far more implemented than typical domain docs imply, yet it
is not currently a live launch surface: the registry sets
availability: 'planned' (registry.ts:489), and getAvailableDomains()
filters out planned domains. "Launch-blocking V1 scope" is roadmap intent, not
current launch state — the 2026-06-23 triage confirms the shell drops Metis to
planned post-hydration.
Packages#
- Apps — all five
apps/metis/{web,admin,api-gateway,worker,mobile}exist (web 93 ts/tsx, admin 62, api-gateway 29, worker 21, mobile 6). - Adapter — the
domain-metisfacade already exists:libs/oshun/domain-metis/src/index.ts(one line) re-exportsadapter.ts(six lines), which re-exports@metis/api-clientand aliasescreateMetisDomainAdapter/createMetisDomainReadAdapterRegistry. The substantive adapter islibs/metis/api-client/src/adapter.ts(~1,111 LOC). Consolidation is tracked under §1.3, but the thin facade is present today. - Domain libraries (non-test LOC):
@metis/agents(23.3 K),@metis/knowledge-graph(19.2 K),@metis/integrations(18.5 K),@metis/assessment(12.4 K),@metis/adaptive(8.5 K),@metis/core(6.1 K),@metis/learning(5.5 K),@metis/tutoring(4.3 K),@metis/course(4.2 K),@metis/verification(4.1 K),@metis/discovery(~1.5 K),@metis/gradebook(~0.85 K) — the last three (gradebook,discovery,verification) exist on disk but were absent from the prior library list. - Contracts —
libs/contracts/src/metis/re-exported as theMetisContractsnamespace (export * as MetisContracts from './metis'atlibs/contracts/src/index.ts:103). - BFF —
apps/oshun/bff/src/routes/:metis-integrity.ts(POST /metis/integrityadjudicate;POST /metis/integrity/:verdictId/appeal;GET /metis/integrity/:verdictId/audit; appeals workspace),metis-tutor-memory.ts(POST/GET /metis/tutor-session-memories[/:sessionId]),admin-metis-byom-decision.ts,metis-search-seeds.ts,assistant-metis-handoff.ts,metis.ts. - Surfaces —
apps/oshun/web/src/app/metis/shipsassessment,byom,courses(incl.courses/new),ingest,lesson,lessons,session,tutor, andupload. The consumer-shell review surface is/operator/metis(apps/oshun/web/src/app/operator/metis/page.tsx) — there is no/admin/metisroute in the consumer web app, and noapps/oshun/web/src/app/domains/metis/directory, even though the registry declaresroute: '/domains/metis'.
The 11 canonical contracts#
All eleven are real Zod schemas in libs/contracts/src/metis/index.ts:
| Contract | Line |
|---|---|
LearningSourceBundleSchema |
251 |
GroundingPackSchema |
461 |
CourseBuildSchema |
643 |
LessonAssetBundleSchema |
978 |
PublicationPackageSchema |
1226 |
TutorPersonaProfileSchema |
1425 |
TutorSessionMemorySchema |
1605 |
LearningObjectiveMapSchema |
1706 |
AssessmentEvidencePackSchema |
1845 |
LearningTelemetryStatementSchema (xAPI/cmi5-compatible) |
2020 |
AcademicIntegrityVerdictSchema |
2061 |
Mastery, decay, and the 6-axis personalization manifold#
The six mastery bands are codified verbatim in
libs/metis/learning/src/mastery/evidence-requirements.ts: unintroduced →
introduced → developing → approaching → mastered → maintaining, each
with a prerequisiteBandFloor, plus half-life decay in decay.ts
(maintainingHalfLifeMultiplier; mastered → approaching demotion). They are
also enumerated as GradebookMasteryBandSchema.
LearnerPersonalizationStateSchema (metis/personalization.ts) is a real Zod
manifold with six axes, each wrapped in a
PersonalizationAxisControl { pinned, loosened, reset, rationale } and
versioned /^\d+\.\d+\.\d+$/: pace; modality
(read-first/watch-first/practice-first/dialogue-first);
prerequisitePath (minimal/scenic plus recap); scaffoldDensity
(hintLadderDepth 0–8, workedExamplesPerArc 0–20); framingRegister
(socratic/direct/narrative/formal-proof); and culturalFrame.
The six core disciplines are codified data#
libs/metis/learning/src/subject-taxonomy/subject-taxonomy.ts codifies
CoreMetisDiscipline = 'philosophy' | 'religion' | 'psychology' | 'neuroscience' | 'anthropology' | 'astronomy'
alongside a SUPPORTING_METIS_SUBJECTS array, a MetisSubjectRole of
'core_headline' | 'supporting_scaffold', and a SUPPORTING_TO_CORE_ANCHOR
map (e.g. cosmology → astronomy, culture → anthropology) — a real anchor
taxonomy, not just prose.
Assessment, knowledge tracing, and the hint ladder#
IRT is real in libs/metis/assessment: irt-models.ts exports
IRTModelFamily, IRTParameters (difficulty/discrimination/guessing),
IRT_BOUNDS, MLE_DEFAULTS, resolveIRTParametersForModel,
isIRTRecalibrationDue; DIF monitoring via
monitorDifferentialItemFunctioning; and an information-gain adaptive item
selector in generation/adaptive-selector.ts (the real "CAT-aligned" behavior —
there is no separately named CAT module). Knowledge tracing is real in
libs/metis/adaptive/src/path/: bkt.js (Bayesian Knowledge Tracing,
Baum-Welch EM), fsrs.js (FSRS-5 DSR), graph-knowledge-tracing.js
(Nakagawa-style), and a unified adaptive-knowledge-engine.js. The tutor's hint
ladder (libs/metis/tutoring/src/hints/hints.ts) is concrete:
HintLevel { SUBTLE, DIRECT, WORKED_EXAMPLE, ANSWER_REVEAL } with
HINT_REVEAL_PERCENTAGES = { 0.1, 0.3, 0.7, 1.0 }.
@metis/verification (4 K LOC) ships the grounded-generation enforcement the
docs only gesture at: a VerificationGate, composeP0Gate,
runVerifiedGeneration (generate-verify-refine loop), and a judge-verifier
panel scorer. @metis/knowledge-graph (19 K LOC, 75 files) ships construction
(entity-relation-extractor, cycle/orphan detection), a GraphRagRetriever
(defaultCommunitySummarizer, multi-hop expansion, pgvector seed, governance
filter), GNN/temporal modules, and a GraphRagBenchmarkSuite.
Academic integrity (Themis)#
AcademicIntegrityVerdict uses verdict classes clear, inconclusive,
violation, severe (index.ts:2063 — not the policy_violation /
severe_violation long forms the spec uses; the gradebook enum adds pending).
Its 10-signal taxonomy (index.ts:2073) is exactly: 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. Two
distinct integrity-mode vocabularies coexist: the GradebookAssessmentMode
(assessed/formative/practice/exam/collaborative, gradebook.ts:25)
and the TutorSessionMemory.integrityMode (teach/hint/practice/
do-not-complete-for-me, index.ts:1557).
Gradebook with role-redacted views#
GradebookEntrySchema (gradebook.ts:121) carries learnerId, assignmentId,
attempt, courseId, score, scoreScale, scoreBasis
(rubric/irt_derived/completion/attempt_count/mixed),
masteryBandAtEmission, assessmentMode, integrityVerdict, and an
emissionTrigger (assignment_completion/mastery_transition/
integrity_verdict_change/manual_recompute), with correctsVersion,
visibility, and tenantBinding. GradebookCorrectionEvent (type
gradebook.correction) and viewGradebookEntryForRole() (gradebook.ts:276,
with DEFAULT_VISIBILITY_RULES for learner/teacher/guardian/
institutional_admin) implement the rights-and-visibility story concretely.
BYOM safety: two separate frameworks#
There are two BYOM frameworks, and the prior docs cited the wrong one for model safety:
byom.ts— bring-your-own-material ingestion connectors (file/url/feed/ lms-import sources).byom-model.ts— the tenant-provided-model safety harness:class ByomModelFramework(~700 LOC) withByomEndpointStatus(active/quarantined/fail_closed_killed/fail_closed_quarantined/…),ByomKillSwitchSource(platform_operator/tenant_operator),ByomPolicyInterlock(Lilith/Isis/Sophia gates),ByomAbuseMonitor,DEFAULT_BYOM_ABUSE_THRESHOLDS,HIGH_RISK_TAGS,ByomTimeoutError, andMemoryByomAuditStream.
Standards-based delivery#
Real in libs/metis/integrations/src/standards/institutional-delivery.ts:
exchangeLtiLaunchToken, createLtiDeepLinkResource, dryRunOneRosterImport,
mapLearnerActivityToXapi, createScormFallbackManifest, exportQti3Item,
importQti3Item, mapLearnerActivityToCaliper, issueOpenBadgeCredential,
requiredMetisV1Standards. LTI 1.3 id_token/JWKS verification is real in
libs/shared/inbound-integrations/src/lti-verification.ts
(VerifyLtiIdTokenInput, LtiJwks, buildLtiAuthenticationRequestUrl,
generateLtiLoginState); SCORM-2004 RTE in scorm-2004-rte.ts; OneRoster in
oneroster.ts; and SAML/OIDC/SCIM identity in identity.ts. All inbound
plumbing lives under libs/shared/inbound-integrations/src/ (see
Foundations).
The adaptive learning loop#
Every item runs the same loop: present → collect → build evidence → update
mastery if a band transition fires → update the personalization manifold → run
Themis signals → route through teacher/operator review if flagged → select the
next item from the bank, KG, and manifold → emit telemetry (xAPI / cmi5 /
Caliper / GradebookEntry). The stated P95 ≤ 600 ms response-to-next-item
budget is a spec assertion — no enforcing runtime gate was found in the code.
Cross-domain wiring and storage gaps#
Canonical cross-domain wirings present in libs/metis/integrations/src/ are
aja, iris, isis, lilith, psyche, sophia, themis, yemaya
(-canonical-wiring.ts). The Tara, Nyx, Veritas, Nisaba, and Arete wirings the
spec claims do not exist as wiring files. Two further honest gaps: there is
no dedicated metis PostgreSQL database — POSTGRES_MULTIPLE_DATABASES
(docker/docker-compose.dev.yml) is
yemaya,lilith,isis,iris,sophia,hathor, bellona,calliope,tara,maat,nisaba,shakti,cybele,kalika,lakshmi,athena,oya,
with metis absent — so Metis's storage strategy (shared oshun_dev vs domain
tables) is undocumented; and the BYOM headline ingest-to-course pipeline is
rated partial/uncovered in the 2026-06-22 completeness audit. For reference,
the launch locale set is OSHUN_LAUNCH_LOCALES
(libs/oshun/i18n/src/index.ts:26): en-US, es-US, fr-FR, de-DE, ar,
he, ja-JP, pt-BR.
Related#
- High-Level Architecture — where the six domains sit relative to substrates and the shell.
- Product Surfaces — the shell, consumer, and operator surfaces these domains render into.
- Sophia — Grounding Substrate — grounds every Veritas claim and Metis lesson, and re-grounds on retraction.
- Lilith — Contemplative Policy Substrate — Tara tone review and the mood crisis hand-off.
- Living Scenes — the Contemplative-Arc cards and Arete Living Offerings.
- Cross-Domain Support — the shared concept graph and bridge contexts that link the domains.
- Search, Discovery, and Knowledge Graph — Nisaba/Metis search and KG promotion.
../ARCHITECTURE.md— the architecture hub.V1/features.md§ Editorial Workflow, Source Verification, and Contradiction DetectionV1/features.md§ Adaptive Learning Loop, Themis Adjudication, and BYOM Safety