gitlink-cli/skills/gitlink-gatekeeper/examples/decision-request-changes.md

170 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 裁决记录 — REQUEST_CHANGES硬门禁失败 + 1 个 major
> 模拟 `gitlink-gatekeeper` 的完整执行记录:采集 → 逐维算分 → 硬门禁 → 裁决 → 渲染评分卡 → dry-run 回写命令。
> 策略:默认 `gatekeeper.yaml`(权重 40/20/15/15/10severity_penalty blocker=100/major=25/minor=5/nit=1thresholds pass=85 / request_changes=60max_changed_files=80
> 命令均来自 `REFERENCE.md` 第 7 节 CLI 映射,已对照真实 shortcut 核验。
**场景**`Gitlink/forgeplus` 仓库 PR #305,重构订单结算逻辑,改动了 4 个源码文件但**未附带任何测试**其中一处折扣计算有边界缺陷major。CI 通过。
---
## ① 采集上下文
```bash
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结论一致
```
---
## ⑤ 渲染的评分卡
```markdown
## 🛡️ 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 永不涉及合并。
```bash
# [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不合并」并等待确认。