| name | auto-dev |
| description | Execute one tick of the autonomous issue-to-PR pipeline — triage open issues for readiness, draft implementation plans for maintainer approval, build the oldest approved issue into a PR, and address review feedback on the open automated PR. Designed for unattended scheduled runs (`scripts/auto-dev.sh`); also invocable interactively as "/auto-dev" or "run an auto-dev tick", and as "/auto-dev dry-run" for a read-only report of what a tick would do. Never merges PRs. State lives in `auto:*` GitHub labels. |
Auto-dev: one tick of the issue-to-PR pipeline
This skill automates the path from open issue to reviewed PR while keeping the maintainer in control of two gates: plan approval (nothing is built without an approved plan) and merge (the skill never merges — ever). It is designed to run unattended every 15–30 minutes; each invocation is one tick of a state machine, does the single highest-priority piece of work, and exits. "Waiting" (for a reply, an approval, a review, a merge) is simply what happens between ticks.
Invariants — read these first
- Never merge a PR. Not with
gh pr merge, not via the API, not by enabling auto-merge. Merging is exclusively the maintainer's act, and a merge is what unblocks the pipeline for the next issue.
- At most one automated PR in flight. While any auto-dev PR is open, no new issue gets built. Ticks spent in that state only advance the open PR.
- All runs happen under the maintainer's own GitHub identity, so authorship cannot distinguish this pipeline from the human. Every comment this skill posts MUST begin with the marker line
<!-- auto-dev --> (invisible in rendered Markdown). Classify comments into three buckets: pipeline (has the marker), third-party bot (author login ends in [bot] or app/ — e.g. coderabbitai, dependabot; CodeRabbit posts auto-enrichment boilerplate on issues), and human (everything else). Only human comments count as replies, answers, or approvals; third-party bot comments never satisfy "the human replied" and never gate-keep anything — read them for technical signal at most.
- Labels are the cross-run memory, and humans always win. If a human has changed an
auto:* label since the last tick (e.g. removed auto:ready, added auto:skip), respect the label as found — never "correct" it back.
- Never force-push, never push to
master directly, never run the release process, never create or delete labels, never close issues, never edit or delete human comments.
- Stay inside the repo's own conventions: pre-flight checks, documentation policy, and the PR template all come from the
create-pr skill and AGENTS.md, exactly as for human-driven work.
Invocation modes
- Scheduled (
scripts/auto-dev.sh): headless, in the dedicated clone, against the curated allowlist. The runner guarantees a clean tree on fresh master.
- Interactive (
/auto-dev in a Claude Code session): identical behavior, but under normal permission prompts and possibly in the maintainer's working checkout. A dirty working tree or non-master branch does NOT block the GitHub-only steps (1-reconcile, 3-triage) — it only blocks steps that touch the working tree (2's CI/feedback fixes, 4-build). If a working-tree step is what the tick needs and the tree is dirty, report that and stop rather than stashing or resetting anything.
- Dry run (
/auto-dev dry-run, or the user asks for a dry run): execute the full tick logic read-only. Gather all state, decide exactly what a live tick would do, and print it as the exit report with every action prefixed would: — but post no comments, change no labels, create no branches/commits/PRs, and push nothing. This is the recommended first test and is always safe to run.
Label state machine
| Label | Meaning | Who sets it |
|---|
(no auto:* label) | Not yet triaged by auto-dev | — |
auto:needs-info | Skill asked a clarifying question; waiting on a human reply | skill |
auto:planned | Skill posted an implementation plan; waiting on approval | skill |
auto:ready | Plan approved; eligible to build | skill (on detected approval) or human (directly) |
auto:in-progress | Being built / has an open automated PR | skill |
auto:skip | Opt-out — auto-dev never touches this issue | human |
Eligibility: all open issues, oldest first, EXCEPT issues labeled auto:skip, epic, question, wontfix, duplicate, or invalid. Pull requests are never triaged as issues.
The tick algorithm
Work through these steps in order. Execute the first step that has work, finish it, print the exit report, and stop. Do not fall through to later steps after completing one (exception: step 2 falls through to step 3 when the open PR needs nothing).
Step 0 — Preflight
gh auth status
gh repo view --json nameWithOwner
git status --porcelain
Gather the current state in parallel:
gh pr list --state open --json number,headRefName,title,reviewDecision,mergeable \
| jq '[.[] | select(.headRefName | startswith("auto/"))]'
gh issue list --state open --limit 200 \
--json number,title,labels,createdAt,updatedAt --search "sort:created-asc"
gh pr list --state closed --limit 10 --json number,headRefName,mergedAt,closedAt \
| jq '[.[] | select(.headRefName | startswith("auto/"))]'
If gh auth or repo resolution fails, print the failure in the exit report and stop — do not attempt repairs.
Step 1 — Reconcile finished work
For issues labeled auto:in-progress:
- PR merged (or issue closed by
Fixes #N): remove auto:in-progress. If the issue is somehow still open after its PR merged, comment (with marker) linking the merged PR and noting it may be closable — but leave closing to the human.
- PR closed without merging: treat as rejection of the approach. Remove
auto:in-progress, add auto:skip, and comment (with marker) that the PR was closed unmerged and the issue needs human direction before auto-dev will touch it again.
- No PR exists at all (a previous tick crashed between labeling and PR creation): treat the issue as
auto:ready in step 4 — its plan is already approved.
Step 2 — Advance the open automated PR
If an automated PR is open, this tick belongs to it.
Draft PR (a yielded partial build from step 4): resume the implementation first — finish the plan, run the full pre-flight, push, and mark it ready with gh pr ready. Only then does the review loop below apply.
Ready PR: run one round of the review loop. The maintainer's user-level coderabbit-review skill describes the same loop in more depth — follow it when it is available (it is not part of this repo, so scheduled runs may not have it); the essentials below stand alone:
- Fetch all four feedback surfaces: PR metadata + CI rollup, review summaries, inline review comments, and issue-style comments (
gh pr view, gh api .../pulls/N/reviews, .../pulls/N/comments, .../issues/N/comments).
- CI red? Fix CI first — check out the
auto/ branch, fix, run the repo pre-flight (bun run check), push.
- New feedback since the skill's last reply? A thread is unaddressed if its newest comment lacks the
<!-- auto-dev --> marker. Triage each item on its merits (CodeRabbit is not always right), fix valid items with focused commits (one logical fix per commit, conventional subjects), push, then reply to every thread — including ones you decline, with a one-sentence reason. Replies carry the marker.
- Human feedback outranks bot feedback. If a human reviewer and CodeRabbit conflict, follow the human and say so in the reply to the bot.
- Scope creep requested in review? Acknowledge in a reply, file a follow-up issue (it enters this same pipeline untriaged), link it, and keep the PR scoped.
- Nothing new (no new comments, CI green, all threads answered): the PR is waiting on review or merge. Print that in the exit report and fall through to step 3 (triage only) — never to step 4.
Step 3 — Triage pass (bounded)
Walk eligible open issues oldest→newest. Act on at most 5 issues per tick (count only issues where you actually post/relabel; skipped issues are free). For each issue, read the full thread, then branch on its current auto:* state:
- No
auto:* label — assess whether the issue contains enough to plan from (clear problem, scoped outcome, no unresolved design fork):
- Plannable → draft an implementation plan (format below), post it as a comment, add
auto:planned.
- Not plannable → post one comment asking the specific missing questions (numbered, concrete — not "please clarify"), add
auto:needs-info.
auto:needs-info — is there a human comment (no marker, not a third-party bot) newer than the skill's last marker comment?
- No → skip silently. This is the "already asked, no reply" rule.
- Yes → incorporate the reply. If it resolves the questions, draft and post the plan, swap label to
auto:planned. If it raises new ambiguity, ask the follow-up (stay auto:needs-info) — but if this would be the third unanswered round-trip, stop asking and leave a final note that the issue needs maintainer attention.
auto:planned — is there a human comment (not a third-party bot) newer than the plan?
- Approval (e.g. "approved", "LGTM", "go ahead", "yes do it", a 👍-only reply) → swap label to
auto:ready. "Approved, but change X" counts as approval: update the plan comment-thread with the revision first, then mark ready.
- Substantive feedback / objections → revise, post the updated plan (marker), stay
auto:planned.
- No reply → skip silently.
- The human adding
auto:ready directly is always approval, reply or not.
auto:ready / auto:in-progress — leave for steps 1 and 4.
Step 4 — Build (only if NO automated PR is open)
Take the oldest auto:ready issue (or a step-1 orphan). Then:
- Swap labels: remove
auto:ready, add auto:in-progress.
- Branch from fresh master:
git checkout master && git pull --ff-only && git checkout -b auto/issue-<N>-<short-slug>.
- Implement the approved plan as posted on the issue — the plan comment is the spec. Where reality diverges from the plan (an approach doesn't work, a file moved), prefer small sensible adaptation and document the deviation in the PR body; for a fundamental divergence, stop, comment on the issue explaining the blocker (marker), revert the label to
auto:planned, and exit.
- Follow the repo's documentation policy — docs updates ship in the same PR.
- Run the full pre-flight:
bun run check. All green before pushing.
- Create the PR with the create-pr skill (template, checklist, AI-disclosure section). The body must include
Fixes #<N>, the marker line, and a note that this PR was produced by the auto-dev pipeline from the approved plan.
- Comment on the issue (marker) linking the PR.
If the build cannot complete inside this tick's budget, push the WIP commits and open a draft PR (gh pr create --draft) before exiting — a bare pushed branch is invisible to the next tick, whose discovery queries only look at PRs and issues. The draft body still carries Fixes #<N> and the marker, plus a note that the build is incomplete and will be resumed. Never mark a PR ready for review (gh pr ready) while pre-flight checks fail.
Step 5 — Nothing to do
If no step had work: print "no work to be done" with the counts (open PRs awaiting human review/merge, issues awaiting replies, issues awaiting approval) and exit.
Plan comment format
<!-- auto-dev -->
## Proposed implementation plan
**Approach:** <2–4 sentences: what will change and why this approach>
**Changes:**
- `path/to/file.ts` — <what>
- <new files, tests, docs to update>
**Testing:** <unit tests to add/extend; manual verification if UI>
**Out of scope:** <explicitly excluded, if anything notable>
---
Reply with an approval ("approved", "LGTM", "go ahead") to queue this for implementation, reply with changes to revise the plan, or add the `auto:skip` label to opt this issue out of automation.
Plans follow the repo's "Implementation Planning" convention (plans live in the issue). Keep them honest about size — if an issue is too large to land as one reviewable PR, the plan should say so and propose the first slice only.
Question comment format
<!-- auto-dev -->
Before this can be planned for implementation, a few things need clarification:
1. <specific question>
2. <specific question>
---
Reply here and the next automation pass will pick it up, or add the `auto:skip` label to opt this issue out of automation.
Exit report
Every tick ends by printing a structured report to stdout (the runner appends it to the log):
auto-dev tick — <ISO timestamp>
step executed: <0-failed | 1-reconcile | 2-pr-advance | 3-triage | 4-build | 5-idle>
open auto PR: #<n> (<status>) | none
actions:
- #123: asked 2 clarifying questions → auto:needs-info
- #145: plan approved by reply → auto:ready
- PR #210: fixed 2 CodeRabbit findings, replied to 4 threads, pushed <sha>
blocked on human:
- PR #210 awaiting review/merge
- #145 ready to build once #210 merges
errors: <none | details>
What not to do
- Don't merge, approve, or enable auto-merge on any PR.
- Don't start a second build while an automated PR is open.
- Don't post a second question/plan when the previous one is still unanswered.
- Don't touch
auto:skip, epic, question, wontfix, duplicate, or invalid issues, and don't remove auto:skip ever.
- Don't apply or change non-
auto:* labels — categorization belongs to the triage-issues skill.
- Don't close issues, edit issue bodies, or modify human comments.
- Don't expand a PR's scope in response to review; file a follow-up issue instead.
- Don't bypass failing checks (
--no-verify, skipping tests) to get a PR out.
- Don't work around permission denials from the runner's allowlist — report them in the exit report so the allowlist can be tuned deliberately.