Skip to content

fix(skills): pr-review-fixer gh-missing fallback - #503

Open
chiptus wants to merge 29 commits into
mainfrom
fix/pr-review-fixer-gh-fallback
Open

chiptus wants to merge 29 commits into
mainfrom
fix/pr-review-fixer-gh-fallback

Conversation

@chiptus

@chiptus chiptus commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Split off from #498, which had this bundled unrelated to the triage-labels/git-conventions docs work there.

pr-review-fixer hard-depended on the gh CLI, which isn't installed in remote/cloud sessions (GitHub access there goes through mcp__github__* tools instead) — confirmed by a real /pr-review-fixer failure. Adds a gh-availability check and an MCP-based fallback path for fetch/resolve/reply, disclosed to its own gh-missing.md (only loaded when gh turns out to be missing) rather than inlined for every reader.

Verification

  • In a session without the gh CLI, /pr-review-fixer now checks command -v gh first and fetches/resolves/replies via mcp__github__* tools instead of failing on command not found — reproduced live against this repo's own PR docs(agents): triage groups, git conventions #498.
  • In a session with gh, the original script-based path is unchanged.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd


Generated by Claude Code

Documents the five canonical triage-role labels as a mutually-exclusive
Linear label group, separates lifecycle markers (agent:wip/agent:pr/epic)
from that group, and consolidates branch-naming + commit/PR title format
into docs/git-conventions.md, linked from CLAUDE.md and autonomic-issues.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
Reorders git-conventions.md so the shared <type> is defined once, before
its first use; front-loads the CLAUDE.md pointer's trigger word; and adds
the missing label-group setup step to the autonomic pipeline's setup
checklist (single source of truth, referenced from triage-labels.md).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
New user-invoked skill that runs setup-matt-pocock-skills to pick this
repo's issue tracker (and its triage labels/domain docs), then reuses
that same tracker choice to scaffold docs/agents/autonomic-issues.md
from a GitHub- or Linear-shaped template — never asking the tracker
question twice.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
Replaces the two lifecycle labels with a single `agent` label whose
stage is read off the issue's native Linear status (In Progress while
claimed, In Review once the PR is open) instead of a second label.
Retired agent:wip/agent:pr in Linear (team UPL) and migrated the one
live issue carrying agent:pr (UPL-7, open PR #463) to
the new scheme. Also updates the setup-chiptus-env Linear template to
match; the GitHub template is unchanged since GitHub issues have no
native per-issue status to borrow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
…arity

Removes a leftover "PR-side label" mention in autonomic-issues.md now
that GitHub PRs carry no mirrored label. Adds a note to the
setup-chiptus-env Linear template (not the repo docs, which are
tracker-specific) explaining that GitHub's native PR state
(draft/ready/merged/closed) already parities Linear's issue status, so
future setups shouldn't invent a matching status label on the PR side.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
The PR-cap paragraph claimed counting stayed correct "even if the label
is forgotten" — true under the old agent:pr-only count, false now that
the count requires both --label agent and --status "In Review" together
(a forgotten label does drop the issue from the count; this is
intentional, since it's what lets a maintainer's own manually-opened PR
skip the cap). Also corrects issue-tracker.md's `issues update --state`
to the actual verified CLI flag, `--status`, which is what the new
claim/PR-review steps already used correctly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
setup-chiptus-env now checks for setup-matt-pocock-skills before
invoking it, installing the mattpocock/skills set via `npx skills`
when missing, instead of assuming it's already there. Also adds a step
to redirect domain docs (CONTEXT.md, ADRs) to an external folder for
repos that can't keep them in-repo (e.g. Portainer, where architecture/
customer docs must stay out of the public repo) — rewriting
docs/agents/domain.md's pointer rather than touching
setup-matt-pocock-skills' own templates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
… docs

