Skip to content

plan-paths.sh claims bash 3.2 compatibility but has not parsed under it since the freshness lint landed #102

Description

@seanrreid

The claim vs the behavior

scripts/lib/plan-paths.sh:10 states:

# bash 3.2 (macOS stock) compatible: no associative arrays, no `mapfile`.

That claim is currently false. The file has not parsed under bash 3.2 since the
premise-freshness lint (#74) landed.

Repro

On stock macOS (/bin/bash is 3.2.57):

$ /bin/bash -n scripts/lib/plan-paths.sh
scripts/lib/plan-paths.sh: line 171: syntax error near unexpected token `;;'
scripts/lib/plan-paths.sh: line 171: `      case "$token" in *//*) continue ;; esac    # drop URL host:port'

$ /bin/bash scripts/lint-plan.sh .agents/plans/any-plan.md
scripts/lib/plan-paths.sh: line 171: syntax error near unexpected token `;;'
$ echo $?
2

Confirmed pre-existing on main (same construct, line 120 there).

Cause

Bash 3.2's parser bug: a ) in a case pattern inside a $( ) command
substitution
closes the substitution early. The offending case sits inside
the command substitution that builds plan_cited_anchors' result.

Why it matters

Every script here uses #!/usr/bin/env bash, so on a machine with no newer bash
ahead of /bin/bash on PATH, scripts/lint-plan.sh exits 2 with a syntax
error instead of linting
. A gate that fails to run is worse than one that runs
noisily — the same gate-legibility family as #98/#99/#101.

CI does not catch it (the runner has bash 4+), and lint-shell-safety.sh does
not parse-check.

Fix

Write the patterns with a leading paren, which 3.2 parses correctly:

case "$token" in (*//*) continue ;; esac

Apply to every case pattern inside a command substitution in the file, then
either verify the header claim holds or drop the claim.

Suggested guard

A parse check — /bin/bash -n (or any 3.2) over every tracked scripts/**/*.sh
— would keep the claim honest. The natural home is lint-shell-safety.sh, which
already enumerates tracked scripts via git ls-files -s after #101.

Provenance

Found by the Wave 2 agent during delivery of the #98/#99/#101 bundle
(branch rad/gate-legibility-lints). Left unfixed there deliberately:
pre-existing, unrelated to #98, and outside that plan's approved scope.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriage:backlogIndependent, one-plan-sized; pick up between arcs

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions