一键导入
clean-code
用于每一项编程任务,以控制流程复杂度。对于任何创建或修改代码的任务,还应使用 clean-agent 协调模式,让创建者和审查者 SubAgent 将 clean-code 作为共同的代码规范。它强制执行复杂度门禁,将每个分支视为新增的逻辑路径,要求有明确的业务理由,尤其适用于实现和代码审查。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
用于每一项编程任务,以控制流程复杂度。对于任何创建或修改代码的任务,还应使用 clean-agent 协调模式,让创建者和审查者 SubAgent 将 clean-code 作为共同的代码规范。它强制执行复杂度门禁,将每个分支视为新增的逻辑路径,要求有明确的业务理由,尤其适用于实现和代码审查。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
当生成或探索性工作可能失败、需要多次尝试、涉及众多约束、需要验证,或会产生不应污染主 Agent 上下文的中间发现时,主动使用本技能。 本技能运行一个整洁的主智能体循环:主 Agent 只负责协调,将上下文导出到文件,派发创建者/审查者 SubAgent,将重试过程留在主上下文之外, 并且只接收工件路径以及 PASS / RETRY / FAILED 审查说明。
每当用户要求编写、重写、缩短、澄清、审查、润色、重构或改写文档及任何面向人类的说明性文本时,请使用本技能。对于任何创建或修改文档的任务,还要使用 clean-agent 协调模式,使创建者和审查者 SubAgent 将 clean-doc 作为共同的沟通规范。它把信息转化为针对特定受众和决策情境的目标导向型沟通,优先考虑读者的语言和风格,并且只保留与决策相关的信息。
强制执行 CZ 的 Git 和 GitHub 交付风格,包括 gitmoji 提交、受保护的 main、仓库本地 worktree、仅 Squash 的 Auto Merge、拉取请求监控、GitHub Actions 验证和安全清理。每当 Codex 设置或更新 GitHub 仓库、创建功能 worktree、准备或发起拉取请求、跟进拉取请求直至合并并完成 Actions,或执行相关 Git 工作流时,都应使用本技能。
当代码运行缓慢、超时、被终止、消耗大量 CPU、执行长时间批处理作业、进行参数扫描、训练模型、处理大型数据集、运行模拟,或目标规模运行时间未知时,使用本技能。它指导智能体逐步探测运行时间,在可行时进行在线 N-T 进度插桩,采用固定超时采样,执行 N-T 扩展估算,并在尝试目标规模前作出全规模运行的通过/不通过决策。如果进行了优化,它要求保留慢速版本的规范输出,证明语义逐字节等价,并在通过并行投入更多 CPU 前优先消除无效工作。本技能不封装性能分析工具,也不提供通用优化方案;它负责判断应全规模运行、停止,还是转入性能分析和原则性优化。
当任务涉及困难推理、原因不明、无法解释的观测、失败的假设、模糊诊断、复杂系统、涌现行为、调查规划,或当前解释空间不完整的任何情形时,请使用此技能。此技能应用递归残差推理:将尚未解释的内容保留为显式残差,把该残差扩展为下一个推理空间,并生成一条从观测到结论、行动或有界停止原因的可追踪路径。
当创建、修改、解释、诊断或验证模型、规则、评分系统、预测、参数选择、机制假设或研究结论时,请使用此技能。它要求同时具备先验依据与实证验证来评估可靠性,并区分可靠结论与黑箱相关性、空洞叙事、事后线索及不可靠主张。
| name | clean-code |
| description | 用于每一项编程任务,以控制流程复杂度。对于任何创建或修改代码的任务,还应使用 clean-agent 协调模式,让创建者和审查者 SubAgent 将 clean-code 作为共同的代码规范。它强制执行复杂度门禁,将每个分支视为新增的逻辑路径,要求有明确的业务理由,尤其适用于实现和代码审查。 |
通过控制流程复杂度来保证代码正确。
对于任何创建或修改代码的任务,包括实现、重构和调试修复,都要求主 Agent 使用 clean-agent 协调模式。将 clean-code 作为领域门禁:把它作为同一份共享规范交给创建者和审查者 SubAgent。由 clean-agent 负责角色分离、审查、重试和升级;不要用编排规则取代本技能的复杂度标准。
仅当任务明确指定 clean-agent 创建模式或审查模式,并提供相同的共享规范来源以及适用的产物路径或审查约定时,才可将当前角色视为已处于 clean-agent 循环中。此时直接履行该角色,无需再派发其他 SubAgent 或启动嵌套循环。仅仅身为 SubAgent、收到委派任务或被要求写入文件,都不满足此豁免条件。
只有在任务不创建或修改任何产物时,才可直接将 clean-code 用于只读的代码讲解、诊断或审查。
每项编程任务都应使用本技能,尤其是实现、重构、调试和代码审查。
将复杂度视为程序中可能存在的逻辑路径数量。
每个分支都会使需要理解、测试并证明符合预期业务语义的路径成倍增加。需要同时关注的路径过多时,人类和 AI 智能体都会出错。除非明确需要,否则不要增加分支。
将每个逻辑分流点都视为分支。
分支包括 if、else、switch、三元表达式、try、catch、throw、循环、break、continue、return、await、回调、分叉、派生工作、功能标志、布尔参数、回退路径,以及执行可能发生分流的任何其他位置。
在修改代码前应用复杂度门禁。
每个新增或修改的分支都必须有充分理由:
如果这条路径是为兼容性而存在,还必须回答:
如果一个分支缺乏充分理由,应将其视为缺陷。不要把它合理化为代码风格、个人偏好或无害的灵活性。如果一条兼容路径没有负责人、可观察的依赖或退出条件,应将其视为复杂度泄漏,不要加入它。
使用最少的必要路径进行实现。
先审查流程复杂度,再审查代码风格。
按严重程度列出发现:
blocker:新增或现有路径缺乏充分的业务含义、掩盖故障,或使正确性难以证明。non-blocker:路径确有必要,但可以更短、更清晰、更局部,或得到更充分的测试。对每项发现,都应指出具体分支并说明:
对非简单改动报告复杂度结果。
包括:
如果没有新增路径,应明确说明。如果没有新增兼容路径,也应明确说明。
兼容性决定哪些输入有效,以及系统应如何响应这些输入,由此在代码中产生分支。如果只针对一组特定输入和行为进行设计,代码就能保持简单、聚焦。如果试图兼容更多不同的输入、边缘情况或故障模式,就会增加分支,使复杂度上升,并让代码更难理解和维护。因此,兼容性是一种技术债务,只有存在明确的业务需要时才应承担。
AI 智能体可能会意外增加兼容路径,但又始终没有足够上下文来移除它们,因此必须引导智能体避免增加不必要的路径,并让主路径保持清晰。
策略是从一个最小实现开始,解决最常见的情况;只有当明确的业务问题确实需要时,才增加分支。
兼容性类似内存分配:每条兼容路径都会分配复杂度,而每次分配都需要退出条件。兼容性不会被自动垃圾回收;在设计时必须确保人类和 AI 智能体日后能够判断是否可安全移除。
除非生命周期明确,否则不要增加兼容行为。兼容路径应记录代码无法表达的信息:谁依赖这项兼容行为、满足什么条件后可移除,以及未来维护者如何验证移除操作是安全的。
当代码无法明显体现移除条件时,在兼容分支旁使用 COMPATIBILITY 注释:
// COMPATIBILITY: 4.8 之前的移动客户端会发送 `user_id`。
// 当低于 4.8 的移动客户端流量连续 30 天低于 1% 时移除。
const userId = body.userId ?? body.user_id;
如果兼容路径没有明确的负责人、可观察的依赖或退出条件,应将其视为泄漏。避免设计日后无法判断是否可回收的 API、对象模型、标志、回退、迁移或公共成员。
良好的兼容设计让清理成为可能。糟糕的兼容设计会产生永久残留。
默认应避免面向对象设计,尤其是公共可变对象模型、继承和基于覆写的行为。类会把每个公共字段和方法都变成兼容面。成员一旦公开,AI 智能体和人类都很难证明每个公共成员是否必须保持兼容,因此类往往会积累兼容债务,导致复杂度爆炸式增长。
除非语言、框架、外部 API、持久化数据模型或明确的业务需要要求使用面向对象建模,否则应优先选择过程式或函数式设计。目标不是遵循某种范式,而是让依赖关系保持显式、流程保持局部,并让兼容面保持较小。
| 风格 | 适合采用的情形 | 应避免的情形 | 复杂度风险 |
|---|---|---|---|
| 过程式 | 任务是一系列清晰的操作,具有显式输入和输出。 | 依赖全局状态、隐藏的初始化顺序,或使用混合了互不相关工作流的长函数。 | 如果共享状态不受控制,可能演变成庞大的隐式状态机。 |
| 函数式 | 逻辑可表达为纯转换、验证、计算或数据映射。 | 变成无点风格(point-free)、过度抽象、深度嵌套,或将控制流隐藏在通用组合器之后。 | 可能把路径隐藏在高阶抽象之后,使调试变得间接。 |
| 面向对象 | 语言、框架、外部 API、持久化模型或业务领域要求稳定的对象边界。 | 仅为了减少参数数量、为未来扩展做准备,或创建宽泛的公共 API 而引入。 | 公共成员、继承、可变实例状态和覆写会产生兼容面和隐藏路径。 |
不要因为参数较多就引入对象或类。在 AI 辅助编程中,传递显式参数是可以接受的,因为编写和更新调用点的成本远低于维护不清晰兼容面的成本。如果语言支持具名参数,应优先使用具名参数,以提高可读性并避免错误。
必须使用面向对象代码时,应保持范围狭窄:
代码表示现实世界中的概念,但永远不等于现实世界本身。
假设有一个分支条件用于检查现实世界的某种状态。代码可能错误地接受、授权、匹配或允许本应拒绝的事物,也可能错误地拒绝、否认、漏掉或阻止本应允许的事物。如果代码完全知道如何对现实世界进行分类,建模误差就不会存在。对于无法消除的建模误差,应推理当近似判断出错时,系统是否仍然安全且可恢复。
应考虑这些错误的概率和影响。
在模糊或近似分支前使用 ASSUMPTION 注释。注释必须自洽完整:指出所近似的现实状态,然后说明如果分支在任一方向判断错误,系统为何仍然安全。优先使用领域中的行为词,而不是假阳性或假阴性等抽象术语。
// ASSUMPTION: 将电子邮件域名匹配视为用户可能属于该组织的弱信号。
// 如果错误地接受用户:他们只能看到加入申请页面,且在管理员批准前
// 无法访问组织数据。
// 如果错误地拒绝用户:他们仍可手动申请邀请。
if (email.endsWith(companyDomain)) {
showJoinRequest();
}
// ASSUMPTION: 在计费 webhook 可能延迟时,将近期成功付款视为
// 订阅处于活跃状态的充分证据。
// 如果错误地授予访问权限:访问仅限当前计费周期,下一次 webhook 或
// 对账任务会撤销权限。
// 如果错误地拒绝访问:用户可在 webhook 同步后重试或联系支持人员;
// 此处不会修改任何计费状态。
if (lastPayment.status === "succeeded") {
allowAccess();
}
如果注释无法解释近似判断出错时系统为何仍然安全或可恢复,应将该分支视为潜在缺陷或漏洞。不要用注释掩盖风险;应减少权限、增加验证、将决策移到更清晰的边界之后,或明确说明故障模式。
如果错误概率低且影响小,可以接受分支判断错误的风险,但仍应对其进行监控,并在造成问题时及时修复。
注释应说明代码自身无法证明的事实。不要注释普通的直线式代码、显而易见的赋值,或可通过命名和测试表达的行为。
注释主要用于:
COMPATIBILITY:安全移除条件无法在代码中表达的兼容分支。ASSUMPTION:对现实世界进行模糊或近似建模,且近似判断出错时系统必须保持安全。RECOVERY:使用真实回退、有限重试、保留上下文后重新抛出,或边界层报告的错误处理路径。INVARIANT:局部代码依赖一项在其他位置强制执行、且无法在当前位置证明的事实。如果注释仅用于解释代码做了什么,应改为简化代码或重新命名。如果需要长篇注释才能证明某个分支合理,应先尝试删除、合并、缩短、拆分、移动、测试或澄清该分支。
错误抛出和捕获是会创建新复杂路径的强大工具,因此必须谨慎使用。
try-catch 中的错误处理始终只有以下四种有效选择。
只有当代码能作出以下某项决策时,才允许使用 try-catch:
cause 或项目现有辅助函数保留原始堆栈。其他情况下绝不要捕获。不要仅为了记录、忽略错误、不保留原始错误地转换错误,或让代码看起来防御性更强而捕获错误。应在呈现或报告错误的地方记录,而不是在每一层都记录。如果包装错误有帮助,应优先使用 newError 或 scopeError 等现有辅助函数;否则,在受支持时使用 new Error(message, { cause: error })。
需要解决包含多个元素的问题时,应考虑是用一条路径遍历这些元素,还是用多条路径分别处理各个元素。除非有明确的业务理由需要区别对待,否则不要为每个元素增加单独路径。
for 循环需要把集合问题收窄为单个元素,才能形成一条路径。如果这些元素真正彼此独立,它们可以成为不同路径。如果它们属于同一个问题,就应在一条路径中通过遍历统一处理。这样可以让主路径保持清晰,避免不必要的分支。
处理同时包含一般情况和特殊情况的问题时,应考虑特殊情况能否作为主路径的一部分用条件逻辑处理,还是必须使用独立路径。如果特殊情况只是一般情况的变体,通常可以在同一条路径中用清晰条件处理。如果它们代表本质不同的场景,则可能值得使用独立路径。
每个函数内部应优先采用线性流程。读者应能把函数理解为一条通用流程,其中只包含必要的局部决策。
当函数需要讨论多个类别、类型、模式或场景时,应将其视为拆分问题的信号。让调用方聚焦于通用流程,并将针对类别的讨论提取到更具体的函数中,使这个范围更窄的问题能够线性处理。
这遵循从一般到具体的原则:外层函数描述宽泛工作流,内层函数处理具体情况。不要让一个函数同时承载过多类别的流程。