Commit da6de33
Plan 00067: QA gates scanned ZERO files in a nested checkout and reported a pass
`./scripts/qa-all.bash` — the gate CLAUDE.md makes mandatory before every
Bash/Python commit — printed `✓ bash: 0 files OK` while checking nothing, in
any checkout living under a path segment it excludes. lts-infra vendors this
repo at untracked/repos/fedora-desktop, so that is not hypothetical.
Cause: the exclusions are repo-root-relative in intent (`untracked/`,
`roles/vendor/`, `.claude/ccy/`, …) but were written as unanchored globs.
`find -path` matches the WHOLE path it prints, so `! -path "*/untracked/*"`
excluded the entire repository. 112 bash files, all JS, and — masked behind
`ruff not installed` — all Python went unscanned, exit 0 throughout. A control
silently degraded to a no-op: the same outcome the ban on `|| true` exists to
prevent, reached without using any banned token.
Fix, in two halves:
- Anchor every root-relative exclusion to `$REPO_ROOT`. `.git`, `node_modules`,
`__pycache__`, `.venv` and `venv` stay unanchored — they legitimately occur at
any depth. This stops today's instance.
- Add a zero-file guard to each gate: finding no files of its language exits 2
with the likely cause named, instead of reporting a pass. This stops the class
— the next mis-scoped exclusion, wrong REPO_ROOT, or rename.
Proven by measurement in the affected checkout, not by reasoning about the patch:
qa-bash exit 0, 0 files -> exit 0, 112 files (105 shellcheck findings, 0 error-level)
qa-js exit 0, 0 files -> exit 0, 6 files
qa-python exit 2 (masked) -> exit 0, 38 files (discovery proof, stub analyser)
The 105 shellcheck findings are warning/info/style on files never analysed here
before — results, not regressions. They must not be re-hidden.
Two things stated rather than smoothed over:
- The plan predicted 86 bash files. The real number is 112: the first estimate
counted only name-matched *.sh/*.bash and missed the second find block, which
picks up shebang'd executables and was equally disabled. The defect was bigger
than the plan said. Corrected in the doc rather than left as an overshoot.
- `qa-python.bash` checks for ruff BEFORE discovery, so neither its anchoring fix
nor its guard is reachable while ruff is absent. Both were proven with a stub
ruff that lints nothing; the 38 files did pass a real py_compile, but the stub's
empty result set is not evidence of clean Python.
Also recorded in CLAUDE/QA.md: a `0 files` report is a failure; never remove the
guard to make a gate work somewhere. Plus a follow-up finding of the same class,
deliberately NOT fixed here — qa-bash treats shellcheck as optional while
qa-python treats ruff as required, so a box without shellcheck gets a green
qa-all with no static analysis of its bash at all. That is an IaC question about
declared dependencies with a far wider blast radius than a path-matching bug.
The `ruff not installed` exit 2 is NOT this repo's gap, contrary to the plan's
original Non-Goal: ruff is declared in both play-python.yml and this repo's own
.claude/ccy/Dockerfile. The gate was run from lts-infra's container, which
installs only ansible-lint and yamllint. Corrected in the plan; the fix belongs
in lts-infra's IaC.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 73396b3 commit da6de33
7 files changed
Lines changed: 547 additions & 28 deletions
File tree
- CLAUDE
- Plan
- Completed/00067-qa-gates-inert-in-nested-checkout
- JOURNAL
- scripts
Lines changed: 181 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
0 commit comments