Skip to content

fix(ci): read the CI patrol's status rollup one PR at a time - #10861

Merged
yiliang114 merged 4 commits into
mainfrom
fix/patrol-rollup-504
Sep 3, 2026
Merged

fix(ci): read the CI patrol's status rollup one PR at a time#10861
yiliang114 merged 4 commits into
mainfrom
fix/patrol-rollup-504

Conversation

@yiliang114

Copy link
Copy Markdown
Collaborator

What this PR does

This PR stops the CI Failure Patrol from asking GitHub for every matched PR's status rollup in one query. The PR search now returns only the cheap fields, and statusCheckRollup is read per PR afterwards. A PR whose rollup cannot be read is skipped with a note on stderr instead of failing the whole scan — the next run picks it up.

Why it's needed

Qwen CI Failure Patrol has failed 100 consecutive scheduled runs (every run in the last ~22 hours; the most recent is 33699092403). Every one dies the same way, before doing any work:

Command failed: gh pr list --repo QwenLM/qwen-code --base main --state open \
  --search status:failure updated:>=2026-08-27 \
  --json number,isDraft,baseRefOid,headRefOid,statusCheckRollup --limit 1000
HTTP 504: 504 Gateway Timeout (https://api.github.com/graphql)

statusCheckRollup expands every check run of every matched PR, so the list query is a single GraphQL call costing matched PRs × check runs. That is what times out, not the page size. Measured against the live API just now — 66 PRs currently match the search, and each carries 34–86 check runs:

query result
search + rollup, --limit 1000 / 200 / 100 / 50 HTTP 504 (~11s each)
search + rollup, --limit 40 HTTP 504
search + rollup, --limit 30 / 20 / 10 OK
search, no rollup, --limit 100 OK, instant
rollup per PR (gh pr view N --json statusCheckRollup) OK, ~0.7s each

Lowering --limit is not a fix: it fails at 40 and would silently drop matched PRs below that. The threshold moves with the repo's open-PR count and each PR's check count, so the query was always going to cross it — it has now.

The patrol is what reruns CI jobs that failed on a flake, so while it is down every flaky red PR stays red until someone reruns it by hand.

Reviewer Test Plan

How to verify

  1. npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/ci-flaky-rerun.test.js scripts/tests/ci-flaky-rerun-workflow.test.js — 42 passing, including the new contract that pins statusCheckRollup out of the list query, merges the per-PR rollups, and skips a PR whose rollup read throws.
  2. Reproduce the failure against the live API — gh pr list --repo QwenLM/qwen-code --base main --state open --search "status:failure updated:>=$(date -u -d '7 days ago' +%F)" --json number,isDraft,baseRefName,headRefOid,statusCheckRollup --limit 50 returns HTTP 504; drop statusCheckRollup and the same search answers immediately.
  3. After merge, watch the next scheduled Qwen CI Failure Patrol run reach Act on classified PR failures instead of dying in Classify stale PR failures.

Evidence (Before & After)

Before: 100/100 scheduled runs failed at Classify stale PR failures with HTTP 504 from the GraphQL endpoint; the Act on classified PR failures job never ran.

After: the list query drops the rollup and each rollup is a separate small read. At the current 66 matched PRs the scan makes 1 + 66 calls at ~0.7s each, about 45 seconds, well inside the job.

Tested on

OS Status
🍏 macOS N/A
🪟 Windows N/A
🐧 Linux

Environment (optional)

Script contract tests plus live gh queries against this repository.

Risk & Scope

  • Main risk or tradeoff: the scan now makes one API call per matched PR instead of one for all of them — 67 calls at today's 66 matches, against a 5000/hour limit, for a job that runs a few times an hour. In exchange no single call's cost scales with the repo.
  • Not validated / out of scope: prsWithMarkers() shares prList and gets the same treatment; it was not the query that failed. Nothing else in the patrol's classification or rerun logic changes.
  • Breaking changes / migration notes: none. prList returns the same shape, minus PRs whose rollup could not be read.

Linked Issues

None — found while auditing red workflows on main.

中文说明

本 PR 做了什么

本 PR 让 CI Failure Patrol 不再在一次查询里向 GitHub 索取所有匹配 PR 的 status rollup。PR 搜索现在只返回廉价字段,statusCheckRollup 改为随后逐个 PR 读取。读取失败的 PR 会被跳过并在 stderr 记录一行,而不是让整次扫描失败 —— 下一次运行会重新处理它。

为什么需要

Qwen CI Failure Patrol 已经连续 100 次定时运行全部失败(最近约 22 小时内的每一次;最新一次是 33699092403)。每一次都在开始干活之前以同样的方式失败:

Command failed: gh pr list --repo QwenLM/qwen-code --base main --state open \
  --search status:failure updated:>=2026-08-27 \
  --json number,isDraft,baseRefOid,headRefOid,statusCheckRollup --limit 1000
HTTP 504: 504 Gateway Timeout (https://api.github.com/graphql)

statusCheckRollup 会展开每个匹配 PR 的每一个 check run,因此这个 list 查询是一次 GraphQL 调用,其代价等于「匹配 PR 数 × 各自的 check run 数」。超时的是它,而不是分页大小。刚刚针对线上 API 的实测 —— 当前有 66 个 PR 匹配该搜索,每个带有 34–86 个 check run:

查询 结果
搜索 + rollup,--limit 1000 / 200 / 100 / 50 HTTP 504(各约 11 秒)
搜索 + rollup,--limit 40 HTTP 504
搜索 + rollup,--limit 30 / 20 / 10 正常
搜索,不带 rollup,--limit 100 正常,瞬时返回
逐个 PR 取 rollup(gh pr view N --json statusCheckRollup 正常,每个约 0.7 秒

调小 --limit 不是修复:它在 40 就失败,而且会静默丢弃阈值以下的匹配 PR。这个阈值随仓库未关闭 PR 数量和每个 PR 的 check 数量移动,所以这个查询迟早会越过它 —— 现在越过了。

Patrol 正是负责对因 flake 失败的 CI job 重跑的组件,所以它停摆期间,每一个 flake 变红的 PR 都会一直红着,直到有人手工重跑。

Reviewer Test Plan

如何验证

  1. npx vitest run --config ./scripts/tests/vitest.config.ts scripts/tests/ci-flaky-rerun.test.js scripts/tests/ci-flaky-rerun-workflow.test.js —— 42 个通过,其中包含新增契约:statusCheckRollup 不出现在 list 查询里、逐个 PR 的 rollup 会被合并、读取抛错的 PR 会被跳过。
  2. 针对线上 API 复现该失败 —— gh pr list --repo QwenLM/qwen-code --base main --state open --search "status:failure updated:>=$(date -u -d '7 days ago' +%F)" --json number,isDraft,baseRefName,headRefOid,statusCheckRollup --limit 50 返回 HTTP 504;去掉 statusCheckRollup 后同样的搜索立即返回。
  3. 合入后观察下一次定时的 Qwen CI Failure Patrol,预期它能进入 Act on classified PR failures,而不是死在 Classify stale PR failures

Evidence(修复前后)

修复前:100/100 次定时运行在 Classify stale PR failures 处以 GraphQL 端点的 HTTP 504 失败;Act on classified PR failures 从未运行。

修复后:list 查询不再带 rollup,每个 rollup 是一次独立的小请求。按当前 66 个匹配 PR 计算,一次扫描发出 1 + 66 次调用,每次约 0.7 秒,合计约 45 秒,远在 job 时限之内。

测试环境

OS Status
🍏 macOS N/A
🪟 Windows N/A
🐧 Linux

Environment(可选)

脚本契约测试,以及针对本仓库的线上 gh 查询。

风险与范围

  • 主要风险或取舍:扫描现在对每个匹配 PR 发一次 API 调用,而不是所有 PR 合成一次 —— 按今天的 66 个匹配算是 67 次,对应每小时 5000 次的限额,而该 job 每小时只运行数次。换来的是不再有任何单次调用的代价随仓库规模增长。
  • 未验证 / 不在范围内:prsWithMarkers() 共用 prList,因此同样受益;它不是失败的那个查询。Patrol 的分类与重跑逻辑没有任何改动。
  • 破坏性变更 / 迁移说明:无。prList 返回结构不变,只是不再包含 rollup 读取失败的 PR。

关联 Issue

无 —— 在排查 main 上变红的 workflow 时发现。

https://claude.ai/code/session_01MCE9CXnMVrX4fUxHpQoUr8

Asking for statusCheckRollup inside the PR search makes one GraphQL call
whose cost grows with matched PRs times their check runs. The repository
outgrew it: the call returns HTTP 504 above ~30 matches, and every
scheduled patrol run has failed since. The same search without the rollup
answers in a second, and per-PR reads are small.

Claude-Session: https://claude.ai/code/session_01MCE9CXnMVrX4fUxHpQoUr8
@qwen-code-ci-bot

qwen-code-ci-bot commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Deferred approval not posted — the PR head moved (or the PR closed) after the review of fc8947f; approving now would attest to unreviewed code. Re-run @qwen-code /triage on the new head. finalize run

⚠️ 延迟审批未提交 —— 审查 fc8947f 之后 PR head 已变更(或 PR 已关闭),此时审批会为未审查的代码背书。请在新 head 上重新运行 @qwen-code /triage查看 finalize 运行

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Template looks good ✓

Problem: This is an observed failure, not theory. The Qwen CI Failure Patrol has failed its last 30 scheduled runs in a row — every one dies in Classify stale PR failures with HTTP 504: 504 Gateway Timeout (https://api.github.com/graphql) from the gh pr list … statusCheckRollup … --limit 1000 call (confirmed in run 33699092403's log). I also reproduced it against the live API: the same search with statusCheckRollup gateway-errors, while the identical search without it returns 66 PRs in ~1.2s, and a per-PR gh pr view N --json statusCheckRollup answers in ~0.8s. The premise checks out.

Direction: Clearly aligned. The patrol is the component that reruns flaky-red CI jobs, so while it is down every flake failure stays red until someone reruns it by hand. Restoring it is unambiguously in scope, and it touches no auth/sandbox/model-selection/telemetry/release surface.

Size: Not applicable — the change is confined to .github/scripts/ci-flaky-rerun.mjs and its test; no packages/*/src/** core paths.

Approach: The scope feels right. Dropping the rollup from the list query and reading it per PR is the minimal fix, and skipping (with a stderr note) a PR whose rollup can't be read — instead of failing the whole scan — is the right tradeoff. No unrelated edits or drive-by refactors; nothing to cut.

Risk: No elevated risk signals — neither changed file matches the revert-correlated high-risk paths.

Moving on to code review. 🔍

中文说明

感谢贡献!

模板完整 ✓

问题:这是已观测到的故障,不是理论问题。Qwen CI Failure Patrol 已连续 30 次定时运行全部失败——每一次都在 Classify stale PR failures 处以 HTTP 504: 504 Gateway Timeout (https://api.github.com/graphql) 挂掉,来自 gh pr list … statusCheckRollup … --limit 1000 调用(已在 run 33699092403 的日志中确认)。我还针对线上 API 做了复现:同样带 statusCheckRollup 的搜索直接网关报错,而不带该字段的同一搜索约 1.2 秒返回 66 个 PR,逐个 PR 的 gh pr view N --json statusCheckRollup 约 0.8 秒返回。前提成立。

方向:明确对齐。patrol 正是重跑 flake 变红 CI job 的组件,它停摆期间每个 flake 失败都会一直红着,直到有人手工重跑。恢复它显然在范围内,且不涉及 auth/沙箱/模型选择/遥测/发布等敏感面。

规模:不适用——改动仅限 .github/scripts/ci-flaky-rerun.mjs 及其测试,不触及 packages/*/src/** 核心路径。

方案:范围合理。把 rollup 从 list 查询中移除、改为逐个 PR 读取是最小修复;对读取失败的 rollup 跳过(并在 stderr 记录)而非让整次扫描失败,也是正确取舍。无无关改动或顺手重构,无可砍内容。

风险:无升级风险信号——两个改动文件均不匹配高回滚率相关的高风险路径。

进入代码审查 🔍

Qwen Code · qwen3.8-max

Reviewed at fc8947f712355151daca2420a576ca43d703d4f8 · re-run with @qwen-code /triage

@qwen-code-ci-bot

qwen-code-ci-bot commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Code review

The implementation is the minimal version of the fix, and it follows the existing code's idiom. The new per-PR read reuses the exact gh pr view <n> --repo … --json statusCheckRollup shape that currentPr() already uses, and the merged { ...pr, statusCheckRollup } keeps the object shape downstream consumers rely on — latestChecks() and toTarget() read statusCheckRollup, number, and headRefOid, all present. Skipping a PR whose rollup can't be read (rather than failing the whole scan) is the right call, and it's logged to stderr so it isn't silent. Sequential await in the loop is fine at this scale (~45s for today's 66 matches, against a 5000-calls/hour limit) and avoids bursting the API. No correctness, security, or regression issues found.

The new test pins the load-bearing contract: statusCheckRollup stays out of the list query, per-PR rollups are merged back in, and a PR whose rollup throws is skipped. The calls length assertion (3 = 1 list + 2 views) would catch a regression to the single-query shape.

No sequence diagram or files table — this is a focused two-file change.

Testing

This is an unattended CI run, so I did not run the PR's code; evidence below is the PR's own CI (via the API) plus my read-only verification of the premise against the live GitHub API.

Final CI results for fc8947f (auto-updated by the triage finalize job after CI completed):

Check Conclusion
Dependency CVE audit ❌ failure
Post Coverage Comment 🚫 cancelled
Test (ubuntu-latest, Node 22.x) 🚫 cancelled
web-shell E2E Smoke (ubuntu-latest, Node 22.x) 🚫 cancelled
Classify PR ✅ success
Desktop Shell (ubuntu-22.04) ✅ success
Desktop Shell (windows-2022) ✅ success
Integration Tests (no-AK, No Sandbox) ✅ success
Secret scan (TruffleHog) ✅ success

One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。

The ubuntu unit suite (Test (ubuntu-latest, Node 22.x) — the job that runs the new ci-flaky-rerun.test.js), plus integration tests and the secret scan, were still in flight at review time. The table above is updated in place by the finalize job once they land. The remaining skipped/success entries are bot orchestration jobs, not test signal.

The one red check, Dependency CVE audit, is not caused by this PR. It's npm audit flagging a uuid advisory (GHSA-w5hq-g745-h8pq), and this PR touches no package.json/lockfile; the same check also fails on main's head commit (8fde141). Pre-existing dependency noise, named as such.

Beyond the PR's own CI, I verified the behavior against the live GitHub API (read-only queries): the list query with statusCheckRollup gateway-errors, the identical search without it returns 66 PRs in ~1.2s, and a per-PR rollup fetch returns in ~0.8s. So both the premise and the fix path are independently confirmed, not just asserted by the PR body.

The only claim that can't be checked pre-merge is the end-to-end "the patrol reaches Act on classified PR failures" (the PR's own Reviewer Test Plan step 3) — that's inherent to a scheduled workflow and is observable only after merge.

中文说明

代码审查

实现是该修复的最小版本,且沿用了现有代码的惯用写法。新的逐 PR 读取复用了 currentPr() 已在使用的 gh pr view <n> --repo … --json statusCheckRollup 形式;合并后的 { ...pr, statusCheckRollup } 保持下游消费者依赖的对象结构——latestChecks()toTarget() 读取的 statusCheckRollupnumberheadRefOid 均存在。对读取失败的 rollup 跳过(而非让整次扫描失败)是正确取舍,且会写入 stderr,并非静默。循环中顺序 await 在当前规模下没问题(按今天的 66 个匹配约 45 秒,对应每小时 5000 次的限额),也避免对 API 造成突发压力。未发现正确性、安全或回归问题。

新增测试钉住了关键契约:statusCheckRollup 不出现在 list 查询里、逐个 PR 的 rollup 会被合并、读取抛错的 PR 会被跳过。calls 长度断言(3 = 1 次 list + 2 次 view)能捕捉回退到单次查询的回归。

无时序图、无文件清单表——这是一个聚焦的双文件改动。

测试

这是无人值守 CI 运行,因此我未运行 PR 的代码;以下证据来自 PR 自身的 CI(经 API 读取)以及我针对线上 GitHub API 对前提做的只读验证。

(上方表格为 PR 自身 CI 检查,由 finalize job 在 CI 结束后原地更新。)

ubuntu 单测套件(Test (ubuntu-latest, Node 22.x)——运行新增 ci-flaky-rerun.test.js 的 job)、集成测试与密钥扫描在审查时仍在运行。其余跳过/成功项为 bot 编排 job,非测试信号。

唯一的红色检查 Dependency CVE audit 并非本 PR 引起:它是 npm audit 报出 uuid 的 advisory(GHSA-w5hq-g745-h8pq),而本 PR 未触及 package.json/lockfile;该检查在 main 的最新提交(8fde141)上同样失败。属于既有的依赖噪音,特此说明。

除 PR 自身 CI 外,我还针对线上 GitHub API 做了只读验证:带 statusCheckRollup 的 list 查询网关报错,不带该字段的同一搜索约 1.2 秒返回 66 个 PR,逐 PR 的 rollup 读取约 0.8 秒返回。因此前提与修复路径均被独立确认,而非仅凭 PR 描述。

唯一无法在合入前验证的是端到端的"patrol 能进入 Act on classified PR failures"(PR 自身 Reviewer Test Plan 第 3 步)——这是定时 workflow 的固有属性,只能在合入后观察。

Qwen Code · qwen3.8-max

Reviewed at fc8947f712355151daca2420a576ca43d703d4f8 · re-run with @qwen-code /triage

@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Confidence: 4/5 — clean, minimal, well-evidenced fix for a real, verified outage; approval deferred only until the PR's own CI lands green.

Stepping back: this restores a piece of CI infrastructure that has been fully down — 30/30 scheduled patrol runs failing — and the patrol is the mechanism that reruns flaky-red jobs. The problem is real and I reproduced it live. The fix is the minimal correct approach: drop the rollup from the list query, read it per PR, skip-and-log on a failed read — and it matches the existing currentPr() idiom. The test pins the contract. No core modules, no high-risk paths, no approval-guardrail concerns.

The one reservation is unrelated to the diff. The Dependency CVE audit check is red, but it fails on main's head commit too and this PR touches no lockfile, so it is pre-existing dependency noise. Heads-up for the maintainer: if that check stays red, the deferred auto-approval below will not fire on its own — a human approval would still be needed, or the uuid advisory fixed separately.

Every change in the diff is necessary; nothing to cut. In six months this reads clearly — the inline comment explains exactly why the rollup moved out of the list query.

Approval deferred until CI lands green on fc8947f712355151daca2420a576ca43d703d4f8 — the ubuntu unit suite, integration tests, and secret scan are still running.

中文说明

置信度:4/5 —— 干净、最小、证据充分的修复,针对一次真实且已验证的故障;仅因 PR 自身 CI 尚未变绿而暂缓批准。

退一步看:这恢复的是一整套已完全停摆的 CI 基础设施——patrol 定时运行 30/30 全部失败,而它正是重跑 flake 变红 job 的机制。问题真实存在,我已在线上复现。修复是最小且正确的方案:把 rollup 从 list 查询中移除、逐个 PR 读取、读取失败则跳过并记录——且沿用了现有 currentPr() 的惯用写法。测试钉住了契约。不触及核心模块、无高风险路径、无批准护栏方面的顾虑。

唯一的保留意见与 diff 无关:Dependency CVE audit 检查为红,但它在 main 最新提交上同样失败,且本 PR 未触及 lockfile,属于既有的依赖噪音。提醒维护者:若该检查持续为红,下方的暂缓自动批准将不会自行触发——届时仍需人工批准,或另行修复 uuid 的 advisory。

diff 中每一处改动都是必要的,无可砍内容。六个月后回看依然清晰——内联注释完整解释了 rollup 为何移出 list 查询。

批准暂缓,等待 CI 在 fc8947f712355151daca2420a576ca43d703d4f8 上变绿——ubuntu 单测套件、集成测试与密钥扫描仍在运行。

Qwen Code · qwen3.8-max

Reviewed at fc8947f712355151daca2420a576ca43d703d4f8 · re-run with @qwen-code /triage

wenshao and others added 3 commits September 3, 2026 09:19
One call per PR is fine; 66 of them in series is 46 seconds against a
ten-minute job budget, and that cost grows with the open-PR count — the
same growth that broke the single bulk query in the first place. Five at a
time brings a 66-PR scan to about ten seconds, and the results stay in
their original order.

Claude-Session: https://claude.ai/code/session_01MCE9CXnMVrX4fUxHpQoUr8
@yiliang114
yiliang114 enabled auto-merge September 3, 2026 03:14

@qwen-code-dev-bot qwen-code-dev-bot left a comment

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.

Reviewed at head aa32e3ed.

  • The failure mode is real and documented with numbers (504 beyond ~30 matches, 100 straight failed scans), and the fix is the right shape: the bulk rollup becomes per-PR small reads, bounded at 5 concurrent so a 66-PR scan stays inside the job's budget without bursting the API, and a single unreadable PR is skipped with a stderr note instead of failing the whole patrol — the next scan picks it up.
  • Index handoff is race-free (the next++ claim happens in the synchronous slice; results land at their original positions so ordering is stable), and skipped entries are dropped via filter(Boolean) rather than surfacing as undefined. The new test pins both the search-query shape (no statusCheckRollup in the list) and the per-PR fetch behavior.
  • No prior reviews or threads; CI has no failures on this head. Per the channel convention the call is on the review itself.

@chiga0 chiga0 left a comment

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.

No blocking findings. Approval blockers: none.

Scope: .github/scripts/ci-flaky-rerun.mjs (full file read) and scripts/tests/ci-flaky-rerun.test.js (new tests reviewed). Cross-file callers of prList (prs(), prsWithMarkers()) and their downstream consumers (selectCandidateTargets, resetSuccessfulFailures) traced.


What I checked

Core change — prList split:

  • statusCheckRollup is absent from the list query args (--json number,isDraft,baseRefName,headRefOid); the per-PR fetch via gh pr view <N> --json statusCheckRollup restores the field on each object before it is returned.
  • detailed[i] = { ...pr, statusCheckRollup } correctly merges the base fields with the fetched rollup; slots where the fetch threw remain undefined and are removed by filter(Boolean).
  • Order preservation: filter(Boolean) is a stable filter on the pre-indexed array, so callers receive PRs in the same order the list query returned them. The concurrency test asserts this ([1..12]).

Concurrency worker pattern:

  • JavaScript is single-threaded; next++ is synchronous and executes without interruption between await yield points. Every i = next++ in the for-loop yields a unique index. No race condition.
  • Five workers claim indices 0-4 synchronously before any await fires. Subsequent iterations are claimed in the for-loop update expression, also synchronously. Correct work-stealing for the JS event loop model.
  • Math.min(PR_DETAIL_CONCURRENCY, prs.length) correctly handles the empty-list and small-list edge cases.

prsWithMarkers() coverage:

  • This caller also flows through the updated prList, so resetSuccessfulFailures receives PRs with statusCheckRollup populated. succeededAfter(pr, state) reads pr.statusCheckRollup — it gets the correct value. A PR whose rollup fetch fails is skipped; the reset logic won't fire for it, but it remains in future scans. Acceptable per the PR's stated design.

Rate-limit arithmetic:

  • At 66 matched PRs: 1 list call + 66 view calls = 67 calls per scan. With PR_DETAIL_CONCURRENCY = 5 the wall time is approximately ceil(66/5) x 0.7 s ~10 s, well within the 10-minute job budget. The 5000-call/hour core limit easily accommodates a few scans per hour.

Test validity:

  • keeps the status rollup out of the PR search query: verifies statusCheckRollup is absent from the list --json arg, that PR 8 (error path) is dropped, and that exactly 3 gh calls are made. The test can fail if the field is re-added to the list query.
  • bounds how many PR detail reads run at once: mock uses setTimeout(resolve, 1) to create real yield points; peak inFlight of 5 is structurally guaranteed (5 workers each increment inFlight synchronously before their first await). The order assertion covers the index-based sparse array.

No issues found in:

  • Error text propagation from skipped PRs to stderr.
  • currentPr (not changed, still fetches statusCheckRollup inline for the freshness check in scan).
  • Callers in the scan and reset entry points.

Cross-check: No prior reviews or inline comments from other reviewers to compare against.

Unreviewed dimensions: Working tree unavailable; test suite was read but not executed locally. The logic is fully traceable statically and the test mocks structurally guarantee the observed behaviors.


Reviewed with AI assistance.

@yiliang114
yiliang114 added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit 03f2098 Sep 3, 2026
57 of 59 checks passed
@qwen-code-ci-bot

Copy link
Copy Markdown
Collaborator

Released in v0.23.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants