Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8b8dc72
feat(review): skip the automatic round when a synchronize only refres…
wenshao Aug 26, 2026
88fe914
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
wenshao Aug 26, 2026
fad703a
refactor(review): move the base-refresh gate body into .github/scripts
wenshao Aug 26, 2026
a7e8811
fix(review): tighten base-refresh gate certification per review feedback
qwen-code-dev-bot Aug 26, 2026
5ac05ba
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
wenshao Aug 27, 2026
21cce5f
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 27, 2026
3d449b8
fix(review): harden the base-refresh ledger lookup against bodyless r…
qwen-code-dev-bot Aug 27, 2026
90c99a7
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 28, 2026
4cf0f3a
fix(review): harden the base-refresh gate per round-2 findings (#10116)
qwen-code-dev-bot Aug 28, 2026
a81269d
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 28, 2026
a15bd5c
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 28, 2026
64fffbf
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 29, 2026
422a5e7
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 29, 2026
402bb22
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 29, 2026
cba5231
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 29, 2026
6e77b50
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 29, 2026
cf5dc5d
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 29, 2026
cad0cf0
fix(review): harden base-refresh gate certification and test isolation
qwen-code-dev-bot Aug 29, 2026
16b58ab
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 29, 2026
aae221b
Merge branch 'main' into feat/review-skip-base-refresh-only-sync
qwen-code-dev-bot Aug 30, 2026
c7499d5
fix(review): close planted-git-config class and marker fall-through i…
qwen-code-dev-bot Aug 30, 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
149 changes: 149 additions & 0 deletions .github/scripts/review-base-refresh-gate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env bash
# Decide whether an automatic `synchronize` review round may be skipped
# because the push only refreshed the base branch (#10111): an update-branch
# merge fires `synchronize` like any push, but a full automatic round costs
# hours for a head whose PR-side diff is unchanged.
#
# Two facts are certified before any review compute is spent: every
# first-parent commit since the head the last completed automatic round
# reviewed is a two-parent merge of the base branch, and the PR's own
# three-dot diff kept the same canonical digest — every changed and
# context byte is hashed after stripping only unstable diff metadata
# (index lines, hunk offsets), so an upstream edit touching the PR's own
# hunks (whitespace included) fails the equality and the full round runs.
# The reviewed head is the newest SUBMITTED ledger-marked review
# (APPROVED, CHANGES_REQUESTED, or COMMENTED, with a submitted_at) posted
# by the AUTHENTICATED account — resolved live via `gh api user`, same
# norm as the fallback dedup — so a participant posting the marker text
# in their own review, a PENDING draft, or a DISMISSED review can never
# certify a head this gate would skip.
#
# Fail-open contract: every probe error or unmatched shape records
# skip=false and the full round runs, and the script never exits non-zero —
# the caller treats a step failure as a pipeline failure worth a fallback
# comment, which a skipped gate is not.
#
# Outputs (GITHUB_OUTPUT): skip=true|false, reviewed_sha, reason.
set -uo pipefail

# Required environment, restated so a misconfigured caller dies naming the
# missing input instead of probing git with empty arguments.
PR_NUMBER="${PR_NUMBER:?}"
EVENT_HEAD_SHA="${EVENT_HEAD_SHA:?}"
BASE_REF="${BASE_REF:?}"
RUN_URL="${RUN_URL:?}"
GITHUB_REPOSITORY="${GITHUB_REPOSITORY:?}"
GITHUB_OUTPUT="${GITHUB_OUTPUT:?}"
GITHUB_STEP_SUMMARY="${GITHUB_STEP_SUMMARY:?}"

SKIP=false
REVIEWED_SHA=''
REASON=''

# Canonical digest of the diff between two commits: every changed and
# context byte is hashed, stripping only unstable metadata (index lines,
# hunk offsets). `git patch-id` is whitespace-insensitive and would
# certify an indentation-only rewrite of PR-owned lines.
diff_digest() {
local diff
diff="$(git diff "$1" "$2" 2>/dev/null)" || return 1
[[ -n "${diff}" ]] || return 0
printf '%s\n' "${diff}" |
sed -E '/^index [0-9a-f]+\.\.[0-9a-f]+/d; /^@@ /d' |
git hash-object --stdin
}

decide() {
REASON='pr head fetch failed'
git fetch --no-tags --quiet origin "refs/pull/${PR_NUMBER}/head" || return

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.

Deferred to the next round on round-budget grounds — not disagreement; the finding is verified real (same disposition as this finding's sibling threads). The uploadpack entrance reproduces as described, and the structural closure (hardened wrapper/workspace sanitization with --upload-pack=git-upload-pack pinned, config isolation, grafts fail-open, per-channel sentinels) is a dedicated work item that exceeds this round's budget — this round ships four verified fixes (R5-3, R7-1, R3-3, R5-2) rather than a partial per-channel patch.

中文说明

按轮次预算延后至下一轮——并非不同意;该发现已核实为真(与本发现同族线程同一处置)。uploadpack 入口按描述复现;结构性封闭(加固包装/工作区净化:钉住 --upload-pack=git-upload-pack、配置隔离、grafts 向开放侧倒、每通道哨兵)是一项超出本轮预算的专门工作——本轮已落地四项已验证修复(R5-3、R7-1、R3-3、R5-2),不做逐通道的局部修补。

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.

Deferred to the next round on round-budget grounds — not disagreement; the finding is verified real (same disposition as this finding's sibling threads). The live-today entrances reproduce; the structural fix (workspace-wide sanitization/hardened wrapper: config isolation, hooks/fsmonitor disabling, --upload-pack pinning, grafts fail-open, per-channel sentinels) is a dedicated work item exceeding this round's budget, which ships R5-3/R7-1/R3-3/R5-2 with red-before witnesses instead of a partial patch.

中文说明

按轮次预算延后至下一轮——并非不同意;该发现已核实为真(与本发现同族线程同一处置)。当前即为活通道的入口均复现;结构性修复(全工作区净化/加固包装:配置隔离、禁用 hooks/fsmonitor、钉住 --upload-pack、grafts 向开放侧倒、每通道哨兵)是一项超出本轮预算的专门工作;本轮改为落地带"修复前为红"见证的 R5-3/R7-1/R3-3/R5-2,不做局部修补。

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.

Deferred to the next round on round-budget grounds — not disagreement; the finding is verified real (same disposition as this finding's sibling threads). The insteadOf+sshCommand, grafts, and diff.context entrances reproduce as described; the structural closure this finding asks for is a dedicated work item exceeding this round's budget. This round ships R5-3/R7-1/R3-3/R5-2 with red-before witnesses; the hardening round follows with one executed sentinel per channel.

中文说明

按轮次预算延后至下一轮——并非不同意;该发现已核实为真(与本发现同族线程同一处置)。insteadOf+sshCommand、grafts、diff.context 入口按描述复现;本发现要求的结构性封闭是一项超出本轮预算的专门工作。本轮落地带"修复前为红"见证的 R5-3/R7-1/R3-3/R5-2;加固轮随后进行,并为每个通道提供一个已执行哨兵。

REASON='event head not reachable from the PR head ref'
git cat-file -e "${EVENT_HEAD_SHA}^{commit}" 2>/dev/null || return
REASON='base branch ref unavailable'
if ! git rev-parse -q --verify "origin/${BASE_REF}^{commit}" >/dev/null; then
git fetch --no-tags --quiet origin "${BASE_REF}" || return

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.

Deferred to the next round on round-budget grounds — not disagreement; the finding is verified real (same disposition as this finding's sibling threads). The reference-transaction hook entrance is re-confirmed on the fallback fetch; the structural closure is a dedicated work item exceeding this round's budget, which ships R5-3/R7-1/R3-3/R5-2 with red-before witnesses instead of a partial per-channel patch.

中文说明

按轮次预算延后至下一轮——并非不同意;该发现已核实为真(与本发现同族线程同一处置)。reference-transaction 钩子入口在回退 fetch 上再次确认;结构性封闭是一项超出本轮预算的专门工作;本轮改为落地带"修复前为红"见证的 R5-3/R7-1/R3-3/R5-2,不做逐通道的局部修补。

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.

Deferred to the next round on round-budget grounds — not disagreement; the finding is verified real (same disposition as this finding's sibling threads). Exactly three channels are hardened today, and the stale-origin/<base>-ref class reproduces as described (with the disclosed reachability caveat); the structural closure — wiring resanitize-git-config.sh (or an equivalent workspace-wide git-state reset) into this workflow before the gate step — is a dedicated work item exceeding this round's budget. This round ships R5-3/R7-1/R3-3/R5-2 with red-before witnesses.

中文说明

按轮次预算延后至下一轮——并非不同意;该发现已核实为真(与本发现同族线程同一处置)。今天恰有三个通道被加固,过期的 origin/<base> 引用类按描述复现(已披露的可达性限定不变);结构性封闭——把 resanitize-git-config.sh(或等效的全工作区 git 状态重置)接入本 workflow、在门步骤之前运行——是一项超出本轮预算的专门工作。本轮落地带"修复前为红"见证的 R5-3/R7-1/R3-3/R5-2。

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.

Deferred to the next round on round-budget grounds — not disagreement; the finding is verified real (same disposition as this finding's sibling threads). The grafts entrance reproduces as described at round 11 (re-parented walk + falsified merge-base → skip=true, under the disclosed reachability conditions); the structural closure (workspace-wide git-state sanitization before the gate, including grafts/hooks/config/refs reset) is a dedicated work item exceeding this round's budget. This round ships R5-3/R7-1/R3-3/R5-2 with red-before witnesses.

中文说明

按轮次预算延后至下一轮——并非不同意;该发现已核实为真(与本发现同族线程同一处置)。grafts 入口按描述在第 11 轮复现(重排父系的行走 + 被伪造的 merge-base → skip=true,在已披露的可达性条件下);结构性封闭(门运行前对整个工作区做 git 状态净化,含 grafts/钩子/配置/引用重置)是一项超出本轮预算的专门工作。本轮落地带"修复前为红"见证的 R5-3/R7-1/R3-3/R5-2。

git rev-parse -q --verify "origin/${BASE_REF}^{commit}" >/dev/null || return

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.

Deferred to the next round on round-budget grounds — not disagreement; the finding is verified real (same disposition as this finding's sibling threads). The reference-transaction hook entrance reproduces on the fallback fetch as described; the structural closure (route ref/object-touching invocations through the workflow's GIT_SAFE idiom, or sanitize the workspace before the gate) is a dedicated work item exceeding this round's budget. This round ships R5-3/R7-1/R3-3/R5-2 with red-before witnesses.

中文说明

按轮次预算延后至下一轮——并非不同意;该发现已核实为真(与本发现同族线程同一处置)。reference-transaction 钩子入口按描述在回退 fetch 上复现;结构性封闭(让触及引用/对象的调用走工作流的 GIT_SAFE 规范,或在门前净化工作区)是一项超出本轮预算的专门工作。本轮落地带"修复前为红"见证的 R5-3/R7-1/R3-3/R5-2。

fi

REASON='reviewed-head lookup failed'
local bot_login reviews
bot_login="$(gh api user --jq '.login')" && [[ -n "${bot_login}" ]] || return
reviews="$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/reviews" --method GET --paginate -F per_page=100)" || return
REVIEWED_SHA="$(
printf '%s' "${reviews}" | jq -sr --arg login "${bot_login}" '
[.[][]
| select(.user.login == $login)
| select(.state == "APPROVED" or .state == "CHANGES_REQUESTED"
or .state == "COMMENTED")
| select(.submitted_at != null)
| select(.body | contains("<!-- qwen-review-ledger"))]
Comment thread
yiliang114 marked this conversation as resolved.
Resolved
| last | .commit_id // empty'
)" || return
REASON='no completed automatic round on this PR'
[[ -n "${REVIEWED_SHA}" ]] || return
REASON='reviewed head not in the fetched history'
git cat-file -e "${REVIEWED_SHA}^{commit}" 2>/dev/null || return
REASON='reviewed head is not an ancestor of the pushed head'
git merge-base --is-ancestor "${REVIEWED_SHA}" "${EVENT_HEAD_SHA}" 2>/dev/null || return

# Bounded walk: a stale reviewed head must not buy an unbounded ancestry
# scan, and past ten first-parent steps this is not the cheap shape the
# gate exists for anyway.
local count c p2
REASON='commit walk failed'
count="$(git rev-list --first-parent --count "${REVIEWED_SHA}..${EVENT_HEAD_SHA}" 2>/dev/null)" || return
[[ "${count}" =~ ^[0-9]+$ ]] || return
REASON='no new commits since the reviewed head'
[[ "${count}" -ge 1 ]] || return
REASON="too many commits since the reviewed head (${count})"
[[ "${count}" -le 10 ]] || return
for c in $(git rev-list --first-parent "${REVIEWED_SHA}..${EVENT_HEAD_SHA}" 2>/dev/null); do
REASON="non-merge commit since the reviewed head: ${c}"
p2="$(git rev-parse -q --verify "${c}^2" 2>/dev/null)" || return
REASON="octopus merge since the reviewed head: ${c}"
if git rev-parse -q --verify "${c}^3" >/dev/null 2>&1; then return; fi
Comment thread
yiliang114 marked this conversation as resolved.
Resolved
REASON="merge of a non-base branch since the reviewed head: ${c}"
git merge-base --is-ancestor "${p2}" "origin/${BASE_REF}" 2>/dev/null || return

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.

Deferred to the follow-up queue — verified real, pairs with R2-4 (same disposition as this finding's sibling threads). The rewrite arm reproduces skip=true on the shipped script while the landed diff gains the dropped commit's content; the fix requires the writer-side base-commit field (outside this PR's footprint, packages/cli) plus the gate-side ancestor check. Both are recorded for the follow-up queue and ship together.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对(与本发现同族线程同一处置)。重写分支在线上脚本上复现 skip=true,同时落地 diff 新增了被丢弃提交的内容;修复需要写入端的 base 提交字段(packages/cli,在本 PR 足迹之外)加门侧祖先检查。两者已记录到后续队列并将一并落地。

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.

Deferred to the follow-up queue — verified real, pairs with R2-4 (same disposition as this finding's sibling threads). No gate-only fix exists; the reviewed base commit must ride the marker, and the writer change lives outside this PR's footprint (packages/cli). Tracked with R2-4's writer half; the gate-side ancestor check and the executed rebased_base shape land with it.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对(与本发现同族线程同一处置)。不存在仅门侧的修复;已评审的 base 提交必须由标记携带,而写入端改动位于本 PR 足迹之外(packages/cli)。已与 R2-4 的写入端一半一并跟踪;门侧祖先检查与已执行的 rebased_base 形态随其一并落地。

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.

Deferred to the follow-up queue — verified real, pairs with R2-4 (same disposition as this finding's sibling threads). The rewritten-base probe reproduces skip=true with gained landing content at this head. The base-identity binding must ride the ledger marker (writer change in packages/cli, outside this PR's footprint, respecting the marker's byte budget and shed cascade); it is recorded with R2-4's writer half and the gate-side check ships with it.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对(与本发现同族线程同一处置)。重写 base 探针在本 head 复现 skip=true 且落地内容新增。base 身份绑定必须由台账标记携带(写入端改动在 packages/cli,在本 PR 足迹之外,须遵守标记字节预算与丢弃级联);已与 R2-4 的写入端一半一并记录,门侧检查随其落地。

done

local mb_r mb_h digest_r digest_h
REASON='merge-base resolution failed'
mb_r="$(git merge-base "origin/${BASE_REF}" "${REVIEWED_SHA}" 2>/dev/null)" || return

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.

Deferred to the follow-up queue — verified real, pairs with R2-4 (same disposition as this finding's sibling threads). No gate-only fix exists: the reviewed base COMMIT must ride the ledger marker, and that writer change lives in packages/cli, outside this PR's footprint. Tracked with R2-4's writer half; the gate-side ancestor check and the executed rebased_base shape land with it.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对(与本发现同族线程同一处置)。不存在仅门侧的修复:已评审的 base 提交必须由台账标记携带,而该写入端改动位于 packages/cli,在本 PR 足迹之外。已与 R2-4 的写入端一半一并跟踪;门侧祖先检查与已执行的 rebased_base 形态随其一并落地。

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.

Deferred to the follow-up queue — verified real, pairs with R2-4 (same disposition as this finding's sibling threads). Binding the certification to the base's identity requires the writer to record the reviewed base tip beside sha/base — outside this PR's footprint (packages/cli) — and the gate-side descendant check lands with it. Recorded with R2-4's writer half.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对(与本发现同族线程同一处置)。把认证绑定到 base 的身份,需要写入端在 sha/base 旁记录已评审的 base 端点——在本 PR 足迹之外(packages/cli)——门侧后代检查随其落地。已与 R2-4 的写入端一半一并记录。

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.

Deferred to the follow-up queue — verified real, pairs with R2-4 (same disposition as this finding's sibling threads). The force-push rewrite probe reproduces skip=true at this head; the marker carries no base identity to compare because the writer emits no base field at all today. Certifying by base commit requires the writer half (outside this PR's footprint, packages/cli); recorded with R2-4.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对(与本发现同族线程同一处置)。强推重写探针在本 head 复现 skip=true;标记中没有任何 base 身份可供比较,因为写入端今天根本不输出 base 字段。以 base 提交认证需要写入端一半(packages/cli,在本 PR 足迹之外);已与 R2-4 一并记录。

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.

Deferred to the follow-up queue — verified real, pairs with R2-4 (same disposition as this finding's sibling threads). The force-push rewrite probe still reproduces skip=true at this head; no gate-only fix exists because the marker carries no base identity. The writer half lives in packages/cli, outside this PR's footprint, and is recorded with R2-4; the gate-side comparison lands with it.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对(与本发现同族线程同一处置)。强推重写探针在本 head 仍复现 skip=true;不存在仅门侧的修复,因为标记不携带任何 base 身份。写入端一半位于 packages/cli,在本 PR 足迹之外,已与 R2-4 一并记录;门侧比较随其落地。

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.

Stays deferred to the follow-up queue (first recorded in round 12). The finding is verified real — a same-name base rewrite does slip through the ref-name-only certification while digest equality holds by construction — but its fix straddles this PR's footprint: recording the reviewed base COMMIT in the ledger marker is writer-side work in packages/cli (paired with the deferred R2-4 writer field), and this PR touches only the gate script, the review workflow, and its test suite. As the finding itself notes, no gate-only fix exists, so the writer field and the gate-side ancestor check (with the executed rebased_base fixture) must land together in the follow-up rather than shipping a gate check keyed on a field no writer emits. The hole stays unarmed until then: no marker carries base today, so the gate cannot skip in production at all.

中文说明

继续保持延后处理,已记录至后续队列(第 12 轮首次记录)。该发现已核实为真——同名 base 分支被重写确实能穿过仅认分支名的认证,且摘要等式按构造成立——但其修复跨越本 PR 的足迹:在台账标记中记录该轮评审所对的 base 提交是 packages/cli 中的写入端工作(与已延后的 R2-4 写入端字段配对),而本 PR 只触及门脚本、评审工作流及其测试套件。正如该发现自身所述,不存在仅门侧的修复,因此写入端字段与门侧祖先检查(连同执行夹具 rebased_base)必须在后续工作中一并落地,而不是先交付一个依赖尚无任何写入端输出的字段的门侧检查。在此之前该漏洞未装弹:今天没有任何标记携带 base,门在生产中根本无法跳过。

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.

Stays deferred to the follow-up queue (first recorded in round 12). Same disposition as the round-12 thread: verified real, but the fix requires the writer-side base-commit field in packages/cli (outside this PR's footprint, paired with the deferred R2-4) plus the gate-side ancestor check landing together; no gate-only fix exists, per the finding itself. Until the writer ships, no marker carries base, the gate never skips in production, and this shape stays unarmed. The gate script changes this round (planted-config class closure, marker fall-through fix) do not interact with this hole.

中文说明

继续保持延后处理,已记录至后续队列(第 12 轮首次记录)。与第 12 轮线程处置相同:已核实为真,但修复需要 packages/cli 中的写入端 base 提交字段(位于本 PR 足迹之外,与已延后的 R2-4 配对)与门侧祖先检查一并落地;按该发现自身所述,不存在仅门侧的修复。在写入端交付之前,没有任何标记携带 base,门在生产中从不跳过,该形态保持未装弹。本轮门脚本改动(植入配置类封闭、标记回退修复)与该漏洞无交互。

mb_h="$(git merge-base "origin/${BASE_REF}" "${EVENT_HEAD_SHA}" 2>/dev/null)" || return

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.

Gate half fixed in 4cf0f3aced; writer half deferred to the follow-up queue, so this thread stays open.

Fixed here. The lookup now parses the marker payload and admits a marker only when its recorded base equals the current BASE_REF, failing open on mismatch (reviewed round certified against base 'main', not 'release') or absence (base 'unknown'). Three executed real-git fixtures pin it: a retargeted_base shape (round R reviewed under main, event BASE_REF=release, PR merges release) asserting skip=false; a legacy sha-carrying marker with no base failing open; and mutation probes — the whole retarget arm was red against the pre-round script (skip=true) and goes red again when the base-match check is removed.

Deferred. Emitting the reviewed round's base ref in the ledger marker payload is a change to the review compose pipeline (packages/cli/src/commands/review/lib/ledger.ts), outside this PR's footprint — recorded in the deferred-findings queue. As the finding itself anticipates, every existing marker therefore fails open and the gate skips nothing until the writer emits the field: the stated fail-open degradation, and the optimization is inert in the meantime.

中文说明

门侧一半已在 4cf0f3aced 修复;写入端一半延后至后续队列,因此本线程保持打开。

本次已修复:查询现在解析标记载荷,仅当标记记录的 base 等于当前 BASE_REF 时才接受该标记;不一致时向开放侧倒(reason 为 reviewed round certified against base 'main', not 'release'),缺失时同样倒(base 'unknown')。三个真实 git 执行夹具钉住该行为:retargeted_base 形态(R 轮在 main 下评审、事件 BASE_REF=release、PR 合入 release)断言 skip=false;带 sha 但无 base 的旧式标记向开放侧倒;变异探针——整个改道分支在改动前的脚本上为红(错误地 skip=true),移除 base 匹配检查后再次变红。

已延后:在台账标记载荷中输出该轮评审所用的 base,属于评审组装管线(packages/cli/src/commands/review/lib/ledger.ts)的改动,超出本 PR 的足迹——已记入延后发现队列。正如该发现本身所预期,在其落地之前所有既有标记都会向开放侧倒、门不会跳过任何 base 刷新:这是其明确给出的 fail-open 降级,优化功能在此期间处于未生效状态。

REASON='PR-side diff computation failed'
digest_r="$(diff_digest "${mb_r}" "${REVIEWED_SHA}")" || return
digest_h="$(diff_digest "${mb_h}" "${EVENT_HEAD_SHA}")" || return
Comment on lines +237 to +238

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.

Deferred to the follow-up queue — verified real, pairs with R2-4. The probe shape reproduces: after a same-named base rewrite, the landed three-dot diff gains content the reviewed round never saw, and the gate still emits skip=true, because the marker carries no base-commit identity to compare. As the finding states, no gate-only fix exists — the information must ride the marker, and that writer change lives in packages/cli, outside this PR's footprint. It is tracked with R2-4's writer half in the follow-up queue; the gate-side ancestor check (git merge-base --is-ancestor "$REVIEWED_BASE_SHA" "origin/${BASE_REF}" || return, failing open) ships with it.

中文说明

延后至后续队列——已核实为真,与 R2-4 配对。探针形态复现:同名 base 被重写后,落地的三点 diff 新增了已评审轮从未见过的内容,而门仍输出 skip=true,因为标记中没有任何 base 提交身份可供比较。如该发现所述,不存在仅门侧的修复——该信息必须由标记携带,而该写入端改动位于 packages/cli,在本 PR 足迹之外。已与 R2-4 的写入端一半一并记录到后续队列;门侧祖先检查(git merge-base --is-ancestor "$REVIEWED_BASE_SHA" "origin/${BASE_REF}" || return,向开放侧倒)随其一并落地。

REASON='empty PR-side diff'
{ [[ -n "${digest_r}" ]] && [[ -n "${digest_h}" ]]; } || return
REASON='the PR-side diff changed'
[[ "${digest_r}" = "${digest_h}" ]] || return

REASON=''
SKIP=true
}
decide

{
echo "skip=${SKIP}"
echo "reviewed_sha=${REVIEWED_SHA}"
echo "reason=${REASON}"
} >> "${GITHUB_OUTPUT}"
if [[ "${SKIP}" != 'true' ]]; then
echo "Base-refresh gate: full round proceeds (${REASON})." >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
echo "Base-refresh gate: head ${EVENT_HEAD_SHA} only merges ${BASE_REF} into reviewed head ${REVIEWED_SHA}; skipping the automatic round." >> "${GITHUB_STEP_SUMMARY}"

# One marker-deduped note per PR, updated in place via the shared upsert
# helper (author-scoped lookup, retried). Blank line after the marker, or
# none of the prose renders — the HTML-block quirk the ack comment documents.
# Note failures only warn: the skip decision is already recorded above.
body_file="$(mktemp "${RUNNER_TEMP:-/tmp}/qwen-review-base-refresh.XXXXXX")" || exit 0
# shellcheck disable=SC2016
printf '<!-- qwen-review-base-refresh -->\n\n🔁 **Base refresh detected** — head `%s` only merges `%s` into the last reviewed head `%s`; the PR-side diff is unchanged, so that review still applies and no new automatic round was spent ([this run](%s)). Comment `@qwen-code /review` for a fresh full review.\n\n<details>\n<summary>中文说明</summary>\n\n🔁 **检测到 base 刷新** —— head `%s` 仅把 `%s` 合入上次已评审的 head `%s`,PR 侧 diff 未变,原有评审结论仍然适用,本次未消耗新的自动评审轮次([本次运行](%s))。如需全新完整评审,请评论 `@qwen-code /review`。\n\n</details>' \
"${EVENT_HEAD_SHA}" "${BASE_REF}" "${REVIEWED_SHA}" "${RUN_URL}" \
"${EVENT_HEAD_SHA}" "${BASE_REF}" "${REVIEWED_SHA}" "${RUN_URL}" > "${body_file}"
"$(dirname "${BASH_SOURCE[0]}")/upsert-bot-comment.sh" \

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.

Stays deferred to the follow-up queue (first recorded in round 12). Verified again at this head: qwen-review-base-refresh occurs 0 times in .github/workflows/qwen-autofix.yml, while the note this gate posts is authored by the REVIEW_BOT account and would count as actionable feedback. The fix — adding the marker to the exclusion alternation at every REVIEW_BOT-admitting filter site, plus the static assertion pairing it with the qwen-review docs-only-medium exclusion — lives entirely in qwen-autofix.yml: outside this PR's diff, and inside the autofix loop's own workflow area, which this PR's review rounds must not modify. It remains recorded for the follow-up queue. The waste stays latent until the writer follow-up lands: no writer emits base today, so the gate cannot skip and the note cannot post in production.

中文说明

继续保持延后处理,已记录至后续队列(第 12 轮首次记录)。已在本 head 上再次核实:qwen-review-base-refresh 在 .github/workflows/qwen-autofix.yml 中出现 0 次,而本门发布的说明恰由 REVIEW_BOT 账号发出,会被计为可执行反馈。修复方案——在每处接纳 REVIEW_BOT 的过滤器位点把该标记加入排除选项组,外加将其与 qwen-review docs-only-medium 排除配对的静态断言——完全位于 qwen-autofix.yml:既在本 PR diff 之外,又属于 autofix 循环自身的工作流区域,本 PR 的评审轮次不得修改该区域。该项继续记录在后续队列中。在写入端后续落地之前该浪费保持潜伏:今天没有写入端输出 base,门无法跳过,说明也不可能在生产中发出。

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.

Stays deferred to the follow-up queue (first recorded in round 12). Disposition unchanged from the round-12 thread: the defect is verified (zero occurrences of the marker in qwen-autofix.yml at this head, re-grepped), but the entire fix is an edit to .github/workflows/qwen-autofix.yml — outside this PR's footprint and inside the autofix loop's own workflow area, which review rounds on this PR are not permitted to modify. The follow-up queue entry carries the fix shape: add qwen-review-base-refresh (trailing space, matching the exclusion regex) to every actionable-feedback filter admitting REVIEW_BOT issue comments, and add the static assertion so dropping the marker from BOT_COMMENT_FILTER turns the suite red.

中文说明

继续保持延后处理,已记录至后续队列(第 12 轮首次记录)。处置与第 12 轮线程相同:缺陷已核实(本 head 上该标记在 qwen-autofix.yml 中出现零次,已重新扫描确认),但整个修复都是对 .github/workflows/qwen-autofix.yml 的编辑——位于本 PR 足迹之外,且属于 autofix 循环自身的工作流区域,本 PR 的评审轮次不得修改。后续队列条目已记录修复形态:在每处接纳 REVIEW_BOT issue 评论的可执行反馈过滤器中加入 qwen-review-base-refresh (带尾随空格,与排除正则形态一致),并新增静态断言,使从 BOT_COMMENT_FILTER 中去掉该标记时测试套件变红。

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.

Stays deferred to the follow-up queue (first recorded in round 12). Verified at this head as in rounds 12–13: the marker appears 0 times in qwen-autofix.yml. This round's gate-script changes (planted-config class closure, -U3 digest pin, marker fall-through fix) do not touch the note path's filter interaction, so the disposition is unchanged: the fix is a qwen-autofix.yml-only edit — outside this PR's footprint and inside the autofix loop's own workflow area, off-limits to this PR's review rounds — and it stays recorded for the follow-up queue with its acceptance criterion (the static assertion pairing the new marker with the docs-only exclusion). Latent until the writer follow-up lands: with no writer emitting base, the gate cannot skip and the note cannot post in production.

中文说明

继续保持延后处理,已记录至后续队列(第 12 轮首次记录)。本 head 上的核实结果与第 12–13 轮一致:该标记在 qwen-autofix.yml 中出现 0 次。本轮门脚本改动(植入配置类封闭、-U3 摘要钉住、标记回退修复)不涉及说明路径与过滤器的交互,因此处置不变:修复是仅针对 qwen-autofix.yml 的编辑——位于本 PR 足迹之外,且属于 autofix 循环自身的工作流区域,本 PR 的评审轮次不得触碰——该项继续连同其验收标准(将新标记与 docs-only 排除配对的静态断言)记录在后续队列中。在写入端后续落地之前保持潜伏:没有写入端输出 base,门无法跳过,说明也不可能在生产中发出。

"${GITHUB_REPOSITORY}" "${PR_NUMBER}" '<!-- qwen-review-base-refresh -->' "${body_file}" \

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.

Deferred to the follow-up queue — verified real. qwen-review-base-refresh appears in none of qwen-autofix.yml's actionable-feedback filters at this head (checked BOT_COMMENT_FILTER at line 3404 and the inline copies), so an engaged PR receiving the note spends a full no-action round per base refresh once the gate can skip. The fix (add the marker to every filter copy admitting REVIEW_BOT issue comments, plus a static assertion pairing it with the docs-only exclusion) lives in qwen-autofix.yml — the autofix loop's own workflow, outside this PR's footprint and a protected area — so it is recorded for the follow-up queue rather than implemented here.

中文说明

延后至后续队列——已核实为真。本 head 上 qwen-review-base-refresh 未出现在 qwen-autofix.yml 的任何可执行反馈过滤器中(已检查第 3404 行的 BOT_COMMENT_FILTER 与各内联副本),因此一旦门可以跳过,收到该说明的被接管 PR 会在每次 base 刷新时消耗一整轮"无需操作"的轮次。修复(把该标记加入所有接纳 REVIEW_BOT issue 评论的过滤器副本,并新增与仅文档排除配对的静态断言)位于 qwen-autofix.yml——autofix 循环自己的 workflow,在本 PR 足迹之外且属受保护区域——故记录到后续队列,不在此实现。

|| echo "::warning::could not post the base-refresh note"
rm -f "${body_file}"
exit 0
37 changes: 33 additions & 4 deletions .github/workflows/qwen-code-pr-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -674,14 +674,43 @@ jobs:
echo "auto_review=$AUTO_REVIEW"
} >> "$GITHUB_OUTPUT"

# An update-branch base refresh (merging current main into the PR
# branch) fires `synchronize` like any push, but adds nothing on the
# PR side — and a full automatic round costs hours (#10111: two base
# refreshes on PR #9729 spent one full round plus one cancelled one).
# The script certifies that shape deterministically (pure base-merge
# chain since the last submitted ledger-marked reviewed head,
# PR-side diff unchanged apart from hunk offsets and index lines)
# and posts one marker-deduped note when it
# skips; its full contract lives in its header. Everything fails OPEN
# into the full round — the script never exits non-zero (a step
# failure would be misreported as a pipeline failure by the fallback
# comment) and continue-on-error is the belt for an unexpected crash.
- name: 'Skip base-refresh-only synchronize'
id: 'base_refresh'
if: |-
steps.context.outputs.should_run == 'true' &&
steps.context.outputs.auto_review == 'true' &&
github.event.action == 'synchronize'
continue-on-error: true
timeout-minutes: 5
env:
GH_TOKEN: '${{ secrets.CI_BOT_PAT }}'
PR_NUMBER: '${{ steps.context.outputs.pr_number }}'
EVENT_HEAD_SHA: '${{ github.event.pull_request.head.sha }}'
BASE_REF: '${{ github.event.pull_request.base.ref }}'
RUN_URL: '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
run: |-
.github/scripts/review-base-refresh-gate.sh

- name: 'Setup Node.js for hosted review'
if: "steps.context.outputs.should_run == 'true' && (github.repository != 'QwenLM/qwen-code' || vars.MAINTAINER_ECS_RUNNER_DISABLED == 'true')"
if: "steps.context.outputs.should_run == 'true' && steps.base_refresh.outputs.skip != 'true' && (github.repository != 'QwenLM/qwen-code' || vars.MAINTAINER_ECS_RUNNER_DISABLED == 'true')"
uses: 'actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e' # v6.4.0
with:
node-version: '22.x'

- name: 'Install Qwen CLI if missing'
if: "steps.context.outputs.should_run == 'true'"
if: "steps.context.outputs.should_run == 'true' && steps.base_refresh.outputs.skip != 'true'"
run: |-
set -euo pipefail
if command -v qwen >/dev/null 2>&1; then
Expand All @@ -702,7 +731,7 @@ jobs:
# inside (set +e, trailing exit 0) are its suspenders. It only decides
# which rung this runner can reach.
- name: 'Install capture tools (tmux + freeze)'
if: "steps.context.outputs.should_run == 'true'"
if: "steps.context.outputs.should_run == 'true' && steps.base_refresh.outputs.skip != 'true'"
continue-on-error: true
# continue-on-error bounds failure, not duration: a hung `sudo
# apt-get update` against a stalled mirror has no other bound and
Expand Down Expand Up @@ -853,7 +882,7 @@ jobs:

- name: 'Run review'
id: 'review'
if: "steps.context.outputs.should_run == 'true'"
if: "steps.context.outputs.should_run == 'true' && steps.base_refresh.outputs.skip != 'true'"
env:
GH_TOKEN: '${{ secrets.CI_BOT_PAT }}'
OPENAI_API_KEY: '${{ secrets.REVIEW_OPENAI_API_KEY }}'
Expand Down
Loading
Loading