Skip to content

feat(pr): draft PRs by default, auto-undraft in pr-patrol#1794

Merged
OAGr merged 5 commits intomainfrom
claude/keen-wilbur
Mar 6, 2026
Merged

feat(pr): draft PRs by default, auto-undraft in pr-patrol#1794
OAGr merged 5 commits intomainfrom
claude/keen-wilbur

Conversation

@OAGr
Copy link
Contributor

@OAGr OAGr commented Mar 6, 2026

Summary

  • crux pr create now creates draft PRs by default (use --no-draft to override)
  • New crux pr ready command validates eligibility before converting draft → ready
  • PR Patrol auto-undrafts draft PRs labeled ready-to-merge when all eligibility checks pass
  • PR Patrol skips draft PRs from the fix queue (no automated fixes on WIP)
  • Added isDraft to GraphQL PR queries and GqlPrNode interface

Why

Previously, agent PRs were immediately mergeable on creation, with no clear signal about whether they'd passed all quality gates. Draft PRs provide a visual "not ready yet" signal in the GitHub PR list, preventing premature merges while the PR awaits CI, review, and comment resolution.

Key changes

  • crux/commands/pr.ts: Default --draft, new ready subcommand with eligibility validation
  • crux/pr-patrol/index.ts: isDraft in GraphQL, is-draft merge block reason, undraftPr() function, auto-undraft phase in patrol cycle, draft PRs filtered from fix queue
  • crux/pr-patrol/index.test.ts: 4 new tests for draft eligibility

