Repository navigation
docs(plan): inject a request clock so the idle-timeout tests stop waiting on wall time (slice C3 of #235) - #289
Merged
Merged
Conversation
Detailed, spike-measured plan for the last open slice of the test-hermeticity umbrella #235: a constructor-injected request clock on ClientManager (7 of 18 time.time() sites join the seam; the 11 reported timestamps stay on wall time), an IDLE_POLL_SLICE_S constant so the idle re-check cadence is patchable, and the idle-timeout tests rewritten to drive a fake clock one idle check at a time. Monotonic time is a named follow-up, not part of this slice, because gateway.list_pending and pmcp status render the stamps as epoch seconds. Measured this session on a throwaway spike (reverted; src/ and tests/ are byte-identical to HEAD in this commit): 10 mutants red by name, 1 slice mutant detected by timing only; 40/40 repeated runs, 0.045 s mean call time vs a 1.11 s baseline; whole suite 4068 passed. Plan-only commit. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013G8iK4noj1iNbSTqJVFEX6
… not hang it Board review of PR #289 found one blocking test-liveness gap in the C3 plan for #235: when the idle check stops reading the clock (new mutant M12, `now = pending.started_at`), the three driver-based tests hung to pytest-timeout (700 s each) instead of failing by name — past the CI job's 25-minute limit, so the job would be cancelled with no red test. Each driver now wraps its loop in `try/except BaseException` and fails every in-flight future with its own exception (`_fail_pending`), so the main await ends by name in ~5 s. Measured: M12 before the fix 3 × `Failed: Timeout` (20 s cap); after it `3 failed, 7 passed in 15.14s`, each `condition not met within 5.0s`. M1–M11 re-run on the revised spike with identical outcomes; 40/40 repeated runs again (0.040 s mean call time); file 253 passed; ruff, format and mypy clean. Also: the PendingRequest comment no longer claims the stamps are compared only with the request clock (handlers/cli subtract time.time() today; that is the monotonic follow-up), the board's `ClientManager.now()` suggestion is recorded as a declined non-goal with reasons, and Verification gains the `uv sync -p 3.10 --all-extras` prerequisite and the seat's Python 3.14.7 confirmation. Plan-only commit; src/ and tests/ are byte-identical to HEAD. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013G8iK4noj1iNbSTqJVFEX6
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.
Detailed plan for slice C3 of see #235: the last open slice of the test-hermeticity umbrella. Plan only;
src/andtests/unchanged.Plan:
.consiliency/plans/detailed-235-c3-clock-injection-20260923-1229.mdDesign in brief
ClientManager(clock=...)is injected through the constructor; the default istime.time. Seven of the 18time.time()call sites inmanager.pyjoin the seam: every site that stamps or compares a request'sstarted_at/last_heartbeat/last_activity_at. The other 11 are reported timestamps or IDs that are never compared with a request stamp, and they stay on wall time.min(idle_timeout_s, 1.0)) becomes a named constant tests can shrink. A fake clock that counts reads lets each test step time exactly once per idle check, so no test waits in real time and none asserts an upper bound on wall-clock time.cli.py:1478/1549,handlers.py:6335), so a monotonic default would makegateway.list_pendingshow 1970.Verified independently by the integrator
Applied the plan's diff and test bodies to a scratch worktree off current main, adding the three test imports the plan lists in its changes table:
tests/test_client_manager.py: 253 passed;ruff check,ruff format --checkandmypy src/clean.time.time()made exactly the three named tests fail. Restored byte-identical.🤖 Generated with Claude Code
https://claude.ai/code/session_013G8iK4noj1iNbSTqJVFEX6
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.