Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5fcabe2
feat(autofix): escalate stopped takeover PRs and age out unanswered p…
wenshao Aug 11, 2026
8ea334c
fix(autofix): harden the takeover auto-release against review round 1
wenshao Aug 12, 2026
cb0351d
fix(autofix): close review round 2 — cycle-scoped heal, retryable sum…
wenshao Aug 12, 2026
5b6c285
fix(autofix): close review round 2 — cycle-scoped markers and mutatio…
wenshao Aug 12, 2026
31444cd
Merge branch 'main' into feat/takeover-fleet-visibility
wenshao Aug 12, 2026
f64c176
fix(autofix): close review round 3 — release-ack label gate and share…
wenshao Aug 12, 2026
3758c68
fix(autofix): close review round 4 — label-lifecycle hardening
wenshao Aug 13, 2026
9c8d732
fix(autofix): close review round 4 — robust release detection and mar…
wenshao Aug 13, 2026
c4ce6e1
fix(autofix): keep the label-DELETE idiom byte-identical across workf…
wenshao Aug 13, 2026
41b905d
test(autofix): close review round 4b — mutation-tested harness hardening
wenshao Aug 13, 2026
2de7171
fix(autofix): close review round 5 — trust boundaries and evidence fr…
wenshao Aug 13, 2026
b575b67
fix(autofix): close review round 6 — contract-safe gates and subshell…
wenshao Aug 13, 2026
bdc360a
chore(autofix): merge main — reconcile paginated-fetch count pins
qwen-code-dev-bot Aug 14, 2026
175e224
fix(autofix): close review round 7 — lever starvation, re-arm anchori…
wenshao Aug 14, 2026
fa2435f
Merge remote-tracking branch 'origin/feat/takeover-fleet-visibility' …
wenshao Aug 14, 2026
78024d2
test(autofix): complete the R4-16 ack-matrix DELETE-count coverage
wenshao Aug 14, 2026
9555662
fix(autofix): close review round 8 — reachable re-arm cleanup, releas…
wenshao Aug 14, 2026
b055a8d
fix(autofix): close review round 9 — honest release-failed ack, clean…
wenshao Aug 14, 2026
7c76edb
fix(autofix): close review round 10 Criticals — exact HTTP 404 releas…
qwen-code-dev-bot Aug 14, 2026
5f24cd5
fix(autofix): close review round 11 Criticals — engaged stale-ack gua…
qwen-code-dev-bot Aug 15, 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
15 changes: 12 additions & 3 deletions .github/workflows/pr-self-report-label.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,20 @@ jobs:
# failure (403 rate limit, 5xx, network) also keeps the step
# green — the job only re-runs on the next PR event — but must
# not disappear: without the warning, the log claims "removed"
# while the label stays on the PR.
# while the label stays on the PR. LBL_DEL_FAILED is keyed on the
# exit status, with the exact "HTTP 404" token as the only
# text-derived exception (a bare 404 substring also rides
# transport failures' embedded URLs), and mirrors the identical
# idiom in qwen-autofix.yml (a contract test pins them in sync).
LBL_DEL_FAILED=false
if ! REMOVE_ERR="$(gh api -X DELETE "repos/${REPO}/issues/${PR}/labels/$(jq -rn --arg l "${LABEL}" '$l|@uri')" 2>&1)"; then
[[ "${REMOVE_ERR}" == *404* ]] || echo "::warning::#${PR}: ${LABEL} removal failed — ${REMOVE_ERR}"
[[ "${REMOVE_ERR}" == *"HTTP 404"* ]] || { LBL_DEL_FAILED=true; echo "::warning::#${PR}: ${LABEL} removal failed — ${REMOVE_ERR}"; }
fi
if [[ "${LBL_DEL_FAILED}" == "true" ]]; then
echo "#${PR}: ${LABEL} removal did not land — will retry on the next PR event"
Comment on lines +112 to +113

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] R7-5: The new LBL_DEL_FAILED failure-branching behaviour added here has no test — scripts/tests/pr-self-report-label.test.js is untouched by this PR. The harness already exercises this path (deleteFails: 'HTTP 500') but asserts only the warning lines; the cross-workflow contract test pins only the two-line DELETE idiom, not this consumer branch. — Failure scenario: deleting the branch (restoring the unconditional 'removed' echo) or inverting the condition ships green: on a DELETE 500 the log again claims the label was removed while it stays on the PR — the exact lying log this change exists to kill.

