Sandcastle reworks PRs with failing CI #20

Closed
opened 2026-07-05 07:32:44 +08:00 by weiwen · 0 comments
Owner

What to build

Extend the .sandcastle planning loop so it looks at open pull requests, not just new issues, and prioritises fixing PRs whose CI is red before starting fresh work.

End-to-end behaviour:

  • The planner reads open PRs inline (via tea pulls list, which exposes a ci field) and treats a PR as needing rework when its CI status is failure. It emits these as PR-rework items, distinct from new-issue items, and lists them first.
  • The orchestrator gains a bounded concurrency budget. PR-rework items claim slots before new issues fill the remainder; overflow defers to the next iteration. (Today the loop runs every unblocked issue in parallel with no cap.)
  • A PR-rework item routes to a new pr-fixer stage instead of the implementer, running in that PR's existing branch sandbox: reproduce the CI failure locally through the project's check gate (nix develop .#ci -c just check), fix it, push the branch, and post a short comment summarising the fix.
  • CI detection is label-free. The PR stays ready-for-human throughout; there is no relabel on the CI path. After the fix push CI re-runs, and the live ci field governs re-pick: while CI is pending the PR is not re-selected, and a renewed failure is re-attempted on later iterations until it passes or the loop hits its iteration cap.

Detection scope for this slice is CI only (ci == "failure"). The changes-requested signal is #21, which adds a ready-for-agent label to PRs via a workflow plus a matching planner arm — that label machinery is out of scope here.

Note: issues and PRs share one index space, but tea issue list and tea pulls list are separate endpoints, so PR labels never leak into the new-issue query.

Acceptance criteria

  • Plan output distinguishes PR-rework items from new-issue items (two groups); PR-rework items are ordered ahead of new issues.
  • The orchestrator honours a max-concurrency budget; PR-rework items claim slots before new issues, and work beyond the budget defers to the next iteration.
  • The planner flags an open PR as needing rework when its CI status is failure.
  • A PR-rework item routes to the pr-fixer pipeline (not the implementer), operating on that PR's existing branch.
  • The pr-fixer reproduces the failure via the project check gate, fixes it, pushes to the PR branch, and posts a brief summary comment. No label change is required on the CI path (the PR stays ready-for-human).
  • When no open PR needs rework, the existing new-issue pipeline behaves exactly as before.
  • docs/agents/triage-labels.md and the main.mts header comment reflect the new PR-rework path.

Blocked by

None - can start immediately.

## What to build Extend the `.sandcastle` planning loop so it looks at open pull requests, not just new issues, and prioritises fixing PRs whose CI is red before starting fresh work. End-to-end behaviour: - The **planner** reads open PRs inline (via `tea pulls list`, which exposes a `ci` field) and treats a PR as *needing rework* when its CI status is `failure`. It emits these as PR-rework items, distinct from new-issue items, and lists them first. - The **orchestrator** gains a bounded concurrency budget. PR-rework items claim slots before new issues fill the remainder; overflow defers to the next iteration. (Today the loop runs every unblocked issue in parallel with no cap.) - A PR-rework item routes to a new **pr-fixer** stage instead of the implementer, running in that PR's existing branch sandbox: reproduce the CI failure locally through the project's check gate (`nix develop .#ci -c just check`), fix it, push the branch, and post a short comment summarising the fix. - **CI detection is label-free.** The PR stays `ready-for-human` throughout; there is no relabel on the CI path. After the fix push CI re-runs, and the live `ci` field governs re-pick: while CI is `pending` the PR is not re-selected, and a renewed `failure` is re-attempted on later iterations until it passes or the loop hits its iteration cap. Detection scope for this slice is CI only (`ci == "failure"`). The changes-requested signal is #21, which adds a `ready-for-agent` label to PRs via a workflow plus a matching planner arm — that label machinery is out of scope here. Note: issues and PRs share one index space, but `tea issue list` and `tea pulls list` are separate endpoints, so PR labels never leak into the new-issue query. ## Acceptance criteria - [ ] Plan output distinguishes PR-rework items from new-issue items (two groups); PR-rework items are ordered ahead of new issues. - [ ] The orchestrator honours a max-concurrency budget; PR-rework items claim slots before new issues, and work beyond the budget defers to the next iteration. - [ ] The planner flags an open PR as needing rework when its CI status is `failure`. - [ ] A PR-rework item routes to the pr-fixer pipeline (not the implementer), operating on that PR's existing branch. - [ ] The pr-fixer reproduces the failure via the project check gate, fixes it, pushes to the PR branch, and posts a brief summary comment. No label change is required on the CI path (the PR stays `ready-for-human`). - [ ] When no open PR needs rework, the existing new-issue pipeline behaves exactly as before. - [ ] `docs/agents/triage-labels.md` and the `main.mts` header comment reflect the new PR-rework path. ## Blocked by None - can start immediately.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
weiwen/evie#20
No description provided.