Epoch prep: accept chronicle-era fact domains and schema ids; emit unchanged (#143, mechanism 1) - #228
Open
MaxGhenis wants to merge 10 commits into
Open
Epoch prep: accept chronicle-era fact domains and schema ids; emit unchanged (#143, mechanism 1)#228MaxGhenis wants to merge 10 commits into
MaxGhenis wants to merge 10 commits into
Conversation
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Summary
Mechanism 1, step 1 of #143 (Max's migration spec, 2026-08-20): dual-domain acceptance, emit unchanged. Fact identity migrates by epoch, never in place. This PR makes every Chronicle reader and validator accept both the ledger-era identifiers and their chronicle-era successors, while everything Chronicle emits stays ledger-named until a later, consumer-gated cutover flips one default.
chronicle/epoch.py— the single registry of frozen ledger identifiers and their successors: 15 hash domains (ledger.aggregate_fact.v2→chronicle.aggregate_fact.v3, …,ledger.fact.v1→chronicle.fact.v2,ledger.source_cell.v1→chronicle.source_cell.v2, …) and the schema ids (ledger.bundle.v1→chronicle.bundle.v2,ledger.consumer_fact.v1→chronicle.consumer_fact.v2,ledger.relational.v1→chronicle.relational.v2,ledger.source_package.v1→chronicle.source_package.v2,policyengine_ledger.consumer_artifact.v2→policyengine_chronicle.consumer_artifact.v3,policyengine_ledger.approved_agents.v1→policyengine_chronicle.approved_agents.v2, …). Canonical payloads and digest suffixes are identical across epochs; only the domain or schema string changes.EMIT_EPOCH = Epoch.LEDGERis the one default a future cutover changes.consumer_contract.py,core.py), artifact and schema pins (policyengine_chronicle/consumer.py,schema.py), bundle ingestion (bundle.py), the relational load path (database.py), source-package readers and lineage (source_package.py,sources/cells.py,sources/rows.py,sources/offline_fetch.py), suite build (suite.py), and governance validation. Key verification recomputes under the epoch declared by the key's own prefix; a key or schema id outside both accepted forms is rejected with an error naming both.sources/admin_packages.pyand the Statbel builder, are pinned to the registry's ledger default). Chronicle-era output exists only behind an explicit epoch argument, to exercise acceptance before the gated flip.Consumer side: PolicyEngine/microcosm#849 accepts the same pairs (including
policyengine_ledger.consumer_artifact.v2today and.v3after the flip). The emit flip is a separate PR gated on microcosm and the Thesis-side validators (brier append gate,pin_ledger.py/verify_custody.py) accepting both epochs.Chronicle Governance
ledger-contract-maintainer(identity, provenance, and consumer contracts). Itsallowed_pathspredate this work and cover onlychronicle/core.py,chronicle/consumer_contract.py,policyengine_chronicle/**and two test files; the readers listed above andchronicle/epoch.pyare outside that list and are disclosed here rather than the manifest being widened silently (same gap flagged on Register raw microdata releases as source artifacts: licence/access fields, hash-only registration, first UK registrations (#221) #227; follow-up to extend the globs).783 passed, 1 skipped;ruff checkclean; changed Python files formatted; wheel build and clean-venv import smoke passed; a GitNexus impact audit drove additional validator and lineage fixes. Goldens byte-identical (asserted).ledger-contract: PASS — identity changes preserve provenance; digests unchanged; no Microcosm responsibility moves into Chronicle.ledger-boundary: PASS — no reconciliation, aging, imputation, activation, or solver construction; no microdata content.Tests
New and extended:
test_chronicle_core.py(+304),test_chronicle_consumer_contract.py,test_chronicle_consumer.py,test_policyengine_chronicle_schema.py,test_chronicle_bundle.py,test_chronicle_database.py,test_chronicle_suite.py,test_chronicle_source_package.py,test_chronicle_source_cells.py,test_chronicle_offline_fetch.py,test_chronicle_artifacts.py,test_belgium_targets.py,test_chronicle_governance.py— chronicle-era rows and artifacts accepted end to end, mixed-epoch artifacts accepted, unknown domains rejected naming both forms, and the property that a chronicle-era key hashes the same canonical payload as its ledger-era key.Authored by a Sol lane (no network); pushed and opened from the dispatching session.
🤖 Generated with Claude Code