@biffo/cli 0.296.7 → 0.296.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/claim.sh +72 -7
package/package.json
CHANGED
package/scripts/claim.sh
CHANGED
|
@@ -285,6 +285,29 @@ remote_branches() {
|
|
|
285
285
|
fi
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
# What issue does $1 derive, per the `<type>/<number>-<slug>` convention,
|
|
289
|
+
# with leading zeros stripped -- or empty if $1 names no issue at all (#1672).
|
|
290
|
+
#
|
|
291
|
+
# ONE place both sides of a collision check go through. `--guard`'s own
|
|
292
|
+
# derivation used to run this pattern once for its own branch and then match
|
|
293
|
+
# CANDIDATE branches with a completely different technique -- a boundary-
|
|
294
|
+
# anchored substring search over the raw, unstripped candidate text. That
|
|
295
|
+
# let a zero-padded branch (`feat/0010-x`) go unmatched against an identical
|
|
296
|
+
# zero-padded sibling (`feat/0010-y`), because the search side had been
|
|
297
|
+
# stripped to `10` and `10` cannot match inside literal `0010` at a boundary
|
|
298
|
+
# (the character before it is `0`, itself alphanumeric). Deriving BOTH sides
|
|
299
|
+
# through this one function and comparing the two normalised numbers, rather
|
|
300
|
+
# than searching for one inside the other's text, removes the asymmetry
|
|
301
|
+
# structurally: whatever stripping happens to the target happens identically
|
|
302
|
+
# to the candidate. It is also deliberately narrower than a bare substring
|
|
303
|
+
# search -- `dm-04` and `104` carry no `/`, so nothing is derived from them,
|
|
304
|
+
# which is what keeps a bare `4` from colliding with either.
|
|
305
|
+
derive_branch_issue() {
|
|
306
|
+
_dbi_n=$(printf '%s' "$1" | sed -n 's#^[^/]*/\([0-9][0-9]*\)-.*#\1#p')
|
|
307
|
+
[ -n "$_dbi_n" ] || return 0
|
|
308
|
+
printf '%s' "$_dbi_n" | sed 's/^0*\([0-9]\)/\1/'
|
|
309
|
+
}
|
|
310
|
+
|
|
288
311
|
# --- the structural claim predicate (#1411, class #1362 instance 8) ---------
|
|
289
312
|
#
|
|
290
313
|
# "Does this open PR claim issue $1?" used to be answered independently at
|
|
@@ -304,8 +327,24 @@ remote_branches() {
|
|
|
304
327
|
# 1. `closingIssuesReferences` -- GitHub's OWN parse of a recognised closing
|
|
305
328
|
# keyword (Closes/Fixes/Resolves and their inflections). Authoritative;
|
|
306
329
|
# never re-derived by a regex here.
|
|
307
|
-
# 2. the branch name (`<type>/<number>-slug`)
|
|
308
|
-
#
|
|
330
|
+
# 2. the branch name (`<type>/<number>-slug`) -- DERIVED the same way on
|
|
331
|
+
# BOTH sides (#1672), not matched as a substring of one. A boundary
|
|
332
|
+
# regex over the raw `headRefName` text, tested against a search number
|
|
333
|
+
# already stripped of leading zeros, is how a zero-padded PR went blind:
|
|
334
|
+
# `0010` strips to `10`, and `(^|[^0-9A-Za-z])10([^0-9A-Za-z]|$)` cannot
|
|
335
|
+
# match literal `0010`, because the preceding `0` is alphanumeric. Fixed
|
|
336
|
+
# by extracting the headRefName's OWN `<type>/<number>-` prefix via a jq
|
|
337
|
+
# capture, stripping ITS leading zeros the same way `guard_issue` is
|
|
338
|
+
# stripped below, and comparing the two normalised numbers for equality
|
|
339
|
+
# -- rather than searching for one inside the literal text of the other.
|
|
340
|
+
# This is deliberately narrower than a bare boundary-anchored substring
|
|
341
|
+
# search: `dm-04` and `104` carry no `/`, so nothing is derived from
|
|
342
|
+
# them at all, and a bare digit run that merely CONTAINS the target
|
|
343
|
+
# (`fix/13520-thing` vs issue 1352) still does not equal it once both
|
|
344
|
+
# are normalised. `capture()` produces NO output (not `false`) when the
|
|
345
|
+
# pattern does not match, which would silently drop the whole `or`
|
|
346
|
+
# chain for a PR like `chore/rename` if used bare -- wrapped in `[...]`
|
|
347
|
+
# first so a non-match becomes an empty array (one output), never zero.
|
|
309
348
|
# 3. the PR body, but ONLY AGENTS.md's own `Refs #N` convention -- the form
|
|
310
349
|
# this estate mandates for a PR that must reference an issue WITHOUT
|
|
311
350
|
# closing it (DDL PRs, "instance of a class" PRs like this one). A
|
|
@@ -319,12 +358,17 @@ remote_branches() {
|
|
|
319
358
|
# NOT claim #N" carries no claiming keyword adjacent to the `#N` and so
|
|
320
359
|
# correctly does not match either (#1327, #1311's exact shape).
|
|
321
360
|
#
|
|
361
|
+
# $1 is normalised (leading zeros stripped) HERE, once, rather than trusting
|
|
362
|
+
# every caller to have done it -- the plain (non-`--guard`) path passes the
|
|
363
|
+
# raw `$ISSUE` a caller typed, which may itself be zero-padded and was never
|
|
364
|
+
# stripped before reaching this function.
|
|
365
|
+
#
|
|
322
366
|
# $2 is the repo slug (`owner/name`) the closing-reference check compares
|
|
323
367
|
# against -- callers already resolve this via `repo_slug()` before calling.
|
|
324
368
|
claim_select_expr() {
|
|
325
|
-
_n
|
|
369
|
+
_n=$(printf '%s' "$1" | sed 's/^0*\([0-9]\)/\1/')
|
|
326
370
|
_slug="$2"
|
|
327
|
-
printf '(([.closingIssuesReferences[]? | select(.number == %s and ((.repository.owner.login + "/" + .repository.name) == "%s"))] | length > 0) or (.headRefName |
|
|
371
|
+
printf '(([.closingIssuesReferences[]? | select(.number == %s and ((.repository.owner.login + "/" + .repository.name) == "%s"))] | length > 0) or (([.headRefName | capture("^[^/]*/(?<n>[0-9]+)-")] | if length > 0 then ((.[0].n | sub("^0+";"")) as $s | if $s == "" then "0" else $s end) else "" end) == "%s") or ((.body // "") | test("(^|[^0-9A-Za-z])(refs?|references?)[ \\t]*:?[ \\t]*#%s([^0-9A-Za-z]|$)"; "i")))' \
|
|
328
372
|
"$_n" "$_slug" "$_n" "$_n"
|
|
329
373
|
}
|
|
330
374
|
|
|
@@ -399,7 +443,18 @@ fi
|
|
|
399
443
|
# question ("would this push collide with someone else's live work?" rather
|
|
400
444
|
# than "is this issue free to claim?").
|
|
401
445
|
if [ -n "$GUARD_BRANCH" ]; then
|
|
402
|
-
|
|
446
|
+
# A BATCH BRANCH NAMES A SEQUENCE, NOT AN ISSUE.
|
|
447
|
+
#
|
|
448
|
+
# `batch/04-stale-reconverge` fits `<type>/<number>-<slug>` exactly, so this read `04` as
|
|
449
|
+
# an issue and refused the push. Measured 2026-08-21: it blocked the FIRST reconverge the
|
|
450
|
+
# Lander ever attempted -- and batching is the remedy `fleet-land` prescribes for a strict
|
|
451
|
+
# branch, so this defect blocks the strategy meant to fix landing. `batch/02-gated-trio`
|
|
452
|
+
# escaped only because no open branch happened to contain `-02-`.
|
|
453
|
+
case "$GUARD_BRANCH" in
|
|
454
|
+
batch/*) exit 0 ;;
|
|
455
|
+
esac
|
|
456
|
+
|
|
457
|
+
guard_issue=$(derive_branch_issue "$GUARD_BRANCH")
|
|
403
458
|
|
|
404
459
|
# No issue named by the branch — most branches, e.g.
|
|
405
460
|
# `security/brace-expansion-5-0-9`. Skip silently, and — this is the point —
|
|
@@ -443,10 +498,20 @@ if [ -n "$GUARD_BRANCH" ]; then
|
|
|
443
498
|
cannot_tell=1
|
|
444
499
|
cannot_tell_reasons="${cannot_tell_reasons}${branch_err_text} "
|
|
445
500
|
else
|
|
501
|
+
# Derive each CANDIDATE branch's issue the same way $guard_issue was
|
|
502
|
+
# derived (#1672), and compare the two normalised numbers -- not a
|
|
503
|
+
# substring search for $guard_issue inside the candidate's raw text. See
|
|
504
|
+
# `derive_branch_issue` above for why that asymmetry was the defect.
|
|
446
505
|
other_branch=$(printf '%s\n' "$raw_branches" |
|
|
447
506
|
sed 's|.*refs/heads/||' |
|
|
448
|
-
grep -
|
|
449
|
-
|
|
507
|
+
grep -v -x "$GUARD_BRANCH" |
|
|
508
|
+
while IFS= read -r _cand; do
|
|
509
|
+
[ -n "$_cand" ] || continue
|
|
510
|
+
_cand_issue=$(derive_branch_issue "$_cand")
|
|
511
|
+
if [ -n "$_cand_issue" ] && [ "$_cand_issue" = "$guard_issue" ]; then
|
|
512
|
+
printf '%s\n' "$_cand"
|
|
513
|
+
fi
|
|
514
|
+
done | head -1)
|
|
450
515
|
if [ -n "$other_branch" ]; then
|
|
451
516
|
conflict=1
|
|
452
517
|
findings="${findings} ${RED}branch${OFF} $other_branch\n"
|