Skip to content

Compare admission-model refusal time to the clock value, not its last reading - #393

Merged
0thernet merged 1 commit into
mainfrom
claude/fv-admission-clock-refusal
Sep 25, 2026
Merged

0thernet merged 1 commit into
mainfrom
claude/fv-admission-clock-refusal

Conversation

@0thernet

Copy link
Copy Markdown
Member

Summary

Fixes a wrong-field assertion in the browser-admission fc.commands model that intermittently fails test 6/8 on main and on every lane merged past #392.

run() asserted that a refusal while a slot was available must have consumed a clock reading at or past the bound (lastRead >= bound). But simulated time advances without a reading: sleep adds its delay and the test commit hook adds commitDelayMs directly to clock.now. A 1 ms budget can expire on the deadline's field check before any subsequent reading — lastRead still 0 while now is already past the bound.

Observed on #391's test 6/8, seed 797548962, counterexample acquire({"timeoutMs":1,"captureRemainingMs":1,"increments":[],"commitDelayMs":1}): the commit hook advanced now to 1, the capture deadline's field check fired before the next now() read, production refused legitimately — and the assertion rejected it at lastRead=0.

The fix compares real.clock.now, which is what the deadline itself observes. A refusal while a slot was free still must be justified by simulated time reaching the bound — the check is not weakened. Same correction at the capture-launch assertion (line 469).

Test plan

  • Mechanism traced: lastRead only updates in readClock; sleep/afterCreateCommitForTest advance now field-only; deadline.throwIfUnavailable checks the field before throwIfUnavailable reads now()
  • CI test 6/8 passes (local replay blocked by host load; the failing schedule runs the real bound state helper)

Generated with Devin

The model asserted a justified refusal had consumed a clock reading at or
past the bound. Simulated time also advances without a reading: sleeps add
their delay and the test commit hook adds commitDelayMs. A one-millisecond
budget can therefore expire on the deadline's field check before any
subsequent reading, leaving lastRead at 0 while now is already past the
bound. CI seed 797548962 reached exactly that: acquire({timeoutMs:1,
captureRemainingMs:1, increments:[], commitDelayMs:1}) refused correctly
at now=1 with lastRead=0, and the assertion rejected a legitimate refusal.

Compare now instead, which is what the deadline itself observes; a refusal
while a slot was free is still unjustified unless simulated time reached
the bound.
@vercel

vercel Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
ghostget Ready Ready Preview Sep 25, 2026 3:55am UTC

Request Review

@0thernet
0thernet merged commit 8c3724c into main Sep 25, 2026
27 checks passed
@0thernet
0thernet deleted the claude/fv-admission-clock-refusal branch September 25, 2026 04:09

This branch was successfully deployed

1 active deployment
Preview — 5b883113 Deployed Sep 25, 2026 by vercel[bot]
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