Status: proposed in PR #635
Scope: convert new same-repository development branches into bounded Draft PR coordination records
The Auto Draft PR Steward keeps the branch as the working surface while making active work visible through a Draft pull request early in its lifecycle.
It does not decide that work is correct, ready for review, or mergeable.
new managed branch
-> steward observes trusted repository metadata
-> Draft PR shell
-> contributor/agent keeps pushing to the same branch
-> normal CI/evidence/review
-> explicit ready-for-review decision
-> normal integration decision
-> source-branch cleanup after durable provenance
A branch remains a Git branch after the Draft PR is created. The PR is the coordination and review record, not a replacement for the branch.
The workflow is .github/workflows/auto-draft-pr.yml.
It runs only from trusted default-branch workflow code:
main;main push trigger;workflow_dispatch entry point that could select arbitrary branch code.Permissions are intentionally narrow:
permissions:
contents: read
pull-requests: write
The workflow never checks out a candidate branch. Candidate code, issue text, PR text, and commit messages are not executed by the privileged steward.
The repository must permit its GITHUB_TOKEN to create pull requests.
If repository Actions policy denies that capability, the steward fails with an explicit 403 diagnostic. Do not work around that boundary with a personal access token or higher-authority secret. Either enable the repository-native capability deliberately or leave automatic PR creation disabled.
The behavior is configured in config/auto-draft-pr.json.
Important controls:
enabled — global kill switch;not_before — rollout cutoff so historical orphan refs are not reopened;managed_prefixes — branch families eligible for Draft PR creation;excluded_prefixes — evidence, scratch, bot, Jules, or hold lanes that stay
outside this automation;infer_stacked_base — prefer the nearest open-PR ancestor for stacked work;max_creations_per_run — mutation flood cap;max_branch_pages / max_pr_pages — fail-closed pagination bounds;max_untracked_branches_per_run — bound commit-metadata inspection;max_candidate_evaluations_per_run — bound ancestry/base evaluation;max_open_pr_heads_for_stack_inference — bound stacked-base comparisons;minimum_rate_limit_remaining — shared GitHub API reserve.The policy loader rejects empty prefixes, overlapping managed/excluded prefixes, non-positive scan bounds, invalid pagination limits, and unsupported schema versions. The checked-in policy keeps a 1500-request core API reserve.
For each run:
main, excluded prefixes, and every branch that already has any
same-repository PR history;main;No direct branch merge is performed.
Generated PRs are always Draft and state that they are coordination records.
The generated title/body:
# in branch/base ref text so a branch name cannot manufacture an
issue reference or accidental issue-closing instruction;PRs created by the repository GITHUB_TOKEN do not themselves trigger a new
downstream workflow cascade. A later ordinary branch push or human
review-state action provides the normal PR check surface.
Each successful steward invocation can render a versioned evidence bundle without
making any additional GitHub API calls. The contract is
schemas/auto-draft-pr-steward-report-v0.1.schema.json.
The trusted workflow writes:
steward-report.json — machine-readable state for automation, CLI, and future
GUI surfaces;steward-report.md — human-readable summary of the same result.Both files are uploaded as a short-retention GitHub Actions artifact named
auto-draft-pr-steward-<run-id> for 14 days.
The report records:
head_moved and pr_already_exists.Artifact publication uses the result already held in memory. It does not rescan branches, reread PR history, or otherwise spend additional GitHub API budget.
A report is evidence about what the steward did, not evidence that the generated
change is correct or mergeable. In particular, the report permanently states
merge: false and auto_merge: false in its authority block.
A maintainer with a read-capable GitHub token can inspect the planned actions without creating PRs:
GITHUB_TOKEN=... python tools/auto_draft_pr_steward.py \
--repo MSKazemi/idkmesh \
--policy config/auto-draft-pr.json \
--dry-run \
--output-json /tmp/idkmesh-steward.json \
--output-md /tmp/idkmesh-steward.md
The JSON output includes:
merge_authorized: false.Check, in order:
not_before;minimum_rate_limit_remaining;head_moved or other skip;GITHUB_TOKEN PR creation.The steward selects the nearest open same-repository PR head that is an ancestor
of the candidate. If none is an ancestor, main is used.
Base inference is coordination assistance only. A wrong or obsolete stack should be corrected explicitly in the PR before review.
That is intentional when the branch predates the rollout cutoff or already has
closed/merged PR history. Historical cleanup remains governed by
docs/planning/BRANCH_CONVERGENCE_POLICY.md; the steward does not reopen old
work merely to reduce the branch count.
No mutation occurred. The run is intentionally fail-closed. Wait for the shared GitHub API budget to recover rather than lowering the threshold during a busy automation period.
The steward may:
It may not:
All normal exact-head CI, evidence, independent review, branch protection, and integration rules remain in force.
The deterministic regression suite is
tests/test_auto_draft_pr_steward.py. It covers the repository policy contract,
historical/excluded refs, stacked-base inference, fork-name collisions, generated
ref sanitization, title bounds, duplicate-creation races, exact-head movement,
API-budget blocking, oldest-first ordering, the per-run mutation cap, workflow
artifact bounds, policy/provenance digests, report rendering, output-path
collision safety, and instance validation against the published report schema.
Use the repository’s normal PR gate for integration evidence.