Repository navigation
fix(review): recheck paginated file inventory versions - #8086
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
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; declaration_source=runtime_reported
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
通过 CLI 读取大型 PR 的评审者,需要文件清单与所选提交版本一致。旧版本在 GraphQL 只返回前100个文件时转用 REST 分页;即使分页期间提交、基线或增删统计改变,只要文件数相同,仍可能把混合版本当成完整来源,导致审错内容和重复返工。
本次验证的改善是:分页完成后重新核对版本和统计,并拒绝重复路径;稳定版本继续返回完整清单,变化或读取失败明确保留为不完整来源。本次不改变审查权限、队列顺序、合并条件或调度,也不承诺跨请求的 GitHub 原子快照。
改动思路 / Approach
已有 provider 统一负责文件来源完整性;复用同一版本比较,将新增成本限制在必要的只读回查和局部去重,不引入第二套状态或权限判断。本次交付分页来源完整性修复及两种现有读取入口的回归验证;不扩展审批、合并、调度或远端原子性。
现有入口先读取 PR 版本与详情,详情不足时沿同一个 helper 分页。原实现仅在超过 API 上限、需要本地 Git 恢复时核对版本;本次让普通完整 REST 结果也使用已有的五字段比较,并在收集过程中拒绝重复路径。失败仍由原调用方处理:普通队列保留不完整结果,指定提交的读取明确报错,随后重新获取当前来源。稳定输入不增加人工确认、配置或复制步骤。
最强反对理由是额外一次 metadata 请求可能把瞬时网络故障转成 incomplete。但在需要精确提交证据的入口,明确重读比把另一版本标成完整更符合既有契约;无需为此增加缓存、第二个判断器或持久状态。分页后的采样仍不是远端原子快照,不能声称消除了所有并发变化。
具体改动 / Changes
完整 diff 为2文件,生产代码6+/2-,测试71+;没有文档、生成物、UI 或状态迁移。审查版本为 d69857a112be42abbf3d5ea24b5ceb7da2146e27,实际 diff 的不可变 merge base 为 71970fb03eb2ab90b353f0895bb1463ca7eaf236,区别于 GitHub 当前基线指针。
关键代码讲解
_fetch_complete_pr_files:在 REST 每页收集时用局部路径集合拒绝重复项;达到声明数量后,只要调用者提供了 snapshot,就重新读取 head、base、文件数和增删总量进行完整比较。任一不符或读回异常返回 None,不能靠相同数量通过。attach_pr_review_details:现有调用者已经把版本化 row 传给分页 helper;本次保留它的失败、列表顺序和结果装配规则,没有另设调用者分类逻辑。scan_github_pull_request_targets:指定准确 head 的公开读取复用同一个详情路径。新拒绝分支沿已有 detail read was incomplete 错误退出,没有把 source completeness 当成 review 或合并许可。
规格依据为 loopx/capabilities/pr_review_queue/README.md,spec_revision=71970fb03eb2ab90b353f0895bb1463ca7eaf236,以改动前的来源完整性与权限条款为准。原文没有编号,以下标签对应既有条款:INV-VERSION(head/base/统计围栏,版本变化为 incomplete)implemented;INV-COMPLETE(失败保留为不完整、稳定完整读取保持形状)implemented;INV-AUTHORITY(完整 API、已有本地 Git 恢复和 closeout 不扩权)implemented。对应证据分别是同一不可变 fixture 的两种入口反例、完整稳定观察逐值对照,以及 inventory/approval-closeout 全模块验证。
已搜索全部 helper 调用及现有 snapshot/Git 恢复实现;当前主干 provider 与这里的 base 仍是同一 Git blob,未把已合入能力重复当作新成果。复用成立,额外抽象没有当前调用者价值。集合属于本次调用内的派生值,不是新的状态词表,也不按字符串片段或文案猜测执行义务。
对主干的风险 / Risks
没有发现本 diff 的阻塞性正确性问题。关键反例是“文件数未变,但分页后版本已变”:同一16例 harness 通过真实生产 scan 入口运行,在 base 为2 PASS/14 FAIL,在 head 为16 PASS。七类负例覆盖 head、base、数量、增删统计、回读不可用和重复路径,两种入口均拒绝;普通队列保持可见的 incomplete,指定提交沿原错误退出。两个稳定正例的全部101行和完整输出逐值相等,没有忽略字段来制造一致。
| 验证 | 结果与边界 |
|---|---|
| 四个完整 provider、inventory、独立 review 和 closeout 模块 | PASS,197项 |
| 同一 base/head fixture 的普通/准确提交 scan | PASS;base14负例失败,head16例全部通过;传输被控制,完整性判断未被模拟 |
| 实际 source-checkout CLI 与真实 GitHub API | PASS;同一稳定192文件 PR 的来源版本、规模及 complete 一致;packet 只展示10个 key_files,仅这10行做了相等比较,未声称比对完整192行 |
| 两端 changed-file Ruff、配置的17文件 mypy 和 provider mypy | PASS |
| 配置的必需 CI Ruff 命令 | FAIL;两端同一 E731,位置 tests/test_manager_context_roundtrip.py:289,完整697字节失败输出完全相同,源文件、workflow、配置和依赖锁字节未变 |
| 标准 exact-diff premerge | PASS;直接检查和所选 canary 通过,无手动 hold;不授予合并权限 |
必需 Ruff 失败仍是失败,严格 change-quality 资格保留 FAILED 和合并阻塞;独立证据表明它在未修改的路径上,当前 policy26 允许保留本次正确性 APPROVE,不能把它写成全绿或要求本 PR 顺手修无关代码。更宽的额外 Ruff 诊断也在两端以同一120项失败、34个失败路径逐个 Git blob 未变,未混充配置的 CI 范围。
作者此前记录的语义 smoke 120秒超时保留为历史观察;本次 exact-head 标准检查在原限制下通过,未由一次成功推断历史原因或长期性能。按当前契约没有查询、轮询或等待远端 CI。真实 GitHub 实测是稳定来源集成,未模拟网络中的真实并发变更;101行反例测试承担这部分受控判别。恢复方式是按当前 source 重读并重新建立准确提交证据,没有后台重试或额外扣额。
我的整体评价 / Verdict
goal_achieved 仅指本次分页来源完整性修复的可验收任务。long_horizon=improved,依据是防止混合版本反复进入后续评审、失败后仍有原重读路线;user_experience=improved,依据是同一 CLI 在稳定输入下不增加人工步骤,而错误来源明确可见。这些是受影响路径的行为判断,没有建立模型采用、净 token、持续时延或完整人工成本收益。
架构 retain,范围 proportionate:一个既有 provider、一次必要的版本回查及局部集合,完整稳定结果保持;default_off_isolation=not_applicable,因为这是公开说明的默认正确性修复,没有新增可选能力或静默开启配置。权限 aligned,未改变 review、closeout、合并或调度授权。局部复用已经是可审查的简化,不需要为了减少行数移动别的 owner。
visual_review=not_applicable:检查的是 CLI JSON/provider 和未变化的展示调用者,没有渲染页面修改;渲染范围无待验项。远端原子快照、安装态 Host/模型采用、长期效率和完整192行现场相等均未验证。当前准确 head 的 APPROVE 与必需 lint/严格资格、GitHub readiness 及维护者合并权限分开,后者继续保留。
English verdict: APPROVE — d69857a; verified version-fenced pagination and duplicate rejection, stable-path parity retained; pre-existing required lint and strict qualification remain failed, with merge authority separate.
Goal And Delivered Outcome
修复大 PR 文件清单与精确 head 混源的问题。GraphQL 详情只返回前 100 个文件时,现有 provider 会通过 REST 分页补全;PR 若在分页期间换 head、更新 base 或改变统计,旧实现仅检查文件数量,仍可能把另一版本的文件作为完整来源。
本改动在现有
github_source入口复用 snapshot 回读,核对 head、base、文件数和增删行数;重复路径也拒绝。普通队列保留 source-incomplete 结果,精确目标读取沿原错误路径退出,调用方重新读取当前版本即可。没有新增审批、配置或审查协议。pull-request-reviewcapability.main, rebased onto71970fb03eb2ab90b353f0895bb1463ca7eaf236before submission.Author Declaration
loopx/capabilities/pr_review_queue/README.mdandskills/loopx-pr-review/SKILL.mdate7a6c8d5f09a8c7e5d6021aabce00223c9324fce._fetch_complete_pr_files.same_snapshotafter ordinary paginated reads; queue and exact-target drift regressionsstatusCheckRollupquery; no CI polling or waitingScope And Continuation
Complete within this provider fix. The same existing Python IO owner serves queue discovery and exact targets; TypeScript review decisions and publication/merge authority are unchanged. No new owner, schema, persistence or compatibility branch is introduced. Reusing the existing version check is the bounded simplification; a new snapshot framework is unnecessary.
The version readback adds one small metadata read only when ordinary REST file completion is needed. It detects observed source drift, without claiming server-side snapshot isolation. Final review publication still requires the existing fresh-head check.
Validation
tests/test_pr_review_github_scan.pyplus Git inventory recovery, independent-review and approval-closeout suites: 197 passed. Includes existing >3000-file Git recovery and ordinary non-paginated reads.d1ed715198bc3d9eafb0fc7ff38afa63f2e79510: complete inventory of 188 files, matching 18,289 additions / 1,979 deletions. This verifies stable read success; concurrent mutation was simulated at the provider boundary.71970fb03eb2ab90b353f0895bb1463ca7eaf236: all direct hygiene/bilingual/compile checks and both selected canaries passed; maintainability 7.33s, semantic 31.28s. The original final-head semantic timeout at 120.553s and earlier pre-rebase pass at 88.53s remain historical results. No source, workload or 120-second limit changed.Frontend / Visual Evidence
UI impact: none. This fixes an existing read-only provider's source-integrity check; existing capability settings and CLI failure/retry paths remain the journey. No rendered surface changed.
Type of Change
LoopX Area
Shared-authority RFC fixture impact
N/A: no authority-store, runtime routing or persistence change.
Boundary Checklist