subtraction-audit

v2026.09.24

代码减法审计与反腐化工程。用于给代码库做减法审计(找死代码/重复实现/死依赖/投机性泛化/死门禁),产出证据驱动的删除候选清单并按风险分级执行;也用于给 AI 重度开发的仓库搭建防膨胀门禁(CI、钩子、死代码基线)。核心信念:代码最终会腐化,人写机器写都一样;防腐化唯一可靠的方式是把约束变成机器门禁、把为什么变成文档、把删除变成一等工作流。方法学源自 DeepSeek Harness(dsh-find-simplifications)。

GitHub
Install command
npx skhub add howell5/subtraction-audit
Markdown
SKILL.md

减法审计 · Subtraction Audit

一次 AI 对话的历史就是一部腐化史:AI 写代码太容易、太膨胀、太容易发散,人写机器写都一样,代码最终会腐化。这套方法把"防腐化"变成可重复的流程:证据驱动的减法审计 + 风险分级执行 + 机器门禁。

核心原则(先读,永远不要跳过)

  1. 门禁 > 散文:约定必须变成可执行检查(退出码非零即失败),否则 Agent 不会遵守。AI 对强制门禁的遵从远高于对散文式约定的遵从。
  2. 测试不是真理:测试钉住的是当前行为,不是正确行为——行为可能是历史妥协的产物。测试必须能为你报告的机制而失败,否则它在撒谎。
  3. 删除是一等公民:简化是常规工作流,不是大扫除。每月的删除行数为零 = 腐化警报。
  4. 决策必须写下来:每条非平凡删除配一条决策记录(Problem / 证据 / 代价 / 回退条件)。
  5. 证据先行:没有消费证据的候选一律不报。"看起来没用"不是证据,rg 才是。

何时使用

  • 用户想"清理一下仓库"、"找找死代码"、"这些能不能删"
  • 用户担心 AI 写的代码膨胀/发散/不可维护
  • 用户想给仓库(尤其是 AI 主力开发的仓库)搭建质量门禁

工作流

Phase 0 · 先懂架构(最重要,最容易翻车)

在声称任何东西"死"之前,先回答这些——跳过这步等于把报告建立在地基上:

  • 入口在哪?路由/端点如何挂载?(静态 import / 动态 require / 框架自动发现如 Next.js pages / 字符串路径)
  • 有没有同名活文件?(例:routes/agent/feedback.ts 疑似死,但 routes/feedback.ts 是活的并挂在 /api/feedback——两个不同文件)
  • 构建/部署怎么描述它?(docker-compose、deploy manifest、runbook、README 声称 vs 实际)
  • 有没有看起来像"占位/骨架"但其实是生产核心的东西?(小包可能是队列消费者、worker、调度器)
  • 环境变量/配置旋钮有没有被外部引用(.env.example、部署平台 env、容器编排)
  • 数据库表 / 队列 / 事件名有没有被字符串引用

反例教训(真实事故):一个 101 行的"worker 骨架"其实是生产必需的 DB 队列消费者(轮询 generation_tasks 表)。部署清单里没有它 ≠ 它可有可无——那可能是配置漂移,甚至意味着生产队列已停摆。别把"部署配置里没有"当成"不需要"。

Phase 1 · 基线测量

  1. 死代码基线:npx knip --reporter json(未使用导出 / 类型 / 文件 / 依赖 / 重复实现 / 二进制)
  2. 仓库卫生:误提交文件(提交消息与内容不符的)、.gitignore 覆盖、.env 是否被跟踪(安全项,必须查)、被提交的大产物/工具输出、空目录、死门禁(脚本存在但没接 CI/钩子)
  3. CI/钩子盘点:.github/、husky pre-commit 实际跑了什么;lint/test/typecheck 有没有任何自动流程执行。零 CI 是腐化积累的根因,要单独列成系统性问题
  4. 记录基线数字——之后每次清理都应下降,只许降不许升

Phase 2 · 分域并行调查

按域派并行子代理(api / web / worker / shared / 根与脚本),每个域用同一套方法论提示词:

  • 调查类别:① 死代码(零生产引用,仅测试引用也算,标注证据)② 重复表示(同一事实两份镜像:两个对象镜像同一批字段、手写类型与生成类型并存)③ 手搓 vs 成熟依赖(协议解析/重试/glob/diff/节流——npm 成熟包或 Node 内置可替代)④ 投机性泛化(没 owner 的配置旋钮、占位服务、注释掉的大块、只被测试保护来维护未用 API)⑤ 死依赖(package.json 有、源码零 import)
  • 铁律:每个候选先全仓库搜消费方,区分生产 / 测试 / 文档三类消费;无证据不报;末尾必须给"有意排除"清单(已核实为活/有意保留的)

