HelixHarness 生成的改动不敢直接合——是规则没写清还是评审缺位?

文章导读
先给判断方向:拿到 HelixHarness 生成的改动不敢合,通常不是“规则没写清”和“评审缺位”二选一,而是两件事处在不同环节——规则决定改动“能不能被生成”,评审决定改动“要不要被人看过”。可行的排查顺序是先按文件把改动归类,看有没有落到任务范围之外的目录;再对照规则条目,确认是规则没覆盖这类目录,还是规则写了但没被读进去。前者补配置,后者查加载路径。两边都补完,再在进入人工评审前加一道自动
📋 目录
  1. A 把这次产出的改动按文件归类
  2. B 对照规则条目检查约束是否覆盖这类改动
  3. C 在配置里补一条针对该类目录的约束并验证
  4. D 补一道进入人工评审前的自动检查
  5. E 记录一次完整闭环供团队复用
A A

先给判断方向:拿到 HelixHarness 生成的改动不敢合,通常不是“规则没写清”和“评审缺位”二选一,而是两件事处在不同环节——规则决定改动“能不能被生成”,评审决定改动“要不要被人看过”。可行的排查顺序是先按文件把改动归类,看有没有落到任务范围之外的目录;再对照规则条目,确认是规则没覆盖这类目录,还是规则写了但没被读进去。前者补配置,后者查加载路径。两边都补完,再在进入人工评审前加一道自动检查,把明显不该出现的改动挡在评审之前。下面每一步都能用差异输出、规则命中日志和命令返回值验证,不依赖对框架行为的猜测。

HelixHarness 产出不敢直接合,先分清是“约束不足”还是“约束没生效”。做法:用 diff 按目录归类改动,逐条对照 rules 配置,看越界目录是没写规则还是规则未加载;补一条最小约束并验证命中,再在评审前加自动检查。边界:规则只能限制生成范围,不能替代人对业务意图的判断;涉及发布、数据结构、权限文件的改动仍需人工确认。具体子命令以本地 helixharness `--help` 为准。

把这次产出的改动按文件归类

不要先读 diff 内容,先看改动落在哪些目录。用两个命令就够:git diff `--stat` 看每个文件改了行数,git diff `--name-only` 拿到纯路径列表再按目录聚合。目的是把“改了 8 个文件”变成“改了 3 个 service 文件、1 个配置文件、4 个迁移脚本”,后面的判断才有依据。

# 只看本次生成的改动范围
 git diff `--name-only` HEAD~1 > /tmp/changed.txt
git diff `--stat` HEAD~1

# 按顶层目录归类,看改动分布
awk -F/ '{print $1"/"$2}' /tmp/changed.txt | sort | uniq -c | sort -rn

归类之后按三条依据判断是否越界:改动目录是否落在任务描述声明的模块内;是否出现了该类任务本不该碰的目录(部署清单、数据库迁移、鉴权与密钥配置、CI 脚本);删除和重命名的文件是否多于新增。第三条常被忽略——生成工具倾向于“顺手重构”,一次任务里出现跨模块的重命名,基本可以直接判定为超出意图。如果任务本身就要求改配置或迁移,把它写进任务描述,而不是靠评审时口头解释。

对照规则条目检查约束是否覆盖这类改动

把上一步归类出的目录,逐个去 rules 配置里找对应条目。摘录时只记三样:条目 id、匹配的路径 glob、允许的动作(create / modify / delete)。如果越界目录在配置里根本找不到条目,是规则缺口;如果条目存在但生成结果与条目不符,是规则没生效,往下走不同方向。

# .helixharness/rules.yaml 摘录示例
rules:
  - id: allow-src-service
    paths: ["src/service/**"]
    actions: [create, modify]
  - id: allow-docs
    paths: ["docs/**"]
    actions: [create, modify]
# 缺口位置:deploy/**、migrations/**、config/security/** 均无条目

判断规则是否生效,看三个可观察点:规则文件在运行日志里是否出现在加载列表,条目数是否与文件一致;生成时是否有 rule hit 之类的命中记录,没有命中记录说明匹配没走到;把一条已知会被拒绝的路径交给 dry-run,看是否返回 deny。若日志里加载条数为 0、或加载路径指向了仓库外的旧配置,属未生效,先修加载路径,不要再加新条目——新条目同样读不进去。

在配置里补一条针对该类目录的约束并验证

补规则时按最小改动来:只针对越界的那一类目录加一条 deny 或“需人工确认”条目,不要顺手重写整个 rules 文件。这样验证结果可归因,出问题也容易回退。

# 追加到 .helixharness/rules.yaml
rules:
  - id: guard-infra
    paths:
      - "deploy/**"
      - "migrations/**"
      - "config/security/**"
    actions: [create, modify, delete]
    effect: deny            # deny | allow
    reason: "涉及发布与数据结构,需人工确认后再改"

验证分两步。先确认配置被读到:运行规则打印或校验子命令,看输出里是否出现 guard-infra 与三条路径;再验证行为:用一条 deploy 下的路径跑 dry-run,输出应给出命中的条目 id 和 deny 结论。失效对照也要做一次——临时注释掉该条目重跑同一命令,结论应回落到默认放行且不再打印该 id,两条输出对比就能确认是这条规则在起作用,而不是别的兜底逻辑。命令名以 helixharness `--help` 为准,不同版本子命令可能不同。

补一道进入人工评审前的自动检查

规则限制的是生成阶段的输入输出,管不住“有人手工把生成的改动又改回去”或“生成器版本切换后规则未加载”。所以在 MR 进入人工评审之前加一道独立检查,只做路径与体积这类确定性判断,不评价代码质量。

# .helixharness/checks.yaml
checks:
  - id: no-infra-touch
    when: pre_review        # 也可挂在 CI 第一个 job
    match:
      paths: ["deploy/**", "migrations/**", "config/security/**"]
    action: fail
    message: |
      本次改动触及部署 / 迁移 / 安全配置目录,未被任务范围显式允许。
      处理:1) 核对是否属于本任务范围;2) 若确需改动,在 rules.yaml 增补带说明的 allow 条目并指定评审人;
      3) 重新生成或由人工提交该部分改动。
  - id: diff-size
    when: pre_review
    match:
      changed_files_gt: 40
    action: warn
    message: "改动文件数异常,请确认是否混入无关重构"

触发时机放在评审入口而不是提交入口:本地 pre-push 只跑 warn,评审入口跑 fail,避免开发阶段被反复打断。未通过时提示内容要写清三件事——命中的检查 id、涉及的具体路径列表、下一步动作(补规则、拆分改动、还是走豁免)。只报“检查未通过”等于没报。

记录一次完整闭环供团队复用

这次从不敢合到收敛,路径本身有复用价值。把记录写成一份短文件,和规则库放在同一目录下,字段固定下来:任务标识与任务描述原文、生成所用命令与框架版本、改动目录分布(归类结果)、命中的规则 id、缺口位置判定(未覆盖 / 未加载)、补充的规则条目 id、自动检查是否通过、人工评审结论、最终处置(补规则 / 改提示词或任务描述 / 拒绝改动)。

复用入口放在规则库根目录的 runbook 索引里,按“越界目录类型”建索引,例如 deploy、migrations、security-config 各一条,指向对应记录和最终生效的规则条目。下次遇到同类越界,先查索引里有没有现成条目,没有再补——同一类问题重复补两次规则,说明任务描述模板本身需要改。记录里的处置结论要写“为什么这条规则最终定成 deny 而不是 allow”,否则半年后没人敢改这条配置。