test(storage): prove raw-authority fair scheduling and CAS-typed retry (hjpx AC3/AC4) - #3345
Conversation
…y (hjpx AC3/AC4) Problem: polylogue-hjpx AC3 requires bounded raw-materialization scheduling that never starves large valid work behind cheap components, and AC4 requires transient failures to remain retryable under a stable plan id while CAS conflicts/incomparable authority stay typed, durable, and non-mutating. hjpx.1 (PR #2961) landed the fair-rotation and plan/outcome-conservation machinery, and later PRs (#3029/#3031/#3034/#3043) hardened it further, but no regression test proved (a) component ordering is size-agnostic rather than cheap-first, (b) a retryable plan keeps its plan_id across a fail-then-succeed cycle, or (c) a genuine CAS-conflict RuntimeError from revision_application.py surfaces through the reconciler as a typed/durable/non-mutating outcome rather than silently vanishing or partially applying. What changed: added three regression tests to tests/unit/storage/test_repair.py: - test_raw_materialization_ordering_is_size_agnostic_and_does_not_starve_large_work: constructs one large-but-executable component (oldest by acquisition) plus five small ones; proves fair age-based ordering selects the large component first, and a cheap-first mutation of _raw_materialization_ordered_components recreates the starvation AC3 names. - test_raw_materialization_transient_failure_retries_with_same_plan_id_then_succeeds: proves a retryable outcome keeps its plan_id across a fail-then-succeed retry and that no parse residue exists before the retry lands. - test_raw_materialization_cas_conflict_outcome_is_typed_durable_and_non_mutating: injects the exact "CAS rejected a conflicting accepted head" message and proves the resulting outcome is typed (retryable), durably recorded in raw_authority_census_plans (source.db), and leaves no parse/application/head residue in source.db or index.db. All three tests were validated anti-vacuously: temporarily mutating the production code under test (cheap-first ordering; a mutated plan_id in the RETRYABLE outcome branch) made the corresponding test fail for the expected reason, then the mutation was reverted (clean `git diff` on production code). No production code gap was found for AC3/AC4 -- the investigation confirms existing behavior in polylogue/storage/repair.py (_raw_materialization_ordered_components) and the generic exception handler around backfill_historical_revision_evidence already satisfy both invariants. AC5/AC6/AC7 status is recorded in the bead's notes, not re-litigated here. Verification: - devtools test tests/unit/storage/test_repair.py tests/unit/sources/test_revision_backfill.py -> 109 passed - devtools test tests/unit/sources/test_revision_backfill.py -> 44 passed - devtools test -k raw_materialization -> 118 passed - devtools test -k raw_authority -> 83 passed - devtools verify --quick -> 17/17 steps green, exit 0 - Not run: devtools verify --seed-testmon/full (per repo convention a focused test-only change needs the narrow gate, not a full-suite seed; a first attempt was aborted on the coordinator's direction since this change doesn't warrant it). Ref polylogue-hjpx Co-Authored-By: Claude <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📝 WalkthroughWalkthroughAdds unit coverage for raw materialization candidate ordering, transient retry handling, durable CAS-conflict outcomes, and non-mutating failure behavior. ChangesRaw materialization repair tests
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/unit/storage/test_repair.py`:
- Around line 2444-2446: Update the test stub raise_cas_conflict to record
selected_raw_ids instead of asserting inside the patched call, then assert the
recorded value equals [raw_id] after repair_raw_materialization returns.
Preserve the RuntimeError(cas_message) behavior so the production
exception-to-RETRYABLE path remains exercised.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b3f544a7-545d-4f07-8999-de652bdbc33d
📒 Files selected for processing (1)
tests/unit/storage/test_repair.py
| def raise_cas_conflict(*args: Any, selected_raw_ids: list[str] | None = None, **kwargs: Any) -> Any: | ||
| assert selected_raw_ids == [raw_id] | ||
| raise RuntimeError(cas_message) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm the per-component backfill_historical_revision_evidence call in repair_raw_materialization
# is wrapped in a broad except that stringifies exceptions into the outcome reason.
rg -n 'backfill_historical_revision_evidence\(' -B5 -A25 polylogue/storage/repair.pyRepository: Sinity/polylogue
Length of output: 1936
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map the test and implementation around the relevant scope without running repository code.
printf '--- test_repair outline matches ---\n'
fd -a 'test_repair.py' . | while read -r f; do
wc -l "$f"
ast-grep outline "$f" --match 'test_raw_materialization_transient_failure_retries_with_same_plan_id_then_succeeds' --view compact 2>/dev/null || true
done
printf '\n--- tests/unit/storage/test_repair.py lines 2360-2465 ---\n'
sed -n '2360,2465p' tests/unit/storage/test_repair.py | nl -ba -v2360
printf '\n--- polylogue/storage/repair.py lines 6460-6545 ---\n'
sed -n '6460,6545p' polylogue/storage/repair.py | nl -ba -v6460
printf '\n--- deterministic except shape probe from source ---\n'
python3 - <<'PY'
from pathlib import Path
p = Path('polylogue/storage/repair.py')
s = p.read_text()
start = s.index('for plan, raw_id in zip(executable_plans, executable_raw_ids, strict=True):')
end = s.index('return RawReplayPlanResults', start)
chunk = s[start:end]
print('contains bare try:', 'try:' in chunk)
print('except Exception or base Exception:', 'except Exception' in chunk or 'except BaseException' in chunk)
print('contains AttributeError specifically before second except:')
for i, idx in enumerate(chunk.find('except ') for _ in range(10)):
pass
# Locate except bodies after the critical try
except_lines = []
for m in __import__('re').finditer(r'except[^\n]*:(?P<body>(?:\n\s+.*)*)', chunk):
body = m.group('body').splitlines()
if body and body[0].strip():
first = body[0].strip()
if len(first) < 160 and first.startswith('outcome'):
except_lines.append((m.group().splitlines()[0].strip(), first))
print('outcome assignments in except bodies:')
for line, first in except_lines:
print(line)
print(first)
PYRepository: Sinity/polylogue
Length of output: 245
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- test_repair outline matches ---'
fd -a 'test_repair.py' . | while read -r f; do
wc -l "$f"
ast-grep outline "$f" --match 'test_raw_materialization_transient_failure_retries_with_same_plan_id_then_succeeds' --view compact 2>/dev/null || true
done
printf '%s\n' ''
printf '%s\n' '--- tests/unit/storage/test_repair.py lines 2360-2465 ---'
sed -n '2360,2465p' tests/unit/storage/test_repair.py | nl -ba -v2360
printf '%s\n' ''
printf '%s\n' '--- polylogue/storage/repair.py lines 6460-6545 ---'
sed -n '6460,6545p' polylogue/storage/repair.py | nl -ba -v6460
printf '%s\n' ''
printf '%s\n' '--- deterministic except shape probe from source ---'
python3 - <<'PY'
from pathlib import Path
import re
p = Path('polylogue/storage/repair.py')
s = p.read_text()
start = s.index('for plan, raw_id in zip(executable_plans, executable_raw_ids, strict=True):')
end = s.index('return RawReplayPlanResults', start)
chunk = s[start:end]
print('contains bare try:', 'try:' in chunk)
print('contains except Exception:', 'except Exception' in chunk)
print('contains except BaseException:', 'except BaseException' in chunk)
except_lines = []
for m in re.finditer(r'except[^\n]*:(?P<body>(?:\n\s+.*)*)', chunk):
body = m.group('body').splitlines()
if body and body[0].strip().startswith('outcome = RawReplayPlanOutcome'):
first = body[0].strip()
except_lines.append((m.group().splitlines()[0].strip(), first))
print('outcome assignments in except bodies:')
for line, first in except_lines:
print(line)
print(first)
PYRepository: Sinity/polylogue
Length of output: 348
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- tests/unit/storage/test_repair.py lines 2360-2465 ---'
sed -n '2360,2465p' tests/unit/storage/test_repair.py
printf '%s\n' ''
printf '%s\n' '--- polylogue/storage/repair.py lines 6460-6545 ---'
sed -n '6460,6545p' polylogue/storage/repair.py
printf '%s\n' ''
printf '%s\n' '--- deterministic except shape probe from source ---'
python3 - <<'PY'
from pathlib import Path
import re
p = Path('polylogue/storage/repair.py')
s = p.read_text()
start = s.index('for plan, raw_id in zip(executable_plans, executable_raw_ids, strict=True):')
end = s.index('return RawReplayPlanResults', start)
chunk = s[start:end]
print('contains bare try:', 'try:' in chunk)
print('contains except Exception:', 'except Exception' in chunk)
print('contains except BaseException:', 'except BaseException' in chunk)
except_lines = []
for m in re.finditer(r'except[^\n]*:(?P<body>(?:\n\s+.*)*)', chunk):
body = m.group('body').splitlines()
if body and body[0].strip().startswith('outcome = RawReplayPlanOutcome'):
first = body[0].strip()
except_lines.append((m.group().splitlines()[0].strip(), first))
print('outcome assignments in except bodies:')
for line, first in except_lines:
print(line)
print(first)
PYRepository: Sinity/polylogue
Length of output: 10222
Move the selected_raw_ids invariant outside the patched call
repair_raw_materialization wraps backfill_historical_revision_evidence() in except Exception and converts runtime failures to a RETRYABLE outcome with reason=f"component execution raised {type(exc).__name__}: {exc}". If assert selected_raw_ids == [raw_id] fails, the test surfaces as a failed retryable run instead of a clear assertion failure. Record the call arg and assert after repair_raw_materialization returns.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/unit/storage/test_repair.py` around lines 2444 - 2446, Update the test
stub raise_cas_conflict to record selected_raw_ids instead of asserting inside
the patched call, then assert the recorded value equals [raw_id] after
repair_raw_materialization returns. Preserve the RuntimeError(cas_message)
behavior so the production exception-to-RETRYABLE path remains exercised.
… dry-run success (#3485) ## Summary Lane C12: `polylogue-9dxn`, `polylogue-5q2u`, `polylogue-f57q` complete with focused production fixes + regression tests; `polylogue-hjpx` closed out via evidence, no new production code (see AC matrix — the P0 defect the bead was filed against is already fixed and regression-tested on `master`, predating this lane). ## Problem Measured baseline (coordinator-verified 2026-07-31): - `RAW_AUTHORITY_PARSER_FINGERPRINT` existed as a proper constant but `sources/revision_backfill.py` hardcoded the literal `"revision-membership-v1"` 8 times instead of importing it; `storage/repair.py`'s terminal-decision check for `decision = 'ambiguous'` had no fingerprint/version gate, so a classifier correction (`polylogue-bu1i`) could never heal already-persisted `ambiguous` verdicts. - `sources/revision_backfill.py:958` (`for logical_key in sorted(logical_keys):`) is lexicographic, lineage-blind — during a rebuild a child (resume/fork) replays before its parent roughly as often as not, triggering the expensive `#2467` deferred-tail normalization path. - `repair_raw_materialization`'s dry-run path unconditionally reported `success=False` even when the preview validly identified real work, breaking `devtools/scale_regression_probe.py`'s `raw_materialization_debt_detected` check. - `polylogue-hjpx`'s own 2026-07-31 reconciliation note claimed PR #3345 (AC3/AC4 regression tests) was unmerged and the P0 gap unresolved. ## Solution **polylogue-9dxn** (`polylogue/storage/raw_authority.py`, `polylogue/sources/revision_backfill.py`, `polylogue/storage/repair.py`): `revision_backfill.py` now imports `RAW_AUTHORITY_PARSER_FINGERPRINT` instead of repeating the literal. Added `SUPERSEDED_MEMBERSHIP_FINGERPRINTS` and bumped the constant to `revision-membership-v2` in the same commit as the gating (per design constraint — a bare bump alone would force a ~4h20m full reparse). The quiescence gate (`uncensused_historical_revision_raw_ids`) now accepts any *known* fingerprint (current or superseded), not only current, so a bump does not force a full archive re-census. `repair.py`'s terminal-ambiguous query (covering both `index_tier.raw_revision_applications` and `raw_session_memberships`) now `LEFT JOIN`s `raw_authority_parser_census` and excludes a raw from the terminal gate when its census fingerprint is superseded; absent census / current fingerprint stays conservative (terminal). **polylogue-5q2u** (`polylogue/sources/revision_backfill.py`): new `_lineage_aware_replay_order` computes roots-first, children-after-parent ordering using `ParsedSession.parent_session_provider_id` the census phase already parsed and spilled. Falls back to lexicographic order for any key whose parent is unresolvable (missing/external/cross-batch/cycle) — nothing is ever skipped. Scheduling-only: the pipeline-decode prefetcher now shares the same order as the writer's replay loop. **polylogue-f57q** (`polylogue/storage/repair.py`, `devtools/scale_regression_probe.py`): dry-run preview success now means "the requested phase completed validly", matching the convention the adjacent branches in the same function already use — `repaired_count` (always 0 for dry-run) remains the sole "nothing mutated" signal. Migrated 6 `test_repair.py` assertions and the scale-probe's own check to the corrected semantics. **polylogue-hjpx**: investigated per evidence-harness discipline (build the failing fixture first). `git merge-base --is-ancestor 64d203c e8a23cc` confirms PR #3345 (hjpx AC3/AC4 regression tests, state MERGED, mergedAt 2026-07-27) is already an ancestor of this lane's base commit (e8a23cc, 2026-07-31) — the bead's own reconciliation note was stale. Attempted to reproduce AC1's named defect (`repair_raw_materialization` reports a scanned/classified raw yielding `replayed_logical_sources=0` with the same candidate remaining forever): the existing regression test `test_raw_materialization_no_progress_component_terminalizes_instead_of_looping` (production fix: commit `6ea374222`, PR #3337) already covers exactly this shape and passes. No new failing fixture could be honestly constructed because the defect does not reproduce against current code — see AC matrix below for what's covered by pre-existing landed work vs. genuinely open. ## Verification ``` devtools test tests/unit/storage/test_raw_authority_ledger.py tests/unit/storage/test_archive_readiness.py tests/unit/storage/test_revision_replay.py tests/unit/storage/test_quarantined_accepted_raw_repair.py -> 99 passed devtools test tests/unit/sources/test_revision_backfill.py -> 59 passed, 1 pre-existing failure unrelated to this branch (test_parse_one_still_replays_real_claude_code_sessions_with_no_path_rule; reproduces identically on unmodified HEAD -- a content-classification gate assertion untouched by this diff) devtools test tests/unit/storage/test_incremental_rebuild_equivalence.py tests/benchmarks/test_graph_resolve_deferred_tail.py -> 3 passed devtools test tests/unit/storage/test_repair.py -> 65 passed devtools test tests/unit/devtools/test_scale_regression_probe.py -> 2 passed devtools test -k raw_materialization -> 115 passed, 2 pre-existing failures unrelated to this branch (test_maybe_run_raw_materialization_whale_pass_*; TypeError on an unrelated mock-signature mismatch in polylogue/config.py:2173, nothing to do with repair.py/dry_run/success) devtools test -k raw_authority -> 92 passed python -m mypy -> Success: no issues found in 2426 source files devtools verify --quick -> 18/18 steps green, exit 0 ``` `devtools verify` (default testmon-affected tier) was not run: testmon is unseeded in this worktree and seeding is a heavy one-time harness step out of proportion to this diff (per repo convention, reserved for harness/dependency changes); the focused selections above plus `--quick` cover the changed surface. ## Per-bead AC matrix **polylogue-9dxn** - `RAW_AUTHORITY_PARSER_FINGERPRINT` is the single source of the fingerprint string; no module hardcodes it -- **satisfied** (8 literals replaced in `revision_backfill.py`; grepped repo-wide for `revision-membership-v1`, zero hits outside the `SUPERSEDED_MEMBERSHIP_FINGERPRINTS` definition itself). - An `ambiguous` verdict under a superseded fingerprint is replayable; one under the current fingerprint stays terminal; both directions covered -- **satisfied** (`test_ambiguous_verdict_under_superseded_fingerprint_is_replayable`, `test_ambiguous_verdict_under_current_fingerprint_stays_terminal`, `test_ambiguous_verdict_with_no_census_row_stays_terminal`). - A bump does not force re-census of unaffected raws, asserted against a fixture -- **satisfied** (`uncensused_historical_revision_raw_ids` accepts any known fingerprint; existing `test_stale_per_raw_parser_fingerprint_is_recensused_before_planning` continues to pass, proving the *targeted* recensus path still works for a genuinely stale/unknown fingerprint while known fingerprints are accepted). **polylogue-5q2u** - AC1 (fixture proves reduced/eliminated deferred-tail hits, no adoption change) -- **satisfied** (`test_lineage_aware_replay_order_reduces_deferred_tail_hits`: 5->0 `_reextract_prefix_tail_db` calls on a 1-parent/5-child fixture). - AC2 (replay outcome parity, differential test) -- **satisfied** (`test_lineage_aware_replay_order_preserves_outcome_parity`: byte-identical `_index_content_manifest` + identical `RevisionBackfillResult` counts between lineage and forced-lexicographic order). - AC3 (cycles/missing/cross-batch parents degrade gracefully, never skip) -- **satisfied** (`test_lineage_aware_replay_order_falls_back_for_unresolvable_parent`; the ordering function's cycle-fallback loop is unconditionally total over its input set by construction). - AC4 (focused tests + `devtools verify --quick` land together) -- **satisfied**. **polylogue-f57q** - Full class-level `MaintenanceOutcome`/receipt contract census across every repair/cleanup handler -- **deferred**. This PR fixes the specific dry-run outcome defect (`repair_raw_materialization`'s preview success semantics) and the two `scale_regression_probe.py` tests it broke, matching the lane's explicit non-goal allowance ("land the typed outcome + the raw-materialization path + scale-probe fix, and file a follow-up bead for remaining handlers"). The broader phase/candidate/eligible/blocked/planned/applied/already-satisfied/failed/remaining vocabulary across every handler remains open scope needing its own design pass, as the bead's own prior note already states. - The seeded raw-materialization case reports phase-honest preview semantics (candidate=eligible=planned=1, applied=0, mutates=false, **success=true**) -- **satisfied** for this one call site; not generalized to a shared typed vocabulary. **polylogue-hjpx** - AC1 (production-shaped fixture + fix/defer) -- **misframed**: the exact defect this AC names (a scanned/classified raw yielding zero replayed logical sources, forever re-selected) is already fixed (commit `6ea374222`, PR #3337) and regression-tested (`test_raw_materialization_no_progress_component_terminalizes_instead_of_looping`), already in this lane's base commit. No new fixture could be honestly built because it does not reproduce. - AC2 (per-plan outcome conservation) -- **satisfied by pre-existing landed work**: `RawReplayPlanOutcome`/`RawReplayPlanStatus` (EXECUTED/RETRYABLE/DEFERRED/TERMINAL/REJECTED_STALE/CARRIED_FORWARD), `_raw_replay_conservation_metrics`, `raw_materialization_plan_conservation_error_count`, and `test_raw_materialization_fails_closed_on_plan_conservation_mismatch` are already live and green. - AC3 (fair bounded scheduling) -- **satisfied by pre-existing landed work** (PR #3345, merged 2026-07-27, confirmed ancestor of this lane's base via `git merge-base --is-ancestor`). - AC4 (retryable/CAS typing) -- **satisfied by pre-existing landed work** (same PR #3345). - AC5 (two quiescent dry-run censuses = fixed point) -- **satisfied by pre-existing landed work** (`record_raw_authority_census`'s `fixed_point` computation; `test_two_successive_quiescent_censuses_are_required_for_fixed_point` passes). - AC6 (scale proof) -- **out of scope** per lane non-goals (no live apply authorized). - AC7 (live-apply ceremony) -- **out of scope** per lane non-goals; the named `devtools test`/`devtools verify` commands were run as this PR's own verification (above), which is the non-live-apply portion of AC7. ## Anti-vacuity statement - **9dxn**: `test_ambiguous_verdict_under_superseded_fingerprint_is_replayable` calls `repair._raw_replay_plan_outcomes` (the exact function `repair_raw_materialization`, the daemon's live raw-materialization repair entrypoint, calls internally) via the public `build_raw_replay_plans` pair. Reverting the `LEFT JOIN raw_authority_parser_census` + `NOT COALESCE(... IN (SELECT value FROM json_each(?)) ...)` guard in `repair.py`'s terminal query back to the unconditional ambiguous check makes this test fail by reclassifying the plan `TERMINAL`. - **5q2u**: `test_lineage_aware_replay_order_reduces_deferred_tail_hits` calls the real production route `backfill_historical_revision_evidence` (its replay loop's `ordered_logical_keys`, computed by `_lineage_aware_replay_order` at its actual call site). Reverting the call site back to `sorted(logical_keys)` makes `lineage_hits` jump from 0 to 5 (verified live during implementation via `monkeypatch.setattr`). - **f57q**: `test_scale_regression_probe_runs_seeded_bug_class_checks` / `test_scale_regression_probe_main_emits_json` exercise `repair_raw_materialization(dry_run=True)` through `run_scale_regression_probe`'s `raw_materialization_debt_detected` check. Reverting `success=True` back to `success=False` in `repair.py`'s dry-run branch reproduces the exact `assert False is True` / `assert 1 == 0` failures observed before this fix. - **hjpx**: no new production surface added by this lane; the anti-vacuity claim is the evidence trail itself (`git merge-base --is-ancestor 64d203c e8a23cc`, plus the passing `-k hjpx` / `-k raw_materialization` / `-k raw_authority` selections against unmodified production code). ## Residuals / follow-ups - **polylogue-f57q**: the full `MaintenanceOutcome` typed vocabulary across every repair/cleanup handler remains open scope (deferred per lane non-goal). A follow-up tracking item should own the handler census explicitly. - **polylogue-hjpx**: the coordinator should re-verify this bead's status against live `master` (not the stale 2026-07-31 reconciliation note) before further dispatch -- AC1-AC5 read as satisfied by already-merged work; only AC6 (scale proof) and AC7's live-apply ceremony remain genuinely open, both explicitly out of scope for any lane under the standing "no live apply is authorized" constraint. - Two pre-existing, unrelated test failures observed and left untouched (out of this lane's scope): `test_parse_one_still_replays_real_claude_code_sessions_with_no_path_rule` (content-classification gate) and `test_maybe_run_raw_materialization_whale_pass_*` (`_bootstrap` mock-signature mismatch in `config.py:2173`). Ref polylogue-9dxn, polylogue-5q2u, polylogue-f57q, polylogue-hjpx
Summary
Adds regression tests proving polylogue-hjpx AC3 (bounded fair scheduling that doesn't starve large valid components behind cheap ones) and AC4 (transient retries keep the same plan id; CAS conflicts surface as typed/durable/non-mutating outcomes). No production code gap was found in either area — both invariants were already implemented (largely via hjpx.1, PR #2961, plus later hardening #3029/#3031/#3034/#3043) but lacked direct regression coverage for these specific failure modes.
Problem
polylogue-hjpx's 7-item acceptance criteria include AC3 (fair bounded component scheduling) and AC4 (transient-interruption retry / CAS-conflict typing). Continuing this bead's evidence-first investigation (see bead notes: AC1 was fixed this session via #3337, AC2/AC5 contributed to via the same fix), I read the full history and the closed hjpx.1/hjpx.2 children to avoid duplicating landed work, then investigated whether AC3/AC4 already hold in production or represent a genuine gap.
_raw_materialization_ordered_componentsinpolylogue/storage/repair.pyorders components by (never-attempted-first, then oldest-attempt-time, then acquisition order) — size is only used as a same-component tie-break, never a cross-component priority. No existing test proved this size-agnostic behavior explicitly, or that a size-preferring order would recreate the exact starvation AC3 names.backfill_historical_revision_evidence(repair.py ~L6517-6560) already classifies any RuntimeError — including the CAS-conflict class raised byrevision_application.py("CAS rejected a conflicting accepted head" / "older accepted frontier" / "incomparable accepted frontier") — into a typed, durably-recorded (raw_authority_census_plansin source.db), non-mutatingRETRYABLEoutcome carrying the sameplan_id. No existing test proved plan-id stability across a fail→retry→succeed cycle, or that a genuine CAS-conflict message specifically produces this typed/durable/non-mutating outcome (existing CAS tests only exercise the low-levelrevision_application.pyfunction raising, not the full reconciler pipeline's classification of that error).Solution
Three new regression tests in
tests/unit/storage/test_repair.py:test_raw_materialization_ordering_is_size_agnostic_and_does_not_starve_large_work— one large-but-executable component (oldest by acquisition) plus five small ones; fair ordering selects the large one first; a cheap-first mutation of_raw_materialization_ordered_componentsrecreates starvation.test_raw_materialization_transient_failure_retries_with_same_plan_id_then_succeeds— a transient lock-style failure produces aretryableoutcome with no parse residue; removing the injected failure and retrying executes with the sameplan_id.test_raw_materialization_cas_conflict_outcome_is_typed_durable_and_non_mutating— injects the exact CAS-conflict RuntimeError message; asserts the outcome isretryable, durably recorded inraw_authority_census_plans, and leaves zero residue in bothsource.db(parsed_at_ms) andindex.db(raw_revision_applications,raw_revision_heads).All three were validated anti-vacuously: I temporarily mutated the production code under test (cheap-first ordering; corrupted
plan_idin the RETRYABLE branch) and confirmed each test fails for the expected reason before reverting (cleangit diffon production code — this PR touches only the test file).AC5/AC6/AC7 status (not re-litigated by this PR, recorded here for continuity): AC5 is code-complete via hjpx.1 (closed). AC6 (July-15 scale proof) remains open in hjpx.2, blocked on host I/O pressure during corpus generation across 4 documented self-aborts — out of scope to duplicate here. AC7's named commands were run as part of this PR's own verification (below).
Verification
devtools test tests/unit/storage/test_repair.py tests/unit/sources/test_revision_backfill.py→ 109 passeddevtools test tests/unit/sources/test_revision_backfill.py→ 44 passeddevtools test -k raw_materialization→ 118 passeddevtools test -k raw_authority→ 83 passeddevtools verify --quick→ 17/17 steps green, exit 0devtools verify/--seed-testmon— per repo convention a focused test-only change uses the narrow gate (devtools test <files>+--quick), not a full-suite seed run.Ref polylogue-hjpx
Summary by CodeRabbit