@biffo/cli 0.172.1 → 0.172.3

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.
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Does each repo's local gate actually cover that repo's CI?
4
+ #
5
+ # ## Why this exists
6
+ #
7
+ # `hook-audit.sh` answers "will a hook execute here". That question hit 100%
8
+ # across the estate on 2026-07-29 while eight repos had a gate that checked
9
+ # **nothing they were written in** — `tabsii-crm` ran one check, terraform-fmt,
10
+ # on a 700-line TypeScript-and-Python change, and printed `verify passed`.
11
+ #
12
+ # Arming was a proxy and it was reported as the outcome. This is the metric that
13
+ # can actually fail: for every repo, the set of check *kinds* its CI runs, minus
14
+ # the ones deliberately excluded, must be covered by the set its gate runs.
15
+ #
16
+ # The parity test in `cli/src/lib/verify-parity.test.ts` compares the gate to CI
17
+ # too — but it runs only in `biffo-template`, the single repo with both a root
18
+ # `package.json` and a root `pyproject.toml`, i.e. the one place the root-only
19
+ # assumption held. It validated the gate where the gate was already correct.
20
+ # This runs everywhere, which is the whole point.
21
+ #
22
+ # Usage:
23
+ # sh scripts/gate-coverage.sh # this repo
24
+ # sh scripts/gate-coverage.sh --estate ~/code # every repo under a directory
25
+ #
26
+ # Exits non-zero if any repo's gate misses a check kind its CI runs.
27
+
28
+ set -uo pipefail
29
+
30
+ ESTATE=""
31
+ [ "${1:-}" = "--estate" ] && ESTATE="${2:-}"
32
+
33
+ # Deliberately excluded from local gates, with the reason. Kept in step with
34
+ # verify-parity.test.ts. An exclusion here must describe what the CI step
35
+ # actually DOES, not what it was assumed to do — the bandit exclusion claimed
36
+ # "the finding gate is the upload step" when `bandit -ll` exits non-zero and it
37
+ # is the run step that fails (#855).
38
+ EXCLUDED_KINDS="pytest build audit gitleaks codeql e2e playwright release-subject ownership"
39
+
40
+ # Reduce a command to the KIND of check it is. Comparing raw command strings is
41
+ # hopeless across repos — CI uses `working-directory:` where the gate uses
42
+ # `--dir` — and what matters is "does a lint run locally where CI runs a lint".
43
+ kind_of() {
44
+ case "$1" in
45
+ *"run lint"*) echo lint ;;
46
+ *"run typecheck"*) echo typecheck ;;
47
+ *"run format:check"*) echo format ;;
48
+ *"run e2e"*) echo e2e ;;
49
+ *"run build"*|*"portal build"*) echo build ;;
50
+ *"run test"*) echo test ;;
51
+ *"ruff check"*) echo ruff-check ;;
52
+ *"ruff format"*) echo ruff-format ;;
53
+ *pyright*) echo pyright ;;
54
+ *pytest*) echo pytest ;;
55
+ *bandit*) echo bandit ;;
56
+ *"terraform fmt"*) echo terraform-fmt ;;
57
+ *playwright*) echo playwright ;;
58
+ *"dependency-audit"*|*"pnpm audit"*|*"pip-audit"*) echo audit ;;
59
+ *gitleaks*) echo gitleaks ;;
60
+ *"check release-subject"*) echo release-subject ;;
61
+ *"check ownership"*) echo ownership ;;
62
+ *"check plugin-terraform"*) echo plugin-terraform ;;
63
+ *"check plugin-collisions"*) echo plugin-collisions ;;
64
+ *install*|*"uv sync"*) echo "" ;;
65
+ *) echo "" ;;
66
+ esac
67
+ }
68
+
69
+ kinds_from_ci() {
70
+ d="$1"
71
+ f="$d/.github/workflows/ci.yml"
72
+ [ -f "$f" ] || return 0
73
+ grep -hoE "run: (pnpm|uv|terraform|sh scripts/)[^\"']*" "$f" 2>/dev/null |
74
+ sed 's/^run: //' | while read -r cmd; do kind_of "$cmd"; done | grep -v '^$' | sort -u
75
+ }
76
+
77
+ kinds_from_gate() {
78
+ d="$1"
79
+ [ -f "$d/scripts/verify.sh" ] || return 0
80
+ (cd "$d" && sh scripts/verify.sh --list 2>/dev/null) |
81
+ while read -r cmd; do kind_of "$cmd"; done | grep -v '^$' | sort -u
82
+ }
83
+
84
+ failed=0
85
+ report() {
86
+ d="$1"
87
+ label="$2"
88
+ if [ ! -f "$d/scripts/verify.sh" ]; then
89
+ printf '%-26s \033[33mNO GATE\033[0m\n' "$label"
90
+ return
91
+ fi
92
+ ci=$(kinds_from_ci "$d")
93
+ gate=$(kinds_from_gate "$d")
94
+ if [ -z "$ci" ]; then
95
+ printf '%-26s \033[90mno CI to mirror\033[0m (gate runs %s)\n' "$label" "$(echo "$gate" | grep -cv '^$')"
96
+ return
97
+ fi
98
+ missing=""
99
+ total=0
100
+ covered=0
101
+ for k in $ci; do
102
+ case " $EXCLUDED_KINDS " in *" $k "*) continue ;; esac
103
+ total=$((total + 1))
104
+ if echo "$gate" | grep -qx "$k"; then covered=$((covered + 1)); else missing="$missing $k"; fi
105
+ done
106
+ if [ -n "$missing" ]; then
107
+ failed=1
108
+ printf '%-26s \033[31m%s/%s\033[0m missing:%s\n' "$label" "$covered" "$total" "$missing"
109
+ else
110
+ printf '%-26s \033[32m%s/%s\033[0m\n' "$label" "$covered" "$total"
111
+ fi
112
+ }
113
+
114
+ printf '\ngate coverage - CI check kinds mirrored by the local gate\n\n'
115
+ if [ -n "$ESTATE" ]; then
116
+ for d in "$ESTATE"/*/; do
117
+ [ -e "$d/.git" ] || continue
118
+ report "${d%/}" "$(basename "${d%/}")"
119
+ done
120
+ else
121
+ root=$(git rev-parse --show-toplevel 2>/dev/null) || { echo "not a git repo" >&2; exit 2; }
122
+ report "$root" "$(basename "$root")"
123
+ fi
124
+
125
+ printf '\n'
126
+ if [ "$failed" -ne 0 ]; then
127
+ printf '\033[31mSome gates do not cover their own CI.\033[0m A gate that misses the language a\n'
128
+ printf 'change is written in reports `verify passed` on work it never checked.\n\n'
129
+ exit 1
130
+ fi
131
+ printf '\033[32mEvery gate covers its own CI.\033[0m\n\n'
@@ -108,15 +108,45 @@ have_script() {
108
108
  # it was written to enforce says exactly that inapplicable and absent must not
109
109
  # look the same -- while reporting "not applicable" for the language the change
110
110
  # was written in.
111
+ # Every directory holding a Python project this repo owns.
112
+ #
113
+ # ## Why this exists (#855)
114
+ #
115
+ # #853 fixed this for JavaScript and left Python with the identical bug. The
116
+ # check was `[ -f pyproject.toml ]` — root only. Every sibling keeps its API at
117
+ # `services/api/pyproject.toml`, so ruff, ruff-format and pyright were skipped
118
+ # entirely, and #853's own rationale applies verbatim: a change pushed green
119
+ # with zero verification of the language it was written in.
120
+ #
121
+ # Found by an agent whose 700-line TypeScript-and-Python change to tabsii-crm
122
+ # ran exactly one check — terraform-fmt — and printed `verify passed`.
123
+ py_dirs() {
124
+ if [ -f pyproject.toml ]; then
125
+ echo "."
126
+ return
127
+ fi
128
+ find . -name pyproject.toml \
129
+ -not -path "*/node_modules/*" -not -path "*/.venv/*" -not -path "*/dist/*" \
130
+ -not -path "*/.worktrees/*" -not -path "*/.terraform/*" -not -path "*/vendor/*" \
131
+ -not -path "*/site-packages/*" 2>/dev/null |
132
+ sed 's|/pyproject.toml$||' | sort
133
+ }
134
+
111
135
  js_dirs() {
112
136
  if [ -f package.json ]; then
113
137
  echo "."
114
138
  return
115
139
  fi
140
+ # `.terraform/` is a DOWNLOAD CACHE of third-party modules, and the two runner
141
+ # repos carry eight vendored lambda packages in it -- each declaring lint and
142
+ # test scripts. Linting someone else's vendored code is slow, always red, and
143
+ # not this repo's business. It is gitignored, so a fresh worktree never has
144
+ # it and the omission was invisible until a primary checkout was audited.
116
145
  find . -name package.json \
117
146
  -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/.next/*" \
118
147
  -not -path "*/.turbo/*" -not -path "*/.worktrees/*" -not -path "*/out/*" \
119
- -not -path "*/coverage/*" -not -path "*/.venv/*" 2>/dev/null |
148
+ -not -path "*/coverage/*" -not -path "*/.venv/*" \
149
+ -not -path "*/.terraform/*" -not -path "*/vendor/*" 2>/dev/null |
120
150
  sed 's|/package.json$||' | sort
121
151
  }
122
152
 
@@ -149,21 +179,42 @@ skip() {
149
179
 
150
180
  # Python first: ruff is near-instant, so the cheapest feedback on the largest
151
181
  # single class of failure comes back immediately.
152
- if [ -f pyproject.toml ]; then
182
+ PY_DIRS=$(py_dirs)
183
+ if [ -n "$PY_DIRS" ]; then
153
184
  if [ -n "$LIST" ] || command -v uv >/dev/null 2>&1; then
154
- run_check ruff-check uv run ruff check .
155
- run_check ruff-format uv run ruff format --check .
156
- run_check pyright uv run pyright
157
- if [ -n "$PYTEST" ]; then
158
- run_check pytest uv run pytest -q
159
- else
160
- skip pytest "excluded - set BIFFO_VERIFY_PYTEST=1 where the suite is fast"
161
- fi
185
+ for d in $PY_DIRS; do
186
+ suffix=""
187
+ [ "$d" != "." ] && suffix="(${d#./})"
188
+ if [ "$d" = "." ]; then
189
+ run_check "ruff-check$suffix" uv run ruff check .
190
+ run_check "ruff-format$suffix" uv run ruff format --check .
191
+ run_check "pyright$suffix" uv run pyright
192
+ # bandit is NOT excluded: it exits non-zero on findings and it is the
193
+ # RUN step that fails in CI, not the artefact upload. See the exclusion
194
+ # audit in verify-parity.test.ts (#855).
195
+ [ -d services ] && run_check "bandit$suffix" uv run bandit -r services -ll -q
196
+ if [ -n "$PYTEST" ]; then
197
+ run_check "pytest$suffix" uv run pytest -q
198
+ else
199
+ skip "pytest$suffix" "excluded - set BIFFO_VERIFY_PYTEST=1 where the suite is fast"
200
+ fi
201
+ else
202
+ run_check "ruff-check$suffix" uv run --directory "$d" ruff check .
203
+ run_check "ruff-format$suffix" uv run --directory "$d" ruff format --check .
204
+ run_check "pyright$suffix" uv run --directory "$d" pyright
205
+ run_check "bandit$suffix" uv run --directory "$d" bandit -r src -ll -q
206
+ if [ -n "$PYTEST" ]; then
207
+ run_check "pytest$suffix" uv run --directory "$d" pytest -q
208
+ else
209
+ skip "pytest$suffix" "excluded - set BIFFO_VERIFY_PYTEST=1 where the suite is fast"
210
+ fi
211
+ fi
212
+ done
162
213
  else
163
214
  skip python "uv not installed"
164
215
  fi
165
216
  else
166
- skip python "no pyproject.toml in this repo"
217
+ skip python "no pyproject.toml anywhere in this repo"
167
218
  fi
168
219
 
169
220
  # Terraform, wherever this repo keeps it: modules/ in the template and
@@ -234,6 +285,17 @@ if [ -n "$FAILED" ]; then
234
285
  printf 'Most format failures are one command: pnpm run format\n\n'
235
286
  exit 1
236
287
  fi
288
+ if [ -z "$PASSED" ]; then
289
+ # "Nothing applicable ran" is a different outcome from "checks passed", and
290
+ # conflating them is the exact failure this gate exists to remove -- the
291
+ # standard's own principle, applied to the gate itself. tabsii-crm ran ONE
292
+ # check on a 700-line change and printed a pass (#855).
293
+ printf '\033[31mverify ran NOTHING - this is not a pass\033[0m\n'
294
+ printf 'No check in this repo was applicable. Either its toolchain is somewhere\n'
295
+ printf 'verify.sh does not look, or this repo should not carry a gate at all.\n'
296
+ printf 'See docs/practices/standards/local-gates.md\n\n'
297
+ exit 1
298
+ fi
237
299
  printf '\033[32mverify passed\033[0m -%s\n' "$PASSED"
238
300
  [ -n "$SKIPPED" ] && printf '\033[90mnot applicable here:%s\033[0m\n' "$SKIPPED"
239
301
  printf '\n'
@@ -0,0 +1,131 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Does each repo's local gate actually cover that repo's CI?
4
+ #
5
+ # ## Why this exists
6
+ #
7
+ # `hook-audit.sh` answers "will a hook execute here". That question hit 100%
8
+ # across the estate on 2026-07-29 while eight repos had a gate that checked
9
+ # **nothing they were written in** — `tabsii-crm` ran one check, terraform-fmt,
10
+ # on a 700-line TypeScript-and-Python change, and printed `verify passed`.
11
+ #
12
+ # Arming was a proxy and it was reported as the outcome. This is the metric that
13
+ # can actually fail: for every repo, the set of check *kinds* its CI runs, minus
14
+ # the ones deliberately excluded, must be covered by the set its gate runs.
15
+ #
16
+ # The parity test in `cli/src/lib/verify-parity.test.ts` compares the gate to CI
17
+ # too — but it runs only in `biffo-template`, the single repo with both a root
18
+ # `package.json` and a root `pyproject.toml`, i.e. the one place the root-only
19
+ # assumption held. It validated the gate where the gate was already correct.
20
+ # This runs everywhere, which is the whole point.
21
+ #
22
+ # Usage:
23
+ # sh scripts/gate-coverage.sh # this repo
24
+ # sh scripts/gate-coverage.sh --estate ~/code # every repo under a directory
25
+ #
26
+ # Exits non-zero if any repo's gate misses a check kind its CI runs.
27
+
28
+ set -uo pipefail
29
+
30
+ ESTATE=""
31
+ [ "${1:-}" = "--estate" ] && ESTATE="${2:-}"
32
+
33
+ # Deliberately excluded from local gates, with the reason. Kept in step with
34
+ # verify-parity.test.ts. An exclusion here must describe what the CI step
35
+ # actually DOES, not what it was assumed to do — the bandit exclusion claimed
36
+ # "the finding gate is the upload step" when `bandit -ll` exits non-zero and it
37
+ # is the run step that fails (#855).
38
+ EXCLUDED_KINDS="pytest build audit gitleaks codeql e2e playwright release-subject ownership"
39
+
40
+ # Reduce a command to the KIND of check it is. Comparing raw command strings is
41
+ # hopeless across repos — CI uses `working-directory:` where the gate uses
42
+ # `--dir` — and what matters is "does a lint run locally where CI runs a lint".
43
+ kind_of() {
44
+ case "$1" in
45
+ *"run lint"*) echo lint ;;
46
+ *"run typecheck"*) echo typecheck ;;
47
+ *"run format:check"*) echo format ;;
48
+ *"run e2e"*) echo e2e ;;
49
+ *"run build"*|*"portal build"*) echo build ;;
50
+ *"run test"*) echo test ;;
51
+ *"ruff check"*) echo ruff-check ;;
52
+ *"ruff format"*) echo ruff-format ;;
53
+ *pyright*) echo pyright ;;
54
+ *pytest*) echo pytest ;;
55
+ *bandit*) echo bandit ;;
56
+ *"terraform fmt"*) echo terraform-fmt ;;
57
+ *playwright*) echo playwright ;;
58
+ *"dependency-audit"*|*"pnpm audit"*|*"pip-audit"*) echo audit ;;
59
+ *gitleaks*) echo gitleaks ;;
60
+ *"check release-subject"*) echo release-subject ;;
61
+ *"check ownership"*) echo ownership ;;
62
+ *"check plugin-terraform"*) echo plugin-terraform ;;
63
+ *"check plugin-collisions"*) echo plugin-collisions ;;
64
+ *install*|*"uv sync"*) echo "" ;;
65
+ *) echo "" ;;
66
+ esac
67
+ }
68
+
69
+ kinds_from_ci() {
70
+ d="$1"
71
+ f="$d/.github/workflows/ci.yml"
72
+ [ -f "$f" ] || return 0
73
+ grep -hoE "run: (pnpm|uv|terraform|sh scripts/)[^\"']*" "$f" 2>/dev/null |
74
+ sed 's/^run: //' | while read -r cmd; do kind_of "$cmd"; done | grep -v '^$' | sort -u
75
+ }
76
+
77
+ kinds_from_gate() {
78
+ d="$1"
79
+ [ -f "$d/scripts/verify.sh" ] || return 0
80
+ (cd "$d" && sh scripts/verify.sh --list 2>/dev/null) |
81
+ while read -r cmd; do kind_of "$cmd"; done | grep -v '^$' | sort -u
82
+ }
83
+
84
+ failed=0
85
+ report() {
86
+ d="$1"
87
+ label="$2"
88
+ if [ ! -f "$d/scripts/verify.sh" ]; then
89
+ printf '%-26s \033[33mNO GATE\033[0m\n' "$label"
90
+ return
91
+ fi
92
+ ci=$(kinds_from_ci "$d")
93
+ gate=$(kinds_from_gate "$d")
94
+ if [ -z "$ci" ]; then
95
+ printf '%-26s \033[90mno CI to mirror\033[0m (gate runs %s)\n' "$label" "$(echo "$gate" | grep -cv '^$')"
96
+ return
97
+ fi
98
+ missing=""
99
+ total=0
100
+ covered=0
101
+ for k in $ci; do
102
+ case " $EXCLUDED_KINDS " in *" $k "*) continue ;; esac
103
+ total=$((total + 1))
104
+ if echo "$gate" | grep -qx "$k"; then covered=$((covered + 1)); else missing="$missing $k"; fi
105
+ done
106
+ if [ -n "$missing" ]; then
107
+ failed=1
108
+ printf '%-26s \033[31m%s/%s\033[0m missing:%s\n' "$label" "$covered" "$total" "$missing"
109
+ else
110
+ printf '%-26s \033[32m%s/%s\033[0m\n' "$label" "$covered" "$total"
111
+ fi
112
+ }
113
+
114
+ printf '\ngate coverage - CI check kinds mirrored by the local gate\n\n'
115
+ if [ -n "$ESTATE" ]; then
116
+ for d in "$ESTATE"/*/; do
117
+ [ -e "$d/.git" ] || continue
118
+ report "${d%/}" "$(basename "${d%/}")"
119
+ done
120
+ else
121
+ root=$(git rev-parse --show-toplevel 2>/dev/null) || { echo "not a git repo" >&2; exit 2; }
122
+ report "$root" "$(basename "$root")"
123
+ fi
124
+
125
+ printf '\n'
126
+ if [ "$failed" -ne 0 ]; then
127
+ printf '\033[31mSome gates do not cover their own CI.\033[0m A gate that misses the language a\n'
128
+ printf 'change is written in reports `verify passed` on work it never checked.\n\n'
129
+ exit 1
130
+ fi
131
+ printf '\033[32mEvery gate covers its own CI.\033[0m\n\n'
@@ -108,15 +108,45 @@ have_script() {
108
108
  # it was written to enforce says exactly that inapplicable and absent must not
109
109
  # look the same -- while reporting "not applicable" for the language the change
110
110
  # was written in.
111
+ # Every directory holding a Python project this repo owns.
112
+ #
113
+ # ## Why this exists (#855)
114
+ #
115
+ # #853 fixed this for JavaScript and left Python with the identical bug. The
116
+ # check was `[ -f pyproject.toml ]` — root only. Every sibling keeps its API at
117
+ # `services/api/pyproject.toml`, so ruff, ruff-format and pyright were skipped
118
+ # entirely, and #853's own rationale applies verbatim: a change pushed green
119
+ # with zero verification of the language it was written in.
120
+ #
121
+ # Found by an agent whose 700-line TypeScript-and-Python change to tabsii-crm
122
+ # ran exactly one check — terraform-fmt — and printed `verify passed`.
123
+ py_dirs() {
124
+ if [ -f pyproject.toml ]; then
125
+ echo "."
126
+ return
127
+ fi
128
+ find . -name pyproject.toml \
129
+ -not -path "*/node_modules/*" -not -path "*/.venv/*" -not -path "*/dist/*" \
130
+ -not -path "*/.worktrees/*" -not -path "*/.terraform/*" -not -path "*/vendor/*" \
131
+ -not -path "*/site-packages/*" 2>/dev/null |
132
+ sed 's|/pyproject.toml$||' | sort
133
+ }
134
+
111
135
  js_dirs() {
112
136
  if [ -f package.json ]; then
113
137
  echo "."
114
138
  return
115
139
  fi
140
+ # `.terraform/` is a DOWNLOAD CACHE of third-party modules, and the two runner
141
+ # repos carry eight vendored lambda packages in it -- each declaring lint and
142
+ # test scripts. Linting someone else's vendored code is slow, always red, and
143
+ # not this repo's business. It is gitignored, so a fresh worktree never has
144
+ # it and the omission was invisible until a primary checkout was audited.
116
145
  find . -name package.json \
117
146
  -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/.next/*" \
118
147
  -not -path "*/.turbo/*" -not -path "*/.worktrees/*" -not -path "*/out/*" \
119
- -not -path "*/coverage/*" -not -path "*/.venv/*" 2>/dev/null |
148
+ -not -path "*/coverage/*" -not -path "*/.venv/*" \
149
+ -not -path "*/.terraform/*" -not -path "*/vendor/*" 2>/dev/null |
120
150
  sed 's|/package.json$||' | sort
121
151
  }
122
152
 
@@ -149,21 +179,42 @@ skip() {
149
179
 
150
180
  # Python first: ruff is near-instant, so the cheapest feedback on the largest
151
181
  # single class of failure comes back immediately.
152
- if [ -f pyproject.toml ]; then
182
+ PY_DIRS=$(py_dirs)
183
+ if [ -n "$PY_DIRS" ]; then
153
184
  if [ -n "$LIST" ] || command -v uv >/dev/null 2>&1; then
154
- run_check ruff-check uv run ruff check .
155
- run_check ruff-format uv run ruff format --check .
156
- run_check pyright uv run pyright
157
- if [ -n "$PYTEST" ]; then
158
- run_check pytest uv run pytest -q
159
- else
160
- skip pytest "excluded - set BIFFO_VERIFY_PYTEST=1 where the suite is fast"
161
- fi
185
+ for d in $PY_DIRS; do
186
+ suffix=""
187
+ [ "$d" != "." ] && suffix="(${d#./})"
188
+ if [ "$d" = "." ]; then
189
+ run_check "ruff-check$suffix" uv run ruff check .
190
+ run_check "ruff-format$suffix" uv run ruff format --check .
191
+ run_check "pyright$suffix" uv run pyright
192
+ # bandit is NOT excluded: it exits non-zero on findings and it is the
193
+ # RUN step that fails in CI, not the artefact upload. See the exclusion
194
+ # audit in verify-parity.test.ts (#855).
195
+ [ -d services ] && run_check "bandit$suffix" uv run bandit -r services -ll -q
196
+ if [ -n "$PYTEST" ]; then
197
+ run_check "pytest$suffix" uv run pytest -q
198
+ else
199
+ skip "pytest$suffix" "excluded - set BIFFO_VERIFY_PYTEST=1 where the suite is fast"
200
+ fi
201
+ else
202
+ run_check "ruff-check$suffix" uv run --directory "$d" ruff check .
203
+ run_check "ruff-format$suffix" uv run --directory "$d" ruff format --check .
204
+ run_check "pyright$suffix" uv run --directory "$d" pyright
205
+ run_check "bandit$suffix" uv run --directory "$d" bandit -r src -ll -q
206
+ if [ -n "$PYTEST" ]; then
207
+ run_check "pytest$suffix" uv run --directory "$d" pytest -q
208
+ else
209
+ skip "pytest$suffix" "excluded - set BIFFO_VERIFY_PYTEST=1 where the suite is fast"
210
+ fi
211
+ fi
212
+ done
162
213
  else
163
214
  skip python "uv not installed"
164
215
  fi
165
216
  else
166
- skip python "no pyproject.toml in this repo"
217
+ skip python "no pyproject.toml anywhere in this repo"
167
218
  fi
168
219
 
169
220
  # Terraform, wherever this repo keeps it: modules/ in the template and
@@ -234,6 +285,17 @@ if [ -n "$FAILED" ]; then
234
285
  printf 'Most format failures are one command: pnpm run format\n\n'
235
286
  exit 1
236
287
  fi
288
+ if [ -z "$PASSED" ]; then
289
+ # "Nothing applicable ran" is a different outcome from "checks passed", and
290
+ # conflating them is the exact failure this gate exists to remove -- the
291
+ # standard's own principle, applied to the gate itself. tabsii-crm ran ONE
292
+ # check on a 700-line change and printed a pass (#855).
293
+ printf '\033[31mverify ran NOTHING - this is not a pass\033[0m\n'
294
+ printf 'No check in this repo was applicable. Either its toolchain is somewhere\n'
295
+ printf 'verify.sh does not look, or this repo should not carry a gate at all.\n'
296
+ printf 'See docs/practices/standards/local-gates.md\n\n'
297
+ exit 1
298
+ fi
237
299
  printf '\033[32mverify passed\033[0m -%s\n' "$PASSED"
238
300
  [ -n "$SKIPPED" ] && printf '\033[90mnot applicable here:%s\033[0m\n' "$SKIPPED"
239
301
  printf '\n'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.172.1",
3
+ "version": "0.172.3",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",