fix: floor the shellcheck sweep on bin/cast, and stop skipping newline-less files #122

Merged
dan-claude-bot merged 1 commit from test/shellcheck-sweep-floor into main 2026-07-21 13:29:57 +00:00

1 commit

Author SHA1 Message Date
dan-claude-bot
5fa484b5d2 fix: floor the shellcheck sweep on bin/cast, and stop skipping newline-less files
#119's class check asserts the swept set covers `git ls-files '*.sh'`.
bin/cast has no `.sh` extension: it enters the set through the shebang
scan, so it is covered by the DERIVATION and not by the ASSERTION. Break
or delete that scan and the shipped entrypoint drops out of the lint
while the check still exits 0 — #118's failure mode (a sweep quietly
narrowing while CI stays green) one level in from where #119 closed it.

There is no non-circular way to re-derive "every extensionless shell
script" inside the script; any second derivation would be the same
shebang scan and would break with it. So the floor is named rather than
computed: `required=(bin/cast)`, asserted present in the swept set. A
rename turns it red, which is correct — the floor is the thing that has
to be updated deliberately. A minimum-count assert was considered and
declined: given the *.sh class check already floors the set, a count
floor's only marginal coverage is "at least one extensionless script
exists", which the named floor states more precisely and with a better
error message, and it would churn on every script added or removed.

Proven to bite. With the shebang allowlist stubbed to match nothing, the
*.sh class check still PASSES and the new floor fails:

    shellcheck-all: 'bin/cast' is not in the swept set
    it has no .sh extension, so it enters only via the shebang scan above —
    that scan is broken, or the file moved. See #121.

Reverted, the sweep is green over 8 scripts again.

Also fixed, from the same review: `IFS= read -r line <"$f" || continue`
skipped any file whose FIRST line lacked a trailing newline, because
`read` returns 1 at EOF even when it populated `line`. A shebang-only
file with no final newline was silently unswept. Now
`|| [ -n "$line" ] || continue`, which falls through on a populated
partial read and still skips genuinely empty files. Measured against a
tracked 9-byte `#!/bin/sh` with no final newline: the fixed scan sweeps 9
scripts including it, the old line sweeps 8 and omits it silently.

Closes #121

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 13:00:53 +00:00