关于 goal-sloc
goal-sloc 面向编码 Agent,指导其简化代码库,并将 SLOC 视为代理指标而非最终目标。它强调验证、结构性改进和如实报告,避免只做表面删减。
主要功能
- 01预检指标与验证保障
- 02使用语义工具分析死代码
- 03按优先级安排精简方式
- 04审查结构性与表面性改动
- 05提供验证和升级处理指引
适用场景
- 01规划代码规模精简工作
- 02检查 SLOC 变化是否带来真实改进
- 03在重构期间验证系统行为
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ maxim-saplin/ goal-sloc --skill goal-sloc安装后在 Claude Code 中输入/goal-sloc确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/flutter-sloc-reference.mdminimal-tools.mdpreflight-checklist.md详细介绍
goal-sloc — 以 SLOC 为北极星,但保持诚实
SLOC 是代理指标,不是目标。目标是打造一个更简单、工程设计更完善且依然正确的系统。SLOC 很有用,因为它能迫使你找出冗余和意外复杂性,并做出真正的取舍。它也很危险,因为它极易被操纵,而且最容易改变它的办法(删除注释、把代码打包到更少的行或调整格式、提取辅助函数)往往不会改善系统。你删除的每一行,都是一项必须证明的主张:“系统现在更好或至少不差,而且仍能正常工作。”
两条不可妥协的原则:巧思(找到真正的结构性收益)和诚实(绝不以牺牲系统为代价优化代理指标;应揭示难以面对的事实,而不是将其掩盖)。
自我审查(承重规则)
最主要的失败模式:*如果不加约束,你会用最简单的办法优化指标,然后称之为进步。*要防范自己的本能:
- 每隔几个里程碑,对缩减内容进行分类:结构性工作所占的比例(移除无用内容或占位内容、迁移、去重、重新架构)与廉价手段所占的比例(精简注释、格式调整、空白字符调整、提取辅助函数)。
- 如果廉价手段占主导,你就是在欺骗自己——停下来寻找结构性工作,或者报告结构性改进空间已枯竭(这本身就是诚实的发现)。
- 在向人类提交的里程碑报告中列出这一比例;不要让他们自己去发现。
0. 预检——开始删减前务必完成
跳过预检是导致「简化」出问题、失去可信度的首要原因。请逐项完成 references/preflight-checklist.md 中的检查;全部答完之前不要开始删减。
0a — 明确目标并理解指标。
- 确认当前目标:具体数值是多少、由哪个工具或命令精确测量,以及目标是否已变动?SLOC 目标通常会随讨论变化,且不会写入配置——每当相关人员提高目标时,都要重新确认;不要相信过时的目标记录。
- 阅读测量工具的说明。它会统计哪些路径或文件(仅跟踪的文件?生成文件?二进制文件?测试?)?如果需要由你定义指标,默认采用非空且非纯注释的行数,并说明是否统计文档注释,以便结果可比较。
- 记录基准总数及各区域的细分数据。
0b — 建立反馈闭环(关键前提)。 无法验证的代码不能安全删减。评估安全保障措施,先补齐缺失项:
- 基准状态下测试通过,并且对你要改动的部分有实际覆盖。测试稀疏 = 最大风险——先补足这些部分的覆盖,否则就要极其谨慎,并进行大量运行时检查。
- 静态分析、类型检查和 lint 均通过。如果没有分析器?最低要求是解析或编译检查加测试。 每次改动后都要重新运行。
- 端到端运行并实际验证真实系统——根据系统形态选用合适方式:应用驱动程序、UI 自动化、HTTP 调用、CLI 调用、集成测试,或(对于库)通过使用者或示例调用其公共 API。最常见、最危险的缺口是缺少运行时反馈闭环——单元测试能证明契约,却不能证明「它确实能运行」。如果无法实际验证,这是首要风险:构建驱动程序,或明确标出这一点。工作期间务必实际运行系统。
0c — 确保能够回滚。 在分支上工作(绝不要在 main 上工作)。每完成一个已验证的里程碑就提交一次,确保任何改动都能轻松撤销——激进删除或重写时尤其需要这样做。
0d — 使用真正的工具绘制代码图谱(不要用 grep)。 使用语义分析工具生成死代码/未使用导出报告以及依赖关系图和复杂度热点。grep 不是代码智能工具——它会漏掉相对导入、重新导出、tear-off、动态/字符串分发等情况,导致错误地判定代码「已失效」。仅用 grep 确认工具报告的结果。如果没有安装相关工具且无法安装,可按以下顺序回退:语言服务器 → 简易 AST 脚本(references/minimal-tools.md 中有可直接粘贴的代码片段)→ 仅用 grep 确认。
0e — 分类并计算下限。 将统计范围内的代码划分为发布代码、测试/开发脚手架和生成代码/平台代码/供应商代码(即「下限」)。计算不可再缩减的下限(生成的配置文件、按行统计的二进制资源、第三方代码),并进行计算:目标在 下限 + 实际功能所需的最小代码量 之上是否仍可达成?如果不可达,现在就说明——剩余差距属于产品/范围决策,而非工程问题。
1. 诚实的精简顺序
合理性/价值顺序——但越往下风险越高:第 1–2 项是安全的;第 6–8 项风险较高,需要建立强有力的反馈闭环(§0b)。每项完成后都要验证(§4)。
- 删除死代码——没有任何引用的文件/导出项/函数(经语义工具验证,而不是用 grep)。纯收益。
- 移除占位/空操作子系统——功能已完整接通,却什么也不做(例如硬编码为“不可用”的开关,或只记录日志的空操作方法)。作为功能,它们就是累赘。纯收益。
- 将放错位置的代码移回正确位置——把发布源代码中的测试/开发/自动化脚手架移到
test/或由薄接口隔离的dev/区域。这是实实在在的结构修正,计数器(不变)会如实反映。(移动文件 ≠ 修改计数器——§2。) - 消除真正的重复代码——将重复代码块合并为一个参数化辅助函数;将 N 个近乎相同的文件合并为一个。(代码行数通常变化不大;这么做是为了提高清晰度。)
- 注释/冗余清理——删减复述代码的注释和 AI 留下的噪声。这是合理的,但也是精神陷阱:这是成本最低的手段,能让数字下降,却毫无设计上的收益。可以顺带清理你本来就要重写的文件;陷阱在于把它单独当作策略。如果这占了你大部分的“进展”,请参阅自我审查。
- 将测试视为规范,进行全新重写——以测试为依据,从头重写最大的文件,丢弃累积的陈旧代码。只有在测试忠实地描述行为时才安全——否则你会把 bug 重写成特性。(对于已经精简过的代码,适度提高代码密度是常见结果;但这不是目标。)
- 架构简化——合并冗余层,消除反模式,深化模块。**代码行数大多持平或增加——这么做是为了质量,而不是数字。**谨防 §5 中的陷阱。
- 委托给库——用成熟依赖替代手写代码,可以将这些代码移出统计范围,而且通常更好——但前提是该库确实是更好的选择,绝不能为了躲避计数器;还要权衡依赖成本。
用尽第 1–8 项后,如果仍高于目标,唯一剩下的手段就是删减功能/范围/平台——这是产品决策。把底线计算清楚后升级给人工处理;绝不要悄悄删除功能。
2. 投机取巧与诚实(请读两遍)
界线在于:系统真的变得更简单/更好了吗,还是你只改动了数字?
| 做法 | 判定 | 原因 |
|---|---|---|
| 修改度量工具以排除某些路径 | ❌ 投机取巧 | 改的是尺子,不是实际对象。 |
| 扩大格式化宽度/压缩代码行/删除空行来获胜 | ❌ 投机取巧 | 只是表面功夫;没有实际变化;还会损害可读性。 |
| 为了获胜删除真实功能/文档 | ❌ 投机取巧(死代码/占位内容除外) | 把范围删减伪装成清理——应升级处理。 |
| 将测试/开发代码移到测试/开发目录 | ✅ 合理 | 结构正确;计数器如实反映现实。 |
| 删除死代码/占位代码/重复代码 | ✅ 合理 | 系统确实变小了。 |
| 精简复述代码/AI 噪声注释 | ✅ 合理的清理——绝不能作为策略 | 这是容易奏效的手段,过度依赖会偏离初衷。 |
| 将手写代码委托给真正的库 | ✅ 合理(如果是更好的工程方案) | 自行维护的代码更少,效果也更好。 |
**度量风险:**自动格式化工具可能会悄悄重新增加你刚精简的行数,让“成果”变成假象。固定一种格式化方案;衡量格式归一化后的差异(一致地重新格式化副本并进行差异比较),从而区分实际精简与格式噪声。不要让子 Agent 临时随意重排格式。
**诚信义务:**如实报告底线;当目标与约束(保留所有功能/平台/不投机取巧)冲突时,用数据说明情况并让人工决定;绝不要声称“它能正常工作”,除非你实际运行过;报告跳过了什么以及原因;报告结构性改动与低成本清理的比例(自我审查)。
3. 停止条件与升级处理
- **收益递减:**连续几个里程碑的成果越来越少、风险却越来越高,或者剩下的所有杠杆都无法减少 SLOC——停止并汇报;不要为了制造变更而制造变更。(警惕重构→后悔→回滚的循环。)
- **范围蔓延防护:**不要启动本次会话内无法完成并验证的重新架构。只折叠了一半的层,或只迁移了一半的模式,都不如不动。
- **触及下限:**当只剩下删减功能、范围或平台时,用具体数字向人类升级并说明权衡——由他们决定。
4. 验证节奏
在 references/preflight-checklist.md → "During-work loop." 中统一定义。简而言之:每次变更后都运行静态分析或编译,并运行相关测试;在里程碑处运行完整测试套件,并在有代表性的目标上运行真实系统并进行对抗性测试(快速连续执行操作、输入错误数据、切换模式——潜在问题和新引入的 Bug 往往会在此时暴露);然后重新测量并提交。
5. 陷阱与风险
| 风险 | 缓解措施 |
|---|---|
| 没有测试或测试薄弱,导致盲目重构 | 先补充涉及区域的测试覆盖率;依靠运行时测试。 |
| 缺少运行时反馈循环 | 在删减之前构建安全的端到端测试;并实际运行。 |
| 把 grep 当作分析工具,导致误判死代码 | 使用语义分析工具;grep 仅用于确认。 |
| 格式化导致代码膨胀 | 固定一种格式;测量格式归一化后的差异。 |
| “深层模块 / 重构 ≠ 行数更少” | 提高内聚性会增加脚手架代码;为改进设计而做,不要把它说成减少 SLOC。 |
| 上帝对象陷阱 | 折叠冗余层可能会让接收方的职责过度集中——重现刚刚消除的坏味道。折叠后应提取内聚的协作者。 |
| 并行 Agent 相互覆盖改动 | 有风险或重叠的编辑应按顺序进行;只有处理互不相关的文件时才并行;完成后进行全局验证。 |
| 把生成代码 / 平台代码 / 原生代码视为不可改动或可以随意改动 | 常见的默认盲点:生成的脚手架代码确实是下限,但真正自定义的原生代码 / 平台代码和其他代码一样可以精简。要分清两者;不要忽视后者。 |
| 将收益递减误认为失败 | 识别只剩删减范围的时机;升级处理(§3)。 |
6. 参考资料
references/preflight-checklist.md— 可直接复制粘贴的预检清单,以及权威的工作期间循环。references/minimal-tools.md— SLOC 计数规范,以及未安装语义分析工具时可直接粘贴使用的死代码 / 孤立导入脚本。references/flutter-sloc-reference.md— Flutter/Dart 相关内容(hooks 与 StatefulWidget、GlobalKey→controller、provider/ChangeNotifier 分层、sealed classes、数据驱动 UI、平台下限、dart format、DCM/GitNexus、通过 VM-service 扩展驱动应用)。