Weight approvals by changed production-line ownership
按变更生产代码行的归属调整审批权重
A fixed one-point reviewer weight does not reflect authorship of the code a pull request changes. Directory-level ownership can reward unrelated code in the same folder and distort the contribution relevant to the review.
English
Problem
A fixed one-point reviewer weight does not reflect authorship of the code a pull request changes. Directory-level ownership can reward unrelated code in the same folder and distort the contribution relevant to the review.
Decision
The approval policy scales a one-point approval by min(2, 1 + 4 × ownedLines / totalLines) over changed old production lines. Ownership of 0% gives one point, 12.5% gives 1.5 points, and 25% or more gives two points. Scores are not rounded before comparison with the two-point success threshold. The merge base supplies both classification and blame, while GitHub associates blame commits with reviewer accounts. Unlinked authors remain in the denominator. Additions have no prior owner and contribute no lines; an empty denominator produces no boost.
The publisher marks the head pending before dependency setup and evaluation, so an interrupted history fetch cannot preserve an earlier success. It uses the live base branch and exact reviewed head, reads complete Git history without checking out PR code, and skips attribution when base points or blockers already decide the result. A maintained lexer separates comments from code across the repository’s source languages. Author lookups batch commits and all reviewers share one measurement. Existing pending-status semantics and review-event validation remain independent requirements.
Alternatives considered
A hard cutoff. Linear weighting distinguishes partial ownership below 25%. The 25% cap lets a reviewer responsible for one quarter of the changed old code satisfy the two-point requirement; additional ownership does not increase their vote beyond that requirement.
Directory-weighted ownership. Code elsewhere in a changed directory does not establish ownership of the lines under review.
Include newly added lines in the denominator. Those lines have no merge-base owner and would dilute the authorship signal for existing code.
Match author names or email strings to reviewer logins. Display names are not account identifiers, and one account can own commits under multiple emails. GitHub’s commit-author account association supplies that mapping.
Consequences
History fetching dominates cold execution. Complete history is required before selecting the merge base: a shallow apparent ancestor can exclude changes from the denominator, so shallow classification cannot safely decide that blame is unnecessary. On 2026-09-11, local measurements of PRs #3969 and #3977 count 73 and 535 old production lines across 4 and 14 files. Three local runs take 0.31–0.32 seconds and 0.87–0.93 seconds; one batched author query adds approximately one second per PR. A fresh single-branch bare clone of master takes 47 seconds on the same host. These are host observations, not CI time guarantees.
Blame measures last-touch authorship, not review quality or semantic expertise. The production classifier excludes unsupported source locations and file extensions; adding shipped source outside its inventory requires extending that classifier. Lexer classification is lexical rather than a semantic test of executable behavior. Evaluation errors retain the error status instead of silently awarding or withholding the boost.
Verification
Policy tests cover the threshold, zero denominators, blockers, shared measurements, and failed attribution. Author tests cover batching, account aggregation, and incomplete responses. Git integration tests exercise merge bases, renames, deletions, mixed comment lines, exclusions, shallow history, and fetching without checking out PR code.
中文
Problem
固定的一分评审权重无法反映评审者对拉取请求所修改代码的作者贡献。目录级归属可能奖励同一文件夹中的无关代码,扭曲与本次评审有关的贡献。
Decision
审批策略 按变更旧生产代码行的归属比例,以 min(2, 1 + 4 × ownedLines / totalLines) 调整一分批准的权重。归属比例为 0% 时计一分,12.5% 时计 1.5 分,25% 及以上时计两分。分数在与两分通过线比较前不做舍入。合并基点同时提供代码分类和 blame 依据,GitHub 将归属提交关联到评审者账号。无法关联账号的作者仍计入分母。新增行没有原作者,不计入行数;分母为空时不提升权重。
发布器在依赖安装和评估前将头提交标记为待定,避免历史拉取中断后保留此前的成功状态。它使用实时 base 分支和被评审的精确 head,读取完整 Git 历史,不检出 PR 代码;基础分数或阻塞评审已决定结果时跳过归属计算。维护中的词法分析器区分仓库各源码语言中的注释与代码。作者查询按提交批量执行,所有评审者共用一次统计。现有的待定状态语义和评审事件验证仍是独立要求。
Alternatives considered
硬阈值。 线性权重区分 25% 以下的部分归属。25% 封顶让负责四分之一变更旧代码的评审者满足两分要求;更多归属不会使其票数超过该要求。
目录加权归属。 变更目录中其他代码的归属不能证明待评审代码行的归属。
将新增行计入分母。 这些行没有合并基点上的作者,会稀释既有代码的作者贡献信号。
将作者姓名或邮箱字符串与评审者登录名匹配。 显示名称不是账号标识,一个账号也可能使用多个邮箱提交代码。GitHub 的提交作者账号关联提供该映射。
Consequences
冷启动的主要开销是拉取历史。选择合并基点前必须具备完整历史:浅历史中看似共同祖先的提交可能使部分变更被排除出分母,因此不能据此安全判定无需 blame。2026-09-11,在本机测量 PR #3969 和 #3977,得到 4 和 14 个文件中的 73 和 535 行旧生产代码。三次本地运行分别耗时 0.31–0.32 秒和 0.87–0.93 秒;每个 PR 的一次批量作者查询额外耗时约一秒。同一主机上,全新单分支裸克隆 master 耗时 47 秒。这些是本机观测值,不是 CI 耗时保证。
Blame 衡量最后修改者归属,不代表评审质量或语义上的专业能力。生产代码分类器排除未支持的源码位置和扩展名;在其清单之外添加交付源码时,必须扩展分类器。词法分类不判断代码是否在语义上可执行。评估错误保留错误状态,不静默授予或取消加权。
Verification
策略测试覆盖阈值、零分母、阻塞评审、共享统计和归属计算失败。作者测试覆盖批量查询、账号聚合和不完整响应。Git 集成测试验证合并基点、重命名、删除、混合注释行、排除规则、浅历史,以及不检出 PR 代码的拉取过程。