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
7 changes: 6 additions & 1 deletion .github/workflows/qwen-code-pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,12 @@ jobs:
echo "PR #${PR_NUMBER} is ${PR_STATE}; skipping acknowledgement." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
ACK_BODY="<!-- qwen-review-ack -->_Qwen Code review request accepted. Review is queued in [workflow run](${RUN_URL})._"
# Blank line after the marker, or none of the prose below renders. A
# line opening with `<!--` starts an HTML block that runs to the line
# containing the closing delimiter, and the REST of that line stays
# inside it — so gluing the text on shipped it as raw source with a
# dead link. Verified against GitHub's own renderer.
ACK_BODY="$(printf '<!-- qwen-review-ack -->\n\n_Qwen Code review request accepted. Review is queued in [workflow run](%s)._' "$RUN_URL")"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] No test pins the %s"$RUN_URL" weaving on this changed line — the new regression test constrains only the marker/body separator. Failure scenario: a future edit drops %s (or the argument) → bash printf with a leftover argument and no conversion spec exits 0 under set -euo pipefail and emits [workflow run]() → the ack comment ships with an empty workflow-run link while the whole suite stays green (verified in bash at this commit). Because issue_comment-triggered reviews never appear in the PR's checks list, the author silently loses the only pointer to their review run — the exact defect this PR fixes, reintroduced with no red test. Suggested fix: assert in this file's source-level style that the printf carrying the marker contains %s and is passed "$RUN_URL" (stronger: execute the ack script with a stubbed gh and assert the captured body contains the marker, a blank line, and the run URL).

中文说明

本行改动中 %s"$RUN_URL" 的编织没有任何测试固定——新增的回归测试只约束了标记与正文之间的分隔。失败场景:未来的编辑删掉 %s(或参数)→ bash printf 带着多余参数且无转换说明符,在 set -euo pipefail 下仍以 0 退出并输出 [workflow run]() → ack 评论带着空的 workflow-run 链接发出,而整个套件保持全绿(已在本提交的 bash 中验证)。由于 issue_comment 触发的评审从不出现在 PR 的 checks 列表中,作者会悄然失去指向其评审 run 的唯一入口——这正是本 PR 修复的缺陷,且无测试变红地被重新引入。建议修复:以本文件现有的源码级断言风格,断言承载标记的 printf 含有 %s 且传入了 "$RUN_URL"(更强:用打桩的 gh 执行 ack 脚本,断言捕获的 body 含标记、空行与 run URL)。

— qwen3.8-max via Qwen Code /review (v0.21.7)

EXISTING_ACK_ID="$(
# -F would otherwise make gh api default to POST.
gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" \
Expand Down
138 changes: 133 additions & 5 deletions scripts/tests/qwen-pr-review-workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ const workflow = readFileSync(
'.github/workflows/qwen-code-pr-review.yml',
'utf8',
);
const workflowsDir = '.github/workflows';
const workflowFiles = readdirSync(workflowsDir).filter((f) =>
/\.ya?ml$/.test(f),
);

