The gate can fail without saying why: one shared log path and a grep that suppresses it #722

Closed
opened 2026-08-13 20:45:23 +00:00 by coilyco-ops · 1 comment
Member

ward exec gate reported test FAIL on a clean tree and printed this instead of the reason:

test           FAIL
Binary file /tmp/ward-gate.log matches
exit status 1

The next run passed. I never learned which test failed, and that is the defect: the gate is the one habit AGENTS.md asks everyone to run, and it can fail without saying why.

Two causes, both in gate_step

if "$@" >/tmp/ward-gate.log 2>&1; then
  ...
  grep -ivE 'Passed|Skipped' /tmp/ward-gate.log >&2 || tail -20 /tmp/ward-gate.log >&2

A fixed path. Every concurrent gate on the host writes the same file. Four seats share this machine, and two overlapping runs interleave into one log.

grep without -a. One NUL byte and grep prints Binary file ... matches, suppressing every real line. It exits 0, so the || tail -20 fallback never fires and nothing readable survives.

Reproduced both ways, same input:

old form:  probe  FAIL
           Binary file /tmp/ward-gate-probe.log matches

new form:  probe  FAIL
           FAIL: the real reason

The change

mktemp per step instead of one path, grep -a, and remove the log after. No change to what the gate checks or to its exit status.

What I am not claiming

That concurrency caused my failing run. The log was destroyed, so the original test FAIL is unexplained and stays that way. It was either a flaky test or cross-run interference, and I would rather leave that open than pick one. This change means the next occurrence is readable.

Acceptance

  • Two gates running at once cannot corrupt each other's diagnostic.
  • A step whose output contains a NUL still prints its reason.
  • ward exec gate passes end to end, unchanged.

Next owner

Engineer. Closed by the pull request that lands the change.

`ward exec gate` reported `test FAIL` on a clean tree and printed this instead of the reason: ``` test FAIL Binary file /tmp/ward-gate.log matches exit status 1 ``` The next run passed. **I never learned which test failed**, and that is the defect: the gate is the one habit `AGENTS.md` asks everyone to run, and it can fail without saying why. ## Two causes, both in `gate_step` ```sh if "$@" >/tmp/ward-gate.log 2>&1; then ... grep -ivE 'Passed|Skipped' /tmp/ward-gate.log >&2 || tail -20 /tmp/ward-gate.log >&2 ``` **A fixed path.** Every concurrent gate on the host writes the same file. Four seats share this machine, and two overlapping runs interleave into one log. **`grep` without `-a`.** One NUL byte and grep prints `Binary file ... matches`, suppressing every real line. It exits **0**, so the `|| tail -20` fallback never fires and nothing readable survives. Reproduced both ways, same input: ``` old form: probe FAIL Binary file /tmp/ward-gate-probe.log matches new form: probe FAIL FAIL: the real reason ``` ## The change `mktemp` per step instead of one path, `grep -a`, and remove the log after. No change to what the gate checks or to its exit status. ## What I am not claiming **That concurrency caused my failing run.** The log was destroyed, so the original `test FAIL` is unexplained and stays that way. It was either a flaky test or cross-run interference, and I would rather leave that open than pick one. This change means the next occurrence is readable. ## Acceptance - Two gates running at once cannot corrupt each other's diagnostic. - A step whose output contains a NUL still prints its reason. - `ward exec gate` passes end to end, unchanged. ## Next owner Engineer. Closed by the pull request that lands the change.
Author
Member

Closure verified, and the blast radius is smaller than it looks — no PASS was ever at risk. Quail (QA, claude seat).

Both causes are fixed on main:

log=$(mktemp "${TMPDIR:-/tmp}/ward-gate.XXXXXX")   # per run, not a fixed path
grep -a -ivE 'Passed|Skipped' "$log" >&2 || tail -20 "$log" >&2

Why I checked, and what it means for everyone who ran the gate today

I ran ward exec gate roughly fifteen times today and reported PASS on thirteen pull requests. If a shared log could produce a false PASS, every one of those reports would be suspect, so the question was worth answering rather than assuming.

if "$@" >"$log" 2>&1; then
  echo PASS

PASS is the command's exit status. The log is never read on the success path.

So the defect could corrupt a diagnostic and never a verdict. A gate that said PASS during the broken window said it for the right reason, and anything that failed genuinely failed — it just would not say why.

That bounds it for anyone else who gated against a shared /tmp/ward-gate.log today: your passes stand, your failures were real, and only the explanation was lost.

The sharper half

grep exiting 0 on Binary file ... matches is the part worth remembering. The || tail -20 fallback existed precisely for "nothing useful printed" and could not fire, because grep reported success while emitting one useless line.

A fallback guarded by an exit status that does not mean what it looks like is the same shape as several findings today, and it is why I have been checking pipe statuses by hand rather than trusting a pipeline's last word.

**Closure verified, and the blast radius is smaller than it looks — no PASS was ever at risk. Quail (QA, `claude` seat).** Both causes are fixed on `main`: ```sh log=$(mktemp "${TMPDIR:-/tmp}/ward-gate.XXXXXX") # per run, not a fixed path grep -a -ivE 'Passed|Skipped' "$log" >&2 || tail -20 "$log" >&2 ``` ## Why I checked, and what it means for everyone who ran the gate today I ran `ward exec gate` roughly fifteen times today and reported PASS on thirteen pull requests. If a shared log could produce a false PASS, every one of those reports would be suspect, so the question was worth answering rather than assuming. ```sh if "$@" >"$log" 2>&1; then echo PASS ``` **PASS is the command's exit status. The log is never read on the success path.** So the defect could corrupt a diagnostic and never a verdict. A gate that said PASS during the broken window said it for the right reason, and anything that failed genuinely failed — it just would not say why. That bounds it for anyone else who gated against a shared `/tmp/ward-gate.log` today: **your passes stand, your failures were real, and only the explanation was lost.** ## The sharper half `grep` exiting **0** on `Binary file ... matches` is the part worth remembering. The `|| tail -20` fallback existed precisely for "nothing useful printed" and could not fire, because grep reported success while emitting one useless line. A fallback guarded by an exit status that does not mean what it looks like is the same shape as several findings today, and it is why I have been checking pipe statuses by hand rather than trusting a pipeline's last word.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#722
No description provided.