ci: flag condition polls bounded by a Task.yield() count - #14019
Conversation
A loop that polls a condition for N Task.yield() calls fails on correct code when the runner is busy, which is the shape the determinism rules ban, but check-test-determinism.py reports none of them because it only matches sleep call sites (#13903). These self-test fixtures describe a yield-count-poll rule and fail until the detector exists. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check-test-determinism.py now reports yield-count-poll: a Swift `for _ in 0..<N` loop that awaits Task.yield() and exits on a condition, with no deadline in the body. A yield waits for nothing, so the bound shrinks exactly when the runner is busy (#13903). Loops that already read a clock, drain yields with no condition, or exit only on cancellation are not flagged. The 126 existing sites in 58 files are allowlisted by file so the strict gate stays green; new files with the shape fail it. The rules doc names the shape beside the sleep ban. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
Warning Review limit reachedNext included review available in 18 minutes. View limit detailsLimit details: You’ve used all 10 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (3)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Self-review. What I verified:
CI tooling and docs only, so I'm enabling squash auto-merge. — Ophelia g1 🍄 |
|
All contributors have signed the CLA ✍️ ✅ |
06c2101 ci: route streamed validation by capability instead of by lane name (manaflow-ai#14002) 1773c54 ci(e2e): start builds from main's DerivedData so test-only changes skip the app compile (manaflow-ai#14016) c890374 ci: pin the nightly runner guards to the whole expression (manaflow-ai#13997) 8abd2e9 ci: flag condition polls bounded by a Task.yield() count (manaflow-ai#14019) e4ca672 ci(ios): record the cmux.app upload once Apple accepts it (manaflow-ai#14014) 260b648 ci: check what the runner variables hold, not just what the workflows say (manaflow-ai#13992) 25ad5af feat(terminal): opt-in macOS text-editing gestures at the shell prompt (manaflow-ai#13921) daf9649 test: drop six focus-history cases superseded by FocusHistoryScopeTests (manaflow-ai#13975) 11202e3 Name the workspace that workspace.reorder could not resolve (manaflow-ai#13961) 2a4f3f6 fix(fork): make the fallback refresh await its own queued validation (manaflow-ai#13960) 4b82298 ci: let test-depot run one app-host test by selector (manaflow-ai#14001) 5d1ecb8 test: give each drained write its own deadline in the short-chunks reader test (manaflow-ai#13999) # Conflicts: # .github/workflows/ci-guards.yml # .github/workflows/ci-health-report.yml # .github/workflows/ios-appstore-upload.yml # .github/workflows/ios-streamed-validate.yml # .github/workflows/iroh-release-gate.yml # .github/workflows/nightly.yml # .github/workflows/test-depot.yml # .github/workflows/test-e2e.yml
Summary
check-test-determinism.pyreported 0 findings incmuxTests, yet 27 waits there polled a condition for a fixed number ofTask.yield()calls (#13903). A yield waits for nothing. N yields take however long N reschedules happen to take, so the bound shrinks exactly when the runner is busy, and a slow pass becomes a failure. That is the shapetest-determinism.mdbans, and it produced theSimulatorPanelThemeTestsflake that #13907 fixed. The checker could not see it because it only matched sleep call sites.The checker now has a
yield-count-pollrule for Swift test files. It flags afor _ in 0..<N/for _ in A...Bloop that awaitsTask.yield(), exits on a condition (breakorreturn), and reads no clock. It does not flag:for _ in 0..<N { await Task.yield() }drains with no condition. Test determinism: 27 waits bound a poll by Task.yield() count, not a deadline — the checker sees none of them #13903's follow-up comment separates these out: they wait for a non-event and need a positive signal, not a deadline.Task.isCancelledOn current
mainthe rule finds 126 sites in 58 files. That includes the 17 remainingcmuxTestssites #13903 lists after #13907, and a random sample of thePackages/**/Testshits were all real condition polls. They are allowlisted per file in.github/test-determinism-allowlist.txt, with a reason pointing at #13903, so the--strictgate stays green. New test files with the shape fail it. The allowlist is keyed by (file, rule), as for the existing rules, so a new site added to an already-listed file is not caught. The rules doc now names the shape beside the sleep ban.Refs #13903. This is the checker half. Converting the 126 sites is separate work, and each file comes off the allowlist once it is converted.
Testing
SimulatorPanelThemeTestsshape,returnandguardexits, a one-line loop, a deadline-bounded loop, a bare drain, a cancellation-only exit, a named index, a Python analogue, and a string literal. Commit 1 adds only the fixtures, and--self-testfails with 4 missing positives. Commit 2 passes (142 positive + 92 negative).python3 scripts/check-test-determinism.py --stricton the branch rebased onto currentmain: 0 active, 126 allowlisted.ci-guards.ymllocally, and all passed except three that fail for environment reasons:test_ghostty_zig_version_sync.shandlint-stored-dispatch-work-items.pyneed submodules this checkout lacks, and the app-hostcatalog-diffline needs$RUNNER_TEMPand a base SHA. Theci-cache-receipts.ymlinvocation (--roots tests/test_ci_cache_restore_receipt.py --strict) passes.Demo Video
Not applicable (CI tooling change).
Checklist
.github/review-bot-rules/test-determinism.md)— Ophelia g1 🍄
Run: run_cmux_main_red_triage_app_host_census_and_pr_review_20260923_07d8d17b
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Adds a
yield-count-pollrule tocheck-test-determinism.pythat flags Swift loops which poll a condition for a fixed number ofTask.yield()calls. A yield waits for nothing, so the bound shrinks exactly when the runner is busy and a slow pass becomes a failure; the checker previously missed this shape because it only matched sleep call sites (refs #13903).--strictgate stays green; new files with the shape now fail it.Migration
Written for commit aa3b9ab. Summary will update on new commits.