Skip to content

Windows CI flakes on HostSessionClient deny latency assertion #8950

Description

@code-yeongyu

Summary

A Windows root-test shard intermittently fails the HostSessionClient confirm auto-deny test even though the correct deny frame reaches the wire. The test currently treats completion within 50 ms as the contract, which makes correctness depend on shared-runner scheduling latency.

Reproduction

Run:

bun test packages/senpi-task/src/runners/rpc-host/session-client-records.test.ts

In a loaded Windows CI shard, the test #then a deny answer is on the wire within 50 ms observed the correct frame after 55.2205 ms and failed only the elapsed-time assertion.

Expected

  • A confirm UI request is answered with confirmed: false.
  • The auto-answer path does not wait for a human-facing timeout or block subsequent session commands.
  • The test asserts this ordering contract deterministically, without a wall-clock latency budget.

Actual

The payload assertion passes, but the test fails when shared-runner scheduling pushes observed elapsed time above 50 ms.

Evidence

  • packages/senpi-task/src/runners/rpc-host/session-client-records.test.ts:42-55 measures performance.now() around socket delivery and asserts < 50.
  • packages/senpi-task/src/runners/rpc-host/session-client.ts:206-214 builds the safe deny/cancel response and dispatches sendExtensionUIResponse without awaiting it; there is no timer on the product path.
  • Windows CI observed Received: 55.220500000003085 after receiving { type: "extension_ui_response", id: "ui-1", confirmed: false }.
  • A 50-run focused macOS control passed, consistent with scheduler-dependent timing rather than a protocol defect.

Root cause

Confirmed test flake: the assertion measures end-to-end wall-clock latency across the socket and CI scheduler instead of the product contract. The product path already dispatches the deny immediately and does not await a UI timeout.

Scope

  • Replace the elapsed-time assertion with a deterministic ordering/non-blocking assertion.
  • Keep the product path unchanged unless additional runtime evidence reveals an accidental await or timer.
  • Prove the fixed test with three focused Windows soak runs of 10 iterations each.

Acceptance criteria

  • The confirm request produces the expected deny frame.
  • A subsequent session command completes without waiting on the UI response path.
  • No fixed sleep, polling delay, enlarged timeout, retry, or platform skip is introduced.
  • Three focused Windows soaks pass 10/10 iterations.

Related

Activity

  1. code-yeongyu commented on Sep 27, 2026

    @code-yeongyu
    OwnerAuthor

    Root cause confirmed.

    • Windows run 36309221289 received the correct frame (extension_ui_response, id: ui-1, confirmed: false) and failed only because socket delivery measured 55.2205 ms against a 50 ms threshold.
    • packages/senpi-task/src/runners/rpc-host/session-client.ts dispatches sendExtensionUIResponse without awaiting it and has no timer on this path.
    • The pre-fix focused macOS control passed 50 repeated runs, confirming the threshold is scheduler-sensitive rather than a product protocol failure.

    Ideal state: assert the observable contract (deny is written and the next session command is not blocked), with no wall-clock budget, retry, sleep, or platform skip. Implementation and focused verification are in progress on fix/win-ci-session-client-deny.

  2. code-yeongyu commented on Sep 28, 2026

    @code-yeongyu
    OwnerAuthor

    Fixed by #8961 (merge commit 6f65ada): the 50 ms wall-clock deny budget is replaced by an ordering proof (deny on the wire before the client's next get_state).

    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