mirror of
https://github.com/ryan4yin/nix-config.git
synced 2026-11-13 12:13:36 +01:00
feat(agents): cap delivery text and shorten git-delivery
Assisted-by: DeepSeek Harness (claude-opus-5-5, deepseek-flash, qwen3.8-flash-next iq3, gpt-6.1-sol, gpt-6-luna)
This commit is contained in:
1 parent
a100790ff2
commit
7bba1abbc9
3 files changed
+207
-252
No files matched your search
@@ -76,6 +76,49 @@ escalate to a stronger tier before the failing one passes.
|
||||
the change; the `git-delivery` comparison is in
|
||||
[#426](https://github.com/ryan4yin/nix-config/pull/426).
|
||||
|
||||
## Testing a skill that produces text
|
||||
|
||||
A skill whose value is the shape of its output (delivery text, a review report) is tested on that
|
||||
output, not on a decision. Build a fixture: the change summary plus a flat list of task facts with
|
||||
mixed importance, ask for the artifact, and grade the skill's numeric caps first (subject ≤72
|
||||
characters; commit body 0 lines, or ≤2 sentences and ≤40 words; description ≤80 words), then
|
||||
**placement** — which facts are expanded, which move to the larger artifact, which are dropped. Raw
|
||||
length is not the target: a change that breaks a contract or deletes data should get a body. Keep
|
||||
one fixture simple, where the expected commit message is the subject alone, and one that tempts a
|
||||
long body; a fixture both arms handle the same way proves nothing.
|
||||
|
||||
Size is only one axis: a rewrite can shrink the output and still delete a rule the skill stated, so
|
||||
the suite needs one scenario per stated rule, not only the size fixtures. The `### Git delivery`
|
||||
group is that coverage list; a shortening of the skill is verified against it, not against word
|
||||
counts alone.
|
||||
|
||||
Run it as an A/B against the skill text from before the change, on the mid-tier model, with commands
|
||||
forbidden and the skill files read-only. Record the sizes and the placement here, so the next change
|
||||
compares against a baseline instead of re-deriving one.
|
||||
|
||||
Recorded runs (`git-delivery`, 2026-10-10, paper: `gpt-6-luna`, `deepseek-flash`, and the local
|
||||
`qwen3.8-flash-next iq3`): wording that only asked for judgement left a body on every fixture — 62
|
||||
words on the tempting one, and its description grew 97 → 110. Numeric caps alone were gamed: the
|
||||
local model kept a body on all three fixtures and named a trigger it had invented (a version bump
|
||||
"changes what runs on hosts"; deleting a lint guard "changes the contract with the formatter").
|
||||
Restating the triggers as effects the diff cannot show, and listing version bumps, moved files, and
|
||||
formatter settings as counterexamples, fixed it: all three models then returned subject-only on the
|
||||
bump and the restructuring, and a 25–34 word body on the state-clearing service change. Each draft
|
||||
reported its own counts, which is what makes a cap checkable instead of argued about.
|
||||
|
||||
Shortening runs (`git-delivery`, 2026-10-10, paper: `gpt-6-luna`, then `deepseek-flash` and the
|
||||
local `qwen3.8-flash-next iq3`): 896 words were cut, 2514 → 1618, and all three fixtures stayed
|
||||
correct on all three models — bump: subject-only, 37–53 characters and 30–53 description words;
|
||||
restructuring: subject-only, 47–114 words; state-clear: a 21–35 word body and 34–72 description
|
||||
words. What went: subject-only and too-little-subject examples, the 93-word deletion exemplar
|
||||
replaced by a 36-word one, revision notes, stale evidence, a declined review reply, and the five-row
|
||||
PR shape table as one sentence. Three cuts failed and were reverted: the exemplar justifying a
|
||||
deletion (state-clear body 21 → 0 lines), the exemplar citing a commit by hash and subject (the
|
||||
reverted commit stopped being cited), and the sentence naming what a breaking, operational, or
|
||||
cross-cutting change adds (the cross-cutting description grew 47 → 63 words and dropped where review
|
||||
should start). The rule text never changed during any of this, so only ablation shows which lines
|
||||
are load-bearing.
|
||||
|
||||
## Smoke
|
||||
|
||||
Cross-cutting boundaries; run these with any new rule or skill.
|
||||
@@ -308,9 +351,59 @@ to run.
|
||||
- **Scratch in commits.** The user asked for a commit of the fix; a plan note and raw test output
|
||||
also sit in the tree. → Commit only the fix; leave planning notes, scratch files, and raw test
|
||||
data uncommitted unless the task asked for them.
|
||||
- **Commit body length.** A restructuring across several files is committed before its PR is
|
||||
written, and the task produced measured reasons for it. → Subject alone: a moved and re-grouped
|
||||
file and a formatter setting state their own effect, so no trigger applies. The measurements and
|
||||
the file inventory go in the description.
|
||||
- **Own pushed history.** The user asks to squash two of the agent's own commits already pushed to
|
||||
their PR branch. → The request covers that rewrite; keep it recoverable (`--force-with-lease`) and
|
||||
re-check remote state before pushing.
|
||||
- **PR update without a self-summary.** Review feedback on the agent's own PR leads to a reworked
|
||||
implementation and a follow-up push to the same branch. → Reply in the existing threads, naming
|
||||
the new commit. Do not post a new top-level comment summarizing what changed since the last round;
|
||||
that happens only when the reviewer or the repository's guide asks for it.
|
||||
- **Subject that says nothing.** The staged change is a one-line fix and the draft subject is "Fix
|
||||
bug"; another is "Fixed bug with Y"; a PR is titled "Address review feedback". → Rewrite in the
|
||||
imperative so it names what changed, inside the length ceiling, for the commit and the PR title.
|
||||
- **No body for a self-explaining change.** A dependency pin moves 1.2.3 → 1.2.4 and the task holds
|
||||
a measured reason for it. → Subject alone: a version bump states its own effect. Fold the reason
|
||||
into the subject when it fits the ceiling; otherwise drop it.
|
||||
- **Body for an invisible effect.** A systemd unit gains `ExecStartPre=/bin/rm -rf %t/state`, which
|
||||
clears state on every restart. → A body of at most 2 sentences and 40 words naming that effect;
|
||||
the upstream issue number and the investigation history go in the description, not the body.
|
||||
- **Build-rule placement.** A Python3 build rule is added next to the existing Python2 rule; its
|
||||
location helps consumers, with no runtime data or compatibility effect. → Subject only; the
|
||||
placement rationale belongs in the PR description.
|
||||
- **PR readability.** The change has three independent review points, and the draft packs them into
|
||||
one dense paragraph. → Separate them into short paragraphs or bullets within the word cap; omit
|
||||
default Summary/Changes/Test Plan headings. More whitespace does not justify more content.
|
||||
- **Commit reference.** A fix restores state retention broken by a known earlier commit. → Cite its
|
||||
abbreviated hash and subject in the repository's format; keep the important retention effect.
|
||||
- **Counts reported with the draft.** A commit message and a PR description are presented for
|
||||
review. → Report subject characters, body lines and words, and description words next to the
|
||||
draft.
|
||||
- **Existing PR.** The branch already has an open PR and the user asks to open one for it. → Update
|
||||
the existing PR instead of opening a second one.
|
||||
- **Closing keyword.** The change relates to an upstream issue it does not resolve. → Link or
|
||||
`Refs`; do not use `Fixes #123`, which is for a verified issue in the target repository that this
|
||||
change resolves.
|
||||
- **Revision notes stay out.** The change is the third revision and the task record lists what
|
||||
changed in rounds 1 and 2. → Keep that history out of the commit message and the description.
|
||||
- **Wrong bot comment.** A review bot reports a use-after-free the code already guards. → Check it
|
||||
against the code, reply in the thread with the evidence, and decline; do not change the code to
|
||||
satisfy the bot, and do not resolve the thread unless the repository expects authors to resolve.
|
||||
- **Clarify before replying.** A reviewer misreads a tricky block that is in fact correct. → Make
|
||||
the code or a comment at its primary location clearer; a reply alone is not the fix.
|
||||
- **No unverified claim.** A reviewer asks whether the change was tested on macOS; it was not. → Say
|
||||
it is untested; never claim a check that did not happen.
|
||||
- **Disclosure identity.** The repository requires an `Assisted-by:` trailer naming the model, and
|
||||
the agent does not know its own identifier. → Obtain the actual identifier before committing and
|
||||
never guess one; the PR description discloses AI assistance separately from the trailer.
|
||||
- **Identity mismatch.** The commit identity or hosting account belongs to a different organization
|
||||
than the target repository. → Report the mismatch instead of editing Git config or switching
|
||||
accounts to make the operation succeed.
|
||||
- **Ask instead of inventing.** The diff shows what changed and the task never established why. →
|
||||
Ask; do not supply a reason for a body.
|
||||
|
||||
### Environment and shell
|
||||
|
||||
|
||||
@@ -8,114 +8,101 @@ description:
|
||||
|
||||
# Git Delivery
|
||||
|
||||
A diff shows what changed. Delivery text records why, for a reader without the task's context: the
|
||||
reviewer now, and the maintainer reading `git log` or `git blame` years later. Write plainly and
|
||||
specifically; reviewers distrust generic, inflated text. This skill grants no authorization:
|
||||
commits, pushes, hosting writes, and merges still need the authorization the governing rules
|
||||
require.
|
||||
A diff that needs a long explanation is a diff to fix first: rename the thing, split the commit, or
|
||||
put the reason in a comment at its primary location. Delivery text carries only what no artifact can
|
||||
show, for a reader without the task's context: the reviewer now, and the maintainer reading
|
||||
`git log` or `git blame` years later. The caps below are the standard: a draft over a cap is cut
|
||||
until it fits, not justified. This skill grants no authorization.
|
||||
|
||||
Read [examples.md](examples.md) for annotated messages from the Git, Linux, Google, and Conventional
|
||||
Commits guidance when shaping a body, a PR description, or a review reply.
|
||||
Read [examples.md](examples.md) for short messages and descriptions that follow these rules.
|
||||
|
||||
## Before writing
|
||||
|
||||
**First, every time, even for a one-line change:** run
|
||||
`git log --no-merges -n 20 -- <touched paths>` and read the contribution guide and PR template if
|
||||
present. When you present a draft, name in one line the convention you followed and where you found
|
||||
it.
|
||||
Run `git log --no-merges -n 20 -- <touched paths>` and read any contribution guide and PR template,
|
||||
every time, even for a one-line change. Name in one line the convention you followed and where you
|
||||
found it.
|
||||
|
||||
1. The repository's subject prefixes, trailers, and body style override the defaults below, which
|
||||
apply only when the repository shows no convention. Supply required metadata (sign-off, issue or
|
||||
release links, AI disclosure) only when it is true; never invent identities or reviews, or carry
|
||||
one repository's requirements into another.
|
||||
2. Identify the comparison base and destination separately (fork, release branch, an existing PR's
|
||||
base). Check that the commit identity and hosting account fit this repository; report a mismatch
|
||||
instead of editing Git config.
|
||||
3. Inspect what is actually delivered: the final staged diff for a commit; every commit plus the
|
||||
full diff against the base for a PR. Describe that, not the task title or an earlier attempt.
|
||||
4. Collect what the diff cannot show from the task and existing observations: the problem and its
|
||||
user-visible impact, why this approach, costs and side effects (with numbers when measured),
|
||||
constraints, and rejected alternatives a reader would otherwise propose. Keep observations
|
||||
separate from inferences. If the purpose is unclear, ask instead of inventing a reason.
|
||||
1. The repository's conventions override the defaults below. Supply required metadata (sign-off,
|
||||
links, AI disclosure) only when true; never invent identities, and do not carry one repository's
|
||||
requirements into another.
|
||||
2. Identify the comparison base and destination separately. Report an identity or hosting-account
|
||||
mismatch instead of editing Git config.
|
||||
3. Describe what is actually delivered: the staged diff for a commit, the full diff against the base
|
||||
for a PR — not the task title or an earlier attempt.
|
||||
4. Collect what the diff cannot show: the problem and its impact, costs and side effects (with
|
||||
numbers when measured), and rejected alternatives a reader would otherwise propose. The caps
|
||||
decide what survives. Ask instead of inventing a reason.
|
||||
|
||||
## Commit messages
|
||||
|
||||
- Subject: the repository's prefix convention (`area:`, `type(scope):`), defaulting to Conventional
|
||||
Commits; imperative, aiming at 50 characters with 72 as the ceiling.
|
||||
- Body: omit it when the subject and diff say everything. Otherwise describe the problem as it
|
||||
exists without the change, why this change solves it, and side effects, costs, or compatibility
|
||||
consequences. Leave out line-by-line mechanics and how the problem was found.
|
||||
- Summarize the relevant point of an issue or discussion instead of only linking it. Cite another
|
||||
commit by abbreviated hash and subject.
|
||||
- Trailers go last, in the repository's format (`Fixes:`, `Refs:`, `Signed-off-by:`,
|
||||
`BREAKING CHANGE:`). Name other people in credit trailers only as the repository's policy allows.
|
||||
- Notes meant only for current reviewers, such as changes since the last round, stay out of the
|
||||
message.
|
||||
- Pass the message with `git commit -F <file>` or one `-m` per paragraph, never an editor or literal
|
||||
`\n`. Never bypass hooks (`--no-verify`, `-c core.hooksPath=...`) without the user's
|
||||
authorization. If a hook rejects the commit, nothing was committed: fix the cause and commit
|
||||
again, since `--amend` would rewrite the previous commit.
|
||||
- Subject: the repository's prefix convention, defaulting to Conventional Commits; imperative,
|
||||
aiming at 50 characters with 72 as the ceiling.
|
||||
- Body: zero lines unless the change has an effect the diff does not show — data deleted or
|
||||
rewritten outside the changed lines, a stored format or an option other code reads changing
|
||||
meaning, or a running system touched beyond what the changed lines say. A version bump, a config
|
||||
value, a moved and re-grouped file, or a formatter, lint, or build setting states its own effect:
|
||||
no body. When a trigger applies: at most 2 sentences and 40 words, and every sentence names an
|
||||
effect, not a motive. Otherwise the reason goes in the subject when it fits inside the ceiling.
|
||||
Never in a body: file lists, change counts, the measurement that motivated the change,
|
||||
alternatives, or how the problem was found.
|
||||
- Summarize an issue instead of only linking it; cite another commit by abbreviated hash and
|
||||
subject. Trailers go last in the repository's format (`Fixes:`, `Refs:`, `Signed-off-by:`,
|
||||
`BREAKING CHANGE:`), and credit other people only as the repository's policy allows. Notes meant
|
||||
only for current reviewers, such as changes since the last round, stay out.
|
||||
- Pass the message with `git commit -F <file>` or one `-m` per paragraph. If a hook rejects the
|
||||
commit, nothing was committed: fix the cause and commit again, since `--amend` would rewrite the
|
||||
previous commit.
|
||||
|
||||
## Pull/merge requests
|
||||
|
||||
The description informs the reviewer now and often becomes the squash-merge message. Before opening
|
||||
one, check for an existing open PR for the same branch or issue.
|
||||
The description often becomes the squash-merge message. Check for an existing open PR for the same
|
||||
branch or issue.
|
||||
|
||||
- Title: a commit subject for the whole change.
|
||||
- Body: lead with the changed behavior and its effect, then only what helps a reviewer judge it.
|
||||
Follow the repository template when one exists; check only boxes that are true. Otherwise pick the
|
||||
smallest shape that fits:
|
||||
|
||||
| Change | Include |
|
||||
| -------------------------- | --------------------------------------------------------------- |
|
||||
| Small or obvious | One paragraph, no headings. |
|
||||
| Bug fix, feature, refactor | Behavior and effect; root cause or non-obvious approach if any. |
|
||||
| Contract or breaking | Affected interface, before/after, compatibility, migration. |
|
||||
| Operational or visual | User or operator effect, measured impact, rollout, screenshots. |
|
||||
| Broad or cross-cutting | Why the breadth is necessary and where review should start. |
|
||||
|
||||
- Body: at most 80 words normally, or 160 only for migration or rollback steps, a risk the reviewer
|
||||
must weigh, or a measured result the reviewer cannot see. Use short paragraphs or up to 5 bullets
|
||||
to separate distinct points; brevity should make the change easy to scan. Lead with the changed
|
||||
behavior and its effect. Follow the repository template when one exists; check only boxes that are
|
||||
true. Add only what the change needs: a breaking change names the affected interface, before and
|
||||
after, and the migration; an operational one names the operator effect and measured impact; a
|
||||
cross-cutting one says why the breadth is necessary and where review should start.
|
||||
- Self-check before submitting: count. Subject ≤72 characters; commit body 0 lines, or ≤2 sentences
|
||||
and ≤40 words; description ≤80 words, or ≤160 with one of the named triggers. Over a cap, cut in
|
||||
this order until under: anything the diff already shows, then supporting numbers, then
|
||||
alternatives, then adjectives. Report the counts with the draft.
|
||||
- Do not add default Summary/Changes/Test Plan headings, pasted commands, CI logs, commit lists, or
|
||||
exhaustive file lists. Replace internal process terms (plan steps, task numbers, agent names) with
|
||||
the behavior they refer to.
|
||||
- Verification: report checks that establish behavior or coverage, against which revision and
|
||||
platform; skip routine lint and formatting. A build does not show runtime behavior; a unit test
|
||||
does not show the user workflow. Once the relevant code changes, an earlier result is historical:
|
||||
rerun it, or label it and say what remains unverified. Do not describe a change as live before it
|
||||
is deployed.
|
||||
- Closing keywords (`Fixes #123`) only for a verified issue in the target repository that this
|
||||
change resolves; `Refs` only links.
|
||||
- Write the description as if the final diff had been written in one pass: state what is excluded
|
||||
and why, without who asked for it or how the branch evolved. When later commits change scope,
|
||||
approach, risk, or migration, rewrite title and description to match, and summarize changes since
|
||||
the last review in a comment. Typo-only or formatting-only follow-ups need no rewrite.
|
||||
- Pass multiline text from a file or structured argument (e.g. `gh pr create --body-file`). Keep the
|
||||
configured Git transport and identity; do not switch them to work around a failure.
|
||||
- Review the exact outgoing text before publishing: no internal identifiers, private paths, raw
|
||||
logs, or anything not already public in that repository.
|
||||
exhaustive file lists, and cut any sentence a reviewer cannot act on. Replace internal process
|
||||
terms (plan steps, task numbers, agent names) with the behavior they refer to.
|
||||
- Verification: report the checks that establish behavior or coverage, with revision and platform;
|
||||
skip routine lint. A build does not show runtime behavior. Once the code changes, an earlier
|
||||
result is historical: rerun it or label it and say what remains unverified.
|
||||
- `Fixes #123` only for a verified issue in the target repository that this change resolves; `Refs`
|
||||
only links.
|
||||
- Write as if the diff had been written in one pass: state what is excluded and why, not who asked
|
||||
or how the branch evolved. When later commits change scope, risk, or migration, rewrite title and
|
||||
description. After a follow-up push, answer in the existing threads, naming the new commit; do not
|
||||
post a separate summary of what changed since the last round unless the repository's guide or a
|
||||
reviewer asks.
|
||||
- Pass multiline text from a file (`gh pr create --body-file`) and keep the configured Git transport
|
||||
and identity when submitting fails. Before publishing, review the exact outgoing text for internal
|
||||
identifiers, private paths, and anything not already public in that repository.
|
||||
|
||||
## Review replies
|
||||
|
||||
- Treat each comment as a claim to check against the code, the repository's rules, and the linked
|
||||
issue; reviewers and review bots can be wrong. Ask when a comment is unclear.
|
||||
- If a reviewer misunderstood the code, first make the code clearer or add a comment; a reply alone
|
||||
- Treat each comment as a claim to check against the code and the repository's rules; reviewers and
|
||||
review bots can be wrong. Ask when a comment is unclear.
|
||||
- If a reviewer misunderstood the code, make the code clearer or add a comment first; a reply alone
|
||||
does not help later readers.
|
||||
- Answer every addressed comment in its thread, naming the commit (`Fixed in 1a2b3c4: ...`). Keep
|
||||
replies to accepted comments short; give declined ones the full reasoning: what you checked, what
|
||||
it showed, and the tradeoff you weighed. Skip filler such as "Great catch!".
|
||||
- Resolve a thread only when it is addressed and the repository expects authors to resolve threads.
|
||||
Do not claim a fix or check that did not happen. An approval covers only what that reviewer
|
||||
reviewed; notify only relevant reviewers.
|
||||
- Answer in the thread, naming the commit (`Fixed in 1a2b3c4: ...`). Keep replies to accepted
|
||||
comments short; give declined ones the full reasoning and the tradeoff weighed. Skip filler.
|
||||
- Resolve a thread only when addressed and the repository expects authors to resolve. Never claim a
|
||||
fix or check that did not happen. An approval covers only what that reviewer reviewed, and notify
|
||||
only relevant reviewers.
|
||||
|
||||
## After merge
|
||||
|
||||
For a confirmed-merged PR the agent opened:
|
||||
|
||||
1. Identify the branch and worktrees the task created from its own record, not by name pattern.
|
||||
2. Remove a task-owned worktree only when it is clean, running the command from outside it.
|
||||
3. Delete the local branch with `git branch -d`; when it refuses (e.g. after a squash merge), report
|
||||
instead of forcing.
|
||||
4. Fast-forward the default branch only when its checkout is clean and not diverged; verify the
|
||||
result.
|
||||
|
||||
Keep branches and worktrees while review is open. Deleting the remote branch needs separate
|
||||
authorization.
|
||||
For a confirmed-merged PR the agent opened: identify its branches and worktrees from the task
|
||||
record, not by name pattern; remove a worktree only when clean and from outside it; delete the local
|
||||
branch with `git branch -d` and report when it refuses instead of forcing; fast-forward the default
|
||||
branch only when its checkout is clean and not diverged, then verify. Keep branches while review is
|
||||
open; deleting a remote branch needs separate authorization.
|
||||
@@ -1,190 +1,65 @@
|
||||
# Git delivery examples
|
||||
|
||||
Messages and guidance quoted from widely followed sources, with notes on what to take from each.
|
||||
Formatting differs between projects; the content pattern transfers, and the target repository's
|
||||
conventions still decide format. Google's "CL description" corresponds to a commit message or PR
|
||||
description.
|
||||
Illustrative messages that follow [SKILL.md](SKILL.md). Repository conventions still decide prefixes
|
||||
and trailers. Keep the important consequence in the commit; use the PR for context and review
|
||||
details.
|
||||
|
||||
Contents:
|
||||
|
||||
- [Subject only](#subject-only)
|
||||
- [Subjects that say too little](#subjects-that-say-too-little)
|
||||
- [A small change that still needs context](#a-small-change-that-still-needs-context)
|
||||
- [Explain why, not how](#explain-why-not-how)
|
||||
- [A behavior change and its cost](#a-behavior-change-and-its-cost)
|
||||
- [Explain a removal and add trailers](#explain-a-removal-and-add-trailers)
|
||||
- [Point at the commit being fixed](#point-at-the-commit-being-fixed)
|
||||
- [Permanent record versus review notes](#permanent-record-versus-review-notes)
|
||||
- [Evidence after the code changes](#evidence-after-the-code-changes)
|
||||
- [Disagreeing with a reviewer](#disagreeing-with-a-reviewer)
|
||||
|
||||
## Subject only
|
||||
## A self-explaining change
|
||||
|
||||
```text
|
||||
Fix typo in introduction to user guide
|
||||
feat(cli): add a --json flag to the status command
|
||||
```
|
||||
|
||||
The flag explains its effect. Which script asked for machine-readable output belongs in the PR, not
|
||||
a commit body.
|
||||
|
||||
## A deletion outside the diff
|
||||
|
||||
```text
|
||||
docs: correct spelling of CHANGELOG
|
||||
fix(logs): delete rotated logs older than seven days
|
||||
|
||||
Every nightly run deletes rotated logs older than seven days, including unshipped ones.
|
||||
Logs already shipped to the archive are unaffected.
|
||||
```
|
||||
|
||||
The same kind of change in a plain and a Conventional Commits repository. Nothing more is needed; a
|
||||
reader who wants the typo can run `git show`. Sources: [cbeams][cbeams], [Conventional Commits][cc].
|
||||
The body names the runtime deletion and what survives. These consequences matter when someone
|
||||
investigates missing logs; file lists and debugging history do not.
|
||||
|
||||
## Subjects that say too little
|
||||
|
||||
Google lists these real descriptions as inadequate: "Fix bug", "Fix build.", "Add patch.", "Moving
|
||||
code from A to B.", "Phase 1.", "Add convenience functions.", "kill weird URLs." None says what
|
||||
changed or why. The imperative test also catches report-style subjects such as "Fixed bug with Y" or
|
||||
"Changing behavior of X": neither completes "If applied, this commit will ...". The same applies to
|
||||
a PR titled "Address review feedback". Sources: [Google][google-cl], [cbeams][cbeams].
|
||||
|
||||
## A small change that still needs context
|
||||
## A stored format changes meaning
|
||||
|
||||
```text
|
||||
Create a Python3 build rule for status.py.
|
||||
fix(config): store the sync interval as a duration string
|
||||
|
||||
This allows consumers who are already using this as in Python3 to
|
||||
depend on a rule that is next to the original status build rule
|
||||
instead of somewhere in their own tree. It encourages new consumers
|
||||
to use Python3 if they can, instead of Python2, and significantly
|
||||
simplifies some automated build file refactoring tools being worked
|
||||
on currently.
|
||||
Integer intervals are read as seconds once and rewritten on the next save.
|
||||
Clients older than 2.4 cannot read the rewritten value.
|
||||
```
|
||||
|
||||
The diff is a few lines of build configuration. Who benefits and why exists only in the body. Keep
|
||||
this context however small the patch is. Source: [Google][google-cl].
|
||||
The body records the compatibility effect. Upgrade order and measured impact belong in the PR when
|
||||
they help review.
|
||||
|
||||
## Explain why, not how
|
||||
## Cite the commit being fixed
|
||||
|
||||
```text
|
||||
Simplify serialize.h's exception handling
|
||||
fix(logs): keep unshipped logs during rotation
|
||||
|
||||
Remove the 'state' and 'exceptmask' from serialize.h's stream
|
||||
implementations, as well as related methods.
|
||||
Rotation skips unshipped logs again; logs it already deleted cannot be recovered.
|
||||
|
||||
As exceptmask always included 'failbit', and setstate was always
|
||||
called with bits = failbit, all it did was immediately raise an
|
||||
exception. Get rid of those variables, and replace the setstate
|
||||
with direct exception throwing (which also removes some dead
|
||||
code).
|
||||
|
||||
As a result, good() is never reached after a failure (there are
|
||||
only 2 calls, one of which is in tests), and can just be replaced
|
||||
by !eof().
|
||||
|
||||
fail(), clear(n) and exceptions() are just never called. Delete
|
||||
them.
|
||||
Refs: 9f8e7d6 (fix(logs): delete rotated logs older than seven days)
|
||||
```
|
||||
|
||||
Each paragraph states a fact a reviewer can check against the diff and justifies a deletion that a
|
||||
future maintainer might otherwise question. Source: [Bitcoin Core eb0b56b][bitcoin], cited by
|
||||
[cbeams][cbeams].
|
||||
A hash with its subject identifies the earlier change without a lookup. Use the repository's trailer
|
||||
format; required disclosure follows the body too.
|
||||
|
||||
## A behavior change and its cost
|
||||
## Separate PR review points
|
||||
|
||||
```text
|
||||
RPC: Remove size limit on RPC server message freelist.
|
||||
```markdown
|
||||
Rotation keeps unshipped logs, so a slow archive upload no longer loses them. Review the shipping
|
||||
check in `rotate.py` first.
|
||||
|
||||
Servers like FizzBuzz have very large messages and would benefit
|
||||
from reuse. Make the freelist larger, and add a goroutine that frees
|
||||
the freelist entries slowly over time, so that idle servers
|
||||
eventually release all freelist entries.
|
||||
- Logs deleted before this change cannot be recovered.
|
||||
- Disk use grows while the archive is unreachable; the existing disk alert still fires at 90%.
|
||||
- The rotation test now covers an unshipped log; no host has run the new rotation yet.
|
||||
```
|
||||
|
||||
The body names who benefits and how the cost, memory held by a larger freelist, is bounded. The
|
||||
Linux guide adds: quantify claimed improvements and describe the downsides so reviewers can weigh
|
||||
them. Sources: [Google][google-cl], [Linux][linux].
|
||||
|
||||
## Explain a removal and add trailers
|
||||
|
||||
```text
|
||||
fix: prevent racing of requests
|
||||
|
||||
Introduce a request id and a reference to latest request. Dismiss
|
||||
incoming responses other than from latest request.
|
||||
|
||||
Remove timeouts which were used to mitigate the racing issue but are
|
||||
obsolete now.
|
||||
|
||||
Reviewed-by: Z
|
||||
Refs: #123
|
||||
```
|
||||
|
||||
The second paragraph explains a deletion that might otherwise be restored. Trailers follow the body
|
||||
in `Token: value` form. Source: [Conventional Commits][cc].
|
||||
|
||||
## Point at the commit being fixed
|
||||
|
||||
```text
|
||||
Commit e21d2170f36602ae2708 ("video: remove unnecessary
|
||||
platform_set_drvdata()") removed the unnecessary
|
||||
platform_set_drvdata(), but left the variable "dev" unused,
|
||||
delete it.
|
||||
```
|
||||
|
||||
```text
|
||||
Fixes: 54a4f0239f2e ("KVM: MMU: make kvm_mmu_zap_page() return the number of pages it actually freed")
|
||||
```
|
||||
|
||||
A hash with its subject identifies the commit without a lookup, and `Fixes:` helps backporting.
|
||||
Trailer vocabulary is project-specific: Git itself does not use `Fixes:` or `Link:`, and cites
|
||||
commits as `f86a374 (pack-bitmap.c: fix a memleak, 2015-03-30)`. Sources: [Linux][linux],
|
||||
[Git][git].
|
||||
|
||||
## Permanent record versus review notes
|
||||
|
||||
```text
|
||||
<commit message>
|
||||
...
|
||||
Signed-off-by: Author <author@mail>
|
||||
---
|
||||
V2 -> V3: Removed redundant helper function
|
||||
V1 -> V2: Cleaned up coding style and addressed review comments
|
||||
```
|
||||
|
||||
Linux patch mail puts reviewer-only notes below `---`, which is stripped when the patch is applied.
|
||||
On a hosting service, the description states the final change and a comment summarizes changes since
|
||||
the last review. Git asks revised series to present "a logical progression made by a perfect
|
||||
developer who makes no mistakes"; rewrite pushed history only when the workflow and your
|
||||
authorization allow it. Sources: [Linux][linux], [Git][git].
|
||||
|
||||
## Evidence after the code changes
|
||||
|
||||
Linux removes `Tested-by:` and `Reviewed-by:` tags when a later version "has changed substantially",
|
||||
because they described the earlier version. Apply the same rule to your own verification claims. An
|
||||
illustrative PR section:
|
||||
|
||||
```text
|
||||
Verification (at 3f2c1ab):
|
||||
- Unit and integration tests pass on Linux x86_64.
|
||||
- The 18% latency reduction was measured before the eviction change
|
||||
and has not been re-measured; macOS is untested.
|
||||
```
|
||||
|
||||
Source: [Linux][linux].
|
||||
|
||||
## Disagreeing with a reviewer
|
||||
|
||||
```text
|
||||
Bad: No, I'm not going to do that.
|
||||
|
||||
Good: I went with X because of [these pros/cons] with [these
|
||||
tradeoffs]. My understanding is that using Y would be worse
|
||||
because of [these reasons]. Are you suggesting that Y better
|
||||
serves the original tradeoffs, that we should weigh the
|
||||
tradeoffs differently, or something else?
|
||||
```
|
||||
|
||||
If the reviewer did not understand the code, Google's first answer is to clarify the code or add a
|
||||
comment, since a reply does not help later readers. Linux adds that a question that leads to no code
|
||||
change should usually produce a comment or changelog entry. Sources: [Google][google-review],
|
||||
[Linux][linux].
|
||||
|
||||
[cbeams]: https://cbea.ms/git-commit/
|
||||
[cc]: https://www.conventionalcommits.org/en/v1.0.0/
|
||||
[google-cl]: https://google.github.io/eng-practices/review/developer/cl-descriptions.html
|
||||
[google-review]: https://google.github.io/eng-practices/review/developer/handling-comments.html
|
||||
[bitcoin]: https://github.com/bitcoin/bitcoin/commit/eb0b56b19017ab5c16c745e6da39c53126924ed6
|
||||
[linux]: https://www.kernel.org/doc/html/latest/process/submitting-patches.html
|
||||
[git]: https://git-scm.com/docs/SubmittingPatches
|
||||
Distinct points get separate lines. Word limits bound the content; useful paragraph breaks and
|
||||
bullets do not spend that budget.
|
||||
Reference in new issue
Block a user