refactor: derive 1954 rank from legacyRank; add generator unit tests #448

Merged
manlycucumber merged 1 commit from feature/63-rank-derivation into develop 2026-07-04 05:58:15 +00:00
manlycucumber commented 2026-07-04 05:57:01 +00:00 (Migrated from github.com)

Foundation-review follow-up (PR #447, top recommendation) — do the rank-model hardening before the full 1954 dataset and Rubrics1954Precedence (#67) depend on the grade↔class pairing.

Problem

A 1954 block authored both legacyRank (grade token) and rank (numeric class) as independent, independently-cited facts. A typo (duplex-ii-classis + rank: 1) would pass every gate — the schema validates each separately and the provenance gate only checks each is cited, not that they agree.

Fix

Make the numeric rank a single derived fact:

  • transformSanctoraleEdition derives rank from legacyRank via DEFAULT_RANK_BY_LEGACY, cited to the grade's own source.
  • Because the 1960 revision re-graded some feasts off the default (the mapping is "deliberately not 1:1"), an explicit self-cited rankOverride handles the divergent cases. The default table is a coarse sort key; the fine grade lives in legacyRank and is what Rubrics1954Precedence (#67) will order on.
  • Fail-closed: an unmapped grade (dominica-*/feria-maior in a sanctoral block) or a rankOverride missing its cite errors the build.

Behaviour-preserving

The 8 authored 1954 blocks drop their now-redundant explicit rank. The regenerated corpus is byte-identical (git status data/corpus is empty after rebuild) — the derivation reproduces the exact same records. The golden fixture and the entire 1962 corpus are untouched.

Tests (the generator had none)

New Node harness — npm test (node --test), wired into the corpus-verify CI job. tools/generator/test/transform.test.mjs covers the derivation across all seven sanctoral grades, rankOverride precedence + its required citation, the unmapped-grade and missing-grade fail-closed paths, and edition-absence skipping.

Closes review follow-up (1); the edition-diff report (2) and enum-scoping (4) remain tracked for the dataset-burndown / #61.

Part of Epic #63.

Foundation-review follow-up (PR #447, top recommendation) — do the rank-model hardening **before** the full 1954 dataset and `Rubrics1954Precedence` (#67) depend on the grade↔class pairing. ### Problem A 1954 block authored *both* `legacyRank` (grade token) and `rank` (numeric class) as independent, independently-cited facts. A typo (`duplex-ii-classis` + `rank: 1`) would pass every gate — the schema validates each separately and the provenance gate only checks each is *cited*, not that they agree. ### Fix Make the numeric `rank` a single **derived** fact: - `transformSanctoraleEdition` derives `rank` from `legacyRank` via `DEFAULT_RANK_BY_LEGACY`, cited to the grade's own source. - Because the 1960 revision re-graded some feasts off the default (the mapping is "deliberately not 1:1"), an explicit **self-cited `rankOverride`** handles the divergent cases. The default table is a *coarse sort key*; the fine grade lives in `legacyRank` and is what `Rubrics1954Precedence` (#67) will order on. - Fail-closed: an unmapped grade (`dominica-*`/`feria-maior` in a sanctoral block) or a `rankOverride` missing its cite errors the build. ### Behaviour-preserving The 8 authored 1954 blocks drop their now-redundant explicit `rank`. **The regenerated corpus is byte-identical** (`git status data/corpus` is empty after rebuild) — the derivation reproduces the exact same records. The golden fixture and the entire 1962 corpus are untouched. ### Tests (the generator had none) New Node harness — `npm test` (`node --test`), wired into the `corpus-verify` CI job. `tools/generator/test/transform.test.mjs` covers the derivation across all seven sanctoral grades, `rankOverride` precedence + its required citation, the unmapped-grade and missing-grade fail-closed paths, and edition-absence skipping. Closes review follow-up (1); the edition-diff report (2) and enum-scoping (4) remain tracked for the dataset-burndown / #61. Part of Epic #63.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Directorium/Core!448
No description provided.