Suggested fix — in the existing failure-policy test:

expect(failed.out).toContain('removal did not land');
expect(failed.out).not.toContain('removed');

(and the inverse for the 404-race and success cases)

中文说明

[建议] R7-5:此处新增的 LBL_DEL_FAILED 失败分支行为没有测试——scripts/tests/pr-self-report-label.test.js 未被本 PR 修改。测试 harness 已经执行到该路径(deleteFails: 'HTTP 500'),但只断言了告警行;跨 workflow 契约测试只钉住了两行 DELETE 惯用法,未覆盖这个消费分支。失败场景:删除该分支(恢复无条件的 'removed' 输出)或反转条件都能绿色通过——DELETE 500 时日志再次声称标签已移除而实际仍在——正是本修改要消灭的假日志。修复建议:在现有失败策略测试中补充 expect(failed.out).toContain('removal did not land')expect(failed.out).not.toContain('removed')(404 竞态与成功用例做反向断言)。

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

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.

R7-5 已修(fa2435f17e):pr-self-report-label.test.js 的失败策略用例补了 LBL_DEL_FAILED 分支断言——HTTP 500 时断言 removal did not land 且不出现 removed;404 竞态与成功用例做反向断言。

else
echo "🏷️ #${PR}: removed ${LABEL} — no self-reported linked issue"
fi
echo "🏷️ #${PR}: removed ${LABEL} — no self-reported linked issue"
else
echo "#${PR}: no change (self=${SELF}, labeled=${HAS_LABEL}, api=${API_OK})"
fi
272 changes: 253 additions & 19 deletions .github/workflows/qwen-autofix.yml

Large diffs are not rendered by default.

747 changes: 717 additions & 30 deletions .github/workflows/qwen-fleet-shepherd.yml

Large diffs are not rendered by default.

178 changes: 178 additions & 0 deletions docs/design/takeover-fleet-visibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Takeover fleet visibility and cap-hit escalation

## Problem statement

As of 2026-08-11, 35 open PRs carry `autofix/takeover`. Two structural gaps:

1. **The takeover pool is invisible.** The Fleet Shepherd
(`qwen-fleet-shepherd.yml`) enumerates only bot-authored PRs (3 today).
The 35 human-authored takeover PRs appear on no dashboard; their state
(working / paused / conflicting / idle-for-days) is knowable only by
opening each PR.

2. **Cap-hit PRs die silently.** When a takeover PR reaches its round cap
(100/100), or a circuit breaker (consecutive-failure, time-budget) stops
it, the loop posts one comment and goes quiet. Five PRs have been paused
since 2026-08-06 with no re-arm: #8213, #8396, #8416, #8439, #8443.
Nothing escalates them — no label, no dashboard entry, no auto-release —
so they hold the takeover label forever ("zombie takeover").

## Proposed changes

### A. `autofix/needs-human` label (qwen-autofix.yml)

A new maintainer-facing label meaning: _the loop has stopped on this PR; a
human must act (re-arm, split, merge, or close)_.

**Applied** in the review scan's cap-notice path (the single funnel every
terminal state passes through: round cap, consecutive-failure cap, and
time-budget cap all write a terminal `autofix-eval` marker with
`round=EFF_MAX_ROUNDS`, which the next scan sees as `ROUND >= EFF_MAX_ROUNDS`
and lands in the cap-notice branch). The label write is placed so it runs
even when the once-per-window notice comment is dedup'd — this backfills the
label onto the already-paused fleet via the regular scan rotation after
deploy (idle backoff defers PRs idle >24h to ~1 scan in 4 — expect hours,
not the first scan).

**Removed** wherever management resumes or a human takes over:

| Path | Site |
| ------------------------------------------------------ | -------------------- |
| `/takeover` re-arm on a managed PR | takeover-command job |
| `/takeover` fresh engage | takeover-command job |
| `/takeover stop` | takeover-command job |
| Manual label engage / release acks | takeover-ack job |
| `/retry` re-arm marker | retry-command job |
| Scan first-pickup engage ack (direct-label engagement) | review-scan job |

Removal is best-effort with a warning on failure, mirroring the existing
`TAKEOVER_LABEL` DELETE pattern (404 tolerated). A stale `needs-human` left
behind by a failed removal is cosmetically wrong but harmless; the next
cap-stop reapplies it anyway.