Workflow

  1. Agent creates PR → draft by default (can't be accidentally merged)
  2. Agent or human labels ready-to-merge when satisfied
  3. PR Patrol checks eligibility → auto-undrafts if all checks pass → merges
  4. crux pr ready lets agents/humans manually undraft with eligibility validation

Test plan

  • 28 pr-patrol tests pass (including 4 new: draft blocking, non-draft passes, draft in findMergeCandidates, undraft-eligible filtering)
  • 23 pr.test.ts tests pass (no regressions)
  • 69 total PR-related tests pass across 4 test files
  • TypeScript check clean (0 errors in modified files)
  • /review-pr completed — found and fixed 3 issues:
    • crux pr ready self-blocked on is-draft (HIGH)
    • Wasteful REST fallback before GraphQL for undrafting (MEDIUM)
    • Failed undraft still attempted merge (MEDIUM)

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added ready command to manually mark draft pull requests as ready for review with comprehensive eligibility checks
    • Introduced automated undraft flow that intelligently transitions eligible draft PRs to ready status before merge operations
  • Tests

    • Expanded test coverage to validate draft pull request handling and merge eligibility verification

OAGr and others added 4 commits March 5, 2026 15:04
Previous run (2026-03-05T07:59:11Z) failed with error_max_turns after
31 turns — Claude ran out with max-turns=30 on a weekly sweep. Also
increase timeout-minutes from 30 to 60 to give sufficient wall-clock
headroom for weekly/monthly cadences.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* origin/main:
  feat(pr-patrol): add auto-merge for PRs labeled ready-to-merge (#1788)
  feat(ci): test Drizzle migrations against throwaway Postgres in CI (#1771)
  feat(ci): integrate Reviewdog for inline PR annotations (#1787)
  fix(ci): add CodeRabbit security gate to block merges on critical findings (#1780)
  feat(statements): CRUD CLI commands + markdown ontology draft workflow (#1784)
  feat(pr-patrol): add main branch CI monitoring and PR overlap detection (#1786)
  feat(ci): add PR size warning (non-test additions) and Drizzle schema drift detection (#1781)
  fix(ci): increase scheduled-maintenance max-turns and timeout (#1783)
  fix: derive test mock column types from Drizzle schema to prevent drift (#1782)
- `crux pr create` now creates draft PRs by default (use --no-draft to override)
- New `crux pr ready` command validates eligibility (CI green, no conflicts,
  no unresolved threads, no unchecked items) before converting draft to ready
- PR Patrol auto-undrafts draft PRs labeled `ready-to-merge` when all other
  eligibility checks pass, then merges in the same cycle
- PR Patrol skips draft PRs from the fix queue (no point fixing drafts)
- Added `isDraft` to GraphQL PR query and `GqlPrNode` interface
- `is-draft` added as a new `MergeBlockReason`
- 4 new tests covering draft eligibility checks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…iled undraft tracking

- Filter out 'is-draft' from block reasons in `crux pr ready` (it's the
  whole point of the command, not a blocker)
- Replace REST-then-GraphQL fallback with direct GraphQL for undrafting
  (REST API doesn't support undrafting, so the REST call always fails)
- Track which PRs were successfully undrafted before attempting merge
  (prevents merge attempts on PRs where undraft API call failed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

🛑 Protected Paths Modified

This PR modifies 1 protected file(s) that control agent behavior, CI pipelines, or validation logic. These changes require human review before merging.

CLI commands (crux/commands/)

  • crux/commands/pr.ts

Action required: Add the rules-change-reviewed label after a human has reviewed the protected file changes.

Why this check exists: Agents have write access to their own behavioral rules. Without human review, a rule change buried in a large PR could weaken validation, bypass gates, or modify agent instructions. See #1405.

@coderabbitai
Copy link

coderabbitai bot commented Mar 6, 2026

Warning

Rate limit exceeded

@OAGr has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 58 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 80004286-86ea-46e4-9af1-f9072dcba786

📥 Commits

Reviewing files that changed from the base of the PR and between c44a509 and 9da88a0.

📒 Files selected for processing (2)
  • crux/commands/pr.ts
  • crux/pr-patrol/index.ts
📝 Walkthrough

Walkthrough

A new ready command for PRs marks draft pull requests as ready for review with eligibility checks (CI status, conflicts, unresolved threads, unchecked checkboxes), while the PR patrol system gains draft-aware logic to handle drafts through a new undraft phase that auto-undrafts eligible PRs and re-evaluates for merging.

Changes

Cohort / File(s) Summary
PR Ready Command
crux/commands/pr.ts
Added ready command to mark draft PRs as ready for review with eligibility validation and optional force bypass. Supports targeting via --pr option or auto-detecting from current branch. Includes GraphQL mutation to undraft PRs and error handling with detailed output.
PR Patrol Draft Handling
crux/pr-patrol/index.ts
Introduced draft PR detection and handling via new isDraft field in GraphQL queries and GqlPrNode interface. Added is-draft as MergeBlockReason. Implemented fetchSinglePr function for single PR fetching and undraftPr function to undraft eligible PRs. New undraft phase in main cycle with re-evaluation after undrafting.
PR Patrol Tests
crux/pr-patrol/index.test.ts
Added test coverage for draft PR handling: verified checkMergeEligibility blocks on drafts, confirmed is-draft block reason presence/absence, and ensured draft PRs are marked as blocked but remain undraft-eligible.

Sequence Diagrams

sequenceDiagram
    participant User
    participant CLI as ready command
    participant GQL as GraphQL API
    participant PR as GitHub PR

    User->>CLI: Execute ready command
    CLI->>GQL: Fetch PR details (isDraft, CI status, etc.)
    GQL-->>CLI: Return PR data
    
    alt PR is eligible
        CLI->>CLI: Validate: isDraft=true, CI passing, no conflicts
        CLI->>GQL: Execute undraft mutation
        GQL->>PR: Mark PR as ready
        GQL-->>CLI: Success response
        CLI-->>User: PR ready for review
    else PR not eligible
        CLI->>CLI: Check eligibility (CI, conflicts, threads, etc.)
        CLI-->>User: Detailed block reasons
    end
Loading
sequenceDiagram
    participant Cycle as PR Patrol Cycle
    participant GQL as GraphQL API
    participant Store as PR Cache
    participant MergeSys as Merge System

    Cycle->>GQL: Fetch all open PRs with isDraft field
    GQL-->>Cycle: PR list with draft status
    
    Cycle->>Cycle: Detect issues & block reasons (including is-draft)
    
    alt Undraft phase
        Cycle->>Cycle: Filter: eligible except for is-draft
        Cycle->>GQL: undraftPr for eligible drafts
        GQL-->>Cycle: Undraft results
        Cycle->>Store: Update PR cache (isDraft=false)
        Cycle->>Cycle: Re-compute merge candidates
    end
    
    Cycle->>MergeSys: Proceed with merge phase
    MergeSys-->>Cycle: Merge outcomes
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A draft once hidden in the night,
Now ready shines with verdant light!
The undraft phase hops through the queue,
Eligibility blooms—CI passing true! 🌿✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: draft PRs by default and auto-undraft functionality in pr-patrol. It directly reflects the primary objectives of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/keen-wilbur

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link

vercel bot commented Mar 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
longterm-wiki-agent3 Error Error Mar 6, 2026 2:27am

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@crux/commands/pr.ts`:
- Around line 650-656: The current filter in the crux pr ready path removes
'ci-pending' from eligibility.blockReasons, allowing PRs to be marked ready
while CI is still running; restore CI as a blocker by removing 'ci-pending' from
the exclusion list in the blockReasons filtering logic (leave only 'is-draft'
excluded) so that checkMergeEligibility(prNode).blockReasons still contains
'ci-pending' unless checks are green; update the code around the force check and
the blockReasons assignment that references eligibility.blockReasons to match
the PR Patrol auto-undraft behavior.
- Around line 622-635: The code currently treats a malformed --pr as falsy and
silently falls back to branch autodetection; change the logic around
options.pr/parseInt so that when options.pr is provided but parseInt yields NaN
you return a user-facing error instead of falling back. Specifically, validate
the parsed value (prNum) using Number.isInteger or !Number.isNaN after parseInt
on options.pr and, if invalid, return an error output/exitCode rather than
running currentBranch()/githubApi; keep the existing branch-autodetect behavior
only when options.pr is undefined or empty.

In `@crux/pr-patrol/index.ts`:
- Around line 1388-1406: The dry-run path only logs "Would undraft" but doesn't
simulate removal of the 'is-draft' block, so findMergeCandidates(...) still sees
the PR as blocked; update the dry-run branch in the loop over draftCandidates to
mirror the real undraft outcome by either adding candidate.number to
undraftedNumbers when config.dryRun is true or by creating the same updated
object used later (removing 'is-draft') so that the subsequent
findMergeCandidates/mergeCandidates logic treats the PR as eligible; touch the
loop that calls undraftPr and the undraftedNumbers set (and keep the existing
undraftPr call in non-dry runs) so dry-run merges are reported exactly like a
real run.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cd65095a-ef91-4c4a-9eea-e9b6ab0383f9

📥 Commits

Reviewing files that changed from the base of the PR and between 6920988 and c44a509.

📒 Files selected for processing (3)
  • crux/commands/pr.ts
  • crux/pr-patrol/index.test.ts
  • crux/pr-patrol/index.ts

- Validate --pr option: return error on malformed values instead of
  silently falling back to branch autodetection
- Keep ci-pending as a blocker for `crux pr ready` to match PR Patrol
  auto-undraft behavior (only is-draft is filtered out)
- Simulate undraft in dry-run mode so merge phase also reports what
  would happen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

✅ CodeRabbit Security Gate

No unresolved Critical or Major CodeRabbit findings. Check passes.

How to resolve: Mark each CodeRabbit thread as resolved in the "Files changed" tab, or add the coderabbit-security-ok label if the findings are false positives. See #1649.

@OAGr OAGr merged commit 1fac8c5 into main Mar 6, 2026
14 of 17 checks passed
@OAGr OAGr deleted the claude/keen-wilbur branch March 6, 2026 02:37
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