Skip to content

Handle each pi stdout line in its own event-loop turn - #2355

Merged
SawyerHood merged 1 commit into
mainfrom
bb/investigate-failing-main-tests-thr_3t6w72mwrv
Aug 24, 2026
Merged

Handle each pi stdout line in its own event-loop turn#2355
SawyerHood merged 1 commit into
mainfrom
bb/investigate-failing-main-tests-thr_3t6w72mwrv

Conversation

@SawyerHood

Copy link
Copy Markdown
Collaborator

What was wrong

The parity self-test pi/compaction reproduces its recording fails on main (CI for #2346 and #2349, job Tests (packages, ubuntu-latest, Node 22.x)). The recording contains a steer. After the steer, pi writes the prompt response and then the tool_execution_end for sleep 2. One pipe read can carry both lines. The pi bridge handled a chunk in one synchronous loop: the event's delivery (deliverInOrder) runs one microtask hop after its line, but the steer's input.accepted runs several await hops after the response. So item.close went out before input.accepted, and the bridge's output order depended on pipe chunking. The parity replay child keeps a 50 ms gap after a response, but a starved CI runner can stall the bridge past that gap. The diff in CI shows this exactly: turn/input/accepted moved, and the sleep 2 row spans seq 9–11 instead of 9–12.

The other red test on main (bridge.lifecycle.test.ts > a failed construction leaves no child, #2346 only) is the pi lifecycle budget flake that #2353 addresses.

What changed

  • plugins/provider-pi/src/bridge/rpc-child.ts: PiRpcChild queues stdout lines and handles one line per event-loop turn (setImmediate). A request's continuation finishes before the next line, which is the order a line-at-a-time read gives.
  • plugins/provider-pi/src/bridge/fake-pi-rpc.mjs: new knob FAKE_PI_BATCH_STEER_REPLY=1 writes a steer's prompt response and the resumed run's first event in one stdout write.
  • plugins/provider-pi/src/bridge/bridge.round2.test.ts: regression test that pins the ack before the same-chunk event.

No wire change. HOST_DAEMON_PROTOCOL_VERSION stays the same: only the bridge's ordering became deterministic.

How you verified

  • The new round2 test fails before the change (ack at index 5, event at index 4) and passes after it.
  • Deterministic repro of the parity failure: a replay child patched to write the post-response line in the same write failed the pi/compaction cell 3/3 before the change and passed 3/3 after it. The patch was a local experiment and is not part of this PR.
  • pnpm exec turbo run test typecheck --filter=./plugins/provider-pi --filter=@bb/provider-parity --force: pi plugin 105/105, parity 56/56, typecheck clean.
  • Off-pipeline: real pi (0.84.3) slice of @bb/agent-runtime#test:integration (integration.provider-basic.test.ts -t "pi provider"): 8/8, including "steers an active turn".

Fixes the pi/compaction parity failure on main (no issue filed).

AGENT GENERATED

The parity self-test `pi/compaction reproduces its recording` failed on
main (#2346, #2349): `turn/input/accepted` for the steer moved after the
`item.close` of the `sleep 2` command, so the row spans shifted.

One pipe read can carry pi's `prompt` response and the events pi wrote
after it. The bridge handled a chunk in one synchronous loop: the next
event's delivery ran one microtask hop after its line, but the steer's
ack runs after several `await` hops past the response. So the ack went
out after the event, and the bridge's order depended on pipe chunking.
A loaded CI runner can stall the bridge past the replay child's 50 ms
post-response gap, which merges the two lines into one read.

`PiRpcChild` now queues stdout lines and handles one line per event-loop
turn. The request continuation finishes before the next line, the order
a line-at-a-time read gives.

Verification: a new fake-pi knob (FAKE_PI_BATCH_STEER_REPLY=1) writes the
steer response and the resumed run's first event in one write; the new
round2 test fails before this change and passes after it. The parity
cell passes 3/3 with a replay child patched to coalesce post-response
writes (it failed 3/3 before). Full pi plugin and parity suites pass.

Co-Authored-By: Claude <noreply@anthropic.com>
@SawyerHood
SawyerHood merged commit 0782b0e into main Aug 24, 2026
15 checks passed
@SawyerHood
SawyerHood deleted the bb/investigate-failing-main-tests-thr_3t6w72mwrv branch August 24, 2026 22:02
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