diff --git a/.github/scripts/__tests__/keepalive-loop.test.js b/.github/scripts/__tests__/keepalive-loop.test.js index d9ad78802..7a5f5f308 100644 --- a/.github/scripts/__tests__/keepalive-loop.test.js +++ b/.github/scripts/__tests__/keepalive-loop.test.js @@ -420,7 +420,7 @@ test('evaluateKeepaliveLoop treats cancelled gate as transient wait', async () = assert.equal(result.reason, 'gate-cancelled'); }); -test('evaluateKeepaliveLoop detects rate limit cancelled gate', async () => { +test('evaluateKeepaliveLoop bypasses rate limit cancelled gate', async () => { const pr = { number: 509, head: { ref: 'feature/cancelled-rate', sha: 'sha-cancelled-rate' }, @@ -440,11 +440,12 @@ test('evaluateKeepaliveLoop detects rate limit cancelled gate', async () => { context: buildContext(pr.number), core: buildCore(), }); - assert.equal(result.action, 'defer'); - assert.equal(result.reason, 'gate-cancelled-rate-limit'); + // Rate limits are infrastructure noise - work should proceed + assert.equal(result.action, 'run'); + assert.equal(result.reason, 'bypass-rate-limit-gate'); }); -test('evaluateKeepaliveLoop detects rate limit cancelled gate from logs', async () => { +test('evaluateKeepaliveLoop bypasses rate limit cancelled gate from logs', async () => { const pr = { number: 510, head: { ref: 'feature/cancelled-rate-logs', sha: 'sha-cancelled-rate-logs' }, @@ -464,8 +465,9 @@ test('evaluateKeepaliveLoop detects rate limit cancelled gate from logs', async context: buildContext(pr.number), core: buildCore(), }); - assert.equal(result.action, 'defer'); - assert.equal(result.reason, 'gate-cancelled-rate-limit'); + // Rate limits are infrastructure noise - work should proceed + assert.equal(result.action, 'run'); + assert.equal(result.reason, 'bypass-rate-limit-gate'); }); test('evaluateKeepaliveLoop force_retry bypasses cancelled gate', async () => { @@ -490,7 +492,7 @@ test('evaluateKeepaliveLoop force_retry bypasses cancelled gate', async () => { assert.equal(result.forceRetry, true); }); -test('evaluateKeepaliveLoop force_retry bypasses rate limit deferred gate', async () => { +test('evaluateKeepaliveLoop rate limit bypass takes precedence over force_retry', async () => { const pr = { number: 512, head: { ref: 'feature/force-retry-rate', sha: 'sha-force-retry-rate' }, @@ -511,9 +513,10 @@ test('evaluateKeepaliveLoop force_retry bypasses rate limit deferred gate', asyn core: buildCore(), forceRetry: true, }); - // Even rate-limited cancellations should be bypassed with forceRetry + // Rate limit bypass is automatic infrastructure handling - takes precedence + // forceRetry is still honored for non-rate-limit cases assert.equal(result.action, 'run'); - assert.equal(result.reason, 'force-retry-cancelled'); + assert.equal(result.reason, 'bypass-rate-limit-gate'); }); test('evaluateKeepaliveLoop force_retry bypasses failed gate', async () => { diff --git a/.github/scripts/keepalive_loop.js b/.github/scripts/keepalive_loop.js index f856d290d..137ccd461 100644 --- a/.github/scripts/keepalive_loop.js +++ b/.github/scripts/keepalive_loop.js @@ -1129,8 +1129,13 @@ async function evaluateKeepaliveLoop({ github, context, core, payload: overrideP runId: gateRun.runId, core, }); - // forceRetry bypasses defer/wait for cancelled gates - if (forceRetry && tasksRemaining) { + // Rate limits are infrastructure noise, not code quality issues + // Proceed with work if Gate only failed due to rate limits + if (gateRateLimit && tasksRemaining) { + action = 'run'; + reason = 'bypass-rate-limit-gate'; + if (core) core.info('Gate cancelled due to rate limits only - proceeding with work'); + } else if (forceRetry && tasksRemaining) { action = 'run'; reason = 'force-retry-cancelled'; if (core) core.info(`Force retry enabled: bypassing cancelled gate (rate_limit=${gateRateLimit})`); @@ -1139,7 +1144,7 @@ async function evaluateKeepaliveLoop({ github, context, core, payload: overrideP reason = gateRateLimit ? 'gate-cancelled-rate-limit' : 'gate-cancelled'; } } else { - // Gate failed - check if we should route to fix mode or wait + // Gate failed - check if failure is rate-limit related vs code quality const gateFailure = await classifyGateFailure({ github, context, pr, core }); if (gateFailure.shouldFixMode && gateNormalized === 'failure') { action = 'fix'; diff --git a/.github/workflows/reusable-10-ci-python.yml b/.github/workflows/reusable-10-ci-python.yml index 739b7ceaa..c0e2df790 100644 --- a/.github/workflows/reusable-10-ci-python.yml +++ b/.github/workflows/reusable-10-ci-python.yml @@ -489,57 +489,41 @@ jobs: echo "Warning: autofix-versions.env not found, installing latest tool versions" >&2 fi - if [ "$has_lock_file" = "false" ]; then - if [ "$format_enabled" = "true" ]; then - add_tool "$black_spec" "black" - add_tool "$docformatter_spec" "docformatter" - add_tool "$isort_spec" "isort" + # Always install dev tools - lock files only contain runtime deps, not dev tools + if [ "$format_enabled" = "true" ]; then + add_tool "$black_spec" "black" + add_tool "$docformatter_spec" "docformatter" + add_tool "$isort_spec" "isort" else - skip_tool "black (format_check disabled)" - skip_tool "docformatter (format_check disabled)" - skip_tool "isort (format_check disabled)" - fi + skip_tool "black (format_check disabled)" + skip_tool "docformatter (format_check disabled)" + skip_tool "isort (format_check disabled)" + fi - if [ "$lint_enabled" = "true" ]; then - add_tool "$ruff_spec" "ruff" - else - skip_tool "ruff (lint disabled)" - fi + if [ "$lint_enabled" = "true" ]; then + add_tool "$ruff_spec" "ruff" + else + skip_tool "ruff (lint disabled)" + fi - if [ "$mypy_enabled" = "true" ]; then - add_tool "$mypy_spec" "mypy" - else - skip_tool "mypy (typecheck disabled)" - fi + if [ "$mypy_enabled" = "true" ]; then + add_tool "$mypy_spec" "mypy" + else + skip_tool "mypy (typecheck disabled)" + fi - add_tool "$pytest_spec" "pytest" - add_tool "$pytest_xdist_spec" "pytest-xdist" - for spec in "${base_test_specs[@]}"; do - add_tool "$spec" "$spec" - done + add_tool "$pytest_spec" "pytest" + add_tool "$pytest_xdist_spec" "pytest-xdist" + for spec in "${base_test_specs[@]}"; do + add_tool "$spec" "$spec" + done - if [ "$coverage_enabled" = "true" ]; then - add_tool "$pytest_cov_spec" "pytest-cov" - add_tool "$coverage_spec" "coverage" - else - skip_tool "pytest-cov (coverage disabled)" - skip_tool "coverage (coverage disabled)" - fi + if [ "$coverage_enabled" = "true" ]; then + add_tool "$pytest_cov_spec" "pytest-cov" + add_tool "$coverage_spec" "coverage" else - # When lock file exists, mark tools as coming from lock file for reporting - if [ "$format_enabled" = "true" ]; then - tools_installed+=("black (from lock)" "docformatter (from lock)" "isort (from lock)") - fi - if [ "$lint_enabled" = "true" ]; then - tools_installed+=("ruff (from lock)") - fi - if [ "$mypy_enabled" = "true" ]; then - tools_installed+=("mypy (from lock)") - fi - tools_installed+=("pytest (from lock)" "pytest-xdist (from lock)") - if [ "$coverage_enabled" = "true" ]; then - tools_installed+=("pytest-cov (from lock)" "coverage (from lock)") - fi + skip_tool "pytest-cov (coverage disabled)" + skip_tool "coverage (coverage disabled)" fi if [ ${#specs[@]} -eq 0 ]; then @@ -789,57 +773,41 @@ jobs: echo "Warning: autofix-versions.env not found, installing latest tool versions" >&2 fi - if [ "$has_lock_file" = "false" ]; then - if [ "$format_enabled" = "true" ]; then - add_tool "$black_spec" "black" - add_tool "$docformatter_spec" "docformatter" - add_tool "$isort_spec" "isort" + # Always install dev tools - lock files only contain runtime deps, not dev tools + if [ "$format_enabled" = "true" ]; then + add_tool "$black_spec" "black" + add_tool "$docformatter_spec" "docformatter" + add_tool "$isort_spec" "isort" else - skip_tool "black (format_check disabled)" - skip_tool "docformatter (format_check disabled)" - skip_tool "isort (format_check disabled)" - fi + skip_tool "black (format_check disabled)" + skip_tool "docformatter (format_check disabled)" + skip_tool "isort (format_check disabled)" + fi - if [ "$lint_enabled" = "true" ]; then - add_tool "$ruff_spec" "ruff" - else - skip_tool "ruff (lint disabled)" - fi + if [ "$lint_enabled" = "true" ]; then + add_tool "$ruff_spec" "ruff" + else + skip_tool "ruff (lint disabled)" + fi - if [ "$mypy_enabled" = "true" ]; then - add_tool "$mypy_spec" "mypy" - else - skip_tool "mypy (typecheck disabled)" - fi + if [ "$mypy_enabled" = "true" ]; then + add_tool "$mypy_spec" "mypy" + else + skip_tool "mypy (typecheck disabled)" + fi - add_tool "$pytest_spec" "pytest" - add_tool "$pytest_xdist_spec" "pytest-xdist" - for spec in "${base_test_specs[@]}"; do - add_tool "$spec" "$spec" - done + add_tool "$pytest_spec" "pytest" + add_tool "$pytest_xdist_spec" "pytest-xdist" + for spec in "${base_test_specs[@]}"; do + add_tool "$spec" "$spec" + done - if [ "$coverage_enabled" = "true" ]; then - add_tool "$pytest_cov_spec" "pytest-cov" - add_tool "$coverage_spec" "coverage" - else - skip_tool "pytest-cov (coverage disabled)" - skip_tool "coverage (coverage disabled)" - fi + if [ "$coverage_enabled" = "true" ]; then + add_tool "$pytest_cov_spec" "pytest-cov" + add_tool "$coverage_spec" "coverage" else - # When lock file exists, mark tools as coming from lock file for reporting - if [ "$format_enabled" = "true" ]; then - tools_installed+=("black (from lock)" "docformatter (from lock)" "isort (from lock)") - fi - if [ "$lint_enabled" = "true" ]; then - tools_installed+=("ruff (from lock)") - fi - if [ "$mypy_enabled" = "true" ]; then - tools_installed+=("mypy (from lock)") - fi - tools_installed+=("pytest (from lock)" "pytest-xdist (from lock)") - if [ "$coverage_enabled" = "true" ]; then - tools_installed+=("pytest-cov (from lock)" "coverage (from lock)") - fi + skip_tool "pytest-cov (coverage disabled)" + skip_tool "coverage (coverage disabled)" fi if [ ${#specs[@]} -eq 0 ]; then @@ -1098,57 +1066,41 @@ jobs: echo "Warning: autofix-versions.env not found, installing latest tool versions" >&2 fi - if [ "$has_lock_file" = "false" ]; then - if [ "$format_enabled" = "true" ]; then - add_tool "$black_spec" "black" - add_tool "$docformatter_spec" "docformatter" - add_tool "$isort_spec" "isort" + # Always install dev tools - lock files only contain runtime deps, not dev tools + if [ "$format_enabled" = "true" ]; then + add_tool "$black_spec" "black" + add_tool "$docformatter_spec" "docformatter" + add_tool "$isort_spec" "isort" else - skip_tool "black (format_check disabled)" - skip_tool "docformatter (format_check disabled)" - skip_tool "isort (format_check disabled)" - fi + skip_tool "black (format_check disabled)" + skip_tool "docformatter (format_check disabled)" + skip_tool "isort (format_check disabled)" + fi - if [ "$lint_enabled" = "true" ]; then - add_tool "$ruff_spec" "ruff" - else - skip_tool "ruff (lint disabled)" - fi + if [ "$lint_enabled" = "true" ]; then + add_tool "$ruff_spec" "ruff" + else + skip_tool "ruff (lint disabled)" + fi - if [ "$mypy_enabled" = "true" ]; then - add_tool "$mypy_spec" "mypy" - else - skip_tool "mypy (typecheck disabled)" - fi + if [ "$mypy_enabled" = "true" ]; then + add_tool "$mypy_spec" "mypy" + else + skip_tool "mypy (typecheck disabled)" + fi - add_tool "$pytest_spec" "pytest" - add_tool "$pytest_xdist_spec" "pytest-xdist" - for spec in "${base_test_specs[@]}"; do - add_tool "$spec" "$spec" - done + add_tool "$pytest_spec" "pytest" + add_tool "$pytest_xdist_spec" "pytest-xdist" + for spec in "${base_test_specs[@]}"; do + add_tool "$spec" "$spec" + done - if [ "$coverage_enabled" = "true" ]; then - add_tool "$pytest_cov_spec" "pytest-cov" - add_tool "$coverage_spec" "coverage" - else - skip_tool "pytest-cov (coverage disabled)" - skip_tool "coverage (coverage disabled)" - fi + if [ "$coverage_enabled" = "true" ]; then + add_tool "$pytest_cov_spec" "pytest-cov" + add_tool "$coverage_spec" "coverage" else - # When lock file exists, mark tools as coming from lock file for reporting - if [ "$format_enabled" = "true" ]; then - tools_installed+=("black (from lock)" "docformatter (from lock)" "isort (from lock)") - fi - if [ "$lint_enabled" = "true" ]; then - tools_installed+=("ruff (from lock)") - fi - if [ "$mypy_enabled" = "true" ]; then - tools_installed+=("mypy (from lock)") - fi - tools_installed+=("pytest (from lock)" "pytest-xdist (from lock)") - if [ "$coverage_enabled" = "true" ]; then - tools_installed+=("pytest-cov (from lock)" "coverage (from lock)") - fi + skip_tool "pytest-cov (coverage disabled)" + skip_tool "coverage (coverage disabled)" fi if [ ${#specs[@]} -eq 0 ]; then @@ -1450,57 +1402,41 @@ jobs: echo "Warning: autofix-versions.env not found, installing latest tool versions" >&2 fi - if [ "$has_lock_file" = "false" ]; then - if [ "$format_enabled" = "true" ]; then - add_tool "$black_spec" "black" - add_tool "$docformatter_spec" "docformatter" - add_tool "$isort_spec" "isort" + # Always install dev tools - lock files only contain runtime deps, not dev tools + if [ "$format_enabled" = "true" ]; then + add_tool "$black_spec" "black" + add_tool "$docformatter_spec" "docformatter" + add_tool "$isort_spec" "isort" else - skip_tool "black (format_check disabled)" - skip_tool "docformatter (format_check disabled)" - skip_tool "isort (format_check disabled)" - fi + skip_tool "black (format_check disabled)" + skip_tool "docformatter (format_check disabled)" + skip_tool "isort (format_check disabled)" + fi - if [ "$lint_enabled" = "true" ]; then - add_tool "$ruff_spec" "ruff" - else - skip_tool "ruff (lint disabled)" - fi + if [ "$lint_enabled" = "true" ]; then + add_tool "$ruff_spec" "ruff" + else + skip_tool "ruff (lint disabled)" + fi - if [ "$mypy_enabled" = "true" ]; then - add_tool "$mypy_spec" "mypy" - else - skip_tool "mypy (typecheck disabled)" - fi + if [ "$mypy_enabled" = "true" ]; then + add_tool "$mypy_spec" "mypy" + else + skip_tool "mypy (typecheck disabled)" + fi - add_tool "$pytest_spec" "pytest" - add_tool "$pytest_xdist_spec" "pytest-xdist" - for spec in "${base_test_specs[@]}"; do - add_tool "$spec" "$spec" - done + add_tool "$pytest_spec" "pytest" + add_tool "$pytest_xdist_spec" "pytest-xdist" + for spec in "${base_test_specs[@]}"; do + add_tool "$spec" "$spec" + done - if [ "$coverage_enabled" = "true" ]; then - add_tool "$pytest_cov_spec" "pytest-cov" - add_tool "$coverage_spec" "coverage" - else - skip_tool "pytest-cov (coverage disabled)" - skip_tool "coverage (coverage disabled)" - fi + if [ "$coverage_enabled" = "true" ]; then + add_tool "$pytest_cov_spec" "pytest-cov" + add_tool "$coverage_spec" "coverage" else - # When lock file exists, mark tools as coming from lock file for reporting - if [ "$format_enabled" = "true" ]; then - tools_installed+=("black (from lock)" "docformatter (from lock)" "isort (from lock)") - fi - if [ "$lint_enabled" = "true" ]; then - tools_installed+=("ruff (from lock)") - fi - if [ "$mypy_enabled" = "true" ]; then - tools_installed+=("mypy (from lock)") - fi - tools_installed+=("pytest (from lock)" "pytest-xdist (from lock)") - if [ "$coverage_enabled" = "true" ]; then - tools_installed+=("pytest-cov (from lock)" "coverage (from lock)") - fi + skip_tool "pytest-cov (coverage disabled)" + skip_tool "coverage (coverage disabled)" fi if [ ${#specs[@]} -eq 0 ]; then diff --git a/tests/workflows/test_keepalive_loop_rate_limit.py b/tests/workflows/test_keepalive_loop_rate_limit.py index 6ea5f48e0..d8dd3f7ab 100644 --- a/tests/workflows/test_keepalive_loop_rate_limit.py +++ b/tests/workflows/test_keepalive_loop_rate_limit.py @@ -30,7 +30,8 @@ def _run_scenario(name: str) -> dict: pytest.fail(f"Invalid harness output: {exc}: {result.stdout}") -def test_keepalive_loop_defers_on_rate_limit_cancellation() -> None: +def test_keepalive_loop_bypasses_rate_limit_cancellation() -> None: + """Rate limits are infrastructure noise, work should proceed.""" result = _run_scenario("cancelled_rate_limit") - assert result["action"] == "defer" - assert result["reason"] == "gate-cancelled-rate-limit" + assert result["action"] == "run" + assert result["reason"] == "bypass-rate-limit-gate" diff --git a/verifier-diff-summary.md b/verifier-diff-summary.md new file mode 100644 index 000000000..24621a9d3 --- /dev/null +++ b/verifier-diff-summary.md @@ -0,0 +1,3 @@ +## PR Diff Summary + +_Diff unavailable or empty._