Skip to content

I1967 — A reporter that sets a flag is a reporter

Make the pipeline-count guard discover a reporter that records a failure by setting a flag, not only one that increments a counter, so a call to it inside a construct that discards the flag is refused like a lost count.

DONE wave 0 · p2 · implementation profile · parallel safe

Part of development-runtime — The runtime has a development surface.

Objective

Make the pipeline-count guard discover a reporter that records a failure by setting a flag, not only one that increments a counter, so a call to it inside a construct that discards the flag is refused like a lost count.

Why

This is the open half of I1513, filed on PR #548, which was closed on 2026-10-03 when the owner decided it. scripts/lib/counting-functions.awk finds only functions whose body adds one to a variable they did not declare local. scripts/ci/pages-check's `bad() { ...; fail=1; }` records its failure as a flag and is invisible to it, so a call to `bad` inside a `... | while read` loop would set the flag in a subshell, lose it, and let the gate exit 0 while printing the failure. #548's I1513 cannot be reused: its number collides with #292's own I1513, and ADR 0053 forbids recycling a gap.

Current state

scripts/lib/counting-functions.awk prints the functions that increment an undeclared variable, and shell-lint refuses a call to one of them inside a pipeline-fed loop (scripts/lib/pipeline-counts.awk, checked against a known-answer fixture first). A function that assigns a constant to an undeclared variable it is not given (`fail=1`, `bad=1`) is not discovered.

Desired state

counting-functions.awk also prints a function whose body assigns a constant to a variable it did not declare local, and shell-lint therefore refuses a call to it inside a pipeline-fed loop, with the file and line. The known-answer fixture carries a flag-setting reporter, and the guard is refused when it does not find it.

Scope

  • scripts/lib/counting-functions.awk
  • scripts/ci/shell-lint
  • test/cases

Out of scope

  • Rewriting gates that are already correct: the guard names what is lost, not what offends taste
  • A check assembled from another program's output that dies silently, which I1513 named as its third face and test/cases/341 covers on its own

Dependencies

None. This issue is a root of the graph.

Acceptance criteria

  • A function that sets a flag rather than incrementing a counter is discovered as a reporter
  • A call to such a reporter inside a pipeline-fed loop is refused, with the file and line
  • The known-answer fixture holds a flag-setting reporter, and the guard refuses itself when it does not find it

Validation

  • bash scripts/ci/shell-lint

Evidence required

  • a_flag_setting_reporter_is_discovered

Evidence

coverstypecommandresultat commit
a_flag_setting_reporter_is_discoveredtestbash test/run.sh 870_a_flag_setting_reporter_is_a_reporterok at 4090b2b8ae, and scripts/ci/shell-lint exits 0: a function that sets a flag is discovered as a reporter, its call in a pipeline-fed loop is refused with file and line, and the guard refuses itself when blinded; the change is 15f95faf92 (PR #742, landed in #806)4090b2b

Risk

Low. The guard can only refuse shapes that already lose a verdict; a false alarm on a flag nobody reads is answered by naming the reporter it found.

Timeline

started
2026-10-08T10:33:59Z
verified
2026-10-08T10:34:35Z
completed
2026-10-08T10:34:40Z

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I1967.yaml. Read it back with majordomus plan show I1967.

Searches the titles and descriptions of every page this site publishes.