Repository navigation
fix(pr-review): allow authorized bypass of readiness holds - #7992
Conversation
Signed-off-by: huangruiteng <huangrt01@163.com>
9663c2d to
8ff4a9a
Compare
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; reasoning_effort=max; runtime_reported; observation_id=85ce6a76f6a8181954175b6c3558ea84b69d6115c425763a9b72b0829234c80c
Exact head 8ff4a9a3063f3ab2195e8a1efad633d9d36d8d86;base 44337e3cb5cbe3e1621550e1fe741853ba5b5a45。未发现本次改动造成的阻断性问题,结论 APPROVE。这份审查不授予合并权限,汇总验证的既有失败保留如下。
动机
已有显式维护者授权、完成当前提交审查和本地验证的合并操作者。当剩余阻塞只是 GitHub 审查策略或远端检查状态时,旧载荷仍把所有 ready=false 都描述成不可 bypass,授权后的下一步也被错误阻断。新载荷保留 ready=false 和非零退出码,另说明本次阻塞是否全部属于可授权覆盖的策略范围;缺少审查、未解决线程、变更后的 head 和冲突仍返回不可覆盖。本 PR 不执行合并,不授予授权,不把覆盖范围提示当成审查或验证通过,也不改变 CI 等待的默认配置。
这里的 readiness 是合并前的当前事实判断,bypass scope 是“哪些剩余策略阻塞可以在另有授权时覆盖”的条件说明。原来的绝对否定把这两件事混在一起,导致操作者即使已有授权和完整证据,也收不到可执行的正确解释。修复的可观察结果是载荷表达准确;本审查没有把一次真实合并或模型采纳当成已完成的结果。
改动思路
复用现有 readiness blocker 集合派生覆盖范围,并同步现有操作文档;不新增授权存储、配置开关或合并执行器。当前 PR 边界为八文件 +126/-38 的 readiness 诊断及其操作契约修复。仅改文档会继续输出相反的机器提示;仅改布尔值会留下相反的操作义务。既有 owner 足够,局部白名单比新权限系统更小。 ready、阻塞原因、当前 head 和返回码继续真实反映普通路径;新增的 admin_bypass_requires 列出审查、本地验证、线程/意见处理、开放且可合并的原 head,以及单独的授权。grants_merge_authority 仍为 false,不能只看到一个 true 就执行合并。
先于 diff 读取了 base 44337e3cb5cbe3e1621550e1fe741853ba5b5a45 的 skills/loopx-pr-merge/SKILL.md、AGENTS.md 和 capability README。它们规定的是旧绝对就绪门;未发现独立、先于本实现且覆盖新 bypass 语义的已接受规范,因此规范判断为 no_spec。我按维护者本次提案逐项验证保留的审查、验证、head、冲突和授权边界,不把本 PR 自己改写的文档当成独立证明。现有 repository experience 仅用于关注真实调用与恢复,并未变成额外验收门。
| 输入 | base | 当前 head |
|---|---|---|
| 完整审查,仅策略阻塞 | ready=false,scope=false | ready=false,scope=true,authority=false |
| 审查缺失/过期、线程未解决、head 改变或冲突 | 不可覆盖 | 仍不可覆盖 |
| 普通就绪输入 | ready=true | ready=true,仍无合并授权 |
这张表来自实际 fixture 执行结果;它说明条件范围,不证明操作者已满足列出的授权义务。
具体改动
关键代码讲解
_ADMIN_BYPASS_OVERRIDABLE_BLOCKERS 复用已有 blocker code,只纳入 GitHub review policy 和远端 check 状态。没有用错误文案或 substring 猜测阻塞类型,也没有新增 canonical 授权状态。
build_merge_readiness 要求每一个 blocker 都在集合中;混入审查、线程、head 或冲突阻塞就返回 false。空集合的 true 只是没有需要覆盖的阻塞,普通路径无需 bypass。既有 review history、thread summary 和 mergeability owner 继续生成事实,函数没有合并执行器。
test_explicit_admin_bypass_may_override_a_readiness_policy_hold 覆盖 ready=false 的新条件说明,并保留 stale-body 反例。文档、两个 skill、AGENTS、repair pattern 和既有 smoke 同步同一条两部分义务:可以覆盖策略 hold,不能替代证据或授权。原有 bilingual 检查失败仍阻止合并。
我另外独立构造 17 组输入,各自在 builder 和安装 console 的离线 fixture 路径执行:正常、策略 hold、CI failure/pending/missing、关闭、Draft、换头、无审查、旧正文、REQUEST_CHANGES、不完整/未解决线程、冲突、未知合并状态,以及另一 reviewer 的普通阻断意见。每个 console fixture 都另放一个不合格 PR;它没有污染目标判断。所有结果均没有授予 merge authority。
对主干的风险
head369/base368项相关 Python 测试通过;17组独立边界案例同时走 builder 和安装 console fixture;每次 fixture 含另一个不合格 PR,目标选择不受影响。策略阻塞仍 exit1/ready=false,所有结果 grants_merge_authority=false。 wait_for_ci=false 的当前任务没有查询、轮询或等待远端 CI;探针中的 CI 状态都是公开安全的合成 fixture。全局默认 wait=true 未改,范围 true 也不表示本地必需验证已完成。
汇总 premerge 不是全绿:6 项 direct 通过,19 项 selected 中 17 项通过、1 项 inherited formatter advisory、1 项 lifecycle 失败;manual holds=0。issue-fix-pr-lifecycle-smoke.py 在隔离原生 canary runner 的不可变 base 和当前 head 都在第 571 行访问 gate_item['evidence'],得到同一 KeyError: 'evidence'。该 lifecycle 因果路径未改,独立 readiness 正反例另行通过,归为 pre-existing unrelated,不能声称已修好。
formatter ratchet 的 render_canonical_todo_sections oversized-function 记录也在两侧完整相同,magnitude regressions=0。早期探针启动/路由错误与修正后的实际 console 执行分别保留,未计入产品通过。新 diagnostic 是自动变化,旧读取者需要理解其条件语义;这也是同步操作文本的原因。
我的整体评价
复用现有 readiness blocker 集合派生覆盖范围,并同步现有操作文档;不新增授权存储、配置开关或合并执行器。当前 PR 边界为八文件 +126/-38 的 readiness 诊断及其操作契约修复。 最强反例是“只要有一个策略阻塞就允许覆盖,顺便吞掉旧审查、未解决意见或冲突”;逐一和混合输入、另一 reviewer 的普通阻断意见、精确 head 改变均返回不可覆盖,排除了这个方向。没有新增用户确认轮次或配置负担;有授权的操作者得到准确说明,缺少条件的操作者仍能看到具体停止原因。
已检查完整 CLI JSON、返回码与所有改动操作文本;没有页面、布局或可视 UI 变更,visual review 不适用。未执行真实 admin merge、远端 CI 或安装后的 Agent 采纳测试;fixture 验证当前源码 console 和规则,不证明实际 GitHub 合并许可。 本次证明的是当前源码 CLI 的范围投影和义务一致性。保留既有独立授权及 closeout;本地验证失败的后续修复和当前 PR 的代码审查结论分别报告,不以绕过诊断来宣布通过所有合并门。
English verdict: APPROVE. The exact head preserves truthful readiness and separate authority while identifying conditionally overridable policy holds. Independent console counterexamples pass. The unchanged lifecycle failure and formatter advisory remain disclosed; remote CI was not consulted and no merge was performed.
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max
审查提交:8ff4a9a3063f3ab2195e8a1efad633d9d36d8d86。PR 已于2026-11-03 16:24:50 UTC 合并为 0098a0918efba50606a32f6190033abadef0fe87,已有同头批准。以下按新发现的独立反例作合并后审查,发现一项需要修复的 P2;本审查未执行合并或管理员操作。
动机 / Motivation
准备合并已评审 PR 的维护者,需要区分普通 readiness 与已有明确授权的管理员绕过。
旧说明把 readiness=false 一律描述成无法绕过;本 PR 允许在证据、线程、当前 head 和合并性均成立时处理策略阻塞。
本轮确认原 readiness 和拒绝结果基本保留,但 UNKNOWN 或缺失的合并性仍被新字段报告为可绕过,当前前置条件没有成立。
本 PR 不授予合并权,不执行合并,也不让缺失评审、本地验证、未解决 finding、变化的 head 或未知合并性成为可忽略条件。
改动思路 / Approach
把可绕过范围派生自现有 blocker owner,比新建审批状态或第二套 readiness 规则更合适;但派生前必须确认非策略前提,不能把未检查到的合并性当作已成立。
当前 PR 只改变只读 readiness 的条件说明与操作指引;最小修复是让未知或缺失 mergeability 保持不可绕过,并在原 CLI fixture 矩阵补齐这两个分支。
不修改这个问题会继续留下“有授权但指令称绝对不可绕过”的矛盾。当前方案的成本很小:一个既有 blocker 集合及其派生诊断,并同步原操作说明;没有新增配置、人工审批状态、写权限或合并执行器。这个方向可以成立,无需为一处条件说明创建新的协议层。但“所有已列出的 blocker 都是策略项”不足以证明“所有非策略证据都已成立”,遗漏的 UNKNOWN 正是两者区别。
具体改动 / Changes
依据先读的 skills/loopx-pr-merge/SKILL.md,spec_revision 44337e3cb5cbe3e1621550e1fe741853ba5b5a45,以及 PR 明示的有界策略变更。Decision-Precondition 的精确 head 评审和必要验证仍必须满足;Configured-CI-Waiting 不授予 bypass/merge 权限;Mergeability-prerequisite 是本提案自己保留的 open、unchanged、mergeable 条件,当前未满足。没有把旧版 blanket ready-only 文本当作不可修改的永久政策;问题在新方案与自己保留的前提矛盾。
完整差异为8文件,+126/-38:1个运行时文件、4个 Agent 指令面、2个测试/示例和1个 capability 文档。已检查完整差异与现有 CLI/归一化/观察调用方。新的字段是现有事实的派生投影,不是新授权事实;本地 exact-token 集合复用已有 blocker vocabulary,不涉及字符串子串分类。
关键代码讲解
- _ADMIN_BYPASS_OVERRIDABLE_BLOCKERS:列出现有策略 blocker。未知 code 默认不属于集合,这一点合理;但未生成的证据 blocker 也不会参与集合判断。
- build_merge_readiness:原
ready、head/review/thread 检查不变,新字段在第110–112行由 blocker 列表推导。前面的合并性分支只在 BEHIND 或 merge_state 本身 UNKNOWN 时标记未验证;BLOCKED 加 UNKNOWN 会落到可绕过策略项。 - build_pr_merge_readiness_packet:既有生产归一化与 CLI 共用。省略 mergeable 也会得到 UNKNOWN,所以这是当前公共入口可到达的输入,不是绕过 owner 手工拼私有结果。
对主干的风险 / Risks
[P2] 确认合并性后才能报告可绕过。 以现有公开 _merge_ready_pr fixture 为起点,保持有效当前 head 批准、完整无未决线程及两项成功的合成检查,只设置 mergeStateStatus=BLOCKED 并改变 mergeable。通过实际 pr-review --fixture ... --check-merge-readiness ... 在不可变基线和当前提交各运行六个用例:
| mergeability / 其他状态 | 基线 override | 当前 override | 独立预期 |
|---|---|---|---|
| MERGEABLE | false | true | 可条件绕过策略项 |
| UNKNOWN | false | true | 必须保留未验证,false |
| 缺失,归一为 UNKNOWN | false | true | 必须保留未验证,false |
| CONFLICTING、CLOSED、未解决线程 | false | false | 不可绕过 |
十二次调用的 ready=false 与退出码1仍保留,因此不是已经发生了一次越权合并;错误在向后续操作者报告的绕过资格。当前 README 明确说缺失 mergeability evidence 时此字段为 false,requires 列表也要求 open_unchanged_mergeable_head。请在原 owner 中先要求确认 MERGEABLE,或把未知/缺失归入现有不可绕过的 unverified blocker,并补这两个真实 CLI 分支。不要通过删除文档里的前提来消除矛盾。
语义与 CI 对齐
三个完整本地模块为343 PASS,基线342 PASS;两边变更 Python 路径 Ruff 和配置指定17模块 mypy 均 PASS,RFC成对、diff、公私边界检查 PASS。已有新 fixture 只证明 MERGEABLE 这一侧,不能替代 UNKNOWN 反例。
标准 premerge 的6个直接检查 PASS;19个选中检查中17 PASS、1项 issue-fix lifecycle FAIL、1项继承的 ratchet advisory。严格质量回执保持 FAIL,原生 gate 为 quality_invalid_receipt。该 lifecycle smoke 在不可变基线与当前同命令均出现 KeyError: evidence;此处只报告这两次观察,不用它免除当前 predicate 的修复。上述状态与新 finding 分开保留,不称整个门禁通过。合成 fixture 中的成功检查不是远端 CI 结果;没有查询、轮询或等待 CI。
我的整体评价 / Verdict
合并后审查:需要修复。现有 owner、派生状态和小范围同步说明是合适边界;修复应直接补全合并性判断,保留正常 readiness、非策略前提和单独授权,无需增加开关或用户确认轮次。新字段的 UNKNOWN 分支使长程交付与操作旅程资格仍为 not_yet_proven;修复后用当前精确 head 重做这组反例与既有 suites。
已检查现有 CLI、Host 输入与操作说明;没有渲染页面、控件或布局变更,视觉评审不适用。 未把源码 CLI 验证扩展为已安装宿主、真实模型或完整用户收益资格。
未发现需要新增第二套状态或兼容框架的理由。这里评审的是条件诊断的真实性;review、验证、线程解决、merge readiness 和实际合并权限继续分别成立,不能从字段存在、安装技能或当前评审推导后续动作授权。
English verdict: REQUEST_CHANGES — post-merge audit of 8ff4a9a: UNKNOWN or omitted mergeability must not advertise admin-bypass eligibility. Valid conditional-policy controls pass; the missing-evidence branch requires a fix and the strict local gate remains failing.
| blockers.append("repository_merge_state_blocked") | ||
|
|
||
| blockers = list(dict.fromkeys(blockers)) | ||
| admin_bypass_overrides_this_gate = not any( |
There was a problem hiding this comment.
[P2] 合并后发现的独立反例:有效同头审查、完整线程和成功合成检查均保持不变,仅令 mergeStateStatus=BLOCKED,mergeable=UNKNOWN 或省略。实际 fixture CLI 两种情况都返回 admin_bypass_overrides_this_gate=true;不可变基线为 false。这里的未知合并性没有被前面的分支加入非策略 blocker,所以仅检查现有 blocker 的集合不足以保证新 README 声明的 open_unchanged_mergeable_head。请先确认 MERGEABLE 或把未知/缺失归入不可绕过的 unverified,并保留 ready=false、authority=false 与对应 CLI 控制用例。
Summary
Fixes the contradictory admin-bypass contract for PR merge readiness.
ready=falseremains a truthful readiness result: it identifies concrete blockers and still fails closed for callers without merge authorization. With explicit maintainer authorization, however, admin bypass may now override a readiness or GitHub review-policy hold instead of being described everywhere as an absolute blocker.The bypass remains narrow. It does not replace:
Semantic changes
pull_request_merge_readiness_v0.authoritynow reports whether every blocker in the current observation is within the admin-bypass scope, scopes that override, and lists the evidence and authority prerequisites that remain mandatory. A missing/stale exact review, incomplete or unresolved thread, changed head, or unmergeable state still makes the override field false.AGENTS.md, and public smoke now use the same two-part rule: report readiness truthfully, allow an explicitly authorized bypass of readiness policy holds, and preserve review/evidence/thread/head/mergeability/authority gates.ready=falseonly because GitHub still reportsREVIEW_REQUIRED; it proves the result remainsready=false, requires admin bypass, and carries the corrected override semantics when the exact reviewed head is otherwise valid.Validation
uv run --extra test python -m pytest tests/test_pr_review_github_scan.py -q: 72 passed.uv run --extra test python -m pytest tests/capabilities/test_pr_review_result_check.py tests/capabilities/test_pr_review_queue.py -q: 271 passed.uv run --extra test python examples/pr-review-command-smoke.py: passed.uv run --extra test python examples/semantic-vocabulary-drift-smoke.py: passed after installing the repository-root npm dev dependencies.git diff --checkand the RFC bilingual check: passed.uv run --extra test loopx canary premerge --from-git-diff --git-diff-base origin/main: all changed-surface checks passed except one pre-existingissue-fix-pr-lifecycle-smokefailure. The sameKeyError: evidencefailure reproduces atorigin/main(44337e3cb5) with the unchanged smoke. The known maintainability-ratchet advisory remains inherited and unrelated to this diff.CI was not polled or waited on under the
loopx-metareview policy.