Repository navigation
Measure SessionStart memory budgets on the injected clock - #887
Conversation
PR Summary by QodoMeasure SessionStart budgets with the injected TimeProvider
AI Description
Diagram
High-Level Assessment
Files changed (17)
|
Code Review by Qodo
1.
|
4e30c0c to
5e5b26e
Compare
5e5b26e to
3e6e491
Compare
3e6e491 to
c13d785
Compare
Lease expiry was already injectable while every budget stayed on the process clock, so a test could fake one and still be timed by the other. TimeProvider carries the monotonic pair, so elapsed time does not move to a wall clock. The two contended cases keep the process clock: their losers wait on the store's file lock, and a clock nothing advances never leaves that retry loop. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ServiceVerify already measured through its injected clock; only the suites handed it the process one, so a runner stalled between entry and the first probe spent the whole 20s budget and the install failed as a timeout. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The budget arithmetic moved to the injected clock while the cancellation enforcing it stayed on a real timer, so a frozen clock bounded nothing and the fetch ran until wall time caught up. Both lanes and the bounded hook wait now arm against the clock the remaining was measured on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
c13d785 to
0cb5083
Compare
Closes #885 — AI-2701
What & why
SessionStartMemoryLeaseStoretook aTimeProviderand used it for lease expiry, but everybudget in the subsystem was measured with static
Stopwatch— so half of it answered to aninjected clock and half to the process, and a test could fake one while being timed by the other.
TimeProvidercarries the monotonic timestamp pair, so the fix keepsStopwatchsemantics ratherthan moving elapsed time onto a wall clock.
A budget is only real if the thing it bounds observes the same clock, so both context lanes arm
their expiry on the injected one too, and the hook's bounded wait uses the clock its
Remainingwas measured on.
ServiceVerifyalready measured everything through its injected clock; itssuites were the only thing still handing it a real one.
Where to look
Two cases deliberately keep the process clock, and say so at the call site: their losers contend
for the store's file lock, whose retry loop waits on the same clock it measures — a clock nothing
advances never leaves it.
The lease store gains no parameter. Every hook call site already held
clock.Time, so theorchestrator and scope resolver take it without any new dependency flowing.
Verification
Two pins, each checked by mutation. Stopping the budget from running down fails only
A_fetch_that_outlives_its_budget_is_dropped_rather_than_injected; reverting the orchestrator tothe static
Stopwatchdoes not even compile (CS9113 is an error here). Re-arming the lane'sexpiry on a real timer fails only
Advancing_past_the_budget_abandons_an_in_flight_fetch, at its30s ceiling — its budget is ten minutes, so nothing but the injected clock can end that fetch.
SessionStartMemoryFoundationTestsServiceVerify*(Install, Start, Replace)Full CLI unit suite: 4003 passed, 19 skipped, 0 failed.
RepositoryDetectionkeeps its ownStopwatchseam and is left alone — the scope resolver thatreaches it is stubbed out in every test here, so threading a clock through it belongs with work
that actually exercises that path.