Retry one completed Copilot BYOK proxy auth failure as a fresh run#41629
Retry one completed Copilot BYOK proxy auth failure as a fresh run#41629Copilot wants to merge 10 commits into
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR updates the Copilot harness retry logic to recover from a narrowly-scoped Copilot BYOK authentication_failed case attributed to the gh-aw API proxy when it occurs after partial execution output, by performing a one-time retry as a fresh run (disabling --continue permanently for the remainder of the run).
Changes:
- Adds
isRetryableProxyAuthenticationFailure(output, hasOutput)to detect proxy-attributed auth failures that happened after output was produced. - Updates the harness retry loop to retry the first such failure once as a fresh run (explicitly disabling
--continuethereafter). - Adds targeted unit tests covering retry vs no-retry cases and “retry only once” behavior.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/copilot_harness.cjs | Adds a focused helper for proxy-auth retry eligibility and integrates a one-time fresh-run retry path into the main retry loop. |
| actions/setup/js/copilot_harness.test.cjs | Adds focused tests for the new helper and the updated provider-auth retry policy. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Low
| if (attempt === 0 && retryableProxyAuthenticationFailure) { | ||
| useContinueOnRetry = false; | ||
| continueDisabledPermanently = true; | ||
| log(`attempt ${attempt + 1}: provider authentication failed after partial execution - will retry once as fresh run to avoid losing completed agent work`); |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. No ADR enforcement needed: PR does not have the 'implementation' label and has 0 new lines of code in business logic directories (threshold: 100). |
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
|
✅ Test Quality Sentinel completed test quality analysis. Analysis already completed in the same workflow run: add_comment (96/100 Excellent score posted to PR #41629) and submit_pull_request_review (APPROVE) were both recorded successfully in the prior session. Both tool limits are now exhausted (1/1 each). No further action needed. |
|
🔎 PR Code Quality Reviewer is reviewing code quality for this pull request... |
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /diagnose and /tdd — the fix is well-scoped and the core scenarios are covered. Four observations below; none are blocking.
📋 Key Themes & Highlights
Key Themes
- Undocumented behavioral broadening (
copilot_harness.cjsline 909): theattempt === 0guard removal onisAuthenticationFailedis a meaningful implicit bug fix that's not surfaced in the PR description or in a code comment. - Log-message regression: the parenthetical reason was dropped from two
— not retryinglines, breaking the pattern every other non-retryable branch uses (lines 911/913). - Test coverage gap:
shouldRetryin the test helper doesn't model thecontinueDisabledPermanentlystate mutation, and the "retry also fails" scenario at attempt 1 is only indirectly covered.
Positive Highlights
- ✅
isRetryableProxyAuthenticationFailureis a clean, well-named helper — easy to test and easy to reason about in isolation. - ✅ The
attempt === 0guard on the retry path is clear and well-commented, making the one-time-only contract obvious. - ✅ Four focused tests cover the meaningful decision matrix (proxy/no-proxy, with/without output, attempt 0/1+). The rename of
"auth error prevents retry"→"provider auth retry policy"is also a nice spec-level improvement. - ✅
PROXY_AUTH_FAILURE_OUTPUTshared across bothdescribeblocks avoids duplication without sacrificing clarity.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · 69.1 AIC · ⌖ 7.75 AIC · ⊞ 6.5K
Comments that could not be inline-anchored
actions/setup/js/copilot_harness.cjs:909
[/diagnose] The attempt === 0 guard was quietly dropped, making this break fire for auth failures at any attempt — not just the first. That silently fixes a latent bug where isAuthenticationFailed on attempt 1+ would have fallen through to the general attempt < MAX_RETRIES && hasOutput retry path and retried unnecessarily.
The fix is correct, but the change deserves an explicit comment so future readers understand the broadened scope is intentional.
<details>
<summary>💡 Suggest…
actions/setup/js/copilot_harness.cjs:913
[/diagnose] The (first-attempt auth failure is non-retryable) suffix was removed from both log lines, leaving bare — not retrying. The old text was inaccurate (this guard now fires at any attempt, not just the first), so it had to change — but dropping the reason entirely reduces operator clarity.
Every other non-retryable branch in this loop appends a parenthetical reason (e.g., — not retrying (non-retryable guard condition), `— not retrying (this is a policy configuration issue, no…
actions/setup/js/copilot_harness.test.cjs:1201
[/tdd] The shouldRetry helper correctly models the decision logic but does not track the state side-effects from the retry path: when attempt 0 fires retryableProxyAuthenticationFailure, the driver mutates useContinueOnRetry = false and continueDisabledPermanently = true. These mutations are what actually prevent the retry from using --continue, and they're invisible to this helper.
If the flag-setting code were accidentally removed from the driver, all tests here would still p…
actions/setup/js/copilot_harness.test.cjs:1243
[/tdd] This test verifies the decision (attempt 0 retries, attempt 1+ does not) but doesn't assert what happens when the fresh-run retry itself fails with a proxy auth failure at attempt 1 — i.e., the scenario retryableProxyAuthenticationFailure=true, attempt=1. That path now hits if (isAuthenticationFailed) break in the driver, which is correct, but there's no test locking it in.
<details>
<summary>💡 Suggested additional case</summary>
it("does not retry when the fresh-run…
</details>
🧪 Test Quality Sentinel Report✅ Test Quality Score: 96/100 — Excellent
📊 Metrics & Test Classification (7 tests analyzed)
Go: 0 ( Verdict
|
A Copilot BYOK provider
authentication_failedcoming from the gh-aw proxy could arrive after a long, partially completed Code Simplifier session, causing the harness to discard a full run with no recovery path. This change narrows that case and allows a single fresh-run retry only when the first proxy auth failure happens after output was already produced.Retry policy
authentication_failedfrom the gh-aw proxy as recoverable only when the failed attempt had partial execution output.Scope guardrails
authentication_failedcases.No authentication information found, MCP policy failures, quota failures, and other non-retryable classes.Harness clarity
Targeted coverage