Skip to content

fix: derive refresh test freshness epochs from the clock - #53

Merged
gabrielspadon merged 1 commit into
mainfrom
fix/refresh-test-epoch-time-bomb
Sep 5, 2026
Merged

fix: derive refresh test freshness epochs from the clock#53
gabrielspadon merged 1 commit into
mainfrom
fix/refresh-test-epoch-time-bomb

Conversation

@gabrielspadon

Copy link
Copy Markdown
Collaborator

What broke

RefreshEngine.run compares the bound discovery policy epoch against its own wall clock (citeforge/refresh/engine.py:116), and derives the inventory task epoch from that same clock (engine.py:142). Ledger.commit_initial_round then requires the inventory authority to agree with the bound discovery policy (citeforge/refresh/ledger.py:4463).

Four tests in tests/test_refresh_discovery.py wrote the literal month they were authored in ("2026-08"), so they agreed with the engine for exactly one calendar month. When the clock rolled to 2026-09 the engine started deriving 2026-09 while the bound policy still said 2026-08, and all four began raising:

ValueError: inventory authority conflicts with bound discovery policy

That is a test-only defect. No production code path pins a month, and the monthly workflow derives its own with date +%Y-%m.

Blast radius

Every Test (py3.10 … py3.14) leg failed identically, which failed the Required CI aggregate and left PR #52 (a Dependabot uv bump touching only requirements-build.in and .lock) BLOCKED on a failure it did not cause. Any PR opened after 2026-09-01 would have been blocked the same way.

Fix

Both engine-driving test modules derive the epoch exactly as the engine does. The staleness test builds its rejected month as an explicit offset from today rather than naming one.

Two guard tests were also passing on the right status for the wrong reason. test_generation_start_binds_discovery_preflight_before_inventory_send was tripping the epoch mismatch instead of the missing s2 credential it exists to prove. Both it and the staleness test now pin the exact detail string their guard must return, so a guard that starts firing for a different cause fails instead of passing silently.

test_no_refresh_test_pins_a_literal_freshness_epoch fails on any double-quoted YYYY-MM literal in a test_refresh_*.py module that drives RefreshEngine, so this cannot be reintroduced. Single-quoted months inside the SQL of test_refresh_corpus.py write a deliberately mismatching epoch to trip a drift guard and are correctly left alone.

Verification

Run locally on Python 3.14.7 against origin/main.

  • Reproduced first: the same 4 failures, same ValueError, before any edit.
  • pytest -m 'not live' (CI's exact invocation): 2077 passed, 2 skipped, 7 deselected.
  • ruff check citeforge/ tests/ main.py: clean.
  • mypy citeforge/ main.py: clean, 56 source files.
  • The four previously-detonating tests re-run under a simulated 2027-02 clock: all pass, confirming the time coupling is gone rather than merely re-pinned to the current month.
  • The new guard was proved to fail by reintroducing a literal into test_refresh_discovery.py, then restored.

Merging this unblocks #52.

RefreshEngine.run compares the bound discovery policy epoch against its
own wall clock, and the ledger's commit_initial_round then requires the
inventory authority to agree with that bound policy. Four tests in
test_refresh_discovery.py wrote the literal month they were authored in,
so they agreed with the engine for exactly one calendar month. On
2026-09-01 the clock rolled over and every one of them began raising
"inventory authority conflicts with bound discovery policy" on all five
interpreters at once, leaving the Required CI aggregate red and every
open pull request unmergeable through no fault of its own.

Both engine-driving test modules now derive the epoch the same way the
engine does, and the staleness test builds its rejected month as an
explicit offset from today rather than naming one.

Two guard tests were passing on the right status for the wrong reason.
test_generation_start_binds_discovery_preflight_before_inventory_send
was tripping the epoch mismatch instead of the missing s2 credential it
exists to prove, so both it and the staleness test now pin the exact
detail string their guard must return.

A new contract test fails on any double-quoted YYYY-MM literal in a
test_refresh_*.py module that drives RefreshEngine, so this cannot be
reintroduced silently. Single-quoted months inside the SQL of
test_refresh_corpus.py are deliberate drift-guard mismatches and stay.

Verified against a simulated 2027-02 clock, and the full suite runs
2077 passed, 2 skipped, 7 deselected with ruff and mypy clean.
@gabrielspadon
gabrielspadon enabled auto-merge (squash) September 5, 2026 11:20
@gabrielspadon
gabrielspadon merged commit 1d1197c into main Sep 5, 2026
11 checks passed
@gabrielspadon
gabrielspadon deleted the fix/refresh-test-epoch-time-bomb branch September 5, 2026 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant