闭环修复
测量不是终点。修复、验证、并测量效果——一条命令走完。
为什么一定要测量
「修 hotspot 回报最高」是一个假设。在你真的修一个、并看到复杂度移动了多少之前,这个说法没有被检验。
dowse 测量修改前后的复杂度,并报告差值。
packages/cli/src/analyze.ts
cognitive -41 / cyclomatic -22 / LoC -111
已验证: typecheck ✓ / tests ✓
成本: $1.86你需要什么
Claude Code,已安装并登录。
claude --version不需要配置 API key——它直接沿用你现有的认证与权限设置。没有 Claude Code 时,有 ANTHROPIC_API_KEY 就能做诊断;要实际应用修改,需要一个能编辑文件的执行环境。
只做诊断
dowse diagnose --top 3由 LLM 读取排名靠前的 hotspot,返回它为什么危险、该怎么修、大致要花多少。
packages/cli/src/analyze.ts
为什么危险: 五个子命令入口各自重复实现了选项解析、
JSON/人类可读输出的分支,以及表格格式化,全都挤在一个文件里;
展示逻辑与命令控制没有分离
估计: 中等(半天)
步骤:
1. 把 couplingFilters 与 asProxy 抽成纯函数
使其可测试,之后的输出改动就不会悄悄破坏聚合逻辑
风险:
- CLI 的标准输出本身就是面向用户的契约,连列顺序变化都会破坏下游这是判断,不是测量值
请与确定性指标(hotspot、health)明确分开。它是 LLM 的阅读结果。
成本与文件数成正比,用 --top 控制。
让它动手修
dowse fix对排名第一的 hotspot 走完诊断 → 修复 → 验证 → 测量。也可以指定文件。
dowse fix packages/core/src/foo.ts默认是空跑
修改一定会被丢弃。这一轮只做验证与测量,让你看到「如果修了会怎样」。
要保留,加上 --apply。
dowse fix --apply通过验证的修改会留在一个工作分支上。
安全阀
因为这个闭环会改写文件,设置了多道防护。
| 防护 | 行为 |
|---|---|
| 检测未提交改动 | 工作区不干净时拒绝执行 |
| 分支隔离 | 在 dowse/fix-<target>-<sha> 上工作 |
| 独立验证 | 类型检查与测试由 dowse 自己执行 |
| diff 上限 | 默认丢弃超过 400 行的修改 |
| 默认空跑 | 不加 --apply 就什么都不保留 |
验证不交给代理
代理自称「修好了」不构成证据。dowse 直接执行类型检查与测试,按退出码判定。
它会从仓库本身判断怎么执行——先看 packageManager 字段,再看锁文件,最后回落到 npm。pnpm、bun、yarn:那个仓库怎么做,它就怎么做。
失败的修改会被丢弃,并显示失败内容。
packages/foo.ts: 已丢弃 —— 类型检查失败
已验证: typecheck ✗ / tests ✓
src/foo.ts(42,10): error TS2322: Type 'string' is not assignable to 'number'.没有验证脚本时
如果一个 workspace 的 package.json 既没有 typecheck 也没有 test 脚本,就什么都验证不了。dowse 此时拒绝报告「通过」,并丢弃修改——而不是放行一个它从未检查过的东西。
有时它什么都不改
如果代理判断没有值得改进的地方,它就不动这个文件。
packages/core/src/metrics/churn.ts: 代理没有做任何修改
合计: 1 个中 0 个改善 / 成本 $0.56这是正确行为。机械地折腾一个本来就简单的文件,换不来任何东西。
如何看结果
┌────────────────────┬─────────┬───────────┬────────────┬──────┬───────┬───────┐
│ target │ outcome │ cognitive │ cyclomatic │ LoC │ diff │ cost │
├────────────────────┼─────────┼───────────┼────────────┼──────┼───────┼───────┤
│ src/analyze.ts │ applied │ -41 │ -22 │ -111 │ 439 │ $1.86 │
└────────────────────┴─────────┴───────────┴────────────┴──────┴───────┴───────┘| 结果 | 含义 |
|---|---|
| applied | 通过验证(空跑时测量后丢弃) |
| 丢弃 —— 验证失败 | 类型检查或测试未通过 |
| 丢弃 —— 改动过大 | 超出 diff 上限 |
| 未改动 | 代理判断无需改进 |
| 中止 | 工作区存在未提交的改动 |
负数表示改善。没有改善时,也如实报告。