| name | implement-suggestion |
| description | Implements review-comment suggestions across one or more PRs. Multi-PR mode (default when $ARGUMENTS contains PR URLs; empty $ARGUMENTS auto-detects the active PR) per PR: resolves a worktree, fetches every actionable comment from both human teammates AND AI code-review bots (claude[bot], coderabbitai[bot], …), validates each through /critical + /confidence, builds a structured suggestion-pack, and dispatches a worker subagent that applies each approved change as its own commit, pushes to the existing branch, and resolves the addressed review thread — so every handled comment ends up resolved and the PR is left clean. Fast-lane for mechanical edits, standard-lane via aw-planner for architectural changes. Free-text mode applies a single pasted suggestion in the current directory. Triggers on "implement suggestion", "apply review comments", "address PR feedback", "implement reviewer feedback", "fix PR comments", "/implement-suggestion". With --watch, loops the apply on a single PR — waiting for new review-bot comments after each push and re-applying until the reviewers go quiet (max 5 iterations); this is the loop /create-pr dispatches post-push.
|
| disable-model-invocation | true |
| argument-hint | [<pr-url>|#<n>] [--critical] [--watch] |
| license | MIT |
| allowed-tools | Bash(gh *) Bash(git *) Bash(gw *) Read Edit Write Glob Grep Skill |
| metadata | {"author":"mthines","version":"2.4.0","workflow_type":"orchestrator","architecture":"parse/resolve/fetch/classify/validate/pack/handoff(fast|standard)/commit-per-comment+resolve-thread/report","composes":["critical","confidence"],"agents":{"planner":"aw-planner"},"tags":["pr","review","comments","github","worktree","autonomous","validation","fast-lane","confidence-gated"]} |
Implement Suggestion
Take reviewer suggestions on one or more pull requests, validate each through
adversarial review (/critical) and a confidence gate (/confidence), then
hand off a structured suggestion-pack to a worker subagent that applies
the approved changes inside the PR's worktree and pushes them — without
opening a new PR.
This skill is a thin orchestrator. The heavy reasoning lives in
/critical and /confidence. Per-PR worktree isolation comes from gw.
Plan authoring for architectural changes is delegated to aw-planner.
The mechanical apply / commit / push runs inside a dispatched worker.
Source of truth. This SKILL.md is a thin index. Detailed procedures live
in rules/*.md, literal artefacts in templates/*.md. Load only what the
current phase asks for.
Mode Detection
Parse $ARGUMENTS once, in this order. First match wins.
| # | Signal in $ARGUMENTS | Mode |
|---|
| 1 | One or more github.com/<owner>/<repo>/pull/<n> URLs (with or without #discussion_r…) | multi-pr |
| 2 | One bare PR number (#123) and the current directory is a PR worktree | multi-pr (n=1) |
| 3 | Free-text prose, pasted comment body, or non-PR URL | free-text |
| 4 | Empty and the current branch has an open PR (auto-detected via gh pr view) | multi-pr (active PR) |
| 5 | Empty and no active PR for the current branch | Prompt the user |
Active PR auto-detection (rule #4): when $ARGUMENTS is empty, run
gh pr view --json number,url,state,headRefName,headRefOid,isDraft (no number =
current branch). If it returns a PR in state OPEN, treat as multi-pr with
that single PR. Print one line before continuing:
Mode: multi-pr Active PR: dash0/console#1234 (current branch)
If the detection finds a MERGED or CLOSED PR, refuse to proceed and ask
the user to confirm explicitly.
--watch modifier (orthogonal to mode): if $ARGUMENTS contains --watch,
the run loops the single-pass on one PR until the review bots go quiet (max 5
iterations). It requires exactly one PR (multi-pr with n=1, or the active PR).
Refuse --watch with more than one PR or in free-text mode. Full procedure in
rules/watch-mode.md — load it now when --watch is set.
Full parsing rules live in rules/input-parsing.md.
State the detected mode and inputs in one line before continuing. Example:
Mode: multi-pr PRs: dash0/console#1234, dash0/console#1278
Architecture
Phase 0: Input parse → PR tuples (or free-text string)
Phase 1: Worktree resolution → gw checkout <pr> per PR; verify clean state
Phase 2: Comment fetch → per-PR ledger (parallel across PRs)
Phase 3: Classify → actionable / nit / discussion / praise
Phase 4: Two-gate validation → /critical → /confidence per actionable comment
Phase 5: Build suggestion-pack → .agent/<branch>/suggestion-pack.md per PR
Phase 6: Handoff (lane-split) → worker: commit-per-comment, push, resolve thread
├── Fast-lane (simple): dispatch worker subagent with pack
└── Standard-lane (complex): aw-planner → plan.md → worker subagent
Phase 7: Report → per-PR table: applied / surfaced / skipped / resolved
Per-PR work in Phases 1–6 runs in parallel across PRs (one message,
multiple Agent / Bash dispatches). Per-comment work in Phase 4 runs
sequentially within a PR so /critical and /confidence see consistent
state.
Multi-PR Workflow
Phase 0 — Input parse
Apply rules/input-parsing.md. Output a
deduplicated list of {owner, repo, prNumber, commentFilter} tuples. Validate
each via gh pr view --json number,state,headRefName,headRefOid,isDraft and
refuse to proceed for any PR in state MERGED or CLOSED.
Phase 1 — Worktree resolution
Apply rules/worktree-resolution.md. For
each PR:
gw checkout <pr-url-or-number> (preferred).
- Verify
git status --porcelain is empty and HEAD == headRefOid.
- Record the absolute worktree path.
Hard rule: never auto-stash, never auto-rebase, never operate in the user's
main worktree.
Phase 2 — Comment fetch
Apply rules/comment-fetching.md. Per PR,
fetch in parallel:
gh api repos/<owner>/<repo>/pulls/<n>/reviews
gh api repos/<owner>/<repo>/pulls/<n>/comments
gh api repos/<owner>/<repo>/issues/<n>/comments
Build one ledger per PR. Include comments from both human teammates and
AI code-review bots (claude[bot], coderabbitai[bot], etc.) — only the
current user's own comments and noise bots (dependabot, github-actions)
are filtered. Exclude resolved threads. Honor commentFilter from Phase 0
if present.
Phase 3 — Classify
Before tagging — read prior lessons. Load the
implement-suggestion-lessons lessons from LoreKit so accumulated
misclassifications and gate mis-calibrations bias this run before they repeat.
Full contract in rules/self-improvement-loop.md#read-lessons-phase-3:
# Narrow-to-broad; silent no-op if memory.* not connected.
memory.list { scope: "repo::{owner}/{repo}", tags: ["loop::implement-suggestion-lessons"], limit: 50 }
memory.list { scope: "global", tags: ["loop::implement-suggestion-lessons"], limit: 50 }
Match each lesson's trigger-context (reviewer source + topic) against the
ledger. Matches are advisory inputs to Phase 3 tagging and the Phase 4 gates
— they never relax the two-gate requirement or a hard rule.
Tag every comment per rules/comment-classification.md:
| Tag | Treatment |
|---|
actionable | Carries to Phase 4 (validation gates). |
nit | Carries to Phase 4; higher confidence bar applies. |
discussion | Skipped; surfaced in Phase 7 report. |
question | Skipped; surfaced. |
praise | Dropped silently. |
Phase 4 — Two-gate validation
For each actionable / nit comment, run gates in this order — full
procedure in rules/validation-gates.md:
Skill("critical", "<mode>") — code if the comment proposes a
specific edit (suggestion block, file:line reference), analysis
otherwise. Capture findings (hidden assumptions, blast radius, steelman).
Skill("confidence", "analysis") — score the change in context of the
comment, surrounding code, and /critical's findings.
Decision matrix:
/confidence score | nit comment | actionable comment |
|---|
| ≥ 90% | apply | apply |
| 80%–89% | surface | apply |
| 70%–79% | surface | surface |
| < 70% | skip | skip |
A /critical finding tagged Must-fix overrides the matrix and
forces surface, even at ≥ 90%. This is non-removable — /critical's
Must-fix calls are designed to catch what /confidence cannot.
(/critical emits Must-fix / Should-fix / Nice-to-have; only Must-fix
overrides — the lower buckets are recorded in the pack.)
Phase 5 — Build suggestion-pack
Write .agent/<branch>/suggestion-pack.md per PR using
templates/suggestion-pack.md. The pack is
the contract handed to the worker — it lists every apply-tagged change
with file:line, the proposed edit, the comment author and ID, and the
/critical + /confidence evidence.
The pack is plan.md-shaped intentionally: it carries an Acceptance
Criteria section (one criterion per applied change) and a "Mode:
existing-pr" header that signals to consumers "commit and push to the
existing branch; do not open a new PR".
Phase 6 — Handoff (lane-split)
Lane is picked from the pack's complexity signals:
| Lane | Trigger | Plan authored by |
|---|
| Fast-lane | All apply changes are single-file mechanical edits AND no /critical finding raised Must-fix; AND total file count ≤ 3 | Skill writes the pack directly |
| Standard-lane | Any change spans ≥ 2 files; OR /critical raised Must-fix on any change; OR ≥ 4 files affected across the PR | Skill dispatches aw-planner with the pack as plan.md seed |
For each PR, dispatch the worker subagent (one message, parallel across PRs):
Agent(
description: "Apply suggestion-pack to PR #<n>",
subagent_type: "general-purpose",
prompt: <the "Worker prompt template" from rules/handoff.md, filled in — the template is inline in that file; no external prompt file exists>
)
Full dispatch contract and prompt template:
rules/handoff.md#worker-prompt-template.
The worker makes one commit per applied comment (each message cites that
comment's @author + URL), pushes once after all commits, then resolves
each addressed review thread — posting a brief Addressed in <sha> reply,
then resolveReviewThread. This leaves a clean one-to-one trail (commit →
resolved comment) and a PR where every handled comment is resolved; only
surface / skip comments stay open. issues / review-summary comments
have no resolvable thread and are reported as such. Full contract in
rules/handoff.md#worker-prompt-template.
The main agent does not edit files in Phase 6. All applies / commits /
pushes / thread resolutions happen inside the worker subagent so the loud loop
(test runs, push retries) stays out of the main context.
Phase 7 — Report
Emit one summary table:
## Implement-Suggestion Results
| PR | Branch | Lane | Applied | Surfaced | Skipped | Commits | Pushed | Resolved |
|----|--------|------|---------|----------|---------|---------|--------|----------|
| dash0/console#1234 | fix/foo | fast | 3 | 1 | 2 | abc1234, def5678, 9a0bcde | ✓ | 3/3 |
| dash0/console#1278 | feat/bar | standard | 0 | 2 | 1 | — | — | 0/0 |
Commits lists one SHA per applied comment (commit-per-comment). Resolved
is <threads-resolved>/<applied-with-a-thread> — comments whose fix landed and
whose thread was resolved, over the applied comments that had a resolvable
thread (issues / review-summary comments have none and are excluded from
the denominator).
Then per PR list:
- Applied — comment ID, author, one-line summary, commit SHA, thread status
(resolved / no-thread).
- Surfaced (needs user) — comment, gate score,
/critical finding if any.
Thread left open.
- Skipped — comment, reason. Thread left open.
After the report — write lessons. Run the retrospective and capture any
durable lesson from the run (a Phase 3 misclassification, a Phase 4 gate
mis-score, a Phase 6 lane misfire, an apply that needed a scoped-check fix).
Full contract, tier classification, and the applied-lesson UPDATE rule in
rules/self-improvement-loop.md#write-lessons:
# Classify scope (universal → global; project-bound → repo::{owner}/{repo}), dedup, then write.
# Silent no-op if memory.* not connected.
memory.search { q: "<lesson keywords>", scopes: ["repo::{owner}/{repo}", "global"], limit: 10 }
memory.write { scope: "<global | repo::{owner}/{repo}>", key: "implement-suggestion-lessons::<slug>", value: "<body>", tags: ["loop::implement-suggestion-lessons", "source::<trigger>"], source_agent: "implement-suggestion", trigger: "<end-of-run | watch-reflag | user-override>" }
A lesson reaching seen_count >= 3 is promotion-eligible — surface the
scope-appropriate one-liner (/create-skill diagnose implement-suggestion for
global; a repo rule via docs for repo::). Never promote silently.
See rules/self-improvement-loop.md#lesson-promotion.
Outcome emit
After writing lessons — emit outcome records to review-outcomes AND write
comment-relevance memories. These are two separate, parallel writes per processed
comment.
Write 1 — review-outcomes bus (existing): appends to the review-outcomes LoreKit bus
(tag loop::review-outcomes) — one fingerprinted outcome record per comment.
This feeds the shared candidate/outcome bus consumed by
agents/shared/rules/outcome-learning.md at promotion time.
Write 2 — reviewer-comment-relevance memory (new): writes a relevance signal
to the reviewer-comment-relevance LoreKit bucket (tag
loop::reviewer-comment-relevance) for each processed comment.
This is the primary write path that makes reviewer and pr-reviewer continuously
better on this specific repository — each resolved or dismissed comment updates
the per-repo signal so future reviews suppress recurring noise and reinforce
reliably-resolved patterns.
See agents/shared/rules/comment-relevance-memory.md § Write
for the full record schema and scope-classification rules.
Reuse the per-comment /critical + /confidence result already in context — do not recompute.
Derive verdict / relevance from the Phase 4 decision matrix:
| Phase 4 outcome | verdict (review-outcomes) | relevance (comment-relevance) | resolution_method |
|---|
| Gate cleared, patch landed | applied | relevant | fixed |
/critical Must-fix raised OR /confidence below threshold | rejected-at-validation | not-relevant | wont-fix |
| Gate cleared but scoped out / deferred | deferred | weak-not-relevant | ignored-at-merge |
| Patch landed then reverted after CI failure | reverted-after-ci | not-relevant | wont-fix |
For applied verdicts, also check the comment thread for explicit "won't fix"
language from the author (won't fix, by design, intentional, nwf, n/a,
👎 reaction):
gh api repos/$REPO/pulls/$PR_NUMBER/comments \
--jq ".[] | select(.in_reply_to_id == $COMMENT_ID) | .body" \
| grep -iE "(won.?t fix|wont fix|by design|intentional|nwf|not going to|n/a)"
If a decline phrase is found, override relevance: not-relevant, resolution_method: wont-fix.
Infer source from the comment author login per the heuristic in review-outcomes.md.
# Write 1 — review-outcomes bus (unchanged).
# Append-only, non-blocking. Silent no-op if LoreKit not connected.
memory.write { scope: "<global | repo::{owner}/{repo}>", key: "review-outcomes::<fingerprint-slug>", value: "<outcome record>", tags: ["loop::review-outcomes", "source::<verdict>"], source_agent: "implement-suggestion", trigger: "outcome-emit" }
# Write 2 — comment-relevance memory (new).
# Deduplicate first; UPDATE seen_count if exists, ADD otherwise.
# Scope: almost always repo::{owner}/{repo}; global only for universal patterns.
memory.search { q: "<fingerprint slug>", scopes: ["repo::{owner}/{repo}", "global"], limit: 5 }
memory.write { scope: "repo::{owner}/{repo}", key: "reviewer-comment-relevance::<fingerprint>", value: "<relevance record>", tags: ["loop::reviewer-comment-relevance", "source::<resolution_method>"], source_agent: "implement-suggestion", trigger: "outcome-emit" }
LoreKit owns storage server-side and dedups on write.
The reviewer-comment-relevance bucket has a 180-day default TTL, refreshed on each sighting.
The review-outcomes bucket has a 30-day volatile TTL.
Both writes are append-only and non-blocking — they MUST NOT gate or delay the Phase 7 report.
If LoreKit's memory.* tools are not connected, both steps are silent no-ops; the apply flow is unaffected.
Watch Workflow (--watch)
A loop wrapper around the multi-PR single-pass, scoped to one PR. Each iteration:
waits for new review activity, runs Phases 1–7 over comments newer than the last
processed timestamp, advances the baseline, and repeats until the reviewers go
quiet or the iteration cap (default 5) is hit. /create-pr dispatches this as a
background subagent post-push so a new PR auto-converges on its bot feedback.
Full loop, the poll-for-new-activity snippet, parameters (--max-iters,
--interval), the per-iteration report, and watch-specific hard rules live in
rules/watch-mode.md.
Inside each --watch iteration, after the per-iteration Phase 7 report:
run the outcome-emit step (see above) for every comment processed in that iteration.
This includes both the review-outcomes bus write AND the reviewer-comment-relevance memory write.
This ensures that reverted-after-ci verdicts and relevance signals are captured at the end of the
iteration where CI failure is detected.
Both emits are append-only and non-blocking in each iteration.
Free-text Workflow
When $ARGUMENTS is prose, a pasted comment, or a single comment permalink
without a PR worktree context:
- Run Phase 4 (two-gate validation) once.
- Apply in the current working directory if the gate clears, otherwise
surface to the user.
- Do not commit or push — the user is driving manually.
Free-text mode preserves v1 behaviour: a quick "implement this colleague
suggestion I just pasted" path with no PR plumbing.
Self-Improvement
/implement-suggestion gets better across runs through a two-tier lessons loop
(fast episodic tier + gated promotion), identical in shape to
autonomous-workflow and fix-bug. It reads implement-suggestion-lessons at Phase 3
and writes at Phase 7 (and on a --watch re-flag), keyed by reviewer source
- comment topic. Lessons are advisory — they bias classification, gate
calibration, and lane selection, but never relax a gate or a hard rule. A lesson
that recurs (
seen_count >= 3) is promotion-eligible to a permanent skill guard
via /create-skill diagnose implement-suggestion.
The loop owns implement-suggestion's own decision phases only; the
standard-lane aw-planner dispatch already contributes to aw-lessons for the
planning of architectural changes — this loop does not duplicate that.
LoreKit (the lorekit-memory skill's memory.* tools) is an optional
companion: if those tools are not connected the whole loop is a silent no-op.
Full contract:
rules/self-improvement-loop.md.
In addition to writing implement-suggestion-lessons, this skill is a producer of two LoreKit buckets:
review-outcomes shared candidate/outcome bus (see agents/shared/rules/review-outcomes.md) — volatile 30-day TTL; consumed by outcome-learning.md at promotion time only.
reviewer-comment-relevance memory bucket (see agents/shared/rules/comment-relevance-memory.md) — durable 180-day TTL; consumed by reviewer and pr-reviewer at the start of every review run (Step 0.7 / Step 1.0) to suppress recurring noise and reinforce reliably-resolved patterns. This is the primary mechanism by which the reviewer pipeline continuously improves on a specific repository.
At Phase 7 (and per-iteration inside --watch), one fingerprinted record is written to each bucket
per processed comment.
Both writes are append-only and non-blocking.
The reviewers consume review-outcomes only at promotion/consolidation time; they consume reviewer-comment-relevance on every review run.
Hard Rules
- Never push with
--force or --force-with-lease without explicit user approval.
- Never push with
--no-verify or bypass hooks.
- Never apply a change whose
/critical review surfaced a Must-fix finding without surfacing first.
- Never auto-rebase a PR branch — surface and stop.
- Never delete or weaken tests or types to make a suggestion fit.
- One commit per applied comment. Each addressed comment is its own commit
(message citing that comment) so
git log maps one-to-one to resolved threads.
- Resolve every addressed thread; leave the rest open. After a comment's fix
lands and is pushed, the worker replies with the commit SHA and calls
resolveReviewThread. surface / skip comments — and any comment whose
commit did not land — stay open. Never resolve a thread whose fix is not on the remote.
- Worktree isolation. Each PR gets its own
gw worktree.
- Resolved threads are skipped at fetch time.
- Main agent does not apply / commit / push in multi-PR mode. Workers do.
- No new PRs. Push to existing branches only — multi-PR mode never invokes
gh pr create.
Prerequisites
| Dependency | Purpose | Required? |
|---|
gh CLI (authenticated) | Fetch comments, resolve PR metadata | Yes for multi-PR |
gw CLI | Worktree creation and reuse per PR | Strongly recommended |
git | Commit + push | Yes |
/critical skill | Adversarial pre-mortem per comment | Yes |
/confidence skill | Gate scoring per comment | Yes |
aw-planner agent | Standard-lane plan authoring | Required when standard-lane fires |
lorekit-memory skill (LoreKit memory.* tools) | implement-suggestion-lessons self-improvement loop (read Phase 3, write Phase 7 / watch re-flag); reviewer-comment-relevance per-repo relevance memory (write Phase 7 / watch); review-outcomes bus (write Phase 7 / watch) | Optional — all three loops are silent no-ops if not connected |
If gh is missing in multi-PR mode, stop and tell the user to install it.
Rules
Templates:
Key Principles
- Analyse once, hand off mechanically. The skill does every
/critical + /confidence call.
Workers only apply pre-validated changes.
- Two-gate validation is non-skippable. Every actionable comment goes through both.
/critical runs first so its findings feed /confidence.
- Lane split mirrors
/fix-bug. Fast-lane skips aw-planner when changes are mechanical.
Standard-lane invokes aw-planner when the pack proposes architectural moves.
- Existing PR is the contract. This skill never opens a new PR. The worker pushes to the
existing branch and Phase 7's report links to the existing PR URL.
- Parallelize per PR, sequentialize per comment. PR-level work fans out; per-PR validation
stays linear so the gates see consistent state.
- Learn across runs, but only advisory.
implement-suggestion-lessons (read Phase 3, write Phase 7)
biases classification, gate calibration, and lane selection from prior runs — but a lesson
never relaxes a gate or a hard rule. Only a recurrence-proven lesson (seen_count >= 3) earns
a confidence-gated, user-approved change to the skill's source.