Repository navigation
Await Arch checks and carry provable catalog curation in ledger appends - #377
Merged
Merged
Conversation
Branch protection on the Chronicle ledger branch requires Append gate, Trusted base append gate and Arch checks, but the resolver's admin token merged on the first two alone. 17 of the 28 resolver appends from 2026-07-10 to 2026-10-19 merged with Arch checks red, and 8 of them turned a green branch red, holding every other pull request into it until a curation PR landed (about 30 of the last 72 days). Since August every such failure came from two curation tests: a concept's first period strip in a new identifier shape, and the identity anchor moving. Neither can be curated before the rows exist, so refusing the append alone would deadlock windowed first prints. The proposal now carries the curation the resolver can prove (catalog_curation): a first strip that is derived alone and sits in the dataPointId segment right after the row's registered series, and an identity-anchor move made only of fresh-UUID mints and same-UUID placeholder enrichments, recorded for Chronicle to re-derive (chronicle#372). The curated state is dry-run with the base's own audit before anything visible happens; curation the audit rejects is dropped. Replaying chronicle#361 and #369 reproduces the human curation in #363 and #371 exactly, with nothing left red. The resolver also awaits Arch checks. ARCH_CHECKS_POLICY decides what a red verdict does: "land" (default, the old behaviour) merges and files the curation work as a Chronicle issue; "refuse" makes Arch checks a required gate. That choice changes when rows needing uncurated work land, so it is queued for Max. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
Review round 1 (in-session Opus), each finding checked before fixing: - P2: Chronicle mints new identities under random UUIDs, so curation computed in its own generator run never matched the catalog _prepare_release_files shipped, and every append that minted lost its curation. catalog_curation now stages the exact catalog and registry the proposal ships and never regenerates. The fake Chronicle module mints uuid4 like the real one; a new end-to-end test through propose_ledger_append checks the shipped fixtures describe the shipped catalog for a fresh mint. - P3: Chronicle reviews a (concept, field, shape) as one decision, so recording one spelling could clear an unproven sibling. A shape is now recorded only when all its first strips are provable, and the dry run requires curation to remove only its own reports (none new, none still standing on a recorded strip by spelling and concept). - P3: a failed status read while waiting on the advisory Arch checks no longer closes a proposal whose required gates passed. - P3: a missing Arch verdict is filed when the dry run predicts red. - P3: catalog_curation never raises (any failure means no curation and a note); a non-regular fixture entry no longer aborts the tree fetch; a repeated catalog row is refused; the curation issue is found across pages; the existing generator runs also drop credentials from their environment (hygiene, not isolation: same user). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thesis#337 gives the two existing generator runs an allowlisted environment; changing the same calls here would only collide with it. The new curation probe keeps its own denylist until it can take that allowlist. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2 (subfleet --task review --tier hard, served by Opus 5.5 with the Codex lanes held): APPROVE WITH NITS, no merge past a required gate. - P2-1 (append gates and tests/fixtures): checked, no change needed. The base's own check_thesis_facts_append.py (7adcc72f, receipt 0.6.2) accepts the replayed chronicle#369 proposal carrying both curated fixtures: "thesis-facts append check OK: 250 rows ... +5 appended vs base, release 27". receipt refuses only data mixed with gate code. - P2-2: a stateful Hypothesis test over sequences of listings and failed reads (multi-page listings, required re-runs, grace and budget expiry): every return rests on a passing latest read whose unbroken run of passing reads holds a confirmed pass. Deleting either confirmation reset fails it or the new deterministic re-run example. - P3-6: a required gate read as anything but passed now ends the current run of passing reads (a fresh confirmation and grace are needed); once a run holds a confirmed pass, a failed or unconfirmed read during the advisory wait merges as the code before advisory gates would have. - P3-5: the dry run judges strips and anchor apart and drops only the rejected part (re-probing what is left); reports belong to a recorded strip by field and shape, and a report naming no shape counts as its. - P3-4: the strip proof requires the dataPointId segment after the registered series to be the stripped spelling for every field. - P3-2/P3-3: identity_anchor_move refuses one identity under two UUIDs and a mint of a UUID the base registry holds; the probe also runs Chronicle's continuity check, so the dry run predicts what CI checks. - P3-7: report_red_ledger_base reads Arch checks on the ledger branch head before each proposal and files a red head, so a red that merged without a verdict is caught on the next run (never holds the append). - P3-10: Actions OIDC/runtime credentials and the GITHUB_ENV/PATH/OUTPUT files join the probe's denylist (thesis#337's allowlist still to come). - P3-11/P3-12: anchor mutations parametrized (each must be exercised), reachable mint-collision and registry-revive cases, a residual that names a moved anchor once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2, P3-9: Arch checks runs once for the proposal branch's push and once for its pull request. The push run can finish green before the pull request run is even listed, and with chronicle#372 only the pull request run checks the anchor move against the base for a new branch. So when Arch checks is a required gate, await_append_gates now holds its pass until two runs have completed (min_runs). The gate fake carries both runs, as a real proposal does, and the stateful gate-wait property models the rule under "refuse". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 3 (hard tier, Opus 5.5): APPROVE WITH NITS. - P3-A: chronicle#372 leaves a new branch's anchor continuity to the pull request run, so under "land" a green push run alone could end the advisory wait and the merge would go ahead with continuity unchecked. Arch checks now needs both runs for a verdict under either policy. - P2-A: the stateful gate-wait property almost never reached a return (about 0.5% of listings passed every required gate). Its listings now pass about half the time, Arch checks takes the shapes the twin rule must tell apart, and 22% of examples end in a merge the oracle checks. Deterministic tests pin each mutant the review named: a pass confirmed across a broken run, a skipped twin counted as a run, "land" not merging on an earlier confirmation (P3-C), and the grace not restarting after a required re-run. All four mutants are killed. - P3-D: report_red_ledger_base bounds its read. - Nits: may_merge is confirmed_once (one flag, three return paths); the unreachable mint-reuse branch is gone. - P3-E: the gate replay was re-run at these heads with the candidate's changed paths and the gate script's identity recorded (~/reviews/thesis-arch-gate-2026-10/gate-replay-369.out): check OK. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 4 (hard tier, Opus 5.5): APPROVE WITH NITS, no P1/P2. - P3-1: the P3-C test returned on its confirmed read before serving any unconfirmed pass. It now serves a confirmed pass, then passing reads with a new attempt id each time, and ends on a failed read or on the deadline; a may_merge that needs the latest read confirmed fails both. - P3-2: the stateful gate-wait property runs with production's min_runs under both policies, and a following test requires a share of its examples to end in merges under each policy. - P3-3: test_resolve_pending.py passes at this head (239 with the curation tests). - Nits: a gate held by min_runs is described as "N of M runs completed"; the torn-read advisory verdict is commented; a dead duplicate check in identity_anchor_move is gone. Both incident replays still match #363/#371 with nothing left red, and the base gate accepts the #369 replay (~/reviews/thesis-arch-gate-2026-10/gate-replay-369.out). Co-Authored-By: Claude Opus 5.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.
Review rounds 1 to 5 are done. Round 5, a confirmation at these heads, is APPROVE WITH NITS with no P1 or P2. Companion PR: PolicyEngine/chronicle#372, which should land first.
CI note:
main's site test (forecast-catalog.test.ts, observation IDs reused by correction rows) was fixed by #378 (merged 670b069), sobuild-and-testcan go green here.The gap
Branch protection on Chronicle's
codex/thesis-ledger-factsrequires three checks: Append gate, Trusted base append gate and Arch checks.REQUIRED_APPEND_GATESnamed only the first two. The resolver's token is an admin andenforce_adminsis off, soawait_append_gatespassing was the whole merge condition.I checked all 28 resolver append PRs, 2026-07-10 to 10-19, against the check runs on their heads, bases and merge commits:
tests/test_build_series_catalog.py:test_identity_uuid_map_matches_reviewed_anchor, which moves on every first-observation mint or placeholder enrichment.The trade-off
(a) Await Arch checks and refuse on red. On its own, this deadlocks.
FIRST-PRINT WINDOW MISSED (refusing): USAspending snapshots, A-19, IRS 1304, SBA).(b) Keep landing and alert. This keeps data on time, but still merges past a required check and leaves the branch red until someone curates.
(c) This PR: proposals carry the curation the resolver can prove, and Arch checks is awaited.
catalog_curationstages the base with the exact catalog and registry the proposal ships (from_prepare_release_files) and probes the base's own catalog code. It never regenerates: Chronicle mints new identities under random UUIDs, so a second generator run would describe a different catalog.derived;parse_ref_period).identity_anchor_problems, chronicle#372).What a red Arch checks does now:
ARCH_CHECKS_POLICY, for Max to ruleThis PR changes nothing about what lands or when. After this PR, Arch checks goes red only for curation the resolver cannot prove (an
overlapfirst strip, a new suspect segment, an unregistered row), for an already-red base, or for a genuine test failure.land(default, current behaviour): merge on the two append gates; printARCH CHECKS FAILED AT MERGE; open or comment on a Chronicle issue titled "Ledger branch red after a resolver append", listing what the dry run expects a curator to do. The issue is also filed when Arch checks has not reported within the 20-minute grace but the dry run predicts red.refuse(option a for that residue): Arch checks becomes a required gate. A red verdict closes the proposal and nothing appends. Rows that need curation wait, and a windowed one can miss its window.This choice moves data timing, so it is queued as a decision for Max rather than decided here. Flipping it is a one-constant change, and the tests already cover both settings.
Evidence: replaying the incidents through the real code
catalog_curationwas run on the real Chronicle bases, with chronicle#372 overlaid, the real appended rows and the real Thesis registration contracts:fy202656bb47bc…→b06bf665…, 5 enrichmentsfy2026b06bf665…→d5b88530…, 5 enrichmentsSo both outages this week would have merged green, with the curation in the same commit.
Invariants (Hypothesis plus examples)
await_append_gatesreturns only when every required gate's state ispassed. It raises a rejection exactly when a required gate failed, and the advisory verdict it reports is never upgraded. Underrefuse, a red or missing Arch checks never merges.propose_ledger_append: the fixtures in the proposal commit describe exactly the catalog that commit ships, even for an append that mints under a random UUID (the round-1 P2).GH_TOKENor the producer signing key.Verification
tests/test_ledger_catalog_curation.py, 38 passed; with the gate, proposal and policy subset oftests/test_resolve_pending.py, 116 passed. The full suite runs in CI.Review round 1 (in-session Opus)
claimedmatch; advisory read failures; issue filing on a missing verdict;catalog_curationraising; issue pagination; repeated catalog rows; a non-regular fixture entry aborting the fetch.ruff: clean on the changed lines.Review round 2 (hard tier, served by Opus 5.5 while the Codex lanes were held): APPROVE WITH NITS
tests/fixtures/**: checked, no change needed. The base's owncheck_thesis_facts_append.py(7adcc72f, receipt 0.6.2) accepts a commit equal to the real chronicle#369 proposal plus both curated fixtures:thesis-facts append check OK: 250 rows, immutable prefix 128, +5 appended vs base, release 27. receipt refuses only data mixed with gate code.GITHUB_ENV/GITHUB_PATH/GITHUB_OUTPUTfiles join the probe's denylist. thesis#337's allowlist is still the real fix.tests/test_resolve_pending.pyplustests/test_ledger_catalog_curation.py, 233 passed.Review round 3 (hard tier, Opus 5.5): APPROVE WITH NITS
report_red_ledger_basenow has a deadline on its read.may_mergeis nowconfirmed_once, and all three return paths go through it. The unreachable mint-reuse branch is removed.Review rounds 4 and 5 (hard tier, Opus 5.5): APPROVE WITH NITS
may_mergethat needs the latest read confirmed. The stateful property uses production'smin_runs, and a follow-on test requires it to reach merges under both policies. A gate held bymin_runsis described as "N of M runs completed".tests/test_resolve_pending.pyplustests/test_ledger_catalog_curation.pypass at 8195ec8 (239; output in~/reviews/thesis-arch-gate-2026-10/pytest-8195ec86.txt).--dist load;servedbound could be tighter;A third live case
chronicle#373 (2026-10-19 19:49Z) merged past a red Arch checks: statcan CPI took its first
2026_09strip in a new shape. Replaying it through this PR'scatalog_curation(registration found, strip derived alone) records exactly that strip, with an empty residual. With this PR it would have merged green. PolicyEngine/chronicle#374 curates it by hand.🤖 Generated with Claude Code