Skip to content

540 is blind to the shell if/then/else verdict: five live arms discard their operands untracked #1255

Description

@OffgridwithJD

What

Selftest part 540 refuses an arm that cannot say what it measured. Both of its
matchers require the && spelling, so the shell if/then/else spelling is
invisible to it:

  "$(if [ "$sj_idx" -ge 2 ]; then echo 1; else echo 0; fi)"

Both branches are constants, the operand is discarded, and the arm renders
got [0] want [1] -- the exact symptom #1164 is named for. Five live arms in
the corpus are lossy this way and none is tracked.

The five

After applying 540's own carve-outs (determinate(): a file test names its own
subject, -eq/-ne/=/==/!=, and -gt/-ge against 0 or 1), so these are
in scope by the suite's own rule rather than by mine:

  capability_sweep.sh        premise: the population is the size this tree holds
                             [ "$n_narrow" -ge 30 ]
  catalog_plan_index.sh      planning a join probed pgcolumnar.storage through storage_pkey
                             [ "$sj_idx" -ge 2 ]
  catalog_plan_index.sh      premise: the join reached storage more than once
                             [ "$((sj_idx + sj_seq))" -ge 2 ]
  selftest/560-...           premise: the caller's text was actually found, so the
                             counts mean something
                             [ "$(printf '%s\n' "$_wire" | wc -l)" -ge 10 ]
  selftest/590-...           premise: declared suites do have clean exits of their own
                             [ "$_da_e0" -ge 4 ]

Raw matches before the carve-outs: 12. The other 7 are excused by
determinate() and are correctly out of scope.

Why this is not one of the gaps 540 already records

540's STILL OUT OF SCOPE section is careful and names three things. All three
are about awk:

  • a verdict computed into a variable and checked later,
  • BEGIN { if (a <= b*2) print "yes"; else print "no" } -- an awk if/else,
  • an awk at the end of a pipe, where $(awk is not in the matched position.

The shell $(if [ ... ]; then echo ...; fi) form is none of these and is not
named anywhere in the file.

The distinction that matters for priority: both recorded awk gaps are closed with
"Zero live sites" and "ZERO ARE LOSSY TODAY", which is why leaving them
open was reasonable. This one has five.

How it was measured, and the lift validated first

The sweep was lifted out of 540 verbatim and validated against the shipped list
before being used for anything, which is the discipline the file itself asks for:

  tracked (comments stripped)  101
  lifted sweep found           101
  comm -23 (found not tracked)  empty
  comm -13 (tracked not found)  empty

Scoped exactly as the suite scopes itself: test/*.sh and test/selftest/*.sh,
excluding 540.

A second, smaller asymmetry in the same matcher

The awk-verdict rule requires the recorder on the same folded line:

  line ~ /(check|check_num|...)[[:space:]]+"/ && line ~ /\$\(awk/

The [ ... ] && echo rule directly below it has no such conjunct, and then
uses name, which the file's own comment describes as "the LAST name seen". So
a helper containing that shape is charged to whichever recorder arm precedes it.
Demonstrated:

  base sweep   planning a join probed pgcolumnar.storage through storage_pkey   <- innocent
               a count against a floor
  fixed sweep  a count against a floor

The comment THE RECORDER MUST BE ON THIS LINE sits directly above the awk rule,
explains this failure, and cites having measured it ("4 of 32 findings were
manufactured that way"). It was applied to one rule of the two.

Adding the conjunct is inert on the corpus today: 101 found before, 101
after, both comm directions empty. So it loses no tracked debt and invents
none, and I am not claiming it fixes a live wrong name -- there isn't one on
main.

What I propose, and what I am not doing

Widen the matcher to the shell if/then/else spelling, add the conjunct to the
[ rule, and add the five arms to lossy_arms.tsv -- then repair them, since a
premise that discards its count is the case the tracked list exists to shrink.

I am not touching catalog_plan_index.sh. Two of the five are in it and it
is live in #1254. That is @jdatcmd's to take or to hand back; the other three are
unclaimed and I will take them if nobody objects.

Found while checking a 540 attribution question raised by a peer session. Their
specific case I could not reproduce -- their helper has no command
substitution, so it cannot match either rule however it is placed -- and the two
findings above are independent of it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MpajdQbkVJ9ey1XyYHcikP

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions