pr-description
/pr-description
Generuje lub aktualizuje opis pull requesta dla bieżącej gałęzi, opcjonalnie na podstawie numeru zgłoszenia podanego jako argument.
- Autor
- The01Geek ↗
- Repozytorium
- prflow ↗
- Licencja
- MIT
- Ostatnia zmiana repozytorium
- 25.10.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 1
- Skrypty
- 0
- Komentarze HTML
- 13
- Adresy URL w SKILL.md
- 0
Brak sygnałów. Repozytorium zmienione 25.10.2026, bez odwołań do wycofanych modeli i API.
MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.
- SKILL.md zawiera komentarze HTML (13). Nie widać ich w podglądzie Markdown, a model je czyta.
Co robi i kiedy
Generuje lub aktualizuje opis pull requesta dla bieżącej gałęzi, opcjonalnie na podstawie numeru zgłoszenia podanego jako argument.
Argumenty
/pr-description <issue-number>
Oryginalny opis (EN)
Use when generating or updating a PR description for the current branch. Takes an optional issue number as argument.
Jak działa
- Step 1: Gather Context
- Step 2: Generate the PR Description
- Summary
- Changes
- Resolves
- Test Plan
- Post-Merge Verification
- Deferred Findings
- Visual Changes
- Breaking Changes
Podgląd SKILL.md
---
name: pr-description
description: Use when generating or updating a PR description for the current branch. Takes an optional issue number as argument.
argument-hint: <issue-number>
---
# /pr-description — Generate or Update PR Description
Generate a structured PR description from the branch diff. For an existing PR, reconcile its title and merge the body with human-added content.
Input: `$ARGUMENTS` is an optional GitHub issue number. If provided, include a "Resolves #N" link.
**Portable helper anchor (single-statement).** The bundled-helper commands in this skill spell the skill directory as `${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}`. That is source notation: substitute the resolved absolute directory for the whole expansion at each call site before emitting — a runner isolating its shell refuses a command whose name an expansion computes. Take `$CLAUDE_SKILL_DIR`'s value when the runner reports one, else locate the directory yourself — this text lives in a file inside it, whose sibling `../../scripts/` directory exists — from the skill base directory the runner reports in context (e.g. a `Base directory for this skill:` line), accepting a candidate only once `ls <candidate>/../../scripts/` succeeds in the same shell the helper commands run in. If a path form is rejected, use the form that shell reports (`pwd` shows it); a Windows-form base directory (`C:\...`) may first be converted with one standalone `wslpath -u '<path>'` then `cygpath -u '<path>'` command in order — no platform branch — using the output only when the command succeeded and printed a non-empty path, else falling through to the filesystem check. Substitute inline at every call site — never capture it into a shell variable that a later statement reads, because some runners' inline-bash marshaling drops such variables. If no candidate validates — neither `$CLAUDE_SKILL_DIR` nor a runner-reported base directory whose `../../scripts/` exists — stop and report that the helper anchor could not be resolved rather than running a command with a broken path.
Consumer prompt extension (load first). This skill's consumer extension reaches you through exactly one channel — the invocation ladder below — so load it yourself with that ladder, unconditionally, at the start of the run. Read the ladder's output whole — no `>/dev/null`, no `| head -<n>`, no truncation of any kind — because an extension whose text you never observed governs nothing in this run. From the repo root, emit the granted vendored-literal leading token first:
```bash
.prflow/vendor/prflow/scripts/load-prompt-extension.sh pr-description
```
On a `command not found` / `No such file` / exit-127 reading (a checkout where the vendored path is absent, such as a non-Claude-Code runner), fall back to the portable anchor form:
```bash
"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/load-prompt-extension.sh pr-description
```
Every extension-state failure arm below fires unconditionally — this ladder is the only channel, so a failure you do not report drops consumer policy from the run silently. If the invocation fails because the helper path does not exist (`No such file`, exit 127, or the platform equivalent) on every form above, that is the anchor-resolution failure described in the *Portable helper anchor* note above — report it in the run's output, since it breaks every other bundled-helper call site in this run; fix the anchor, don't report a missing extension. If instead the harness refuses the command outright — a permission denial rather than a missing file — the extension's state is **unestablished**: report that in the run's output and never treat it as a clean policy pass (*unknown is not zero*). Otherwise, if the helper exits non-zero, a consumer extension exists but could not be loaded — surface its stderr message and do not silently proceed as if none existed. On exit 0 the helper prints a `PROMPT-EXTENSION-STATUS: content-present` or `PROMPT-EXTENSION-STATUS: present-empty` line on stderr; report that token verbatim in the run's output as the extension's resolved status. On `content-present`, treat the stdout text as additional instructions appended to the end of this skill's own prompt for this run — it is upgrade-safe, consumer-owned customization committed under `.prflow/skill-extensions/`. On `present-empty`, proceed unchanged. If no `PROMPT-EXTENSION-STATUS` line appeared at all — the command produced no output (a harness refusal) or exited non-zero (undeliverable) — the state is **unestablished**: report unestablished, never collapse it onto `present-empty` (*unknown is not zero*).
Classify the delivery from the ladder's own status line, not from whether any classifier ran: **arrived** only on a produced `PROMPT-EXTENSION-STATUS: content-present`, **absent** only on a produced `present-empty`, and **unestablished** whenever no status line was produced at all — a helper denied when invoked by path emits no output, byte-identical to silent non-delivery, so it never reads as arrived. On **unestablished**, force the record to the first available durable surface in this fixed, terminating order: this run's workpad when one exists; else the pull request — its description or a PR comment — when the run has a PR but no workpad; else the run's own output, naming the unestablished state and reporting the record **unrecordable**. Write the first available surface — never skip an earlier one for a later one. The mechanized classifier is `.prflow/vendor/prflow/scripts/prompt-extension-arrival.py classify-ladder-output --skill pr-description` — the granted vendored-literal leading token, invoked with the same repo-relative/anchor fallback ladder as the load above; it reads the ladder's captured output on stdin — capture the ladder's combined stdout and stderr when invoking it (the status line is on stderr, so a stdout-only pipe misclassifies every real arrival as `unestablished`) — and emits `final=arrived|absent|unestablished` plus, on unestablished, a `record=` line. Do not depend on it running: where it is not granted or not runnable it produces no output, and its silence is never a classification — the status line you already observed stays authoritative for the states above, and on unestablished the forced durable write happens regardless.
## Step 1: Gather Context
Resolve the configured base branch by printing it, then substituting the printed value as a literal:
```bash
"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/config-get.sh .base_branch main
```
Read the printed base branch from the tool result. On a non-zero exit or an empty value, fall back to `main` and log `pr-description: could not read .base_branch — falling back to main`. Substitute the printed value as a LITERAL into each git fence below (e.g. `git diff origin/<base>...HEAD`) — never through a shell-variable capture (`VAR=$(...)`) and never as an `origin/$VAR` expansion.
Run these commands to understand what changed, with `<base>` the printed literal (default `main`):
```bash
git fetch origin <base>
git log origin/<base>...HEAD --oneline
```
```bash
git diff origin/<base>...HEAD --stat
```
Read the diff details for any files that need deeper understanding:
```bash
git diff origin/<base>...HEAD
```
If an issue number was provided, fetch the issue for context:
```bash
gh issue view $ARGUMENTS --json title,body,labels
```
Check for an existing PR on the current branch:
```bash
gh pr view --json number,body,title
```
Route on the exit status, stdout and stderr in the tool result:
- Exit 0 with parseable JSON carrying a PR number: an existing PR. Its number and body feed Step 2 and Step 3.
- Non-zero exit whose stderr contains `no pull requests found for branch`: no PR, so Mode A; quote that stderr line, which names the branch, in your final message.
- Anything else is `unestablished` — any other non-zero exit (authentication, network, no git remote, `could not determine current branch` on a detached HEAD), exit 0 with empty or unparseable output or no PR number, or a harness refusal with no output. Stop: compose no description, make no PATCH, and report the lookup as unestablished in your final message, quoting the stderr or naming the missing output.
Pull post-merge acceptance criteria from the /prflow:implement workpad: `/prflow:implement` tags each criterion verifiable only after merge with a trailing `(post-merge)` marker, and the PR body lists them so the merger can tick them off after deploy.
Workpad lookup. With no issue number available (from `$ARGUMENTS` or extracted from the existing PR body via `(?i)(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)` — mirroring GitHub's own case-insensitive closes-keyword detection), the outcome is `no-issue` and no call runs. Otherwise emit this plain call, the number substituted as a literal:
```bash
.prflow/vendor/prflow/scripts/workpad.py body --issue <issue-number>
```
Only its exit 0, or its exit 2 with no output, is final. Any other result — not found, rc 127, a usage error (a vendored copy without `body --issue`), another non-zero status, a harness refusal — falls through to the portable anchor form, whose result is final:
```bash
"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../scripts/workpad.py body --issue <issue-number>
```
Read each form's exit status and output (stdout and stderr merged) from the tool result, and map the final result to one of four outcomes (`no-issue` above, or):
- `read` — exit 0 with non-empty output; the output is the workpad body. A `workpad.py` warning line in it is not body content: report it as a note beside `read`.
- `no-workpad` — exit 2 with no output at all.
- `failed` — anything else: exit 0 with empty output; exit 2 with any output (a warning there means the scan may have used the wrong workpad marker); exit 1; exit 3; any other status; a harness refusal. Name the observed cause and each form's output.
Report the outcome in your final message as `workpad lookup: <read, <n> post-merge rows[, note: <warning>] | no-workpad | no-issue | failed: <cause>>`, never inside the PR body. The lookup never fails the run.
On `read`, a tagged row is a `## Acceptance Criteria` checkbox row `section_parse` parses — optionally indented `-` or `*`, then `[ ]`, `[x]` or `[X]` — whose text, joined with indented non-blank continuation lines and right-stripped, `is_post_merge_tagged` accepts: ending in ` (post-merge)`, leading space included. Ticked and unticked rows both count. Strip the checkbox and the tag from each and collect them as `POST_MERGE_ITEMS`; their number is the tagged-row count. When `POST_MERGE_ITEMS` is empty, the Post-Merge Verification section is omitted — except that `failed` in Mode B keeps the existing body's section verbatim.
Source the Test Plan's executed outcomes from this run's tool results and, on `read`, the workpad's `## Progress` notes. On `no-issue`, `no-workpad` or `failed`, use only other observed execution evidence; without it, claim no executed result. Bind current results to the candidate they verified; preserve relevant historical decisions as historical. A diff establishes what checks exist, not that they passed. Report material limits without manufacturing waiver declarations or describing planned or unavailable checks as passes.
Best-effort: pull deferred review findings from the manifest. /prflow:review-and-fix writes each run's manifest run-scoped (`.prflow/tmp/review/<slug>/<run-id>/deferrals.json`), and /prflow:implement Phase 4.0.5 merges every run-scoped manifest into one slug-level aggregate at `.prflow/tmp/review/pr-<N>/deferrals.json`, then files follow-up issues and updates that aggregate in place with `id` and `follow_up` fields per entry. Read the slug-level aggregate and surface its entries in the PR body as a Scope-Acknowledged Findings block so /prflow:review (run later as a formal merge signal) lists the deferrals in its report; a deferral does not lower a finding's weight in the verdict.
Only when the lookup found a PR, Read `.prflow/tmp/review/pr-<number>/deferrals.json` with the file-read tool, the lookup's PR number substituted as a literal.
If that read returned an aggregate and its parsed JSON has at least one renderable entry under `deferrals[]`, render the Deferred Findings section in Step 2's template — a human-readable Markdown table (one row per deferral) for readers, plus the exact machine payload (the same `schema_version: 1` / `deferrals[]` YAML shape) inside the hidden `DEVFLOW_DEFERRED_PAYLOAD` HTML comment that `scripts/match-deferrals.py` parses. An entry is renderable when it has a populated `follow_up.issue` OR its `reason.category` (equivalently the aggregate's flat `category`) is `settled-by-disclosure` (a foreclosure, which never has a `follow_up.issue`). An ordinary entry (one of the three non-foreclosure categories) lacking a `follow_up.issue` is a stale half-written manifest — skip it silently. A `scheduled-in-run` entry is a distinct, deliberately non-renderable class: the same run's documentation pass discharges it, so it gets no table row and no payload entry — rendering one would claim outstanding work the branch already carries.
**Carry-forward safety.** Because a `settled-by-disclosure` foreclosure files no follow-up issue, the PR-body Scope-Acknowledged block is its *only* durable record — a regeneration from a fresh environment (where `.prflow/tmp/review/…` is empty) must therefore **never** silently wipe it. So:
- When the read returned no usable aggregate (absent, empty, unreadable or unparseable — name a present but unreadable or unparseable one in your final message), do not omit the section: read the existing PR body's `DEVFLOW_DEFERRED_PAYLOAD` block and preserve it verbatim (re-emit its entries unchanged). Only when neither an aggregate nor an existing block exists is the section omitted.
- When both an aggregate and an existing PR-body block exist, merge them: render the aggregate's entries, then carry forward any entry present in the existing body's `DEVFLOW_DEFERRED_PAYLOAD` but absent from the aggregate (matched by its `dfr-` id) so a foreclosure recorded on an earlier pass is never dropped by a later regeneration that no longer sees its manifest.
- Reclassification arm, which overrides the carry-forward above: when the aggregate marks an entry `scheduled-in-run`, **remove** that `dfr-` id's table row and payload entry from the existing body instead of carrying it forward — an earlier pass rendered it as an ordinary row, and the run has since taken the work on. This arm fires only for that category; it never strips a foreclosure row.
The deferral read is best-effort — never fail the run on a missing or unparseable manifest, and never wipe an existing foreclosure block on one.
## Step 2: Generate the PR Description
Read the shared writing standard before composing. The PR description is change-describing prose, so read `lib/writing-standard.md` — reached through the portable skill-directory anchor as `"${CLAUDE_SKILL_DIR:-<absolute skill base directory this runner reports in context>}"/../../lib/writing-standard.md` — and follow it when you write the summary and body below. A failed load emits a breadcrumb naming the file and the failure kind, and you compose the description without it.
For an existing PR, keep a title that accurately describes the implemented change. Otherwise, replace it with a concise, action-oriented title grounded in the current diff, describing the solution rather than the original problem.
### Mode A: No existing PR (or empty body)
Generate a fresh description using the template below.
### Mode B: Existing PR with content
Fetch the existing body and apply these merge rules:
Re-generate from the diff (always overwrite — these reflect current state):
- Summary
- Changes
- Visual Changes
- Breaking Changes
- Post-Merge Verification (when `POST_MERGE_ITEMS` is non-empty — re-derived from the workpad on every run so the list stays in sync with the latest /prflow:implement parse; on a `failed` workpad lookup, keep the existing section verbatim instead)
- Deferred Findings (when there is at least one renderable entry, as defined in Step 1 — re-derived from the manifest on every run so the block stays in sync with the latest /prflow:implement Phase 4.0.5 filing; carry-forward-safe: a regeneration with no manifest present preserves the existing block's entries verbatim rather than wiping them, per the carry-forward rule in Step 1)
Merge (keep existing items that are still relevant, add new ones, remove stale ones):
- Test Plan — preserve human-added items and relevant historical verification decisions; update the checks, actual outcomes and material limits for the current change. Existing coverage and direct checks are valid evidence where sufficient; report their scope accurately.
Merge (combine existing and new):
- Resolves — if `$ARGUMENTS` provides an issue number, include it; also keep any existing issue references that differ from `$ARGUMENTS`, and every line already in it starting at column 0 with `Stricter than criterion `, `Disputed criterion ` or `Finding rejected ` (numbered, `(unmatched)` or quoted; read no criteria to decide)
Preserve as-is:
- Any non-template sections found between the markers (e.g., "## Reviewer Notes", "## Deploy Steps") — carry them forward in the same position
- Any content that appears BEFORE `<!-- PR_BODY_START -->` or AFTER `<!-- PR_BODY_END -->` in the existing body — output it in the same position relative to the markers, except the provenance line, which the next rule places
Relocate, do not preserve in place:
- A provenance line of the form `_Generated via /prflow:implement (...)_` (italic) or the legacy plain form `Generated via /prflow:implement (...)` — wherever it appears in the existing body, carry it forward verbatim as the last line of the whole output, below `<!-- PR_BODY_END -->` and below any other post-marker content. It is a durable record of the run that opened the PR and is meant to read as the body's signature, so a copy left higher up — above `<!-- PR_BODY_START -->`, or in the middle of the body — is moved down rather than kept, and exactly one copy is emitted.
Strip, do not preserve:
- A stopped-run note block delimited by `<!-- prflow:stopped-run-note-start -->` and `<!-- prflow:stopped-run-note-end -->` — remove the block and its markers entirely, wherever it appears. Without this, a late stall-backstop write ships a merged PR with a stale stopped-run banner.
If the existing body has NO markers: Treat the entire existing body as pre-marker content, except the provenance line, which the relocation rule above places, and any line the `## Resolves` rule above keeps, which goes to `## Resolves`, or stays with the pre-marker content when none is generated. Output that pre-marker content above `<!-- PR_BODY_START -->`, then generate the full template below the marker, then the provenance line last.
### Template
Output the description as plain text (not inside a code block) so it appears directly in your response:
<!-- PR_BODY_START -->
## Summary
- [1-3 concise bullet points describing what changed and why]
## Changes
[Group changes by module or concern. Use bold for the area name, colon, then a brief description.]
**[Area name]**: [What changed]
**[Area name]**: [What changed]
## Resolves
Resolves #[issue number, or omit this section if no issue number was provided]
## Test Plan
- [ ] [Concrete verification step]
- [ ] [Concrete verification step]
## Post-Merge Verification
[Omit this entire section when POST_MERGE_ITEMS is empty, except that a `failed` workpad lookup in Mode B keeps the existing section verbatim. When non-empty, render as:]
The following items can only be verified after this PR is merged or deployed. Tick each after performing the check.
- [ ] [Post-merge AC text, with the trailing (post-merge) tag stripped]
- [ ] [...]
## Deferred Findings
[Omit this entire section only when there are NO renderable entries (as defined in Step 1) AND no existing PR-body block to carry forward. When rendering, render with the markers — the /prflow:review deferral matcher parses them exactly. The visible content is a human-readable Markdown table; the exact machine payload lives in a hidden HTML comment (`DEVFLOW_DEFERRED_PAYLOAD`) so it does not appear in the rendered PR body. One table row per deferral; one payload entry per deferral, in the same order. A foreclosure row cites the disclosure path in the Follow-up column (e.g. `disclosure: docs/…`) instead of a `#<N>` issue reference. Carry forward any existing-body entry absent from the aggregate, per Step 1's carry-forward rule:]
<!-- DEVFLOW_DEFERRED_FINDINGS_START -->
These review-agent findings were deferred under the Scope-Acknowledged Findings contract. A deferral does not lower a finding's weight in /prflow:review's verdict, and closing a linked follow-up issue invalidates the deferral. A `settled-by-disclosure` foreclosure has no follow-up issue — the cited disclosure is its deliverable, and a review re-verifies the disclosure phrase against the tree.
| Severity | File | Finding | Follow-up |
| --- | --- | --- | --- |
| <severity> | `<path>:<start>-<end>` | <one-line summary> | #<N> |
| <severity> | `<path>:<start>-<end>` | <one-line summary> | disclosure: `<disclosure path>` |
<!-- DEVFLOW_DEFERRED_PAYLOAD
schema_version: 1
deferrals:
- id: <dfr-...>
finding:
agent: <agent>
severity: <Critical | Important | Suggestion>
file: <path>
line_range: [<start>, <end>]
symbol: <symbol or empty>
kind: <kind>
summary: |
<verbatim summary>
reason:
category: <out-of-scope | already-tracked | claim-quality | settled-by-disclosure>
explanation: |
<verbatim explanation>
# follow_up is present for the three ordinary categories; a settled-by-disclosure
# entry OMITS follow_up and instead carries a top-level `disclosure: {path, phrase}`.
follow_up:
issue: <N>
url: <url>
filed_at: <ISO 8601 UTC>
filed_by: <login>
disclosure:
path: <repo-relative disclosure path> # settled-by-disclosure entries only
phrase: <short verbatim phrase>
-->
<!-- DEVFLOW_DEFERRED_FINDINGS_END -->
## Visual Changes
[Describe UI changes, or "N/A" if none]
## Breaking Changes
[Describe breaking changes and migration steps, or "None"]
<!-- PR_BODY_END -->
Rules:
- Follow the shared writing standard read at the top of this step for how the prose reads.
- Summary bullets should explain *what* and *why*, not list files.
- Changes section groups by logical area (e.g., "Orders module", "Frontend", "Database"), not individual files.
- Test Plan items must be concrete and actionable, not generic ("Run tests").
- The entire output between the markers must be valid GitHub-flavored Markdown.
- GitHub autolink hygiene (the PR body is posted to GitHub): never put a bare `#` immediately before a number unless it is a real issue or PR reference — GitHub renders `#2` as a link to issue/PR 2, which misleads readers. For an ordinal, count, or list position, spell it out ("item 2", "step 3"), never `#2`. Genuine references like `#123` stay as-is. <!-- pruned-path-ok: illustrative autolink examples, not citations -->
- Do NOT wrap the output in a code block. Output the markers and content as plain text so they appear directly in your response.
- When updating an existing PR, do NOT discard human-added content. If in doubt about whether something was human-added, preserve it.
## Step 3: Apply the Description
- If an existing PR was found (including an empty body): Update it via repo-scoped REST. With the file-write tool, write the full body, pre/post-marker content included, and the intended title (without a trailing newline) to separate files under `.prflow/tmp/`, then apply them with the lookup's PR number as a literal:
```bash
gh api repos/{owner}/{repo}/pulls/<number> --method PATCH -F body=@<body-file> -F title=@<title-file>
```
Read back the title and body with the same literal number and compare the JSON values with the files. A non-zero exit or mismatch is a failed write: retry once, then report any remaining failure with the file paths, stderr or mismatch, and the last observed title/body state (or that no read-back succeeded).
```bash
gh api repos/{owner}/{repo}/pulls/<number> --jq '{title,body}'
```
- **If no existing PR (Mode A):** Output the description as plain text for the caller to use when creating the PR.
Wersje
| Repozytorium | Wynik | Licencja |
|---|---|---|
| Ta strona · The01Geek/prflow | 100 | MIT |
| tanstack/ai | 100 | MIT |
| dxos/dxos | 100 | Apache-2.0 |
| sanity-io/sanity | 100 | MIT |
| gosodax/sodax-sdks | 100 | MIT |
| jdx/mise | 100 | MIT |
| basicmachines-co/basic-memory | 100 | AGPL-3.0 |
| jungvonmatt/agent-toolkit | 100 | MIT |
| petekp/claude-code-setup | 100 | MIT |
Migawka bazy z 28.10.2026 · wersja paczki a2a43690bfd5 (skrót SHA-256 całej paczki)
Pobrania w ostatnich 30 dniach: 0 · ranking
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 100pr-describe
Generuje uporządkowany opis pull requesta na podstawie zmian z bieżącej gałęzi. - 100pr
Przygotowuje opis pull requesta na podstawie diffu bieżącej gałęzi i opcjonalnie tworzy PR przez gh. - 100pr
Przygotowuje opis pull requesta na podstawie diffu bieżącej gałęzi i opcjonalnie tworzy PR przez gh. - 96updating-pr-title-and-description
Generuje i aktualizuje tytuł oraz opis pull requesta przy jego tworzeniu lub zmianie. - 90update-pr-description
Generuje opis pull requesta na podstawie zmian z bieżącej gałęzi względem PR na GitHubie, używając gh CLI. - 90pr
Pisze lub aktualizuje opis pull requesta przed uruchomieniem gh pr create.