# LG-3 — CORE-Logos Studio: Contents tabs (Lexicon / Glosses / Morphology) **Date:** 2026-06-14 **Wave:** read-only CORE-Logos Studio (L1–L5). Parent pack: `docs/handoff/core-logos-studio-readonly-briefs-2026-06-14.md`. Plan: `docs/workbench/core-logos-studio-plan.md`. **Depends on:** **LG-2 merged** (`/logos` route shell + the 10 `Logos*` TS interfaces already mirrored + `NOT_YET_MIRRORED` shrunk). Rebase on it. May be authored in parallel with LG-4, but **merges sequentially** with it (shared train files: `routes.ts` / `App.tsx` / `api.ts` / `evidenceAddress.ts`) — rebase-union + retest, Wave R/M discipline. **Scope (hard):** the three **Contents** tabs only — Lexicon, Glosses, Morphology. **No Alignment tab (LG-4). No mutation affordances.** Reads only `GET /logos/packs/{id}/contents` (`LogosPackContents`). ## Non-negotiables - **No theater, no recompute.** Render only fields the `/logos/contents` endpoint returns. Dangling-link flags **reuse** the LG-1 safety report's `dangling_morphology_links` — never recompute link integrity in React. - Read-only; determinism (no nondeterministic ordering); doctrine gates green. ## Build Add three tabs to the existing `/logos` `TabBar` (pattern: `src/app/packs/PacksRoute.tsx`). Each list uses the shared primitives: `src/design/components/VirtualizedList`, `src/design/components/SearchInput`, `src/design/hooks/useListNavigation.ts`, with selection tokens. ### Lexicon (`LogosLexiconRow`) Columns: `entry_id` · `surface` · `lemma` · `language` · `pos`/`part_of_speech` · `semantic_domains` · `morphology_id` · `provenance_ids` · `epistemic_status`. - Search over surface/lemma/domain; filter by `epistemic_status`; group by semantic domain. - Flag rows whose `morphology_id` appears in the safety report's `dangling_morphology_links` (cross-reference, don't recompute). - `speculative` is the expected default (ADR-0021) — label neutrally. ### Glosses (`LogosGlossRow`) Columns: `gloss_id` · `lemma` · `gloss` · `pos` · linked `entry_ids` · `provenance_ids` · `epistemic_status`. Link each gloss to its lexicon entries via `entry_ids`. Raw row available in a collapsible (`raw`). ### Morphology (`LogosMorphologyRow`) - Render the ordered operator chain **in schema order**: `root → prefix_chain → stem → inflection → suffix_chain`. Ordering is load-bearing (Semitic root / Koine grammar) — **never re-sort**. - Link to the lexicon entry via `morphology_id`; flag dangling (same cross-reference to the safety report). ### Evidence subjects (`src/app/evidenceAddress.ts`) Add three subject kinds + address grammar (alongside the LG-2 `logos_pack`): - `logos_entry` → `logos::entry:` - `logos_gloss` → `logos::gloss:` - `logos_morphology` → `logos::morphology:` Each: union member, equality, encode/parse, right-inspector projection, copyable pointer, `?inspect=` sync, chain-rail derivation. Round-trip tests in `evidenceAddress.test.ts`. ## Acceptance / tests - Render + filter + keyboard-nav tests for each tab against fixture `LogosPackContents`. - Dangling-link flag test: a row flagged in the safety report shows the flag; others don't. - Morphology order test: chain renders in schema order (assert against a known Hebrew entry, e.g. `he-morph-008` suffix `ים`). - `evidenceAddress.test.ts` — round-trip for all three new kinds. - `routes.test.tsx` / `schemaDrift` / `enumCoverage` stay green. **No new engine schemas** (LG-2 mirrored them) — `NOT_YET_MIRRORED` untouched. - `pnpm build` clean. - **Run the FULL `pnpm exec vitest run` before push — it must pass AND exit.** The CI `workbench-ui` job gates on the whole suite; focused per-file runs miss a PR's own new test files and cross-cutting tests (LG-2 lesson: stale route-count assertions only surfaced in the full run, never the focused one). ## Out of scope (separate brief) - **LG-4** — Alignment tab + holonomy-absent confirmation.