Skip to content

P106: the dictionary-group index + the 84000 harvest - #146

Merged
arvicco merged 9 commits into
mainfrom
phase-106
Sep 27, 2026
Merged

arvicco merged 9 commits into
mainfrom
phase-106

Conversation

@arvicco

@arvicco arvicco commented Sep 27, 2026

Copy link
Copy Markdown
Owner

The dictionary-group index + the 84000 harvest

Dictionary shelves now group by lect, every dictionary-shaped surface answers from the group, and the 84000 shelf's two long-named follow-ups — the back-matter glossary term bank and the Derge title crosswalk — are built. Two hardening riders close real incident classes in the lect facet's lifecycle and the batch-link replay contract.

The dictionary-group census (dictionary_stats, migration 036)

One precompiled row per dictionary: shipped language code, the lect node it resolves to through the nabu-lects ladder (per-source overrides included; NULL = the registry defines no such node — censused as unresolved, never silently invented), live entry count. Derived wholesale in both rebuild flavors and rake builders:refresh, per source after any dictionary-bearing sync.

Surfaces re-read the group:

  • nabu language <code> gains its dictionary-group block — every shelf at or under the code's resolved node (prefix semantics: lat collects the la-med shelf's lat:med), entries descending, render-capped with an honest truncation line;
  • define's header and --lang validation (and the MCP define lang enum) read the census instead of live-scanning the shelf table, with the byte-identical fallback for underived catalogs;
  • the site census gains dictionary_lects / dictionary_unresolved_codes (54 / 61 live), cited from the languages page through Liquid only, guard-tested.

