name: spec-refine-github description: >- Use when a GitHub spec PR needs review and PR comments ingested into spec.md and qna.md: prepare comments.md from GitHub (with edit detection and qna.md placement rules), run spec-refine phases, commit spec.md and qna.md only (never comments.md), then push and reply on threads—or defer those writes to harness post-automation. Pair with spec-refine and spec-start for formats.
Cursor Agent Skills: prefer explicit @-style invocation; other tooling may ignore.
disable-model-invocation: true
spec-refine-github (PR comments into spec and Q&A, push updates)
Use this skill together with spec-refine (and spec-start for qna.md / spec.md grammar). This document adds GitHub + git + PR mechanics only. Do not duplicate the Phase 1–3 procedure in spec-refine/SKILL.md—after you prepare comments.md / qna.md from GitHub data, run that file’s phases in order on the resolved topic directory.
When a session only needs local planning files without GitHub, use spec-refine alone.
Relationship to spec-refine and spec-start-github
- Eligibility and ingest (this skill) — checkout PR head, confirm exactly one touched
docs/plans/YYYY-MM-DD-<topic>/tree, pull comments from GitHub, writecomments.mdand/or append###answers toqna.mdper the rules below. - Refine pass — follow
spec-refinethrough Phase 1 → Phase 2 → Phase 3 (including deleting emptycomments.mdwhen that skill says to). - Publish —
git addonly publishable paths,git commit; thengit pushand review-thread replies only when local mode (see Harness vs local). This skill overridesspec-refine’s default “documentation only / commit only if asked” for GitHub-bound runs: committing the topic’sspec.md/qna.mdafter a successful refine is in scope when this skill is invoked for a PR refresh.
If spec-start-github exists in the repo, treat its branch naming (agent/*-spec-*) and harness vs local language as hints for the same automation family—not as the only way to qualify a PR.
Harness vs local (mirror spec-start-github)
Primary signal: session or wrapper instructions.
| Mode | When | Agent must |
|---|---|---|
| Harness | Session or wrapper says post-automation owns git push and/or GitHub API writes (thread replies) |
After git commit, do not git push. Do not post review-thread replies via gh api. Emit a handoff: branch name, remote, git push suggestion, and copy-pastable gh api examples for thread replies (REST URLs, JSON bodies, thread / comment IDs). |
| Local | No such restriction | May git push the PR head branch. May post optional short replies on review threads (Step F). |
Harness authors may set an env var such as SPEC_REFINE_GITHUB_POST_SCRIPT_PUSHES=1 (or equivalent session wording) so ownership of pushes is explicit—session text still wins when it conflicts.
Inputs
PR_NUMBERor PR URL — required unless inferred fromgh pr status/ current branch’s tracking PR.ghCLI authenticated to read the PR always; write (push, create replies) only in local mode.
Step 1 — Resolve PR and checkout
gh pr view "${PR_NUMBER}" --json number,url,baseRefName,headRefName,headRepositoryOwner,files
Check out the PR head (typical pattern):
gh pr checkout "${PR_NUMBER}"
Confirm the working tree matches the PR you intend to update.
Step 2 — Eligibility guard (one modified topic directory)
Many directories under docs/plans/ may exist on the default branch; that is normal. The guard uses paths changed by this PR, not repo-wide counts.
List paths touched by the PR vs its base, for example:
gh pr diff "${PR_NUMBER}" --name-onlyAlternatively use
gh pr view "${PR_NUMBER}" --json filesand derive paths from thefilesentries (usepath/path+previousPathif renames matter).From that set, keep only paths under
docs/plans/YYYY-MM-DD-<topic>/(topic slug convention matchesspec-start: dated folder with kebab-case slug).Exactly one distinct topic directory prefix must appear among changed paths. If zero or two or more such prefixes appear, stop with a clear error—do not guess.
At PR head, that directory must contain both
spec.mdandqna.md(required forspec-refine). If either is missing, stop.
Optional: if the head branch matches agent/*-spec-*, note alignment with spec-start-github; do not require that pattern for eligibility.
Step 3 — Fetch GitHub comments
Pull enough metadata to support edit detection and threading:
Pull request review comments (inline on diffs): REST
GET /repos/{owner}/{repo}/pulls/{pull_number}/commentsviagh api, or GraphQL equivalent. Capture at least:id,body,path,line/original_line,side,diff_hunk,in_reply_to_id,created_at,updated_at,html_url,commit_id(or current head) as needed for mapping.Issue comments on the PR (conversation tab):
GET /repos/{owner}/{repo}/issues/{pull_number}/comments(the PR number is the issue number). Captureid,body,updated_at,html_url.
Use owner / repo from gh repo view --json nameWithOwner -q .nameWithOwner or from the PR JSON.
Step 4 — Ingest into comments.md and qna.md
Ingest markers and edited comments
Use one stable marker convention everywhere you mirror GitHub text into committed files, for example:
<!-- gh-rc:COMMENT_ID ts:UPDATED_AT_ISO -->
placed on the line immediately after the ### heading (or at the start of an inline insert inside an answer body) so reruns can find prior ingests.
- First time you ingest comment
COMMENT_ID: write the marker with the GitHubupdated_at(or body hash) you observed, then the prose. - Later runs: if GitHub’s
updated_ator body changed since the marker’sts/ recorded snapshot, update the previously ingested material (replace or revise)—do not skip forever. - If the comment is unchanged and already fully reflected next to its marker, skip re-adding duplicate prose.
For issue (conversation) comments, you may use a parallel prefix, e.g. <!-- gh-ic:COMMENT_ID ts:... -->, in comments.md only (still not committed if only in scratch—see routing).
Routing
Inline review on
spec.md(path matches topicspec.md): append a new section tocomments.mdfollowing the shape inspec-refine(e.g. ## For file spec.md lines N with the reviewer text and permalink). Do not commitcomments.md.Non-inline PR feedback (issue comments, review summaries without a single line): append to
comments.mdas general## …blocks with attribution when useful.Inline review on
qna.md— placement preserves intent (map the commented line to the current file after checkout):Resolve which
## Q-NN — …block contains the line (and whether the line is before the first###, after the last###for that question, or inside a### Answer …body, including nested####).Comment on the question stem (under
## Q-NNbullets, before any###, or clearly addressing the question row): treat as a new answer — append### Answer — …under that## Q-NNperspec-start(qna.mdformat): unique slug, permalink line under heading when long, then marker + body.Comment after all answers for that
## Q-NN(below the final###of that block): treat as a new answer — append another### Answer — …at the end of that question.Comment inside an existing
### Answer …body: treat as discussion on that answer — prefer in-place edits inside that answer (extra paragraph, blockquote, or a child#### Threadsubsection). Avoid silently moving the text to an unrelated top-level###. If in-place merge is unsafe, add a new###that cites the target answer heading and states the correction or dispute explicitly.
When multiple GitHub threads map to the same ## Q-NN, preserve thread order where sensible; later activity may supersede earlier per spec-refine “later overrides earlier” guidance.
Step 5 — Run spec-refine
Execute Phase 1 → Phase 2 → Phase 3 from spec-refine/SKILL.md on the single topic directory you locked in Step 2.
Step 6 — Commit (never comments.md)
git addwith explicit paths only — at minimum:docs/plans/YYYY-MM-DD-<topic>/spec.mddocs/plans/YYYY-MM-DD-<topic>/qna.md- plus any tracked optional assets under that same directory that
spec-refinelegitimately changed.
Never stage
comments.md. If it appears staged, rungit restore --staged -- docs/plans/.../comments.md(and verify it is not in the commit).Commit with a message consistent with repo conventions, e.g. “Address PR review feedback” and reference the driving issue with
Refs #Nwhen known (the PR itself is not an issue number—link the PR URL in the body if helpful).
Step 7 — Push (local mode only)
In local mode, git push to update the existing PR branch (use the remote tracking branch for the PR head).
In harness mode, do not push; include exact suggested commands in the final reply.
Step 8 — Review-thread replies (local mode, optional)
Posting replies is a GitHub write, same class as git push.
- Harness mode: Do not call reply APIs; output suggested
gh api/ GraphQL mutations and thread / comment IDs. - Local mode: Best-effort only—when new or updated answer material clearly corresponds to an open review thread on
qna.md, post a short reply (for examplegh api -X POST repos/{owner}/{repo}/pulls/{pr}/comments/{comment_id}/replies -f body='…'per GitHub “Create a reply for a review comment”;comment_idmust be a top-level thread root, not a reply). If mapping is uncertain, skip rather than spam the wrong thread.
Retain thread id next to ingested material (e.g. <!-- gh-thread:THREAD_ROOT_ID --> near the marker) when it helps a harness or a later run. Document that force-pushes, line shifts, and resolved threads can break mapping.
Aftercare (message to user)
- Topic directory path, PR URL, and local vs harness outcome.
- List files changed in the commit; confirm
comments.mdwas not committed. - Top remaining
## Q-NNitems that still need humans. - If harness: paste push and thread-reply handoff blocks.