From 47e63cacca6d069568ed86edb8617786924d21dc Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sun, 14 Jun 2026 02:12:40 +0000 Subject: [PATCH 1/4] fix(ci): status-reaper compensates non-required governance PR shadows (#2770 #2767) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gitea posts redundant non-required governance contexts alongside the required pull_request_target variants: - sop-checklist / all-items-acked (pull_request) - qa-review / approved (pull_request_review) - security-review / approved (pull_request_review) - retired sop-tier-check / tier-check (pull_request_review) When the trusted (pull_request_target) context succeeded, these shadows kept the aggregate commit status red even though the merge gate was already satisfied. Teach status-reaper to detect governance shadows by workflow name (a workflow with no push: trigger) and compensate the failed shadow to success when the matching pull_request_target context is green. CI workflows that have a push trigger are excluded so their (pull_request) failures remain real signals. Adds regression tests covering: - sop-checklist (pull_request) + target success → compensated - qa-review (pull_request_review) + target success → compensated - target missing/failed → preserved - CI workflow with push trigger + target success → preserved Refs #2770, #2767. Co-Authored-By: Claude --- .gitea/scripts/status-reaper.py | 82 ++++++++++- .../scripts/tests/test_status_reaper_api.py | 128 ++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) diff --git a/.gitea/scripts/status-reaper.py b/.gitea/scripts/status-reaper.py index 74f9842b0..e65bb3a27 100644 --- a/.gitea/scripts/status-reaper.py +++ b/.gitea/scripts/status-reaper.py @@ -143,6 +143,11 @@ PR_SHADOW_COMPENSATION_DESCRIPTION = ( "shadowed by successful push status on same SHA; see " ".gitea/scripts/status-reaper.py)" ) +GOVERNANCE_SHADOW_COMPENSATION_DESCRIPTION = ( + "Compensated by status-reaper (non-required pull_request/pull_request_review " + "governance shadow overridden by successful pull_request_target status; see " + ".gitea/scripts/status-reaper.py)" +) CANCELLED_PUSH_COMPENSATION_DESCRIPTION = ( "Compensated by status-reaper (push run was cancelled/superseded; " "Gitea 1.22.6 reports cancelled runs as failure statuses)" @@ -153,6 +158,8 @@ CANCELLED_DESCRIPTION = "Has been cancelled" # default-branch workflow runs. PUSH_SUFFIX = " (push)" PULL_REQUEST_SUFFIX = " (pull_request)" +PULL_REQUEST_TARGET_SUFFIX = " (pull_request_target)" +PULL_REQUEST_REVIEW_SUFFIX = " (pull_request_review)" # -------------------------------------------------------------------------- # Conductor snapshot (operator-config#158) @@ -488,6 +495,41 @@ def push_equivalent_context(context: str) -> str | None: return f"{workflow_name} / {job_name}{PUSH_SUFFIX}" +def target_equivalent_context(context: str, source_suffix: str) -> str | None: + """Return the matching `(pull_request_target)` context for a suffixed context. + + Handles `(pull_request)` and `(pull_request_review)` governance shadows. + """ + parsed = parse_suffixed_context(context, source_suffix) + if parsed is None: + return None + workflow_name, job_name = parsed + return f"{workflow_name} / {job_name}{PULL_REQUEST_TARGET_SUFFIX}" + + +def is_non_push_governance_context( + context: str, workflow_trigger_map: dict[str, bool] +) -> bool: + """True if `context` belongs to a workflow that has no push: trigger. + + Governance workflows (sop-checklist, qa-review, security-review) emit + non-required `(pull_request)` / `(pull_request_review)` shadows alongside + the required `(pull_request_target)` context. Workflows that DO have a + push trigger are CI checks whose `(pull_request)` status is an independent + gate signal and must NOT be compensated here. + """ + for suffix in (PULL_REQUEST_SUFFIX, PULL_REQUEST_REVIEW_SUFFIX): + parsed = parse_suffixed_context(context, suffix) + if parsed is not None: + workflow_name, _job_name = parsed + has_push = workflow_trigger_map.get(workflow_name) + # Only classify as a compensatable governance shadow when we know + # the workflow and it is NOT push-triggered. Unknown workflows are + # preserved (fail-closed: don't mask a signal we can't classify). + return has_push is False + return False + + # -------------------------------------------------------------------------- # Compensating POST # -------------------------------------------------------------------------- @@ -562,6 +604,8 @@ def reap( "compensated_pr_shadowed_by_push_success": 0, "compensated_cancelled_push": 0, "preserved_pr_without_push_success": 0, + "compensated_governance_shadow": 0, + "preserved_governance_without_target_success": 0, "compensated_contexts": [], } @@ -594,6 +638,36 @@ def reap( counters["preserved_non_failure"] += 1 continue + # Governance shadow compensation (#2770 / #2767). + # Non-required `(pull_request)` and `(pull_request_review)` contexts + # emitted by governance workflows (sop-checklist, qa-review, + # security-review, retired sop-tier-check) are informational shadows + # of the required `(pull_request_target)` context. When the trusted + # target context succeeded, the shadow must not keep the aggregate + # commit status red. CI workflows that also have a `push:` trigger are + # excluded — their `(pull_request)` status is an independent gate. + if is_non_push_governance_context(context, workflow_trigger_map): + source_suffix = ( + PULL_REQUEST_SUFFIX + if context.endswith(PULL_REQUEST_SUFFIX) + else PULL_REQUEST_REVIEW_SUFFIX + ) + target_equivalent = target_equivalent_context(context, source_suffix) + if target_equivalent is not None and target_equivalent in successful_contexts: + post_compensating_status( + sha, + context, + s.get("target_url"), + description=GOVERNANCE_SHADOW_COMPENSATION_DESCRIPTION, + dry_run=dry_run, + ) + counters["compensated"] += 1 + counters["compensated_governance_shadow"] += 1 + counters["compensated_contexts"].append(context) + else: + counters["preserved_governance_without_target_success"] += 1 + continue + # Default-branch `pull_request` contexts can be stale shadows of # the exact same workflow/job already proven by the successful # `push` context on the same SHA. Compensate only that narrow @@ -618,7 +692,7 @@ def reap( # Only `(push)`-suffix contexts hit the hardcoded-suffix bug. # Other failed contexts are preserved unless handled by the - # pull-request-shadow rule above. + # governance-shadow or pull-request-shadow rules above. if not context.endswith(PUSH_SUFFIX): counters["preserved_non_push_suffix"] += 1 continue @@ -766,6 +840,8 @@ def reap_branch( "compensated_pr_shadowed_by_push_success": 0, "compensated_cancelled_push": 0, "preserved_pr_without_push_success": 0, + "compensated_governance_shadow": 0, + "preserved_governance_without_target_success": 0, "compensated_per_sha": {}, "sha_api_errors": 0, "skipped": True, @@ -783,6 +859,8 @@ def reap_branch( "compensated_pr_shadowed_by_push_success": 0, "compensated_cancelled_push": 0, "preserved_pr_without_push_success": 0, + "compensated_governance_shadow": 0, + "preserved_governance_without_target_success": 0, "compensated_per_sha": {}, "sha_api_errors": 0, } @@ -825,6 +903,8 @@ def reap_branch( "compensated_pr_shadowed_by_push_success", "compensated_cancelled_push", "preserved_pr_without_push_success", + "compensated_governance_shadow", + "preserved_governance_without_target_success", ): aggregate[key] += per_sha[key] diff --git a/.gitea/scripts/tests/test_status_reaper_api.py b/.gitea/scripts/tests/test_status_reaper_api.py index e2d02aeb4..3e655c0ee 100644 --- a/.gitea/scripts/tests/test_status_reaper_api.py +++ b/.gitea/scripts/tests/test_status_reaper_api.py @@ -250,3 +250,131 @@ def test_get_combined_status_self_fetches_when_sha_not_in_snapshot(monkeypatch): assert combined["state"] == "success" finally: os.unlink(path) + + +def test_reap_compensates_governance_shadow_when_target_passed(monkeypatch): + mod = load_reaper() + posted = [] + + def fake_post(sha, context, target_url, *, description="", dry_run=False): + posted.append((sha, context, target_url, description, dry_run)) + + monkeypatch.setattr(mod, "post_compensating_status", fake_post) + + # sop-checklist has no push trigger, so its failed (pull_request) shadow is + # noise when the required (pull_request_target) context is green. + counters = mod.reap( + {"sop-checklist": False, "qa-review": False, "security-review": False}, + { + "statuses": [ + { + "context": "sop-checklist / all-items-acked (pull_request)", + "status": "failure", + "target_url": "https://git.example.test/sop-pr", + }, + { + "context": "sop-checklist / all-items-acked (pull_request_target)", + "status": "success", + }, + { + "context": "qa-review / approved (pull_request_review)", + "status": "failure", + "target_url": "https://git.example.test/qa-pr-review", + }, + { + "context": "qa-review / approved (pull_request_target)", + "status": "success", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 2 + assert counters["preserved_governance_without_target_success"] == 0 + assert posted == [ + ( + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + "sop-checklist / all-items-acked (pull_request)", + "https://git.example.test/sop-pr", + mod.GOVERNANCE_SHADOW_COMPENSATION_DESCRIPTION, + False, + ), + ( + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + "qa-review / approved (pull_request_review)", + "https://git.example.test/qa-pr-review", + mod.GOVERNANCE_SHADOW_COMPENSATION_DESCRIPTION, + False, + ), + ] + + +def test_reap_preserves_governance_shadow_when_target_missing_or_failed(monkeypatch): + mod = load_reaper() + posted = [] + monkeypatch.setattr( + mod, + "post_compensating_status", + lambda sha, context, target_url, *, description="", dry_run=False: posted.append( + context + ), + ) + + counters = mod.reap( + {"sop-checklist": False}, + { + "statuses": [ + { + "context": "sop-checklist / all-items-acked (pull_request)", + "status": "failure", + }, + # target context failed → preserve the shadow as a real signal. + { + "context": "sop-checklist / all-items-acked (pull_request_target)", + "status": "failure", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 0 + assert counters["preserved_governance_without_target_success"] == 1 + assert posted == [] + + +def test_reap_preserves_ci_pull_request_failure_even_when_target_passed(monkeypatch): + mod = load_reaper() + posted = [] + monkeypatch.setattr( + mod, + "post_compensating_status", + lambda sha, context, target_url, *, description="", dry_run=False: posted.append( + context + ), + ) + + # A CI workflow that also has a push trigger is NOT a governance shadow; + # its (pull_request) failure is an independent gate signal and must be + # preserved even if a (pull_request_target) variant happens to be green. + counters = mod.reap( + {"CI": True}, + { + "statuses": [ + { + "context": "CI / Platform (Go) (pull_request)", + "status": "failure", + }, + { + "context": "CI / Platform (Go) (pull_request_target)", + "status": "success", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 0 + assert counters["preserved_pr_without_push_success"] == 1 + assert posted == [] -- 2.52.0 From 2bd911a1cb81eae5a1a31d662a91cb9e9394440d Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sun, 14 Jun 2026 02:19:41 +0000 Subject: [PATCH 2/4] fix(ci): narrow governance shadow compensation to explicit allowlist (#2770 #2767) CR2 and Researcher both flagged that the previous predicate compensated any no-push PR-triggered workflow, which could mask real failures in workflows like gate-check-v3 or reserved-path-review. - Introduce GOVERNANCE_SHADOW_ALLOWLIST containing exactly the compensatable governance workflows: sop-checklist, qa-review, security-review, and the retired sop-tier-check. - Rename is_non_push_governance_context -> is_governance_shadow_context and require the workflow name to be in the allowlist. - Add regression tests proving non-governance no-push workflows are preserved and that retired sop-tier-check shadows are still compensated. Refs PR #2814 --- .gitea/scripts/status-reaper.py | 28 +++++-- .../scripts/tests/test_status_reaper_api.py | 75 +++++++++++++++++++ 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/.gitea/scripts/status-reaper.py b/.gitea/scripts/status-reaper.py index e65bb3a27..040245581 100644 --- a/.gitea/scripts/status-reaper.py +++ b/.gitea/scripts/status-reaper.py @@ -161,6 +161,14 @@ PULL_REQUEST_SUFFIX = " (pull_request)" PULL_REQUEST_TARGET_SUFFIX = " (pull_request_target)" PULL_REQUEST_REVIEW_SUFFIX = " (pull_request_review)" +# Governance workflows whose non-required `(pull_request)` / `(pull_request_review)` +# shadows may be compensated when the trusted `(pull_request_target)` variant is +# green. This is an EXACT allowlist — every other workflow is preserved, even if +# it has no `push:` trigger, to avoid masking real failures. +GOVERNANCE_SHADOW_ALLOWLIST = frozenset( + {"sop-checklist", "qa-review", "security-review", "sop-tier-check"} +) + # -------------------------------------------------------------------------- # Conductor snapshot (operator-config#158) # -------------------------------------------------------------------------- @@ -507,21 +515,25 @@ def target_equivalent_context(context: str, source_suffix: str) -> str | None: return f"{workflow_name} / {job_name}{PULL_REQUEST_TARGET_SUFFIX}" -def is_non_push_governance_context( +def is_governance_shadow_context( context: str, workflow_trigger_map: dict[str, bool] ) -> bool: - """True if `context` belongs to a workflow that has no push: trigger. + """True if `context` is a compensatable governance shadow. - Governance workflows (sop-checklist, qa-review, security-review) emit - non-required `(pull_request)` / `(pull_request_review)` shadows alongside - the required `(pull_request_target)` context. Workflows that DO have a - push trigger are CI checks whose `(pull_request)` status is an independent - gate signal and must NOT be compensated here. + Only `(pull_request)` / `(pull_request_review)` contexts emitted by the + explicitly allowed governance workflows (`sop-checklist`, `qa-review`, + `security-review`, and the retired `sop-tier-check`) are eligible. + Workflows that DO have a `push:` trigger are excluded even if they are in + the allowlist — their PR/review status is an independent gate signal. + Unknown workflows or workflows not in the allowlist are preserved + (fail-closed: never mask a signal we can't classify). """ for suffix in (PULL_REQUEST_SUFFIX, PULL_REQUEST_REVIEW_SUFFIX): parsed = parse_suffixed_context(context, suffix) if parsed is not None: workflow_name, _job_name = parsed + if workflow_name not in GOVERNANCE_SHADOW_ALLOWLIST: + return False has_push = workflow_trigger_map.get(workflow_name) # Only classify as a compensatable governance shadow when we know # the workflow and it is NOT push-triggered. Unknown workflows are @@ -646,7 +658,7 @@ def reap( # target context succeeded, the shadow must not keep the aggregate # commit status red. CI workflows that also have a `push:` trigger are # excluded — their `(pull_request)` status is an independent gate. - if is_non_push_governance_context(context, workflow_trigger_map): + if is_governance_shadow_context(context, workflow_trigger_map): source_suffix = ( PULL_REQUEST_SUFFIX if context.endswith(PULL_REQUEST_SUFFIX) diff --git a/.gitea/scripts/tests/test_status_reaper_api.py b/.gitea/scripts/tests/test_status_reaper_api.py index 3e655c0ee..76c302c5c 100644 --- a/.gitea/scripts/tests/test_status_reaper_api.py +++ b/.gitea/scripts/tests/test_status_reaper_api.py @@ -378,3 +378,78 @@ def test_reap_preserves_ci_pull_request_failure_even_when_target_passed(monkeypa assert counters["compensated_governance_shadow"] == 0 assert counters["preserved_pr_without_push_success"] == 1 assert posted == [] + + +def test_reap_preserves_non_governance_no_push_shadow_when_target_passed(monkeypatch): + mod = load_reaper() + posted = [] + monkeypatch.setattr( + mod, + "post_compensating_status", + lambda sha, context, target_url, *, description="", dry_run=False: posted.append( + context + ), + ) + + # A no-push workflow that is NOT in the governance allowlist must be + # preserved even when its (pull_request_target) variant is green. + counters = mod.reap( + {"custom-audit": False}, + { + "statuses": [ + { + "context": "custom-audit / check (pull_request_review)", + "status": "failure", + }, + { + "context": "custom-audit / check (pull_request_target)", + "status": "success", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 0 + assert counters["preserved_non_push_suffix"] == 1 + assert posted == [] + + +def test_reap_compensates_retired_sop_tier_check_shadow_when_target_passed(monkeypatch): + mod = load_reaper() + posted = [] + + def fake_post(sha, context, target_url, *, description="", dry_run=False): + posted.append((sha, context, target_url, description, dry_run)) + + monkeypatch.setattr(mod, "post_compensating_status", fake_post) + + counters = mod.reap( + {"sop-tier-check": False}, + { + "statuses": [ + { + "context": "sop-tier-check / tier-verify (pull_request)", + "status": "failure", + "target_url": "https://git.example.test/tier-pr", + }, + { + "context": "sop-tier-check / tier-verify (pull_request_target)", + "status": "success", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 1 + assert counters["preserved_governance_without_target_success"] == 0 + assert posted == [ + ( + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + "sop-tier-check / tier-verify (pull_request)", + "https://git.example.test/tier-pr", + mod.GOVERNANCE_SHADOW_COMPENSATION_DESCRIPTION, + False, + ), + ] -- 2.52.0 From 11fcbb05862407c0e567870cd971caf606a55daf Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sun, 14 Jun 2026 02:40:55 +0000 Subject: [PATCH 3/4] =?UTF-8?q?fix(ci):=20address=20PR=20#2814=20round-2?= =?UTF-8?q?=20RCs=20=E2=80=94=20retired=20workflow=20+=20named=20non-gover?= =?UTF-8?q?nance=20preserves?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Treat retired allowlisted workflows (sop-tier-check) as compensatable even when they are absent from the workflow trigger map (the YAML was removed). - Add regression test proving sop-tier-check shadows are compensated without a trigger-map entry. - Add parametrized regression test covering the named non-governance no-push workflows flagged by CR2: gate-check-v3, reserved-path-review, lint-required-no-paths, lint-required-context-exists-in-bp, audit-force-merge, status-reaper, umbrella-reaper. Each is preserved (not compensated) when its (pull_request_target) equivalent is green. Refs #2814 #2770 #2767 --- .gitea/scripts/status-reaper.py | 14 +-- .../scripts/tests/test_status_reaper_api.py | 99 ++++++++++++++++++- 2 files changed, 106 insertions(+), 7 deletions(-) diff --git a/.gitea/scripts/status-reaper.py b/.gitea/scripts/status-reaper.py index 040245581..25dbc1531 100644 --- a/.gitea/scripts/status-reaper.py +++ b/.gitea/scripts/status-reaper.py @@ -525,8 +525,10 @@ def is_governance_shadow_context( `security-review`, and the retired `sop-tier-check`) are eligible. Workflows that DO have a `push:` trigger are excluded even if they are in the allowlist — their PR/review status is an independent gate signal. - Unknown workflows or workflows not in the allowlist are preserved - (fail-closed: never mask a signal we can't classify). + Retired workflows may be absent from the trigger map (the workflow file was + removed); they are treated as non-push so their historical shadow contexts + remain compensatable. Unknown workflows or workflows not in the allowlist + are preserved (fail-closed: never mask a signal we can't classify). """ for suffix in (PULL_REQUEST_SUFFIX, PULL_REQUEST_REVIEW_SUFFIX): parsed = parse_suffixed_context(context, suffix) @@ -535,10 +537,10 @@ def is_governance_shadow_context( if workflow_name not in GOVERNANCE_SHADOW_ALLOWLIST: return False has_push = workflow_trigger_map.get(workflow_name) - # Only classify as a compensatable governance shadow when we know - # the workflow and it is NOT push-triggered. Unknown workflows are - # preserved (fail-closed: don't mask a signal we can't classify). - return has_push is False + # Retired allowlist workflows may be missing from the map; treat + # absence as "known non-push". Active allowlist workflows that + # genuinely have a push trigger are preserved. + return has_push is not True return False diff --git a/.gitea/scripts/tests/test_status_reaper_api.py b/.gitea/scripts/tests/test_status_reaper_api.py index 76c302c5c..8db01f78e 100644 --- a/.gitea/scripts/tests/test_status_reaper_api.py +++ b/.gitea/scripts/tests/test_status_reaper_api.py @@ -1,6 +1,7 @@ import importlib.util import json import pathlib +import pytest import urllib.error @@ -411,7 +412,7 @@ def test_reap_preserves_non_governance_no_push_shadow_when_target_passed(monkeyp ) assert counters["compensated_governance_shadow"] == 0 - assert counters["preserved_non_push_suffix"] == 1 + assert counters["compensated"] == 0 assert posted == [] @@ -453,3 +454,99 @@ def test_reap_compensates_retired_sop_tier_check_shadow_when_target_passed(monke False, ), ] + + +def test_reap_compensates_retired_sop_tier_check_when_missing_from_trigger_map(monkeypatch): + """The retired sop-tier-check workflow file is intentionally removed, so the + real workflow trigger map will not contain it. It must still be compensatable + because it is explicitly allowlisted as a retired governance shadow.""" + mod = load_reaper() + posted = [] + + def fake_post(sha, context, target_url, *, description="", dry_run=False): + posted.append((sha, context, target_url, description, dry_run)) + + monkeypatch.setattr(mod, "post_compensating_status", fake_post) + + counters = mod.reap( + # Deliberately omit sop-tier-check from the trigger map. + {}, + { + "statuses": [ + { + "context": "sop-tier-check / tier-verify (pull_request)", + "status": "failure", + "target_url": "https://git.example.test/tier-pr", + }, + { + "context": "sop-tier-check / tier-verify (pull_request_target)", + "status": "success", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 1 + assert counters["preserved_governance_without_target_success"] == 0 + assert posted == [ + ( + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + "sop-tier-check / tier-verify (pull_request)", + "https://git.example.test/tier-pr", + mod.GOVERNANCE_SHADOW_COMPENSATION_DESCRIPTION, + False, + ), + ] + + +@pytest.mark.parametrize( + "context", + [ + "gate-check-v3 / gate (pull_request)", + "reserved-path-review / check (pull_request_review)", + "lint-required-no-paths / lint (pull_request)", + "lint-required-context-exists-in-bp / lint (pull_request_review)", + "audit-force-merge / audit (pull_request)", + "status-reaper / reap (pull_request_review)", + "umbrella-reaper / reap (pull_request)", + ], +) +def test_reap_preserves_named_non_governance_no_push_shadows(context, monkeypatch): + """Real merge-control/lint/audit workflows that are NOT in the governance + allowlist must be preserved even when they have no push trigger and their + (pull_request_target) variant is green. Auto-greening these would mask real + failures.""" + mod = load_reaper() + posted = [] + monkeypatch.setattr( + mod, + "post_compensating_status", + lambda sha, context, target_url, *, description="", dry_run=False: posted.append( + context + ), + ) + + workflow_name = context.split(" / ", 1)[0] + counters = mod.reap( + {workflow_name: False}, + { + "statuses": [ + { + "context": context, + "status": "failure", + }, + { + "context": context.replace( + " (pull_request)", " (pull_request_target)" + ).replace(" (pull_request_review)", " (pull_request_target)"), + "status": "success", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 0 + assert counters["compensated"] == 0 + assert posted == [] -- 2.52.0 From 840fad886902062bf74214d573c1635da6510bea Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sun, 14 Jun 2026 02:48:14 +0000 Subject: [PATCH 4/4] fix(ci): scope retired-workflow absent-map handling to sop-tier-check only (#2814) CR2 round-3: the previous fix treated ANY allowlisted workflow missing from workflow_trigger_map as compensatable, which would fail open if an active governance workflow were ever missed by trigger-map discovery. - Split GOVERNANCE_SHADOW_ALLOWLIST (active: sop-checklist, qa-review, security-review) from GOVERNANCE_SHADOW_RETIRED_ALLOWLIST (sop-tier-check). - Active allowlist workflows require an explicit trigger-map entry of False. - Retired sop-tier-check remains compensatable when absent from the map. - Add regression test proving missing qa-review is preserved while missing sop-tier-check is compensated. Refs #2814 #2770 #2767 --- .gitea/scripts/status-reaper.py | 40 +++++++++++-------- .../scripts/tests/test_status_reaper_api.py | 37 +++++++++++++++++ 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/.gitea/scripts/status-reaper.py b/.gitea/scripts/status-reaper.py index 25dbc1531..a7893cf3f 100644 --- a/.gitea/scripts/status-reaper.py +++ b/.gitea/scripts/status-reaper.py @@ -163,11 +163,15 @@ PULL_REQUEST_REVIEW_SUFFIX = " (pull_request_review)" # Governance workflows whose non-required `(pull_request)` / `(pull_request_review)` # shadows may be compensated when the trusted `(pull_request_target)` variant is -# green. This is an EXACT allowlist — every other workflow is preserved, even if -# it has no `push:` trigger, to avoid masking real failures. +# green. This is an EXACT active allowlist — every other workflow is preserved, +# even if it has no `push:` trigger, to avoid masking real failures. GOVERNANCE_SHADOW_ALLOWLIST = frozenset( - {"sop-checklist", "qa-review", "security-review", "sop-tier-check"} + {"sop-checklist", "qa-review", "security-review"} ) +# Retired workflows whose historical shadow contexts still appear on old commits +# and must remain compensatable even though the workflow YAML has been removed. +# They are treated as known non-push when absent from the trigger map. +GOVERNANCE_SHADOW_RETIRED_ALLOWLIST = frozenset({"sop-tier-check"}) # -------------------------------------------------------------------------- # Conductor snapshot (operator-config#158) @@ -520,27 +524,31 @@ def is_governance_shadow_context( ) -> bool: """True if `context` is a compensatable governance shadow. - Only `(pull_request)` / `(pull_request_review)` contexts emitted by the - explicitly allowed governance workflows (`sop-checklist`, `qa-review`, - `security-review`, and the retired `sop-tier-check`) are eligible. - Workflows that DO have a `push:` trigger are excluded even if they are in - the allowlist — their PR/review status is an independent gate signal. - Retired workflows may be absent from the trigger map (the workflow file was - removed); they are treated as non-push so their historical shadow contexts - remain compensatable. Unknown workflows or workflows not in the allowlist - are preserved (fail-closed: never mask a signal we can't classify). + Active governance workflows (`sop-checklist`, `qa-review`, `security-review`) + are compensatable only when their trigger map entry is explicitly `False`. + Retired workflows (`sop-tier-check`) may be absent from the trigger map + because their YAML was removed; they are treated as known non-push so their + historical shadow contexts remain compensatable. + + Workflows that DO have a `push:` trigger are excluded even if they are in an + allowlist — their PR/review status is an independent gate signal. Unknown + workflows or workflows not in any allowlist are preserved (fail-closed). """ for suffix in (PULL_REQUEST_SUFFIX, PULL_REQUEST_REVIEW_SUFFIX): parsed = parse_suffixed_context(context, suffix) if parsed is not None: workflow_name, _job_name = parsed + if workflow_name in GOVERNANCE_SHADOW_RETIRED_ALLOWLIST: + # Retired workflow: absent from the trigger map is expected. + # Only a push-triggered retired workflow is preserved. + has_push = workflow_trigger_map.get(workflow_name) + return has_push is not True if workflow_name not in GOVERNANCE_SHADOW_ALLOWLIST: return False + # Active allowlist workflow: require an explicit known-no-push entry. + # If the parser ever misses the workflow, fail-closed (preserve). has_push = workflow_trigger_map.get(workflow_name) - # Retired allowlist workflows may be missing from the map; treat - # absence as "known non-push". Active allowlist workflows that - # genuinely have a push trigger are preserved. - return has_push is not True + return has_push is False return False diff --git a/.gitea/scripts/tests/test_status_reaper_api.py b/.gitea/scripts/tests/test_status_reaper_api.py index 8db01f78e..d2b917c84 100644 --- a/.gitea/scripts/tests/test_status_reaper_api.py +++ b/.gitea/scripts/tests/test_status_reaper_api.py @@ -500,6 +500,43 @@ def test_reap_compensates_retired_sop_tier_check_when_missing_from_trigger_map(m ] +def test_reap_preserves_active_governance_shadow_when_missing_from_trigger_map(monkeypatch): + """Active governance workflows must be explicitly known-no-push in the trigger + map. If the parser/discovery misses them, the reaper must fail-closed and + preserve their shadow rather than auto-green it.""" + mod = load_reaper() + posted = [] + monkeypatch.setattr( + mod, + "post_compensating_status", + lambda sha, context, target_url, *, description="", dry_run=False: posted.append( + context + ), + ) + + counters = mod.reap( + # Deliberately omit qa-review from the trigger map. + {}, + { + "statuses": [ + { + "context": "qa-review / approved (pull_request_review)", + "status": "failure", + }, + { + "context": "qa-review / approved (pull_request_target)", + "status": "success", + }, + ], + }, + "db3b7a93e31adc0cb072a6d177d92dd73275a191", + ) + + assert counters["compensated_governance_shadow"] == 0 + assert counters["compensated"] == 0 + assert posted == [] + + @pytest.mark.parametrize( "context", [ -- 2.52.0