You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
The guard budget test pins which command gets named, so it fails when CI is slow #24
tests/emit-claude-code.test.ts, "stops with a budget it can name when the guards outlive
the hook", fails intermittently on CI. It failed on node 22 in run 32344838190 while node
20 and 24 passed, then passed on all three when the failed job was re-run.
The fixture puts two guards at one node, against a shared budget:
That holds only when the first sleep 1 finishes inside the 1200 ms budget. The margin is
about 200 ms, and it has to cover process spawn plus hook overhead. On a loaded runner the
first command spends the budget by itself, so the message names it instead:
observation exitZero:{"command":"sleep 1"} failed: the 1200ms guard budget for this
transition was spent while sleep 1 was running.
The behaviour under test is correct in both cases. The run stops, the message names the
command that spent the budget, and the transition is not taken. Only the assertion is over
specified. It pins which of the two commands gets named, and that depends on timing.
Why it matters
Run 32344838190 was the CI for #23, a release. So the release stalled on a red check that
had nothing to do with the change, and a reader has to open the log to learn that.
Options
Assert the shape rather than the identity. The message names one of the two
commands. That matches the guarantee the test defends, which its own comment states:
"Neither command is slow on its own, and a per-command bound would let both through."
Which command gets blamed is not part of that guarantee.
Widen the margin, for example a 1800 ms budget, so the first command reliably fits. Still
timing dependent, only less often.
Replace the sleeps with something of deterministic duration. Hard to do portably.
Activity