Context
In scripts/check-skill-precompute-compose.sh:93-112, target discovery runs inside mapfile -t targets < <( case "$first" in ... esac ). The base-ref branch validates the ref and, on failure, prints an error and runs exit 2 (lines 103-106) -- but that exit terminates only the process-substitution subshell. The parent never observes its status (mapfile's own status reflects the read, and process-substitution exit codes are not propagated), so targets is simply empty and the script proceeds to scan zero files and exit 0. An invalid base ref (a typo'd branch, a shallow clone missing the ref) therefore reads as "nothing to gate": a silent pass in exactly the situation the validation was written to catch. The error text does go to stderr, but the exit code, which is what CI gates on, says success.
Proposed work
- Validate the base ref in the parent shell before the
mapfile (move the git rev-parse --verify check out of the process substitution), exiting 2 from the parent on failure.
- Add a test case invoking the script with a bogus base ref and asserting exit 2 (the suite already exists for this script).
Acceptance criteria
References
scripts/check-skill-precompute-compose.sh:93-112 (mapfile process substitution at line 93; unreachable-to-the-parent exit 2 at line 105)
- Found by the batch-simplify sweep on branch
claude/code-tidying-batch-simplify-s7ljbi; deliberately not fixed there because the sweep was behavior-preserving.
Context
In
scripts/check-skill-precompute-compose.sh:93-112, target discovery runs insidemapfile -t targets < <( case "$first" in ... esac ). The base-ref branch validates the ref and, on failure, prints an error and runsexit 2(lines 103-106) -- but that exit terminates only the process-substitution subshell. The parent never observes its status (mapfile's own status reflects the read, and process-substitution exit codes are not propagated), sotargetsis simply empty and the script proceeds to scan zero files and exit 0. An invalid base ref (a typo'd branch, a shallow clone missing the ref) therefore reads as "nothing to gate": a silent pass in exactly the situation the validation was written to catch. The error text does go to stderr, but the exit code, which is what CI gates on, says success.Proposed work
mapfile(move thegit rev-parse --verifycheck out of the process substitution), exiting 2 from the parent on failure.Acceptance criteria
--all, and--pathsmodes behave as before.References
scripts/check-skill-precompute-compose.sh:93-112(mapfileprocess substitution at line 93; unreachable-to-the-parentexit 2at line 105)claude/code-tidying-batch-simplify-s7ljbi; deliberately not fixed there because the sweep was behavior-preserving.