Recorded v1 limit: a dictionary carries ONE language code; mixed dictionaries group under their primary. A companion registry PR (arvicco/nabu-lects#17) covers the ancient-language tail of the unresolved census — after it merges and reaches canonical, resolution rises 175 → 326 of 464 on the same census.

The 84000 glossary shelf (second dictionary lane)

Every publication's back-matter <div type="glossary"> entity records — Tibetan script, Wylie, Sanskrit, English rendering, definition — load as ONE shared xct-headed shelf (e84000-glossary) through the secondary dictionary lane. Discovery delegates to the primary adapter's cone and duplicate-pair winner rule, filtered to gloss-bearing files, so the lane can never disagree with the passage shelf about editions. Tibetan headwords strip the trailing shad before folding so EWTS-typed queries hit (define gser 'dab → garuḍa), while key_raw keeps the verbatim upstream term; both real upstream gloss shapes parse (bare <term> + inline definition, and translationMain + <note type="definition">). License: the entries inherit 84000's stated CC BY-NC-ND 3.0 grant (class nc), credited as the source row states.

The 84000 → Derge title crosswalk

Every 84000 header — the 3,926 placeholder stubs (which carry the titles of every untranslated text) and the published translations — names its Toh text in English and Wylie; the Derge shelves mint those documents title-less. The new pass fills documents.title by EXACT Toh key (a part key titles the part document; no base-container inference), published headers winning over placeholders. Runs in both rebuild flavors, builders:refresh, and after e84000/derge syncs.

Riders

  • Lect-facet lifecycle hardening: LectFacets.rebuild!'s delete + rewrite + census now run in one transaction (a killed rebuild can no longer strand a zero-row axis); builders:refresh covers the lect facet, the dictionary census and the title crosswalk; nabu health gains three loud invariants — stats claiming staged documents beside an empty facet, per-key census drift, and override-ruled sources holding live documents with zero staged rows.
  • Place scopes in the replay contract: place mine / place link record producer + scope + gazetteer in config/link_scopes.yml, and the links-stage replay (extracted to LinkScopeReplay, dispatch and ordering test-pinned) re-runs both — place-link after place-mine, with a loud failure when the places registry is absent.
  • Registrations: the new table classified in the derivability manifest; the two new corpus stages labeled in the rebuild profile (their time reaches the report and the durable ETA record).

The live round (run, verified)

bin/nabu sync e84000 --parse-only
# 388 documents =skipped (content unchanged) · dict +56,794 entries into e84000-glossary
# 124,223 passages reindexed · crosswalk refs re-derived (488 edges)
# derge titles: 4,451 of 4,560 documents titled (the 109 remainder have no
# exact-key 84000 header — the honest gap until a bare-base header exists)

dictionary_stats derived live: 464 rows, 54 lect nodes, 61 unresolved codes. Suite 9,971 runs / 207,527 assertions / 0 failures; rubocop 1,265 files clean; site census restamped from the live catalog at this gate.

One row per dictionary (shipped language code, resolved lect node via
the nabu-lects ladder, live entry count) in migration 036, derived by
Store::DictionaryStats: wholesale in both rebuild flavors, per source
after any dictionary-bearing sync (primary shelf or secondary lane;
withdrawals count). A code the registry cannot place stays NULL — the
censused-unresolved posture — and cards can now read the group without
scanning millions of entries (the desk-commands law).
The language card gains its dictionary-group block: every shelf whose
lect resolution lands at or under the code's node (prefix semantics),
entries descending, render-capped with an honest truncation line.
define's header and lang validation, and the MCP define lang enum, read
the dictionary_stats census when one is derived (live-scan fallback
stays for underived catalogs, byte-identical). The site census gains
dictionary_lects + dictionary_unresolved_codes (54 / 61 live), cited
from languages.md through Liquid only, with the SSOT guard extended.
The publication back matter's glossary entity records (bo/Wylie/
Sanskrit/English terms + definitions, parsed around since the shelf
landed) become one shared xct-headed dictionary via the secondary
dictionary lane: discovery delegates to the primary adapter's cone and
winner rule, filtered to gloss-bearing files; Tibetan headwords strip
the trailing shad so folded lookups meet EWTS-typed queries while
key_raw keeps the verbatim term; both upstream gloss shapes (bare term
+ inline definition, translationMain + note definition) parse.
Every 84000 header — 3,926 placeholder stubs and the published
translations — carries its Toh text's English and Wylie mainTitles;
the derge shelves mint those documents title-less. The new pass reads
the headers off canonical/e84000 (published files through the primary
adapter's duplicate-pair winner rule) and fills documents.title by
EXACT Toh key, no base-container inference. Runs in both rebuild
flavors, in builders:refresh, and after e84000/derge syncs; absent
tree is a clean no-op.

builders:refresh also gains the lect-facet stage plus the two new
censuses — the sanctioned in-phase pass now covers every rebuild-only
derivation a killed rebuild could strand dark.
The materialized lect axis went dark corpus-wide when a killed rebuild
committed LectFacets' wholesale DELETE without the rewrite, and nothing
went red for a day. Three closures: (1) rebuild!'s delete + rewrite +
census now run in ONE transaction, so a kill can never strand the
zero-row state; (2) builders:refresh covers the lect facet (landed with
the P106-5 wiring); (3) nabu health gains the stats-vs-facet invariant
— stats claiming staged documents beside a zero-row facet, per-key
census drift, and override-ruled sources holding live documents with
zero staged rows all go loud with the re-derive remedy named.
The 2026-09-27 rebuild re-minted the links journal and silently
dropped the standing 3.25M-edge place-mine run: the place CLIs never
recorded their scopes and the links-stage replay knew only the three
original batch producers. Both halves closed: place mine / place link
record producer+scope+gazetteer in link_scopes.yml on every apply, and
the replay dispatch — extracted to LinkScopeReplay so order and
dispatch are pinned — covers both, with place-link ordered after
place-mine (promotion needs the candidates) and a loud failure when
the places registry is absent.
architecture 11 records dictionary_stats (the precompiled per-lect
group census, its readers and the recorded v1 one-code limit) and the
second dictionary lane; 02-sources' 84000 row flips the named
follow-up to built (glossary lane) and records the Derge title
crosswalk.
The derivability manifest classifies the new catalog table, and the
rebuild profile labels the two new corpus stages so their time reaches
the report and the durable ETA record (the P58-P77 vanishing-stage
lesson, caught by both census guards on the first full-suite run).
…talog

2,608,205 dictionary entries across 465 shelves under 55 registry lect
nodes (61 codes censused unresolved) — the glossary shelf's first
census — plus the routine axis-page recounts.
@arvicco
arvicco merged commit 81f5137 into main Sep 27, 2026
2 checks passed
@arvicco
arvicco deleted the phase-106 branch September 27, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant