Oshun Platform · Features

Nisaba — Scholarly Study

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

10sections18 minread6tables

On this page

Nisaba is Oshun V1's scholarly study domain: the home for primary-source texts, manuscript witnesses, critical editions, translations, lexicon and morphology data, a text-anchored concept graph, annotations, notebooks, study plans, and citations. It serves the reader who wants to study a passage in depth — comparing editions and translations, inspecting a manuscript image beside its transcription, looking up a word's morphology, or tracing a concept across traditions — and it serves credentialed scholars who review and constitute that material. Architecturally, Nisaba sits as one of the V1 consumer domains under the unified shell (alongside Tara, Arete, Veritas, Nyx, and Metis), backed by a deep contracts substrate and a large collection of philology engines. This page is the canonical reference for what is implemented today, what is contract-modeled but not yet wired at runtime, and what is honestly aspirational. The defining tension to hold while reading: Nisaba has an unusually deep, real substrate (contracts, philology engines, criticism tooling) wrapped in shell surfaces that still run on stubs — the hydrated shell reports the domain disconnected (see Honest status (V1) below).


Where Nisaba lives in the codebase#

Nisaba is not one package — it is a thin shell adapter sitting on top of a deep, real substrate.

Layer Path What it is
Shell domain adapter libs/oshun/domain-nisaba (@oshun/domain-nisaba) The thin adapter the unified shell consumes: card models, deep links, launch actions, search/recommendation glue, study-plan re-exports
Canonical contracts libs/contracts/src/nisaba/index.ts The fully-implemented zod schema substrate: Passage, Manuscript, Edition, Translation, LexiconEntry, MorphologyEntry, Annotation, concept graph, Notebook, StudyPlan, Citation, ScholarProfile
Domain engines libs/nisaba/* (~22 sub-packages) The working philology stack: @nisaba/languages, @nisaba/criticism, @nisaba/philology, @nisaba/study-plans, @nisaba/editions, @nisaba/annotations, and more
Consumer web surfaces apps/oshun/web/src/app/nisaba/* The reader hub at /nisaba plus presentational sub-routes
Power-user surface components/domains/NisabaSurface.tsx, mounted by DomainRouteExperience on /domains/[domainId] The deep concept-graph / lexicon / manuscript tools

The libs/nisaba/* collection holds 22 sub-packages: annotations, api-client, assistant, canon, client, comparative, core, corpora, criticism, cross-domain, database, editions, geotemporal, languages, mobile, paleography, philology, schemas, standards, study-plans, translations, and workspace. The richest of these — by far the largest body of real Nisaba code — is @nisaba/languages, a polyglot philology engine described in its own section below. The V1 source docs barely mentioned it (under the phrase "morphology lookup"); this page corrects that omission.


Surfaces#

Consumer hub at /nisaba plus presentational depth at:

  • /nisaba/compare — edition and translation comparison
  • /nisaba/daily — the daily passage flow
  • /nisaba/graph — concept-graph exploration
  • /nisaba/lexicon — lexicon and gloss panels
  • /nisaba/manuscript — manuscript image / transcription viewing
  • /nisaba/notebook — a single notebook's editor
  • /nisaba/notebooks — the notebook index (plural; this route exists alongside the singular notebook)
  • /nisaba/plan — study plans
  • /nisaba/scholar — scholar / expert mode

These are rendered in the Lilith design system's NisabaRoom. Note that both notebook (singular, the editor) and notebooks (plural, the index) are real directories under apps/oshun/web/src/app/nisaba/; earlier docs listed only the singular.

Power-user surface. The deeper scholarly tools (concept graph, lexicon, manuscript inspection) are served through NisabaSurface (apps/oshun/web/src/components/domains/NisabaSurface.tsx), which is lazy-loaded and mounted by DomainRouteExperience. There is no dedicated apps/oshun/web/src/app/domains/nisaba/ route folder (unlike Veritas, which has one). Nisaba's power surface resolves only through the dynamic catch-all route apps/oshun/web/src/app/domains/[domainId]/page.tsx; inside DomainRouteExperience.tsx, the domainId switch returns <NisabaSurface origin={origin} stack={stack} hydratedPath={hydratedPath} />. The path /domains/nisaba therefore resolves and works, but it is not backed by its own directory — a clarification over the original prose, which implied a dedicated folder.

V1 scope summary#

Nisaba is the scholarly passage, source, text, study, and concept-graph domain. V1 Nisaba includes:

  • First-class shell recognition across web, mobile, home, recommendations, universal search, library, activity timeline, notifications, onboarding, assistant awareness, and analytics.
  • Web landing/dashboard, reading workspace, edition comparison, translation comparison, manuscript viewing, annotations, highlights, concept-graph exploration, lexicon panels, morphology panels, timelines, influence networks, notebooks, collections, study plans, citations, exports, and scholar/expert mode.
  • Mobile domain home, reading queue, daily passage, compact highlight flow, annotation flow, quick compare, glossary lookup, morphology lookup, saved manuscripts or editions, study reminders, and assistant-assisted explanation with inspectable citations.
  • Cross-domain passage companions for Tara, study plans for Arete, source depth for Veritas, cosmology overlays for Nyx, shared concept-graph linking, and domain-to-domain recommendations.
  • Tests for adapter mapping, filters, passage save, annotate, notebooks, reading, compare, annotation, daily passage, highlight, accessibility, and large-text performance.

The canonical contracts (libs/contracts/src/nisaba/index.ts)#

This file is the implemented heart of Nisaba's data model: a set of fully-typed zod schemas with cross-field superRefine validation. It is real code, not a sketch — every schema below ships with invariants that reject malformed input. The top-level types are Passage, Manuscript, Edition, Translation, LexiconEntry, MorphologyEntry, Annotation, ConceptGraphNode, ConceptGraphEdge, Notebook, StudyPlan, Citation, and ScholarProfile, plus nested schemas (PassageSegment, ApparatusEntry, LexiconSense, NotebookItem, StudyPlanStep, TextRangeSelector, CanonicalReference) and helper predicates (isPublishedPassage, conceptEdgeRequiresEvidence, scholarCanVerifyCitations).

Shared enums and primitives#

Schema Values
NisabaScriptSchema latin, greek, hebrew, arabic, devanagari, pali-sinhala, coptic, cuneiform, tibetan, chinese, japanese, syriac, ethiopic, other
TextDirectionSchema ltr, rtl, vertical, boustrophedon
TextFormatSchema plain-text, markdown, tei-xml, html
PartOfSpeechSchema (12) noun, verb, adjective, adverb, pronoun, particle, preposition, conjunction, interjection, numeral, proper-noun, unknown
MorphologyFeatureSchema (14) case, number, gender, person, tense, aspect, mood, voice, state, degree, stem, root, prefix, suffix
CitationStyleSchema chicago, mla, apa, sbl, cts, custom
RightsStatusSchema public-domain, open-license, licensed, restricted, unknown
ScholarCredentialKindSchema academic-degree, faculty-appointment, editorial-role, translator-credit, institutional-affiliation, community-expert

The boustrophedon direction (alternating line-by-line left-right then right-left) and scripts like cuneiform, syriac, and ethiopic exist because Nisaba is built for the actual scholarly long tail — ancient inscriptions, not just modern prose. The morphology vocabulary (14 grammatical features, including Semitic state and stem and the Indic prefix/suffix slots) is similarly designed for the breadth of the languages the engines cover.

CanonicalReference — stable scholarly citation#

CanonicalReferenceSchema carries a scheme drawn from a concrete enum — cts (Canonical Text Services URNs), osis (Open Scripture Information Standard), sefaria, library-of-congress, or custom — alongside a reference, a normalizedReference, an optional urn, the workId/workTitle, and a divisionPath (the work → book → chapter → verse path, up to 12 levels). This is how a passage gets a stable, scheme-aware citation independent of which edition it happens to be reading.

Passage#

A Passage (PassageSchema) is the atomic reading unit. It carries:

  • canonicalReference (the CanonicalReference above),
  • tradition, language, script, direction,
  • the text and a normalizedText (each up to 250,000 chars), with textFormat,
  • segments — an array of PassageSegments (label, order, offsets) that must be strictly ordered and non-overlapping (ensureOrderedSegments rejects current.order <= previous.order and current.startOffset < previous.endOffset),
  • a sourceLineage block linking manuscriptIds, an editionId, translationIds, and citationIds,
  • bindings to conceptNodeIds, lexiconEntryIds, morphologyEntryIds, and annotationIds,
  • a status (draft | review | published | archived).

A key invariant: a published passage must carry at least one source citationsuperRefine rejects status === 'published' with an empty sourceLineage.citationIds. The helper isPublishedPassage(passage) exposes this state. This is the schema-level expression of Oshun's grounding promise: no published scholarly text without provenance.

Manuscript — the witness#

A Manuscript (ManuscriptSchema) is a physical or digitized witness. It carries a siglum, tradition, language/script, a repository (name, city, country, shelfmark, catalogUrl), a dateRange (notBefore/notAfter/displayLabel), a material (papyrus | parchment | paper | stone | clay | metal | digital), an extent (folio/line counts, completeness), and a digitization block whose status is one of not-digitized | digitized | iiif | transcribed, with an imageManifestUrl, transcriptionId, and ocrQualityBand.

Real cross-field rules enforce:

  • digitized or IIIF manuscripts require an imageManifestUrl (you cannot claim a witness is digitized and then fail to point at its images),
  • non-public-domain manuscripts require a licenseLabel,
  • the date range is coherent (notAfter cannot precede notBefore),
  • relatedPassageIds are unique.

Edition — the constituted text and its apparatus#

An Edition (EditionSchema) is a scholarly text constituted from one or more witnesses. Its editionType is critical | diplomatic | reader | digital | facsimile. It declares manuscriptIds (the witnesses it draws on, 1–300), editorScholarProfileIds, and an apparatus: an array of ApparatusEntrys, each a variant reading (lemma, reading, note) keyed to witnessManuscriptIds.

The cross-field check here is the one that matters most: every apparatus entry's witnessManuscriptIds must be declared in the edition's manuscriptIds — you cannot cite a variant reading against a witness the edition does not claim. The schema also requires that published editions carry a publicationDate and that approved editions carry reviewer identity and a reviewedAt timestamp. Editions are versioned (via createdAt/updatedAt and review state) and a passage cites a specific edition through its sourceLineage.editionId.

Translation#

A Translation (TranslationSchema) is a per-target-language rendering bound to a passageId and optionally an editionId. It declares distinct sourceLanguage and targetLanguage (a superRefine rejects them being equal), a locale, translator scholar profiles, the text/textFormat, rights metadata, and a translationMode:

translationMode Meaning
literal Word-for-word
formal-equivalence Structurally faithful
dynamic Sense-for-sense / dynamic equivalence
commentarial Translation interwoven with explanation
adaptive Free adaptation

Approved translations, like editions, require a reviewer identity and reviewedAt. Because translations are bound to a passage and (optionally) an edition, edition comparison and translation comparison can render interlinearly.

Lexicon and morphology#

A LexiconEntry (LexiconEntrySchema) carries lemma/normalizedLemma, language/script, an optional transliteration, a partOfSpeech, an array of roots, one-or-more glosses, and one-or-more senses — each LexiconSense carrying an ordered gloss, a semanticDomain slug, and the passageIds where that sense is attested. It also tracks etymology, inflectedForms, sourceCitationIds (at least one required), relatedEntryIds, and a reviewState. Entries cannot relate to themselves.

A MorphologyEntry (MorphologyEntrySchema) parses a single attested word form. It binds a passageId/segmentId/tokenIndex, records the surface and normalizedSurface, an optional lemmaEntryId, a partOfSpeech, and an array of features (each a { feature, value } pair drawn from the 14-value MorphologyFeature enum, deduplicated by feature). Critically it records the parsing provenance: parsing.method is one of human | rule-engine | model-assisted | imported, with a score, and a rule says human parsing requires a reviewerScholarProfileId — you cannot attribute a parse to a human without naming one. This is the data behind "glossary lookup" and "morphology lookup": a tapped word resolves to these records.

Concept graph#

ConceptGraphNode and ConceptGraphEdge are Nisaba's contribution to the platform-wide concept graph (see Search, Discovery, Recommendations, and Knowledge Graph).

A ConceptGraphNodeSchema.kind is one of 10: term, deity, place, person, textual-theme, ritual-practice, cosmology, historical-event, school, manuscript-family. Each node carries a summary, traditions, languageCoverage, aliases, passageIds, lexiconEntryIds, and externalRefs (authority/identifier/url triples to external authority files).

A ConceptGraphEdgeSchema.relation is one of 9: broader-than, narrower-than, related-to, influences, contrasts-with, translation-equivalent, ritualizes, comments-on, shares-source-lineage. Each edge has a direction, evidencePassageIds, citationIds, a confidenceBand (high | medium | low | contested), and a rationale. Two real invariants: an edge cannot point to its own source node, and a high-confidence edge must carry at least one evidence passage or citation — exposed via conceptEdgeRequiresEvidence(edge). This is the schema-level form of expert-review gating on high-stakes edges.

Correction to earlier prose. Earlier V1 docs described Nisaba's edge labels as refers-to / derives-from / comparative-to / lineage-of, and said "influence networks render the derives-from and comparative-to subgraph." None of those four labels exist in the implemented enum. They were illustrative. The real relation enum is the 9-value set above; a reader following the old vocabulary would author edges the contract rejects. The closest real analogues are influences (for influence networks) and shares-source-lineage (for lineage).

Annotations, notebooks, study plans, citations#

  • Annotation (AnnotationSchema) anchors a highlight / note / question / variant-note / commentary / cross-reference / morphology / lexicon to a target (passage | segment | translation | manuscript | edition | token) via an optional TextRangeSelector. It has visibility (private | shared | public), tags, linkedNotebookIds, citationIds, and a status. Rules: non-highlight annotations require body text; segment and token annotations require a text selector. The TextRangeSelector itself enforces endOffset > startOffset.
  • Notebook (NotebookSchema) is a curated container of passageIds, annotationIds, conceptNodeIds, citationIds, and ordered NotebookItems (kinds: passage | annotation | concept | citation | note | study-step), with collaborators (owner/editor/commenter/viewer) and a kind (research | translation | philology | teaching | reflection | collection). A shared notebook requires at least two collaborators.
  • StudyPlan (StudyPlanSchema) is an ordered sequence of StudyPlanSteps. The 9 step kinds are read-passage, compare-translation, view-manuscript, lexicon-review, morphology-review, concept-map, annotation, reflection, assessment. Steps must be strictly ordered (ensureOrderedSteps); a non-reflection step requires a targetId; active plans require a startedAt, completed plans a completedAt. The plan declares a level (introductory/intermediate/advanced/scholar) and an objective.
  • Citation (CitationSchema) binds a subject (any of ten object kinds) to a source (manuscript | edition | translation | article | book | lexicon | database) with a locator (page/folio/line/section), a style from the 6-value CitationStyle enum (including the scholarly sbl and cts), a formatted string, a rightsStatus, and a verification block. Approved citations require a verifiedAt and a scholarProfileId.

ScholarProfile — credentials and review authority#

A ScholarProfile (ScholarProfileSchema) carries credentials (each a { credentialId, kind, institution, field, verified, verifiedAt } where a verified credential requires a verifiedAt), areasOfExpertise, languages, an attributionPreference (full-name | initials | institutional | anonymous-review), disclosureControls, and a reviewAuthority block:

jsonc
"reviewAuthority": {
  "canApproveEditions": true,
  "canApproveTranslations": true,
  "canVerifyCitations": true,
  "maxReviewRisk": "high"   // "low" | "medium" | "high"
}

The entitlement gate is real and enforced at the schema level: citation verification authority requires at least one verified credential — the superRefine rejects reviewAuthority.canVerifyCitations === true when no credential is verified, and the predicate scholarCanVerifyCitations(profile) expresses the same check. This is the contract behind scholar/expert mode's review gating.


The shell adapter (@oshun/domain-nisaba)#

The @oshun/domain-nisaba package is the thin layer the unified shell consumes. Its NisabaApiAdapter interface (libs/oshun/domain-nisaba/src/types.ts) defines the read/write surface the shell calls:

Method Purpose
getDailyPassage One passage for today (by user/tradition/locale)
getContinueReading Resume state with progressPercent and lastReadAt
getSavedPassages / savePassage / unsavePassage The saved-passage list and toggles
getStudyReminders / setStudyReminder / toggleStudyReminder Study reminders
getConceptThreads Concept threads (id, label, summary, passage/tradition counts)
getWorkspaceEntries Workspaces / notebooks / projects / compares
searchLibrary Multi-mode philological search (see below)
getHealth Adapter health (ok / degraded / down)

The adapter exposes a NisabaResearchType for workspace entries — CRITICAL_EDITION | TRANSLATION | COMPARATIVE_STUDY | PHILOLOGICAL_ANALYSIS | MANUSCRIPT_SURVEY — and a NisabaProjectStatus (DRAFT/ACTIVE/REVIEW/PUBLISHED/ARCHIVED). The package's index.ts re-exports the adapter, card model, deep links, launch actions, the domain adapter, the concept-graph linkages, the domain recommendations, the Metis relationship glue, and the study-plans re-export.

The adapter's search model — undocumented in the original prose — is a genuine multi-mode surface. searchLibrary accepts a searchMode of:

NisabaSearchMode Use
fulltext Free-text search
lemma Search by dictionary headword
morphology Search by parsed grammatical form
semantic Concept / meaning search
regex Regular-expression matching
proximity Co-occurrence / nearness search

and filters by NisabaSearchEntityKind (passage | source | concept | notebook | collection), traditions, and languages. Each hit (NisabaSearchHit) carries the kind plus the relevant target id (passageId / sourceId / conceptId / notebookId / collectionId).

Cross-domain wiring (real)#

Nisaba's cross-domain links are implemented, not aspirational. concept-graph-linkages.ts delegates to the shared concept graph in @oshun/navigation, calling buildOshunSharedConceptGraphThread and inferOshunSharedConceptIds. It maintains a small alias map, NISABA_CONCEPT_ID_ALIASES, that maps Nisaba-local concept ids onto the platform's shared concept ids:

ts
const NISABA_CONCEPT_ID_ALIASES = {
  'concept-attention': 'focus-protection',
  'nisaba-concept-detachment': 'honest-reflection',
  'nisaba-concept-nonreaction': 'honest-reflection',
};

buildNisabaSharedConceptGraphThreads then materializes shared threads anchored on a passage, concept thread, or search hit (with target paths like /library/passage/{id}?view=grounded and /library/concept/{id}).

domain-recommendations.ts builds cross-domain recommendations on top of this. A NisabaDomainRecommendationCandidate carries a reason of either shared_concept_graph or source_study, a targetDomain (any non-Nisaba shared domain plus metis), and an itemType (claim_handoff | ritual_handoff | practice_handoff | event_handoff | study_handoff). Shared-concept links score from a per-target-kind base (claim 91, ritual 88, practice 87, learning_objective 86, event 85, decaying by thread index); Metis study moments score source_backed_tutoring 94, study_guide 91, lesson_path 89. Recommendations are deduped to one per target domain and capped (default 5). These map onto NisabaCrossDomainRecommendationItem (web) and NisabaMobileRecommendationCardItem (mobile). This is the implemented form of "passage companions for Tara, study plans for Arete, source depth for Veritas, cosmology overlays for Nyx," and study handoffs to Metis.

Study plans re-export#

libs/oshun/domain-nisaba/src/study-plans.ts re-exports the real @nisaba/study-plans engine, surfacing createNisabaStudyPlan, recordNisabaLearnerProgress, sequenceNisabaStudyResources, initializeNisabaLearnerTracking, and the supporting types (NisabaCompletionForecast, NisabaStudyPlanCadence, NisabaStudyPlanDifficulty, NisabaStudyPlanObjective, NisabaStudyResourceSequence, and more). Skipping a step is logged, never penalized — consistent with Arete's humane-cadence policy.


@nisaba/languages — the polyglot philology engine#

This is the largest body of real Nisaba code and was nearly invisible in the original V1 docs. @nisaba/languages (libs/nisaba/languages/src) ships 30+ script/language modules plus transliteration, tokenization, and a lexicon service. Its index.ts exports each language as a namespace module and also exports concrete ScriptHandler classes for direct use.

The covered scripts/languages include: hebrew, aramaic (Imperial and Biblical), syriac, arabic, ethiopic, phoenician (with Paleo-Hebrew and Moabite), samaritan, ugaritic, cuneiform (Sumerian), egyptian-hieroglyphic, egyptian-hieratic, egyptian-demotic, coptic, devanagari, pali, prakrit, tibetan, tamil-brahmi, grantha, kharoshthi, classical-chinese, ancient-greek, latin, avestan, old-persian, old-church-slavonic, runic, and linear-b — plus transliteration, tokenization, and lexicon.

The concrete exported handlers include:

Handler Script
ImperialAramaicScriptHandler, BiblicalAramaicScriptHandler Aramaic
SyriacScriptHandler Syriac
ArabicScriptHandler Arabic
EthiopicScriptHandler Ethiopic
PhoenicianScriptHandler, PaleoHebrewScriptHandler, MoabiteScriptHandler Phoenician family
SamaritanScriptHandler Samaritan
UgariticScriptHandler Ugaritic
SumerianCuneiformHandler Cuneiform
EgyptianHieroglyphicHandler, EgyptianHieraticHandler, EgyptianDemoticHandler Egyptian
CopticHandler, DevanagariHandler, PaliHandler, PrakritHandler, TibetanHandler
TamilBrahmiHandler, GranthaHandler, KharoshthiHandler Indic
ClassicalChineseHandler, AncientGreekHandler, LatinHandler
AvestanHandler, OldPersianHandler, OCSHandler, RunicHandler, LinearBHandler

The lexicon namespace exports a LexiconService for unified multi-lexicon lookup (e.g. service.lookup('word', { language: 'hbo' })). The cuneiform module ships a real ATF (ASCII Transliteration Format) parser, generator, and Unicode bridge under cuneiform/atf/ — the conceptual bridge to Oracc/CDLI conventions mentioned elsewhere lives here, in code, not as an external API call.

This engine is what makes "morphology lookup," "glossary lookup," and the script-aware NisabaScript/TextDirection contract values more than labels: each script handler can classify characters, transliterate, and tokenize the languages it covers.


@nisaba/criticism — textual criticism and IIIF linking#

@nisaba/criticism (libs/nisaba/criticism/src) is the textual-criticism engine: it ships collation-engine.ts, apparatus-generation.ts, stemmatic-analysis.ts, cbgm-analysis.ts (Coherence-Based Genealogical Method), lachmannian-reconstruction.ts, witness-classification.ts, scribal-error-taxonomy.ts, leiden-conventions.ts, siglum-management.ts, and more — the working machinery behind the Edition apparatus model.

It also ships real IIIF manifest linking in iiif-linking.ts, exporting an IIIFLinkRegistry, IIIFManifestRef, IIIFCanvasRef, WitnessManifestLink, CanvasTextMapping, and functions like createIIIFLinkRegistry, createManifestLink, addCanvasTextMapping, and findCanvasForPosition. This is how a manuscript's digitization.imageManifestUrl connects to a transcription so the reading workspace can show a manuscript image alongside its transcription — all in-code, against the IIIF Presentation API shape, with no external base-URL configuration required.


Reading, study, and scholar workflows#

Reading workspace states#

A passage view supports split-view edition compare, split-view translation compare, manuscript image alongside transcription, and a lexicon/morphology side panel. Reading position is surfaced as a continuation token (getContinueReading returns progressPercent and lastReadAt) so study resumes mid-passage across devices.

Daily passage#

One passage per day per declared study plan or free-reading interest, with a compact highlight flow and an assistant-assisted explanation whose every interpretive claim exposes inspectable Sophia citations.

Scholar / expert mode (contract-modelled, runtime gated)#

Scholar mode is an entitlement-gated reading mode that exposes the critical apparatus, witness sigla, full morphology, alternative editorial readings, and direct manuscript-image access. The ScholarProfile carries credentials, expertise domains, attribution preferences, disclosure controls, and the reviewAuthority gate described above. The schema-level gating is real and enforced; the runtime entitlement gate that turns scholar mode on per-user is not yet verified end-to-end — see "Honest status" below.

Citations and export#

A passage, annotation, or notebook entry exports with a canonical citation (edition version pinned) and an integrity manifest; exports are gated on the source edition's rights metadata (RightsStatus). The Citation contract models this; the integrity-manifest export pipeline is part of the broader Output Gallery, Lineage, Branch, and Replay and Privacy, Consent, Data Portability, and User Controls machinery.

Cross-domain companions#

Passage companions surface in Tara ritual completion (reflection passages on declared themes); study plans feed Arete goals; source depth backs Veritas claims through shared sources; cosmology passages overlay Nyx events; and the shared concept graph links passages, claims, phenomena, and learning objectives. The implemented form of this is the domain-recommendations.ts machinery above.


External-source binding — what is real vs. aspirational#

The original docs (and ARCHITECTURE.md) claimed Nisaba binds to external sources "configured via NISABA_SEFARIA_API_URL, NISABA_CDLI_API_URL, NISABA_IIIF_BASE_URL." These environment variable names do not exist in the codebase. A repository-wide grep across all *.ts files returns zero occurrences of any of the three. They are fabricated/aspirational and should not be relied on.

What does exist, in code, are conceptual references to those standards inside the engines: the ATF parser in @nisaba/languages/src/cuneiform/atf/ handles the transliteration format used by Oracc/CDLI cuneiform corpora, and the iiif-linking.ts module in @nisaba/criticism implements IIIF manifest linking as a typed in-process registry. There is no configured HTTP client calling Sefaria, CDLI, or an IIIF base URL today.

Likewise, the source-lifecycle invalidation cascade — where a source-edition correction fires an edition-update notice on notebooks that cited the affected passage — is modeled in the contracts (the sourceLineage, citationIds, and review-state fields are all present) but the runtime wiring that fires the notice is unverified. Treat it as spec, not shipped.


Honest status (V1)#

Per the 2026-06-23 triage:

  • Nisaba is disconnected in the hydrated shell. After profile hydration, Nisaba reports disconnected and Metis reports planned, dropping the live shellDomainCount to 4. The contracts, engines, and adapter exist; the live shell connection does not yet light up for Nisaba.
  • The scholarly-read e2e journey runs on a stub workspace API. The nisaba-scholarly-read journey exercises a stub workspace API, and the scholar apparatus it shows is render-only — the apparatus is displayed but not yet backed by a live constituted edition at runtime.
  • The notebook-capture-and-cite journey has a stubbed round-trip. The nisaba-notebook-capture-and-cite journey has its Sophia stable-ID round-trip stubbed; the citation capture renders but the durable stable-ID grounding loop is not yet wired through.
  • Durable annotation re-anchoring across edition revisions is described and the schema supports it (TextRangeSelector, sourceLineage versioning), but the re-anchoring runtime is not verified.

This is the candid picture: Nisaba has an unusually deep and real substrate (the contracts and the @nisaba/languages / @nisaba/criticism engines are genuine, substantial code), wrapped in shell and e2e surfaces that are still running on stubs. The remaining work is integration and runtime wiring, tracked in the V1 backlog — not new schema or engine design.