fix(ci): keep qwen-autofix.yml under GitHub's 500 KB start-runs limit - #9517
Conversation
GitHub does not start runs for a workflow file larger than 500 KB (512,000 bytes) and reports nothing when it stops. qwen-autofix.yml crossed that line on 2026-08-19 at 512,782 bytes: schedule ticks stopped firing, every workflow_dispatch sat "queued" forever with zero jobs and could not be cancelled, and issues/issue_comment went quiet — while pull_request_review runs kept succeeding, because a PR event resolves the workflow from the PR's own branch and those carry older, smaller copies of this file. The loop therefore looked half-alive and stayed dark for a day. Move 75 long comment blocks (1,326 lines) verbatim into a sibling design record, .github/workflows/qwen-autofix.md, leaving each block's opening lines plus a `qwen-autofix.md#af-NNN` pointer where it sat: 518,055 -> 426,437 bytes. No executable line changes — the YAML parses to an identical document outside `run:`, every `run:` script still passes `bash -n`, and the only lines removed anywhere are comments. Steps that are duplicated verbatim across jobs share one pointer so they stay byte-identical. Add .github/scripts/check-workflow-size.sh (gate at 470,000 bytes), wired into CI on every profile: a .github-only PR classifies as `github_ci_only` and skips the `full`-only checks, which is exactly the PR that can trip this. Tests pin the gate, every workflow's size, and pointer/section symmetry. Delete qwen-autofix-recovery.yml. It was cloned during the incident on the theory that the workflow ENTITY was wedged, but it carried the same oversized file, so its dispatches queued identically and its schedule never fired.
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
|
Thanks for the PR — this one restores the autofix loop itself, so I went through the gate carefully. Template: the body skips the template headings (What this PR does / Why it's needed / Reviewer Test Plan / …) for free-form sections. Normally that's a bounce, but the content covers everything the template asks for — with stronger evidence than most template fill-ins — so I'm treating it as a substance pass and noting the deviation instead of blocking on headings. Problem: real, and I verified it independently. The 500 KB start-runs wall is not hypothetical here:
Direction: aligned — this repairs and then safeguards the repo's own automation. The gate (fail 470,000 / warn 445,000) sits comfortably below both the documented limit and the empirically observed boundary. Size: no core-package paths touched ( Approach: right-sized. Moving long-form comments verbatim into a sibling design record is the lowest-risk byte reduction available — executable lines untouched — and the gate plus tests turn a silent failure mode into a loud one. Deleting the recovery clone is part of the same repair, not scope creep: it carried the same oversized file (verified: 518,544 bytes), so it could never have fired. Risk: no high-risk-path matches — every changed file is CI config, CI scripts, or tests. Moving on to code review. 🔍 中文说明感谢这个 PR——它恢复的是 autofix 循环本身,所以门禁过得比较仔细。 模板:正文没有使用模板标题(What this PR does / Why it's needed / Reviewer Test Plan 等),而是自由格式分节。通常这会被打回,但内容覆盖了模板要求的全部信息——证据比大多数模板填写更扎实——因此按实质通过处理,只记录偏差,不以标题为由阻塞。 问题:真实存在,且已独立核实。 500 KB start-runs 上限在本仓库不是假设:
方向:对齐——修复并加固仓库自身的自动化。门禁(470,000 失败 / 445,000 告警)远低于文档上限与实测边界。 规模:未触及核心包路径(仅 方案:范围恰当。把长篇注释逐字迁入同目录设计记录是风险最低的减字节方式——可执行行不动——门禁加测试让静默失败变成显式报错。删除 recovery 克隆是同一次修复的一部分,不是顺手扩张:它带着同样超限的文件(已核实 518,544 字节),永远不可能生效。 风险:无高风险路径命中——改动全部为 CI 配置、CI 脚本与测试。 进入代码审查。🔍 — Qwen Code · qwen3.8-max Reviewed at |
Code reviewThe central claim — "no executable line changes" — is mechanically checkable, so I checked it mechanically (static analysis of the before/after files fetched via the API; no PR code was run):
No blockers. The one residual I could not verify myself: the actionlint/shellcheck/yamllint/prettier pass the description claims isn't visible as separate checks here — the green TestingCI evidence for the reviewed commit, quoted from the checks API:
Both 中文说明代码审查核心主张——"没有任何可执行行变化"——可以机械验证,我也确实做了机械验证(对经 API 获取的改动前后文件做静态分析;未运行任何 PR 代码):
无阻塞项。唯一无法自行核实的残留:描述中声称的 actionlint/shellcheck/yamllint/prettier 通过,在这里没有独立的 check 可见——绿色的 测试被审提交的 CI 证据,引自 checks API(见上表)。 该提交上两个 — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — everything checkable was checked and held; the docked point is the free-form body noted below, a nit, not a doubt. Stepping back: this PR is the opposite of speculative hardening — the failure was observed, dated, and sized to the byte, and I re-verified the evidence trail against the API rather than taking the description's word for it. The fix is the minimum set that both restores the loop and keeps it alive: move prose, never executable lines (proven statically, not just claimed), then make the wall loud with a gate wired into exactly the CI profile that skips full checks — the profile a Residuals, none blocking: the body skips the template headings (the substance is all there, unusually thorough); and the zombie queued dispatches named under "After merge" remain a maintainer to-do once this lands. Approving, pinned to the reviewed commit. ✅ 中文说明Confidence: 4/5 —— 所有可验证的都验证了,且全部成立;扣掉的一分只给下面提到的自由格式正文,那是 nit,不是疑虑。 退一步看:这个 PR 与"理论性加固"恰恰相反——故障是被观测到、有日期、有精确字节数的,而我没有采信描述的说辞,是对着 API 重新核实了证据链。修复是"既恢复循环、又让循环活下去"的最小集:迁移的是文字,绝不是可执行行(静态证明,而非口头声明),然后用门禁把这堵墙变成显式报错,并恰恰挂载在会跳过 full 检查的那个 CI profile 上—— 残留项均不阻塞:正文跳过了模板标题(实质内容齐备且异常详尽);以及"合并之后"点名的僵尸排队 dispatch,是落地后留给 maintainer 的待办。 按被审提交固定批准。✅ — Qwen Code · qwen3.8-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
LGTM, looks ready to ship. ✅
doudouOUC
left a comment
There was a problem hiding this comment.
Comprehensive review — head 1a529d5
Verified the PR's mechanical claims independently against this exact commit. No defects found. Approving.
Verification evidence
1. Zero executable-line drift (the core safety claim) — confirmed by two independent methods:
git diffoverqwen-autofix.yml: every deleted and every added line is a whole-line#comment or blank — 0 non-comment lines on either side.- Stripped all comment lines (with heredoc-state tracking so
#-leading heredoc data lines are kept) from both the pre-change and post-change files: both sides reduce to the identical 4,284-line document. Allrun:scripts,if:,env:,concurrency:, matrices, and the 3 heredoc bodies are unchanged.
2. Verbatim migration — of the 1,307 substantive deleted comment lines, 1,305 are present verbatim in qwen-autofix.md; the only 2 absent lines are exactly the deliberate exception the PR declares (the falsified 2026-08-19: no-op comment diagnosis), and the corrected account is present in the design-record header.
3. Pointer symmetry — 72 unique qwen-autofix.md#af-NNN pointers ↔ 72 <a id="af-NNN"> anchors, consistent with the 75-block count (cross-job verbatim steps share one id: af-010 ×3, af-011 ×2). workflow-size.test.js pins this in both directions plus the contents table, and passes 57/57 locally.
4. Gate + wiring — check-workflow-size.sh gates at 470,000 / warns at 445,000, under GitHub's 512,000-byte start-runs limit; runs green locally. The CI step in ci.yml is gated on skip_ci only, NOT on ci_profile, so a .github-only PR (github_ci_only) still runs it — the exact PR class that can trip the limit.
5. Recovery clone deletion — qwen-autofix-recovery.yml removed with zero remaining references in .github/ or scripts/.
6. Tests — qwen-autofix-workflow.test.js runs 168 pass / 12 fail locally, but the SAME 12 tests fail identically on the pre-PR base commit (39fc769d3a) in this environment: the failures are mapfile: command not found from macOS's bash 3.2, pre-existing and unrelated to this PR. CI's Test (ubuntu-latest) job is green at this head, where bash 5.x runs the full suite.
7. Size — qwen-autofix.yml is 426,437 bytes, under both the gate and the limit.
中文说明
针对 head 1a529d5 独立机械验证了 PR 的全部关键论断:① qwen-autofix.yml 的 diff 中被删/被增的行全部是整行注释或空行(非注释行 0 行);带 heredoc 状态跟踪地剥离两侧注释后,均归约为完全相同的 4,284 行文档——零可执行行漂移成立,3 处 heredoc 体未变。② 1,307 行实质删除注释中 1,305 行逐字存在于设计记录,唯二缺失恰为 PR 声明的有意例外(已证伪的 no-op 诊断),更正说明已在 md 头部确认。③ 72 个指针 id 与 72 个锚点双向对称,与"75 块、跨 job 重复 step 共享 id"的说明一致。④ 门禁 470K 低于 GitHub 512K 限制,CI 步骤仅按 skip_ci 门控、不受 ci_profile 限制,.github-only PR 也会运行。⑤ recovery 克隆删除后无任何残留引用。⑥ 本地 12 个失败用例在基线 commit 上以完全相同的名单失败(macOS bash 3.2 缺 mapfile 的环境问题),CI ubuntu 作业在本 head 为绿。⑦ 文件 426,437 字节,门禁与限制之下。未发现缺陷,予以 Approve。
CI Test checks out PR HEAD, then runs check-workflow-size.sh added on main in QwenLM#9517. Without this merge the script is missing and the job exits 127.
Picks up QwenLM#9517, which adds .github/scripts/check-workflow-size.sh. main's ci.yml already invokes that script against the PR head's files, so every branch predating QwenLM#9517 fails "Test (ubuntu-latest, Node 22.x)" at the "Check workflow file size" step with exit 127 (No such file or directory). This merge is what clears that required check; no source change is involved.
wenshao
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
Not explored to full depth (tool budget reached): chunk 10: identifying the 5 failing tests in scripts/tests/qwen-autofix-workflow.test.js and the origin/main comparison run to attribute them (suite runs hung on this con….
Not linted (tool limitation, not a blocker): the executable-script lint — .github/workflows/ci.yml: actionlint embedded-shell source mapping is not yet supported — not linted; the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted.
中文说明
已审查。 建议见行内评论。
未探索到全部深度(达到工具调用预算):chunk 10:identifying the 5 failing tests in scripts/tests/qwen-autofix-workflow.test.js and the origin/main comparison run to attribute them (suite runs hung on this con…。
未检查(工具限制,非阻断):the executable-script lint — .github/workflows/ci.yml: actionlint embedded-shell source mapping is not yet supported — not linted; the executable-script lint — .github/workflows/qwen-autofix.yml: actionlint embedded-shell source mapping is not yet supported — not linted。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| # repository secrets: GitHub withholds them from every run | ||
| # tied to a pull request whose head lives in a fork, and the | ||
| # run header states it outright (`Secret source: None`). So | ||
| # CI_DEV_BOT_PAT arrives EMPTY and neither review-scan nor | ||
| # review-address could authenticate from here — the earlier | ||
| # claim that "this event runs in BASE-repo context" held for | ||
| # the workflow FILE, which is read from base, but not for the | ||
| # credentials. | ||
| # Admitting the PR anyway spent two API reads to decide it, | ||
| # then three more failing inside the scan, which exited 1 on | ||
| # `metadata_fetch_failed` — a reason whose blocked comment | ||
| # promises "a later scheduled scan will retry", true for a | ||
| # 5xx and false for a credential this run was never handed. | ||
| # Every review of a fork PR reddened the workflow while | ||
| # changing nothing, and that noise buried the failures that | ||
| # do need a human. | ||
| # The label and the feedback both keep working: the scheduled | ||
| # scan runs in repo context and admits fork takeover PRs on | ||
| # its own. This mirrors the pull_request label branch below, | ||
| # which already declines forks for exactly this reason. | ||
| # Full rationale → qwen-autofix.md#af-006 |
There was a problem hiding this comment.
[Suggestion] The comment excision cut the retained lead-in mid-sentence at 55 of the 75 pointer sites (verified by a sweep over all sites); runtime behaviour is unaffected — this is about the on-site summaries the pointer scheme exists to provide. This is the worst instance: the original sentence read 'GitHub withholds them from every run tied to a pull request whose head lives in a fork' — the excision deleted the qualifier, leaving a false universal claim (the schedule/dispatch paths in this same file authenticate with CI_DEV_BOT_PAT). Other notable shapes: af-014/af-056 truncate the 'keep this block byte-identical to its twin (the contract test pins them equal)' instruction to a dangling 'keep this'; af-041 cuts the SECURITY invariant clause; af-064/af-068 leave dangling colons whose promised lists were excised; af-005 leaves a dangling colon (also replicated in the md heading/TOC); af-071 is cut at an em-dash, which punctuation-based sweeps miss. Full census (pointer ids): af-003, af-005, af-006, af-008, af-009, af-010 (×3 copies), af-011 (×2), af-012, af-014, af-015, af-016, af-017, af-018, af-020 (also swallowed the closing === of the TAKEOVER ACK banner), af-023, af-025, af-026, af-027, af-028, af-029, af-031, af-033, af-035, af-036, af-037, af-038, af-041, af-042, af-043, af-044, af-045, af-046, af-047, af-048, af-049, af-050, af-051, af-053, af-054, af-056, af-057, af-058, af-059, af-060, af-061, af-063, af-064, af-065, af-066, af-068, af-070, af-071. Fix: one sweep — trim each retained lead-in to the last complete sentence, or complete it into one self-contained line; re-probe with em-dash and dangling-colon awareness; edit the three byte-identical af-010 copies together (the contract test pins them equal) and the two af-011 copies together.
中文说明
注释抽取把 75 个指针位点中 55 处的保留引导语在句中截断(已对全部位点扫描核实);运行行为不受影响——问题在于指针机制本应提供的就地摘要。此处是最严重的一例:原句为 'GitHub withholds them from every run tied to a pull request whose head lives in a fork',抽取删掉了限定从句,留下一个错误的绝对化断言(本文件的 schedule/dispatch 路径使用 CI_DEV_BOT_PAT 认证)。其他典型形态:af-014/af-056 把 'keep this block byte-identical to its twin(合约测试钉住两者相等)' 的维护指令截成悬空的 'keep this';af-041 截断了 SECURITY 不变量子句;af-064/af-068 留下悬空冒号(其承诺的列表已被删除);af-005 留下悬空冒号(并复制到 md 的标题/目录);af-071 在破折号处被截断,基于标点的扫描会漏掉它。完整清单(指针 id):af-003、af-005、af-006、af-008、af-009、af-010(×3 份)、af-011(×2)、af-012、af-014、af-015、af-016、af-017、af-018、af-020(还吞掉了 TAKEOVER ACK 横幅的收尾 ===)、af-023、af-025、af-026、af-027、af-028、af-029、af-031、af-033、af-035、af-036、af-037、af-038、af-041、af-042、af-043、af-044、af-045、af-046、af-047、af-048、af-049、af-050、af-051、af-053、af-054、af-056、af-057、af-058、af-059、af-060、af-061、af-063、af-064、af-065、af-066、af-068、af-070、af-071。修复:一次扫描——把每处引导语裁剪到最后一个完整句子,或补全为自足的一行;以破折号和悬空冒号形态重新探测;三份逐字相同的 af-010 副本需一起编辑(合约测试钉住三者相等),af-011 的两份副本同理。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| # Deliberately gated on skip_ci ONLY, not on the CI profile: a PR that | ||
| # touches nothing but .github/ classifies as `github_ci_only`, and that | ||
| # is exactly the PR most likely to push a workflow file past GitHub's |
There was a problem hiding this comment.
[Suggestion] This comment (and its twin in scripts/tests/workflow-size.test.js) claims a PR touching nothing but .github/ classifies as github_ci_only, but classify-profile.mjs defines GITHUB_CI_ONLY_FILES as a hardcoded 3-file allowlist (pr-safety-precheck.mjs, its test, and qwen-pr-safety-precheck.yml), and classify-profile.test.mjs pins classifyChangedFiles(['.github/workflows/ci.yml']) === 'full'. Probe against the real classifier at this commit: ci.yml only → full, qwen-autofix.yml only → full, all 3 allowlisted → github_ci_only. The step's actual gating (skip_ci only, runs on every profile) is correct and test-pinned — only the recorded rationale is wrong. Failure scenario: a maintainer trusting this comment re-gates the step onto the github_ci_only profile and silently removes the size gate from every workflow-editing PR — exactly the PRs that can trip the 500 KB limit. Reword to match the classifier: github_ci_only is a 3-file allowlist (one of which is a workflow file — the narrow case this gate additionally covers), while workflow-file PRs classify as full.
中文说明
这条注释(以及 scripts/tests/workflow-size.test.js 中的孪生注释)声称只改 .github/ 的 PR 会被分类为 github_ci_only,但 classify-profile.mjs 把 GITHUB_CI_ONLY_FILES 定义为硬编码的 3 文件白名单(pr-safety-precheck.mjs、其测试、qwen-pr-safety-precheck.yml),且 classify-profile.test.mjs 钉住了 classifyChangedFiles(['.github/workflows/ci.yml']) === 'full'。在本提交上对真实分类器探测:仅 ci.yml → full、仅 qwen-autofix.yml → full、三个白名单文件 → github_ci_only。该 step 的实际门控(仅 skip_ci、所有 profile 都跑)是正确且有测试钉住的——只是注释记录的理由错了。失败场景:维护者相信这条注释,把该 step 改为仅在 github_ci_only profile 下运行,就会静默地让所有改动 workflow 的 PR 失去大小门禁——而那恰恰是最可能触发 500 KB 限制的 PR。请按分类器实情改写:github_ci_only 是 3 文件白名单(其中之一是 workflow 文件——正是本门禁额外覆盖的窄场景),而改 workflow 的 PR 分类为 full。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| // A .github-only PR classifies as `github_ci_only`; gating the check on the | ||
| // `full` profile would skip it for exactly the changes that can trip it. |
There was a problem hiding this comment.
[Suggestion] Same false classifier claim as the ci.yml comment discussed in this review: a .github-only PR does NOT classify as github_ci_only — that profile is a hardcoded 3-file allowlist (pr-safety-precheck.mjs, its test, qwen-pr-safety-precheck.yml), verified by probe against classify-profile.mjs at this commit. Please reword together with the ci.yml comment so the two stay consistent.
中文说明
与 ci.yml 中讨论过的注释是同一个错误的分类器断言:只改 .github/ 的 PR 并不会分类为 github_ci_only——该 profile 是硬编码的 3 文件白名单(pr-safety-precheck.mjs、其测试、qwen-pr-safety-precheck.yml),已在本提交上对 classify-profile.mjs 探测证实。请与 ci.yml 注释一并改写,保持一致。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| const gateBytes = Number( | ||
| gateScript.match(/GATE_BYTES="\$\{WORKFLOW_SIZE_GATE_BYTES:-(\d+)\}"/)?.[1], | ||
| ); |
There was a problem hiding this comment.
[Suggestion] No test executes .github/scripts/check-workflow-size.sh — this suite regex-parses it as data, so its runtime behaviour (exit codes, the ::error/::warning branches, the scanned-file glob, the read-failure path) is untested. On the github_ci_only profile the vitest suite does not run at all, and that lane (which today reaches qwen-pr-safety-precheck.yml) is where this script is the ONLY size check. Concrete breakage: a glob typo (.github/workflow/*.yml) that shopt -s nullglob turns into zero files checked still exits 0 with a green '✅ every workflow file is under the … gate' message — a dead gate nothing catches. Probe at this commit confirms both arms are exercisable as-is: WORKFLOW_SIZE_GATE_BYTES=1 → ::error per file + exit 1; default env → exit 0. Add a spawn-based test for both arms.
中文说明
没有任何测试会执行 .github/scripts/check-workflow-size.sh——本套件只是用正则把它当作文本解析,因此其运行时行为(退出码、::error/::warning 分支、扫描的文件 glob、读取失败路径)未被测试。在 github_ci_only profile 下 vitest 套件根本不会运行,而该通道(目前会触及 qwen-pr-safety-precheck.yml)恰恰只有这个脚本作为唯一的大小检查。具体损坏方式:glob 拼写错误(.github/workflow/*.yml)在 shopt -s nullglob 下变成零文件受检,却仍以退出码 0 输出绿色的 '✅ every workflow file is under the … gate'——门禁失效且无人察觉。已在本提交上探测确认两个分支都可以直接测:WORKFLOW_SIZE_GATE_BYTES=1 → 每文件一条 ::error + 退出码 1;默认环境 → 退出码 0。建议补一个 spawn 脚本的测试覆盖两个分支。
— qwen3.8-max via Qwen Code /review (v0.21.11)
|
|
||
| <a id="af-072"></a> | ||
|
|
||
| ### 72. review-address · Report dry-run / failure — Flip the status comment out of "working" so a finished round never leaves a live-looking… |
There was a problem hiding this comment.
[Suggestion] Misattributed section: the af-072 pointer (qwen-autofix.yml L6402) sits directly above - name: 'Finalize autofix status comment' (L6403), and this section's text documents exactly that step's PATCH-only / stale != 'true' gating — but the heading, the Contents entry (L122) and the In … line all say Report dry-run / failure. This violates the record's own 'titled with the job and step it belongs to' contract; a maintainer grepping the record for the finalize step finds nothing, and readers of the Report dry-run / failure group are pointed at logic outside their step. Retitle all three lines as review-address · Finalize autofix status comment.
中文说明
章节归属错误:af-072 的指针(qwen-autofix.yml L6402)紧邻 - name: 'Finalize autofix status comment'(L6403)上方,本节内容描述的正是该 step 的 PATCH-only / stale != 'true' 门控——但标题、目录条目(L122)和 In … 行都写作 Report dry-run / failure。这违反了该记录自身'titled with the job and step it belongs to'的约定;维护者在记录中搜索 finalize step 会一无所获,而 Report dry-run / failure 分组的读者会被指向不属于自己 step 的逻辑。请把三处一并改为 review-address · Finalize autofix status comment。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| # Growth brake: measure the PR's net size (insertions minus | ||
| # deletions) over this window and ... | ||
| # Full rationale → qwen-autofix.md#af-030 |
There was a problem hiding this comment.
[Suggestion] The worked example pairs the growth-brake comment with #af-030, but the real growth-brake pointer — qwen-autofix.yml L4282-4284, whose lead-in this example quotes — says #af-043; af-030 is the unrelated grace-windows section. The example demonstrates exactly the pointer/section-id desync the adjacent editing rule ('keep the pointer and the section id in sync') forbids, and the new tests only assert id resolution, so a copycat mis-targeted pointer passes. Point the example at af-043 and align its lead-in with the actual YAML lead-in ('deletions vs the merge base), split into test lines and source').
| # Growth brake: measure the PR's net size (insertions minus | |
| # deletions) over this window and ... | |
| # Full rationale → qwen-autofix.md#af-030 | |
| # Growth brake: measure the PR's net size (insertions minus | |
| # deletions vs the merge base), split into test lines and source ... | |
| # Full rationale → qwen-autofix.md#af-043 |
中文说明
示例把 growth brake 注释配对了 #af-030,但真实的 growth brake 指针——qwen-autofix.yml L4282-4284(示例引用的正是其引导语)——写的是 #af-043;af-030 是无关的 grace-window 章节。该示例恰好演示了相邻编辑规则('keep the pointer and the section id in sync')所禁止的指针/章节 id 失配,而新测试只断言 id 可解析,照抄示例的错误指针也能通过。请把示例指向 af-043,并让其引导语与 YAML 实际引导语一致('deletions vs the merge base), split into test lines and source')。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| public ::warning::. Same reasoning, same shape as the `gh api | ||
| user` checks elsewhere in this file. |
There was a problem hiding this comment.
[Suggestion] The migration left ~22 positional references ('above'/'below'/'this file'/'both arms') that resolved against the YAML at the original site but are false or unresolvable in this record; this is the anchor instance — 'elsewhere in this file' now means the md, which contains zero gh api user occurrences (the twins live in qwen-autofix.yml L867/L1515). Verified members include: af-047 'the trajectory clause below' (clause stayed at yml L4647-4656); af-010 'the local allowlist below' (no allowlist anywhere in the record); af-038 'the hygiene steps below' (they are sections 10-11 ABOVE); af-007 'the constants discipline above' (yml L199-206); af-014/af-056 twins 'the digest gate below' (gates yml L1547/L5548, never given a section — edit the twins together); af-017 'the engage post below' (yml L1863-1867); af-019; af-024; af-025 'decision below' (also in its heading + Contents entry); af-026; af-029 'fetched just above' (fetch yml L2831); af-039; af-043 'deferral machinery below'; af-044 'the merge-tree conflict probe above' (probe yml L4118-4126, never migrated); af-048 'the deferred renderer below' (renderer yml L4516-4635); af-052 'the reply block below'; af-054; af-055 'both arms below' (arms yml L5642/L5700; also Contents entry + heading); af-058 'the retry loop below'; af-060 'the upsert below / the block near the end of this step' (block yml L6344-6395); af-062; af-067 'BOTH gh api calls above' (calls yml L6066-6068); af-070; af-071. Fix (one move covers all): add a sentence to 'How the pointers work' stating that positional references in migrated text point at the original pointer site in qwen-autofix.yml; additionally reword the worst sites — af-014/af-056 twins, af-025 (heading + Contents), and af-060/af-067, whose referents have no section at all.
中文说明
迁移后约有 22 处方位引用('above'/'below'/'this file'/'both arms')在原 YAML 位点可以解析、在这份记录中却为假或无法解析;此处是锚定实例——'elsewhere in this file' 现在指 md 本身,而 md 中没有任何 gh api user 检查(孪生检查在 qwen-autofix.yml L867/L1515)。已核实的成员包括:af-047 'the trajectory clause below'(该子句留在 yml L4647-4656);af-010 'the local allowlist below'(记录中不存在任何 allowlist);af-038 'the hygiene steps below'(它们在上方第 10-11 节);af-007 'the constants discipline above'(yml L199-206);af-014/af-056 孪生 'the digest gate below'(门禁在 yml L1547/L5548,从未立节——两处孪生需一起改);af-017 'the engage post below'(yml L1863-1867);af-019;af-024;af-025 'decision below'(其标题与目录条目同样携带);af-026;af-029 'fetched just above'(fetch 在 yml L2831);af-039;af-043 'deferral machinery below';af-044 'the merge-tree conflict probe above'(探针在 yml L4118-4126,未迁移);af-048 'the deferred renderer below'(渲染器在 yml L4516-4635);af-052 'the reply block below';af-054;af-055 'both arms below'(两臂在 yml L5642/L5700;目录条目与标题亦携带);af-058 'the retry loop below';af-060 'the upsert below / the block near the end of this step'(块在 yml L6344-6395);af-062;af-067 'BOTH gh api calls above'(调用在 yml L6066-6068);af-070;af-071。修复(一步覆盖全部):在 'How the pointers work' 中加一句——迁移文本中的方位引用指向 qwen-autofix.yml 中原指针位点;另对最严重的几处改写:af-014/af-056 孪生、af-025(标题+目录)、以及 af-060/af-067(其指称对象在记录中完全没有章节)。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| - [68. review-address · Report dry-run / failure — NEWEST is empty because Prepare never RAN TO A VERDICT — an earlier step failed or the…](#af-068) | ||
| - [69. review-address · Report dry-run / failure — Consecutive-failure circuit breaker, distinct from the round cap.](#af-069) | ||
| - [70. review-address · Report dry-run / failure — -c drops any partial multi-byte sequence a byte-level head -c may have split, so the…](#af-070) | ||
| - [71. review-address · Report dry-run / failure — Bilingual companion. Repo convention is English first, Chinese in a collapsed <details>.…](#af-071) |
There was a problem hiding this comment.
[Suggestion] The bare, unclosed <details> tag in this Contents entry (and its ### 71. heading twin at ~L2113) renders as a live disclosure widget on GitHub — probe via GitHub's own POST /markdown (mode=gfm) on the exact lines: the link truncates at 'collapsed ' and a stray widget swallows the trailing text (<li><a href="#af-071">71. … Chinese in a collapsed </a><details> Details .…</details></li>); escaping the tag flips it to 0 <details> elements with the full text. These are the only two unfenced occurrences — every </details> in the file sits inside ```text fences — and nothing catches it (the new tests assert id resolution only). Ironically this is the exact failure mode section 71 documents for PR comments.
| - [71. review-address · Report dry-run / failure — Bilingual companion. Repo convention is English first, Chinese in a collapsed <details>.…](#af-071) | |
| - [71. review-address · Report dry-run / failure — Bilingual companion. Repo convention is English first, Chinese in a collapsed `<details>`.…](#af-071) |
(Escape the heading twin the same way.)
中文说明
该目录条目中裸露且未闭合的 <details> 标签(以及约 L2113 的 ### 71. 标题孪生)在 GitHub 上会渲染成一个真实的折叠组件——已用 GitHub 官方 POST /markdown(mode=gfm)对原文探测:链接在 'collapsed ' 处被截断,多余组件吞掉了后续文本(<li><a href="#af-071">71. … Chinese in a collapsed </a><details> Details .…</details></li>);将标签转义后翻转为 0 个 <details> 元素且文本完整。这是全文件仅有的两处未加围栏的出现——所有 </details> 都在 ```text 围栏内——且没有任何测试能发现(新测试只断言 id 可解析)。讽刺的是,这正是第 71 节自身所记载的 PR 评论失效模式。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| reset the streak at each push ("Addressed the latest review | ||
| feedback"), deliberate no-op ("no changes needed"), or pre-agent | ||
| infra-failure marker ("AutoFix could not start"). After the |
There was a problem hiding this comment.
[Suggestion] This enumeration lists three CONSEC_FAIL streak-reset triggers, but the breaker walk (qwen-autofix.yml L6163) also resets on a fourth headline needle — *"updated a stale base"*. The final paragraph covers only the current-round exemption (STALE_BASE_RETRY guard at L6140), which is a distinct mechanism from the walk reset. Failure scenario: an editor extending or refactoring the reset list from this record omits the stale-base needle; a window containing a stale-base auto-update plus unrelated transient failures then accumulates streak through the progress round and trips CONSECUTIVE_FAILURE_CAP early, marking the PR terminal despite mid-window progress. Add the fourth needle to the enumeration ('…a stale-base auto-update round ("updated a stale base") also RESETS the streak — distinct from the current-round exemption').
中文说明
此处列举了三个 CONSEC_FAIL 连败重置触发条件,但断路器扫描(qwen-autofix.yml L6163)还会在第四个 headline 针——*"updated a stale base"*——上重置。末段只覆盖了当轮豁免(L6140 的 STALE_BASE_RETRY 守卫),那是与扫描重置不同的机制。失败场景:编辑者依据本记录扩展或重构重置列表时漏掉 stale-base 针;一个包含 stale-base 自动更新外加若干无关瞬时失败的窗口,会在已有进展的轮次上继续累计连败,提前触发 CONSECUTIVE_FAILURE_CAP,把 PR 标记为终态。请在列举中补上第四个针('……stale-base 自动更新轮次("updated a stale base")同样会重置连败——与当轮豁免不同')。
— qwen3.8-max via Qwen Code /review (v0.21.11)
| expect(designDoc).toContain('base conflict'); | ||
| expect(designDoc).toContain('still-red checks'); |
There was a problem hiding this comment.
[Suggestion] The migrated assertion lost its scope: it previously matched only reviewScanJob (pinning the idle-backoff rationale where the comment lived); now expect(designDoc).toContain('base conflict') matches the whole 2152-line doc, where the string occurs three times — af-002 (md L192, 'base conflicts may drive code changes'), af-027 (L926, the intended referent), and af-066 (L1991) — the first and third as substrings of 'base conflicts'. Dropping the af-027 enumeration of the two scan-only signals keeps this green via the unrelated occurrences, so the documented invariant the test exists to catch can be deleted unflagged. (still-red checks occurs once and stays effectively pinned.) Scope the assertion to the section:
| expect(designDoc).toContain('base conflict'); | |
| expect(designDoc).toContain('still-red checks'); | |
| const idleBackoff = designDoc.slice( | |
| designDoc.indexOf('<a id="af-027">'), | |
| designDoc.indexOf('<a id="af-029">'), | |
| ); | |
| expect(idleBackoff).toContain('base conflict'); | |
| expect(idleBackoff).toContain('still-red checks'); |
中文说明
迁移后的断言丢失了作用域:原先只匹配 reviewScanJob(在注释原所处位置钉住 idle-backoff 理由);现在 expect(designDoc).toContain('base conflict') 匹配整份 2152 行的记录,而该字符串出现三次——af-002(md L192,'base conflicts may drive code changes')、af-027(L926,预期指称)、af-066(L1991)——首尾两处还是 'base conflicts' 的子串。删除 af-027 中关于两个 scan-only 信号的列举,断言仍会经由无关出现处保持绿色,该测试本要捕捉的已记录不变量可以被无声删除。(still-red checks 仅出现一次,实际仍被钉住。)请把断言限定到该章节:
— qwen3.8-max via Qwen Code /review (v0.21.11)
qwen-autofix-recovery.yml was deleted on main (#9517, the oversized-file incident fix): accept the deletion — the clone carried the same jobs as qwen-autofix.yml, where this branch's bindings already landed — and drop it from the sandbox-image contract test's workflow list.
|
Released in v0.21.15. |
…wth (QwenLM#9677) * chore(ci): migrate autofix prose to the design record and ratchet growth `qwen-autofix.yml` was at 462,720 bytes — 90% of GitHub's 500 KB start-runs limit and 7,280 under this repo's gate. The prose migration in QwenLM#9517 had regained 78 KB; a single feature commit gave 25 KB of it back two days later, 53% of it comment lines that belonged in the design record. Nothing objected, because the gate is a ceiling and only speaks when a file is already at the wall. Two changes, addressing the level and the slope. Level: 76 comment blocks of 8+ lines move into qwen-autofix.md as af-073..af-148, each leaving its opening two lines plus the usual pointer. The file drops to 419,995 — 50 KB under the gate. Slope: every workflow's recorded size now lives in .github/workflows/.size-baseline, and check-workflow-size.sh fails a file that exceeds its entry by more than 4 KB. Growing a file is still allowed; the ratchet only insists the growth be visible in review instead of discovered at the wall. A file well under its baseline warns so the slack is reclaimed rather than banked. Two things the migration had to learn, both caught by contract tests rather than by inspection: Identical prose shares one af id. A step inlined into several jobs must stay byte-identical across copies, and minting a separate id per copy broke that for the git-config sanitize step — same length, different pointer digits. A cross-file editing contract is not prose. "This copy and the one in qwen-triage must be edited together" only does its job where the editor will see it; moving it to the design record is how a lockstep silently breaks. Blocks naming a sibling workflow or script, or spelling the contract out, stay put. Behaviour is unchanged and checked, not assumed: both YAML documents were parsed and compared with comment lines dropped from every string, and they are equal. * fix(ci): harden the workflow-size ratchet per review - key the vitest baseline lookups by separator-agnostic file name so the merge-queue Windows lane resolves entries (split('/') missed win32 joins) - fail closed on malformed .size-baseline lines: non-numeric values, leading zeros (bash octal), and extra fields no longer disable or mis-key the ratchet; keep an unterminated final line - execute the gate script end-to-end in tests (growth, missing entry, missing baseline, slack warning, malformed line) so its decision branches are witnessed - correct af-079/af-123/af-084 attributions in the design record * fix(ci): pin ratchet boundaries and skip pre-bash-4 test hosts * fix(ci): end migrated autofix teasers at sentence boundaries per review --------- Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com> Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com> Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
The failure
GitHub does not start runs for a workflow file larger than 500 KB (512,000 bytes) — documented limit — and it fails silently: no annotation, no failed run, no disabled-workflow banner.
qwen-autofix.ymlcrossed that line on 2026-08-19 00:17 UTC and the autofix/takeover loop went dark for a day.a4a3850fe5(#9329)846fc05461(#9386)4154bd7457(#9479)The symptom set reads like an Actions outage, which is why it took a day to spot:
schedule(*/10)issue_commentissuesworkflow_dispatchqueuedforever with zero jobs, uncancellable via the APIpull_request_reviewThat last row is the trap. A PR event resolves the workflow from the PR's own branch, and those branches carry older, smaller copies of the file — the run that succeeded at 21:06 on 08-19 used a 476,244-byte copy. So the loop kept posting green runs while every scheduled scan was dead.
Two follow-on effects:
qwen-autofix-recovery.yml(fix(ci): clone qwen-autofix into a recovery workflow entity #9482) was cloned on the theory that the workflow entity was wedged. The clone carried the same oversized file (518,544 bytes), so its dispatches queued identically and itsschedulenever fired once in nine hours.queueddispatch as in-flight, so it stopped re-dispatching:🫀 last scan signal: 2026-08-19T05:01:14Z (1107m ago), liveness-relevant in-flight: 1. Worth hardening separately (aqueuedrun with zero jobs for >N minutes is not in flight).The fix
.github/workflows/qwen-autofix.md. Each block leaves its opening lines plus aqwen-autofix.md#af-NNNpointer where it sat, so the YAML still reads top-to-bottom and the reasoning is one hop away. 518,055 → 426,437 bytes..github/scripts/check-workflow-size.shfails at 470,000 bytes, warns at 445,000, and runs in CI on every profile — a.github-only PR classifies asgithub_ci_onlyand skips thefull-only checks, which is exactly the PR that can trip this.scripts/tests/workflow-size.test.jspins the gate below GitHub's limit, every workflow file under the gate, the CI wiring, and pointer/section symmetry in both directions.Why this is safe
No executable line changes. Verified mechanically against the pre-change file:
run:strings are blanked (every job,if:,env:,concurrency:, matrix and output unchanged);run:scripts passbash -non both sides, and a line-by-line walk finds zero code-line drift — the only deletions anywhere are whole#comment lines (1,326 of them, 0 non-comment);#is data, not a comment — the extractor tracks heredoc state);2026-08-19: no-op comment forcing Actions to re-parse this fileline recorded a diagnosis we now know was wrong, and the corrected account replaces it in the file header.Sanitize workspace git configin three jobs) share one pointer id, so the byte-equality contract between the copies still holds.scripts/tests/qwen-autofix-workflow.test.jspasses (237 tests with the new suite). Two assertions in it pinned a rationale rather than a code line; they now read the design record.npm run test:scriptsis green apart fromqwen-pr-review-workflow.test.js, which fails identically onorigin/mainin this environment (root-user sudo probe).actionlint, shellcheck, yamllint and prettier all pass.
After merge
The zombie
queueddispatches (32203631619,32206055039,32217861831,32259801409, plus the two recovery-clone runs) still need cancelling — until they clear, Fleet Shepherd's liveness lever stays wedged atin-flight: 1.中文说明
故障
GitHub 不会为超过 500 KB(512,000 字节)的 workflow 文件启动 run(官方限制),而且失败是静默的:没有 annotation、没有失败的 run、没有 workflow 被禁用的提示。
qwen-autofix.yml在 2026-08-19 00:17 UTC 越过这条线,autofix/takeover 循环随之停摆一天。a4a3850fe5(#9329)846fc05461(#9386)4154bd7457(#9479)症状看起来像 Actions 平台故障,所以花了一天才定位:
schedule(*/10)issue_commentissuesworkflow_dispatchqueued、零 job,API 也取消不掉pull_request_review最后一行正是陷阱所在:PR 事件是从 PR 自己的分支解析 workflow 文件的,而那些分支上是更早、更小的版本 —— 08-19 21:06 成功的那次 run 用的是 476,244 字节的副本。于是循环一边持续产出绿色 run,一边所有定时扫描已经死透。
两个衍生问题:
qwen-autofix-recovery.yml(fix(ci): clone qwen-autofix into a recovery workflow entity #9482)当时是按"workflow entity 被 backend 卡死"的判断克隆出来的。克隆体带着同样超限的文件(518,544 字节),所以它的 dispatch 一样排队卡死,九小时里schedule一次都没触发。queueddispatch 计为 in-flight,于是不再补发扫描:🫀 last scan signal: 2026-08-19T05:01:14Z (1107m ago), liveness-relevant in-flight: 1。这一点值得单独加固(queued且零 job 超过 N 分钟的 run 不应算作在飞)。修复
.github/workflows/qwen-autofix.md。每个块在原处保留开头几行加一个qwen-autofix.md#af-NNN指针,YAML 仍能顺读,理由只隔一跳。518,055 → 426,437 字节。.github/scripts/check-workflow-size.sh在 470,000 字节失败、445,000 字节告警,并且在 CI 的所有 profile 下都运行 —— 只改.github的 PR 会被分类为github_ci_only,跳过所有full专属检查,而那恰恰是最可能触发此问题的 PR。scripts/tests/workflow-size.test.js固定住门禁值低于 GitHub 限制、每个 workflow 文件低于门禁、CI 挂载方式,以及指针与章节的双向一致性。为什么是安全的
没有任何可执行行发生变化。与改动前的文件做了机械比对:
run:字符串置空后,两边 YAML 解析出完全相同的文档(所有 job、if:、env:、concurrency:、matrix 与 output 均未变);run:脚本两侧全部通过bash -n,逐行走查零代码行漂移 —— 全文件被删除的行只有整行#注释(1,326 行,非注释行 0 行);#开头的行是数据不是注释,提取器跟踪 heredoc 状态);2026-08-19: no-op comment forcing Actions to re-parse this file这条记录的是一个现已证伪的诊断,文件头部改用更正后的说明取代它;Sanitize workspace git config)共用同一个指针 id,因此副本之间的字节相等契约依然成立。scripts/tests/qwen-autofix-workflow.test.js通过(连同新增用例共 237 项)。其中两条断言锁定的是理由而非代码行,现改为读取设计记录。npm run test:scripts除qwen-pr-review-workflow.test.js外全绿,而该文件在本环境下于origin/main上同样失败(root 用户的 sudo 探针)。actionlint、shellcheck、yamllint、prettier 均通过。
合并之后
僵尸
queueddispatch(32203631619、32206055039、32217861831、32259801409,以及 recovery 克隆的两个 run)仍需取消 —— 在它们清掉之前,Fleet Shepherd 的 liveness lever 会一直卡在in-flight: 1。