@biffo/cli 0.243.1 → 0.244.0
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/_skeletons/plugin-template/.githooks/pre-push +54 -0
- package/_skeletons/sibling-template/.githooks/pre-push +54 -0
- package/_skeletons/sibling-template/apps/frontend/package.json +3 -2
- package/_skeletons/sibling-template/apps/frontend/pnpm-lock.yaml +53 -52
- package/package.json +1 -1
- package/scripts/claim.sh +147 -9
|
@@ -9,6 +9,19 @@
|
|
|
9
9
|
# own reporting. CI jobs that push (notably the core-v* tag workflow) have no
|
|
10
10
|
# `uv` on PATH, so firing here made tag pushes fail with `uv: not found` (code
|
|
11
11
|
# 127) and blocked releases. GitHub Actions and every mainstream CI set $CI.
|
|
12
|
+
# git EXPORTS GIT_DIR (and friends) into every hook. In a worktree that points
|
|
13
|
+
# at `<main>/.git/worktrees/<name>` -- a real directory, where an ordinary
|
|
14
|
+
# checkout has `.git` as a FILE -- and turbo reads it expecting the latter,
|
|
15
|
+
# dying with `I/O error: Is a directory (os error 21)` before a single test
|
|
16
|
+
# runs. Reproduced directly: `GIT_DIR=... pnpm turbo run test` fails, the same
|
|
17
|
+
# command without it passes 3/3.
|
|
18
|
+
#
|
|
19
|
+
# That made the gate unpassable from any worktree, which AGENTS.md section 1
|
|
20
|
+
# mandates as the place all work happens. Unsetting is safe: every git command
|
|
21
|
+
# below discovers the repo from the working directory, which is the worktree
|
|
22
|
+
# root and is what they should be operating on anyway.
|
|
23
|
+
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
|
|
24
|
+
|
|
12
25
|
[ -n "${CI:-}" ] && exit 0
|
|
13
26
|
|
|
14
27
|
# Escape hatch, deliberately explicit rather than a flag on git. `--no-verify`
|
|
@@ -40,6 +53,47 @@ cd "$root" || exit 0
|
|
|
40
53
|
# cannot run, that is a reason to stop, not to wave the push through.
|
|
41
54
|
sh scripts/biffo.sh rewrite-scope-check || exit 1
|
|
42
55
|
|
|
56
|
+
# --- Claim guard (#1231 instance 2) -------------------------------------------
|
|
57
|
+
#
|
|
58
|
+
# `scripts/claim.sh` (packaged inside `@biffo/cli`, run through the bridge
|
|
59
|
+
# above) has asked the estate's four-signal question about "is this issue
|
|
60
|
+
# taken?" since #1209 -- but nothing ever RAN it. It shipped advisory-only, so
|
|
61
|
+
# the fix for the collisions it exists to catch was itself subject to the same
|
|
62
|
+
# failure: a collision happens precisely when someone does not think to check.
|
|
63
|
+
#
|
|
64
|
+
# `--guard <branch>` is the enforced form. It derives the issue number from the
|
|
65
|
+
# branch name (`<type>/<number>-slug>`) and, when the branch names one, checks
|
|
66
|
+
# for another remote branch or another OPEN PR naming the same issue -- NEVER
|
|
67
|
+
# the `in-progress` label (three of four real collisions were "work exists,
|
|
68
|
+
# label does not") and NEVER identity (a claim on #1109 was recorded as
|
|
69
|
+
# `github-actions[bot]` because of a repo-local `user.email` override). It
|
|
70
|
+
# excludes the branch being pushed and any PR whose head IS that branch, so
|
|
71
|
+
# pushing your own branch a second time cannot block you on your own work.
|
|
72
|
+
#
|
|
73
|
+
# A branch that names no issue returns before any network call -- most
|
|
74
|
+
# branches are fine, and noise kills a gate. Measured on a branch that DOES
|
|
75
|
+
# name one: the added latency is the cost of two `gh` lookups, similar in
|
|
76
|
+
# order of magnitude to `rewrite-scope-check` above.
|
|
77
|
+
branch=$(git symbolic-ref --quiet --short HEAD) || branch=""
|
|
78
|
+
|
|
79
|
+
if [ -n "$branch" ]; then
|
|
80
|
+
sh scripts/biffo.sh claim --guard "$branch"
|
|
81
|
+
claim_status=$?
|
|
82
|
+
|
|
83
|
+
if [ "$claim_status" -eq 1 ]; then
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# $claim_status -eq 2 is "cannot tell" -- no network, gh unauthenticated, an
|
|
88
|
+
# API error -- and claim.sh has already printed a warning. Deliberately NOT
|
|
89
|
+
# blocked here: unlike every other gate in this file, this is a COORDINATION
|
|
90
|
+
# gate, not a correctness one. A false block costs the ability to push at
|
|
91
|
+
# all; a miss costs a recoverable collision caught early (every collision in
|
|
92
|
+
# #1209's own incident was caught before duplicate work merged). Set
|
|
93
|
+
# BIFFO_CLAIM_STRICT=1 to make claim.sh itself collapse cannot-tell into
|
|
94
|
+
# exit 1 instead, if you would rather block than guess.
|
|
95
|
+
fi
|
|
96
|
+
|
|
43
97
|
# Through the version-pinned CLI since #1109, so a repo cannot run a gate two
|
|
44
98
|
# versions old -- eight of them did, and tabsii-crm checked ONE thing in eight
|
|
45
99
|
# on a 700-line change and printed `verify passed` (#855). There is one copy of
|
|
@@ -9,6 +9,19 @@
|
|
|
9
9
|
# own reporting. CI jobs that push (notably the core-v* tag workflow) have no
|
|
10
10
|
# `uv` on PATH, so firing here made tag pushes fail with `uv: not found` (code
|
|
11
11
|
# 127) and blocked releases. GitHub Actions and every mainstream CI set $CI.
|
|
12
|
+
# git EXPORTS GIT_DIR (and friends) into every hook. In a worktree that points
|
|
13
|
+
# at `<main>/.git/worktrees/<name>` -- a real directory, where an ordinary
|
|
14
|
+
# checkout has `.git` as a FILE -- and turbo reads it expecting the latter,
|
|
15
|
+
# dying with `I/O error: Is a directory (os error 21)` before a single test
|
|
16
|
+
# runs. Reproduced directly: `GIT_DIR=... pnpm turbo run test` fails, the same
|
|
17
|
+
# command without it passes 3/3.
|
|
18
|
+
#
|
|
19
|
+
# That made the gate unpassable from any worktree, which AGENTS.md section 1
|
|
20
|
+
# mandates as the place all work happens. Unsetting is safe: every git command
|
|
21
|
+
# below discovers the repo from the working directory, which is the worktree
|
|
22
|
+
# root and is what they should be operating on anyway.
|
|
23
|
+
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
|
|
24
|
+
|
|
12
25
|
[ -n "${CI:-}" ] && exit 0
|
|
13
26
|
|
|
14
27
|
# Escape hatch, deliberately explicit rather than a flag on git. `--no-verify`
|
|
@@ -40,6 +53,47 @@ cd "$root" || exit 0
|
|
|
40
53
|
# cannot run, that is a reason to stop, not to wave the push through.
|
|
41
54
|
sh scripts/biffo.sh rewrite-scope-check || exit 1
|
|
42
55
|
|
|
56
|
+
# --- Claim guard (#1231 instance 2) -------------------------------------------
|
|
57
|
+
#
|
|
58
|
+
# `scripts/claim.sh` (packaged inside `@biffo/cli`, run through the bridge
|
|
59
|
+
# above) has asked the estate's four-signal question about "is this issue
|
|
60
|
+
# taken?" since #1209 -- but nothing ever RAN it. It shipped advisory-only, so
|
|
61
|
+
# the fix for the collisions it exists to catch was itself subject to the same
|
|
62
|
+
# failure: a collision happens precisely when someone does not think to check.
|
|
63
|
+
#
|
|
64
|
+
# `--guard <branch>` is the enforced form. It derives the issue number from the
|
|
65
|
+
# branch name (`<type>/<number>-slug>`) and, when the branch names one, checks
|
|
66
|
+
# for another remote branch or another OPEN PR naming the same issue -- NEVER
|
|
67
|
+
# the `in-progress` label (three of four real collisions were "work exists,
|
|
68
|
+
# label does not") and NEVER identity (a claim on #1109 was recorded as
|
|
69
|
+
# `github-actions[bot]` because of a repo-local `user.email` override). It
|
|
70
|
+
# excludes the branch being pushed and any PR whose head IS that branch, so
|
|
71
|
+
# pushing your own branch a second time cannot block you on your own work.
|
|
72
|
+
#
|
|
73
|
+
# A branch that names no issue returns before any network call -- most
|
|
74
|
+
# branches are fine, and noise kills a gate. Measured on a branch that DOES
|
|
75
|
+
# name one: the added latency is the cost of two `gh` lookups, similar in
|
|
76
|
+
# order of magnitude to `rewrite-scope-check` above.
|
|
77
|
+
branch=$(git symbolic-ref --quiet --short HEAD) || branch=""
|
|
78
|
+
|
|
79
|
+
if [ -n "$branch" ]; then
|
|
80
|
+
sh scripts/biffo.sh claim --guard "$branch"
|
|
81
|
+
claim_status=$?
|
|
82
|
+
|
|
83
|
+
if [ "$claim_status" -eq 1 ]; then
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# $claim_status -eq 2 is "cannot tell" -- no network, gh unauthenticated, an
|
|
88
|
+
# API error -- and claim.sh has already printed a warning. Deliberately NOT
|
|
89
|
+
# blocked here: unlike every other gate in this file, this is a COORDINATION
|
|
90
|
+
# gate, not a correctness one. A false block costs the ability to push at
|
|
91
|
+
# all; a miss costs a recoverable collision caught early (every collision in
|
|
92
|
+
# #1209's own incident was caught before duplicate work merged). Set
|
|
93
|
+
# BIFFO_CLAIM_STRICT=1 to make claim.sh itself collapse cannot-tell into
|
|
94
|
+
# exit 1 instead, if you would rather block than guess.
|
|
95
|
+
fi
|
|
96
|
+
|
|
43
97
|
# Through the version-pinned CLI since #1109, so a repo cannot run a gate two
|
|
44
98
|
# versions old -- eight of them did, and tabsii-crm checked ONE thing in eight
|
|
45
99
|
# on a 700-line change and printed `verify passed` (#855). There is one copy of
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@vitejs/plugin-react": "^4.7.0",
|
|
31
31
|
"eslint": "^9.18.0",
|
|
32
32
|
"eslint-config-next": "^15.5.22",
|
|
33
|
-
"jsdom": "^
|
|
33
|
+
"jsdom": "^30.0.1",
|
|
34
34
|
"prettier": "^3.4.2",
|
|
35
35
|
"typescript": "^5.7.3",
|
|
36
36
|
"vite": "^6.4.3",
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
"overrides": {
|
|
41
41
|
"postcss@<8.5.18": ">=8.5.18",
|
|
42
42
|
"sharp@<0.35.0": ">=0.35.0",
|
|
43
|
-
"brace-expansion@<5.0.9": ">=5.0.9"
|
|
43
|
+
"brace-expansion@<5.0.9": ">=5.0.9",
|
|
44
|
+
"undici@<7.29.0": ">=7.29.0"
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -8,6 +8,7 @@ overrides:
|
|
|
8
8
|
postcss@<8.5.18: '>=8.5.18'
|
|
9
9
|
sharp@<0.35.0: '>=0.35.0'
|
|
10
10
|
brace-expansion@<5.0.9: '>=5.0.9'
|
|
11
|
+
undici@<7.29.0: '>=7.29.0'
|
|
11
12
|
|
|
12
13
|
importers:
|
|
13
14
|
|
|
@@ -60,8 +61,8 @@ importers:
|
|
|
60
61
|
specifier: ^15.5.22
|
|
61
62
|
version: 15.5.22(eslint@9.39.4)(typescript@5.9.3)
|
|
62
63
|
jsdom:
|
|
63
|
-
specifier: ^
|
|
64
|
-
version:
|
|
64
|
+
specifier: ^30.0.1
|
|
65
|
+
version: 30.0.1
|
|
65
66
|
prettier:
|
|
66
67
|
specifier: ^3.4.2
|
|
67
68
|
version: 3.9.4
|
|
@@ -73,27 +74,20 @@ importers:
|
|
|
73
74
|
version: 6.4.3(@types/node@22.20.0)
|
|
74
75
|
vitest:
|
|
75
76
|
specifier: ^4.1.0
|
|
76
|
-
version: 4.1.9(@types/node@22.20.0)(jsdom@
|
|
77
|
+
version: 4.1.9(@types/node@22.20.0)(jsdom@30.0.1)(vite@6.4.3(@types/node@22.20.0))
|
|
77
78
|
|
|
78
79
|
packages:
|
|
79
80
|
|
|
80
81
|
'@adobe/css-tools@4.5.0':
|
|
81
82
|
resolution: {integrity: sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==}
|
|
82
83
|
|
|
83
|
-
'@asamuzakjp/css-color@
|
|
84
|
-
resolution: {integrity: sha512-
|
|
85
|
-
engines: {node: ^
|
|
86
|
-
|
|
87
|
-
'@asamuzakjp/dom-selector@7.1.1':
|
|
88
|
-
resolution: {integrity: sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==}
|
|
89
|
-
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
|
90
|
-
|
|
91
|
-
'@asamuzakjp/generational-cache@1.0.1':
|
|
92
|
-
resolution: {integrity: sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==}
|
|
93
|
-
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
|
84
|
+
'@asamuzakjp/css-color@6.0.5':
|
|
85
|
+
resolution: {integrity: sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA==}
|
|
86
|
+
engines: {node: ^22.13.0 || >=24.0.0}
|
|
94
87
|
|
|
95
|
-
'@asamuzakjp/
|
|
96
|
-
resolution: {integrity: sha512-
|
|
88
|
+
'@asamuzakjp/dom-selector@8.3.2':
|
|
89
|
+
resolution: {integrity: sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==}
|
|
90
|
+
engines: {node: ^22.13.0 || >=24.0.0}
|
|
97
91
|
|
|
98
92
|
'@aws-crypto/sha256-js@1.2.2':
|
|
99
93
|
resolution: {integrity: sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==}
|
|
@@ -223,8 +217,8 @@ packages:
|
|
|
223
217
|
peerDependencies:
|
|
224
218
|
'@csstools/css-tokenizer': ^4.0.0
|
|
225
219
|
|
|
226
|
-
'@csstools/css-syntax-patches-for-csstree@1.1.
|
|
227
|
-
resolution: {integrity: sha512-
|
|
220
|
+
'@csstools/css-syntax-patches-for-csstree@1.1.7':
|
|
221
|
+
resolution: {integrity: sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==}
|
|
228
222
|
peerDependencies:
|
|
229
223
|
css-tree: ^3.2.1
|
|
230
224
|
peerDependenciesMeta:
|
|
@@ -1875,11 +1869,11 @@ packages:
|
|
|
1875
1869
|
resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==}
|
|
1876
1870
|
hasBin: true
|
|
1877
1871
|
|
|
1878
|
-
jsdom@
|
|
1879
|
-
resolution: {integrity: sha512-
|
|
1880
|
-
engines: {node: ^
|
|
1872
|
+
jsdom@30.0.1:
|
|
1873
|
+
resolution: {integrity: sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==}
|
|
1874
|
+
engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0}
|
|
1881
1875
|
peerDependencies:
|
|
1882
|
-
canvas: ^3.
|
|
1876
|
+
canvas: ^3.2.3
|
|
1883
1877
|
peerDependenciesMeta:
|
|
1884
1878
|
canvas:
|
|
1885
1879
|
optional: true
|
|
@@ -1936,8 +1930,8 @@ packages:
|
|
|
1936
1930
|
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
|
1937
1931
|
hasBin: true
|
|
1938
1932
|
|
|
1939
|
-
lru-cache@11.5.
|
|
1940
|
-
resolution: {integrity: sha512-
|
|
1933
|
+
lru-cache@11.5.2:
|
|
1934
|
+
resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==}
|
|
1941
1935
|
engines: {node: 20 || >=22}
|
|
1942
1936
|
|
|
1943
1937
|
lru-cache@5.1.1:
|
|
@@ -2395,8 +2389,8 @@ packages:
|
|
|
2395
2389
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
|
2396
2390
|
engines: {node: '>=8.0'}
|
|
2397
2391
|
|
|
2398
|
-
tough-cookie@6.0.
|
|
2399
|
-
resolution: {integrity: sha512-
|
|
2392
|
+
tough-cookie@6.0.2:
|
|
2393
|
+
resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==}
|
|
2400
2394
|
engines: {node: '>=16'}
|
|
2401
2395
|
|
|
2402
2396
|
tr46@0.0.3:
|
|
@@ -2453,9 +2447,9 @@ packages:
|
|
|
2453
2447
|
undici-types@6.21.0:
|
|
2454
2448
|
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
|
2455
2449
|
|
|
2456
|
-
undici@
|
|
2457
|
-
resolution: {integrity: sha512-
|
|
2458
|
-
engines: {node: '>=
|
|
2450
|
+
undici@8.10.0:
|
|
2451
|
+
resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==}
|
|
2452
|
+
engines: {node: '>=22.19.0'}
|
|
2459
2453
|
|
|
2460
2454
|
unfetch@4.2.0:
|
|
2461
2455
|
resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==}
|
|
@@ -2572,6 +2566,10 @@ packages:
|
|
|
2572
2566
|
resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==}
|
|
2573
2567
|
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
|
2574
2568
|
|
|
2569
|
+
whatwg-url@17.1.0:
|
|
2570
|
+
resolution: {integrity: sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==}
|
|
2571
|
+
engines: {node: ^22.14.0 || >=24.0.0}
|
|
2572
|
+
|
|
2575
2573
|
whatwg-url@5.0.0:
|
|
2576
2574
|
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
|
2577
2575
|
|
|
@@ -2623,25 +2621,20 @@ snapshots:
|
|
|
2623
2621
|
|
|
2624
2622
|
'@adobe/css-tools@4.5.0': {}
|
|
2625
2623
|
|
|
2626
|
-
'@asamuzakjp/css-color@
|
|
2624
|
+
'@asamuzakjp/css-color@6.0.5':
|
|
2627
2625
|
dependencies:
|
|
2628
|
-
'@asamuzakjp/generational-cache': 1.0.1
|
|
2629
2626
|
'@csstools/css-calc': 3.2.1(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
|
|
2630
2627
|
'@csstools/css-color-parser': 4.1.9(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)
|
|
2631
2628
|
'@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0)
|
|
2632
2629
|
'@csstools/css-tokenizer': 4.0.0
|
|
2630
|
+
lru-cache: 11.5.2
|
|
2633
2631
|
|
|
2634
|
-
'@asamuzakjp/dom-selector@
|
|
2632
|
+
'@asamuzakjp/dom-selector@8.3.2':
|
|
2635
2633
|
dependencies:
|
|
2636
|
-
'@asamuzakjp/generational-cache': 1.0.1
|
|
2637
|
-
'@asamuzakjp/nwsapi': 2.3.9
|
|
2638
2634
|
bidi-js: 1.0.3
|
|
2639
2635
|
css-tree: 3.2.1
|
|
2640
2636
|
is-potential-custom-element-name: 1.0.1
|
|
2641
|
-
|
|
2642
|
-
'@asamuzakjp/generational-cache@1.0.1': {}
|
|
2643
|
-
|
|
2644
|
-
'@asamuzakjp/nwsapi@2.3.9': {}
|
|
2637
|
+
lru-cache: 11.5.2
|
|
2645
2638
|
|
|
2646
2639
|
'@aws-crypto/sha256-js@1.2.2':
|
|
2647
2640
|
dependencies:
|
|
@@ -2800,7 +2793,7 @@ snapshots:
|
|
|
2800
2793
|
dependencies:
|
|
2801
2794
|
'@csstools/css-tokenizer': 4.0.0
|
|
2802
2795
|
|
|
2803
|
-
'@csstools/css-syntax-patches-for-csstree@1.1.
|
|
2796
|
+
'@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)':
|
|
2804
2797
|
optionalDependencies:
|
|
2805
2798
|
css-tree: 3.2.1
|
|
2806
2799
|
|
|
@@ -4483,28 +4476,28 @@ snapshots:
|
|
|
4483
4476
|
dependencies:
|
|
4484
4477
|
argparse: 2.0.1
|
|
4485
4478
|
|
|
4486
|
-
jsdom@
|
|
4479
|
+
jsdom@30.0.1:
|
|
4487
4480
|
dependencies:
|
|
4488
|
-
'@asamuzakjp/css-color':
|
|
4489
|
-
'@asamuzakjp/dom-selector':
|
|
4481
|
+
'@asamuzakjp/css-color': 6.0.5
|
|
4482
|
+
'@asamuzakjp/dom-selector': 8.3.2
|
|
4490
4483
|
'@bramus/specificity': 2.4.2
|
|
4491
|
-
'@csstools/css-syntax-patches-for-csstree': 1.1.
|
|
4484
|
+
'@csstools/css-syntax-patches-for-csstree': 1.1.7(css-tree@3.2.1)
|
|
4492
4485
|
'@exodus/bytes': 1.15.1
|
|
4493
4486
|
css-tree: 3.2.1
|
|
4494
4487
|
data-urls: 7.0.0
|
|
4495
4488
|
decimal.js: 10.6.0
|
|
4496
4489
|
html-encoding-sniffer: 6.0.0
|
|
4497
4490
|
is-potential-custom-element-name: 1.0.1
|
|
4498
|
-
lru-cache: 11.5.
|
|
4491
|
+
lru-cache: 11.5.2
|
|
4499
4492
|
parse5: 8.0.1
|
|
4500
4493
|
saxes: 6.0.0
|
|
4501
4494
|
symbol-tree: 3.2.4
|
|
4502
|
-
tough-cookie: 6.0.
|
|
4503
|
-
undici:
|
|
4495
|
+
tough-cookie: 6.0.2
|
|
4496
|
+
undici: 8.10.0
|
|
4504
4497
|
w3c-xmlserializer: 5.0.0
|
|
4505
4498
|
webidl-conversions: 8.0.1
|
|
4506
4499
|
whatwg-mimetype: 5.0.0
|
|
4507
|
-
whatwg-url:
|
|
4500
|
+
whatwg-url: 17.1.0
|
|
4508
4501
|
xml-name-validator: 5.0.0
|
|
4509
4502
|
transitivePeerDependencies:
|
|
4510
4503
|
- '@noble/hashes'
|
|
@@ -4555,7 +4548,7 @@ snapshots:
|
|
|
4555
4548
|
dependencies:
|
|
4556
4549
|
js-tokens: 4.0.0
|
|
4557
4550
|
|
|
4558
|
-
lru-cache@11.5.
|
|
4551
|
+
lru-cache@11.5.2: {}
|
|
4559
4552
|
|
|
4560
4553
|
lru-cache@5.1.1:
|
|
4561
4554
|
dependencies:
|
|
@@ -5080,7 +5073,7 @@ snapshots:
|
|
|
5080
5073
|
dependencies:
|
|
5081
5074
|
is-number: 7.0.0
|
|
5082
5075
|
|
|
5083
|
-
tough-cookie@6.0.
|
|
5076
|
+
tough-cookie@6.0.2:
|
|
5084
5077
|
dependencies:
|
|
5085
5078
|
tldts: 7.4.6
|
|
5086
5079
|
|
|
@@ -5153,7 +5146,7 @@ snapshots:
|
|
|
5153
5146
|
|
|
5154
5147
|
undici-types@6.21.0: {}
|
|
5155
5148
|
|
|
5156
|
-
undici@
|
|
5149
|
+
undici@8.10.0: {}
|
|
5157
5150
|
|
|
5158
5151
|
unfetch@4.2.0: {}
|
|
5159
5152
|
|
|
@@ -5206,7 +5199,7 @@ snapshots:
|
|
|
5206
5199
|
'@types/node': 22.20.0
|
|
5207
5200
|
fsevents: 2.3.3
|
|
5208
5201
|
|
|
5209
|
-
vitest@4.1.9(@types/node@22.20.0)(jsdom@
|
|
5202
|
+
vitest@4.1.9(@types/node@22.20.0)(jsdom@30.0.1)(vite@6.4.3(@types/node@22.20.0)):
|
|
5210
5203
|
dependencies:
|
|
5211
5204
|
'@vitest/expect': 4.1.9
|
|
5212
5205
|
'@vitest/mocker': 4.1.9(vite@6.4.3(@types/node@22.20.0))
|
|
@@ -5230,7 +5223,7 @@ snapshots:
|
|
|
5230
5223
|
why-is-node-running: 2.3.0
|
|
5231
5224
|
optionalDependencies:
|
|
5232
5225
|
'@types/node': 22.20.0
|
|
5233
|
-
jsdom:
|
|
5226
|
+
jsdom: 30.0.1
|
|
5234
5227
|
transitivePeerDependencies:
|
|
5235
5228
|
- msw
|
|
5236
5229
|
|
|
@@ -5252,6 +5245,14 @@ snapshots:
|
|
|
5252
5245
|
transitivePeerDependencies:
|
|
5253
5246
|
- '@noble/hashes'
|
|
5254
5247
|
|
|
5248
|
+
whatwg-url@17.1.0:
|
|
5249
|
+
dependencies:
|
|
5250
|
+
'@exodus/bytes': 1.15.1
|
|
5251
|
+
tr46: 6.0.0
|
|
5252
|
+
webidl-conversions: 8.0.1
|
|
5253
|
+
transitivePeerDependencies:
|
|
5254
|
+
- '@noble/hashes'
|
|
5255
|
+
|
|
5255
5256
|
whatwg-url@5.0.0:
|
|
5256
5257
|
dependencies:
|
|
5257
5258
|
tr46: 0.0.3
|
package/package.json
CHANGED
package/scripts/claim.sh
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
# sh scripts/claim.sh 1234 # check, and claim if free
|
|
43
43
|
# sh scripts/claim.sh 1234 --check # report only, change nothing
|
|
44
44
|
# sh scripts/claim.sh 1234 -R owner/repo
|
|
45
|
+
# sh scripts/claim.sh --guard <branch> # pre-push gate — see below
|
|
45
46
|
#
|
|
46
47
|
# 0 free — and claimed, unless --check
|
|
47
48
|
# 1 taken, or already closed — the reason is printed
|
|
@@ -51,15 +52,50 @@
|
|
|
51
52
|
# A check that cannot see its input must not report "free".
|
|
52
53
|
#
|
|
53
54
|
# Requires `gh`, authenticated. Uses gh's embedded jq, so no jq binary needed.
|
|
55
|
+
#
|
|
56
|
+
# ## `--guard <branch>` — the pre-push gate (#1231 instance 2)
|
|
57
|
+
#
|
|
58
|
+
# The four-signal check above is advisory: nothing ever runs it for you, so a
|
|
59
|
+
# collision happens precisely when someone does not think to check. `--guard`
|
|
60
|
+
# is the enforced half, called from `.githooks/pre-push` on every push.
|
|
61
|
+
#
|
|
62
|
+
# It answers a narrower question than the plain form above, on purpose:
|
|
63
|
+
#
|
|
64
|
+
# - **Derives the issue from the branch name.** Pattern `<type>/<number>-…`,
|
|
65
|
+
# e.g. `feat/1234-thing`. A branch that does not name an issue (most of
|
|
66
|
+
# them) is skipped SILENTLY, before any network call — most branches are
|
|
67
|
+
# fine and noise kills a gate.
|
|
68
|
+
# - **Never checks the `in-progress` label.** Of four real collisions in one
|
|
69
|
+
# morning, three were "work exists, label does not" — so a gate keyed on
|
|
70
|
+
# the label would have caught one of four. This checks only what git and
|
|
71
|
+
# GitHub cannot help but know: an open PR, a remote branch.
|
|
72
|
+
# - **Never compares identity.** A claim on #1109 was recorded as
|
|
73
|
+
# `github-actions[bot]` because of a repo-local `user.email` override —
|
|
74
|
+
# usernames are not a trustworthy signal here.
|
|
75
|
+
# - **Excludes the branch being pushed, and any PR whose head IS that
|
|
76
|
+
# branch**, from counting as a conflict. Without this, pushing your own
|
|
77
|
+
# branch a second time blocks you on your own work.
|
|
78
|
+
# - **A real conflict — another branch or another open PR naming the same
|
|
79
|
+
# issue — exits 1**, naming what was found. AGENTS.md permits stealing a
|
|
80
|
+
# claim that is over an hour stale, with a comment; the message points
|
|
81
|
+
# there rather than being a dead end.
|
|
82
|
+
# - **"Cannot tell" (no network, `gh` unauthenticated, an API error) warns
|
|
83
|
+
# and exits 2 — never 1.** By default the caller should treat 2 as a pass:
|
|
84
|
+
# this is a COORDINATION gate, not a correctness one, and a false block
|
|
85
|
+
# costs the ability to push at all while a miss costs a recoverable
|
|
86
|
+
# collision caught early (see "What it cannot do" above). Set
|
|
87
|
+
# `BIFFO_CLAIM_STRICT=1` to make this script itself collapse cannot-tell
|
|
88
|
+
# into exit 1 instead, for anyone who would rather block than guess.
|
|
54
89
|
|
|
55
90
|
set -u
|
|
56
91
|
|
|
57
92
|
ISSUE=""
|
|
58
93
|
REPO=""
|
|
59
94
|
CHECK_ONLY=""
|
|
95
|
+
GUARD_BRANCH=""
|
|
60
96
|
|
|
61
97
|
usage() {
|
|
62
|
-
sed -n '2,
|
|
98
|
+
sed -n '2,84p' "$0" | sed 's/^# \{0,1\}//'
|
|
63
99
|
exit 2
|
|
64
100
|
}
|
|
65
101
|
|
|
@@ -70,6 +106,10 @@ while [ $# -gt 0 ]; do
|
|
|
70
106
|
shift 2
|
|
71
107
|
;;
|
|
72
108
|
--check) CHECK_ONLY=1; shift ;;
|
|
109
|
+
--guard)
|
|
110
|
+
GUARD_BRANCH="${2:-}"
|
|
111
|
+
shift 2
|
|
112
|
+
;;
|
|
73
113
|
-h | --help) usage ;;
|
|
74
114
|
*)
|
|
75
115
|
ISSUE="$1"
|
|
@@ -78,13 +118,6 @@ while [ $# -gt 0 ]; do
|
|
|
78
118
|
esac
|
|
79
119
|
done
|
|
80
120
|
|
|
81
|
-
case "$ISSUE" in
|
|
82
|
-
'' | *[!0-9]*)
|
|
83
|
-
echo "claim: give an issue number, e.g. sh scripts/claim.sh 1234" >&2
|
|
84
|
-
exit 2
|
|
85
|
-
;;
|
|
86
|
-
esac
|
|
87
|
-
|
|
88
121
|
RED=$(printf '\033[31m')
|
|
89
122
|
GREEN=$(printf '\033[32m')
|
|
90
123
|
YELLOW=$(printf '\033[33m')
|
|
@@ -94,12 +127,117 @@ OFF=$(printf '\033[0m')
|
|
|
94
127
|
gh_issue() { if [ -n "$REPO" ]; then gh issue "$@" --repo "$REPO"; else gh issue "$@"; fi; }
|
|
95
128
|
gh_pr() { if [ -n "$REPO" ]; then gh pr "$@" --repo "$REPO"; else gh pr "$@"; fi; }
|
|
96
129
|
|
|
130
|
+
# `git ls-remote --heads ""` fails outright ("fatal: bad repository ''") rather
|
|
131
|
+
# than falling back to the default remote — `${REPO:+url}` expands to an empty
|
|
132
|
+
# STRING ARGUMENT when $REPO is unset, not to no argument at all. That silently
|
|
133
|
+
# broke signal 3 below for every caller that does not pass -R, which is nearly
|
|
134
|
+
# all of them: the branch check never fired, and nothing noticed because the
|
|
135
|
+
# label and open-PR signals usually catch a collision first. Found while
|
|
136
|
+
# building `--guard`, which depends on this signal actually working.
|
|
137
|
+
remote_branches() {
|
|
138
|
+
if [ -n "$REPO" ]; then
|
|
139
|
+
git ls-remote --heads "https://github.com/$REPO.git"
|
|
140
|
+
else
|
|
141
|
+
git ls-remote --heads
|
|
142
|
+
fi
|
|
143
|
+
}
|
|
144
|
+
|
|
97
145
|
LABEL=in-progress
|
|
98
146
|
TAKEN=0
|
|
99
147
|
REASONS=""
|
|
100
148
|
|
|
101
149
|
note() { REASONS="${REASONS} $1\n"; TAKEN=1; }
|
|
102
150
|
|
|
151
|
+
# --- --guard <branch>: the enforced pre-push gate -----------------------------
|
|
152
|
+
#
|
|
153
|
+
# Deliberately short-circuits before any of the four-signal machinery below —
|
|
154
|
+
# it asks two of those four questions, not all four, and answers a different
|
|
155
|
+
# question ("would this push collide with someone else's live work?" rather
|
|
156
|
+
# than "is this issue free to claim?").
|
|
157
|
+
if [ -n "$GUARD_BRANCH" ]; then
|
|
158
|
+
guard_issue=$(printf '%s' "$GUARD_BRANCH" | sed -n 's#^[^/]*/\([0-9][0-9]*\)-.*#\1#p')
|
|
159
|
+
|
|
160
|
+
# No issue named by the branch — most branches, e.g.
|
|
161
|
+
# `security/brace-expansion-5-0-9`. Skip silently, and — this is the point —
|
|
162
|
+
# before touching the network at all.
|
|
163
|
+
if [ -z "$guard_issue" ]; then
|
|
164
|
+
exit 0
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
cannot_tell=0
|
|
168
|
+
conflict=0
|
|
169
|
+
findings=""
|
|
170
|
+
cannot_tell_reasons=""
|
|
171
|
+
|
|
172
|
+
# --- an open PR referencing the issue, excluding our own branch's PR --------
|
|
173
|
+
pr_err=$(mktemp)
|
|
174
|
+
open_prs=$(gh_pr list --state open --limit 100 --json number,title,body,headRefName \
|
|
175
|
+
--jq "[.[] | select(((.title + \" \" + .body) | test(\"(^|[^0-9])#$guard_issue([^0-9]|\$)\")) or (.headRefName | test(\"(^|[^0-9])$guard_issue([^0-9]|\$)\")))] | .[] | select(.headRefName != \"$GUARD_BRANCH\") | \"#\(.number) \(.headRefName)\"" \
|
|
176
|
+
2>"$pr_err")
|
|
177
|
+
pr_status=$?
|
|
178
|
+
pr_err_text=$(cat "$pr_err")
|
|
179
|
+
rm -f "$pr_err"
|
|
180
|
+
|
|
181
|
+
if [ "$pr_status" -ne 0 ]; then
|
|
182
|
+
cannot_tell=1
|
|
183
|
+
cannot_tell_reasons="${cannot_tell_reasons}${pr_err_text} "
|
|
184
|
+
elif [ -n "$open_prs" ]; then
|
|
185
|
+
conflict=1
|
|
186
|
+
findings="${findings} ${RED}open PR${OFF} $(printf '%s' "$open_prs" | head -1)\n"
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
# --- a remote branch naming the issue, excluding our own branch -------------
|
|
190
|
+
branch_err=$(mktemp)
|
|
191
|
+
raw_branches=$(remote_branches 2>"$branch_err")
|
|
192
|
+
branch_status=$?
|
|
193
|
+
branch_err_text=$(cat "$branch_err")
|
|
194
|
+
rm -f "$branch_err"
|
|
195
|
+
|
|
196
|
+
if [ "$branch_status" -ne 0 ]; then
|
|
197
|
+
cannot_tell=1
|
|
198
|
+
cannot_tell_reasons="${cannot_tell_reasons}${branch_err_text} "
|
|
199
|
+
else
|
|
200
|
+
other_branch=$(printf '%s\n' "$raw_branches" |
|
|
201
|
+
sed 's|.*refs/heads/||' |
|
|
202
|
+
grep -E "(^|[^0-9])$guard_issue([^0-9]|$)" |
|
|
203
|
+
grep -v -x "$GUARD_BRANCH" | head -1)
|
|
204
|
+
if [ -n "$other_branch" ]; then
|
|
205
|
+
conflict=1
|
|
206
|
+
findings="${findings} ${RED}branch${OFF} $other_branch\n"
|
|
207
|
+
fi
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
if [ "$conflict" -eq 1 ]; then
|
|
211
|
+
printf '%b' "${RED}claim --guard: issue #$guard_issue looks claimed by someone else.${OFF}\n$findings"
|
|
212
|
+
echo
|
|
213
|
+
echo "${DIM}If you believe it is abandoned (no activity for over an hour), AGENTS.md${OFF}"
|
|
214
|
+
echo "${DIM}permits stealing it deliberately — say so in a comment on the issue first,${OFF}"
|
|
215
|
+
echo "${DIM}then push. Never steal a fresh claim.${OFF}"
|
|
216
|
+
exit 1
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
if [ "$cannot_tell" -eq 1 ]; then
|
|
220
|
+
if [ -n "${BIFFO_CLAIM_STRICT:-}" ]; then
|
|
221
|
+
echo "${RED}claim --guard: cannot tell whether #$guard_issue is claimed elsewhere${OFF} — ${DIM}$cannot_tell_reasons${OFF}" >&2
|
|
222
|
+
echo "${DIM}BIFFO_CLAIM_STRICT=1 is set, so cannot-tell blocks the push.${OFF}" >&2
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
echo "${YELLOW}claim --guard: cannot tell whether #$guard_issue is claimed elsewhere${OFF} — ${DIM}$cannot_tell_reasons${OFF}" >&2
|
|
226
|
+
echo "${DIM}Warning and letting the push through: this is a coordination gate, not a${OFF}" >&2
|
|
227
|
+
echo "${DIM}correctness one. Set BIFFO_CLAIM_STRICT=1 to block instead of guessing.${OFF}" >&2
|
|
228
|
+
exit 2
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
exit 0
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
case "$ISSUE" in
|
|
235
|
+
'' | *[!0-9]*)
|
|
236
|
+
echo "claim: give an issue number, e.g. sh scripts/claim.sh 1234" >&2
|
|
237
|
+
exit 2
|
|
238
|
+
;;
|
|
239
|
+
esac
|
|
240
|
+
|
|
103
241
|
# --- 0. Does the issue exist, and is it still open? --------------------------
|
|
104
242
|
|
|
105
243
|
meta=$(gh_issue view "$ISSUE" --json state,title,labels \
|
|
@@ -150,7 +288,7 @@ fi
|
|
|
150
288
|
#
|
|
151
289
|
# Catches work that has been pushed but has no PR yet. Whole-number match again.
|
|
152
290
|
|
|
153
|
-
branches=$(
|
|
291
|
+
branches=$(remote_branches 2>/dev/null |
|
|
154
292
|
sed 's|.*refs/heads/||' |
|
|
155
293
|
grep -E "(^|[^0-9])$ISSUE([^0-9]|$)" 2>/dev/null)
|
|
156
294
|
|