write-tech-pr-description
Writes or revises a pull request (or merge request) description that explains the change, its reason, review boundaries, and verified evidence. Use when opening a draft, after planning, or after implementation.
Synopsis
User-invoked. Name this skill when you want the agent to apply it. disable-model-invocation is true.
Source file: skills/write-tech-pr-description/SKILL.md.
Front matter
- name
write-tech-pr-description- description
- Writes or revises a pull request (or merge request) description that explains the change, its reason, review boundaries, and verified evidence. Use when opening a draft, after planning, or after implementation.
- disable-model-invocation
true
Full contents
---
name: write-tech-pr-description
description: Writes or revises a pull request (or merge request) description that explains the change, its reason, review boundaries, and verified evidence. Use when opening a draft, after planning, or after implementation.
disable-model-invocation: true
---
# Write a pull request (or merge request) description
Read [write-tech-core](../write-tech-core/SKILL.md) first.
A description is a review aid and a durable record. It tells a reviewer what
problem the change answers, what behaviour changes, and how the result was
checked. It is not a changelog of files and it is not a copy of the diff.
SlopKit merge requests carry two blocks. The planning block is written while
the plan is written, by the agent that owns the artifact. The execution block
is written by the developer, after the code exists. Markers keep them apart:
```markdown
<!-- kit:plan -->
**Outcome:** one sentence naming what is true after this lands.
Plan: [plan.md](https://gitlab.example/-/blob/<branch>/.slopkit/plans/tasks/<slug>/plan.md)
Spec: !130, item 2 (only when true)
## Problem
## What changes
## Acceptance criteria
## Not in this MR (only when a reviewer would ask)
<!-- /kit:plan -->
<!-- kit:execution -->
## What was built
## Proof
<!-- /kit:execution -->
```
A spec or epic merge request keeps an empty execution block. Nothing implements
it, so there is nothing to report.
## Planning block
**Outcome** names the result, not the activity: "a merge clears its status
label" rather than "handle status labels on merge".
**Plan** links the plan file on the branch, so the reviewer can read the full
plan without searching. Link the spec and the item only when they exist.
**Problem** gives the symptom a reader can recognise: what breaks, who hits it,
what it costs. Evidence, not restatement of the plan.
**What changes** states the behaviour before and after, grouped by intent. Three
to six bullets. A reviewer must be able to check each one against the diff.
**Not in this MR** names the boundary only when a reviewer would otherwise ask
for the missing piece. Leave the section out when nothing qualifies.
<!-- fragment:acceptance_template -->
## Acceptance criteria
Write each criterion as external behaviour: the actor, the starting state, the
action, and the result. Add the denial or failure path when one exists. A
developer must be able to deliver the criterion, and a reviewer must be able to
see that it holds.
Do not describe how the criterion is tested. Evidence belongs under Proof, and
a check is not the behaviour it checks.
<!-- /fragment:acceptance_template -->
The criteria here are the plan's criteria, shortened. They are not a second
list invented for the description.
## Execution block
**What was built** reports what the diff does. Every deviation from the plan
appears here with its reason: a risk that did not materialise, a criterion that
could not be met, a surface that had to change. Never rewrite the planning
block to match the shipped result — the plan is the record of what was agreed,
and a reader needs both to compare them.
<!-- fragment:proof_template -->
## Proof
Record evidence that each acceptance criterion holds. Any form counts: a
command and its output, a log line, a screenshot, a recording, a page the
reader can open, a pipeline job. Name what you ran or where you looked, and
include the part of the result that settles the question.
Choose the evidence the behaviour needs. A narrow check does not prove a wide
behaviour, and a wide check is noise when one line settles it.
<!-- /fragment:proof_template -->
## Rules
- Never list every edited file. A reviewer reads the diff for that.
- Never number implementation steps. A description is not a plan.
- Never narrate labels, status transitions, CI retries, or who opened the
merge request.
- Never leave an empty section. Delete the heading instead.
- Whenever you name a file, link it. In a description use a blob URL on the
merge-request branch, so the link works before the merge.
- Say "not checked" plainly when a check did not run. Never claim CI is green
when only a local command passed.
## Updating the description
In SlopKit Agency the description is written with `mr_update_description`:
`section: "plan"` while planning, `section: "execution"` after implementation.
The tool replaces only its own block, so a human's edit and the other block
survive. Do not rewrite the whole body by hand.
## Examples
A task merge request, complete:
```markdown
The steward-page guard says how long it waited
<!-- kit:plan -->
**Outcome:** a missing page and a first-attempt success both report elapsed
seconds, so a page written by an earlier run no longer reads like one written
by this one.
Plan: [plan.md](https://gitlab.techtailors.net/slopkit/agency/-/blob/plan/steward-page-guard/plan.md)
## Problem
`scripts/assert-steward-page.ts` prints `steward page present: <path>` or a
`MISSING` line. Neither carries a wall clock, so a job log cannot say whether
the page was written in this run or a previous one.
## What changes
- The success line names the attempt count and the elapsed seconds.
- The `MISSING` line ends with the same suffix, so the two are comparable.
- Exit codes, budget, and attempt arithmetic stay as they are.
## Acceptance criteria
- A first-attempt success reads `after 1 attempt(s) (0s)`.
- A page written on the fourth attempt reads the elapsed seconds.
- A missing page ends with the same suffix as the success line.
## Not in this MR
The fetch and the retry policy.
<!-- /kit:plan -->
<!-- kit:execution -->
## What was built
One `started` timestamp before the loop and one suffix formatter used by both
branches. The attempt counter stays in the success line only, because the
`MISSING` line already prints it.
Deviation: the plan said the `MISSING` line gains only seconds. It also needed
the attempt count to keep the two lines comparable, so both share the suffix.
## Proof
- `node --test scripts/assert-steward-page.test.ts` — 9 passed, including the
four existing assertions with the new expected strings.
- Job log `16599`: `steward page present: … after 3 attempt(s) (6s)`.
<!-- /kit:execution -->
```
A spec merge request, execution block present but empty:
```markdown
<!-- kit:plan -->
**Outcome:** the relay console shows one spec's epics and tasks as a single
execution.
Spec: [SPEC.md](https://gitlab.techtailors.net/slopkit/agency/-/blob/spec/relay-console/SPEC.md)
## Problem
An operator reads four projects to learn whether one spec is moving.
<!-- /kit:plan -->
<!-- kit:execution -->
<!-- /kit:execution -->
```
Never write this:
```markdown
Opened by SlopKit scaffolder.
Plan: `.slopkit/plans/tasks/x/plan.md`
## Changes
1. Edit `src/errors.ts` line 31.
2. Add a test in `scripts/x.test.ts`.
3. Run `npm test`.
```
It has no problem, no outcome, no reviewable behaviour, and no evidence. The
reader learns only which files changed — which is what the diff already says.
## Verification gate
Before writing, compare every claim to the plan, the diff, or the check you
ran. Check commands, counts, links, and test status. A description that says
"verified" must name what was verified and where the result can be seen.