Problem
scripts/ci/pr_review_merge_scheduler.py::main() deliberately isolates PR-local mutation failures: it converts a caught RuntimeError into an action_error decision and continues inspecting the rest of the queue. That isolation is useful, but the CLI then unconditionally returns 0.
As a result, an update, merge, auto-merge, or dispatch mutation can fail, appear only in the structured summary as action_error, and still leave the scheduler job/workflow with a passing process result. The current tests explicitly assert this behavior.
Impact
A green scheduler check can be mistaken for successful mechanical governance even though a requested mutation failed. This weakens operational alerting and makes consumers parse logs or JSON to discover a material action failure.
Acceptance criteria
- Preserve PR isolation: one failed mutation must not prevent later PRs from being inspected.
- After the full bounded scan, emit the existing structured per-PR summary.
- Return a non-zero terminal result when one or more material mutation/dispatch attempts ended in
action_error.
- Keep ordinary policy states such as
wait, blocked, skip, or deferred capacity distinguishable from execution failure.
- Ensure the reusable/required workflow exposes the failure without losing the summary artifact/job summary.
- Add regression coverage for:
- one
action_error followed by an unaffected PR;
- multiple
action_error decisions;
- no-action-error success;
- structured output retained before terminal failure;
- workflow consumer propagation.
- Document whether a targeted single-PR run and an organization sweep use the same terminal policy.
Evidence
scripts/ci/pr_review_merge_scheduler.py catches RuntimeError per PR and creates Decision(..., "action_error", ...), then returns 0.
tests/test_pr_review_merge_scheduler.py::test_main_keeps_scanning_after_action_error and the update-branch 403/422 test assert that the CLI returns 0 while the summary contains action_error.
Related work
This issue is about terminal workflow truthfulness, not credential selection or queue serialization.
Problem
scripts/ci/pr_review_merge_scheduler.py::main()deliberately isolates PR-local mutation failures: it converts a caughtRuntimeErrorinto anaction_errordecision and continues inspecting the rest of the queue. That isolation is useful, but the CLI then unconditionally returns0.As a result, an update, merge, auto-merge, or dispatch mutation can fail, appear only in the structured summary as
action_error, and still leave the scheduler job/workflow with a passing process result. The current tests explicitly assert this behavior.Impact
A green scheduler check can be mistaken for successful mechanical governance even though a requested mutation failed. This weakens operational alerting and makes consumers parse logs or JSON to discover a material action failure.
Acceptance criteria
action_error.wait,blocked,skip, or deferred capacity distinguishable from execution failure.action_errorfollowed by an unaffected PR;action_errordecisions;Evidence
scripts/ci/pr_review_merge_scheduler.pycatchesRuntimeErrorper PR and createsDecision(..., "action_error", ...), then returns0.tests/test_pr_review_merge_scheduler.py::test_main_keeps_scanning_after_action_errorand the update-branch 403/422 test assert that the CLI returns0while the summary containsaction_error.Related work
This issue is about terminal workflow truthfulness, not credential selection or queue serialization.