howell5/willhong-skills

subtraction-audit

代码减法审计与反?

Installation

$ npx skills add howell5/willhong-skills --skill subtraction-audit

Summary

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

Also in this package

Other skills from howell5/willhong-skills.

npx skills add howell5/willhong-skills

Browse all from howell5/willhong-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 1
License MIT
Default branch main
Open issues 0
Status Active

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,388 B
  • docs SUMMARY.md 583 B

History

  1. First recorded snapshot · 1 installs

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.globrequire(.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 基线 + 风险分级),教训已内嵌于本文