Generalizes the external-docs step from just CONTEXT.md/ADRs to the
entire docs/agents/ folder (issue tracker, triage labels, autonomic
pipeline, domain consumer rules), matching the Portainer pattern: the
external root mirrors the in-repo layout exactly, so the docs' own
mutual cross-references need no rewriting — only CLAUDE.md/AGENTS.md's
entry pointers and the Routine prompts need to resolve a .git/-local
pointer file to the external root. Also flags the real gap this
creates for cloud Routine firings, which work off a fresh clone with
no access to this machine's .git/ contents.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
…only

An env var (e.g. AGENTS_DOCS_REPO) holding a separate docs repo's git
URL is now the default pointer mechanism, since it's settable in a
Routine's own environment_variables and so actually solves the cloud-
portability gap the .git/-local file couldn't. The .git/ file stays as
a lighter option for a solo local setup with no Routines involved, but
the skill now asks the user to choose explicitly between the two
rather than defaulting silently, since the choice decides whether the
autonomic pipeline can read the docs at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
…nsumers

CLAUDE.md's pointers stay plain ("See docs/agents/X.md", no conditional
phrasing) since it's always read locally regardless of where docs live
and per-pointer resolution text would duplicate the same logic at every
call site. Instead, step 3 now has the skill grep for whichever
mattpocock skills actually read CONTEXT.md/docs/adr/docs/agents
directly (domain-modeling, triage, code-review, etc.) and prepend the
external-docs check to each of those, plus the two Routine prompts —
the actual code paths that need to know, once, in one place per file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
autonomic-issues-github.md and autonomic-issues-linear.md were ~90%
identical (triage bar, quality gates, guardrails, notifications, both
routine prompts verbatim) with only the label/status mechanism, CLI
commands, and a few paragraphs differing per tracker — real
duplication of a single source of truth. Merged into one
autonomic-issues.md with the differing paragraphs wrapped in
<!-- tracker:github --> / <!-- tracker:linear --> marker pairs,
positioned right next to their counterpart; filling the template is
now "delete the blocks for the tracker you didn't pick."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
… fragments

The interleaved-marker design didn't scale: every section grew another
block per tracker, so a third tracker would mean editing every section
of an already-written file. Replaces it with a skeleton
(autonomic-issues.md, 100% tracker-invariant prose) plus small
per-tracker fragment files (tracker-github.md, tracker-linear.md) that
each supply the same five named slots (INTRO, SHARED_STATE,
INTAKE_QUERY, FIX_FIRING_STEPS, SETUP_ITEMS). Adding a tracker is now
"write one new fragment file against these five slots" — the skeleton
never changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
The Setup checklist's items 3-4 lived in the skeleton after the
fragment-supplied items 1-2, relying on markdown list continuation
across a template substitution boundary — fragile in general, and
prettier's markdown reflow already collapsed it into one broken
paragraph on the prior commit. SETUP_ITEMS now owns the whole 1-4 list
in each fragment (2 short duplicated lines) instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
…l table

Both prior designs (interleaved markers, then skeleton+fragments) kept
duplicating full paragraphs per tracker when only a handful of facts
actually differ: how "claimed"/"in review" are represented, how
priority works, how a PR declares its issue link. Rewrites the whole
doc in tracker-agnostic language (triage rubric, quality gates,
guardrails, bail/fail handling, notifications, routine prompts never
mention a tracker) referring back to one small "Tracker specifics"
table for the load-bearing facts only — not a CLI reference, which the
agent already gets from the tracker's own usage/--help. Adding a
tracker is now one new table column, not a new file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
GitHub and Linear are columns in the table, not rows; a new tracker
adds a column. Matches the wording already used in SKILL.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
Missed applying the earlier agent-label-plus-native-state decision to
GitHub's own column: it still described the old agent:wip -> agent:pr
swap. A GitHub PR's own draft/ready-for-review/merged state already
tells you claimed vs in-review once a PR exists, same reasoning as
Linear's native status — so GitHub gets one `agent` label too, applied
at claim and never swapped. Updated the two callers that assumed a
literal marker-move action (Fix firing step 6, the manual-PR
coexistence note) to describe the inferred state instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
The "don't add a matching status label on the GitHub PR side" note was
sitting in the Linear cell even though its subject is GitHub's own PR
state; moved to the GitHub cell (referencing the Linear cell for
contrast) instead of being explained from the other tracker's row.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
…s missing

