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
9 changes: 7 additions & 2 deletions .github/workflows/qwen-autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,13 @@ env:
# hostile commenter cannot steer the agent.
TRUSTED_ASSOC: '["OWNER", "MEMBER", "COLLABORATOR"]'
# Hard cap on automated review-address rounds per PR. After this the bot stops
# and leaves the PR for a human.
MAX_ROUNDS: '5'
# and leaves the PR for a human. Raised from 5: across the last 40 bot PRs
# only 3 ever reached the cap and all 3 merged AT it (one having spent two of
# its five rounds on the verify-gate ENOENT that #7330 fixed), so the ceiling
# was near enough to bind on a bad day without any headroom for one. The cap
# exists to stop an unproductive LOOP, not to ration ordinary iteration —
# a genuinely stuck PR still stops, just later.
MAX_ROUNDS: '10'
# An auth/access model error (401/402/403, "no access"/"does not exist")
# never self-heals - only a maintainer can fix the key - and every retry
# costs an agent run AND a PR comment. Cap those attempts far below
Expand Down
16 changes: 15 additions & 1 deletion scripts/tests/qwen-autofix-workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,21 @@ describe('qwen-autofix workflow', () => {
expect(workflow).toContain(
'AUTOFIX_BOT: "${{ vars.AUTOFIX_BOT_LOGIN || \'qwen-code-dev-bot\' }}"',
);
expect(workflow).toContain("MAX_ROUNDS: '5'");
// The round budgets are tuning knobs; what must hold is their ORDERING.
// Asserting the literal numbers only detected edits — it would not catch
// a cap that stopped binding, which is the failure that matters.
const num = (key) =>
Number(workflow.match(new RegExp(`\\b${key}: '(\\d+)'`))?.[1]);
const strictRounds = num('MAX_ROUNDS');
const takeoverRounds = num('TAKEOVER_MAX_ROUNDS');
const authRounds = num('API_AUTH_MAX_ROUNDS');
// A strict cap at or above the takeover cap makes the takeover label a
// no-op; an auth sub-cap at or above the strict cap stops short-circuiting
// the retries only a maintainer can fix, which is what it exists for.
expect(strictRounds).toBeGreaterThan(0);
expect(strictRounds).toBeLessThan(takeoverRounds);
expect(authRounds).toBeGreaterThan(0);
expect(authRounds).toBeLessThan(strictRounds);
expect(workflow).toContain("MAX_OPEN_AUTOFIX_PRS: '5'");
expect(reviewScanJob).toContain('isCrossRepository');
expect(reviewScanJob).toContain('not an open main-targeting PR');
Expand Down
Loading