Community编程与开发github.com

fictormarcel2/untangle

用于修复因AI编码工具快速构建而变得难以更改或信任的代码库——存在重复实现、_v2/_final文件、看似通过但无意义的测试、死代码、修复破坏无关功能、无人能解释的代码——或者当需要审计、清理、解耦或去混乱化仓库,或使其对编码智能体安全可继续使用时。

untangle 是什么?

该技能旨在系统性地解构由AI编码工具快速构建导致的混乱代码库,解决重复实现、死代码、无效测试等核心问题。它适用于Claude Code等AI编程代理,通过严格四阶段流程(审计、分类、重构、维护)确保代码库变得可维护、可验证。审计阶段只读分析,不修改代码;分类阶段由人类决策,AI提供推荐;重构阶段逐个切片安全修改;维护阶段添加自动化检查防止混乱复发。核心原则包括:保持修改和决策的透明记录(UNTANGLE.md)、每个发现必须有证据、任何修改前需人类批准、结构和行为变更分两次提交、优先减代码而非增依赖。最终目标是每个功能只有一种实现方式、测试能有效捕捉错误、每个代码片段都有存在理由、决策被文档化、自动化检查阻止混乱再生。

兼容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/fictormarcel2/untangle-everything/tree/HEAD/skills/untangle

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

解耦 (Untangle)

一个混乱的代码库是一堆无人做出的决策。AI只按照下一个提示的要求编写代码,从不拒绝,从不提议重新思考,因此仓库现在对每件事情都有三种实现方式,且没有任何记录说明为什么。解耦意味着为每个决策做一个选择,将其记录下来,并使代码及其检查与之一致。

你负责映射、提供证据和执行修改。人类负责做出决策。

目标状态

当以下所有五点成立时,工作完成:

  1. 每种功能只有一种方式:认证、数据访问、错误处理、配置、日志。
  2. 当行为错误时测试会失败。
  3. 每个保留的代码片段都有存在的理由,且有人能说出来。
  4. 决策被记录下来,放在下一个开发者或智能体会读到的地方。
  5. 自动化检查防止混乱重新蔓延。

如果代码库已经满足这些条件,就说明情况并停止。无中生有地制造工作是失败的审计。

每个阶段的规则

  • 分类账就是状态。 仓库根目录下的 UNTANGLE.md 记录覆盖率、发现、决策和进度。首先阅读它,并在你的回合结束前更新它。一次长时间的清理会超出你的上下文窗口;分类账是传承下去的东西。如果它已存在,则从中恢复,而不是重新审计。
  • 有证据才算是发现。 每个发现都带有 文件:行号 以及能证明它的命令或观察结果。“感觉很乱”不是发现。
  • 你提出建议,人类做决定。 未经批准的分类账行,任何内容都不能被删除、合并或被宣布为赢家。为每个决策推荐一个默认选项,以便审批过程轻松。
  • 结构和行为变更需分两次提交。 重构同时修复错误的情况无法被验证是哪一种变更。
  • 只报告你实际运行过的内容。 记录命令及其真实结果。记录你仔细阅读过的内容、你仅映射到的内容,以及你从未打开过的内容。
  • 减法。 不重写,不引入新依赖,不添加新抽象层,不添加兼容性填充。代码行数应该减少。
  • 秘密。 如果发现活跃的凭证,立即停止并告知人类立即更换。永远不要打印其值。永远不要自己重写历史。

阶段

审计 → 分类 → 重构 → 维护,按此顺序。在没有分类账的情况下,从审计开始。在有分类账的情况下,从它所记录的阶段继续。指定阶段或路径的参数可以缩小工作范围。它永远不能跳过审计,因为重构仅基于已批准的发现进行。

1. 审计:只读