The skill's fetch/resolve/reply steps hard-depended on the gh CLI,
which isn't installed in this remote session (GitHub access here goes
through mcp__github__* tools instead) — confirmed by the failed
fetch-review-threads.sh run. Adds an explicit gh-availability check at
the top of Phase 1 and an MCP-based path alongside each gh-dependent
step (fetch via pull_request_read, resolve via resolve_review_thread,
reply via add_reply_to_pull_request_comment / add_issue_comment) that
reconstructs the same data shape, so the rest of the skill is
unaffected by which path ran.

Note: this file is npx skills-managed (mattpocock/skills) — a future
bare reinstall would overwrite this fix back out.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
Linear's mutual-exclusivity feature kept the five canonical triage-role
labels enforced structurally, but nothing said what covers that on
GitHub, which has no equivalent group feature. Adds a table row and a
setup-checklist clause: GitHub relies on the triage skill's own
discipline (remove any other triage-role label before applying a new
one) instead of the tracker enforcing it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
…r's grouped look

Confirmed via linearis that Linear's own label names stay plain
(ready-for-agent, not triage/ready-for-agent) — the grouped display
comes from each label's parent pointing at the triage group label,
which Linear's UI renders hierarchically. GitHub has nothing
equivalent, so the closest substitute is naming the five labels with
a literal triage/ prefix. Documented in the Tracker specifics table
(with the Linear cell clarifying the contrast) and suggested as a
default during setup-matt-pocock-skills' own label-naming question.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
- Disclosed step 3's external-docs mechanics (pointer options, layout,
  the grep-and-patch recipe for consumer skills) into a new
  external-docs.md, reached only on the "external" branch most repos
  never take, instead of sitting inline in the main procedural flow
  every reader sees.
- Trimmed a duplicated explanation in the Tracker specifics table: the
  GitHub "Lifecycle labels" row restated the draft/ready/merged
  mapping the "Claimed / in review" row above it already gives: now
  points back at it instead.
- Fixed a stale "the templates generate" (plural, left over from the
  since-collapsed multi-file design).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
This session iterated the autonomic-issues.md template through four
different shapes reactively; worth a slower discussion session before
more incremental edits. Captures the open questions (tracker-table
generality, external-docs relocation being unvalidated, npx skills
unverified, the triage/ prefix suggestion being unvalidated) rather
than restating the diffs, which live in this branch's commit history.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
Split out to #499, since it still needs a discussion
pass before it's done (see that PR's handoff doc) and shouldn't hold
up these settled repo-docs changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
The previous fix wrapped the fetch script in "gh available: run ...",
but that used the !`command` auto-exec markdown syntax, which the
harness pre-executes unconditionally at skill-load time -- before the
model ever reads the conditional prose around it. That's exactly what
the reported /pr-review-fixer failure showed: the script still ran
(and failed on gh: command not found) despite the branch text saying
to check first. Removes the auto-exec syntax so the agent runs the
check and the script itself via the Bash tool, where the branch can
actually take effect.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
…ts own file

Per review feedback on PR #498: the "gh missing" branch (Phase 1's MCP
fetch recipe, Phase 4's resolve/reply mechanics) was inline in every
reader's path even though only some sessions need it. Split into
gh-missing.md, pointed to from Phase 1 and Phase 4 only where the gh
CLI turns out to be unavailable -- same progressive-disclosure move
already applied to setup-chiptus-env.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
This branch keeps only the pr-review-fixer gh-fallback fix, unrelated
to the triage-labels/git-conventions docs work on
docs/triage-labels-git-conventions / PR #498. The settled repo docs
stay there instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
Copilot AI lite review requested due to automatic review settings September 16, 2026 06:53
@vercel

vercel Bot commented Sep 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
upline Ready Ready Preview Sep 16, 2026 8:08am UTC

