Skip to content

Parent wake that meets the promptAsync hold waits a whole extra hold (Windows CI: parent-wake empty-turn recovery test) #8951

Description

@code-yeongyu

Summary

On dev push CI, test (windows-latest, 1/2) failed in parent-wake-empty-turn-requeue.test.ts: "BackgroundManager parent wake empty-turn recovery > #given parent history contains the empty assistant turn #when idle flushes the requeued wake #then one retry prompt is delivered" (run 36300728869, 4440 ms, waitUntil at :98 called from :270).

Root cause

This is a product race that Windows timer granularity exposes, not only a slow runner.

  • The first parent-wake dispatch leaves a promptAsync post-dispatch hold on the session: DEFAULT_PROMPT_ASYNC_POST_DISPATCH_HOLD_MS = 2_000 (packages/utils/src/prompt-async-gate/timing.ts:1). The hold's expiry is checked lazily with Date.now() (reservations.ts pruneExpiredReservations).
  • When a retry meets that hold, parent-wake-prompt-dispatch.ts requeues it with scheduleFlush(2_000), a delay equal to the whole hold length.
  • The retry is armed a few ms after the hold starts. If the timer fires even a tick before Date.now() crosses expiresAt (Windows timers and Date.now() tick on coarse, different clocks), the gate still reports reserved and the wake waits a second full hold (~4 s). In production that is a needless extra 2 s of parent-wake latency. The test's 4 s sleep-polling window turns it into a red job.

Expected

  • A wake that meets a gate hold retries when that hold actually expires.
  • The test waits on the exact event (the retry promptAsync call) instead of a sleep-poll loop.

Acceptance criteria

  • The gate's reserved result carries the hold's expiresAt. The parent wake schedules its retry for expiresAt - now (a fixed 2 s stays only as the fallback when there is no expiry).
  • A deterministic regression test pins that retry delay with a frozen clock.
  • The empty-turn test has no polling loop. A focused Windows soak of the file passes 3 x 10 iterations.

Refs #8324

Activity

  1. code-yeongyu commented on Sep 28, 2026

    @code-yeongyu
    OwnerAuthor

    Fixed by #8961 (merge commit 6f65ada): a parent wake retry no longer waits a second promptAsync hold; the sleep-polling waitUntil is gone.

    Evidence: 3 focused windows-latest soaks green before merge (in the PR); the combined fix set was full-matrix green 3 times on the integration head; after merge, dev push CI run 36360065018 on e89647d (which contains every win-ci fix) was green in all 3 attempts on every Windows job, with the test steps actually executed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions