---
name: implement-issues
description: "Run one implementation tick on the current repo's ready-for-agent issues, then stop. Pick the oldest unassigned ready-for-agent issue, implement its agent brief in an isolated worktree, get tests and lint green, run /review-fix, and open a non-draft PR with \"Closes #N\", then stop. If the brief proves underspecified or the work can't go green, abort and demote the issue instead of shipping a guess. Never merges. Does one issue end-to-end per tick, so it composes with /loop for a recurring implementation loop (e.g. `/loop /implement-issues`, `/loop 1h /implement-issues`). GitHub-only (uses `gh`). The middle leg of the pipeline: process-issues -> implement-issues -> process-prs. Use when the user wants to implement ready-for-agent issues, turn triaged issues into pull requests, or set up a recurring AFK implementation agent."
---

# Implement issues (one tick)

One `ready-for-agent` issue implemented end-to-end per invocation, then stop.
Compose with `/loop` for recurrence (`/loop /implement-issues`,
`/loop 1h /implement-issues`); `/loop` owns pacing. Never schedule yourself.

This is the middle leg of the loop pipeline:

```
process-issues  ->  implement-issues  ->  process-prs
(ready-for-        (non-draft PR,         (review +
 agent issue)       Closes #N)             recommend-* verdict, you merge)
```

State derives entirely from GitHub (labels, assignees, branches, open PRs), so a
tick is idempotent: with no grabbable issue it costs one `gh issue list` and
exits.

## Rails

- **Never merge.** The PR is opened for review; merging stays the maintainer's
  hand (and `/process-prs`'s verdict is a recommendation, not an action).
- **Never ship a guess.** If the brief is underspecified or the work can't reach
  green, abort and demote (see below), never open a speculative PR.
- **The finalize gates are mandatory, not optional.** `/review-fix` and
  `/recommit` run on **every** change before the PR opens, whatever its size, and
  `/verify` runs whenever the change is behavioral and a smoke is practical. "It's
  a one-line / test-only / obviously-correct change" is **not** grounds to skip
  `/review-fix` or `/recommit`, and a manual diff read is **not** a substitute for
  `/review-fix`. That rationalization is exactly how unreviewed AI-slop lands in a
  PR. Skipping a gate that applies is a process violation; if one genuinely cannot
  run, say so explicitly in the report rather than silently dropping it.
- **Never take an issue owned by another loop.** Only unassigned issues are
  grabbable; assignment is the ownership signal.
- **Never touch clean-room / relicensing issues.** Those are owned by their own
  dispatcher and run under a protocol that forbids reading the prior
  implementation. This pass reads the brief and explores the codebase normally,
  which would contaminate such work. The unassigned-only rail keeps it out, but
  treat this as a hard boundary.
- **Every issue comment starts with a disclaimer:**
  `> *This was generated by AI during implementation.*`.

## 0. Preflight

- Abort if not a git repo, or if there is no GitHub remote. This skill is
  **GitHub-only** (`gh`, issues, pull requests).
- If the repo has no `ready-for-agent` label, there is nothing to do; exit.

## 1. Pick and claim one issue

Grabbable = `ready-for-agent` **and** unassigned **and** not owned by another
active loop **and** has no existing branch or open PR for it.

```bash
gh issue list --state open --label ready-for-agent \
  --json number,title,createdAt,assignees \
  --jq '[.[] | select((.assignees | length) == 0)] | sort_by(.createdAt) | .[0]'
```

(`gh issue list --assignee ""` does **not** filter to unassigned, so the
unassigned check lives in the `jq`.)

Take the **oldest** grabbable issue. If none, report and exit.

- The issue **must carry an agent brief** (the `triage` skill's `AGENT-BRIEF.md`
  contract). If it has `ready-for-agent` but no brief, that is a gate violation:
  comment, remove `ready-for-agent`, apply `needs-triage`, and stop. Do not
  implement from a bare title.
- **Claim it:** create the conventional branch in an isolated worktree with
  `git wt feat/<N>-slug` (or `fix/<N>-slug` per the issue's category; ignored
  files travel into the worktree), and assign the issue to yourself
  (`gh issue edit <N> --add-assignee @me`). The branch and the assignee are the
  claim, so a later tick or another loop skips it.

## 2. Implement and finalize

Work entirely in the worktree, treating the agent brief as the contract (the
issue body is context); run the steps below in order:

1. Implement the brief. Read code before changing it; touch only what the brief
   requires; respect any ADRs / `CONTEXT.md`.
2. Get the **full test suite and lint/typecheck green**.
3. Confirm **every acceptance criterion** in the brief is satisfied.
4. `/review-fix` to a clean round (reviewers -> fixes -> re-verify; stop on a
   clean round or on oscillation). Invoke the skill; a hand review of the diff
   does not count.
5. `/recommit` into a clean, logical commit sequence.
6. `/verify` whenever the change is behavioral and a smoke is practical (the
   skill picks the method per project type). This is the one conditional gate:
   skip it only when the change is non-behavioral (e.g. test-only or docs) or no
   smoke is practical, and note the reason in the report.

## 3. Open the PR

`/make-pr`: push and open a **non-draft** PR (the branch is already
conventional, so no `/make-branch` rename is needed), body `Closes #N`, assignee
the git user, and **no verdict label** (`/process-prs` applies that during its
independent review). `/make-pr` drafts PRs it opens autonomously by default, so
pass an **explicit ready (non-draft) request** to override that; otherwise the
PR lands as a draft and `/process-prs`'s non-draft queue never picks it up.
Record the PR url in the report and stop.

## 4. Abort and demote

If the brief proves underspecified mid-implementation, or the work cannot reach
green:

1. Remove the worktree and branch (releases the claim, leaves no cruft).
2. Unassign the issue (`gh issue edit <N> --remove-assignee @me`).
3. Post a disclaimer-prefixed comment naming the **specific** blocker (the
   ambiguous requirement, the failing behavior, what a human must decide).
4. **Demote** by swapping the labels with
   `gh issue edit <N> --remove-label ready-for-agent --add-label <state>`
   (GitHub labels are additive, so `ready-for-agent` must be removed explicitly).
   `<state>` is `needs-info` if it needs the reporter, or `ready-for-human` if it
   needs a maintainer decision or a human to get it green.

No PR. The demoted issue re-enters the pipeline rather than dying silently.

## Report

End with one line for `/loop`: the issue implemented and the PR url, the
abort + demotion, or "no unassigned ready-for-agent issue this tick." If a
finalize gate was skipped or could not run, note which and why alongside that
line.

## Composition

Consumes `/process-issues`'s `ready-for-agent` output and produces a PR that
`/process-prs` finalizes and verdicts. Three single-purpose passes, each
`/loop`-paced, none ever merging: triage, implement, finalize.
