# 裁决记录 — 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 标签，不合并」并等待确认。
