Skip to content

test(lint-shellcheck): deterministic barrier for worker-cap concurrency proof - #542

Merged
screenleon merged 3 commits into
mainfrom
feat/cc552-worker-cap-barrier
Aug 26, 2026
Merged

test(lint-shellcheck): deterministic barrier for worker-cap concurrency proof#542
screenleon merged 3 commits into
mainfrom
feat/cc552-worker-cap-barrier

Conversation

@screenleon

Copy link
Copy Markdown
Owner

Summary

  • CC-552: test_default_worker_cap used sleep 0.1 inside the ShellCheck stub to widen a race window for observing two-way concurrency, which QA rules forbid and which host scheduling could silently weaken (the old assertion only required max_active >= 1, so it would pass even without genuine overlap).
  • Workers now register at a counter guarded by the repo's existing serialize_with_lock and block on a blocking FIFO read (bounded 5s timeout, never a polling sleep) until a second worker signals release; a second FIFO carries an ack so the releasing worker doesn't exit before the released worker actually wakes, closing an asymmetric fast-exit window a gate reviewer found.
  • The assertion is now max_active == 2 (a real, deterministic proof of overlap) instead of >= 1. If the real cap ever collapses to 1, the lone worker's bounded FIFO read times out and fails with a clear message instead of hanging (avoiding the FIFO-open hang shape from CC-543).
  • BACKLOG.md CC-552 flipped to done in this same PR.

Test plan

  • bash tests/shell/test-lint-shellcheck.sh (17/17, including the changed case, run 5x for stability)
  • tools/lint/lint-shellcheck.sh clean on the whole repo
  • Manual jobs=3 mutation of a fixture copy of lint-shellcheck.sh: confirmed the barrier now observes max_active=6 and fails, where it previously would have silently reported 2 and passed
  • pmctl gate run --executor codex --policy generic → GO (after 2 remediation rounds: portable-lock reuse + sleep-free blocking wait, then the ack-handshake fix)
  • tests/bin/run-all-tests.sh → 104 passed, 0 failed, 0 skipped

🤖 Generated with Claude Code

https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx

screenleon and others added 3 commits August 26, 2026 20:54
…a file barrier

test_default_worker_cap used sleep 0.1 inside the ShellCheck stub to widen a
race window for observing two-way concurrency, which QA rules forbid and
which host load can silently weaken (max_active could observe 1 even when
the real cap is 2, since the old assertion only required >= 1). Workers now
register at a flock-serialized counter and all release together once exactly
two are concurrently registered, making the max_active == 2 assertion a
deterministic property of the protocol. A bounded 5s deadline fails the
stub with a clear message instead of hanging if the cap ever degrades to 1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx
qa-tester's gate review correctly flagged that the bounded busy-wait
(sleep-in-a-loop) still counted as forbidden sleep-based synchronization.
Switch to a blocking read on a bidirectionally-opened FIFO (open O_RDWR
never blocks, sidestepping the open()-hangs-forever failure mode a prior
ticket hit with a read-only/write-only FIFO) with a bounded -t timeout as
the only failure path, and reuse the repo's existing serialize_with_lock
helper for the counter mutex instead of a bespoke flock call (critic's
portability finding). Also fixed the fixture's total shell-file count,
which was odd and left the last worker of the sliding window unpaired.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx
…ner wakes

qa-tester's second gate round found that the releasing worker wrote its
release signal and immediately proceeded toward deregistration without
confirming the released worker actually woke up -- under a hypothetical
cap-3 regression, both original workers could deregister before a
concurrently-forked third worker reached the counter lock, letting the
observed max_active read 2 even though 3 were briefly resident. Add a
second FIFO for a blocking ack: the releaser now waits for the released
worker's ack before either side deregisters, closing that asymmetric
fast-exit window. Verified with a jobs=3 mutation of the fixture's copy
of lint-shellcheck.sh -- the test now observes max_active=6 and fails,
where it previously would have reported 2 and passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177ds9nxEMtsh3bwpBxNHYx
@screenleon
screenleon force-pushed the feat/cc552-worker-cap-barrier branch from 2e0ce06 to c283ec6 Compare August 26, 2026 11:56
@screenleon
screenleon merged commit 1b55144 into main Aug 26, 2026
64 checks passed
@screenleon
screenleon deleted the feat/cc552-worker-cap-barrier branch August 26, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant