tests.yml caps each bats shard at timeout-minutes: 25 with the comment "A shard has generous headroom under this cap; a timeout is a genuine hang." That assumption no longer holds on macOS runners, and the failure it produces is a wall-clock cancellation of a passing shard, not a hang and not a flaky test.
Measured on main (run 31936446984, 2026-08-16): bats (macos-latest 1/4) took 21m17s of the 25m budget; the other quarters took ~10–11m. The shard helper's own header still cites 125s/298s/366s/71s quarters — the suite has grown well past those numbers.
How it bites a PR: sharding is count-balanced and computed from the tree, so a PR that adds tests re-packs the shards. On #507 (+13 @tests), the re-pack made bats (macos-latest 4/4) a 384-test shard that runs all 384 tests to ok 384 and is then cancelled by the timeout — observed twice, at 25m07s and 25m20s, with the final ok landing seconds before the cancellation (second run: last ok 384 at 14:03:39, cancel at 14:04:07). The log shows 1..384 with zero failures; the "genuine hang" the cap was written to catch is exactly what this is not.
With main's largest quarter already at 21m, a test-adding PR that re-packs a shard past ~25m of runtime hits the same cancellation, and the signature (a CANCELLED shard failing the check) reads like the PR broke something.
Possible directions (maintainer's call): raise SHARD_TOTAL for macOS, raise the cap while keeping a genuine-hang detector (e.g. a no-output watchdog instead of wall-clock), or move the balancing weight from @test count to measured runtime. Related but distinct: #595 / #828 are about flaky individual tests; this one is capacity.
Happy to send whichever direction you prefer as a PR.
tests.ymlcaps each bats shard attimeout-minutes: 25with the comment "A shard has generous headroom under this cap; a timeout is a genuine hang." That assumption no longer holds on macOS runners, and the failure it produces is a wall-clock cancellation of a passing shard, not a hang and not a flaky test.Measured on main (run 31936446984, 2026-08-16):
bats (macos-latest 1/4)took 21m17s of the 25m budget; the other quarters took ~10–11m. The shard helper's own header still cites 125s/298s/366s/71s quarters — the suite has grown well past those numbers.How it bites a PR: sharding is count-balanced and computed from the tree, so a PR that adds tests re-packs the shards. On #507 (+13
@tests), the re-pack madebats (macos-latest 4/4)a 384-test shard that runs all 384 tests took 384and is then cancelled by the timeout — observed twice, at 25m07s and 25m20s, with the finaloklanding seconds before the cancellation (second run: lastok 384at 14:03:39, cancel at 14:04:07). The log shows1..384with zero failures; the "genuine hang" the cap was written to catch is exactly what this is not.With main's largest quarter already at 21m, a test-adding PR that re-packs a shard past ~25m of runtime hits the same cancellation, and the signature (a CANCELLED shard failing the check) reads like the PR broke something.
Possible directions (maintainer's call): raise
SHARD_TOTALfor macOS, raise the cap while keeping a genuine-hang detector (e.g. a no-output watchdog instead of wall-clock), or move the balancing weight from@testcount to measured runtime. Related but distinct: #595 / #828 are about flaky individual tests; this one is capacity.Happy to send whichever direction you prefer as a PR.