6.2 KiB
6.2 KiB
裁决记录 — REQUEST_CHANGES(硬门禁失败 + 1 个 major)
模拟
gitlink-gatekeeper的完整执行记录:采集 → 逐维算分 → 硬门禁 → 裁决 → 渲染评分卡 → dry-run 回写命令。 策略:默认gatekeeper.yaml(权重 40/20/15/15/10,severity_penalty blocker=100/major=25/minor=5/nit=1,thresholds pass=85 / request_changes=60,max_changed_files=80)。 命令均来自REFERENCE.md第 7 节 CLI 映射,已对照真实 shortcut 核验。
场景:Gitlink/forgeplus 仓库 PR #305,重构订单结算逻辑,改动了 4 个源码文件但未附带任何测试,其中一处折扣计算有边界缺陷(major)。CI 通过。
① 采集上下文
gitlink-cli pr +view -i 305 --owner Gitlink --repo forgeplus --format json
gitlink-cli pr +files -i 305 --owner Gitlink --repo forgeplus --format json
gitlink-cli pr +diff -i 305 --owner Gitlink --repo forgeplus --format json
gitlink-cli api GET /Gitlink/forgeplus/pulls/305/commits --format json
gitlink-cli ci +builds --owner Gitlink --repo forgeplus --format json
采集结果摘要
| 信号 | 值 |
|---|---|
| 标题 | refactor(billing): rework settlement pipeline |
| 描述 | 非空,长度 88 字符(≥30),无 #<n> 关联 |
changed_files |
4 |
changed_src |
4(settlement.go / discount.go / invoice.go / tax.go) |
changed_tests |
0 |
| commits | 3 条,符合 Conventional Commits 的 2 条(1 条为 wip: fix)→ conforming=2 |
| CI | passing |
| AI 审查发现 | 0 blocker / 1 major / 1 minor / 2 nit |
② 逐维算分(公式代入,可复算)
review_findings(权重 40) — §3.1
penalty = 25(major) + 1×5(minor) + 2×1(nit) = 32
score = 40 × max(0, 1 − 32/40) = 40 × (1 − 0.8) = 40 × 0.2 = 8
test_coverage(权重 20) — §3.2
changed_src=4 > 0, changed_tests=0
→ score = 0
pr_hygiene(权重 15) — §3.3
描述≥30 ✓ (+1/3)
关联 Issue ✗ (0)
体量 changed_files=4 ≤ max_changed_files/2 = 40 ✓ (+1/3)
命中比例 = 2/3
score = round(15 × 2/3) = round(10.0) = 10
commit_quality(权重 15) — §3.4
conforming/total = 2/3
score = round(15 × 2/3) = round(10.0) = 10
ci_status(权重 10) — §3.5
CI passing → score = 10
总分
total = 8 + 0 + 10 + 10 + 10 = 38
③ 硬门禁判定(§4)
| 门禁 | 配置 | 命中? |
|---|---|---|
forbid_blocker_findings |
true | 否(0 blocker) |
require_ci_pass |
true | 否(passing) |
require_tests_for_src_changes |
true | 是(changed_src=4>0 且 changed_tests=0) |
require_linked_issue |
false | —(未启用) |
max_changed_files |
80 | 否(4 ≤ 80) |
hard_gate_failed = true。
④ 裁决(§5)
hard_gate_failed = true
→ verdict = REQUEST_CHANGES (无视总分;本例 total=38 < request_changes(60) 也指向 REQUEST_CHANGES,结论一致)
⑤ 渲染的评分卡
## 🛡️ Gatekeeper Report — PR #305 refactor(billing): rework settlement pipeline
**Verdict: ❌ REQUEST_CHANGES** · Score: 38/100 · policy: gatekeeper.yaml@v1
| Dimension | Weight | Score | Notes |
|-----------|:------:|:-----:|-------|
| Review findings | 40 | 8/40 | 0 blocker / 1 major / 1 minor / 2 nit |
| Test coverage | 20 | 0/20 | 4 src / 0 test files |
| PR hygiene | 15 | 10/15 | desc ✓ / linked issue ✗ / size ✓ |
| Commit quality | 15 | 10/15 | 2/3 conventional |
| CI status | 10 | 10/10 | passing |
### ⛔ Hard gate failures (1)
- `require_tests_for_src_changes`: 改动了 4 个源码文件,但本 PR 未包含任何测试文件
### 🔴 Must fix (1)
- [major] 折扣金额未做下限保护,满减叠加时可算出负数总价 — discount.go:72
### 🟡 Should fix (1)
- [minor] `settle()` 吞掉了 tax 计算的 error,应向上传播 — settlement.go:118
### 🔵 Nits (2)
- [nit] commit `wip: fix` 不符合 Conventional Commits,建议 rebase 整理 — (commit)
- [nit] 导出结构体 `Invoice` 字段缺少注释 — invoice.go:14
### ✅ Strengths
- 改动聚焦、体量适中(4 文件),CI 全绿
### Next steps
1. **补测试**(最高优先级):为 4 个改动源码文件补单元测试,解除 `require_tests_for_src_changes` 硬门禁
2. 修复折扣下限的 major 缺陷,建议补一条针对负数总价的回归测试
3. 整理 `wip: fix` commit、补充 error 传播后,重新触发 gatekeeper
---
*Generated by gitlink-gatekeeper · policy-as-code PR gate · re-run after changes*
⑥ 将执行的回写命令(dry-run 展示)
默认 dry-run,不传
--apply时仅打印。REQUEST_CHANGES 永不涉及合并。
# [dry-run] 1) 评分卡作为评论回写(与 workflow 脚本一致,走 pr +comment)
gitlink-cli pr +comment -i 305 -b "$(cat scorecard.md)" --owner Gitlink --repo forgeplus
# 裁决=REQUEST_CHANGES 不直接用平台的强语义 rejected(留给人工);裁决靠评分卡标题 + 标签表达
# [dry-run] 2) 打 needs-changes 标签(labels.request_changes = "gatekeeper:needs-changes")
gitlink-cli label +create -n "gatekeeper:needs-changes" -c "#D1242F" \
-d "Gatekeeper verdict: REQUEST_CHANGES" --owner Gitlink --repo forgeplus
# 标签挂到 PR 背后的 issue.id(非 PR 号):
ISSUE_ID=$(gitlink-cli pr +view -i 305 --owner Gitlink --repo forgeplus --format json | jq -r '.data.issue.id')
gitlink-cli api POST /Gitlink/forgeplus/issues/$ISSUE_ID --body '{
"issue_tag_ids": [<gatekeeper:needs-changes 的 tag_id>],
"done_ratio": 0,
"subject": "<PR 原标题>",
"description": "<PR 原描述>"
}'
# [dry-run] 3)(子题三善后)创建 tracking issue 汇总必修项并关联 PR #305
# 注意:用 $'...' 让 \n 成为真实换行(双引号里的字面 \n 不会换行)
gitlink-cli issue +create --owner Gitlink --repo forgeplus \
-t "[gatekeeper] PR #305 必修项跟踪" \
-b $'由 gatekeeper 裁决 REQUEST_CHANGES 触发。\n硬门禁: require_tests_for_src_changes。\nMust fix: discount.go:72 折扣下限。\n关联 PR: #305'
实际写回需追加
--apply,Agent 会先复述「将回写 1 条评论 + 打 gatekeeper:needs-changes 标签 + 建 1 条 tracking issue,不合并」并等待确认。