Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ ratio (R-5) is the control on that; capacity only decides what a date is allowed
| Predicate | Derive with | Fix |
|---|---|---|
| R-1 fixed-but-open | open issues cited by a `main` commit since the previous tag whose subject/body uses `Closes/Fixes/Resolves #N` or is `fix(...)`: must be ∅ | close with the commit sha as receipt |
| R-2 closing-reference | merged PRs since the previous tag whose body cites an issue without a closing keyword: must be ∅ going forward (guard `scripts/check_pr_closes_issue.sh` on the PR; `Refs #N` is allowed only with `no-close:` and a reason) | the guard refuses the PR |
| R-2 closing-reference | merged PRs since the previous tag whose body cites an issue without a closing keyword: must be ∅ going forward (guard `scripts/check_pr_closes_issue.sh` on the PR; `Refs #N` is allowed only with `keep-open:` and a reason — not `no-close:`, which GitHub's parser reads as a real closing keyword despite the negating prefix, #3400) | the guard refuses the PR |
| R-3 dead branches | remote branches with no open PR and a tip older than 14 d: must be ∅ | archive to `refs/archive/<branch>` (objects kept, reversible), then delete the head |
| R-4 dirty PRs | PRs `DIRTY` for more than one train: must be ∅ | a verdict per PR in the train: rebase (union tool, or by hand) or close with the reason |
| R-5 ratio | `closure / arrival` over the train window, recorded; ratchet as below | — |
Expand Down
17 changes: 16 additions & 1 deletion scripts/check_pr_closes_issue.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,16 @@ REF_RE='#[0-9]+'
# bare "close: #N" (that is CLOSE_RE's job, and is fine -- it really does
# close). "no-close:", "wont-fix:", "skip-resolve:" all match; "Closes #123"
# does not (nothing precedes "Closes").
NOCLOSE_LANDMINE_RE='[A-Za-z]+-(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)[[:space:]]*:[[:space:]]*([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+)?#[0-9]+'
#
# The colon is OPTIONAL, matching CLOSE_RE's own `:?` exactly -- an
# independent review of the first cut of this fix (evidence/pr-review/3497)
# found that a colon-less body ("no-fix #123 tracked elsewhere") satisfied
# CLOSE_RE (which never required the colon) while failing to satisfy a
# landmine regex that mandated one, so it was judged a VALID closing
# reference instead of the #3400 landmine it actually is. Confirmed as a real
# gap, not a false alarm: `no-fix #123` reproduces the exact bug this guard
# exists to catch, just spelled without the colon.
NOCLOSE_LANDMINE_RE='[A-Za-z]+-(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)[[:space:]]*:?[[:space:]]*([A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+)?#[0-9]+'

# A REFERENCE TO A PULL REQUEST IS NOT AN UN-CLOSED ISSUE.
#
Expand Down Expand Up @@ -234,6 +243,11 @@ STUB
write_case_landmine_noclose="no-close: #123"
write_case_landmine_wontfix=$'Closes #999\nwont-fix: #123 -- tracked separately'
write_case_landmine_mixed_with_valid_close=$'Closes #456\nno-close: #123 stays open for the GDN device path'
# PR #3497's own independent review (evidence/pr-review/3497) found this row
# missing: the colon is optional in CLOSE_RE, so it must be optional here too,
# or "no-fix #123" (no colon) reads as a VALID closing reference instead of
# the landmine it is.
write_case_landmine_no_colon="no-fix #123 tracked elsewhere"

run_case() {
name="$1"
Expand Down Expand Up @@ -263,6 +277,7 @@ STUB
run_case "landmine-noclose" "$write_case_landmine_noclose" 1
run_case "landmine-wontfix" "$write_case_landmine_wontfix" 1
run_case "landmine-mixed-with-valid-close" "$write_case_landmine_mixed_with_valid_close" 1
run_case "landmine-no-colon" "$write_case_landmine_no_colon" 1

# --- a PR reference is not an un-closed issue ---------------------------
run_kind_case() { # run_kind_case NAME BODY WANT [CMD]
Expand Down
Loading