A PR closed or merged while paused keeps `needs-human` — deliberately. No
closure removal path exists (the route drops commands on non-open PRs, every
enumeration is `--state open`, and there is no `pull_request: closed`
trigger), and the residue is inert: all consumers filter on open state, so
the label only marks the resolved escalation in the closed PR's own history.
All-state label queries should pair the label with a state filter.

Label creation follows the existing convention: `gh label create` (idempotent,
fixed color) before the first REST add, so a missing label never gets a random
color.

### B. Shepherd covers the takeover pool (qwen-fleet-shepherd.yml)

A second enumeration — open PRs with `autofix/takeover`, including forks —
drives a **second dashboard table** in the same edited-in-place issue:

| PR | Author | Updated | State | Note |
| --- | ------ | ------- | ----- | ---- |

State comes from the list payload (conflicting / ci red / checks in flight /
idle). PRs carrying `autofix/needs-human` get a `🛑 needs-human` state; for
those few PRs the shepherd additionally reads the comment stream (fail-closed)
to recover the terminal timestamp (latest `<!-- takeover-cap-reached -->`
notice) and the stop reason (first line of the latest terminal "AutoFix
stopped" headline, else "round cap reached").

**NON-GOAL:** the existing levers (conflict dispatch, stale-base sync) stay
scoped to the bot fleet. Takeover-PR conflicts are already the autofix scan's
job (`HAS_CONFLICT` selects them as targets), and `update-branch` on
contributor branches is out of scope for this change.

### C. Auto-release lever (qwen-fleet-shepherd.yml)

When a PR carries **both** `autofix/takeover` and `autofix/needs-human` and
its terminal timestamp is older than `AUTO_RELEASE_DAYS` (default 3, tunable
via the `QWEN_SHEPHERD_AUTO_RELEASE_DAYS` repo variable):

1. Post one bilingual summary — dedup'd by its
`<!-- fleet-shepherd auto-release -->` marker (scoped to the current
pause cycle): why it was released, the stop reason, and the human's
options (merge / close / split + re-takeover).
2. Remove `autofix/takeover` (the loop disengages). A failed removal finds
the marker and retries only the DELETE; a failed summary leaves both
labels in place so the whole release retries next tick.
3. Keep `autofix/needs-human`: the PR still needs a human decision, and the
label remains the filterable TODO list. It clears on re-engage/re-arm via
the paths in (A).

Idempotency needs no marker comment: the lever's scope condition (both labels)
is false after the release, so it cannot re-fire. Per-tick cap
(`MAX_RELEASES_PER_TICK`, default 3) bounds blast radius; `live_skip` is
re-checked immediately before the mutation, mirroring every existing lever.

## Key design decisions

- **Label write lives in the scan, not the address leg.** Every terminal stop
converges on `round=EFF_MAX_ROUNDS` markers, which the scan's cap branch
already observes with comments loaded and PAT identity verified. One hook
point covers all stop reasons, including future ones.
- **Pause reason comes from the terminal marker headline**, because the
scan-side notice always says "round cap (N/N)" even when a breaker fired
(observed on #8443: both comments present).
- **Bootstrap without a backfill job:** the label write runs even when the
notice comment is dedup'd, so currently-paused PRs are labeled by the
regular scan rotation after deploy — note the scan's idle backoff defers
PRs idle >24h (exactly the paused population) to ~1 scan in 4, so expect
the backfill within a few hours (median ~2h, p90 ~6h), not minutes.
- **Auto-release keyed on the notice timestamp**, not label age: labels carry
no timestamps, and the notice is written by the same identity-verified path
that applies the label. Resume evidence newer than the notice vetoes the
release — the bot's re-arm/engage markers, a re-arm command comment, or a
fresh `labeled` event. Command comments count only while FRESH
(`RESUME_COMMAND_GRACE_SEC`, 2h) and UNSUPERSEDED by a refusal ack
(`fork-refused` / `base-refused` / `skip-blocked`): an accepted command is
acked within minutes; an ignored one (no route permission) simply expires;
and no permission check is mirrored into the shepherd — the route's

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] R5-29: Round-5 finding still stands at the reviewed commit (re-confirmed this round): the design doc flatly contradicts code this same PR adds — compute_resume_ts DOES mirror a permission check (collaborators/${cauthor}/permission, write/maintain/admin gate, bounded reads, PERM_READ_FAILED), and this round's verification shows it has already drifted from the route's acceptance set (the route also admits in-repo authors at triage — see the R6-31 companion finding in the terminal report). — Failure scenario: an operator debugging release behavior believes any stranger's fresh command counts as resume evidence (the doc's "no permission check is mirrored" + "simply expires" wording), and a future edit citing the doc's "a mirrored copy would only drift" rationale could remove the permission read to align code with doc — reopening the stranger-shadow hole the newest-first scan, the read budget, and the R5-4 machinery exist to close. Fix: rewrite the bullet to describe the implemented behavior (permission-checked command authors; bounded reads; fail-closed deferral; no-permission commands never count) — and reconcile the triage-author drift.

