| name | review-issue |
| description | Evaluate a GitHub issue against workspace principles and ADRs before work begins. Records findings in progress.md and best-effort posts them as a comment on the issue. |
Review Issue
Usage
/review-issue <issue-number>
Overview
Evaluate an issue before work begins. Checks scope, principle alignment, ADR
relevance, repo placement, and dependencies. Records findings in progress.md
(the canonical record) and best-effort posts them as a comment on the issue —
does not modify the issue body. See Posting behavior below.
Lifecycle position: review-issue → plan-task → review-plan → implement → review-code
This skill evaluates the issue itself (is it well-scoped? in the right
repo? conflicting with ADRs?). For evaluating an implementation plan, use
plan-task. For evaluating a completed PR, use review-code.
Posting behavior: GitHub posting is best-effort. The progress.md
entry (step 7) is the canonical record, written and committed first. Step 8
posts a comment for human visibility on GitHub, but skips silently when no
gh auth is present (e.g., container dispatch per
#532). A skipped
post does not change the phase status — the skill reports complete as
long as the progress.md entry was committed.
The best-effort guarantee covers the write path only. The read path
remains an auth dependency: step 1's gh issue view <N> (and the step 7a.1
owning-repo probe) need at least a read token to fetch the issue body the
review is built from. With no read auth those calls fail before any
progress.md entry can be written, so the "persist-first ⇒ always complete"
guarantee holds only when a read token is present. A read-only token (the
common container case) satisfies the read path while still tripping the
write-path 403 the post handles above.
Host-injected read context (zero container auth, #552).
The read dependency disappears entirely when the host fetches the issue body
and passes it to the dispatcher via
dispatch_subagent.sh --context-file <path>. The
dispatcher splices the body into the handoff under an
## Injected GitHub context heading; this phase then reads that injected section
instead of running gh issue view, satisfying the read path with no GitHub
auth inside the container. --context-file is composable with --skill, so the
auto entry-type and model still apply. When the injected section is present,
prefer it over step 1's gh issue view — the host has already fetched the
canonical body. Caveat: the injected context is the issue/PR body only —
it omits the labels, assignees, comments, and linked-PR fields that step 1's
gh issue view --json … would otherwise surface. Review from the body; if a
specific check needs that metadata, note its absence rather than assuming it.
Precondition: invoke from the owning repo's cwd. Issue numbers are
scoped per-repo (rolker/ros2_agent_workspace#42 and
rolker/unh_marine_autonomy#42 are different issues). Steps 1 and 8
(gh issue view <N> and gh issue comment <N>) resolve the repo via
the current directory's origin — so cd into the repo that owns the
issue before invoking /review-issue <N>. From the wrong cwd the
skill will either fail loudly (NotFound) or silently query/comment
on a colliding-number issue in the wrong repo. Step 7's
owning-repo probe creates the right worktree for progress.md even if
cwd is mismatched, but the view step (and any best-effort comment in
step 8) will already have hit the wrong repo by then. If you don't know
which repo owns <N>, use step 7a.1's probe pattern up front (probe workspace, then project
repos under layers/main/*/src/*) and cd to the match before
invoking. Cwd-independent owning-repo resolution is tracked as
#478 —
until that lands, the precondition is load-bearing.
Steps
1. Read the issue
gh issue view <N> --json title,body,labels,assignees,milestone,comments,url
If the handoff carries an ## Injected GitHub context section (the host
passed dispatch_subagent.sh --context-file, #552),
read that section instead — it is the host-fetched issue body, and this dispatch
has no GitHub read auth to run gh issue view.
Identify:
- What is being proposed?
- Which repo does this affect? (workspace infra, or a project repo?)
- Is there a linked PR or existing work?
2. Load governance context
Read the evaluation criteria:
.agent/knowledge/principles_review_guide.md — principle quick reference,
ADR applicability, and consequences map
Read the governance docs:
docs/PRINCIPLES.md — workspace principles
docs/decisions/*.md — ADR titles (read full text only for triggered ADRs)
If the issue targets a project repo, also check:
- The project repo's
PRINCIPLES.md
.agent/project_knowledge/ if available (symlink to manifest repo's .agents/workspace-context/)
3. Assess scope
- Well-scoped? Can this be completed in a single PR? If not, should it
be broken into sub-issues?
- Right repo? Does this change belong in the workspace repo or a project
repo? Check the workspace vs. project separation principle.
- Dependencies? Does this depend on other open issues? Will other issues
need to wait for this one?
4. Evaluate principle alignment
For each relevant principle, assess whether the proposed change aligns:
| Principle | Status | Notes |
|---|
| ... | OK / Watch / Action needed | Specific observation |
Statuses:
- OK — No concerns
- Watch — Worth noting but not blocking
- Action needed — Should be addressed before or during implementation
Skip principles that clearly don't apply.
5. Check ADR applicability
Using the ADR applicability table from the review guide, identify which ADRs
are triggered by this type of change. For each triggered ADR:
- Does the issue description account for the ADR's requirements?
- If not, note what may be missing.
6. Check consequences
Using the consequences map: if this issue changes something in the "If you
change..." column, note the corresponding "Also update..." items. These
should be part of the issue scope or flagged as follow-up work.
7. Persist to progress.md
Append a ## Issue Review entry to
.agent/work-plans/issue-<N>/progress.md so the timeline reflects
that the issue has been governance-reviewed before plan-task starts.
Per ADR-0013.
This is the canonical record — it is written and committed here,
before the best-effort GitHub post (step 8), so the phase status
never depends on whether the post succeeds.
7a. Locate-or-create the owning worktree. review-issue is
typically the first skill in the lifecycle, so a worktree may not
exist yet. Since progress.md commits cannot land on a protected
default branch, this step creates a worktree on demand:
7a.1. Resolve the owning repo first. Issue numbers can collide
across the workspace repo and project repos (e.g., workspace #42 is
a different issue from unh_echoboats_project11#42), so the issue
number alone is not enough to identify a worktree.
gh issue view <N> without --repo resolves against the current
directory's origin (don't pass --repo <owner/repo> — that's the
value we're trying to determine). Probe in order:
- Workspace first — from the workspace root,
gh issue view <N> --json repository --jq '.repository.nameWithOwner'
succeeds if <N> is a workspace issue.
- Project repos next — if the workspace lookup returns
NotFound, try each project repo under layers/main/*/src/*:
(cd <path> && gh issue view <N> --json repository --jq '.repository.nameWithOwner').
First success wins; record both the path and owner/repo.
- No match — stop with an error; the issue may live in a repo
not currently checked out, or
<N> is wrong.
This mirrors plan-task step 4's cwd-based gh issue view <N>
pattern.
7a.2. Check $WORKTREE_ISSUE and the worktree's repo slug. If
$WORKTREE_ISSUE matches <N> and the worktree's repo slug
matches the owning repo's short slug, you're already in the right
worktree — skip to step 7b. If only the number matches, treat it as a
miss and continue to step 7a.3 (you're in the wrong-repo worktree for
a colliding number).
worktree_enter.sh exports $WORKTREE_ROOT, $WORKTREE_TYPE, and
$WORKTREE_ISSUE — but not the repo slug. Derive it from
$WORKTREE_ROOT's basename:
if [ -z "${WORKTREE_ROOT:-}" ]; then
WORKTREE_SLUG=""
else
WT_BASENAME=$(basename "$WORKTREE_ROOT")
case "$WT_BASENAME" in
issue-workspace-*) WORKTREE_SLUG="workspace" ;;
issue-*) WORKTREE_SLUG="${WT_BASENAME#issue-}"; WORKTREE_SLUG="${WORKTREE_SLUG%-*}" ;;
*) WORKTREE_SLUG="" ;;
esac
fi
Compare $WORKTREE_SLUG against the owning repo. Step 7a.1 returned
owner/repo form; the slug-relevant comparison depends on type:
- Workspace issue — the
owner/repo from step 7a.1 matches the
workspace repo's nameWithOwner (e.g., rolker/ros2_agent_workspace).
Match iff WORKTREE_SLUG == "workspace".
- Project-repo issue — the
owner/repo from step 7a.1 matches a
project repo (e.g., rolker/unh_marine_autonomy). Match iff
WORKTREE_SLUG equals the repo-name portion (unh_marine_autonomy).
7a.3. If not, check whether a worktree for the issue already
exists. Use an anchored, repo-aware pattern so neighbouring issue
numbers (e.g. 4700 for <N>=470) and unrelated repo worktrees don't
match:
ls -d "/path/to/workspace/.workspace-worktrees/issue-workspace-<N>" 2>/dev/null
ls -d "/path/to/workspace/layers/worktrees/issue-<repo-slug>-<N>" 2>/dev/null
Or grep worktree_list.sh output with a numeric boundary:
.agent/scripts/worktree_list.sh \
| grep -E "issue-(workspace|<repo-slug>)-<N>($|[^0-9])"
7a.4. If a worktree exists, source it to enter:
source .agent/scripts/worktree_enter.sh --issue <N> [--repo-slug <slug>]
(Or cd to the path directly when sourcing isn't possible.) When the
issue number collides across repos, pass --repo-slug <slug> to
disambiguate (see WORKTREE_GUIDE.md).
7a.5. If neither: determine worktree type from the owning repo
(workspace for issues in the workspace repo, layer for project-repo
issues — same logic as plan-task step 4). Create the worktree:
worktree_create.sh does NOT open a draft PR when invoked without
--plan-file; only the worktree + branch are created. plan-task then
commits the plan to the branch but, by default, does not open a PR
(local-first, #492) — a draft PR follows only if plan-task is run with
--draft-pr (or the worktree was created with --plan-file); otherwise
the /run-issue orchestrator opens the real PR at the end.
7b. Append the entry. Create the parent directory if needed
(review-issue typically runs before plan-task, so
.agent/work-plans/issue-<N>/ may not exist yet):
mkdir -p .agent/work-plans/issue-<N>
Then use frontmatter for a new file:
---
issue: <N>
---
Append:
## Issue Review
**Status**: complete
**When**: <YYYY-MM-DD HH:MM ±HH:MM>
**By**: <agent name> (<model>)
**Issue**: #<N>
**Comment**: (best-effort post follows this entry; not recorded inline)
**Scope verdict**: <well-scoped | needs-splitting | needs-more-detail>
### Actions
- [ ] <each "Action needed" principle finding>
- [ ] <each "Recommendation" worth following up on>
If the scope verdict is well-scoped and there were no Action-needed
principle findings and no Recommendations, set ### Actions to a
single checkbox item (keeping ADR-0013's checkbox-list schema
uniform for downstream consumers):
- [ ] No actions — issue is plan-task-ready. If there are
Recommendations but no Action-needed findings, list the Recommendations
under ### Actions so the timeline preserves them — they're follow-up
candidates downstream consumers should be able to see.
Commit:
git -C <worktree-path> add .agent/work-plans/issue-<N>/progress.md
git -C <worktree-path> \
-c user.name="$AGENT_NAME" \
-c user.email="$AGENT_EMAIL" \
commit -m "progress: issue review for #<N>"
The per-invocation -c overrides are required by
AGENTS.md § Agent Commit Identity
because the skill instructions run in fresh subshells where the
set_git_identity_env.sh exports may not be in scope; without them
check_pr_authors.py (CI mechanism C, #468)
will reject the commit.
The branch (feature/issue-<N>) now exists with one commit. If the
user decides not to proceed (and so plan-task never runs), they can
remove the worktree + branch via
.agent/scripts/worktree_remove.sh --issue <N>.
8. Post findings as a comment (best-effort)
With the canonical record committed (step 7), post the review as a
comment on the issue for human visibility. Do not modify the issue
body. This step is best-effort: it skips silently when no gh auth
is present (e.g., container dispatch per
#532), and a
skipped or failed post does not change the phase status — it stays
complete as long as step 7 committed the entry.
## Review
### Scope Assessment
**Well-scoped?** Yes/No — [explanation]
**Right repo?** Yes/No — [explanation]
**Dependencies**: [list or "none identified"]
### Principle Alignment
| Principle | Status | Notes |
|---|---|---|
| ... | ... | ... |
### ADR Applicability
| ADR | Triggered | Notes |
|---|---|---|
| ... | ... | ... |
### Consequences
- [items that should be updated as part of this work]
### Recommendations
- [specific suggestions, if any]
---
**Authored-By**: `$AGENT_NAME`
**Model**: `$AGENT_MODEL`
Use --body-file for the comment (not --body). The post is best-effort:
gate it on gh auth so it skips cleanly when none is present, and treat a
failed post itself as non-fatal. The auth gate is necessary but not
sufficient — a read-only token (e.g. the container's GH_TOKEN) makes
gh auth status --active pass, yet gh issue comment then fails with a 403.
Because the comment is wrapped (|| echo …) the phase still completes; the
progress.md entry written in step 7 is the record regardless of post outcome.
BODY_FILE=$(mktemp /tmp/gh_body.XXXXXX.md)
cat << 'COMMENT_EOF' > "$BODY_FILE"
[review content]
COMMENT_EOF
if gh auth status --active 2>/dev/null; then
gh issue comment <N> --body-file "$BODY_FILE" \
|| echo "[review-issue] Comment post failed (e.g. read-only token / 403) — continuing; progress.md is the record."
else
echo "[review-issue] No GitHub auth — skipping comment post (progress.md is the record)."
fi
rm "$BODY_FILE"
Next step
Lifecycle: Issue Review → plan-task
Hand off to the next phase in a fresh-context sub-agent — independence
between lifecycle steps is what makes the timeline trustworthy (a reviewer who
shares the author's context inherits their blind spots). Use the dispatcher:
.agent/scripts/dispatch_subagent.sh --mode in-process --issue <N> --skill plan-task
The sub-agent reads the last ## Issue Review entry in
.agent/work-plans/issue-<N>/progress.md for your output, and writes its own
## Plan Authored entry when done.
No auto-chaining (Scope E): this skill never dispatches the next phase itself —
the host orchestrator (/run-issue,
#492) drives,
pausing at user checkpoints. This step only emits this prompt and its
progress.md entry.
Guidelines
- Comment, don't edit — the issue body is the authoritative spec. Review
findings are advisory input posted as a comment with their own timestamp.
- Be actionable — "Watch: might be too large for a single PR" is useful.
"Looks fine" without specifics is not.
- Don't block unnecessarily — most issues are fine. Flag genuine concerns,
not hypothetical risks.
- Note gaps, don't fill them — if the issue is missing detail, note what's
missing. Don't rewrite the issue.