Skip to content

Delegate push, draft PR, and the CI-green loop to the implementer subagent - #342

Open
ikuwow wants to merge 7 commits into
mainfrom
delegate-push-and-ci-to-implementer
Open

Delegate push, draft PR, and the CI-green loop to the implementer subagent#342
ikuwow wants to merge 7 commits into
mainfrom
delegate-push-and-ci-to-implementer

Conversation

@ikuwow

@ikuwow ikuwow commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Purpose

The implementer subagent stopped at local commits, so the parent agent was left running the CI-green loop by hand: push, watch checks, read the failure log, fix, push again. That is mechanical repetition on the most expensive agent in the session, and it left two cases with no delegated path at all — work that only CI can verify (no local environment for it), and follow-up commits on an existing PR, where the commit was delegated but the push that makes it visible was not.

This moves "get the branch to a green draft PR" into the implementer by default, and keeps the parts that need judgment — the PR body's rationale, code review, ready-for-review, merge — with the parent.

Key changes

  • The implementer now pushes, opens a draft PR, watches CI, and fixes failures on its own. This is default behavior for every dispatch, single or parallel; the parent opts out with "do not push" or "commits only". Branch and worktree creation stay with the parent.
  • Its PR body is a fixed placeholder and its title is prefixed WIP:. A plausible-looking body written by a subagent invites the parent to lightly edit it instead of writing the real one, so an obvious stub is the safer artifact — what matters is that the PR exists. /pr-selfcheck already fails a stub body on PR Body Checklist items 1 and 6, so nothing has to remember to catch it.
  • Guardrails against the failure modes this opens up: a cap of 3 fix-and-push rounds, a ban on going green by weakening the check (deleting or skipping tests, continue-on-error, disabling a rule, loosening an assertion), report-don't-fix for failures the diff did not cause, and an explicit force-push ban. The default-branch precondition treats an unresolvable origin/HEAD and a detached HEAD as failures rather than passes, since no hook covers pushes.
  • The git-workflow skill gains one state-based step (skip PR creation when the branch already has one) and no implementer-specific conditionals. Knowledge that the implementer exists stays in implementation-delegation.md so either side can change without dragging the other along.
  • The permission allowlist gains the two push forms git-essentials.md already prescribes, which is what lets the loop run unattended.

Notes

Those allowlist entries are deliberately narrow. A broad Bash(git push *) was the first attempt, and the review found it silently auto-approves two paths the deny list misses: git push origin +main, which forces via plus-refspec, and git push origin HEAD:main, which puts a feature branch straight onto the default branch. Granting only the two prescribed forms covers the documented procedure with no new surface, and anything else still prompts.

The new rules are not deployed until this merges, so this PR itself was pushed and opened by the parent. The delegated path gets its first real exercise on the next delegated task.

Verification

  • pre-commit run --all-files → all hooks pass except Check userscript version bump, which fails identically on main (userscripts/ime-enter-fixer.user.js: content changed but // @version was not bumped) and touches no file in this diff
  • jq empty claude/settings.json → exit 0
  • Every gh and git command quoted in the new instructions checked against --help on gh 2.96.0; git symbolic-ref --short refs/remotes/origin/HEAD confirmed to exit 128 when origin/HEAD is unset, which is why that case is now an explicit precondition failure
  • Behavioral check on the next delegated implementation task: the implementer pushes, opens a WIP: draft PR, and reports its ## PR / ## CI sections

ikuwow and others added 7 commits July 28, 2026 16:37
Add a Push, draft PR, and CI section describing default push and
draft-PR behavior, fix-and-push limits, and preconditions. Split the
first Constraints bullet so push and draft-PR creation move to the
implementer while final PR title/body, review, ready-for-review, and
merge stay with the parent. Extend Verification to require honest
reporting of local vs CI-delegated checks, and add PR/CI sections to
the default output format.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Update the parallel-dispatch bullet so each implementer pushes its own
branch and opens its own draft PR with a placeholder title and body,
matching the implementer's new default push behavior. Add a review
bullet reminding the parent to rewrite the placeholder title and body
before running /pr-selfcheck.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Add a leading step to Create a PR so the skill checks for an existing
PR first, bringing its title and body up to the PR Body Checklist
instead of creating a duplicate. This lets the skill pick up branches
where an implementer already opened a placeholder draft PR without
naming the implementer.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Add Bash(git push) and Bash(git push *) to permissions.allow so the
implementer's new default push behavior does not hit an ask/deny
prompt. Both forms are needed since Bash(git push *) alone does not
match a bare git push. Existing deny rules for --force, -f, --delete,
--mirror, and --force-with-lease still win, since deny is evaluated
before allow.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
The Commits section still ended with "The parent reviews your commits
and owns push and the PR", which now contradicts the Push, draft PR,
and CI section directly below it. Keep only the review half.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SGZd5xCiU5f3dugLesAsPa
Bash(git push *) auto-approved forms the deny list does not cover:
git push origin +main forces via plus-refspec, and git push origin
HEAD:main puts a feature branch straight onto the default branch --
Bash(git push * :*) needs a literal space before the colon, so it
misses the latter. Both were newly silent on an agent this branch also
authorizes to push on its own.

git-essentials.md prescribes exactly two forms, so allow exactly those
two. Anything else prompts, as before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SGZd5xCiU5f3dugLesAsPa
Five fixes:

The existing-PR branch said "pushing the new commits is the whole job",
which reads as terminal even though it sits above the CI watch in the
same list. It now routes to the watch, which is the case where a
regression is most likely.

The default-branch precondition had an indeterminate third outcome:
git symbolic-ref exits 128 when origin/HEAD is unresolvable, and
git rev-parse --abbrev-ref HEAD returns the literal HEAD when detached.
Both now count as a failed precondition, and the branch lookup uses
symbolic-ref --quiet, which reports detachment instead of hiding it.
The claim about which hooks watch which tools is gone -- it was true
today but would rot silently if a Bash-matched push guard is ever
added.

Push and draft-PR creation were only announced in the parallel-dispatch
section and in the subagent's own file, so a parent dispatching a single
implementer had no way to learn the behavior exists or how to opt out.
Both now appear in the agent description and under Ordering.

The skip-creation branch in the skill bypassed the step that shows the
PR URL, so in the delegated flow the user could reach Phase 4 without
ever seeing the link.

"no checks reported" from a just-created PR is a registration race, not
a CI failure, and the reason for --body-file is no longer restated a
third time.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SGZd5xCiU5f3dugLesAsPa
@ikuwow
ikuwow marked this pull request as ready for review July 28, 2026 08:14
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