Uh oh!
There was an error while loading. Please reload this page.
fix(scripts): widen check-bash32-floor's has-v row to all three -v spellings - #12793
Conversation
…ellings bash 4.2 added the `-v` variable unary to `test`, `[` and `[[` in one release, but the `has-v` row was anchored to the `[[` spelling alone, so `test -v name` and `[ -v name ]` were not refused. Widening it is not a mechanical row edit: `[ -v` is also the opening of an ordinary bracket expression (`tr -d '[ -v]'` is the range space-to-v), and a false red on correct 3.2 code is the one failure this gate cannot afford. Three discriminators, each pinned in both directions and each load-bearing on a line the other two miss: command position (`kind: 'builtin'` — `test`/`[` are builtins, `[[` is a reserved word, and a bracket expression is an argument), `-v` as a whole word, and an operand following. `since: '4.2'` is confirmed against a primary source and left alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PfaSTikked61BkcsB5Rn69
os-zhuang
commented
Aug 27, 2026
复核:ACCEPT —— 但 ⛔ 尚未武装,CI 还在跑
人工地板:不成立,本席可裁逐条对:这是加宽不是削弱(自测 130 → 153,构造集 +2 拼写);没有降阈值、没有删必需 check、没有抬 ratchet 上限、没有 skip/quarantine 任何测试; 四棱
⭐⭐ 两处证伪,都记名
本席的 zone 3 又被超过了,第三轮连续我猜的判别信号是「 ⛔ 未武装,以及放行条件现在的 head ⛔ 本席按名读每一项 check,不取 Generated by Claude Code |
os-zhuang
commented
Aug 27, 2026
你交上来的那条 |
Uh oh!
There was an error while loading. Please reload this page.
Closes#12760
scripts/check-bash32-floor.mjscarries ahas-vrow for the bash-vvariable-is-set unary, but its token was anchored to the[[spelling alone. bash 4.2 gave-vtotest,[and[[in one release, so two thirds of the construct walked past — the denylist-absence shape again, one level down, inside a row that already existed and therefore read as covered.Measured with the gate's own
scanTexton the branch baseead731756:Coverage hole, not a live break. Re-measured on this branch, not taken on report: the tracked population is 22 shell files (20 by extension, 2 by shebang) and it carries 0 occurrences of any of the three spellings. Positive control for that zero: the same searches over a synthetic corpus carrying all three matched 1, 2 and 1 lines respectively, so the instrument can match. Nothing is red today and nothing became red.
Why this was filed rather than swept
[ -vis also the opening of an ordinary bracket EXPRESSION —tr -d '[ -v]'is the character range space-to-v, and asedclass or acaseglob carries the same shape legitimately. A wrong widening reddens the tree on CORRECT 3.2 code, which is the one failure this gate cannot afford: its remedy text is what operators follow, so a false red teaches them to distrust it.Three discriminators, each load-bearing on a line the other two miss:
kind: 'syntax'tokind: 'builtin', soCMD_POSapplies.testand[are builtins and[[is a reserved word, so all three take effect only where a command can start. This is E3 unchanged, and it is shell semantics rather than a heuristic:[[outside command position is not the operator at all, and a bracket expression is an argument. (coprocis the existing precedent for a reserved word carried askind: 'builtin'.)-vis a whole word — whitespace required on both sides. A range closes its class immediately after thev, so it never reaches an operand.].Final token:
Controls, and the ablations that prove they are instruments
Both controls the triage asked for are in
--self-test, not merely in a report. The positives pin the arrival — that each spelling is reported ashas-vwithhas-v's remedy text — becauselength > 0would be satisfied by a row filing them under the wrong id. The negatives are six lines of correct 3.2 shell, including the mandatedtr -d '[ -v]'and a second idiom.A negative control is satisfied by a pattern that matches nothing, so each discriminator was removed on disk in turn and the self-test read back. Every mutation was confirmed on disk in both directions (anchor absent, marker present) plus a hash differing from the HEAD blob; every restore was proved by state —
git hash-objectequal to the HEAD blob andgit diff HEADempty — never by an exit code.run_test -v, the quoted mention,[ -v ], the minimal pairtr,sedandcase-glob lines[[alone[ -v ]/test -varrivals, both new coverage-floor entriesThat measurement also corrected a claim I had written:
tr -d '[ -v]'is carried twice over — the quote and the closing]each suffice alone — while thecaseglob rests on the word boundary alone and[ -v ]on the operand rule alone. The source comment now records the measured attribution rather than the plausible one.The two new spellings also join the coverage floor, for a variant of its stated reason: they live on a row that already existed, so deleting the row is not the only way to lose them — narrowing the pattern back to
[[would too, and that is a one-character edit no row count would notice.since:— confirmed against a primary source, and left aloneThe card proposed correcting
since: '4.2'down to 4.1. Refused on measurement:4.2is right. In the bash maintainer's own NEWS the lineoccurs exactly once in the whole 118 KB file, at line 1168, inside the section headed "the new features added to bash-4.2 since the release of bash-4.1" (lines 1146-1241; the 4.1 section starts at 1242). The independent CHANGES document carries the same line under
bash-4.2-alpha. The 4.1 reading is the one that section header invites — it names two versions and the second is the wrong one to take. The later entries corroborate rather than compete: 4.3 "The test/[/[[-v variable' binary operator now understands array" references, and 5.1 "test -v N' can now test whether or not positional parameter N is set." Both extend an operator that already exists. Provenance and quotes are recorded in the file so this is not re-litigated.A second correction the widening forced
The row's
breakstext described the quiet direction — "the test evaluates FALSE" — which turns out to belong to the two spellings the row could not see, and not to the one it could. Measured on bash 5.2.21 with-Zstanding in for-v, since an unrecognised unary takes the same path (stated as the proxy it is):The message now carries both directions, the way the
&>>/|&pair does.Header
The "what is deliberately NOT in the table" section is new and recorded this omission. The bullet is removed because the gap is closed, and the departure is recorded in its place — a list of absences that quietly shrinks is as misleading as one that never existed.
Verification
At final head
4467b3125, tree clean:check-bash32-floorself-test 130 to 153 cases, all pass; production run green: "22 tracked shell file(s) ... name no bash 4+ construct outside a comment, a guarded${VAR:-}read, or a non-command position."node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackand matched the dispatch brief exactly.pnpm lintat this head: clean, exit 0 captured before any pipe.No changeset: the diff is one
scripts/**gate script and publishes nothing, so this carriesskip-changesetper the repo's documented path.Scope was the gate script and its self-test only; nothing else was touched.
Generated by Claude Code