Skip to content

feat(claude): draft as the review turn's status signal β€” guard drop, kickoff convert, handoff restoreΒ #101

Description

@gingur-bot

Draft stops being a review-turn precondition and becomes its in-progress signal (like πŸ‘€ on issue turns): re-assigning the bot to a ready (LGTM'd) PR must fire a re-review turn; the workflow converts the PR to draft while the turn runs; on failure the handoff restores the trigger-time state.

Context: this task comes from ask #98. Implement after #96 merges (same files). Coordinate with #97: whichever lands second rebases; do not block on it.

Changes:

  1. .github/workflows/claude.review.yml
    • Drop github.event.pull_request.draft from the job if:; four guards remain (assignee==bot, PR author==bot, head claude/task-*, same-repo+open). Update the "All five guards" comment.
    • Add a Draft step (after Checkout, before Secrets β€” the signal must not depend on Infisical): step-level if: ${{ !github.event.pull_request.draft }}, runs gh pr ready --undo "$PR" with GH_TOKEN: ${{ github.token }} (job already has pull-requests: write; GraphQL convertPullRequestToDraft works under it). The step if: makes the already-draft first-review case a clean skip rather than relying on CLI idempotency.
    • Pass trigger-time draft state to the handoff: draft: ${{ github.event.pull_request.draft }}.
    • No trigger loops: draft↔ready conversions emit converted_to_draft/ready_for_review; this workflow listens only to assigned (unchanged).
  2. actions/claude.handoff/action.yml
    • New optional input draft (default ''): "the PR's trigger-time draft state as a string ('true'/'false'); empty for issue turns".
    • New step Restore, if: inputs.status != 'success' && inputs.draft == 'false': gh pr ready "$ISSUE" with github.token. Mirrors Unack: the in-progress signal is removed on success (the agent flips ready on LGTM) and failure alike; a PR that was draft going in stays draft. Issue-turn callers (plan/implement) pass nothing β†’ step never runs.
    • Update the action description: to mention the draft-restore.
  3. actions/claude.review/prompt.md β€” moot check (step 2): moot is now merged or closed only. Drop "already marked ready" β€” the workflow converts to draft at kickoff, and re-reviews of previously-LGTM'd PRs are legitimate. Add one line of re-review context: prior reviews may include an LGTM; a re-review walks the acceptance criteria against the new head as usual.

Verdict semantics are unchanged: LGTM β†’ reviewer flips ready; blocking findings β†’ stays draft (draft is the only merge guard β€” the bot cannot REQUEST_CHANGES on its own PR).

Acceptance criteria:

  • Guard has exactly four clauses; assigning the bot to a ready open bot-authored same-repo claude/task-* PR starts the job (verify with act or a dry event-payload eval).
  • The Draft step converts a ready PR before the agent step and is skipped when the PR was already draft.
  • Handoff: non-success + draft == 'false' β†’ PR restored to ready; non-success + draft == 'true' β†’ stays draft; success β†’ step never runs. Both prior states exercised (a forced-failure run or act per repo CLAUDE.md).
  • Issue-turn callers of claude.handoff are byte-for-byte unaffected in behavior (no draft input passed).
  • Review prompt's moot definition = merged/closed only.

Metadata

Metadata

Assignees

Labels

claude-taskagent-implementable task

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions