PI Coding Agent 拓展

让 AI 写的代码
先过一道风险分级

Agent 一个回合改动几十个文件,逐行审查已不现实。pi-diff-risk 在每轮回复后自动扫描变更, 为每个文件计算量化风险分,输出四色标注目录树 —— 把「哪些改动值得看」从主观判断, 变成确定性的、可配置的决策产物。

无需 Git 仓库 零上下文成本 确定性评分,无随机性 权重阈值可配置
3
结构化风险信号
70%
中高危识别准确率(LLM 机评)
0 token
不回灌模型,无上下文开销
4
高 / 中 / 低危 / 未变更
The Problem

代码生产变廉价了,审查信任却变稀缺了

过去写200 行代码要半天,审它只需十分钟。现在 Agent 三十秒产出 800 行 —— 审查成为了新的瓶颈。 而人的注意力并没有变多,于是大多数人选择了最糟的策略:不看。

现状

全量审查,或者干脆不审

面对几十个文件的 diff,要么硬着头皮翻完(成本高、注意力衰减、越往后越敷衍), 要么直接合并赌它没问题。前者不可持续,后者迟早出事 —— 尤其当 Agent 悄悄动了鉴权逻辑或支付流程时。

本项目的解法

把审查目标从「覆盖」收敛到「聚焦」

资深工程师看 diff 时其实有直觉:这块没问题、那块得仔细看。 本项目把这份直觉拆成可计算的信号:碰了敏感领域吗?测试跟上了吗?改动量异常吗? 然后用颜色把注意力精确导向真正危险的地方。

How It Works

五步,全自动,你什么都不用做

核心设计是把变更范围严格锁定在「这一轮 Agent 改了什么」,而不是累积改动 —— 所以基线快照必须卡在回合起点。

1

回合开始时拍基线

监听 agent_started,递归扫描项目,记录每个文件的 size / mtime, 并缓存 200KB 以内的文本内容。

2

Agent 自由工作

完全不干预、不拦截、不阻塞。Agent 新建、修改、删除文件,一切照常。

3

回合结束时再拍一次

监听 agent_settled,二次扫描后与基线对比,得出新增 / 修改 / 删除清单。

4

还原行级增删并评分

对修改文件用 LCS 算法算出 +N/-M,再跑三信号加权模型输出 0–100 分。

5

渲染彩色目录树

结果作为自定义卡片渲染在对话底部,不进消息历史,因此不消耗任何上下文。

Scoring Model

三个信号,各自回答一个问题

权重不是均分的 —— 敏感领域出事的代价最大,所以给它最高权重; 改动量大不等于危险,所以给它最低权重。

sensitivity0.40

它碰了要命的地方吗?对文件路径和变更内容双向匹配 8 类高危模式,命中越多分越高。

authsecretscryptopaymentsmigrationsinfracideps
test-gap0.35

改完之后有人验证吗?源码变了但同批改动里没有对应测试文件,直接吃满惩罚。测试文件自身与文档类文件免检。

*.test.**.spec.*__tests__/tests/
diff-size0.25

改动规模超出可审范围了吗?按增删行数分五档。大改不必然危险,但确实更难看懂 —— 所以权重最低。

≥500 → 1.0≥200 → 0.7≥80 → 0.4≥20 → 0.15
// 最终得分:三信号加权求和,再乘以文件类型系数
riskScore = ( sensitivity × 0.40 + testGap × 0.35 + diffSize × 0.25 ) × typeMultiplier × 100

// 同样改 200 行,.ts 和 .md 的风险量级根本不同
typeMultiplier:  .ts .py .go .rs .java = 1.0   │   .json .yaml .toml = 0.7   │   .css .html = 0.5   │   .md .txt = 0.2
≥ 65 HIGH
红色 · 必须逐行 review
35 – 64 MED
黄色 · 建议扫一眼
< 35 LOW
绿色 · 可以放心跳过
Live Output

Agent 回复完毕后,你会看到这个

三个真实场景,切换看看不同风险等级下的渲染效果。

常规改动
鉴权变更 + 缺测试
支付模块大重构
pi · diff-risk panel
📋 变更风险: LOW (27/100)
24 files changed │ 0 high 0 medium 24 low │ Aggregate risk: 27/100
~/projects/my-site/
├── src/
│   ├── layouts/
│   │   └── Layout.astro[LOW risk=22]
│   ├── pages/
│   │   ├── agents/
│   │   │   └── index.astro       [LOW risk=20]
│   │   ├── skills/
│   │   │   └── index.astro       [LOW risk=20]
│   │   ├── 404.astro             [LOW risk=22]
│   │   └── index.astro           [LOW risk=31]
│   ├── styles/
│   │   └── global.css            [LOW risk=20]
│   └── ui/
│       ├── command-dialog.tsx    [LOW risk=28]
│       └── copy-button.tsx       [LOW risk=25]
├── DESIGN.md                     [LOW risk=1]
└── package.json
全部低危 · 无高危信号命中 · 可直接合并
📋 变更风险: MED (52/100)
7 files changed │ 0 high 3 medium 4 low │ Aggregate risk: 52/100
~/projects/backend/
├── src/
│   ├── auth/
│   │   ├── token.ts              [MED risk=58]
│   │   └── middleware.ts         [MED risk=45]
│   ├── api/
│   │   └── routes.ts             [LOW risk=18]
│   ├── config/
│   │   └── env.ts                [LOW risk=12]
│   └── utils/
│       ├── hash.ts               [MED risk=42]
│       └── logger.ts             [LOW risk=8]
├── tests/
│   └── utils.test.ts             [LOW risk=10]
└── .env.example
Signals
  src/auth/token.ts  [58/100]  +45/-12
    sensitivity (×0.40): sensitive: auth, secrets
    test-gap    (×0.35): no test file changed
  src/auth/middleware.ts  [45/100]  +30/-5
    sensitivity (×0.40): sensitive: auth
    test-gap    (×0.35): no test file changed
  src/utils/hash.ts  [42/100]  +25/-8
    sensitivity (×0.40): sensitive: crypto
📋 变更风险: HIGH (78/100)
3 files changed │ 1 high 1 medium 1 low │ Aggregate risk: 78/100
~/projects/payment-svc/
├── src/
│   ├── billing/
│   │   └── checkout.ts          [HIGH risk=85]
│   ├── config/
│   │   └── stripe.ts             [MED risk=48]
│   └── models/
│       └── invoice.ts            [LOW risk=15]
└── package.json
Signals
  src/billing/checkout.ts  [85/100]  +580/-120
    sensitivity (×0.40): sensitive: payments, secrets
    test-gap    (×0.35): no test file changed
    diff-size   (×0.25): very large: +580/-120
  src/config/stripe.ts  [48/100]  +35/-5
    sensitivity (×0.40): sensitive: payments, secrets
⚠ 600 行支付逻辑重写且零测试覆盖 —— 合并前必须人工 review
HIGH ≥65 高危 MED 35–64 中危 LOW <35 低危 灰色 · 本轮未变更
Try It

自己动手,算一个风险分

下面这个计算器跑的就是项目里真实的评分逻辑。调一调参数,看分数和等级怎么变。

auth
secrets
payments
crypto
migrations
infra
ci
deps
/ 100
03565100
sensitivity × 0.400.000
test-gap × 0.350.350
diff-size × 0.250.100
加权和 × 类型系数 × 10045
Engineering Notes

几个关键决策

📌

为什么必须卡在回合边界

用户关心的是「这一轮改了什么」,不是仓库里累积的所有改动。 所以基线快照必须在 agent_started 拍 —— 只在结束时扫一次,就没有可比对的基准。 每轮结束后基线自动前移,天然实现增量视图。

大文件自动降级,控制扫描耗时

LCS 是 O(m×n),几千行的文件跑满 DP 表会明显卡顿。 超过 2000 行时自动降级为集合匹配(Set 求交), 牺牲一点精度换取稳定的响应速度 —— 反正风险分只需要量级正确。

🪶

零上下文成本

风险卡片走 registerEntryRenderer 渲染为自定义 entry, 不进入消息历史、不参与下一轮请求构造。 意味着无论展示多少次,都不会挤占对话窗口或增加 token 账单。

🎛

权重与阈值全部可配

写死一套规则等于假设所有团队的风险容忍度相同。 三个信号权重、两个判级阈值均可通过 ~/.pi/agent/pi-diff-risk.json 调整 —— 严格的团队可以把 review 阈值下调到 25,让更多改动进入视野。