fix: complete Klaud final sweep lifecycle / 完善 Klaud 最终扫描流程 - #2843
fix: complete Klaud final sweep lifecycle / 完善 Klaud 最终扫描流程#2843adibarra wants to merge 1 commit into
Conversation
定向验证后将候选 PR 标记为 ready,并在修复前移除最终扫描标签、恢复草稿状态;Stop hook 同时验证精确 head 的可复用最终扫描。
| query = urlencode({'event': 'pull_request', 'branch': branch, 'per_page': 100, | ||
| 'created': '>=' + os.environ['KLAUDE_STARTED_AT']}) | ||
| sweep_pages = github_read(repository, 'actions/workflows/run-sweep.yml/runs?' + query, paginate=True) | ||
| sweep_runs = [run for page in sweep_pages for run in page['workflow_runs']] | ||
| if any(page['total_count'] > len(sweep_runs) for page in sweep_pages): | ||
| raise ValueError('Incomplete sweep run listing') | ||
| exact_runs = [run for run in sweep_runs if run['head_sha'] == pull['head']['sha']] | ||
| if not exact_runs: | ||
| return {'decision': 'block', 'reason': 'No final run-sweep.yml run exists for the exact PR head. Keep full-sweep-enabled applied and wait for the labeled run to appear.'} | ||
| sweep = max(exact_runs, key=lambda run: run['created_at']) | ||
| if sweep['status'] != 'completed' or not sweep.get('conclusion'): | ||
| return {'decision': 'block', 'reason': 'The final run-sweep.yml run is still queued or running. Continue monitoring every job and do not stop before it is terminal.'} | ||
| if sweep['conclusion'] != 'success': | ||
| return {'decision': 'block', 'reason': 'The final run-sweep.yml run did not succeed. Remove full-sweep-enabled and return the PR to draft before any repair push, then diagnose, repair within budget and repeat final validation.'} |
There was a problem hiding this comment.
🔴 check_stop() treats the highest-created_at run-sweep.yml run for the PR's exact head SHA as authoritative, but run-sweep.yml also re-triggers (via 'labeled'/'unlabeled' pull_request events, including labels unrelated to full-sweep e.g. skip_queue, ci-patchwork, ci-checklist-complete) without a new commit. A run whose check-changelog job is skipped (label not in its if-list) concludes 'skipped', which never equals 'success'; if such a run lands after the real successful full sweep, max() picks it and check_stop wrongly reports the final sweep failed, telling the agent to strip full-sweep-enabled and revert to draft/repair despite a real prior success. …
Extended reasoning...
…Fix: only compare against runs whose jobs actually executed the check-changelog logic (e.g. filter out event actions that the workflow's own if-condition would skip, or key off run['status']/job outcomes rather than the newest timestamp) so an unrelated label churn can't mask a completed successful full sweep.
PR has full-sweep-enabled, is ready, and its real run-sweep.yml run for head H succeeds with reusable artifacts. Afterward some other tracked label (e.g. ci-checklist-complete) is added or removed on the same PR with no new commit; run-sweep.yml's pull_request 'labeled'/'unlabeled' trigger fires again for head H, but check-changelog's job-level if evaluates false for that label, so the job (and everything depending on it) is skipped and the run concludes 'skipped'. check_stop() at main.py:185-192 selects exact_runs by head_sha==H, takes max by created_at (the new skipped run), sees status=='completed' but conclusion=='skipped' != 'success', and returns the block reason at line 192 instructing the agent to remove full-sweep-enabled and return to draft before repairing —…
Verification: normal — new code added by this PR (utils/klaude/main.py:179-192) selects the "final" sweep with sweep = max(exact_runs, key=created_at) and blocks stop whenever that run's conclusion != 'success', with no filter on conclusion or job outcome. run-sweep.yml triggers on pull_request labeled/unlabeled (lines 33-42) gated by paths: perf-changelog.yaml — which a full-sweep PR always modifies…
Summary / 摘要
Klaud previously kept its candidate PR draft while applying
full-sweep-enabled, sorun-sweep.ymlskipped the final reusable sweep. It also had no mechanical guard against stopping during that final validation.此前 Klaud 会在候选 PR 仍为草稿时添加
full-sweep-enabled,导致run-sweep.yml跳过最终可复用扫描;同时也缺少阻止 agent 在最终验证期间提前结束的机制。This change makes Klaud mark the PR ready before applying the final-sweep label. If the sweep fails, Klaud removes the label and returns the PR to draft before pushing repairs, preventing each intermediate push from launching another full sweep. The Stop hook now tracks the candidate's open PR, exact head SHA, final
run-sweep.ymlstate and reusable artifacts.本次修改要求 Klaud 在添加最终扫描标签前将 PR 标记为 ready。扫描失败时,Klaud 会先移除标签并将 PR 改回草稿,再推送修复,避免每次中间推送触发新的完整扫描。Stop hook 现在会检查候选的开放 PR、精确 head SHA、最终
run-sweep.yml状态和可复用产物。Validation / 验证
actionlint .github/workflows/klaude-plan.yml .github/workflows/klaude-candidate.ymlPython compile check with
uvManual Stop-hook scenarios covering targeted work, draft/missing/running/failed final sweeps, missing artifacts and successful reusable completion
zizmor 1.30.0 standard and auditor modes: no new findings; existing baseline is 4 low, 3 medium and 0 high findings in auditor mode
使用
uv完成 Python 编译检查手动覆盖定向运行、草稿/缺失/运行中/失败的最终扫描、缺少产物及成功复用等 Stop-hook 场景
zizmor 1.30.0 标准与 auditor 模式均无新增问题;auditor 模式的既有基线为 4 个 low、3 个 medium、0 个 high
Note
Medium Risk
Changes Klaud Cold agent prompts and the Stop hook that gates session completion; misbehavior could skip final sweeps or leave agents running longer, but scope is limited to auto-sweep CI orchestration rather than production serving or auth.
Overview
Fixes a gap where Klaud could label a draft PR with
full-sweep-enabled, sorun-sweep.ymlnever ran the final reusable validation, and the agent could stop before that work finished.The candidate workflow now sets
KLAUDE_BRANCH, keeps the PR draft through targeted e2e attempts, and after a passing targeted run instructs Klaud to push the changelog, rungh pr ready(without requesting review), then applyfull-sweep-enabled. If the final sweep fails, it must remove the label and return the PR to draft before any repair push so intermediate commits do not re-trigger full sweeps.check-stopstill blocks on in-flight owned e2e runs, and whenfull-sweep-enabledis present it also blocks until the open PR is non-draft, a successfulrun-sweep.ymlexists for the exact head SHA, and that run has non-expired reusable benchmark/eval artifacts. Docs (docs/klaude*.md,KLAUD_DEBUG.md§7.3) describe the same lifecycle.Reviewed by Cursor Bugbot for commit 3d93801. Bugbot is set up for automated code reviews on this repo. Configure here.