feat(gatekeeper): add optional advisory flags(软建议层·默认关闭·确定性) #306

Merged
wbtiger merged 1 commits from recorder/gitlink-cli:feat/gatekeeper-advisory-flags into master 2026-07-14 22:24:22 +08:00
Contributor

这个 PR 做什么

给已合并的 gatekeeper 加一个可选、默认关闭、确定性的「软建议层」(advisory_flags):硬门禁是真牙齿(命中即 REQUEST_CHANGES),咨询标记只在评分卡里提示、不参与评分、不改变裁决,把「超体量 PR 该提示拆分但不该阻断」这类治理建议留给人。

关键性质

  • 加性 + 向后兼容:默认关闭;旧策略无此段时行为完全不变(实测:默认策略对真实 PR #275 跑,无 advisory 节、PASS 87/100 不变)。
  • 确定性:只消费已采集的 PR 数据,不依赖当前时间等非确定性输入,保持「同输入 → 同分 → 同裁决」。
  • 不碰评分主逻辑evaluate_advisory_flags() 独立于 score_dimensions/decide_verdict,五维评分与裁决逻辑零改动。
  • 首个标记 large_pr_files(变更文件数 ≥ 阈值 → 建议拆分),正回应本仓 166 个 open PR 积压里「大 PR 该提示而非阻断」的实况。

真机验证

开启 advisory 对真实 open PR #275(10 文件)跑 dry-run:advisory 触发「建议拆分」,但裁决仍 PASS 87/100(软建议不改判)。15 个单测全绿(8 评分 + 7 advisory,含「开 advisory 不改总分/裁决」的不变量)。

改动面

仅扩展已合并的 gatekeeper:skills/gitlink-gatekeeper/(REFERENCE + 示例配置)+ examples/workflows/pr-quality-gatekeeper/(脚本 + 测试 + 文档 + demo)。延续 #90 Skill → #219 工作流 → #220 issueops 这条门禁链的第 4 环。## 这个 PR 做什么

给已合并的 gatekeeper 加一个可选、默认关闭、确定性的「软建议层」(advisory_flags):硬门禁是真牙齿(命中即 REQUEST_CHANGES),咨询标记只在评分卡里提示、不参与评分、不改变裁决,把「超体量 PR 该提示拆分但不该阻断」这类治理建议留给人。

关键性质

  • 加性 + 向后兼容:默认关闭;旧策略无此段时行为完全不变(实测:默认策略对真实 PR #275 跑,无 advisory 节、PASS 87/100 不变)。
  • 确定性:只消费已采集的 PR 数据,不依赖当前时间等非确定性输入,保持「同输入 → 同分 → 同裁决」。
  • 不碰评分主逻辑evaluate_advisory_flags() 独立于 score_dimensions/decide_verdict,五维评分与裁决逻辑零改动。
  • 首个标记 large_pr_files(变更文件数 ≥ 阈值 → 建议拆分),正回应本仓 166 个 open PR 积压里「大 PR 该提示而非阻断」的实况。

真机验证

开启 advisory 对真实 open PR #275(10 文件)跑 dry-run:advisory 触发「建议拆分」,但裁决仍 PASS 87/100(软建议不改判)。15 个单测全绿(8 评分 + 7 advisory,含「开 advisory 不改总分/裁决」的不变量)。

改动面

仅扩展已合并的 gatekeeper:skills/gitlink-gatekeeper/(REFERENCE + 示例配置)+ examples/workflows/pr-quality-gatekeeper/(脚本 + 测试 + 文档 + demo)。延续 #90 Skill → #219 工作流 → #220 issueops 这条门禁链的第 4 环。

## 这个 PR 做什么 给已合并的 gatekeeper 加一个**可选、默认关闭、确定性**的「软建议层」(advisory_flags):硬门禁是真牙齿(命中即 REQUEST_CHANGES),咨询标记只在评分卡里提示、**不参与评分、不改变裁决**,把「超体量 PR 该提示拆分但不该阻断」这类治理建议留给人。 ## 关键性质 - **加性 + 向后兼容**:默认关闭;旧策略无此段时行为完全不变(实测:默认策略对真实 PR #275 跑,无 advisory 节、PASS 87/100 不变)。 - **确定性**:只消费已采集的 PR 数据,不依赖当前时间等非确定性输入,保持「同输入 → 同分 → 同裁决」。 - **不碰评分主逻辑**:`evaluate_advisory_flags()` 独立于 `score_dimensions`/`decide_verdict`,五维评分与裁决逻辑零改动。 - 首个标记 `large_pr_files`(变更文件数 ≥ 阈值 → 建议拆分),正回应本仓 166 个 open PR 积压里「大 PR 该提示而非阻断」的实况。 ## 真机验证 开启 advisory 对真实 open PR #275(10 文件)跑 dry-run:advisory **触发**「建议拆分」,但裁决仍 **PASS 87/100**(软建议不改判)。15 个单测全绿(8 评分 + 7 advisory,含「开 advisory 不改总分/裁决」的不变量)。 ## 改动面 仅扩展已合并的 gatekeeper:`skills/gitlink-gatekeeper/`(REFERENCE + 示例配置)+ `examples/workflows/pr-quality-gatekeeper/`(脚本 + 测试 + 文档 + demo)。延续 #90 Skill → #219 工作流 → #220 issueops 这条门禁链的第 4 环。## 这个 PR 做什么 给已合并的 gatekeeper 加一个**可选、默认关闭、确定性**的「软建议层」(advisory_flags):硬门禁是真牙齿(命中即 REQUEST_CHANGES),咨询标记只在评分卡里提示、**不参与评分、不改变裁决**,把「超体量 PR 该提示拆分但不该阻断」这类治理建议留给人。 ## 关键性质 - **加性 + 向后兼容**:默认关闭;旧策略无此段时行为完全不变(实测:默认策略对真实 PR #275 跑,无 advisory 节、PASS 87/100 不变)。 - **确定性**:只消费已采集的 PR 数据,不依赖当前时间等非确定性输入,保持「同输入 → 同分 → 同裁决」。 - **不碰评分主逻辑**:`evaluate_advisory_flags()` 独立于 `score_dimensions`/`decide_verdict`,五维评分与裁决逻辑零改动。 - 首个标记 `large_pr_files`(变更文件数 ≥ 阈值 → 建议拆分),正回应本仓 166 个 open PR 积压里「大 PR 该提示而非阻断」的实况。 ## 真机验证 开启 advisory 对真实 open PR #275(10 文件)跑 dry-run:advisory **触发**「建议拆分」,但裁决仍 **PASS 87/100**(软建议不改判)。15 个单测全绿(8 评分 + 7 advisory,含「开 advisory 不改总分/裁决」的不变量)。 ## 改动面 仅扩展已合并的 gatekeeper:`skills/gitlink-gatekeeper/`(REFERENCE + 示例配置)+ `examples/workflows/pr-quality-gatekeeper/`(脚本 + 测试 + 文档 + demo)。延续 #90 Skill → #219 工作流 → #220 issueops 这条门禁链的第 4 环。
recorder added 1 commit 2026-06-28 00:28:37 +08:00
00f2eab716 feat(gatekeeper): add optional advisory flags (soft layer, default-off, deterministic)
Add a complementary soft layer to the hard gates: advisory_flags surface
governance hints (e.g. oversized-but-not-blocked PRs -> suggest splitting) in
the scorecard WITHOUT affecting score or verdict. Hard gates stay the real
teeth; advisory leaves the call to humans.

- additive & backward-compatible: default off; policies lacking the section
  behave exactly as before (verified: default policy on real PR #275 yields
  zero advisory section, PASS 87/100 unchanged)
- deterministic: consumes only already-collected PR data (no wall-clock input),
  preserving same-input -> same-score -> same-verdict
- first flag large_pr_files (changed-files >= threshold) answers the
  166-open-PR backlog reality where big PRs should be flagged, not blocked
- evaluate_advisory_flags() is separate from score_dimensions/decide_verdict;
  the 5-dim scoring and verdict logic are untouched
- 7 new unit tests (15 total) incl. an invariant that enabling advisory does
  NOT change total/verdict; verified live on real open PR #275
- REFERENCE.md 1.9 + gatekeeper.yaml + verification.md E + demo scorecard

Extends the merged gatekeeper line (#90 skill -> #219 workflow -> #220 issueops).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
wbtiger merged commit 7fa661f693 into master 2026-07-14 22:24:14 +08:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Gitlink/gitlink-cli#306
No description provided.