function runReviewStep() {
const doc = parse(workflow);
Expand Down Expand Up @@ -2175,14 +2179,12 @@ describe('workflow expression length', () => {
// length 21000` (e.g. run 31239579253). CI stayed green the whole time — no
// test covered this, which is why it is covered here.
const LIMIT = 21000;
const dir = '.github/workflows';
const files = readdirSync(dir).filter((f) => /\.ya?ml$/.test(f));

it('keeps every templated run block under the limit', () => {
expect(files.length).toBeGreaterThan(0);
expect(workflowFiles.length).toBeGreaterThan(0);
const over = [];
for (const file of files) {
const doc = parse(readFileSync(join(dir, file), 'utf8'));
for (const file of workflowFiles) {
const doc = parse(readFileSync(join(workflowsDir, file), 'utf8'));
for (const [jobId, job] of Object.entries(doc?.jobs ?? {})) {
for (const step of job?.steps ?? []) {
const body = step?.run;
Expand Down Expand Up @@ -2274,3 +2276,129 @@ describe('command shape matching', () => {
expect(stripCr).toBeGreaterThan(firstLine);
});
});

describe('bot comment markers', () => {
// A line that opens with `<!--` starts an HTML block, and that block runs to
// the line holding the closing delimiter INCLUSIVE — the rest of that line
// stays inside it and is never parsed as Markdown. The queued-ack comment
// glued its prose straight onto the marker and reached every PR as raw
// source with a dead link. Measured through GitHub's own renderer
// (POST /markdown, mode=gfm): marker+text -> 0 <a>/0 <em>; marker+"\n"+text
// and marker+"\n\n"+text -> 1 <a>/1 <em>.
//
// The rule keys off ONE thing: a marker that opens a string literal, and

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The "marker opens a string literal" rule misses the same bug class when the marker sits mid-literal but at the start of a rendered line. Failure scenario: BODY="$(printf 'Thanks for the review!\n\n<!-- qwen-review-ack -->_queued._')"offenders=[] because the char before <!-- is a space, yet after printf expansion the marker lands at line start with glued prose — the exact defect this PR fixes, shipped with the regression test green (confirmed by running the guard verbatim; no current workflow has this shape, so this is a guard-coverage gap). Suggested fix: state this gap in the known-gap comment, or walk backward to the nearest literal-internal \n (in printf/$' contexts) and flag glued prose when the marker starts a rendered line.

中文说明

"标记打开字符串字面量"规则会漏掉同一缺陷类:标记位于字面量中间、却落在渲染行的行首。失败场景:BODY="$(printf 'Thanks for the review!\n\n<!-- qwen-review-ack -->_queued._')"offenders=[],因为 <!-- 前的字符是空格;但 printf 展开后标记落在行首且正文粘接——正是本 PR 修复的缺陷,在回归测试全绿时发出(已用原样守卫运行确认;当前没有 workflow 是这种形状,属于守卫覆盖缺口)。建议修复:在已知缺口注释中声明该缺口,或回溯到字面量内最近的 \n(printf/$' 上下文中),当标记位于渲染行首时标记粘接正文。

— qwen3.8-max via Qwen Code /review (v0.21.7)

// what remains inside that literal after it. That is what distinguishes
// BUILDING a comment body from merely REFERENCING a marker — `jq
// contains("<!-- m -->")` and `printf '<!-- m -->' "$VAR"` leave nothing
// after the marker and are fine, while `="<!-- m -->prose"` does not. The
// scan is bounded to the marker's physical line: a glued body is by
// definition on that line, and searching past it would couple the guard to
// unrelated quotes elsewhere in the file — a doc example quoting an unclosed
// `--body "<!-- m -->` would break the moment any later line gained a `"`.
//
// Known gaps, stated rather than papered over: bodies split across printf
// arguments (`printf '%s%s' '<!-- m -->' 'prose'`) — detecting them means
// modelling which literal is the format string, and every cheap
// approximation flagged the legitimate `printf '<!-- m -->' "$VAR"` form;
// bodies assembled across statements or files (one `echo` per line into a
// `--body-file`); markers at physical line start (heredocs, YAML block
// scalars); markers mid-literal that only land at a rendered line start
// after `\n` expansion (`printf 'x\n<!-- m -->prose'`); multi-line literals
// whose closing quote sits on a later line; a line-wrapped printf whose
// format opens with the marker (the `\n` exemption reads one physical
// line); continuations after a marker-ending literal other than an
// adjacent quoted literal or bare `$(…)` — `$VAR` expansion, unquoted
// words, `$'…'` literals, backtick substitution, backslash-newline, and
// text after the closing `)` of a wrapping subshell assignment
// (`BODY="$(printf '<!-- m -->')prose"`); closing that shape needs a
// subshell discriminator that false-positives on legitimate jq
// `contains("<!-- … -->"))` references inside `$(…)` assignments;
// trailing end-of-line comments — the `#` skip only fires when the
// comment OPENS the physical line, so a glued marker quoted in a
// trailing comment is still flagged; YAML double-quoted scalars
// (`body: "<!-- m -->\nprose"`) — YAML expands `\n`, but the scanner
// cannot cheaply tell a YAML scalar from a shell literal where `\n`
// stays literal; and marker-headed bodies built outside
// `.github/workflows` — the `.github/scripts/*.mjs` comment builders
// (template literals and pushed marker lines) are not scanned. All are
Comment on lines +2321 to +2323

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The enumeration scopes builder-pattern gaps to bodies built outside .github/workflows, but a live builder inside the scanned directory is equally invisible to the guard: pr-force-push-reminder.yml holds its marker only as a standalone JS constant (line 101) and assembles the body with [MARKER, '', english, …].join('\n') — the scanner sees no glue site in that file, and "built outside .github/workflows … not scanned" implies everything inside is covered. — Failure scenario: probe-verified — changing that join separator to '' makes the emitted body start <!-- pr-force-push-reminder -->Please do not rebase… (prose glued onto the marker — the exact dead-rendering regression this PR fixes), while both marker tests still pass. — Suggested fix: extend this enumeration to cover marker constants joined/concatenated to prose at runtime inside workflow files (naming the pr-force-push-reminder.yml array-join builder), or add a targeted assertion pinning that file's MARKER, '', separator element.

中文说明

[建议] 枚举把"拼装器模式"的缺口限定在 .github/workflows 之外构造的正文,但扫描目录内部同样存在一个对守卫不可见的现存拼装器:pr-force-push-reminder.yml 只把 marker 作为独立 JS 常量(第 101 行)持有,正文用 [MARKER, '', english, …].join('\n') 拼装——扫描器在该文件里看不到任何粘接点,而"在 .github/workflows 之外构造……不被扫描"的措辞暗示目录内的一切都在覆盖范围内。— 失败场景:已用探针验证——把该 join 分隔符改成 '' 后,发出的正文以 <!-- pr-force-push-reminder -->Please do not rebase… 开头(正文直接粘在标记上——正是本 PR 修复的"死渲染"回归),而两个 marker 测试仍然通过。— 建议修复:把此枚举扩展为覆盖 workflow 文件内部在运行时经 join/拼接与正文相连的 marker 常量(点名 pr-force-push-reminder.yml 的数组 join 拼装器),或者增加一个针对性断言,固定该文件中 MARKER, '', 的分隔元素。

— qwen3.8-max via Qwen Code /review (v0.21.8)

// latent — nothing glues a marker today.

it('never glues prose onto a comment marker, in any workflow', () => {
expect(workflowFiles.length).toBeGreaterThan(0);
const offenders = [];
for (const file of workflowFiles) {
const text = readFileSync(join(workflowsDir, file), 'utf8');
// The class excludes `\n` so a `<!--` inside a nearby comment cannot
// let one match span lines, swallow the real marker, and get discarded
// by the comment skip below — the guard would then pass with the very
// regression present. `>` stays allowed inside a marker (lazy match to
// the first `-->` on the line) so arrow-style markers are covered too.
const re = /<!--[^\n]*?-->/g;
let m;
while ((m = re.exec(text)) !== null) {
const lineStart = text.lastIndexOf('\n', m.index) + 1;
const prefix = text.slice(lineStart, m.index);
// Prose in a YAML or shell comment never reaches a comment body.
if (/^\s*#/.test(prefix)) continue;
Comment on lines +2341 to +2342

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The comment skip only fires for comments that OPEN a physical line; an end-of-line YAML or shell comment containing a quoted marker with glued prose is still scanned and flagged, contradicting the rationale comment above it. Probe-verified against the verbatim scan logic: foo: bar # example: '<!-- m -->prose' and echo hi # docs '<!-- m -->prose' here are both pushed into offenders, while the full-line-comment control is correctly skipped. The limit is absent from the known-gaps enumeration. — Failure scenario: a future workflow edit documents a glued-marker shape in a trailing inline comment — e.g. noting the exact regression this PR fixes, the way this PR's own workflow comment does — → CI fails on a false "glued prose" accusation for prose that sits in a comment and cannot reach any comment body.

Fix: declare the limit in the known-gaps comment alongside its siblings, or strip trailing-comment regions before scanning (a # starts a comment only when preceded by whitespace and not inside an open literal).

中文说明

注释跳过只对"以注释开头"的物理行生效;行尾的 YAML 或 shell 注释中若包含带粘接正文的引号标记,仍会被扫描并标记,与上方的理由注释相矛盾。已用逐字提取的扫描逻辑验证:foo: bar # example: '<!-- m -->prose'echo hi # docs '<!-- m -->prose' here 都会进入 offenders,而整行注释的对照组被正确跳过。该限制不在 known-gaps 枚举中。失败场景:未来某次编辑在行尾内联注释里记录粘接标记的形状——例如像本 PR 自己的 workflow 注释那样注明它所修复的这个回归——→ CI 会误报"粘接正文",尽管注释里的正文根本不可能进入任何评论 body。修复:把该限制补进 known-gaps 注释,或在扫描前剥掉行尾注释区域(仅当 # 前有空白且不在未闭合字面量内部时才视为注释起点)。

— qwen3.8-max via Qwen Code /review (v0.21.8)

const quote = m.index === lineStart ? null : text[m.index - 1];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] Markers at physical line start are skipped unconditionally (quote === null), which puts heredoc- and YAML-block-scalar-built comment bodies outside the guard. Failure scenario: moving the ack body into $(cat <<'BODY' … <!-- qwen-review-ack -->_Qwen Code… BODY)offenders=[] even though GitHub renders that line as raw source with a dead link (confirmed by running the guard verbatim). Heredocs are already a common multi-line idiom in this repo's workflows (11 <<' uses across 6 files), so a routine refactor resurrects this PR's exact regression with the guard green. The known-gap comment declares the printf-arguments gap but not this one. Suggested fix: extend the scan to line-start markers inside heredocs opened in a run: block, or declare this gap in the same comment block so the test name does not promise coverage the rule does not provide.

中文说明

物理行首的标记被无条件跳过(quote === null),这使得 heredoc / YAML 块标量构造的评论 body 完全落在守卫之外。失败场景:把 ack body 移入 $(cat <<'BODY' … <!-- qwen-review-ack -->_Qwen Code… BODY)offenders=[],尽管 GitHub 会把该行渲染为带死链接的原始文本(已用原样守卫运行确认)。heredoc 已是本仓库 workflows 中常见的多行写法(6 个文件 11 处 <<'),一次常规重构就会让本 PR 修复的回归在守卫全绿时复活。已知缺口注释声明了 printf 参数拆分缺口,但没有声明这一个。建议修复:把扫描扩展到 run: 块中 heredoc 里的行首标记,或在同一注释块中声明该缺口,使测试名称不承诺规则并未提供的覆盖。

— qwen3.8-max via Qwen Code /review (v0.21.7)

// Only a marker that OPENS a string literal can be building a body.
if (quote !== "'" && quote !== '"') continue;
Comment on lines +2343 to +2345

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] Whitespace between the opening quote and the marker evades this check (text[m.index - 1] is a space, not a quote), but GFM/CommonMark still open an HTML block on a marker line with up to 3 leading spaces (and an indented code block at 4+) — the exact regression this guard exists to catch ships green, and the shape is absent from the known-gaps enumeration. — Failure scenario: a future edit writes BODY=" <!-- m -->_prose [workflow run](%s)._" with one cosmetic space. Probe-verified: a verbatim replica of this scanner passes the 1/3/4-space shapes, while marked and markdown-it emit 0 <a>/0 <em> for 1–3 leading spaces — identical to the original bug — and raw <pre><code> at 4. — Suggested fix: treat whitespace-only space between the opening quote and the marker as still opening the literal — match the end of prefix against /(['"])[ \t]*$/ and use the captured quote. Probe-verified caveat: also allow [ \t]* before the exemption's trailing ['"]$ anchor, or a format-position space before the marker becomes a new false positive; alternatively declare the shape in known-gaps.

中文说明

[建议] 开引号与标记之间的空白可以绕过这一检查(此时 text[m.index - 1] 是空格而不是引号),但 GFM/CommonMark 对行首至多 3 个空格的标记行仍会开启 HTML block(4 个及以上则是缩进代码块)——本守卫要拦截的回归会原样绿灯上线,且该形状不在 known-gaps 枚举中。— 失败场景:未来某次编辑写出 BODY=" <!-- m -->_prose [workflow run](%s)._"(一个无意义的空格)。已用探针验证:逐字复制的扫描器对 1/3/4 空格形状全部放行,而 marked 与 markdown-it 在 1–3 个前导空格下输出 0 个 <a>/0 个 <em>——与原始缺陷完全一致——4 个空格时则是原始 <pre><code>。— 建议修复:把"开引号与标记之间仅有空白"仍视为打开字面量——用 /(['"])[ \t]*$/ 匹配 prefix 末尾并取捕获的引号。探针验证的注意事项:豁免条件里行尾的 ['"]$ 锚点前也要允许 [ \t]*,否则格式串位置在标记前带空格会变成新的误报;或者把该形状声明进 known-gaps。

— qwen3.8-max via Qwen Code /review (v0.21.8)

const rest = text.slice(m.index + m[0].length);
const lineEnd = rest.indexOf('\n');
const line = lineEnd === -1 ? rest : rest.slice(0, lineEnd);
const end = line.indexOf(quote);
// No closing quote on this line means either the marker ends the line
// inside a multi-line literal (a real newline separates the body,
// which renders) or the quote is prose in a doc example — neither
// glues anything ON the marker's line.
if (end === -1) continue;
let glued = line.slice(0, end);
if (glued === '') {
// The literal ended at the marker — but an adjacent literal on the
// same line concatenates onto it at runtime, and so does an
// unquoted `$(…)` (its output is invisible to this scan).
const after = line.slice(end + 1);
if (after[0] === "'" || after[0] === '"') {
const q2 = after[0];
const e2 = after.slice(1).indexOf(q2);
glued = e2 === -1 ? '' : after.slice(1, 1 + e2);
} else if (after[0] === '$' && after[1] === '(') {
glued = after;
}
Comment on lines +2365 to +2367

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The same-line continuation model after an empty marker literal only recognizes a following quoted literal or $(…); every other continuation bash concatenates at runtime passes the guard. Probe-verified shapes (guard logic run verbatim → offenders=[]; bash → glued, exit 0): BODY="<!-- m -->"$PROSE ($VAR expansion), BODY='<!-- m -->'prose (unquoted word), BODY='<!-- m -->'$'prose' (ANSI-C literal), backtick substitution, BODY="<!-- m -->"\ + newline + "prose" (no-space backslash continuation), and BODY="$(printf '<!-- m -->')prose" (text after the wrapping subshell's ) — proven by running the actual guard test against a fixture workflow). None is declared in the known-gaps comment, which presents the adjacency model as deliberate and complete. (Aggregates three independently found, probe-verified findings.) — Failure scenario: each shape is one keystroke from this PR's own ACK_BODY="$(printf '…')" pattern → the marker glues to prose at runtime → the exact raw-source/dead-link bug this PR fixes ships with the guard reporting offenders === [].

Fix options: declare these shapes in known-gaps, or treat any non-whitespace continuation outside the marker literal as suspect. Caution if closing the hole: a naive "any text after )" rule produced 11 false positives on existing jq contains("<!-- … -->")) references during probing — the discriminator must require the marker literal to sit inside a subshell-wrapped assignment (="(…" in the prefix).

中文说明

空标记字面量之后的同行续接模型只识别紧随的引号字面量或 $(…);其余任何会被 bash 在运行时拼接的续接形式都能通过守卫。已用逐字提取的守卫逻辑 + bash 逐一验证(守卫 offenders=[],bash 实际粘接且 exit 0):BODY="<!-- m -->"$PROSE($VAR 展开)、BODY='<!-- m -->'prose(未加引号的词)、BODY='<!-- m -->'$'prose'(ANSI-C 字面量)、反引号替换、BODY="<!-- m -->"\ + 换行 + "prose"(无空格反斜杠续行)、以及 BODY="$(printf '<!-- m -->')prose"(文本落在包裹子shell 的 ) 之后——通过向守卫测试投放 fixture workflow 实证)。known-gaps 注释未声明其中任何一种,而该注释把邻接模型表述为刻意且完备的设计。(本条聚合了三条独立发现、均经探针验证的 finding。)失败场景:上述每种形状距离本 PR 自己的 ACK_BODY="$(printf '…')" 模式都只有一步之遥 → 运行时标记与正文粘接 → 本 PR 所修复的「原始文本、死链接」缺陷在守卫全绿的情况下再次上线。修复选项:把这些形状声明进 known-gaps,或把标记字面量之外任何非空白续接都视为可疑。若要堵洞请注意:探针验证时,朴素的") 后任何文本"规则会在现有 jq contains("<!-- … -->")) 引用上产生 11 个误报——判别条件必须要求标记字面量位于子shell 包裹的赋值内部(前缀中含 ="(…")。

— qwen3.8-max via Qwen Code /review (v0.21.8)

}
if (glued === '') continue;
// The two-character `\n` escape separates only where the shell
// expands it: a printf format string or ANSI-C `$'…'` opened at the
// END of the prefix — an unrelated printf earlier on the same line
// must not bless a plain double-quoted assignment, where `\n` stays
// a literal backslash-n and the prose stays on the marker's line.
if (
glued.startsWith('\\n') &&
/printf\s+(?:-\S+\s+(?:\S+\s+)?|--\s+)?['"]$|\$'$/.test(prefix)
) {
continue;
Comment on lines +2375 to +2379

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The \n exemption models incompletely where a backslash-n escape actually separates marker from body — three probe-verified shapes flag correctly-rendering bodies (spurious CI red), and none is declared in the known-gaps enumeration (which documents the analogous YAML case): (1) jq/JSON-string escape — BODY="$(jq -rn '"<!-- m -->\n" + $body')": JSON's \n becomes a real newline in jq output (verified), the prose renders on its own line, but the prefix ends jq -rn '" and matches neither exemption branch (a fixture reproduced the failure); (2) printf '%b' argument position — BODY="$(printf '%b' '<!-- m -->\nprose')": bash expands escapes in a %b argument (od-verified real newline), but the marker literal is not in the format position, so it is flagged; (3) insignificant whitespace before the escape — printf '<!-- m --> \nprose': a stray trailing space after the marker defeats glued.startsWith('\\n') although the HTML block still closes on the marker line and the prose renders (A/B probe: spaced variant flagged, unspaced passes). — Suggested fix: widen the exemption (/^\s*\\n/ instead of startsWith('\\n') under the same prefix condition; add a '%b'-argument alternative), and declare the jq/JSON shape in the known-gaps comment beside the YAML case — or declare all three if the strictness is deliberate.

中文说明

[建议] \n 豁免对"反斜杠 n 实际上把标记与正文分开"的情形建模不完整——已用探针验证的三种形式会把渲染正常的正文判成违规(CI 误报红),且都未在 known-gaps 枚举中声明(枚举里已记录了类似的 YAML 情形):(1) jq/JSON 字符串转义——BODY="$(jq -rn '"<!-- m -->\n" + $body')":JSON 的 \n 在 jq 输出中变成真实换行(已验证),正文在独立行上正常渲染,但 prefix 以 jq -rn '" 结尾,两个豁免分支都不匹配(fixture 复现了失败);(2) printf '%b' 参数位——BODY="$(printf '%b' '<!-- m -->\nprose')":bash 会对 %b 参数展开转义(od 验证为真实换行),却因标记字面量不在格式串位置而被标记;(3) 转义前的无关空白——printf '<!-- m --> \nprose':标记后一个多余的行尾空格使 glued.startsWith('\\n') 失效,但 HTML block 仍在标记行结束、正文照常渲染(A/B 探针:带空格变体被标记,不带空格通过)。— 建议修复:放宽豁免(同一 prefix 条件下用 /^\s*\\n/ 代替 startsWith('\\n');为 '%b' 参数位增加一个豁免分支),并把 jq/JSON 形式与 YAML 情形并列补进 known-gaps 注释——如果刻意保持严格,则把三种形式都声明出来。

— qwen3.8-max via Qwen Code /review (v0.21.8)

}
offenders.push(
`${file}: ${text.slice(m.index, m.index + 56).split('\n')[0]}`,
);
}
}
expect(offenders).toEqual([]);
});

it('pins the workflow-run URL into the ack printf', () => {
// bash printf with a leftover argument and no conversion spec exits 0
// under `set -euo pipefail` and emits `[workflow run]()`, so nothing
// else catches a dropped `%s` or `"$RUN_URL"` on the ack line. Assert
// the link shape, not bare co-existence: a `%s` displaced out of the
// parens keeps both pieces on the line and re-ships the dead link.
const ackLine = workflow
.split('\n')
.find(
(l) => l.includes('printf') && l.includes('<!-- qwen-review-ack -->'),
);
expect(ackLine).toBeDefined();
expect(ackLine).toContain('[workflow run](%s)');
expect(ackLine).toContain('"$RUN_URL"');
Comment on lines +2400 to +2402

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Suggestion] The URL-pin test asserts %s and "$RUN_URL" merely co-exist on the ack line, not that the URL is woven into the markdown link — a displaced %s or marker-as-argument refactor passes both tests and re-ships the dead-link comment this PR fixes.

Failure scenario: a future edit rewrites the ack line to ACK_BODY="$(printf '%s%s' '<!-- qwen-review-ack -->' "$RUN_URL")" (marker moved out of the format into its own argument — the natural refactor, since $RUN_URL is already an argument) or moves %s outside the link parens ([workflow run]%s._). Both forms keep %s and "$RUN_URL" somewhere on the line, so the two toContain assertions pass. Real bash confirms the output renders [workflow run]https://… with no parens / the URL glued onto the marker line — GitHub's HTML block swallows the line, the comment ships as raw source with a dead link again, and CI stays green.

Suggested change
expect(ackLine).toBeDefined();
expect(ackLine).toContain('%s');
expect(ackLine).toContain('"$RUN_URL"');
expect(ackLine).toContain('[workflow run](%s)');
中文说明

URL 固定测试只断言 %s"$RUN_URL" 同时出现在 ack 行上,并未断言 URL 真的织入了 markdown 链接——一旦 %s 被移出链接括号、或标记被改成 printf 的独立参数,两个 toContain 断言仍然通过,死链评论会再次发出。失败场景:把 ack 行改写为 printf '%s%s' '<!-- qwen-review-ack -->' "$RUN_URL",或把 %s 移出括号。bash 实测输出为 [workflow run]https://…(无括号)或 URL 直接粘在标记行——GitHub 的 HTML block 吞掉整行,评论以原始文本发出且链接失效,CI 依旧全绿。建议改为断言链接形状,例如 expect(ackLine).toContain('[workflow run](%s)')

— DeepSeek/deepseek-v4-flash via Qwen Code /review (v0.21.8)

});
});
Loading