Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
93f1c1f
fix(autofix): charge regressions to the brake and gate test weakening
Aug 26, 2026
f736f01
Merge remote-tracking branch 'origin/main' into autofix-regression-an…
Aug 27, 2026
115832a
fix(autofix): attribute test weakening to round commits, close marker…
Aug 27, 2026
0f64789
fix(autofix): close weakening-gate merge/typechange escapes, own-lane…
Aug 27, 2026
7417b92
Merge remote-tracking branch 'origin/main' into autofix-regression-an…
Aug 27, 2026
a5b39f3
fix(autofix): close weakening-gate comment, attribute, and name-frami…
Aug 27, 2026
79ced42
fix(autofix): close weakening-gate masking escapes and delete/restore…
Aug 28, 2026
4dd2b27
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Aug 28, 2026
92d7db8
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Aug 28, 2026
d937968
fix(autofix): close weakening-gate lexer, marker-shape, and verdict e…
Aug 28, 2026
2c295b1
fix(autofix): close weakening-gate member-assertion, marker-spelling,…
Aug 29, 2026
876d25a
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Aug 29, 2026
263c8fe
fix(autofix): close weakening-gate merge coverage, freight phantom, a…
Aug 29, 2026
71f464c
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Aug 29, 2026
af00ea1
fix(autofix): close weakening-gate cross-commit, merge-discard, and s…
Aug 30, 2026
59d2bde
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Aug 30, 2026
cd3c89d
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Aug 31, 2026
25700bf
fix(autofix): close weakening-gate matcher-credit, each-skip, and mer…
Aug 31, 2026
a05f197
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 1, 2026
788bfcb
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 1, 2026
cc7fb69
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 1, 2026
5c9fccc
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 1, 2026
38a5114
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 1, 2026
607bbe3
fix(autofix): close weakening-gate tail-drop, skip-netting, fast-forw…
Sep 2, 2026
5f938d8
fix(autofix): stop the weakening gate charging honest test edits (#10…
Sep 2, 2026
d0bde3d
fix(autofix): measure test weakening with the parser, not a text cens…
Sep 3, 2026
b2600f3
Merge remote-tracking branch 'origin/main' into HEAD
Sep 3, 2026
9d5d1dc
chore: record the merged qwen-autofix.yml size
Sep 3, 2026
1894b2c
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 3, 2026
9021f3b
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 4, 2026
e20bddb
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 4, 2026
eab96e7
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 4, 2026
87dd954
fix(autofix): merge the base-refresh hold into the regression brake
Sep 6, 2026
9465cd7
fix(autofix): stage the surface counter with the pre-merge absence gu…
Sep 6, 2026
0916dd4
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 6, 2026
d94ba0e
fix(autofix): close the weakening gate's fail-open paths and make gre…
Sep 6, 2026
1c0a9a4
test(autofix): execute the paths the weakening gate's own guards protect
Sep 6, 2026
2237313
fix(autofix): follow git's trivial-merge rule when merge-file refuses
Sep 6, 2026
0a49945
fix(autofix): bound main's contribution by what the merge actually took
Sep 7, 2026
01f8ade
fix(autofix): clamp main's credit by what the merge actually landed
Sep 7, 2026
ddf1899
fix(autofix): clamp only main's removals, never its additions
Sep 7, 2026
3573a11
fix(autofix): measure main's contribution where main made it
Sep 7, 2026
15e9e1e
fix(autofix): decide the baseline by what main LANDED, not by what it…
Sep 7, 2026
034e3aa
Merge remote-tracking branch 'origin/main' into HEAD
Sep 7, 2026
8412b62
fix(autofix): chain main's events, and let the merge decide what it a…
Sep 7, 2026
3f2a047
fix(autofix): drop the event whenever main holds no side and the file…
Sep 7, 2026
636235d
fix(autofix): read movement from the bytes where the surface is unmea…
Sep 7, 2026
dd32d1b
fix(autofix): decide the byte fallback by what was measured, not by t…
Sep 7, 2026
8585bf5
fix(autofix): let a skips-only file reach the bytes, and pin every field
Sep 7, 2026
ee6419f
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 7, 2026
3ba5a42
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 8, 2026
c0aa595
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 8, 2026
933fc64
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 8, 2026
b94032b
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 8, 2026
d089bd8
Merge branch 'main' into autofix-regression-and-test-weakening-gates
Sep 9, 2026
a211bc0
fix(autofix): close the escape hatches the review found in the weaken…
Sep 9, 2026
01c9111
fix(autofix): arm-aware guard conditions, lane-list dedup, branch-sid…
Sep 10, 2026
1aa2a02
fix(autofix): Playwright-aware kinds, placeholder-safe folds, fallbac…
Sep 10, 2026
48320a1
Merge remote-tracking branch 'origin/main' into pr-10188
Sep 10, 2026
5d5bf2d
Merge remote-tracking branch 'origin/main' into pr-10188
Sep 10, 2026
0c319a3
Merge remote-tracking branch 'origin/main' into pr-10188
Sep 10, 2026
3ecdc29
fix(autofix): measure a merge's landed delta by which side the resolu…
Sep 10, 2026
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
28 changes: 28 additions & 0 deletions .github/scripts/autofix-push-and-report.sh
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,10 @@ if [[ "${OUTCOME}" == "fixed" ]]; then
# the per-PR tracking issue (script content from expression
# context; append-only comment design — see the script).
run_deferred_upsert
# The sha the push loop above actually left on the branch — the merge
# retry can advance it past the verified head, and the regression marker
# must name what the PR now carries.
PUSHED_HEAD="$(git rev-parse HEAD 2> /dev/null || echo '')"
{
echo "🤖 Addressed the latest review feedback (round ${NEXT_ROUND}/${MAX_ROUNDS}). What changed, and what I pushed back on: · 已处理最新评审反馈(第 ${NEXT_ROUND}/${MAX_ROUNDS} 轮)。改动内容与我反驳保留之处如下:"
echo
Expand Down Expand Up @@ -621,6 +625,10 @@ if [[ "${OUTCOME}" == "fixed" ]]; then
echo
echo "${RESOLUTION_NOTE}"
fi
if [[ -n "${REGRESSED_ROUND:-}" ]]; then
echo
echo "🩸 Regression charged to round ${REGRESSED_ROUND}: that round pushed onto a head whose checks were all green and left them red. It no longer counts as progress for the consecutive-failure brake. · 已将回归记在第 ${REGRESSED_ROUND} 轮:该轮在检查全绿的 head 上推送后检查转红,因此不再计入连续失败熔断的有进展判定。"
fi
echo
echo "Re-review when you have a moment. After round ${MAX_ROUNDS} this bot stops and leaves the PR for a human. · 有空请复审;第 ${MAX_ROUNDS} 轮后本 bot 停止并将 PR 交给人工。"
echo
Expand All @@ -629,6 +637,21 @@ if [[ "${OUTCOME}" == "fixed" ]]; then
echo
echo "<!-- autofix-eval ts=${NEWEST} acted=true round=${NEXT_ROUND} win=${WINDOW:-none} -->"
echo "<!-- autofix-redcheck head=${REPORT_HEAD} -->"
# Regression accounting (af-155). Two distinct facts, both keyed to the
# eval marker's window so the consecutive-failure walk reads them with
# the same filter it already applies to the eval markers:
# autofix-push — what THIS round pushed, and whether the head it
# pushed ONTO was fully green. Only an acted round
# writes it; a no-op pushed nothing to regress.
# head= is the PUSHED sha, not REPORT_HEAD (which
# deliberately records the pre-round head).
# autofix-regression — the PRIOR round prepare found had left a green
# head red. Written by whichever report this round
# posts, so the record survives a later failure.
echo "<!-- autofix-push round=${NEXT_ROUND} head=${PUSHED_HEAD} pre=${CHECK_STATE:-none} key=${WINDOW:-none} -->"
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
if [[ -n "${REGRESSED_ROUND:-}" ]]; then
echo "<!-- autofix-regression round=${REGRESSED_ROUND} key=${WINDOW:-none} -->"
fi
if [[ "${GROWTH_BASE_NEW}" == 'true' ]]; then
echo "<!-- autofix-growth-base src=${GROWTH_BASE_SRC} test=${GROWTH_BASE_TEST} key=${GROWTH_BASE_WIN:-${WINDOW:-none}} -->"
fi
Expand Down Expand Up @@ -672,6 +695,11 @@ else
echo
echo "<!-- autofix-eval ts=${NEWEST} acted=false round=${ROUND} win=${WINDOW:-none} -->"
echo "<!-- autofix-redcheck head=${REPORT_HEAD} -->"
# No autofix-push marker: a no-op round pushed nothing that could
# regress. The regression it OBSERVED still has to be recorded here.
if [[ -n "${REGRESSED_ROUND:-}" ]]; then
echo "<!-- autofix-regression round=${REGRESSED_ROUND} key=${WINDOW:-none} -->"
Comment thread
wenshao marked this conversation as resolved.
Resolved
fi
if [[ "${GROWTH_BASE_NEW}" == 'true' ]]; then
echo "<!-- autofix-growth-base src=${GROWTH_BASE_SRC} test=${GROWTH_BASE_TEST} key=${GROWTH_BASE_WIN:-${WINDOW:-none}} -->"
fi
Expand Down
1,045 changes: 1,045 additions & 0 deletions .github/scripts/run-autofix-review-verification.sh

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/.size-baseline
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
6495 pr-self-report-label.yml
9646 qwen-autofix-fork-bridge.yml
5942 qwen-autofix-fork-signal.yml
454547 qwen-autofix.yml
460577 qwen-autofix.yml
7061 qwen-ci-flaky-rerun.yml
210113 qwen-code-pr-review.yml
79041 qwen-fleet-shepherd.yml
Expand Down
78 changes: 78 additions & 0 deletions .github/workflows/qwen-autofix.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ task-oriented guides — what a maintainer types and what happens next — see:
- [152. review-scan · Scan for PRs with new feedback — Convergence-signal circuit breaker (#10107): the review side diagnoses a non-converging…](#af-152)
- [153. review-address · Prepare branch and feedback — Convergence-break mirror (#10107): the scan refuses to select while the breaker holds,…](#af-153)
- [154. review-address · Report dry-run / failure — Convergence-break report guard (#10122): the report step's stale-base retry is a sibling…](#af-154)
- [155. review-address · Prepare branch and feedback — Classify the live head: a round that pushes onto a fully GREEN head and leaves…](#af-155)

---

Expand Down Expand Up @@ -4200,3 +4201,80 @@ reading holds, exactly like the conflict verdict's skip above it. A
skipped retry reports the gate failure honestly instead; the park's own
notice is still the scan's job.
```

<a id="af-155"></a>

### 155. review-address · Prepare branch and feedback — Classify the live head: a round that pushes onto a fully GREEN head and leaves…

In `review-address` · `Prepare branch and feedback`.

```text
Classify the live head: a round that pushes onto a fully
GREEN head and leaves it red introduced the red. Until this
existed the loop had no notion of a regression at all —
`grep -rE 'regress|introduced'` over the workflow, the gate
script and the SKILL hit only prose about WRITING regression
tests. The consecutive-failure brake counts "rounds that
pushed nothing", so a round that pushed a fix and turned CI
red counted as a SUCCESS and reset the counter; the red it
created came back as the next round's input and was paid for
out of the round budget. A PR could alternate regress /
repair indefinitely while every brake read it as converging.

The gate cannot close this on its own. It runs build,
typecheck, lint and `--changed` tests for the touched
workspaces only, and says so — "Full regression is covered by
regular CI on the PR after the push". Everything the gate
does run IS already charged: a check that fails on the round
tree and passes at `origin/<branch>` is a rejection, and a
rejected round pushes nothing and feeds the brake. What is
left over is precisely the post-push signal — the full suite,
the other packages, other platforms — and that verdict does
not exist until CI finishes, long after the job has ended.

So the accounting is deferred rather than waited on, and it
is measured, never inferred:

- Every ACTED round stamps `autofix-push round= head= pre=
key=`. `pre=` is this classifier's verdict on the head
the round STARTED from; `head=` is the sha it pushed
(NOT the redcheck marker's, which deliberately records
the pre-round head).
- The next round's prepare charges a regression only when
all four hold: the live head is exactly the sha that
marker names (nothing else moved the branch), `pre=green`
(fully green — `pending` and `none` are not green, so a
check still running at push time can never be charged),
the marker's window key matches, and the head is red NOW.
- The observing round writes `autofix-regression round=
key=` into whichever report it posts — pushed, no-op or
failure — so the record survives the round that made it.
- The consecutive-failure walk stops resetting on a
regressing round's headline, reading the round number out
of the headline the report already wrote it into. The
walk also adds THIS round's own observation, which is not
in the fetched comment list yet: without it the newest
regressing push escapes by exactly one round, and that is
the round that matters.

Attribution is deliberately conservative on every axis that
could charge the loop for someone else's red. A head that
moved (a human push, a base update) breaks the head equality
and drops the charge. A re-arm changes the window key and
drops the whole set with it. Cancelled checks are not red
here, matching the scan's own N_RED_NOW filter. The loop's
own lanes are excluded wholesale by the canonical five-name
filter this file's other own-lane filters use — deliberately
NOT the feedback renderer's review-address carve-out, which
keeps failed and in-flight address runs visible as feedback:
a charge verdict must never see them (a failed own round is
feedback, not a regression the pushed code authored, and an
in-flight own check would hold the verdict at pending across
the trigger family whose suite attaches to the PR
head). What remains uncovered is a flake: a
genuinely flaky check failing on the bot's push
reads as a regression. The consequence is bounded on purpose
— one regression only declines to RESET a counter that needs
five consecutive non-progress rounds to trip, and the
recovery is automatic, since a clean push resets it.
```
90 changes: 87 additions & 3 deletions .github/workflows/qwen-autofix.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
name: 'Qwen Autofix'

# One workflow for the whole autonomous-fix lifecycle:
Expand Down Expand Up @@ -4720,6 +4720,49 @@
[[ -z "${OVER_BUDGET_AUTHORS}" ]] && OVER_BUDGET_AUTHORS='[]'
[[ "${OVER_BUDGET_AUTHORS}" != '[]' ]] && echo "🚦 regular-feedback budget exhausted this window for: $(jq -r 'join(", ")' <<< "${OVER_BUDGET_AUTHORS}")"
fi
# ---- regression accounting ------------------------------------
# Classify the live head: a round that pushes onto a fully GREEN
# head and leaves it red introduced the red. Recorded now, charged
# by the consecutive-failure walk later.
# The charge verdict counts ONLY checks outside the loop's own
# lanes — the canonical five-name exclusion this file's other
# own-lane filters use. A red auxiliary lane (review-pr, patrol,
# fork bridge/signal) or the loop's own failed/in-flight
# review-address run is the loop's business, not a regression the
# pushed code introduced; charging it would bill a round for a
# red it never authored, and an in-flight own check would hold
# the verdict at pending for the whole trigger family whose suite
# attaches to the PR head. The review-address carve-out stays at
# the FEEDBACK sites (N_FAILED_CHECKS / N_RED_NOW), where a
# failed own round genuinely is new feedback.
# Full rationale → qwen-autofix.md#af-155
CHECK_STATE="$(jq -r '
[ .[] | select((((.workflowName // "")
| IN("Qwen Autofix", "🧐 Qwen Pull Request Review", "Qwen CI Failure Patrol", "Qwen Autofix Fork Bridge", "Qwen Autofix Fork Signal")) | not)) ] as $c
| if ($c | length) == 0 then "none"
Comment thread
wenshao marked this conversation as resolved.
Resolved
elif any($c[]; (.conclusion // .state // "")
| IN("FAILURE", "FAILED", "ERROR", "TIMED_OUT", "ACTION_REQUIRED")) then "red"
Comment thread
wenshao marked this conversation as resolved.
Resolved
elif any($c[]; ((.status // "") | IN("QUEUED", "IN_PROGRESS", "WAITING", "PENDING"))
Comment thread
wenshao marked this conversation as resolved.
Resolved
or ((.conclusion // .state // "") | IN("PENDING", ""))) then "pending"
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
else "green" end' "${WORKDIR}/checks.json" 2> /dev/null || echo 'none')"
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
case "${CHECK_STATE}" in green | red | pending | none) ;; *) CHECK_STATE='none' ;; esac
REGRESSED_ROUND=''
LAST_PUSH="$(jq -r --arg ab "${AUTOFIX_BOT}" '
[ .[] | select((.user.login // "") == $ab) | . as $c | ($c.body // "")
| [ scan("<!-- autofix-push round=([0-9]+) head=([0-9a-f]+) pre=([a-z]+) key=([^ ]+) -->") ] | .[]
| {r: .[0], h: .[1], p: .[2], k: .[3], at: ($c.created_at // "")} ]
| sort_by(.at) | last // {}
| "\(.r // "") \(.h // "") \(.p // "") \(.k // "")"' \
"${WORKDIR}/ic.json" 2> /dev/null || echo '')"
read -r LP_ROUND LP_HEAD LP_PRE LP_KEY <<< "${LAST_PUSH}" || true
if [[ -n "${LP_ROUND:-}" && "${LP_HEAD:-}" == "${CHECKED_OUT_HEAD}" \
&& "${LP_PRE:-}" == 'green' && "${LP_KEY:-}" == "${WINDOW:-none}" \
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
&& "${CHECK_STATE}" == 'red' ]]; then
Comment thread
wenshao marked this conversation as resolved.
Resolved
REGRESSED_ROUND="${LP_ROUND}"
echo "🩸 #${PR}: round ${LP_ROUND} pushed ${CHECKED_OUT_HEAD:0:9} onto a green head and it is red now — charging that round as a regression"
fi
echo "check_state=${CHECK_STATE}" >> "${GITHUB_OUTPUT}"
echo "regressed_round=${REGRESSED_ROUND}" >> "${GITHUB_OUTPUT}"
echo "stale=${STALE}" >> "${GITHUB_OUTPUT}"
echo "effective_round=${ROUND}" >> "${GITHUB_OUTPUT}"
echo "round_start=${LIVE_ROUND_START}" >> "${GITHUB_OUTPUT}"
Expand Down Expand Up @@ -5847,6 +5890,11 @@
# variable (not a secret), already the agent's OPENAI_MODEL.
MODEL: '${{ vars.QWEN_AUTOFIX_MODEL || vars.QWEN_PR_REVIEW_MODEL }}'
CHECKED_OUT_HEAD: '${{ steps.prepare.outputs.checked_out_head }}'
# Regression accounting (af-155): the head state this round STARTED
# from, stamped into the round's own push marker, and the prior
# round prepare charged as a regression.
CHECK_STATE: '${{ steps.prepare.outputs.check_state }}'
REGRESSED_ROUND: '${{ steps.prepare.outputs.regressed_round }}'
VERIFIED_HEAD: '${{ steps.final_verify.outputs.verified_head }}'
RESANITIZE_SHA256: '${{ steps.stage.outputs.resanitize_sha256 }}'
UPSERT_SRC: '${{ steps.stage.outputs.upsert_src }}'
Expand Down Expand Up @@ -5928,6 +5976,11 @@
EFFECTIVE_ROUND: '${{ steps.prepare.outputs.effective_round }}'
MODEL: '${{ vars.QWEN_AUTOFIX_MODEL || vars.QWEN_PR_REVIEW_MODEL }}'
CHECKED_OUT_HEAD: '${{ steps.prepare.outputs.checked_out_head }}'
# Regression accounting (af-155): the head state this round STARTED
# from, stamped into the round's own push marker, and the prior
# round prepare charged as a regression.
CHECK_STATE: '${{ steps.prepare.outputs.check_state }}'
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
REGRESSED_ROUND: '${{ steps.prepare.outputs.regressed_round }}'
# This step also posts a round report (timeout / gate-rejection /
# abort), so it writes the per-round growth-now marker too — else an
# over-budget round that never reaches 'Push and report' leaves a
Expand Down Expand Up @@ -6356,18 +6409,42 @@
| ($wins | length) > 0 and (($wins | last) == $win))]
| sort_by(.created_at) | .[]
| (.body | gsub("\r"; "") | split("\n")[0])' <<< "${COMMENTS_JSON}" 2> /dev/null || true)"
# Rounds a later round measured as having left a green head red
# (af-155). Same window filter the eval markers above use, so a
# re-arm drops the whole set with the rounds it keyed.
REGRESSED_ROUNDS="$(jq -r --arg ab "${AUTOFIX_BOT}" --arg win "${WINDOW:-none}" '
[ .[] | select((.user.login // "") == $ab) | (.body // "")
| [ scan("<!-- autofix-regression round=([0-9]+) key=([^ ]+) -->") ] | .[]
| select(.[1] == $win) | .[0] ]
| unique | join(" ")' <<< "${COMMENTS_JSON}" 2> /dev/null || true)"
# THIS round's own observation is not in COMMENTS_JSON yet — the
# marker rides the report this step is still composing. Without
# it the newest regressing push always escapes the walk by one
# round, which is exactly the round that matters.
[[ -n "${REGRESSED_ROUND:-}" ]] && REGRESSED_ROUNDS="${REGRESSED_ROUNDS} ${REGRESSED_ROUND}"
while IFS= read -r H; do
[[ -n "${H}" ]] || continue
if [[ "${H}" == *"Addressed the latest review feedback"* || "${H}" == *"no changes needed"* || "${H}" == *"AutoFix could not start —"* || "${H}" == *"updated a stale base"* ]]; then
CONSEC_FAIL=1
# A push that turned the checks red is not progress: it
# bought the next round's work rather than reducing it, and
# resetting here let a PR alternate regress/repair forever
# while every brake read it as converging. The round number
# is read from the headline the same report wrote it into.
H_ROUND=''
[[ "${H}" =~ \(round\ ([0-9]+)/ ]] && H_ROUND="${BASH_REMATCH[1]}"
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
if [[ -n "${H_ROUND}" && " ${REGRESSED_ROUNDS} " == *" ${H_ROUND} "* ]]; then
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
CONSEC_FAIL=$(( CONSEC_FAIL + 1 ))
else
CONSEC_FAIL=1
fi
else
CONSEC_FAIL=$(( CONSEC_FAIL + 1 ))
fi
done <<< "${PRIOR_HEADS}"
if [[ "${CONSEC_FAIL}" -ge "${CONSECUTIVE_FAILURE_CAP}" ]]; then
MARK_ROUND="${MAX_ROUNDS}"
HEADLINE="🤖 AutoFix stopped after ${CONSEC_FAIL} consecutive rounds that pushed nothing (failed rounds, timeouts, gate rejections, or stops under instruction). Retrying at the same per-round budget is not converging — this usually means the PR is too large or conflicts with a fast-moving \`main\`. A human should rebase, split, or reduce it, then comment \`${RETRY_COMMAND}\` to re-arm. Until then future scans will skip this PR."
HEADLINE_ZH="🤖 AutoFix 已停止:连续 ${CONSEC_FAIL} 轮未能推送任何内容(失败轮次、超时、验证门拒绝或按指示停止)。以相同的单轮预算重试并不收敛 —— 这通常意味着 PR 过大,或与快速变动的 \`main\` 冲突。应由人工 rebase、拆分或缩减它,然后评论 \`${RETRY_COMMAND}\` 重新武装。在此之前,后续扫描将跳过本 PR。"
HEADLINE="🤖 AutoFix stopped after ${CONSEC_FAIL} consecutive rounds without progress (failed rounds, timeouts, gate rejections, stops under instruction, or a push that left the checks red). Retrying at the same per-round budget is not converging — this usually means the PR is too large or conflicts with a fast-moving \`main\`. A human should rebase, split, or reduce it, then comment \`${RETRY_COMMAND}\` to re-arm. Until then future scans will skip this PR."
HEADLINE_ZH="🤖 AutoFix 已停止:连续 ${CONSEC_FAIL} 轮没有进展(失败轮次、超时、验证门拒绝、按指示停止,或推送后检查转红)。以相同的单轮预算重试并不收敛 —— 这通常意味着 PR 过大,或与快速变动的 \`main\` 冲突。应由人工 rebase、拆分或缩减它,然后评论 \`${RETRY_COMMAND}\` 重新武装。在此之前,后续扫描将跳过本 PR。"
fi
# CUMULATIVE timeout breaker — the sibling of the consecutive
# one above, for the failure shape it cannot see: timeouts
Expand Down Expand Up @@ -6532,6 +6609,13 @@
if [[ "${MARK_TS}" != '9999-12-31T23:59:59Z' ]]; then
echo "<!-- autofix-redcheck head=${REPORT_HEAD} -->"
fi
# A failed round pushed nothing, so it writes no autofix-push
# marker — but the regression prepare charged to the PRIOR round
# must still be recorded, or a run of failures after a regressing
# push would lose it entirely (af-155).
if [[ -n "${REGRESSED_ROUND:-}" ]]; then
Comment thread
wenshao marked this conversation as resolved.
Resolved
echo "<!-- autofix-regression round=${REGRESSED_ROUND} key=${WINDOW:-none} -->"
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
fi
} > "${WORKDIR}/report.md"
gh pr comment "${PR}" --repo "${REPO}" --body-file "${WORKDIR}/report.md" || echo "::warning::Failed to post handoff comment on PR #${PR}"
fi
Expand Down
Loading