Thesis-facts append gate: immutable prefix, reviewed proposals, assertion versioning#86
Merged
Conversation
The observation ledger becomes append-only with enforcement, not convention (ledger architecture review 2026-07-10, findings 3 and 5): - ledger/immutable_prefix.json freezes the 128 rows present at contract-enforcement start (per-line SHA-256 + cumulative digest, including the 13 rows whose in-place rewrites the review's history analysis surfaced). CI fails if any frozen byte changes. - scripts/check_thesis_facts_append.py gates every change: append-only diff against the PR base, per-row invariants, post-prefix binding requirements (assertionVersion, retrievedAt, sourceVintage, ledgerRepoSha, responseArchive; targetContentHash and sourceBindingProjection together or not at all), and explicit supersede semantics — a duplicate identity is legal only as a correction naming the version it replaces, with pre-versioning rows addressable by their recomputable content hash. - tests/test_policyengine_ledger.py returns to CI rewritten as invariants that hold at any row count, replacing the stale closed 49-ID inventory that had been excluded since it went stale. - arch.core vocabulary learns the shapes the ledger actually contains (week_ending/quarter periods, level aggregation, economy entity) — the excluded test had been hiding that the branch's own validator rejected the resolver's rows. - .github/workflows/thesis-facts-append.yml runs the gate on every pull request into this branch; the Thesis resolver now appends via reviewed proposals that merge only after this gate passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis
added a commit
to MaxGhenis/brier
that referenced
this pull request
Jul 10, 2026
The resolver no longer PUTs the accepted thesis-facts branch directly (review finding 5). It branches a proposal from the exact state the rows were built against, opens a pull request, waits for the ledger-side append gate (immutable prefix, append-only diff, per-row bindings, supersede semantics — PolicyEngine/ledger#86), merges only on success, and verifies the merged branch extends what it proposed. A failed or absent gate leaves the proposal open for humans and fails the run loudly. Branch protection on codex/thesis-ledger-facts now requires the gate, so the reviewed path is the only non-admin path. Co-Authored-By: Claude Fable 5 <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.
Step 4 of the ledger-review hardening (
~/thesis-brief/ledger-architecture-review-sol-2026-07-10.md, findings 3 and 5): the thesis-facts observation ledger becomes append-only with enforcement.What this adds
ledger/immutable_prefix.json— freezes the 128 rows present at contract-enforcement start (per-line SHA-256 + cumulative digest). The 13 rows whose in-place rewrites the review's git-history analysis surfaced (8 in6c92094, 5 more in816e9a3) are recorded asknownInPlaceRewriteswith their commit evidence — flagged, not re-rewritten.scripts/check_thesis_facts_append.py— deterministic review for every change: immutable prefix intact, append-only diff vs the PR base, per-row invariants, post-prefix binding requirements (assertionVersion,retrievedAt,sourceVintage,ledgerRepoSha,responseArchive;targetContentHash+sourceBindingProjectiontogether or not at all, digest and unit cross-checked), and explicit supersede semantics (finding 3: corrections append a row naming the version they replace; pre-versioning rows are addressable by their recomputable content hash).tests/test_policyengine_ledger.pyre-enters CI, rewritten as immutable-prefix invariants that hold at any row count (the old closed 49-ID inventory went stale at the first append and had been excluded from CI — finding 5).arch/core.pyvocabulary learns the shapes the ledger actually contains (week_ending/quarterperiods,levelaggregation,economyentity). The excluded test had been hiding that this branch's own validator rejected the resolver's rows..github/workflows/thesis-facts-append.ymlruns the gate on every PR intocodex/thesis-ledger-facts. The Thesis resolver (MaxGhenis/brier) switches from direct Contents-API writes to append proposals that merge only after this gate passes.Verification
python3 scripts/check_thesis_facts_append.py→ OK (128 rows, prefix 128)uv run pytest tests/test_policyengine_ledger.py -q→ 9 passed (includes adversarial cases: rewritten prefix line detected, duplicate identity without supersedes rejected, stale supersedes target rejected, explicit correction accepted)uv run ruff checkon all touched files → clean🤖 Generated with Claude Code