Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/contribution-check.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .github/workflows/contribution-check.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ sandbox:
sudo: false
tools:
cli-proxy: true
bash: ["cat", "ls", "find", "grep", "head", "tail", "wc"]
bash: ["cat", "ls", "find", "grep", "head", "tail", "wc", "git", "jq *"]
github:
mode: gh-proxy
toolsets: [pull_requests, repos, issues]
Expand Down
3 changes: 1 addition & 2 deletions actions/setup/js/copilot_harness.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1287,10 +1287,9 @@ async function main() {
log(`attempt ${attempt + 1}: AI credits marker found in CLI output without trusted firewall audit confirmation — preserving normal failure handling`);
}
const shouldTreatAICreditsExceededAsSuccess = trustedAICreditsExceeded && !isAuthenticationFailed;
if (shouldTreatAICreditsExceededAsSuccess || nonRetryableGuard.awfAPIProxyBlockingRequests || isInvocationCapExceeded) {
if (shouldTreatAICreditsExceededAsSuccess || isInvocationCapExceeded) {
const reasons = [];
if (shouldTreatAICreditsExceededAsSuccess) reasons.push("AI credits budget exceeded");
if (nonRetryableGuard.awfAPIProxyBlockingRequests) reasons.push("AWF API proxy is blocking requests");
if (isInvocationCapExceeded) {
reasons.push("LLM invocation cap saturated — the pooled per-run budget is fully exhausted; retries cannot make progress");
}
Expand Down
6 changes: 6 additions & 0 deletions actions/setup/js/copilot_harness.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,12 @@ describe("copilot_harness.cjs", () => {
expect(shouldRetry(result, 0)).toBe(false);
});

it("retries AWF API proxy blocks instead of treating them as a guard condition", () => {
const result = { exitCode: 1, hasOutput: true, output: "awf api proxy is blocking requests for this run" };
expect(detectNonRetryableHarnessGuard(result.output).awfAPIProxyBlockingRequests).toBe(true);
expect(shouldRetry(result, 0)).toBe(true);
});

it("does not retry the observed CAPIError 429 quota exceeded error even when session produced output", () => {
const result = {
exitCode: 1,
Expand Down
28 changes: 28 additions & 0 deletions pkg/cli/contribution_check_workflow_contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,31 @@ func TestContributionCheckWorkflowSafeOutputContract(t *testing.T) {
assert.Contains(t, text, "\"issue_number\":35304", "Workflow should include a concrete add_comment issue_number example")
assert.Contains(t, text, "model: claude-haiku-4.5", "Workflow should require small model for contribution-checker subagent calls")
}

func TestContributionCheckWorkflowAllowsRequiredShellCommands(t *testing.T) {
repoRoot, err := gitutil.FindGitRoot()
if err != nil {
t.Skipf("Skipping test: not in a git repository: %v", err)
}

workflowPath := filepath.Join(repoRoot, ".github", "workflows", "contribution-check.md")
content, err := os.ReadFile(workflowPath)
require.NoError(t, err, "Should read contribution-check workflow")

text := string(content)
assert.Contains(t, text, `"git"`, "Workflow must allow git fetch/diff commands used by contribution-checker subagents")
assert.Contains(t, text, `"jq *"`, "Workflow must allow jq payload construction for safeoutputs create_issue")

lockPath := filepath.Join(repoRoot, ".github", "workflows", "contribution-check.lock.yml")
lockContent, err := os.ReadFile(lockPath)
require.NoError(t, err, "Should read compiled contribution-check workflow")

lockText := string(lockContent)
for _, token := range []string{
"--allow-tool '\\''shell(git:*)'\\''",
"--allow-tool '\\''shell(jq)'\\''",
"--allow-tool '\\''shell(safeoutputs:*)'\\''",
} {
assert.Containsf(t, lockText, token, "Compiled workflow must contain %s", token)
}
}