Create or update the PR for the current branch, with a description that lets the reviewer understand why this change exists, what the implementation looks like, and what existing users will lose.
Workflow
-
Read the PR template:
Read(.github/pull_request_template.md) -
Find or create the PR:
- First check whether the current branch has a PR:
gh pr view --json url,number,title,state 2>/dev/null。 - If not, look at
git status --short --branchand the commits on the current branch. - Commit the remaining changes, push the branch with upstream, and use
gh pr createto create the PR. - Follow the repository's git safety rules.
- First check whether the current branch has a PR:
-
Gather the context needed to explain the change:
- Read the linked issue and related task artifacts.
- Read the full diff (
git diff main...HEAD) and enough surrounding code to understand the behavior and ownership. - If the PR already exists, use
gh pr viewto get the metadata and the list of changed files.
-
Write the description section by section according to the template. Write the description in the language the user is currently using, and the behavior change table as well; only three things are fixed: the PR title stays in English Conventional Commit format, the changeset stays in English (see the
gen-changesetsskill), and the section headings follow the template's original wording.- Requirement or Bug: one sentence, or
Resolve #<number>. Do not write more. - Bug Reproduction Steps: only needed for bug-type PRs; for features write
N/A. If the steps are already in the issue, writeSee linked issue。 - Root Cause: only needed for bug-type PRs; for features write
N/A. Explain the root cause, and whether this is a fundamental fix or a workaround. - Code Changes: if a visual outline can make it clear, do not write prose; see "Visual outline of code changes".
- Behavior Changes and Affected Users: fill in the behavior change table first, then list the affected modules and test coverage; see "Behavior changes and affected groups".
- Checklist: check all that apply.
- Requirement or Bug: one sentence, or
-
Publish the description:
- First save it to a temporary file, then
gh pr edit <number> --body-file <path>orgh pr create --body-file <path>。 - to confirm the update succeeded.
- First save it to a temporary file, then
Behavior changes and affected groups
This section answers one question: after this is merged, what will existing users lose. Most past regressions in this repository came from nobody answering this question, not from logic errors.
Criteria:Any input that worked before the change (config keys, environment variables, command-line arguments, provider response shapes, session data written by older versions, client requests, hook payloads) must behave unchanged after the change, unless a change is explicitly declared here and a fallback is given.
How to write it:
-
List every observable behavior the diff changes, one per line. Include ones you think are "unchanged" but whose branch conditions moved: will newly added conditions match existing inputs before the old conditions do; who was taking deleted or narrowed branches before the change. Internal packages get bundled into the CLI release package, so "internal" does not mean users won't notice. Use the PR description's language for the table; the example below is in English only to show the shape:
Behavior Before After Who relies on the old behavior Escape hatch reasoning parsing when reasoning_detailsis an arraystring reasoningalso readstring ignored OpenAI-compatible gateways that send both (OpenRouter dialect) none -
Groups must be named specifically; do not write "some users". Take them from
.agents/skills/review-pr/surfaces.md: clients (TUI, print mode, desktop and web, VS Code, ACP, SDK), provider dialects, platforms, config states, data vintages, external scripts. -
For changes to prompt text (system prompt, tool descriptions, reminders), put each sentence on its own line, and state clearly what behavior this sentence constrained before the change, who depended on it, and what constrains it now. "No test references this sentence" is not evidence of no impact.
-
For replacements or bypasses of old paths (porting, runtime binding, protocol replacement), additionally list the old path's feature inventory: which environment variables it recognized, what fallbacks it had, which inputs it accepted, and where each of these lives in the new path.
-
If there truly is no observable change, write
None, and explain the evidence: which branches, default values, and contract files were not touched. -
After the table, list the affected modules and the test coverage corresponding to each row. For default flips or removed behavior, there must be a test that pins down the old behavior for the unaffected population, and the changeset must state what users lost; see the
gen-changesetsskill; if there is no way back, ask the maintainer to make an explicit decision in the PR.
Visual outline of code changes
Prefer structured views over prose. Use the minimal combination that explains the implementation clearly, and do not list categories that did not change.
For logic or algorithm changes, use a pseudocode diff:
on(save)
- write content
+ if content is unchanged
+ return cached result
+ write new content
+ invalidate cache
For runtime control flow, use a call tree diff:
submitForm
createSession
persistPrompt
+ expandSkillMention
launchAgent
- navigateToSession
+ navigateToSession
+ subscribeToEvents
For changes in file responsibilities, use a shallow file tree diff:
src/
├── commands/
+│ └── show-me.ts # expands the slash command
├── sessions/
-└── transport.ts
+└── transport/
+ ├── client.ts
+ └── stream.ts
For component or UI structure changes, use a tree diff:
<SessionPage>
useSessionEvents()
<SessionToolbar>
+ <RunSkillButton />
<SessionTimeline>
+ <SkillResultCard />
For component interactions, control flow, or data flow, use Mermaid; it is especially useful when explaining bug mechanisms:
sequenceDiagram
participant User
participant UI
participant Daemon
User->>UI: choose command
UI->>Daemon: send expanded prompt
Daemon-->>UI: stream result
For key data structure or type changes, use a code block in the corresponding language:
interface SessionEvents {
onTurnStart(cb: (turn: Turn) => void): void;
onTurnEnd(cb: (turn: Turn) => void): void;
}
Rules for the visual outline:
- When the focus is "what changed" and the surrounding shape already exists, use a
diffblock. - When most of it is new content, or diff notation would obscure attribution and order, use the corresponding language or a
textblock to give the complete target shape. - Explain in the order that is easiest to understand: files first or data structures first, whichever fits.
- Talk like one person speaking to another: simple, coherent, concise.