From d1c6fce937d750a80f541622cb4516c5decf489b Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sat, 6 Jun 2026 17:27:08 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix(ci):=20lint-pre-flip=20fail-closed=20?= =?UTF-8?q?=E2=80=94=20unreadable=20success=20logs=20treated=20as=20masked?= =?UTF-8?q?=20+=20workflow=20flag=20flipped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SCRIPT fail-closed: - unreadable log + success status → masked_run (was warn-only PASS). Quirk #10 (continue-on-error masking) cannot be verified when logs are pruned; fail-closed means block the flip. WORKFLOW flag: - continue-on-error: true → false on scan job. Diff-proof: 35/35 pytest tests pass. Refs: mc#1982, internal#219 §1 --- .gitea/scripts/lint_pre_flip_continue_on_error.py | 11 +++++++++++ .../tests/test_lint_pre_flip_continue_on_error.py | 11 ++++++----- .../workflows/lint-pre-flip-continue-on-error.yml | 15 ++++++--------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/.gitea/scripts/lint_pre_flip_continue_on_error.py b/.gitea/scripts/lint_pre_flip_continue_on_error.py index bdf417efb..749a56d38 100644 --- a/.gitea/scripts/lint_pre_flip_continue_on_error.py +++ b/.gitea/scripts/lint_pre_flip_continue_on_error.py @@ -582,6 +582,17 @@ def verify_flip(flip: dict, branch: str, n: int) -> dict: "target_url": target_url, "samples": ["[log unavailable; status itself is " + state + "]"], }) + elif state == "success": + # Fail-closed: unreadable log on a success status is a + # potential Quirk #10 mask (continue-on-error hiding real + # failures). We cannot verify it's clean, so treat as + # masked rather than allowing the flip. + result["masked_runs"].append({ + "sha": sha, + "status": state, + "target_url": target_url, + "samples": ["[log unavailable; cannot verify status is genuine — treat as masked]"], + }) break samples = grep_fail_markers(log_text) if state in ("failure", "error"): diff --git a/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py b/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py index 333fb814a..44acb7f48 100644 --- a/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py +++ b/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py @@ -320,10 +320,10 @@ class TestVerifyFlip(unittest.TestCase): self.assertEqual(len(verdict["fail_runs"]), 1) self.assertEqual(verdict["fail_runs"][0]["status"], "failure") - def test_unreadable_log_warns_not_blocks(self): - # Acceptance test #5: log fetch 404 (None) → warn, not block. - # Status is `success`, log is None — we can't tell, so we warn - # and allow. + def test_unreadable_log_on_success_blocks(self): + # Fail-closed: log fetch 404 (None) on a success status is a + # potential Quirk #10 mask — we cannot verify it's genuine, so + # we block the flip rather than allowing it. with mock.patch.object(lpfc, "recent_commits_on_branch", return_value=["sha1"]): with mock.patch.object( lpfc, "combined_status", @@ -332,7 +332,8 @@ class TestVerifyFlip(unittest.TestCase): with mock.patch.object(lpfc, "fetch_log", return_value=None): verdict = lpfc.verify_flip(FLIP_FIXTURE, "main", 5) self.assertEqual(verdict["fail_runs"], []) - self.assertEqual(verdict["masked_runs"], []) + self.assertEqual(len(verdict["masked_runs"]), 1) + self.assertIn("log unavailable", verdict["masked_runs"][0]["samples"][0]) self.assertTrue(any("log unavailable" in w for w in verdict["warnings"])) def test_unreadable_log_with_failure_status_still_blocks(self): diff --git a/.gitea/workflows/lint-pre-flip-continue-on-error.yml b/.gitea/workflows/lint-pre-flip-continue-on-error.yml index 5f9021867..e54d0c5a6 100644 --- a/.gitea/workflows/lint-pre-flip-continue-on-error.yml +++ b/.gitea/workflows/lint-pre-flip-continue-on-error.yml @@ -61,11 +61,9 @@ name: Lint pre-flip continue-on-error # feedback_no_shared_persona_token_use. # # Phase contract (RFC internal#219 §1 ladder): -# - This workflow lands at `continue-on-error: true` (Phase 3 — -# surface defects without blocking). Follow-up PR flips it to -# `false` ONLY after this workflow's own recent runs on `main` -# are confirmed clean — exactly the discipline the workflow -# itself enforces. Eat your own dogfood. +# - Flipped to `continue-on-error: false` after Researcher live-verified +# clean runs. The script's own 35 pytest tests pass and recent PR +# history shows no masked regressions — the gate is now enforcing. on: pull_request: @@ -97,10 +95,9 @@ jobs: name: Verify continue-on-error flips have run-log proof runs-on: ubuntu-latest timeout-minutes: 8 - # Phase 3 (RFC internal#219 §1): surface broken flips without blocking - # the PR yet. Follow-up flips this to `false` once the workflow itself - # has clean recent runs on main. mc#1982 interim — remove when CoE→false. - continue-on-error: true # mc#1982 + # Fail-closed: the lint script is verified clean (35/35 tests pass, + # Researcher live-check confirmed). Masking removed per mc#1982 close-out. + continue-on-error: false steps: - name: Check out PR head (full history for base-SHA access) uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 -- 2.52.0 From 8a63d16f8c7fd044d3d0febd3d86c97feea36964 Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sat, 6 Jun 2026 17:42:44 +0000 Subject: [PATCH 2/2] =?UTF-8?q?fix(ci):=20lint-pre-flip=20fail-closed=20?= =?UTF-8?q?=E2=80=94=20ApiError=20and=20zero-runs=20now=20blocking=20(#236?= =?UTF-8?q?9=20RC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per Researcher + CR2 RC: - combined_status() ApiError now appends to masked_runs (was warning+continue) - zero checked_commits now appends to masked_runs (was warning+allow) - zero recent commits now appends to masked_runs (was warning+allow) - Final decision already blocks on masked_runs, so unverifiable flips are now blocked rather than passing with warnings only. Diff-proof: 36/36 pytest tests pass. Refs: core#2369, Researcher RC + CR2 RC. --- .../lint_pre_flip_continue_on_error.py | 26 ++++++++++----- .../test_lint_pre_flip_continue_on_error.py | 33 ++++++++++++++----- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/.gitea/scripts/lint_pre_flip_continue_on_error.py b/.gitea/scripts/lint_pre_flip_continue_on_error.py index 749a56d38..ccd03e356 100644 --- a/.gitea/scripts/lint_pre_flip_continue_on_error.py +++ b/.gitea/scripts/lint_pre_flip_continue_on_error.py @@ -546,16 +546,24 @@ def verify_flip(flip: dict, branch: str, n: int) -> dict: shas = recent_commits_on_branch(branch, n) if not shas: - result["warnings"].append( - f"no recent commits on {branch} (cannot verify flip)" - ) + result["masked_runs"].append({ + "sha": "", + "status": "unverified", + "target_url": "", + "samples": [f"no recent commits on {branch} — cannot verify flip"], + }) return result for sha in shas: try: status_doc = combined_status(sha) except ApiError as e: - result["warnings"].append(f"combined-status for {sha}: {e}") + result["masked_runs"].append({ + "sha": sha, + "status": "error", + "target_url": "", + "samples": [f"combined-status API error: {e}"], + }) continue statuses = status_doc.get("statuses") or [] # First entry matching the context name. Newest SHAs come @@ -616,10 +624,12 @@ def verify_flip(flip: dict, branch: str, n: int) -> dict: break if result["checked_commits"] == 0: - result["warnings"].append( - f"no runs of {target_context!r} found in the last {n} commits on " - f"{branch} — cannot verify; allowing flip with warning" - ) + result["masked_runs"].append({ + "sha": "", + "status": "unverified", + "target_url": "", + "samples": [f"no runs of {target_context!r} found in the last {n} commits on {branch} — cannot verify flip"], + }) return result diff --git a/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py b/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py index 44acb7f48..31a3739b8 100644 --- a/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py +++ b/.gitea/scripts/tests/test_lint_pre_flip_continue_on_error.py @@ -350,9 +350,9 @@ class TestVerifyFlip(unittest.TestCase): self.assertEqual(len(verdict["fail_runs"]), 1) self.assertIn("log unavailable", verdict["fail_runs"][0]["samples"][0]) - def test_zero_runs_history_warns_allows(self): - # No commits with a matching context — newly added workflow. - # Allow with warning. + def test_zero_runs_history_blocks(self): + # No commits with a matching context — cannot verify the flip. + # Fail-closed: treat as masked rather than allowing. with mock.patch.object(lpfc, "recent_commits_on_branch", return_value=["sha1", "sha2"]): with mock.patch.object( lpfc, "combined_status", @@ -361,17 +361,32 @@ class TestVerifyFlip(unittest.TestCase): verdict = lpfc.verify_flip(FLIP_FIXTURE, "main", 5) self.assertEqual(verdict["checked_commits"], 0) self.assertEqual(verdict["fail_runs"], []) - self.assertEqual(verdict["masked_runs"], []) - self.assertTrue(any("no runs of" in w for w in verdict["warnings"])) + self.assertEqual(len(verdict["masked_runs"]), 1) + self.assertIn("cannot verify flip", verdict["masked_runs"][0]["samples"][0]) - def test_zero_commits_warns_allows(self): - # Empty branch (newly created repo, e.g.). Allow with warning. + def test_zero_commits_blocks(self): + # Empty branch (newly created repo, e.g.). Fail-closed: block. with mock.patch.object(lpfc, "recent_commits_on_branch", return_value=[]): verdict = lpfc.verify_flip(FLIP_FIXTURE, "main", 5) self.assertEqual(verdict["checked_commits"], 0) self.assertEqual(verdict["fail_runs"], []) - self.assertEqual(verdict["masked_runs"], []) - self.assertTrue(any("no recent commits" in w for w in verdict["warnings"])) + self.assertEqual(len(verdict["masked_runs"]), 1) + self.assertIn("cannot verify flip", verdict["masked_runs"][0]["samples"][0]) + + def test_combined_status_api_error_blocks(self): + # Fail-closed: combined_status ApiError means the check history is + # unreadable — we cannot verify the flip, so block as masked. + with mock.patch.object(lpfc, "recent_commits_on_branch", return_value=["sha1"]): + with mock.patch.object( + lpfc, "combined_status", + side_effect=lpfc.ApiError("GET /statuses/sha → HTTP 500"), + ): + verdict = lpfc.verify_flip(FLIP_FIXTURE, "main", 5) + self.assertEqual(verdict["checked_commits"], 0) + self.assertEqual(verdict["fail_runs"], []) + # One masked_run from the ApiError, one from zero checked_commits. + self.assertEqual(len(verdict["masked_runs"]), 2) + self.assertIn("API error", verdict["masked_runs"][0]["samples"][0]) # -------------------------------------------------------------------------- -- 2.52.0