Repository navigation
Fold seven entity-drift lineages into their economy/aggregate siblings - #344
Merged
MaxGhenis merged 6 commits intoOct 12, 2026
Merged
Conversation
Max's ruling d353 (2026-09-27): the hand-recorded May 2026 rows of seven series carry a different entity from every resolver print of the same series, so the catalog kept two lineages for each. Alias inheritance never crosses an entity slice, and the curated-merge recipe restores the split on regeneration (reproduced 2026-09-22). - build_series_catalog.py reads a curated seed, ledger/seeds/entity_folds.json (chronicle_entity_folds_v1). Before identities are grouped, current rows of a fold's concept and geography carrying the absorbed entity are read as carrying the survivor entity; the observation file is never changed. The absorbed row's names join the survivor's aliases, its binding retires with the --remint-note, and the catalog commits to the seed as entity_folds_sha256 (absent without a seed). - Once a committed catalog declares the digest, regenerating without the seed is a hard error. A fold that matches no current row is inert; a fold must name an absorbed identity the registry has bound and a survivor the committed catalog holds. - The default seed path is seeds/entity_folds.json beside the catalog, so the Thesis resolver's staged regeneration and temporary test repos resolve it without new flags. - Regenerated with --allow-remint: 228 -> 221 series, seven retire lines, no mint, no supersede; observation_count still sums to the 233 current rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Behaviour: two drift lineages fold into one, the survivor keeps its UUID, the absorbed binding retires with the note, the catalog commits to the seed, and regeneration is byte-identical. A first fold is refused without --allow-remint and pending under --check. - Ratchet: deleting the seed under a catalog that declares it is a hard error. Emptying a fold revives the absorbed UUID. A fold matching no current row is inert. Alias-spelled absorbed rows fold too. - Refusals: closed seed schema (twelve cases), strict JSON, an absorbed identity the registry never bound, a survivor with no committed row. - Property (Hypothesis, any split of one series across two entities, overlapping months allowed): observations are conserved, nothing is minted or superseded, exactly the absorbed UUID retires, the survivor spans every period, regeneration is byte-identical, and an emptied fold revives exactly the absorbed UUID. - docs/catalog-curation-backlog.md: the seven entity-drift families move from blocked to folded, with the survivors, the retired bindings, the two unfolded sibling pairs and how to undo a fold. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
feat/catalog-entity-fold-d353
branch
from
October 12, 2026 13:52
dcca5a4 to
a803f08
Compare
This was referenced Oct 12, 2026
Merged
Answers the independent review of a803f08. - Any change to the entity-fold seed is an identity change and needs --allow-remint --remint-note, even when it plans no registry event: retargeting a fold's survivor moved observations between two existing lineages with no ceremony (three-entity regression added). - Undoing a fold now restores earlier same-dimension spelling merges. A row that matches nothing in its own slice rejoins a retired identity of its own entity whose names live on another slice's row, and those names move back off that row. Undoing all seven folds on the committed artifacts reproduces the pre-fold catalog exactly apart from the seed and registry digests; before this, the us.frb and us.census spellings revived as separate identities. The property test and an alias-bearing regression assert the exact round trip. - A folded row's own entity is validated before the fold replaces it. - The strict-JSON seed test checks duplicate keys, NaN and Infinity separately. - The docstring says what the fold guarantees about corrections: an inert fold never fails. Superseding a pre-versioning row is refused by the builder whatever the folds say (a pre-existing limitation #306 addresses); a test shows a correction superseding a versioned absorbed row, with either entity, regenerates with the registry unchanged. A second test appends new prints of a folded series under both entities with the registry unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Answers the independent review of 9c9313b. - The rule that lets a row rejoin a retired identity through names held in another entity slice now applies only to folds marked "undone": true. At 9c9313b it applied on every run, so an ordinary append of a new spelling could revive an unrelated retired identity without the ceremony (the review's append-only replay; now a regression test that fails on the old generator and passes here). - Folds are undone by the marker, never by deletion: removing an entry that git HEAD still holds is refused, because the entry is the record the builder needs to hand absorbed spellings back. - Documented limits: a curated alias no current row spells stays on the survivor after an undo (regression added), and the seed ratchet compares with the committed catalog header, which is trusted like every generated artifact. - Marking all seven committed folds undone still reproduces the pre-fold catalog exactly apart from the seed and registry digests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Answers the independent review of d3d23ff. - Each fold now declares absorbed_names, the absorbed row's concept and aliases, checked for equality against that row while it is committed. Folding matches only those spellings; at d3d23ff the matcher used every survivor alias, so a new absorbed-entity row spelled by a survivor-only alias was silently captured (regression added). Replaying the fold from the pre-fold state with the new seed reproduces the committed catalog and registry byte for byte; an incomplete absorbed_names is refused. - Undo moves exactly the declared names back, so curated aliases no row spells now round-trip too (the regression asserts the exact pre-fold catalog). - The seed comment and the missing-seed error say to mark a fold undone, not to remove it; the docstring sentence that lost words is whole again; the round-4 regression retires its lineage by an appended superseding correction instead of rewriting the journal. - Regenerated with the ceremony for the new seed digest; the registry is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Answers the minors of the approving review of 38716ee. - At fold time, an absorbed name already held by a row in the survivor's slice is refused: shared ownership made the undo inexact. - While a fold stands, the survivor must hold every absorbed name alone; a hand edit that drops one from the survivor or gives it to another series is refused instead of routing folded rows there. - The docstring's field list names absorbed_names and the undone marker, and the property test's description says the fold is marked undone. The committed catalog, a fresh fold from d7e45bc and a full marked undo all reproduce as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
to ThesisInstitute/thesis
that referenced
this pull request
Oct 12, 2026
…alog #344's seed now declares each fold's absorbed names, which changes the catalog's entity_folds_sha256 and nothing else. The fixture is its catalog at 0e1dc63b byte for byte. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
October 12, 2026 19:37
Contributor
Author
|
Merging at 0e1dc63 under Max's ruling d353 (2026-09-27: economy/aggregate survives, all seven entity-drift pairs, generator fold).
|
MaxGhenis
added a commit
that referenced
this pull request
Oct 12, 2026
…period-invariant Conflicts: build_catalog keeps both plan keys (entity_folds_applied from #344, strips from this branch); test_committed_catalog_is_current_and_valid keeps the reviewed-strip audit in place of #344's one-time re-pin of the exact spelling list. The committed catalog now declares entity_folds_sha256, so _committed_build, the ABS CPI regression and the next-period test pass bsc.ENTITY_FOLDS, and the independent replay resolves a row an active fold absorbs (fold geography and absorbed entity, concept among the declared absorbed_names, read from the seed) at the survivor entity. The folds change no strip: the reviewed fixture is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 16, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements Max's ruling d353 (2026-09-27): seven series whose hand-recorded May 2026 rows carry a bespoke entity, while every resolver print carries
economy/aggregate, fold into theireconomy/aggregatelineage. Companion PRs: ThesisInstitute/thesis#342 (merged: stages the fold seed in the resolver's catalog regeneration, accepts the new catalog key) and ThesisInstitute/thesis#346 (re-stamps three docket pins and adds their BLS API templates; merges after this PR and the next resolver run).The defect
Catalog identity is (concept, geography, entity). Alias inheritance never crosses an entity slice, and the curated-merge recipe restores the split on regeneration (reproduced 2026-09-22). So seven series held two observed lineages each (the "entity-drift families" in
docs/catalog-curation-backlog.md). In Thesis, a docket entry that declares a source binding must find its source id in exactly one candidate lineage, which held back BLS API templates for the unemployment rate and CPI headline and core.The fix
scripts/build_series_catalog.pyreads a curated seed,ledger/seeds/entity_folds.json(chronicle_entity_folds_v1). Each fold names a concept, geography, absorbed entity, survivor entity,absorbed_names(the absorbed row's concept and aliases) and a note.--remint-note; the survivor keeps its UUID. The catalog commits to the seed asentity_folds_sha256(absent without a seed; generator version stays 3).--allow-remint --remint-note. Deleting the seed under a catalog that declares it is refused."undone": true. The absorbed identity revives with its original UUID, spellings it had absorbed earlier rejoin it, and exactly its declared names move back off the survivor. Deleting a fold entry is refused while git HEAD holds it.absorbed_namesmust equal the absorbed row's names when the fold is made; a name already held in the survivor's slice is refused at fold time; while a fold stands the survivor must hold every absorbed name alone; a fold must name an identity the registry has bound and a survivor with a committed observed row; a folded row's own entity is still validated. A fold matching no current row is inert.Regenerated artifacts
retired, append-only)Survivors keep their UUIDs: db2f3857, 70ca2ecf, e5e402d5, 1d271205, 8c999902, 9668ecdb, dbfd5050. Retired: 8dbbd54f, 3e796803, d85c3c7f, e8e6e43e, d0212a1e, 978252a9, d5634fc4. Replaying the fold from d7e45bc's catalog and registry with the committed seed reproduces both files byte for byte. Marking all seven folds undone reproduces the pre-fold catalog exactly, apart from the seed and registry digests.
Invariants (stated and tested)
observation_countsums tocurrent_assertion_rowsbefore and after any fold (Hypothesis property over any split of one series across two entities).Also in this PR
test_committed_catalog_is_current_and_valid's exact stripped-spelling list was stale since 598f394 (the branch head's required "Arch checks" has been red). This PR re-pins it to the current catalog; the fold changes no strip. Audit period strips by reviewed template, not an exact spelling list #309 proposes replacing the list with a reviewed audit.pyproject.toml/uv.lockhunks as Audit period strips by reviewed template, not an exact spelling list #309). The runtime set the trusted append gate installs (--no-dev) is unchanged.ledger/**with the generator andpyproject.toml/uv.lockwould become a mixed proposal for the append gate and would have to be split.Review
Independent GPT-6.1 Sol reviews, rounds 3 to 7 (round 1 and 2 reviewed the proposal). Rounds 3 to 5 requested changes, each answered in a commit: legacy-correction claim narrowed, retarget ceremony, exact undo, entity validation, undo scoped to the explicit marker, absorbed names declared. Round 6 approved at 38716ee with minors; 0e1dc63 answers them and the round-7 delta review approved it. Reports and responses:
~/chief-of-staff/state/chronicle-lineage/reviews/on Max's machine.Locally at 0e1dc63: 198 tests pass, ruff 0.14.10 clean,
--checkgreen, doctests pass.🤖 Generated with Claude Code