chiptus pushed a commit that referenced this pull request Sep 16, 2026
Split out to #503, unrelated to this branch's
triage-labels/git-conventions docs work.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd
Per Copilot review on PR #498 (posted after the file had already moved
here): allowed-tools grants no git command, only "command -v gh" and
the GitHub MCP calls, so "owner/repo from the git remote" was an
instruction the skill has no permission to carry out. Points at the
session's own repo context instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HFNqcr5d2EN6T6TkTc8WBd

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved findings block reliable PR discovery and MCP review-thread handling.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds an MCP fallback for pr-review-fixer when the gh CLI is unavailable.

Changes:

  • Detects gh availability and preserves the existing CLI path.
  • Documents MCP-based fetching, resolving, and replying.
File summaries
File Summary and findings
.agents/skills/pr-review-fixer/SKILL.md Adds fallback routing. Moderate (1 vote): the fallback cannot discover the owner, repository, and PR number without additional lookup support or required inputs.
.agents/skills/pr-review-fixer/gh-missing.md Documents the MCP workflow. Moderate (1 vote): no supported PR-number discovery path. Critical (1 vote): returned comment data and IDs do not match the review-thread shape required by later phases, including line 15.
Review details

Suppressed comments (3)

.agents/skills/pr-review-fixer/SKILL.md:10

  • The fallback cannot reliably identify the PR it is supposed to read. pull_request_read needs an owner/repo and PR number, but this skill's allowlist only permits command -v gh (not git remote, branch inspection, or a GitHub lookup). gh-missing.md then tells the agent to derive those values from the current branch, so a normal /pr-review-fixer invocation with no PR number cannot reach Phase 1. Allow the needed lookup tool(s), or require the caller to provide owner/repo/number before invoking the fallback.
allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/fetch-review-threads.sh) Bash(${CLAUDE_SKILL_DIR}/scripts/resolve-thread.sh *) Bash(gh pr comment *) Bash(command -v gh) mcp__github__pull_request_read mcp__github__resolve_review_thread mcp__github__add_reply_to_pull_request_comment mcp__github__add_issue_comment

.agents/skills/pr-review-fixer/gh-missing.md:16

  • Phase 4 requires comments[].html_url to derive the numeric parent comment ID, but Phase 1's fallback contract only preserves author and body for each comment. If the agent follows this normalization, inline replies have no parent ID and add_reply_to_pull_request_comment cannot be called. Explicitly retain html_url (or the numeric comment ID) in the Phase 1 shape.

- `method: get_review_comments` → review threads. Each has `id` (the GraphQL

.agents/skills/pr-review-fixer/gh-missing.md:11

  • Unlike the gh pr view script, this fallback has no way to determine the current PR number: a git remote only supplies owner/repo, while pull_request_read requires a pullNumber, and no PR lookup or branch-to-PR mapping is provided. A normal invocation that supplies only the current branch therefore cannot make the first MCP call. Add a supported PR-number discovery path (or require and document the PR number as input) before using this fallback.
Reconstruct the same `{threads, reviews, issueComments}` shape from
`mcp__github__pull_request_read`. This skill's `allowed-tools` grants no git
command, so don't try to derive owner/repo/PR number by shelling out — use
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +13 to +17
- `method: get_review_comments` → review threads. Each has `id` (the GraphQL
thread node ID — this is what `resolve_review_thread` below needs, keep it),
`is_resolved`, `path`, `line`, and `comments[]` with `author`/`body`. Keep
only `is_resolved == false` — the tool doesn't filter this for you the way
the script's `jq` does.
@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown

Playwright test results

passed  65 passed

Details

stats  65 tests across 21 suites
duration  1 minute, 19 seconds
commit  36a6b3a

The "reads {threads, reviews, issueComments} the same way" sentence
was stated once in SKILL.md's Phase 1 already, ahead of the pointer
into gh-missing.md, so repeating it there was redundant.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01776GRzBiT1RkWHD7vyctrp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants