Fix the flaky autosave-yield test that broke CI on main#144
Merged
Conversation
test_a_user_save_waits_out_a_real_in_flight_autosave_tick_instead_of_being_dropped failed once on main after #142 merged, then passed on a re-run of identical code. It is a genuine flake, and the fragility is mine - I wrote this test in #138. Cause: the test raced the real autosave loop with interval_seconds=0.02 while each tick held the guard for ~0.1s. Because _loop sleeps AFTER a tick, ticks ran effectively back-to-back, so the user's save had to win a scheduling race in the narrow window between one tick releasing the guard and the next re-claiming it. On top of that it asserted a 1.0s wall-clock bound against a 2.0s production timeout - a 2x margin on a contended 2-core CI runner. Fixed by removing the race rather than widening the bound: - register_autosave now exposes bus.autosave_guarded_tick, the same testability seam already used for bus.autosave_task and bus.chat_save_state (the file's own comments justify exactly this: a closure-local is unreachable to the tests that must prove the wiring). - The test drives exactly ONE real tick through that seam with interval_seconds=3600, so the periodic loop can never fire and no second tick can steal the guard back mid-handoff. - The tick's duration is controlled by a gate instead of a sleep, so the user's save provably arrives while the guard is genuinely held. - AUTOSAVE_YIELD_TIMEOUT_SECONDS is patched to 30s and the save asserted within 5s: a missing release signal still fails it, now with a 6x margin instead of 2x. Still drives the REAL _guarded_tick, so it keeps catching what it exists to catch - verified by mutation: dropping the AUTOSAVE owner tag fails it, and dropping the released.set() signal fails it. Ran 25/25 green locally. Full suite: 2438 passed, compileall clean. Co-Authored-By: Claude Opus 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.
Summary
test_a_user_save_waits_out_a_real_in_flight_autosave_tick_instead_of_being_droppedfailed on main after #142 merged. It is a flake, and the fragility is mine — I wrote this test in #138.Evidence it's a flake, not a regression: the identical code passed CI on the PR branch and failed on the post-merge run; the test and the code under it were untouched by #142/#143.
That said, a flaky test in CI is a real defect, so it's fixed properly rather than re-run.
Cause
The test raced the real autosave loop at
interval_seconds=0.02while each tick held the guard for ~0.1s._loopsleeps after a tick, so ticks ran effectively back-to-back — the user's save had to win a scheduling race in the narrow window between one tick releasing the guard and the next re-claiming it. On top of that it asserted a 1.0s wall-clock bound against a 2.0s production timeout: a 2× margin on a contended 2-core Windows runner.Fix — remove the race, don't widen the bound
register_autosavenow exposesbus.autosave_guarded_tick, the same testability seam already used forbus.autosave_taskandbus.chat_save_state(that file's own comments justify exactly this: a closure-local is unreachable to the tests that must prove the wiring works).interval_seconds=3600, so the periodic loop never fires and no second tick can steal the guard back mid-handoff.AUTOSAVE_YIELD_TIMEOUT_SECONDSis patched to 30s and the save asserted within 5s — a missing release signal still fails it, now with a 6× margin instead of 2×.It still catches what it exists to catch
Verified by mutation against the real
_guarded_tick:AUTOSAVE_OWNERtagreleased.set()signalRan 25/25 green locally.
Validation
python -m compileall -q .passesNote
I did also try to reproduce under synthetic CPU load; my load generator failed to spawn, so that run proved nothing and I discarded it rather than citing it as evidence.