From 85768dc489d9622152b12d2c91d298349032ab75 Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Tue, 18 Aug 2026 17:13:30 -0400 Subject: [PATCH] docs: put the closing keyword where Gitea will actually read it 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 --- CLAUDE.md | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 57c6f60..58ce0b9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -53,14 +53,40 @@ reinvention: - **Hard blockers are real Gitea dependencies**, which render on the issue itself, and the blocked issue carries `Status/Blocked`. - **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 -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 ` after the merge, with a comment naming -the commit that shipped it. `close` also drops `Status/In Progress`, -because a claim outlives the work if nothing takes the label off. +**The closing keyword goes in the commit body, one issue per line.** + +``` +docs: delete four documents that contradict the code + + + +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 +` 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