--- name: pr-body description: "Use when you are about to open a pull request, edit a pull request description, write a PR summary, or update the proposed squash-commit message on an existing PR. Defines the silk-release marker contract that lets humans, local agents and cloud agents share one PR description without overwriting each other: which regions you own, which are regenerated, and the two incompatible spellings of a closing reference. Triggered by \"open a PR\", \"gh pr create\", \"gh pr edit\", \"write the PR description\", \"update the PR body\", \"link the issues on this PR\". Covers the DESCRIPTION only; the PR title and a proposed-squash-commit fence belong to the commit-create skill." user-invocable: false allowed-tools: - execute --- # pr-body A PR description in this ecosystem is a shared document with more than one writer. `@savvy-web/silk-release-action` regenerates part of it on every push to the release branch; humans type into it; local and cloud agents write summaries into it. HTML-comment markers are what keep those writers from destroying each other's work. Read this before you write into any PR description. The failure mode is silent: the wrong region accepts your text, looks correct in the browser, and is gone after the next push with no error anywhere. Write ONLY between markers you own. Everything inside `` … `` that is not inside a region named below is regenerated wholesale by the release action, and your edits there are destroyed without warning or signal. Never hand-edit the `owned="…"` attribute on the references marker. It is how the action tells its own references from yours; a wrong value makes it delete a real reference or resurrect a dropped one. --- ## The document ````markdown ```proposed-squash-commit feat: add the thing - item - item Closes #123, #456 Signed-off-by: Name ``` Closes #123 Closes #456 ```` Anything OUTSIDE `silk-release:start`/`end` is human territory and survives every regeneration. A human's note above the managed region is never yours to edit. --- ## Who owns what | Region | Owner | Survives regeneration | | --- | --- | --- | | Above/below the managed region | Humans | Yes — never regenerated | | `silk-release:summary` | **You** | Yes — carried through explicitly | | `proposed-squash-commit` fence | **You**, on a non-release PR | **No** on a release PR — see below | | `silk-release:references` | Shared — you may ADD | Your additions yes, via `owned` | | Everything else inside the managed region | The action | Rebuilt every push | ### The summary region Yours. Write real markdown here — headings, lists, tables, links, code fences. This is the one place in the document where prose is unconstrained, and it is the right home for everything the commit message is not allowed to carry: reasoning, investigation notes, evidence, benchmarks, screenshots, migration guidance, review instructions. The action carries this region through on every regeneration, so your work survives. It writes nothing into it — it only reserves it. ### The proposed-squash-commit fence This block becomes the eventual squash-commit message. `proposed-squash-commit` is not a GFM language and appears to be undocumented, but GitHub renders it. **Do not "correct" it to `text`** — it is the agreed target that integrations read. Its contents must satisfy the repo's commitlint preset, because it is a commit message. **Invoke the `commit-create` skill and follow it** — the brevity doctrine, the type enum, the subject rules and the trailer rules all apply unchanged. A few bullets or one to two short paragraphs; the depth goes in the summary region above, which is exactly what that region is for. To check it before you write it, extract the block to a file and run: ```bash bash "/../commit-create/scripts/validate-message.sh" ``` On a **release PR**, the release action rebuilds this fence from the PR title, its own linked-issue set and the configured signoff on every push. It is NOT carried through the way the summary is. A rewrite you make here is lost the moment another commit lands on the release branch. So: on a release PR, treat the fence as read-only unless the PR is about to merge with no further pushes expected. Put anything that must survive in the summary region. On an ordinary feature PR — where no action manages the body — the fence is yours to write and maintain. ### The references region This is what actually links issues to the PR, and the rules are empirical, not inferred from GitHub's documentation: - **Only a bare `Closes #N` line, outside every fence, links an issue.** Each on its own line, nothing before or after it on that line. - **A reference inside a fenced block is inert.** GitHub does not see it. That is why the same issues appear twice in the document, spelled differently: | Location | Spelling | Read by | | --- | --- | --- | | Inside the `proposed-squash-commit` fence | `Closes #123, #456` — one comma-separated line | commitlint | | Inside the references region | `Closes #123` — one bare line each | GitHub's linker | **Neither consumer accepts the other's spelling.** The duplication is load-bearing. Do not "simplify" it, do not make the two forms match, and do not move the bare lines inside the fence to tidy the body. To link an issue the action does not know about, add a bare `Closes #N` line inside the references region. It carries through: the action subtracts the ids in `owned="…"` from what it finds, and preserves the rest as yours. You cannot force-link an issue the action has deliberately dropped. If an issue is in the action's set and closed, it stays out no matter what you add — that is the action's call, not yours. --- ## Writing the summary The audience is a reviewer deciding whether to approve, and a maintainer six months later asking why this shipped. Lead with what changed and why it is safe. - Open with the outcome in two or three sentences. What behavior is different now? A reviewer should be able to stop after this paragraph and know whether they care. - Then the reasoning the commit message cannot carry: what you ruled out, what surprised you, what you verified and how. - Call out anything a reviewer must check by hand — a migration, a behavior change a consumer could trip over, a deliberate scope exclusion. - State what you did NOT do, if the diff would otherwise imply you did. - Verification belongs here, concretely: the command you ran and its result, not "all tests pass". Do not recap the diff file by file. GitHub already renders it, and a listing crowds out the reasoning that only you have. Unlike the commit body, length here is not the enemy — irrelevance is. A long summary that a reviewer reads once and acts on beats a short one that sends them into the diff to reconstruct your intent. --- ## Editing an existing description Always read before you write. The body is a shared document and you are not its only author. ```bash gh pr view --json body --jq .body ``` Then: 1. Locate your region's markers in what came back. 2. Replace only the text BETWEEN them. 3. Write the whole body back, with every other byte unchanged — including the human prose outside the managed region and the `owned` attribute. If the markers are absent, the PR is not managed by the release action. Write an ordinary description; do not synthesize a managed region to make it look like one. If the body has markers but your region is missing its pair, stop and report it rather than guessing where the region should go. A misplaced marker pair is worse than none — it makes the action regenerate over content it does not own. --- ## Before you post 1. Are you writing only inside a region you own? 2. Is the `proposed-squash-commit` block valid against `commit-create` — type, subject, brevity, trailers, signoff? 3. Does the fence use the comma-separated `Closes #a, #b` form, and the references region the one-per-line bare form? 4. Are the bare `Closes` lines outside every fence? 5. Is the `owned` attribute exactly as you found it? 6. Does every byte outside your region match what `gh pr view` returned? 7. On a release PR: is anything that must survive the next push in the summary region rather than the fence? ## What the pre-tool-use hook checks on a PR body A `gh pr create`/`gh pr edit` body passes through the silk pre-tool-use hook, but it is NOT held to the commit-message rules. Markdown headers, code fences and long summaries are all fine here — the rules that forbid them describe a commit body, and a PR description is a different document. Two checks do still apply, and both are advisory: - **plan-leakage** — do not cite `.claude/plans/`, `.claude/design/`, `okf/`, or write "as decided in the plan". A PR body carries the reasoning itself, not a pointer to where it lives: plan files are not committed at all, and a design record moves and gets rewritten. Restate the reasoning in the summary. - **closes-trailer** — if the branch name encodes a ticket, the body should close it. Add the bare `Closes #N` line to the references region. The `proposed-squash-commit` block is exempt from the commit rules *as part of the PR body*, but its contents still have to pass commitlint when the squash actually happens. Validate it with `commit-create`'s script before you rely on it. When a check flags something, fix the body — do not reach for `--no-verify` or an equivalent bypass.