中文说明

[Suggestion] R5-29:第 5 轮发现在被审提交上仍然存在(本轮再次确认):设计文档与本 PR 自己添加的代码直接矛盾——compute_resume_ts 确实镜像了权限检查(collaborators/${cauthor}/permission、write/maintain/admin 门、有界读取、PERM_READ_FAILED),且本轮验证显示它已经与路由的接受集合发生漂移(路由还接受 triage 级的仓库内作者——见终端报告中的伴生发现 R6-31)。失败场景:排查释放行为的运维者会相信任何陌生人的新鲜命令都被计为恢复证据(文档的"不镜像权限检查"+"自然过期"措辞);未来某次编辑若引用文档"镜像拷贝只会漂移"的理由删除权限读取以使代码对齐文档——将重新打开陌生人遮蔽漏洞,而 newest-first 扫描、读取预算与 R5-4 机制正是为堵住它而存在。修复:重写该条目以描述实际实现(命令作者经权限检查、有界读取、fail-closed 推迟、无权限命令不计入),并消除 triage 作者漂移。

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

collaborator check is the authorization gate, and a mirrored copy would
only drift.
Comment on lines +128 to +130

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] R5-29: The new design doc flatly contradicts code this same PR adds: the release lever DOES mirror a permission check — it reads repos/${REPO}/collaborators/${CMD_AUTHOR}/permission and counts a command comment only for write/maintain/admin (qwen-fleet-shepherd.yml:756-765, added in this diff as the R4-14 fix). The stale wording also survives inline in the workflow comment block at ~:728, directly above the R4-14 comment that contradicts it. — Concrete cost: docs/design/ is committed guidance; its stated rationale (mirroring "would only drift") is an explicit invitation to delete the CMD_PERM read as drift-cleanup in a follow-up — doing so reintroduces exactly the defect R4-14 fixed (a permissionless stranger posting the command at least every 2h vetoes auto-release forever, since an ignored command gets no refusal ack and never expires by supersession); a reviewer auditing the shepherd with the doc as ground truth would likewise misclassify the permission read as unnecessary.

Fix — replace the sentence with the shipped behavior ("Command comments count only while FRESH, UNSUPERSEDED by a refusal ack, AND issued by a write/maintain/admin commenter — one collaborators permission read, only when a command is the sole resume evidence (R4-14); a renewing stream of stranger commands must not veto a release forever") and delete the stale "No permission check here on purpose" line in the workflow comment block.

中文说明

[Suggestion] R5-24:新设计文档与本 PR 自己新增的代码直接矛盾:释放杠杆确实镜像了一个权限检查——读取 repos/${REPO}/collaborators/${CMD_AUTHOR}/permission,且只有 write/maintain/admin 的命令评论才被计入(qwen-fleet-shepherd.yml:756-765,由本 diff 作为 R4-14 修复新增)。陈旧措辞还留在工作流 ~:728 的注释块中,恰好位于与之矛盾的 R4-14 注释上方。具体代价:docs/design/ 是入库的指导意见;其给出的理由(镜像"只会漂移")是在明确邀请后续把 CMD_PERM 读取当作漂移清理删掉——那样做会重新引入 R4-14 修复的缺陷(无权限的陌生人每 2h 至少发一次命令即可永久否决自动释放,因为被忽略的命令没有拒绝 ack、也永远不会被取代而过期);以该文档为依据审计 shepherd 的评审者同样会把权限读取误判为多余。修复:把该句替换为已落地的行为描述,并删除工作流注释块中陈旧的"此处刻意不做权限检查"一行。

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

