# Nisaba — Scholarly Study

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](./domain-tara.md),
[Arete](./domain-arete.md), [Veritas](./domain-veritas.md),
[Nyx](./domain-nyx.md), and [Metis](./domain-metis.md)), 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)](#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 `PassageSegment`s (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 citation**
— `superRefine` 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 `ApparatusEntry`s,
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](./search-discovery-recommendations.md)).

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 `NotebookItem`s
  (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
  `StudyPlanStep`s. 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.

### Multi-mode philological search

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](./domain-metis.md).

### 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](./domain-arete.md) 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](./sophia-grounding.md)
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](./output-gallery-lineage.md) and
[Privacy, Consent, Data Portability, and User Controls](./privacy-consent-portability.md)
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.

---

## Related

- [Metis — Education and Tutoring](./domain-metis.md) — the primary cross-domain
  study handoff target
- [Veritas — Grounded Stories and Claims](./domain-veritas.md) — source depth
  shared via the concept graph
- [Tara — Rituals and Contemplative Practice](./domain-tara.md) and
  [Nyx — Sky Events and Perspective](./domain-nyx.md) — passage companions and
  cosmology overlays
- [Arete — Goals, Habits, and Reflection](./domain-arete.md) — study plans feed
  Arete goals under a shared humane-cadence policy
- [Search, Discovery, Recommendations, and Knowledge Graph](./search-discovery-recommendations.md)
  — the shared concept-graph substrate
- [Sophia Grounding](./sophia-grounding.md) — inspectable citations behind
  interpretive claims
- [Customer Curation, Notebooks, Collections, and Sharing](./customer-curation-notebooks.md)
  — the notebook and collection surfaces
- [Product Surfaces](./product-surfaces.md) and
  [Subsystem Glossary](./glossary.md) — orientation across V1
- The hub: [../features.md](../features.md)
