From 489488a2bf9e1556fd7af3ab340bb4a325e7c51f Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 14 Oct 2026 13:53:25 -0700 Subject: [PATCH 1/4] test: over 100 checks, a held check still waits for its rescue (no bead) Co-Authored-By: Claude Opus 5.5 --- scripts/test-glaeda-gh.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/scripts/test-glaeda-gh.py b/scripts/test-glaeda-gh.py index 7d244c8c1..912003c4a 100644 --- a/scripts/test-glaeda-gh.py +++ b/scripts/test-glaeda-gh.py @@ -1271,6 +1271,32 @@ def in_run(check: dict, run: int, seconds: int, required: bool = True) -> dict: data["checks"][0]["failedSteps"] = ["Run selected tests"] self.assertEqual(gg.verdict("pr", data, "green"), 1) + def test_over_100_checks_a_held_check_still_waits_for_its_rescue(self) -> None: + """manaflow-ai/cmux#20733 (95 checks shown of more): the rescue cancelled a queued fast tier, and + the wait exited 1 on GitHub's FAILURE rollup while 13 checks still ran and the re-run was due.""" + now = time.time() + queued = {**check_run("fast tier", conclusion="CANCELLED"), "id": "CR_q", "databaseId": 5, + "startedAt": iso(now - 104), "completedAt": iso(now - 5), + "checkSuite": {"conclusion": "CANCELLED", "workflowRun": {"databaseId": 9, "workflow": {"name": "cmux-next"}}}} + running = check_run("react-apps-check", status="IN_PROGRESS", conclusion=None) + data = gg.parse_pr(pr_node(1, rollup="FAILURE", checks=[queued, running, check_run("build")])) + data["checks"][0]["stepCount"] = 0 + many = {**data, "checksTruncated": True, "checkState": "FAILURE"} + self.assertIsNone(gg.verdict("pr", many, "green")) + self.assertIsNone(gg.verdict("pr", many, "done")) + # the re-run never came: the rollup's FAILURE decides once the grace is over + settled = {**many, "checks": [c for c in many["checks"] if c.get("name") != "react-apps-check"]} + self.assertEqual(gg.verdict("pr", settled, "green", now=now + gg.RESCUE_GRACE + 1), 1) + # a real failure in the shown checks still fails at once; with none shown and none held, the + # rollup's FAILURE is a check past the first 100 + broken = gg.parse_pr(pr_node(2, rollup="FAILURE", checks=[queued, check_run("lint", conclusion="FAILURE")])) + broken["checks"][0]["stepCount"] = 0 + self.assertEqual(gg.verdict("pr", {**broken, "checksTruncated": True, "checkState": "FAILURE"}, "green"), 1) + hidden = gg.parse_pr(pr_node(3, rollup="FAILURE", checks=[check_run("build")])) + self.assertEqual(gg.verdict("pr", {**hidden, "checksTruncated": True, "checkState": "FAILURE"}, "green"), 1) + ok = gg.parse_pr(pr_node(4, rollup="SUCCESS", checks=[check_run("build")])) + self.assertEqual(gg.verdict("pr", {**ok, "checksTruncated": True, "checkState": "SUCCESS"}, "green"), 0) + def test_a_check_cancelled_before_any_step_is_held_for_the_rescue(self) -> None: """manaflow-ai/cmux#20608: the owned-pool rescue cancelled a fast tier still queued for a runner (no step ran) and re-ran it; a wait that read the gap exited 1 before the re-run.""" From a4fc7e5a04dc906868dd7719dced503cbb9bfd6c Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 14 Oct 2026 13:53:48 -0700 Subject: [PATCH 2/4] fix: over 100 checks, a held or running check defers the rollup's FAILURE (no bead) Co-Authored-By: Claude Opus 5.5 --- scripts/glaeda-gh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/glaeda-gh b/scripts/glaeda-gh index cf809039a..5a5b5639e 100755 --- a/scripts/glaeda-gh +++ b/scripts/glaeda-gh @@ -1236,10 +1236,22 @@ def classify(data: dict, now: float | None = None, grace: float = RESCUE_GRACE) def check_verdict(data: dict, until: str = "green", now: float | None = None, grace: float = RESCUE_GRACE) -> int | None: """The checks alone, whatever the PR's state or head: EXIT_OK, EXIT_FAIL, or None while pending.""" - if data.get("checksTruncated"): # more than 100 checks: GitHub's own rollup decides - state = data.get("checkState") - return EXIT_OK if state == "SUCCESS" else EXIT_FAIL if state in {"FAILURE", "ERROR"} else None checks = data.get("checks") or [] + if data.get("checksTruncated"): + # More than 100 checks: only the first 100 are here, so GitHub's rollup decides, except that a + # check shown as held or still running defers its FAILURE (manaflow-ai/cmux#20733: a queued fast + # tier the rescue cancelled read as a failure while 13 checks still ran). + state = data.get("checkState") + if state == "SUCCESS": + return EXIT_OK + if state not in {"FAILURE", "ERROR"}: + return None + groups = classify(data, now, grace) + if groups["failed"] and until != "required": + return EXIT_FAIL + if groups["held"] or (until == "done" and groups["pending"]): + return None + return EXIT_FAIL if not checks: return None # nothing has reported yet marked = any(c.get("required") for c in checks) From a738f625b7e712a2bf820b474ca239a3221aec22 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 14 Oct 2026 13:55:20 -0700 Subject: [PATCH 3/4] test: over 100 checks, --until done waits out a shown failure's running siblings (no bead) Co-Authored-By: Claude Opus 5.5 --- scripts/test-glaeda-gh.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/test-glaeda-gh.py b/scripts/test-glaeda-gh.py index 912003c4a..75e046faf 100644 --- a/scripts/test-glaeda-gh.py +++ b/scripts/test-glaeda-gh.py @@ -1292,6 +1292,10 @@ def test_over_100_checks_a_held_check_still_waits_for_its_rescue(self) -> None: broken = gg.parse_pr(pr_node(2, rollup="FAILURE", checks=[queued, check_run("lint", conclusion="FAILURE")])) broken["checks"][0]["stepCount"] = 0 self.assertEqual(gg.verdict("pr", {**broken, "checksTruncated": True, "checkState": "FAILURE"}, "green"), 1) + # --until done waits for every shown check to finish, failure or not, as under 100 checks + busy = gg.parse_pr(pr_node(5, rollup="FAILURE", checks=[check_run("lint", conclusion="FAILURE"), running])) + self.assertIsNone(gg.verdict("pr", {**busy, "checksTruncated": True, "checkState": "FAILURE"}, "done")) + self.assertEqual(gg.verdict("pr", {**busy, "checksTruncated": True, "checkState": "FAILURE"}, "green"), 1) hidden = gg.parse_pr(pr_node(3, rollup="FAILURE", checks=[check_run("build")])) self.assertEqual(gg.verdict("pr", {**hidden, "checksTruncated": True, "checkState": "FAILURE"}, "green"), 1) ok = gg.parse_pr(pr_node(4, rollup="SUCCESS", checks=[check_run("build")])) From 13395fe4e234448c40b103b1695ee584aee0507a Mon Sep 17 00:00:00 2001 From: Leo Li Date: Wed, 14 Oct 2026 13:55:31 -0700 Subject: [PATCH 4/4] fix: over 100 checks, --until done waits for every shown check (no bead) Co-Authored-By: Claude Opus 5.5 --- scripts/glaeda-gh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/glaeda-gh b/scripts/glaeda-gh index 5a5b5639e..cafcfcb31 100755 --- a/scripts/glaeda-gh +++ b/scripts/glaeda-gh @@ -1247,11 +1247,11 @@ def check_verdict(data: dict, until: str = "green", now: float | None = None, if state not in {"FAILURE", "ERROR"}: return None groups = classify(data, now, grace) + if until == "done" and (groups["pending"] or groups["held"]): + return None # every shown check finishes first, as under 100 checks if groups["failed"] and until != "required": return EXIT_FAIL - if groups["held"] or (until == "done" and groups["pending"]): - return None - return EXIT_FAIL + return None if groups["held"] else EXIT_FAIL if not checks: return None # nothing has reported yet marked = any(c.get("required") for c in checks)