- **The release lever gets its own enumeration** of the paused population
(needs-human ∩ takeover, stalest-first) — not the takeover display window
and not the needs-human display window: released PRs keep `needs-human`
and age back into that display window, so feeding the lever from it would
truncate exactly the fresh pauses that become release-eligible. All three
enumerations cap at 100 with loud saturation warnings; a display
enumeration failure degrades to an error row, and a paused-enumeration
failure skips the lever for that tick — the dashboard write (which
carries the liveness watermark) always runs.
- **The summary posts before the label removal**, dedup'd by its own marker
scoped to the current pause cycle (only markers newer than the latest cap
notice count), so a failed comment leaves both labels in place and the
whole release retries next tick; a failed removal finds the marker and
retries only the DELETE; and a re-armed-and-re-capped PR still gets its
second summary.
- **Stale-label heal:** a fork PR released by hand gets no release ack (the
route suppresses fork `unlabeled` events), so nothing else clears its
`needs-human`. The shepherd watches the awaiting-human pool for a
human-actor `unlabeled` event on the takeover label that is NEWER than the
latest label-apply (a stale unlabel from an earlier takeover cycle must
never heal this cycle's label), and clears the stale label — bounded per
tick, skip-vetoed, and never triggered by the bot's own auto-release.
- **Shepherd timing:** 15-minute tick with a per-tick release cap — a backlog
of expired PRs drains over a few ticks rather than one burst.

## Files affected

- `.github/workflows/qwen-autofix.yml` — env, cap-notice branch, six
label-removal sites.
- `.github/workflows/qwen-fleet-shepherd.yml` — env, takeover enumeration,
dashboard takeover table plus a read-only "Awaiting human" section
(released PRs keep `needs-human` and would otherwise vanish from every
surface), auto-release lever.

## Scope boundaries

- No changes to round caps, breakers, or review-bot behavior.
- No shepherd levers on takeover PRs other than auto-release.
- No notification/@-mention of maintainers (comment + label + dashboard only).
- `autofix/needs-human` on plain (non-takeover) bot PRs is applied by the same
scan path and shown on the dashboard, but the auto-release lever never
touches them (they have no takeover label to release).

## Open questions

- Default `AUTO_RELEASE_DAYS=3` — short enough to keep the pool clean, long
enough for a maintainer to re-arm over a weekend? Adjustable without a
deploy via the repo variable.
24 changes: 24 additions & 0 deletions scripts/tests/pr-self-report-label.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,10 @@ describe('pr-self-report-label', () => {
});
expect(race.removed).toBe(true);
expect(race.out).not.toContain('::warning::');
// R7-5: a 404 race means the end state holds → the success claim fires,
// the "did not land" claim must not.
expect(race.out).toContain('removed');
expect(race.out).not.toContain('removal did not land');
// Any other DELETE failure keeps the step green (the job only re-runs
// on the next PR event) but MUST surface — a silent run would claim
// "removed" while the label stays on the PR.
Expand All @@ -200,6 +204,26 @@ describe('pr-self-report-label', () => {
expect(failed.out).toContain('::warning::');
expect(failed.out).toContain('removal failed');
expect(failed.out).toContain('HTTP 500');
// R7-5: the LBL_DEL_FAILED branching — a failed DELETE must NOT claim
// the label was removed (the lying-log shape this change exists to kill).
expect(failed.out).toContain('removal did not land');
expect(failed.out).not.toContain('removed');
Comment on lines +207 to +210

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] R10-4: null Location 1 of 3 — the pr-self-report-label harness (R7-5 block). — Failure scenario: pattern finding — the 404-vs-other failure-classification boundary is unpinned: the DELETE-failure fixtures pass identically under the production loose *404* match and the strict HTTP 404 form, so nothing verifies a tightening at any of the three harnesses.

Suggested fix: 模式发现——404 与其他失败的分类边界无 pin:DELETE 失败 fixture 在生产宽松 *404* 匹配与严格 HTTP 404 形式下表现完全一致,因此三个 harness 中没有任何东西能验证收紧。失败场景:探针验证:在生产位点应用严格形式 mutant,194 个测试仍全绿;文本含 "404" 但并非 HTTP-404 响应的探针 fixture(如 HTTP 502: Bad Gateway (upstream retry of request 404))目前在 stop 分支被误判为已落地——发布 released ack 并移除 needs-human。该形状的边界 fixture 今天即为红色,可钉住 R10-1/R10-3 的修复;缺了它,"有测试覆盖"并不提供这种覆盖。

中文说明

probe-verified: the strict-form mutant at the production sites keeps all 194 tests green; and a probe fixture whose text contains "404" without being an HTTP-404 response (e.g. HTTP 502: Bad Gateway (upstream retry of request 404)) is today misclassified as landed at the stop arm — the released ack posts and needs-human is removed. A boundary fixture of that shape is red today and pins the R10-1/R10-3 fix; without it, "covered by tests" offers no such coverage.

建议修复:Add one fixture per harness whose error text contains "404" but is not an HTTP-404 response, asserting the failure classification (warning / release-failed / no cleanup).

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

// R10-1/R10-3: the tolerated token is exactly "HTTP 404" — a transport
// failure embedding a 404-bearing request URL must warn and report
// not-landed, never read as the already-off case (the loose *404*
// match hit the URL's PR number and claimed "removed").
const transport = run({
prAuthor: 'alice',
issueAuthors: 'bob',
Comment on lines +215 to +217

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 exact-token "HTTP 404" 404-tolerance on the six needs-human removal sites is behaviorally pinned at only one of them (the ack job, R10-3 — the only site with the adversarial bare-404-substring vector); the contract test pins only the DELETE command shape and the warning-string count. — Failure scenario: Mutation probe: regressing the /retry site from "HTTP 404" to 404 shipped green (both suites). A transport failure whose embedded request URL carries a 404-series PR number (issues/4041 — the exact shape this diff's own R10 test models) then reads as the tolerated already-off case, suppressing the ::warning:: on a failed removal; a stale autofix/needs-human lingers with no operational trace until the shepherd cleanup happens to heal it.

Suggested fix: Extend the R4-20 replay with a substring-transport deleteFail vector asserting removal failed IS emitted, and/or pin the six tolerance lines textually (expect(workflow.match(/[[ "${NH_ERR}" == *"HTTP 404"* ]]/g)).toHaveLength(6)).

中文说明

六个 needs-human 移除点上的精确 token "HTTP 404" 404 容忍,只在其中一个点(ack job,R10-3——唯一带对抗性裸-404-子串向量的点)有行为引脚;契约测试只引脚 DELETE 命令形态与警告字符串计数。突变探针:把 /retry 点还原成 404 后全部测试仍绿。失败场景:URL 内嵌 404 段 PR 号的传输层失败(issues/4041——本 diff 自己的 R10 测试所建模的形态)会被读成被容忍的'已移除'情形,抑制移除失败的 ::warning::;过期的 autofix/needs-human 会不留任何运维痕迹地滞留,直到 shepherd 清理碰巧治愈。修复:为 R4-20 replay 增加 substring-transport 向量并断言出现 removal failed,和/或文本引脚化六处容忍行。

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

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 without code change — the exact-token HTTP 404 tolerance is behaviorally pinned at only one of six needs-human removal sites (pr-self-report suite). The workflow's non-convergence brake engaged (diff over the window's growth budget for 2+ rounds, still not shrinking), so this round is a maintainer handoff and all code fixes are suspended pending the landing decision. Whether this lands in-PR or as a follow-up issue is the maintainer's call; thread left open.

中文说明

推迟处理、本轮未做代码改动 —— 精确 token HTTP 404 容忍在六个 needs-human 移除点中只有一处有行为引脚(pr-self-report 套件)。工作流的非收敛刹车已触发(diff 连续 2 轮以上超出窗口增长预算且仍在增长),本轮为移交维护者的交接轮,一切代码修复在落地决策前暂停。在 PR 内落地还是作为后续 issue 处理由维护者决定;线程保持开放。

hasLabel: true,
deleteFails:
'gh: Delete "https://api.github.com/repos/o/r/issues/4041/labels/review%2Fself-reported": dial tcp 140.82.121.4:443: connect: connection refused',
});
expect(transport.removed).toBe(true);
expect(transport.out).toContain('::warning::');
expect(transport.out).toContain('removal failed');
expect(transport.out).toContain('removal did not land');
expect(transport.out).not.toContain('removed');
// POST carries NO tolerance: a label that fails to apply must fail the
// step (the runBlock sets -e), not leave the PR unlabeled behind green.
expect(() =>
Expand Down
Loading