repo-config/configure.sh check mode uses jq's walk/1, which is absent from jq 1.5. On a host carrying jq 1.5 the ruleset comparison does not degrade, it aborts with a compile error, so check cannot report on the repository at all.
Audited against hub main 3a7cc64. Found by a Copilot review on ptr727/Blog#11, which re-vendors this canonical into that repo, and re-verified by hand before filing.
The evidence
The $norm filter introduced with the payload-driven check mode (#540) is built on walk:
norm='def n: walk(if type=="array" then (if length==0 then . elif ...) else . end); n'
repo-config/configure.sh:222 defines it, and check_ruleset applies it to both sides of every parameterized rule comparison.
Reproduced on jq 1.5 and on jq 1.7, using the same filter shape rather than the real payloads:
$ jq --version
jq-1.7
$ echo '{"a":[3,1,2]}' | jq -c 'def n: walk(if type=="array" then sort else . end); n'
{"a":[1,2,3]}
$ jq --version
jq-1.5
$ echo '{"a":[3,1,2]}' | jq -c 'def n: walk(if type=="array" then sort else . end); n'
jq: error: walk/1 is not defined at <top-level>, line 1:
def n: walk(if type=="array" then sort else . end); n
jq: 1 compile error
Why it is worth fixing rather than documenting
The failure mode is the one the script's own design notes argue against. A jq that cannot compile the filter makes check_ruleset fail on every parameterized rule, so a run on such a host reports drift it never compared, which is the inverse of the "clean audit over drift it never compares" defect #538 already tracks.
It also lands where the script is least likely to be exercised before it matters. A maintainer runs check on whatever host is in front of them, and the fleet's supported platforms do not pin a jq version anywhere I can find.
Two shapes, and the tradeoff
- Define
walk locally in the jq program. It is eight lines of jq and works across versions, so the script keeps one code path. It grows the filter, which is already the longest inline jq in the file.
- Assert the jq version up front, next to the existing tool checks, and fail with a message naming the requirement. Smaller, and it turns a compile error into an explanation, but it makes the script refuse to run on a host where everything except this one comparison would have worked.
The first is the better default, since check is the read-only mode and refusing to run is a worse outcome than running. Stated as a preference, not a decision, and it is yours.
Not proposing a downstream fix
configure.sh is carried verbatim, so the finding is declined on ptr727/Blog#11 and raised here instead. Whatever lands re-vendors to the nine repos the ledger currently lists as carrying a stale copy.
🤖 Generated with Claude Code
repo-config/configure.shcheck mode uses jq'swalk/1, which is absent from jq 1.5. On a host carrying jq 1.5 the ruleset comparison does not degrade, it aborts with a compile error, socheckcannot report on the repository at all.Audited against hub
main3a7cc64. Found by a Copilot review on ptr727/Blog#11, which re-vendors this canonical into that repo, and re-verified by hand before filing.The evidence
The
$normfilter introduced with the payload-driven check mode (#540) is built onwalk:norm='def n: walk(if type=="array" then (if length==0 then . elif ...) else . end); n'repo-config/configure.sh:222defines it, andcheck_rulesetapplies it to both sides of every parameterized rule comparison.Reproduced on jq 1.5 and on jq 1.7, using the same filter shape rather than the real payloads:
Why it is worth fixing rather than documenting
The failure mode is the one the script's own design notes argue against. A jq that cannot compile the filter makes
check_rulesetfail on every parameterized rule, so a run on such a host reports drift it never compared, which is the inverse of the "clean audit over drift it never compares" defect #538 already tracks.It also lands where the script is least likely to be exercised before it matters. A maintainer runs
checkon whatever host is in front of them, and the fleet's supported platforms do not pin a jq version anywhere I can find.Two shapes, and the tradeoff
walklocally in the jq program. It is eight lines of jq and works across versions, so the script keeps one code path. It grows the filter, which is already the longest inline jq in the file.The first is the better default, since
checkis the read-only mode and refusing to run is a worse outcome than running. Stated as a preference, not a decision, and it is yours.Not proposing a downstream fix
configure.shis carried verbatim, so the finding is declined on ptr727/Blog#11 and raised here instead. Whatever lands re-vendors to the nine repos the ledger currently lists as carrying a stale copy.🤖 Generated with Claude Code