Skip to content

About

Deterministic change-impact reports for any diff — risk findings with file:line evidence, blast-radius graph, review priorities. Zero dependencies.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

impact-report

输入一个 diff,输出一份可复算的变更影响面报告。

风险清单、影响层级图、review 优先级、CODEOWNERS 负责人 —— 每条结论都带 path:line 证据。 零依赖(Python 标准库),自包含 HTML,无 CDN、无 JS、无外链。

CI Python Dependencies License


为什么不用 LLM 直接判断影响面

因为影响面是可以算出来的事实,不是需要"感觉"的判断题。

让模型读一遍 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 分析或写出失败

影响面是怎么算的

  1. 解析 diff —— 兼容 git diff 与 diff -u,支持新增/删除/重命名/二进制、 缺省 count 的 hunk 头,以及 git 的 C 引用路径(中文 / 含空格)
  2. 抽取符号 —— Python 走 ast(精确到函数/类/方法与方法行号),其他语言走保守正则
  3. 建依赖图 —— 静态 import / require / #include 的反向边
  4. 扩散 —— 从变更文件沿反向边 BFS,得到 depth 0/1/2… 的影响层级 (文件已从工作树消失时,用 import 说明符做退化匹配补回反向边)
  5. 判定 —— 13 条规则逐条执行,每条都带 path:line 证据
  6. 渲染 —— 纯算术布局,按层级分列,不用力导向图,不引入随机

风险规则

规则 级别 触发条件
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 位,任何人可复算核对

这意味着评审结论可以被别人一键复现,而不是"某次模型输出的感觉"。


用在 CI 里

- name: 变更影响面报告
  run: |
    python -m impact --repo . \
      --range "origin/${{ github.base_ref }}...HEAD" \
      --format all --fail-on high --strict-empty

产出 impact-report.md,可以直接贴进 PR 评论;命中 high 及以上时这一步会让流水线失败。


作为 Agent Skill

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 路径

English

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-empty

Requires Python 3.9+. See docs/RULES.md for the 13 built-in rules.


License

MIT

About

Deterministic change-impact reports for any diff — risk findings with file:line evidence, blast-radius graph, review priorities. Zero dependencies.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages