Repository navigation
Conversation
7aa9bc7 to
ca2ce33
Compare
|
Friendly review ping — scheduled-run 400s now pair compacted tool results and record provider 400s as failed runs so the GUI doesn't show success after a 400 (#655, head |
ca2ce33 to
2c2cefe
Compare
2c2cefe to
b5d0805
Compare
|
Rebased onto |
6bf943a to
4151255
Compare
|
Refreshed onto current The failure was in new upstream code, not this diff:
Fixed in Deterministic A/B forcing the interleaving (output visible, exit 50 ms later): Local verification: |
…er 400s as failed runs Scheduled runs hit OpenAI 400 when compaction left a tool message without its tool_calls parent, and engine ERROR events were treated as success so last_status stayed ok. Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # coworker/server/manager.py
Scheduled runs already recorded EventType.ERROR as last_status=error; the GUI finalize path still hardcoded ok. Read the trailing error notice instead, and cover scheduler last_status plus the engine outbound orphan-tool feed. Co-authored-by: Cursor <cursoragent@cursor.com>
…ast output `shell_task_output(wait_seconds=N)` breaks its wait loop on the *first* of exit or new output. A one-shot command prints its last line and then exits a few milliseconds later, so waking on that line returned status "running" for a task that was already finished — the caller asked to be told when it was done and still had to poll again. After waking on output with the process not yet reaped, wait up to 250 ms (still inside the caller's deadline) for the exit so the same call returns `status="exited"` with the final line. Deterministic A/B, forcing the interleaving (output visible, exit 50 ms later): status "running" before, "exited" after. The new regression test encodes that interleaving and fails on the previous code; `tests/test_shell.py` 45 passed, full suite 5265 passed / 37 skipped.
716ecfa to
f52ade8
Compare
Fixes #655.
Problem
Scheduled runs abort with OpenAI 400 (
Messages with role 'tool' must be a response to a preceding message with 'tool_calls'), including the first run of a brand-new task. Interactive sessions doing the same work succeed. The runner still recordslast_status=ok.This is not a duplicate of #350 (load-side pairing repair) or #395 (compaction token estimates). #350 cannot fire on a fresh scheduled session; the 400 happens on the live provider feed after compaction. No other open PR is linked to #655.
Cause
toolrow (or on anoticethat is stripped next), so the parenttool_callsassistant message is gone and the API rejects the request.TurnEngine.run()converts provider failures intoEventType.ERRORand returns without raising._run_scheduled_tasktreated a finished generator as success.finalize_manual_runpath hardcodedstatus=ok/last_status=okfrom the saved transcript, so a live 400 looked successful too.Fix
errorwhen the engine emitsEventType.ERROR.finalize_manual_runreads a trailingnotice/kind=errorfrom the transcript and stampserrorinstead ofok. A later successful retry is stillok.Tests
tests/test_compaction.py— orphan-tool tail, rewind to parent assistant, notice-strip orphanstests/test_automation.py— scheduled provider 400 is stored aserror; scheduler copies that tolast_status; manual finalize does the sametests/test_engine.py—_outbound_messages()does not send a leadingrole=toolafter compaction + notice stripMade with Cursor