Repository navigation
fix(agent): make turn lifecycles explicit state machines - #2311
Confidence 6/10 · 1 issue to address
🟡 Confidence 6/10 · needs attention. Held at 6 because a correctness warning is open.
1 warning −1 · tests covered · risk high −1 · 1/1 new units observable
Reworks the autonomous turn into explicit settle/abort paths with coherent failure status, and makes the socket reconnect on a stalled handshake. The phase/settle logic reads correctly, but the new settle deadlines cannot cut a hung write.
runAutonomousTurnruns the phases, then settles once viasettleTurnoraborted.phaserecords each ending; the turn-end and PR failure reason derive from all of them.- Runner turn-ends now go through
session.endTurn, gated by the turn slot. - ConnectorSocket gives up a dial that has not opened within
OPEN_TIMEOUT_MSand reconnects.
Findings
🟠 Warning · F1 · Effect.timeout on the settle's submit cannot cut an uninterruptible write
correctness · apps/ai/src/chat/turn-runner.ts:792
submitReview runs inside runAutonomousTurn's uninterruptible settle, so Effect.timeout(SUBMIT_SAVED_TIMEOUT) cannot interrupt it: a hung submit holds the settle — and with it the session's turn slot, since endTurn is below it — for as long as the provider call runs. progress.ts:178 makes the write interruptible before its timeout for exactly this reason.
Thread `restore` from `runAutonomousTurn`'s mask into `settleTurn` and run each write as `restore(write).pipe(Effect.timeout(...))`, keeping only the bookkeeping uninterruptible, as `progress.ts` does.
What was checked
- Abort path:
failUnfinishedskips superseded aborts andsettlere-checks the slot, so an abort cannot overwrite a filed review. phaseonly catches non-interrupt causes, so an abort still reaches the settler's interrupt path instead of being swallowed.- The saved-review submit now runs before
endTime/finish, so it is not racing the review row's failure write.
Observability coverage: 1 of 1 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
Autonomous turn settle (runAutonomousTurn) |
background work | yes | Turn span re-annotated after settle (turn-runner.ts:816); maple.pr_review.failure_reason per row write (autonomous-settle.ts:54) |
12c1c94 · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
Annotations
Check warning on line 792 in apps/ai/src/chat/turn-runner.ts
maple-review-bot / Maple / review
correctness: `Effect.timeout` on the settle's submit cannot cut an uninterruptible write
`submitReview` runs inside `runAutonomousTurn`'s uninterruptible settle, so `Effect.timeout(SUBMIT_SAVED_TIMEOUT)` cannot interrupt it: a hung submit holds the settle — and with it the session's turn slot, since `endTurn` is below it — for as long as the provider call runs. `progress.ts:178` makes the write interruptible before its timeout for exactly this reason.