Splitting on separators anywhere in a line broke quoted strings apart, so
echo 'note; bun run changelog:check-prerelease-notes ...' produced a bare
command position and satisfied the ordering assertion.
Track quote state while scanning, stop at an unquoted inline comment, and
keep redirects from being read as pipes. Cover quoted separators, inline
comments, trailing comments, and pipe-vs-redirect.
An unanchored pattern matched the command text anywhere on an executable
line, so wrapping it in echo or printf satisfied the ordering assertion
while the workflow ran no validation at all.
Split each line on shell separators, strip control-flow prefixes, and
match anchored patterns against those command positions. Cover the helper
directly with cases for echo, printf, comments, and quoted mentions.
Matching a step's whole run body meant a commented-out command satisfied
the ordering assertion, so commenting out the prerelease notes check left
the test green while the workflow no longer validated anything.
Match executable lines only, and fold the version argument into the same
match so dropping it also fails.
The line-based guards allow-listed known-safe spellings, so bracket forms
like ${{ steps.version.outputs['VERSION'] }} never entered the candidate
list and passed, and the ordering check read indexOf over raw text, which
a comment naming the step could satisfy.
Parse the workflows instead and assert on step structure: no template
expression may appear in any run body, every step reading $RELEASE_VERSION
or $TAG_NAME must declare it in env, and the prerelease notes check must
precede the publishing step in the release job's step list.
Verified each guard fails on the three evasions it now covers.
The AUR test pinned the literal ${{ steps.version.outputs.VERSION }}
interpolation that moved into an env block, so it failed once the tag
value started reaching the shell as $RELEASE_VERSION.
Update that assertion and add guards for the invariant behind the move:
no tag-derived value may be interpolated into a run body, where GitHub
substitutes it before the shell parses the line. Also assert the
prerelease workflow runs the committed-notes check before it creates or
edits the release.
Document that the fragment delta resolves git paths against cwd, which
is both the project root and the repository root.