除了 UNTANGLE.md 之外,不更改任何内容。从 templates.md 中的模板开始。

  1. 基线。 找到真实的安装、构建、测试、lint 和类型检查命令并运行它们。逐字记录结果。一个连其 README 中的构建命令都无法工作的仓库是一个发现。
  2. 先映射,再阅读。 文件列表、大小、入口点、导入方向、来自 Git 历史的变更频率。然后选择要仔细阅读的地方,风险最高的优先:认证、金钱、数据写入、基础设施。按路径记录覆盖率。
  3. 使用 catalog.md 进行搜索。 临时运行分析工具(npx、uvx、go run),使项目的依赖保持不被触及。
  4. 测试测试本身。 选择三个业务规则。对于每个规则,修改该规则使其在不引发异常的情况下返回错误答案,运行测试套件,然后使用 git restore 恢复文件,并确认 git status 是干净的。记录是否有任何测试注意到了改动。
  5. 评分:使用 templates.md 中的评分卡。每个检查项为通过、失败或“无法从仓库验证”,并附带人类必须回答的问题。
  6. 报告并停止。 按风险列出最重要的发现,什么是好的,以及哪些未被覆盖。

2. 分类:决策

  1. 在逐一列出修复方案之前,寻找那个能同时解决多个发现的单一决策。问问自己,如果从一开始就知道需求,这段代码应该是什么样子。
  2. 对于每个存在竞争实现的关注点,推荐一个赢家并给出理由:调用次数最多、测试最完善、与框架约定最匹配。
  3. 将每个发现标记为“保留”、“修复”或“删除”。按风险排序:造成危害的可能性 × 依赖它的程度。
  4. 对切片进行排序。安全网优先,然后是删除(成本低且能缩小后续所有工作),接着是整合,最后是重组。
  5. 提供一张表格,一次性获得批准,并在获得批准前停止。将拒绝记录为 wontfix 并附上原因。

3. 重构:一次一个切片

在名为 untangle/<主题> 的分支上工作。绝不推送。对于每个已批准的切片:

  1. 安全网。 测试覆盖了此切片所触及的行为,并且你已经观察到它们在故意破坏下失败。如果没有,首先编写特征化测试:固定当前代码所做的,包括其中的错误。将每个错误作为新发现记录,而不是悄悄修复它。
  2. 修改一个关注点。
  3. 使用完整的基线命令进行验证。 如果出现红色,修复修改或还原该切片。
  4. 提交,附带发现 ID,更新分类账,然后继续下一个切片,无需询问。

当某个切片需要分类账中尚未包含的决策时,停止并询问。

“死亡”意味着被证明不可达:静态工具的结论加上通过字符串查找、反射、路由、依赖注入名称、配置、定时任务、模板、公共 API 和仓库外部调用者进行的动态可达性搜索。任何未被证明的内容都是 suspect(可疑的),并交给人类处理。

4. 维护:使其持久

  1. 对于每个决策,询问机器能否强制执行。如果可以,添加 lint 规则、导入边界、CI 步骤或测试。文本规则只适用于机器无法检查的情况。
  2. 根据决策编写 AGENTS.md:命令、每个关注点的唯一方式(附带示例文件指针)以及新代码的位置。保持足够简短,以便每个会话都能阅读。如果存在 CLAUDE.md、.cursorrules 或类似文件,让其中一个作为源文件,其余的都指向它。
  3. 为每个选择了赢家的决策编写 ADR。
  4. 确保 README 中关于干净签出的设置是真实的,并提交一个环境变量模板。
  5. CI 运行基线命令并在失败时报告错误。分支保护和告警路由位于仓库外部,因此为人类列出它们。
  6. 重新评分,记录前后对比,并将未完成的项目列在分类账中。

当你想要这样做时

想法应该这样做
“趁我在这儿,顺手修复一下”添加一个发现。未经批准的修改正是混乱产生的根源。
“测试过时了,我调整一下断言”结构变更后测试变红意味着变更改变了行为。修复该变更或还原它。
“没有地方引用这个,它是死的”针对动态可达性证明它,或将其标记为 suspect。
“一个包装器能让旧的调用者继续工作”更新调用者。一个填充层只是换了个新名字的多余物。
“这应该重写”使用切片。重写会丢弃所有测试未覆盖的行为。
“我已经覆盖了整个代码库”覆盖率是分类账所说的你读过的内容。
“上下文越来越长了,我得快点收尾”写入分类账,说明剩余内容,然后停止。
“测试套件通过了,所以它正常工作”通过只证明了审计步骤 4 中显示的测试能力。

相关技能