fix: converge raw components holding byte-governed append fragments - #4019
Merged
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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
A Codex rollout that grows in place accumulates both
fullsnapshots andappendfragments under one logical source. Append fragments are deliberatelynever parsed for identity, and the parser-census receipt written for them was
failed— a status that satisfies neither branch of the census-complete gate.Every raw-materialization pass therefore re-selected the fragment, rewrote the
same receipt, and reported "paused until the persisted parser census completes"
forever, which stopped raw-replay planning for every
fullsnapshot sharingthe authority component. This receipts a byte-governed fragment as the complete
observation it is, so those components converge.
Problem
polylogue-39kcs(bucket B7 of the dyica classification — the only genuine gapin the 111-failure population): codex session
019f49d8-0185-7c43-8793-db6e57db13e1is acquired, parsed, and censused butabsent from
index.db. It is the only codex logical source with a parsed rawmissing from the index out of 1448 checked.
The
parse_errorthe bead quotes —RuntimeError: membership replay cannot replace an unconvertible byte head— is not the live cause. That wording nolonger exists in the codebase (PR #3646 replaced it with the typed, retry-eligible
MembershipReplayConflictError); it is a legacy string frozen on one raw row.Two measurements ruled the membership-replay hypothesis out entirely:
classify_historical_full_revision_streamsover the 22 real fullblobs resolves a clean, unambiguous byte-prefix chain — every revision
byte_proven, headdd0cbb34b9(90,822,451 bytes, the current on-disk file).Nothing about this cohort is "unconvertible" today.
backfill_historical_revision_evidencematerializes the session with 29,280messages, even with the live archive's 21 stale
raw_session_membershipsrows (
decision IS NULL,revision_authority='quarantined') staged first.The actual blocker is upstream of replay, in the census/planning handshake:
_persist_revision_censusroutes everysource_index < 0raw straight to thebyte-authority membership receipt (
BYTE_AUTHORITY_CENSUS_DETAIL) withoutparsing it — correct, appends are governed by byte revision authority.
record_current_parser_source_censusthen computedcomplete=Falsefor thatraw (no parsed sessions, no membership rows, not a typed non-session artifact)
and wrote
status='failed'carrying the byte-authority detail.uncensused_historical_revision_raw_idsaccepts onlycomplete+detail LIKE 'parser-observed:%', orfailedat the currentresource-blocked fingerprint. The fragment's receipt matches neither, so it is
reported uncensused on every pass, forever.
Reproduced against the real shape: with the component rebuilt from the live
blobs, six consecutive whale-escalation passes each returned
success=Falsewith
Raw replay planning paused until the persisted parser census completes for 22 relevant raw(s)and zero progress. The live source has 767 such fragments.This is the "converged or explicitly blocked" invariant failing in the silent
direction: the pass claims unfinished census work for a raw the census can never
say anything more about, instead of typing it as the authority debt it is.
Solution
polylogue/storage/sqlite/archive_tiers/revision_governance.py—record_current_parser_source_censusnow treats an append-position raw(
source_index < 0) whose membership census is the byte-authority governancereceipt as having an authoritative empty identity set, exactly like the existing
typed_non_sessionbranch it sits beside. The receipt becomescomplete/parser-observed: append fragment governed by byte revision authority.The fragment's
revision_authorityis untouched — it staysquarantined, stillcounted as durable authority debt. Only the census receipt changes, from "we
have not finished looking at this" to "we looked, and byte governance owns it".
The
source_index < 0guard keeps the branch off full snapshots even if onesomehow carried the marker, matching how
storage/repair.pyalready reads thesame detail.
Alternative rejected: special-casing the byte-authority detail inside
uncensused_historical_revision_raw_idsinstead. That leaves the durablereceipt lying about its own status and makes every other consumer of
raw_authority_parser_censusdisagree with the gate.Nothing in revision-authority refusal semantics changed: the byte-chain
classifier, the polylogue-52l2 retired-sibling guard, the polylogue-eqnv
source-path guard, and both
MembershipReplayConflictErrorrefusals areuntouched.
Two existing tests asserted the old receipt shape and were updated with the
reason recorded inline — they were encoding the livelock, not protecting an
invariant.
test_raw_materialization_reports_uncensused_append_fragments_as_pending_debtnow asserts the census reaches quiescence while the fragment is still reported
as
append authority quarantinedebt; its three authority-bucket transitions(pending → quarantined → fragment) are unchanged and still pass.
Verification
Red first.
test_raw_materialization_converges_component_with_byte_governed_append_fragmentdrives the real
repair_raw_materializationentry point and failed on theparent commit at the census gate:
Green after the fix, and the whole affected surface with it:
That set is every test file in the repo that references
raw_authority_parser_censusorparser-observed.Against the real 019f49d8 shape, in a scratch archive built from the live blobs
(21 distinct full revisions + append fragments bound as the live rows are bound,
live blob store read-only, live archive never written):
success=False,index sessions: (0,)attempt 0: success=True repaired=1,index sessions: (1,),('codex-session:019f49d8-0185-7c43-8793-db6e57db13e1', 29280)At the daemon's ordinary 64 MiB envelope the component is still explicitly
resource-blocked (
plan_deferred_count 1.0, "retry through bounded stream-safewhale pass"). That is the correct typed blocked state and is what routes it to
the whale pass — the invariant now holds at both envelopes.
Gate substitution (deliberate, per lane policy). The final plain
devtools verifywas skipped. Policy is to rundevtools whyfirst and skipthe full run when it predicts a bootstrap; it did:
Re-provisioning this lane's venv changed the testmon environment digest, so no
graph exists for it and a plain verify becomes a full-corpus bootstrap (~45 min
measured median) rather than a warm affected-selection run. The focused
devtools testselections above plusdevtools verify --quickare this PR'sgate in its place. The coordinator records the merge receipt centrally at head.
Also not run:
test_codex_804_live_proof.py::test_sanitized_codex_804_revision_recovery_proof(900s timeout,
storage_scale). It is provably unaffected —tests/infra/whale_fixtures.pynever setssource_indexorrevision_kind, soevery raw it acquires is
source_index=0, and the new branch is gated onsource_index < 0. Its three fast red-mutation guards do pass.Bead disposition matrix
polylogue-39kcs67ab67c52); red-first production-route regression test (9ccfaa893); the real 019f49d8 cohort converges to 29,280 messages where it previously livelocked.Ref polylogue-dyica— AC#2 ("parser or lifecycle defects have production-routeregression tests that fail when the original failure is reintroduced") is
satisfied for this defect by the new test. The rest of dyica (the backup-gated
live reclassification pass for the 110 benign rows, AC#1/#4) is untouched and
stays open.