Compare commits

...
Author SHA1 Message Date
yonlu 97f2eb85ee docs: put the closing keyword where Gitea will actually read it
CI / check (push) Skipped
CI / e2e (push) Skipped
CLAUDE.md said the Closes list was unreliable and to close by hand. It
is unreliable for a specific reason, and the rule can say what works.

Gitea parses commit messages that reach main. It does not parse the PR
body, which closes something only if the merge happens to copy it into
the merge commit message. Both halves were measured here: #83's merge
commit carried "Closes #9, #13, #14, ..." and closed five of the ten,
because a comma list is only partially matched; #93's merge commit body
was a lone Reviewed-on: trailer, so #92 stayed open behind a perfectly
correct Closes line in the PR description.

So the keyword goes in the commit body as a footer, one issue per line.
That costs nothing elsewhere -- Conventional Commits allows a footer,
commit-check only regexes the subject, and semantic-release reads the
type from the subject, so no release decision changes. The existing
rule that the issue number stays out of the subject is untouched and
was never about the body.

The verification step stays, because a squash or a hand-edited merge
message still drops the footer.

This commit is the experiment: if #98 and #100 close when this branch
merges without anyone touching them, the mechanism is confirmed.

Closes #98
Closes #100
2026-08-18 17:13:30 -04:00
+33 -7
View File
@@ -53,14 +53,40 @@ reinvention:
- **Hard blockers are real Gitea dependencies**, which render on the - **Hard blockers are real Gitea dependencies**, which render on the
issue itself, and the blocked issue carries `Status/Blocked`. issue itself, and the blocked issue carries `Status/Blocked`.
- **A PR body carries a commit-to-issue table, the verification - **A PR body carries a commit-to-issue table, the verification
actually run, and a `Closes` list** — PR #83 is the shape. actually run, and a `Closes` list** — PR #83 is the shape. That list
is for whoever reads the PR; what actually closes an issue is the
footer below.
**And the `Closes` list does not reliably close anything.** #83 listed **The closing keyword goes in the commit body, one issue per line.**
ten and five of them stayed open, shipped in `main`, for a fortnight.
So closing is a step you take and check, not a keyword you trust: ```
`./scripts/issue.sh close <n>` after the merge, with a comment naming docs: delete four documents that contradict the code
the commit that shipped it. `close` also drops `Status/In Progress`,
because a claim outlives the work if nothing takes the label off. <body>
Closes #98
```
**Gitea parses commit messages that reach `main`; it does not parse the
PR body**, which only closes anything if the merge happens to copy it
into the merge commit. Both halves of that were measured. #83's merge
commit carried `Closes #9, #13, #14, …` and closed **five of ten** — a
comma list is partially matched. #93's merge commit body was one
`Reviewed-on:` trailer, so #92 stayed open behind a perfectly correct
`Closes` line in the PR description.
A footer costs nothing elsewhere: Conventional Commits allows one,
`scripts/commit-check.sh` only regexes the subject, and
semantic-release reads the type from the subject — so this changes no
release decision. The rule that the issue number stays out of the
**subject** is unaffected, and was never about the body.
**Check it anyway.** A squash, or a merge message edited by hand,
still drops the footer. `./scripts/issue.sh list --state open` after a
merge, looking for what you just shipped; `./scripts/issue.sh close
<n>` for whatever did not take, with a comment naming the commit.
`close` also drops `Status/In Progress`, because a claim outlives the
work if nothing takes the label off.
## Planning ## Planning