forked from Gitlink/gitlink-cli
164 lines
5.7 KiB
Markdown
164 lines
5.7 KiB
Markdown
# 裁决记录 — COMMENT(总分介于两阈值之间,无硬门禁失败)
|
||
|
||
> 模拟 `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 #277,给配置加载器增加默认值合并能力,改动 2 个源码文件,附 1 个测试文件,CI 通过;AI 审查只发现若干 minor/nit(无 blocker、无 major)。总分落在 60–85 之间 → COMMENT(建议性意见,不阻塞、不批准)。
|
||
|
||
---
|
||
|
||
## ① 采集上下文
|
||
|
||
```bash
|
||
gitlink-cli pr +view -i 277 --owner Gitlink --repo forgeplus --format json
|
||
gitlink-cli pr +files -i 277 --owner Gitlink --repo forgeplus --format json
|
||
gitlink-cli pr +diff -i 277 --owner Gitlink --repo forgeplus --format json
|
||
gitlink-cli api GET /Gitlink/forgeplus/pulls/277/commits --format json
|
||
gitlink-cli ci +builds --owner Gitlink --repo forgeplus --format json
|
||
```
|
||
|
||
**采集结果摘要**
|
||
|
||
| 信号 | 值 |
|
||
|------|----|
|
||
| 标题 | `feat(config): merge defaults on load` |
|
||
| 描述 | 非空,长度 52 字符(≥30),**无** `#<n>` 关联 |
|
||
| `changed_files` | 2 |
|
||
| `changed_src` | 2(`loader.go` / `merge.go`) |
|
||
| `changed_tests` | 1(`merge_test.go`) |
|
||
| commits | 3 条,符合 Conventional Commits 的 2 条 → conforming=2 |
|
||
| CI | passing |
|
||
| AI 审查发现 | 0 blocker / 0 major / 3 minor / 2 nit |
|
||
|
||
---
|
||
|
||
## ② 逐维算分(公式代入,可复算)
|
||
|
||
**review_findings(权重 40)** — §3.1
|
||
```
|
||
penalty = 3×5(minor) + 2×1(nit) = 17
|
||
score = 40 × max(0, 1 − 17/40) = 40 × (23/40) = 40 × 0.575 = 23
|
||
```
|
||
|
||
**test_coverage(权重 20)** — §3.2
|
||
```
|
||
changed_src=2 > 0, changed_tests=1 > 0
|
||
ratio = min(1, 1/2) = 0.5
|
||
score = round(20 × (0.5 + 0.5×0.5)) = round(20 × 0.75) = 15
|
||
```
|
||
|
||
**pr_hygiene(权重 15)** — §3.3
|
||
```
|
||
描述≥30 ✓ (+1/3)
|
||
关联 Issue ✗ (0)
|
||
体量 changed_files=2 ≤ 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 = 23 + 15 + 10 + 10 + 10 = 68
|
||
```
|
||
|
||
---
|
||
|
||
## ③ 硬门禁判定(§4)
|
||
|
||
| 门禁 | 配置 | 命中? |
|
||
|------|------|:------:|
|
||
| `forbid_blocker_findings` | true | 否(0 blocker) |
|
||
| `require_ci_pass` | true | 否(passing) |
|
||
| `require_tests_for_src_changes` | true | 否(changed_src=2>0 且 changed_tests=1>0) |
|
||
| `require_linked_issue` | false | —(未启用) |
|
||
| `max_changed_files` | 80 | 否(2 ≤ 80) |
|
||
|
||
`hard_gate_failed = false`。
|
||
|
||
---
|
||
|
||
## ④ 裁决(§5)
|
||
|
||
```
|
||
hard_gate_failed = false
|
||
total = 68:not (≥ pass 85),not (< request_changes 60)
|
||
→ 介于两阈值之间 → verdict = COMMENT
|
||
```
|
||
|
||
---
|
||
|
||
## ⑤ 渲染的评分卡
|
||
|
||
```markdown
|
||
## 🛡️ Gatekeeper Report — PR #277 feat(config): merge defaults on load
|
||
|
||
**Verdict: 💬 COMMENT** · Score: 68/100 · policy: gatekeeper.yaml@v1
|
||
|
||
| Dimension | Weight | Score | Notes |
|
||
|-----------|:------:|:-----:|-------|
|
||
| Review findings | 40 | 23/40 | 0 blocker / 0 major / 3 minor / 2 nit |
|
||
| Test coverage | 20 | 15/20 | 2 src / 1 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 |
|
||
|
||
### 🟡 Should fix (3)
|
||
- [minor] `mergeDefaults` 对 nil map 未保护,可能 panic — merge.go:33
|
||
- [minor] 深拷贝缺失,合并后仍共享底层 slice — merge.go:58
|
||
- [minor] 加载失败时未记录原始路径,定位困难 — loader.go:21
|
||
|
||
### 🔵 Nits (2)
|
||
- [nit] 导出函数 `Merge` 缺少 doc 注释 — merge.go:18
|
||
- [nit] 一条 commit 未用 `type(scope):` 前缀 — (commit)
|
||
|
||
### ✅ Strengths
|
||
- 改动小而聚焦,附带了测试,CI 全绿
|
||
- 无 blocker、无 major,整体方向正确
|
||
|
||
### Next steps
|
||
1. 处理 3 条 minor(尤其 nil map 与共享 slice),并补充关联 Issue 编号
|
||
2. 修复后总分有望跨过 pass 阈值(85)转为 PASS;当前为非阻塞的 COMMENT,维护者可酌情合并
|
||
---
|
||
*Generated by gitlink-gatekeeper · policy-as-code PR gate · re-run after changes*
|
||
```
|
||
|
||
---
|
||
|
||
## ⑥ 将执行的回写命令(dry-run 展示)
|
||
|
||
> 默认 dry-run,不传 `--apply` 时仅打印。COMMENT 裁决不阻塞、不批准、不合并。
|
||
|
||
```bash
|
||
# [dry-run] 1) 评分卡作为评论回写(与 workflow 脚本一致,走 pr +comment)
|
||
gitlink-cli pr +comment -i 277 -b "$(cat scorecard.md)" --owner Gitlink --repo forgeplus
|
||
# 也可作为评审记录:gitlink-cli pr +review -i 277 --status common --content "$(cat scorecard.md)"
|
||
|
||
# [dry-run] 2) 打 review 标签(labels.comment = "gatekeeper:review")
|
||
gitlink-cli label +create -n "gatekeeper:review" -c "#0969DA" \
|
||
-d "Gatekeeper verdict: COMMENT" --owner Gitlink --repo forgeplus
|
||
# 标签挂到 PR 背后的 issue.id(非 PR 号):
|
||
ISSUE_ID=$(gitlink-cli pr +view -i 277 --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:review 的 tag_id>],
|
||
"done_ratio": 0,
|
||
"subject": "<PR 原标题>",
|
||
"description": "<PR 原描述>"
|
||
}'
|
||
|
||
# COMMENT 不合并、不创建 tracking issue(仅 REQUEST_CHANGES 才善后建 issue)。
|
||
```
|
||
|
||
> 实际写回需追加 `--apply`,Agent 会先复述「将回写 1 条评论 + 打 gatekeeper:review 标签,不合并」并等待确认。
|