fix(scripts): decide .vale.ini readability by reading it, not by access(2)
Issue #97 item 1 reports the unreadable-.vale.ini guard as untested. It was worse: it was dead. `[[ -r ]]` is access(2), which asks whether the permission bits would allow a read -- and for uid 0 that is yes even on a mode-000 file. This hook runs at pre-push and the dev environment is root, so the guard could never fire where it exists to fire. That is why no uid-independent test for it existed; there was nothing to test. Readability is now decided by actually reading (`cat`), which is uid-independent and strictly stronger, catching EISDIR and EIO that access(2) reports on neither. `cat`, not a `< "$ini"` redirect: opening a directory for reading succeeds, only the read fails. The missing branch moves to `-e`, so a directory sitting where the file belongs is reported as unreadable rather than sending the reader hunting for a deleted file. The new case asserts the MESSAGE, not the exit code. With the guard removed the script still exits 1 -- the greps hit the unreadable path and blame a missing StylesPath on a file that has one. An exit-code-only test would have been green with the guard deleted. Also stops paying for vale in cases that only assert .vale.ini text: 21 of 28 script runs now mask it via the PATH_NO_VALE mechanism case 12 already builds, cutting the suite's bottleneck ~3.5x (issue #97 item 5). The helper falls back to an unmasked run rather than skipping, so a machine where masking is unavailable loses speed, never coverage. That masking is a coverage gain, not only a speedup. With vale on PATH, cases 8 and 9 could not detect deletion of the assertions they were written to catch: a dropped StylesPath also breaks the glob probe, so the script exited 1 for the wrong reason and both cases went green. Verified against the pre-change files -- the same mutation was caught by one incidental assertion before, and by three after. Refs #97 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT
This commit is contained in:
@@ -67,15 +67,31 @@ AGENT_INI="$AGENT_AUDIT/assets/vale/.vale.ini"
|
||||
|
||||
for ini in "$SKILL_INI" "$AGENT_INI"; do
|
||||
rel_ini="${ini#"$REPO_ROOT"/}"
|
||||
if [[ ! -f "$ini" ]]; then
|
||||
# `-e`, not `-f`: a path that exists but is not a readable regular file (a
|
||||
# directory sitting where the file should be, say) is not "missing", and
|
||||
# reporting it as missing sends you looking for a deleted file. It belongs to
|
||||
# the unreadable case below, which is the one that describes what actually
|
||||
# went wrong.
|
||||
if [[ ! -e "$ini" ]]; then
|
||||
err "$rel_ini is missing — without it vale falls back to an upward config search and lints with whatever it finds"
|
||||
continue
|
||||
fi
|
||||
# Present but unreadable is its own case: every assertion below is a grep, and
|
||||
# grep exits 2 on a read error. The override capture swallows that into an
|
||||
# empty result, which would read as "no findings" rather than "not checked".
|
||||
if [[ ! -r "$ini" ]]; then
|
||||
err "$rel_ini is not readable — none of its assertions could run, and an unreadable file cannot be distinguished from a clean one downstream"
|
||||
# empty result, which would read as "no findings" rather than "not checked",
|
||||
# and the two greps above it report "has no StylesPath"/"names no Kyberforge"
|
||||
# for a file that may well have both — a misdiagnosis, not a missed one.
|
||||
#
|
||||
# Decided by ACTUALLY READING the file, not by `[[ -r ]]`. `-r` is access(2),
|
||||
# which answers "would the permission bits allow it" — and for uid 0 that is
|
||||
# yes even on a mode-000 file (verified). This hook runs at pre-push, and this
|
||||
# repo's dev environment is root, so an `[[ ! -r ]]` guard could never fire in
|
||||
# the one place it exists to fire: it was untestable because it was dead. A
|
||||
# read attempt is also the stricter question, catching EISDIR and EIO, which
|
||||
# access(2) reports on neither. `cat`, not a bare `< "$ini"` redirect: opening
|
||||
# a directory for reading succeeds, only the read fails.
|
||||
if ! cat "$ini" >/dev/null 2>&1; then
|
||||
err "$rel_ini exists but could not be read — none of its assertions could run, and an unreadable file cannot be distinguished from a clean one downstream"
|
||||
continue
|
||||
fi
|
||||
# StylesPath is resolved relative to the .vale.ini, which is the only reason
|
||||
|
||||
Reference in New Issue
Block a user