| name | gh-issue |
| description | Strict issue-to-PR lifecycle for GitHub issues in the Plumb Rust workspace. Investigates, plans, implements (TDD), verifies, reviews, creates PR, waits for CI, and cleans up. Supports worktree isolation and durable run state for session resumption. |
| user_invocable | true |
/gh-issue — GitHub issue delivery lifecycle for Plumb
Strict delivery lifecycle that drives one or more GitHub issues from
investigation through merged PR against aram-devdocs/plumb.
Use /gh-runbook first when the source is a runbook spec that still
needs to be fanned out into grouped issues.
Usage
/gh-issue 17 # Single issue
/gh-issue 17 18 19 # Multiple related issues (single PR)
/gh-issue 17 --worktree # Isolated worktree
/gh-issue 17 --resume # Resume after compaction
State management
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py init-run <primary> <slug> [--issues 17 18 19] [--worktree]
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --phase implementing
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --pr 42
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --review spec pass
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --commit abc1234
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py validate-resume <primary> <slug>
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py poll-pr <primary> <slug>
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py cleanup-worktree <primary> <slug>
Phases
investigating > planning > bootstrapped > implementing > verifying > reviewing > pr > waiting-ci > cleanup > done
Lifecycle
Phase 1 — investigating
- Fetch issue(s):
gh issue view <N> --repo aram-devdocs/plumb --json number,title,body,labels,milestone,assignees,comments
- Identify affected crates, layers, and files via codebase exploration.
- Read the root
AGENTS.md, the scoped AGENTS.md for any crate touched (crates/plumb-*/AGENTS.md), and .agents/rules/ — the Plumb invariants live there.
- Check for blocking dependencies (issues referenced in body).
- If the issue came from a runbook spec, re-read the spec in
docs/runbooks/ to confirm batch and gate context.
- Initialize run state:
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py init-run <primary> <slug> --issues <N> [<M>...]
Phase 2 — planning
- Determine issue type from labels:
feat, fix, refactor, test, chore, docs, perf, ci, build, style, revert.
- Branch name:
codex/<primary>-<type>-<slug> (e.g., codex/17-feat-cdp-chromium-launch).
- If this invocation addresses multiple issues (
/gh-issue 66 67 69 70 …), the intent is one bundled PR closing every issue. Read .agents/rules/dispatch-strategy.md to confirm the bundle is appropriate for these tickets (same crate, pattern similarity, combined diff under ~400 LOC). If bundling is a mistake, stop and re-dispatch per ticket.
- Identify:
- Target crate(s) and files.
- Required subagent(s) from Plumb's set:
01-implementer, 08-rule-author (for new rules), 09-mcp-tool-author (for MCP tools), 10-quick-fix (for trivial fixes).
- Review gates — always
02-spec-reviewer → 03-code-quality-reviewer → 05-architecture-validator → 04-test-runner. Add 06-security-auditor in parallel when the change touches plumb-cdp, plumb-mcp, URL handling, or dependency-graph changes.
- Whether a local
/gh-review --local-diff main...HEAD pass is required before opening the PR.
- Whether user-facing docs need a humanizer pass (any PR touching
docs/src/**).
- Write the plan to
.agents/runs/gh-issue/<primary>-<slug>/plan.md using .agents/skills/gh-issue/assets/plan-template.md.
- Present the plan to the user for approval before proceeding.
Phase 3 — bootstrapped
- Create the branch from
main:
git checkout main && git pull origin main
git checkout -b <branch-name>
- If
--worktree flag: use EnterWorktree instead.
- Update run state:
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --phase bootstrapped --branch <branch-name>
Phase 4 — implementing
- Dispatch the right subagent per the plan:
01-implementer for general work.
08-rule-author for new rule + golden test + doc.
09-mcp-tool-author for new MCP tool + protocol test.
10-quick-fix only for trivial, single-commit work — otherwise use 01-implementer.
- TDD: write the failing test first (golden snapshot, integration test, or unit test), then the minimum code to pass.
- Honor Plumb invariants (
.agents/rules/):
- Layer discipline —
plumb-core depends on nothing internal; unsafe only in plumb-cdp with // SAFETY:; println!/eprintln! only in plumb-cli.
- Determinism — no
SystemTime::now/Instant::now in plumb-core; IndexMap for observable output; sort key (rule_id, viewport, selector, dom_order).
- No
unwrap/expect/panic! in library crates; thiserror-derived enums for errors; anyhow only in plumb-cli::main.
- No
todo!/unimplemented!/dbg!.
- Commit atomically with Conventional Commits:
<type>(<scope>): <description>.
- Update run state after each commit:
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --commit <sha>
Phase 5 — verifying
- Run the full gate:
just validate
Or the narrow equivalent while iterating:
cargo fmt --all -- --check && \
cargo clippy --workspace --all-targets --all-features -- -D warnings && \
cargo nextest run --workspace --all-features
- If failures: dispatch
07-debugger to diagnose, then 01-implementer to fix, then loop back to verifying.
- If docs under
docs/src/** changed: run the humanizer skill before review.
- Update run state:
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --phase verifying
Phase 6 — reviewing
Sequential gates (review-gate-guard hook enforces the order):
02-spec-reviewer — does the change satisfy the spec exactly, nothing more?
- Record:
--review spec pass (or fail).
03-code-quality-reviewer — idiomatic Rust, error shapes, lint suppression justified? Only runs after spec passes.
- Record:
--review quality pass.
05-architecture-validator — layering, unsafe boundary, deny-lints respected?
- Record:
--review architecture pass.
04-test-runner — runs just validate + just determinism-check + cargo deny check.
- Record:
--review test pass.
06-security-auditor (parallel with any of the above when triggered) — required when the change touches plumb-cdp, plumb-mcp, URL/config parsing, or deps.
- Record:
--review security pass or not_required.
/gh-review local dry-run — mirror of .github/workflows/claude-code-review.yml:
python3 .agents/skills/gh-review/scripts/gh_review.py --local-diff main...HEAD
If the PR already exists, prefer --pr <number>. Any blocker finding sends you back to implementing.
Phase 7 — pr
Non-optional. The session does NOT end until a PR exists, unless it's a worktree-only dry run explicitly requested by the user.
- Push the branch:
git push -u origin <branch-name>
- Render the PR body from
.agents/skills/gh-issue/assets/pr-body-template.md — it mirrors .github/PULL_REQUEST_TEMPLATE.md section-for-section. Fill every section; do not collapse.
- Create the PR targeting
main:
gh pr create --repo aram-devdocs/plumb --base main \
--title "<type>(<scope>): <description>" \
--body-file /tmp/<primary>-pr-body.md
- Update run state:
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --phase pr --pr <number>
Phase 8 — waiting-ci
Non-optional. The session loops here until BOTH of these converge:
- Every CI check on the PR is green (
gh pr checks <PR>).
- The Claude code reviewer (
.github/workflows/claude-code-review.yml) has posted a comment on the PR ending with Verdict: APPROVE.
Until both hold, the session does not advance. No exceptions.
Loop:
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py poll-pr <primary> <slug>
The poller reports one of:
ci: pass, review: approve — proceed to cleanup.
ci: pass, review: request_changes — read the review comment, dispatch 01-implementer (or 07-debugger if the issue is unclear) to fix, push, loop.
ci: pass, review: block — same as above; treat as a hard stop that needs a fix before advancing.
ci: pass, review: pending — review hasn't posted yet; wait and re-poll (respect GitHub rate limits — sleep ≥ 60s between polls).
ci: fail — read failure details, dispatch 07-debugger → 01-implementer, push the fix, loop.
Fix loop (applies to both CI failures and review REQUEST_CHANGES/BLOCK verdicts):
- Read the failure / review comment:
gh pr checks <PR> --repo aram-devdocs/plumb --fail-fast
gh pr view <PR> --repo aram-devdocs/plumb --json comments --jq '.comments[-1].body'
- Dispatch
07-debugger for root-cause diagnosis if the failure / feedback is non-obvious.
- Dispatch
01-implementer (or 10-quick-fix for trivial) with the fix scope.
- Push the fix:
git push origin <branch-name>
- Record the fix commit:
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py update-state <primary> <slug> --commit <sha>
- Re-poll. The Claude reviewer auto-triggers on every push; CI re-runs on every push.
Hard budget: if the loop runs > 10 iterations without converging, stop and surface to the user. Something deeper is wrong and needs human judgment.
When both converge: --phase cleanup.
Phase 9 — cleanup
- Update run state to
cleanup.
- If
--worktree: cleanup-worktree removes the worktree and runs git worktree prune.
- Return to
main in the primary checkout:
git checkout main && git pull origin main
Phase 10 — done
--phase done.
- Final report: PR URL, issues addressed, every review gate verdict, CI final state, Claude review verdict, any iteration count beyond 1.
Durable run state
Per invocation: .agents/runs/gh-issue/<primary>-<slug>/.
state.json
{
"primary": 17,
"issues": [17],
"slug": "cdp-chromium-launch",
"phase": "implementing",
"branch": "codex/17-feat-cdp-chromium-launch",
"pr": null,
"commits": ["abc1234"],
"reviews": {
"spec": "pass",
"quality": null,
"architecture": null,
"test": null,
"security": "not_required"
},
"worktree": false,
"created": "2026-04-23T22:00:00Z",
"updated": "2026-04-23T22:30:00Z"
}
plan.md
Written during planning from assets/plan-template.md. Covers: issue summary, acceptance criteria, affected crates, implementation approach, subagent dispatch plan, review gates, adjacent skill usage (/gh-runbook, /gh-review, humanizer).
Resuming after compaction
ls .agents/runs/gh-issue/
python3 .agents/skills/gh-issue/scripts/gh_issue_run.py validate-resume <primary> <slug>
Then read state.json and plan.md and resume from the recorded phase. The save-session Stop hook writes a per-session summary so context survives compaction.
Rules
- Branch MUST target
main. Plumb has no dev branch.
- Branch pattern:
codex/<primary>-<type>-<slug>.
- Commits use Conventional Commits — the
commit-msg lefthook validator enforces it.
- TDD is mandatory: test first, implementation second.
- Review gates are mandatory and sequential: spec → quality → architecture → test; security-auditor in parallel when triggered.
- Never bypass pre-commit or pre-push hooks — no
--no-verify.
- All implementation goes through subagents; the root orchestrator never edits
crates/*/src/*.rs directly (delegation-guard hook enforces this).
- Every state transition goes through
gh_issue_run.py.
See also: AGENTS.md, .agents/rules/, /gh-review, /gh-runbook, humanizer skill.