Phase 3 · 高危复核(删除前必做)

对每个候选追加复核,尤其是 api/web 路由与公共导出:

  • 全仓库 rg,含动态引用与字符串路径(import.meta.glob、require(、.route("字符串"))
  • 同名活文件检查(见 Phase 0 教训)
  • 框架自动发现检查(Next.js pages/API routes 会被框架自动注册——knip 在这里会误报;确认应用用的是框架路由还是 React Router 等显式路由)
  • 部署/文档引用检查(deploy manifest、runbook、env)
  • 测试是否钉死了它不存在(如 doesNotMatch(/<Component/) 断言)——那是删除的助攻证据

Phase 4 · 风险分级

级别含义处置
🟢 绿证据闭环(生产+测试+文档零消费,无同名/动态/框架引用)可放心删
🟡 黄删前确认(是否存在运行时 parse?本地实现是否自持一份?合并后是否要冒烟?)先查再删
🔴 红需产品决策(两条实现路径是否都活着?生产依赖哪个?部署是否受影响?)单独立项,问人

Phase 5 · 分批次执行

  • 每批 = 一类候选(卫生 → 死文件 → 死导出 → 重复合并 → 死依赖),不要混批
  • 每批配一条决策记录(DECISIONS.md:Problem / 证据 / 代价 / 回退条件)
  • 每批后跑验证:tsc --noEmit(全包,不是只查一半)+ lint + knip 基线不升
  • 涉及生产组件的改动(队列消费者、worker、部署相关、env 旋钮)改后必须跑冒烟测试

Phase 6 · 系统修复(比删代码重要)

  • 零 CI 是根因:建最小 CI——lint + test + typecheck 全包 + knip 基线,失败即红
  • 钩子补齐:pre-commit 跑 lint/typecheck(staged 范围)
  • 把"删除行数"放进月度复盘指标:为零就是警报

交付物模板(报告结构)

  1. 腐化存量基线(knip 数字)
  2. 系统性问题(CI/门禁/部署漂移——单独列,比删代码重要)
  3. P0 卫生(误提交/产物/ignore)→ P1 死文件 → P2 死导出 → P3 重复实现 → P4 死状态 → 死依赖
  4. 安全专项(.env 是否入库、密钥扫描)
  5. 有意排除清单(已核实为活的)
  6. 分风险执行计划 + 必须由产品回答的问题清单

常见陷阱

  • 把"部署清单里没有"当成"不需要"——可能是配置漂移或生产停摆(worker 教训)
  • 被 knip 误报带偏——框架自动发现、动态 require、字符串引用都会造成误报,必须人工复核
  • 只见树木——只删明显死符号,漏掉文件级重复生命周期/防御机制最重的地方(检查:两个文件实现同一份 withRetry、两套并行组件树)
  • 一次全删不验证——必须分批 + 每批验证基线
  • 不区分生产/测试/文档消费——"只有测试引用"也是死代码,但要标注证据
  • 不问产品问题就删 🔴 级候选

配套模板

子代理分域提示词骨架(Phase 2 用):

你是代码简化审计员。审计目标:<路径>(<规模>)。只读,绝不修改文件、不跑构建。
方法:只报有证据的候选。每个候选先在**整个仓库**用 rg 搜消费方,区分"生产代码消费" vs "只有测试/文档消费"。没有消费证据的一律不报。
重点找:①死代码 ②重复表示 ③手搓 vs 成熟依赖 ④投机性泛化 ⑤死依赖。
产出:Markdown 表格,按置信度排序,最多 15 条。每列:候选(文件:行+符号)| 证据(rg 搜了什么)| 建议动作 | 置信度(高/中/低)。末尾列"有意排除的"。中文输出。

决策记录模板(Phase 5 用):

# DECISION: <删除/合并/降级> <对象>

## Problem
<当前 API/文件/依赖是什么,消费证据(生产 N 处 / 仅测试 / 仅文档)>

## 证据
<rg 命令与结果;同名/动态/框架引用检查结果>

## 代价 / 我们放弃什么
<最强的反对理由;未来可能需要的场景>

## 回退条件
<什么情况下要恢复>

## 验证
<tsc / lint / knip 基线对比;冒烟范围>

参考来源

  • 方法学源自 DeepSeek Harness:dsh-find-simplifications skill、AGENTS.md 约定、144 条简化类 Agent Notes、质量门禁记录、postmortem 0002/0003(测试不是真理)
  • 实战案例:berryon 减法审计(4 域并行 + knip 基线 + 风险分级),教训已内嵌于本文
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

Not specified

Source path

skills/subtraction-audit

Default branch

main

Latest commit

b3ee4c9

Tree SHA

777f0fb