orchestrator: audit and bug-hunt fixes (submit stalls, attention, finish) (#9)

* orchestrator: recoverable submit stalls, quiet worker close, ready-timeout screen

- Activity gate retries Enter once at half the stall budget; a TUI still
  settling its input box could drop the first and leave the prompt unsent.
- A background-submit stall parks the task at input_required with
  reason submit_unconfirmed instead of failed; the worker turning working
  later resumes it, so its work stays reportable and finishable.
- Exits are idempotent (the PTY's late on_exit no longer re-raises
  attention), an exited pane drops input/permission attention to unread,
  and task.finish/task.cancel clear their worker's attention.
- ready_timeout evidence carries screen_tail, so a folder-trust or login
  prompt is visible in task.get.
- SKILL.md examples use --agent claude: a plain sh never gets ready.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* submit: a pane closed mid-submit is NO_SUCH_PANE, not a panic

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* orchestrator: task.start refuses a relative worktree path

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* orchestrator: persist background submit outcomes

A ready timeout, stall or accepted submit moved the task with no request
handler to flag the snapshot; a crash then recovered it as pending and
failed it with stage restart.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* orchestrator: a merge timeout that cannot restore the target is IO_ERROR

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* orchestrator: discard kills and reaps the whole worker group

A TERM to the leader left HUP-ignoring children (nohup builds) running
in the worktree that discard removes next.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* orchestrator: branch deletion keeps the first cleanup error and tells the truth

A failed worktree removal leaves the branch checked out, so the delete
always failed and overwrote the real cause; branch_deleted also recorded
the request, not the outcome.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* orchestrator: a merge git refuses without conflicts reports git's reason

A pre-merge-commit hook or unrelated histories came back as a
MERGE_CONFLICT with no files, or as a failed abort when no merge had
started.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs: task.finish error codes, worker reaping and absolute start path

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* orchestrator: review fixes for parked submits and merge failures

- Enter retry only into an untouched input box (idle/done, no decision,
  no permission prompt).
- A parked submit whose turn ends records turn_ended_without_report.
- A non-conflict merge failure is stored in finish_error like conflicts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* tests: discard reap check requires procfs instead of passing vacuously

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
802c150635Simone committed on 10/4/2026, 1:10:46 PM· committed by GitHubparent9ae7108
10 files changedLine totals unavailable