Skip to content

feat(governance): patrol 政策文件(W3-C2 .github#219,ADR-0065) - #241

Merged
randypanding merged 1 commit into
mainfrom
w3c2-patrol-policy
Aug 21, 2026
Merged

feat(governance): patrol 政策文件(W3-C2 .github#219,ADR-0065)#241
randypanding merged 1 commit into
mainfrom
w3c2-patrol-policy

Conversation

@randypanding

@randypanding randypanding commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

动机

ADR-0065 决策 3:patrol 频控/降频/开单上限/权限声明版本化集中此文件(阈值唯一真源)——频控过松刷屏/过紧漏报的调参走 C1,不走代码。本 PR 是 W3-C2 的政策半件(执行引擎在 CI-Workflows pipeline/patrol/,PR #57)。

变更清单

  • 新增 governance/policy/patrol.yaml(仅 append 新文件,不动既有政策文件)

AC 映射(.github#219)

  • AC-2(频控)rate_limit.max_issues_per_repo_per_hour: 2 / per_day: 6——指纹去重之外的第二道闸(突发缺陷潮按仓限速,deferred 下一窗口再攻击)。CI-Workflows 测试 test_throttle_downshift.py 断言本配置被消费(非硬编码)。
  • AC-4(yield/降频)yield.snr_threshold: 0.05 / snr_window_issues: 20 / downshift_daily_issue_cap: 1——信噪比(真 bug/开单数)低于阈值自动降频(收敛而非停巡)+ needs-human。
  • AC-1(observation 桶)observation.escalate_after_independent: 2——宪法 §3 钉死两次独立(不同 run 且不同 seed);patrol.py 加载时断言此值为 2,放宽须先修 ADR。
  • 权限铁律(卡面:只读运行+开 issue,不得改代码)permissions.allowed: [read-run, open-issue]forbidden: [push, pr-write, label-write, code-write]——声明性复核(执行面在 CI-Workflows patrol.yml job 级 permissions),patrol.py 缺 forbidden 声明即 fail-closed 拒跑。

关键决策记录(详见文件内注释)

  • issue_mode: draft(shadow 起步):bug issue 落草稿 artifact,零线上噪音;切 gh 真开单 = C1 政策变更,由 owner 按演习 yield 数据拍板。
  • targets 当前只挂 CI-Workflows demo 靶场(blastRadius 可控);新仓接入 = targets 追加条目(C1)。
  • LLM 源经 metering wrapper(ADR-0062),无凭据诚实降级计数——政策声明于 sources.llm

测试方法

  • 生产政策端到端冒烟(本地,CI-Workflows 仓):patrol.py run --policy governance/policy/patrol.yaml …llm=skipped-no-creds opened=2 deferred=5(频控 2/小时 + LLM 诚实降级实证;详见 CI-Workflows PR#57 body)
  • 政策加载断言:缺段/缺 forbidden 声明/schema 头不符 → patrol.py exit 2(fail-closed 拒跑)

风险与回滚

  • 阈值失当 → 本文件即调参面(C1 变更引用 ADR-0065);yield 数据驱动(ADR-0073 dashboard 消费)
  • 回滚 → targets 置空或 CI-Workflows 摘除 patrol.yml schedule 即停(ADR-0065 回滚条款:cron 停即静默,台账留存无害)

Card: #219

Summary by CodeRabbit

  • 新功能
    • 新增巡逻政策配置,支持定义目标仓库、探针资源及巡逻版本。
    • 支持设置仓库级小时/日频率限制与观察升级阈值。
    • 支持配置来源采样、降频、结果产出及草稿开单模式。
    • 新增权限声明配置,可明确允许与禁止的操作。

patrol.yaml——patrol 巡逻服务阈值唯一真源(ADR-0065 决策 3):
频控(每仓每小时/每日开单上限)/observation 两次独立升级/yield 降频阈值
(SNR<0.05 收敛 1 单/日+needs-human)/三源参数(LLM 走 metering wrapper,
无凭据诚实降级)/issue_mode=draft shadow 起步/权限声明(allowed 只含
read-run+open-issue;forbidden 显式列 push/pr-write/label-write——
patrol.py 加载时断言,缺声明 fail-closed 拒跑)。

执行面:CI-Workflows pipeline/patrol/patrol.py(.github/workflows/patrol.yml
每日 02:43 UTC 拉取本文件后巡逻,拉取失败 fail-closed)。阈值改动=C1 变更
须引用 ADR。

Card: #219
Copilot AI lite review requested due to automatic review settings August 21, 2026 19:04
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 89270db9-a9c4-4c0d-b889-ca5f5400c036

📥 Commits

Reviewing files that changed from the base of the PR and between 94a8d2f and c3782f2.

📒 Files selected for processing (1)
  • governance/policy/patrol.yaml

Included review availability: Your plan provides up to 10 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

Changes

巡逻政策

Layer / File(s) Summary
巡逻政策配置
governance/policy/patrol.yaml
新增 patrol-policy/v1 配置。配置探针目标、每小时和每日 issue 限额、独立观察升级条件、yield 参数、三类采样来源、draft 开单模式及允许和禁止的权限。

Suggested labels: security, feature

Merge Risk: 🔵 Low · up to c3782

This PR adds a localized centralized patrol policy file, but merge should wait for the required C1 owner-only approval, valid ADR-0065 reference, and passing governance check; no broader implementation risk is indicated.

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning 标题使用了有效的 Conventional Commits 前缀,且内容相关,但长度为 57 个字符,超过 50 个字符限制。 将标题缩短至 50 个字符以内,同时保留 feat 前缀和 patrol 政策配置的核心描述。
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch w3c2-patrol-policy

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add versioned patrol policy file for rate limiting, yield, and permissions

✨ Enhancement ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Add versioned patrol policy YAML as the single source of patrol thresholds.
• Define rate limiting, observation escalation, and yield-based downshift parameters.
• Declare targets, LLM/metamorphic/escape source knobs, issue draft mode, and permissions.
Diagram

graph TD
  A["governance/policy/patrol.yaml"] --> B["CI-Workflows patrol workflow"] --> C["patrol.py engine"] --> D["Policy enforcement"] --> E["Draft artifacts"]
  D --> F("GitHub Issues")
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Keep thresholds in patrol engine code
  • ➕ No separate policy distribution/fetch step
  • ➕ Strong compile-time coupling between config and implementation
  • ➖ Violates ADR-0065 goal of centralized, versioned single source of truth
  • ➖ Requires code PRs for tuning; slower iteration and higher risk of hardcoding drift
2. Store policy alongside CI-Workflows (engine repo)
  • ➕ Config and executor co-located; simpler operational ownership
  • ➕ Avoids cross-repo fetch concerns
  • ➖ Loses central governance visibility/audit in the .github repo
  • ➖ Harder to share a unified policy baseline across multiple target repos
3. Use GitHub org/repo variables as policy surface
  • ➕ Fast runtime tuning without repo changes
  • ➕ Access-controlled knobs for limited parameters
  • ➖ Poor auditability/versioning compared to a committed policy file
  • ➖ Hard to represent structured policy (targets/sources/permissions) safely

Recommendation: Keep the policy as a committed, versioned YAML under governance/policy, as implemented here. It matches ADR-0065’s intent (single source of truth, tunable without touching engine code) while still allowing fail-closed enforcement in the executor; alternatives either reduce auditability or force code changes for routine tuning.

Files changed (1) +65 / -0

Other (1) +65 / -0
patrol.yamlIntroduce versioned patrol policy with throttling, yield, and permissions +65/-0

Introduce versioned patrol policy with throttling, yield, and permissions

• Adds a new patrol policy YAML (schema patrol-policy/v1) intended as the single source of truth for patrol thresholds. It defines demo target wiring, per-repo/hour and per-repo/day rate limits, observation escalation (2 independent runs), yield/SNR-based downshift caps, source knobs (escape/metamorphic/LLM), shadow issue_mode=draft, and an explicit allow/forbid permission contract for fail-closed enforcement.

governance/policy/patrol.yaml

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new, centralized governance policy file for the “patrol” service so rate limiting, yield/downshift thresholds, observation escalation, and permission declarations are versioned and adjustable via C1 policy changes (per ADR-0065 / .github#219), instead of code changes.

Changes:

  • Introduces governance/policy/patrol.yaml as the single source of truth for patrol thresholds and operational limits.
  • Declares patrol’s allowed/forbidden permission set in policy (intended for fail-closed validation by the patrol loader).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +54 to +56
# 开单形态:draft=shadow 起步(bug issue 草稿落 artifact,零线上噪音——W3-C2
# 演习即此形态);切 gh(真开单+bug 标签)= C1 政策变更,由 owner 按演习 yield
# 数据拍板。开单必附 trace+指纹(AC-1),复现判定走 ADR-0064 三值协议。
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Policy invariants unvalidated 🐞 Bug ☼ Reliability
Description
该 PR 引入新的阈值真源 patrol.yaml,但本仓 gate 只做 yaml.safe_load 的语法解析,不校验必须字段/类型/不变量,导致未来任何结构性误改都可能在本仓 CI
放行、到下游 patrol 执行时才 fail-closed 停巡。尤其是文件内声明了硬约束(如 observation.escalate_after_independent 固定为
2、permissions.forbidden 必须存在),但当前没有机器执行的本仓侧断言。
Code

governance/policy/patrol.yaml[R29-33]

+observation:
+  # 宪法 §3 钉死:LLM"看着不对"只进 observation 桶,两次独立出现才升级开单;
+  # 独立=不同 run 且不同 seed(防同 run 重复采样灌水)。值固定 2——放宽须先修 ADR
+  escalate_after_independent: 2
+
Relevance

●●● Strong

Recent accepted precedents strengthen fail-closed semantic validation and explicit policy invariants
beyond syntax parsing.

PR-#50
PR-#49

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
patrol.yaml 明确声明了必须遵守的不变量(如 observation 固定为 2、permissions 必须声明 forbidden),但当前 gate 对
governance/**/*.yaml 的检查只做语法级 safe_load,不会在 PR 阶段捕获字段缺失/类型错误/不变量被破坏的问题。历史上本仓也曾因“校验过松”专门加固 gate
的配置校验逻辑(JSON 顶层对象断言)。

governance/policy/patrol.yaml[29-33]
governance/policy/patrol.yaml[59-65]
.github/workflows/gate.yml[52-65]
PR-#61

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`governance/policy/patrol.yaml` 作为阈值唯一真源引入后,本仓 CI 目前仅验证“YAML 可解析”,没有任何结构/类型/不变量校验。这样未来 PR 可能把关键字段拼错、删段、改类型(例如把数字写成字符串、漏掉 permissions.forbidden)而在本仓 gate 放行,直到下游 patrol 引擎运行时才 fail-closed(等价于“静默停巡直到有人注意到”)。

## Issue Context
- gate.yml 的“YAML 全量解析”仅调用 `yaml.safe_load` 并打印 OK,不做结构断言。
- patrol.yaml 自身注释声明了必须满足的硬约束(如 observation 固定值、permissions 必须带 forbidden),但注释不是机器可执行约束。

## Fix Focus Areas
- .github/workflows/gate.yml[52-65]
- governance/policy/patrol.yaml[29-33]
- governance/policy/patrol.yaml[59-65]

## Implementation sketch
1. 新增一个轻量校验脚本(例如 `scripts/validate_patrol_policy.py`),读取 `governance/policy/patrol.yaml` 并做至少以下断言(fail-closed 非 0 退出):
  - 顶层必须是 dict;`schema`/`version` 存在且为期望值(如果 `schema` 是合同的一部分)。
  - 必须字段存在:`targets`(list)、`rate_limit`、`observation`、`yield`、`sources`、`issue_mode`、`permissions`。
  - 类型断言:数值字段为 int/float、`permissions.allowed/forbidden` 为 list[str]。
  - 不变量断言:`observation.escalate_after_independent == 2`;`permissions.forbidden` 必须非空;可选地断言 `issue_mode` ∈ {draft, gh}。
2. 在 gate.yml 的 YAML 解析步骤后追加一步运行该脚本,确保 policy 结构性错误在本仓 PR 阶段被拦下。
3.(可选)将校验范围扩展为未来可能新增的 `governance/policy/*.yaml` 的结构校验,但本 PR 至少要把新引入的 patrol policy 纳入。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 16 rules
Review mode: ⚖️ Balanced: This adds a runtime-consumed governance policy controlling patrol rate limits, escalation, issue behavior, and permissions; its behavioral and authorization impact warrants a complete single-pass review, but the localized one-file change is not dense enough for extended.

Grey Divider

Tip of the day
💡 Did you know, you can tweak Display preferences with a live preview to see your comment before it ships

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment on lines +29 to +33
observation:
# 宪法 §3 钉死:LLM"看着不对"只进 observation 桶,两次独立出现才升级开单;
# 独立=不同 run 且不同 seed(防同 run 重复采样灌水)。值固定 2——放宽须先修 ADR
escalate_after_independent: 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

1. Policy invariants unvalidated 🐞 Bug ☼ Reliability

该 PR 引入新的阈值真源 patrol.yaml,但本仓 gate 只做 yaml.safe_load 的语法解析,不校验必须字段/类型/不变量,导致未来任何结构性误改都可能在本仓 CI
放行、到下游 patrol 执行时才 fail-closed 停巡。尤其是文件内声明了硬约束(如 observation.escalate_after_independent 固定为
2、permissions.forbidden 必须存在),但当前没有机器执行的本仓侧断言。
Agent Prompt
## Issue description
`governance/policy/patrol.yaml` 作为阈值唯一真源引入后,本仓 CI 目前仅验证“YAML 可解析”,没有任何结构/类型/不变量校验。这样未来 PR 可能把关键字段拼错、删段、改类型(例如把数字写成字符串、漏掉 permissions.forbidden)而在本仓 gate 放行,直到下游 patrol 引擎运行时才 fail-closed(等价于“静默停巡直到有人注意到”)。

## Issue Context
- gate.yml 的“YAML 全量解析”仅调用 `yaml.safe_load` 并打印 OK,不做结构断言。
- patrol.yaml 自身注释声明了必须满足的硬约束(如 observation 固定值、permissions 必须带 forbidden),但注释不是机器可执行约束。

## Fix Focus Areas
- .github/workflows/gate.yml[52-65]
- governance/policy/patrol.yaml[29-33]
- governance/policy/patrol.yaml[59-65]

## Implementation sketch
1. 新增一个轻量校验脚本(例如 `scripts/validate_patrol_policy.py`),读取 `governance/policy/patrol.yaml` 并做至少以下断言(fail-closed 非 0 退出):
   - 顶层必须是 dict;`schema`/`version` 存在且为期望值(如果 `schema` 是合同的一部分)。
   - 必须字段存在:`targets`(list)、`rate_limit`、`observation`、`yield`、`sources`、`issue_mode`、`permissions`。
   - 类型断言:数值字段为 int/float、`permissions.allowed/forbidden` 为 list[str]。
   - 不变量断言:`observation.escalate_after_independent == 2`;`permissions.forbidden` 必须非空;可选地断言 `issue_mode` ∈ {draft, gh}。
2. 在 gate.yml 的 YAML 解析步骤后追加一步运行该脚本,确保 policy 结构性错误在本仓 PR 阶段被拦下。
3.(可选)将校验范围扩展为未来可能新增的 `governance/policy/*.yaml` 的结构校验,但本 PR 至少要把新引入的 patrol policy 纳入。

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@randypanding
randypanding merged commit 9fc03e2 into main Aug 21, 2026
14 checks passed
@randypanding
randypanding deleted the w3c2-patrol-policy branch August 21, 2026 19:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants