输入一个 diff,输出一份可复算的变更影响面报告。
风险清单、影响层级图、review 优先级、CODEOWNERS 负责人 —— 每条结论都带 path:line 证据。
零依赖(Python 标准库),自包含 HTML,无 CDN、无 JS、无外链。
因为影响面是可以算出来的事实,不是需要"感觉"的判断题。
让模型读一遍 diff 然后说"这个改动可能影响支付模块",你既无法验证它对不对,也没法在 CI 里复现。
impact-report 把这件事拆成两半:
| 谁 | 负责什么 |
|---|---|
| 确定性内核 | 改了什么、影响了谁、命中哪条规则、证据在哪一行 —— 纯函数,可复算 |
| Agent / 人 | 读 IR,挑重点,写人类读得懂的叙述 —— 但不许引入 IR 之外的事实 |
每份报告带一个 report_id(IR 的 sha256 前 12 位)。同一份输入,任何人都能跑出字节完全相同的结果。
$ python -m impact --repo tests/demo --diff tests/demo/change.patch --format all
已写入 impact-report.html(html)
已写入 impact-report.json(json)
已写入 impact-report.md(md)
[中] 中风险(41/100):对外 API 变更。本次改动 1 个文件,影响链覆盖 4 个文件。 | 风险分 41/100 | 改动 1 文件 / 影响 4 文件 | report_id=<12 位内容指纹>
优先 review:app/api.py、tests/test_core.py、app/worker.py命中规则:R001 对外 API 变更(高)· R002 签名变更(高)· R012 未同步更新测试(中)· R004 影响面(低)。
HTML 报告长这样:结论卡 → 影响面 SVG(按层级分列,纯算术布局)→ 风险清单(带证据) → 本次改动 → 变更符号与调用方 → 受影响文件 → 建议优先 review → CODEOWNERS。
📷 想加一张截图或 GIF?渲染一次然后截图放进
docs/assets/即可, 具体位置见docs/PUBLISHING.md。
# 1) pip(发布到 PyPI 后可用)
pip install impact-report
# 2) 作为 Agent Skill
npx skills@latest add Time0ut575/impact-report
# 3) 零安装,直接用
git clone https://github.com/Time0ut575/impact-report && cd impact-report
python -m impact --help要求 Python 3.9+,没有任何第三方依赖。
# 三种输入方式,任选其一
python -m impact --repo . --range HEAD~1..HEAD # git 区间
python -m impact --repo . --diff change.patch # patch 文件
git diff main...HEAD | python -m impact --repo . --diff - # stdin
# 想先看看效果(用内置 demo,不需要 git 历史)
python tests/make_fixture.py
python -m impact --repo tests/demo --diff tests/demo/change.patch --format all常用参数:
| 参数 | 说明 |
|---|---|
--format html|json|md|all |
输出格式,默认 html |
--out / --json-out / --md-out |
各自指定输出路径,自动创建父目录 |
--max-depth N |
影响面扩散层数,默认 2(超过 3 层信噪比急剧下降) |
--fail-on none|low|medium|high|critical |
CI 门禁,命中即退出码 1 |
--strict-empty |
空 diff 视为用法错误(退出码 2),防止区间写错后绿灯通过 |
--verify-determinism |
跑两遍并逐字节比较,自证可复算 |
--timestamp |
报告里写入生成时间(会破坏可复算性,与上者互斥) |
| 产物 | 用途 |
|---|---|
impact-report.html |
自包含报告:结论、影响面 SVG、风险清单、受影响文件、负责人 |
impact-report.json |
中间表示(IR),Agent 与 CI 消费的唯一事实来源 |
impact-report.md |
直接贴进 PR 评论 |
| 退出码 | 0 通过 · 1 命中 --fail-on · 2 用法错误 · 3 分析或写出失败 |
- 解析 diff —— 兼容
git diff与diff -u,支持新增/删除/重命名/二进制、 缺省 count 的 hunk 头,以及 git 的 C 引用路径(中文 / 含空格) - 抽取符号 —— Python 走
ast(精确到函数/类/方法与方法行号),其他语言走保守正则 - 建依赖图 —— 静态
import/require/#include的反向边 - 扩散 —— 从变更文件沿反向边 BFS,得到
depth0/1/2… 的影响层级 (文件已从工作树消失时,用 import 说明符做退化匹配补回反向边) - 判定 —— 13 条规则逐条执行,每条都带
path:line证据 - 渲染 —— 纯算术布局,按层级分列,不用力导向图,不引入随机
| 规则 | 级别 | 触发条件 |
|---|---|---|
R001 |
高 | 改动了对外符号,且仓库内已有调用方 |
R002 |
高 | 定义的同一行同时出现删除与新增(签名变更) |
R003 |
阻断 / 中 | 符号被删除;若仍有引用则为阻断级 |
R004 |
高 / 中 / 低 | 下游文件数 ≥8 / ≥4 / ≥1 |
R005 |
阻断 | 命中迁移、*.sql、schema.prisma、*.proto |
R006 |
高 | 命中鉴权/安全命名(auth、token、session…) |
R007 |
中 | 配置与环境文件(settings/、*.env、*.toml…) |
R008 |
高 | 依赖清单(requirements*.txt、package.json、go.mod…) |
R009 |
中 | CI 与容器(.github/workflows/、Dockerfile…) |
R010 |
中 | 入口文件(main.py、app.ts、server.py…) |
R011 |
阻断 | 被删除的文件仍被其他文件 import |
R012 |
中 | 改了生产代码但没有同步改测试 |
R013 |
中 / 低 | 增减行数 ≥1000 / ≥300 |
每条规则的触发条件、证据形态、常见误报与建议动作,见 docs/RULES.md。
$ python -m impact --repo . --diff change.patch --verify-determinism --format json --out out.json
determinism: OK (ir=same html=same md=same)渲染器有几条硬约束,CI 会逐条检查:
- 不用随机数、不读当前时间、不依赖字典/集合迭代顺序
- HTML 里没有
<script>、<link>、<img>、href= report_id只取决于 diff 内容 + 仓库内容:换 checkout 目录名、换 patch 文件名都不会变, 同事之间可以拿report_id直接核对"是不是同一份报告"report_id是 IR 的 sha256 前 12 位,任何人可复算核对
这意味着评审结论可以被别人一键复现,而不是"某次模型输出的感觉"。
- name: 变更影响面报告
run: |
python -m impact --repo . \
--range "origin/${{ github.base_ref }}...HEAD" \
--format all --fail-on high --strict-empty产出 impact-report.md,可以直接贴进 PR 评论;命中 high 及以上时这一步会让流水线失败。
skill/SKILL.md 约束 Agent 只能做两件事:跑内核拿事实、读 IR 写叙述,
并且强制每条结论引用 path:line 或 finding.id,不许编造 IR 里没有的文件与风险。
放进你客户端的 skills 目录即可(Claude Code / Codex / OpenCode / DSH 等);
不同客户端的目录约定差异见 docs/PUBLISHING.md。
impact-report/
├─ impact/ 内核(零依赖)
│ ├─ diffparse.py unified diff 解析
│ ├─ symbols.py 符号与 import 抽取
│ ├─ graph.py 反向依赖图 + 影响面扩散
│ ├─ rules.py 13 条风险规则
│ ├─ report.py 确定性 IR + 风险分 + report_id
│ ├─ render.py 自包含 HTML / 内联 SVG / Markdown
│ └─ cli.py CLI + CI 门禁
├─ skill/SKILL.md Agent Skill 外壳
├─ scripts/
│ ├─ selfcheck.py 端到端 + 确定性自检
│ └─ smoke_range.py 用真实 git 仓库验证 --range
├─ tests/ 22 个用例 + demo 仓库生成器
└─ docs/
├─ RULES.md 规则参考
├─ PUBLISHING.md 发布清单
└─ LAUNCH.md 冲 star 行动清单
- 非 Python 语言的符号抽取是保守正则,会漏、可能误报;Python 走
ast,准确度高 - 依赖图只认静态
import/require/#include,不解析动态导入、依赖注入、跨语言调用 - 仓库超过
--max-files(默认 4000)会截断,inputs.index_truncated会置真 CODEOWNERS是 last-match-wins(与 GitHub 一致,catch-all 要写在前面),匹配用简化的fnmatch- 「调用方」证据(
R001/R003)在变更点周围最多 3 层、最多 80 个文件范围内扫描, 范围见inputs.reference_scan_depth/reference_scan_files - 空 diff 默认只告警并退出 0("没改动"本身不是风险);CI 里请加
--strict-empty - 被删除 / 重命名的旧文件已不在工作树时,反向边靠 import 说明符退化匹配补回,精确度低于正常解析
- 不支持按规则关闭(
.impactignore/--disable-rule在路线图上) - 不会推断"业务影响"(比如"这会掉多少 GMV")—— 那不属于确定性代码的职责
-
--disable-rule/.impactignore -
--baseline:与上一次报告对比,只报新增风险 -
benchmark/:覆盖召回率、索引耗时、token 成本 - 更多语言的精确解析(TypeScript / Go 优先)
- GitHub Action 官方封装,一行接入
非常欢迎,尤其是新规则和新语言支持 —— impact/rules.py 是一条规则一段代码,
加规则不用动别处。请先读 CONTRIBUTING.md,其中「确定性铁律」是硬性要求。
python -m unittest discover -s tests -v # 22 个用例
python scripts/selfcheck.py # 端到端 + 确定性
python scripts/smoke_range.py # --range 真实 git 路径impact-report turns any diff into a deterministic change-impact report: risk findings with
path:line evidence, a layered blast-radius graph, review priorities and CODEOWNERS owners —
rendered as a self-contained HTML/SVG/JSON/Markdown. Zero dependencies (Python stdlib only).
Every report carries a report_id (sha256 of the intermediate representation), so any reviewer
can reproduce the exact same bytes. The code writes the facts; the agent writes the narrative.
python -m impact --repo . --range main...HEAD --format all --fail-on high --strict-emptyRequires Python 3.9+. See docs/RULES.md for the 13 built-in rules.