编码纪律
概览
把所有编码任务先收束到一个工程纪律入口:先判断任务类型,再选择最小合适流程,最后用复杂度、测试、接口、故障和长期维护责任做门禁。
这个 skill 是总入口,不是把所有规则都硬套一遍。简单改动走轻量路径;行为变化、bug、重构和审查走对应模式。它也不替代项目自己的 AGENTS.md、测试策略或代码规范;如果有冲突,优先遵守用户明确要求和当前仓库规范。
执行分组
按下面九个环节组织任务;第 3、4、7、8、9 步按需触发,不要求每个任务完整走一遍:
- 边界与授权:确认目标、非目标、成功标准、只读边界和副作用授权。
- 代码与事实理解:读取当前代码、测试、规范、接口、数据模型和领域术语。
- 方案、Spec 与设计确认:复杂需求读取 plan-spec-and-grill.md,执行内置的规格化和逐轮确认。
- 任务拆分与执行切片:大功能或重构读取 plan-spec-and-grill.md,执行内置的纵向 tickets 和依赖拆分。
- 代码实现:读取 implementation-loop.md,按功能、故障或重构模式小步修改。
- 测试、审查与质量验证:按实现验证规则运行类型检查、测试和 review,检查 AI 编码反模式和文档影响。
- 编码完成后的架构复盘:非微小改动读取 architecture-improvement-review.md,提出架构改进候选;不自动重构。
- 文档、知识与交接收尾:代码影响文档时联动
neat-freak;需要中断或移交时读取 handoff-and-delivery.md。 - Git、Worktree 与交付核对:涉及提交、冲突、分支或 push 时读取 git-worktree-guardrails.md。
主链路是“理解 → 实现 → 验证 → 收尾”。方案、拆票和架构复盘是受条件控制的辅助环节,不是普通编码任务的固定前置流程。
所有运行期中间产物统一放到项目根目录的 .baku-coding-discipline/,按类型分组;不在项目根目录散落 spec、plan、ticket、报告、诊断脚本或 handoff。具体目录和生命周期见 runtime-artifacts.md。
第一步
开始编码前先完成这四件事:
- 明确用户要的结果、非目标、假设和成功标准。
- 如果用户说“先研究、只排查、先方案、不要执行、先别改、只读看看”,先进入只读 / 方案模式。
- 搜索并阅读相关代码、项目规范、测试和已有接口;不要凭文件名猜。
- 选择一个执行模式;不确定时先用最轻量模式,再按风险升级。
- 复杂需求存在关键未决事项时,可在只读 / 方案模式下按需进行规格化、逐轮确认和纵向切片;明确需求和微小修改不要额外触发。
- 如果要编辑文件,先给 3-6 条计划,并写清每步验证方式;微小修改可以压缩流程,但不能跳过最小验证。
- 预判文档影响:只要变更可能影响 API、数据结构、配置、状态、业务规则、模块入口、联调方式、运维方式或用户可见行为,就把文档同步列为本次任务的一部分。
Git 提交建议
- 一个提交只表达一个清晰、可回滚的意图,标题说明结果,正文说明动机、影响和验证。
- 可以采用 Conventional Commits,例如
feat(scope): add capability;常见类型包括feat、fix、refactor、docs、test、perf、build、ci和chore,不要用feature代替feat。 - 分支同步、提交标题语言、emoji、scope 命名、推送门禁和是否允许强制推送属于项目约束,按当前仓库的
AGENTS.md执行。 - 涉及提交、push、worktree 或分支归属时,必须先读取 git-worktree-guardrails.md,再执行只读核对、提交范围确认和 push 前门禁。
模式路由
按任务选择一个主模式,必要时组合:
- 只读 / 方案:用户要求先研究、只排查、先方案、不要执行时使用。只允许读代码、查日志、运行只读查询和写方案文档;禁止改代码、跑有副作用命令或顺手修相邻问题。
- 微小修改:错别字、明显一行配置、纯格式或小文案。直接做最小改动,运行最便宜的检查。
- 功能 / 行为变更:新增能力或改变行为。走 TDD 风格:一个可观察行为,一条测试或验证路径,一次最小实现。
- 故障 / 性能回归:报错、失败、异常、性能下降。先建立反馈循环和复现,再假设、加观测、修复、补回归测试。
- 重构 / 架构调整:结构调整、抽象迁移、技术债偿还。先确认 ROI、范围和回滚边界,再拆小步,每步保持可工作。
- 审查:用户要求 review、合并前检查或审查 AI 生成代码。按规范和需求两轴报告问题,先列风险。
按需读取 reference,避免把所有细则一次性塞进上下文:
- mode-routing.md:选择主模式、只读边界、各模式完成条件。
- ai-coding-antipatterns.md:写业务逻辑、错误处理、测试、调试修复或审查 AI 生成代码时,识别静默 fallback、catch-all、弱测试、假实现和调试日志误删。
- code-style.md:实际修改代码、设计公共接口、做代码审查或接收 AI 生成补丁时,补充编码规范、命名和注释要求。
- architecture-patterns.md:需求存在多种算法、外部实现或可扩展变体时,选择 Strategy、Adapter、Registry、State Machine 和 Factory,并识别过度设计。
- deep-module-design.md:模块、接口、深度、seam、adapter、leverage、locality、删除测试、依赖类别和替代接口设计。
- domain-modeling.md:主动维护领域术语、具体场景、代码对照、CONTEXT.md 和 ADR。
- module-boundary-design.md:非微小需求开始前,输出模块职责、依赖方向、公共契约和扩展路径。
- plan-spec-and-grill.md:复杂需求在只读 / 方案模式下需要整理 spec、逐轮确认设计决策或拆分纵向 tickets 时读取;不作为普通编码任务的前置流程。
- implementation-loop.md:从 spec / tickets 到实现的纵向循环、持续验证、最终 review 和提交边界。
- architecture-improvement-review.md:非微小代码改动完成后,检查当前实现是否存在值得改进的架构摩擦;只报告候选,不静默修改。
- handoff-and-delivery.md:任务中断、跨 Agent 交接或需要把当前状态交给下一位执行者时读取。
- runtime-artifacts.md:所有运行期 spec、plan、ticket、grill、架构、handoff、诊断和报告的隐藏目录及分组规则。
- reliability-checklist.md:涉及外部依赖、并发、事务、重试、回滚或数据兼容时,逐项检查稳定性风险。
- readability-review.md:审查流水账、命名、控制流、隐式状态和新人可理解性。
- git-worktree-guardrails.md:涉及提交、push、分支、worktree、远端同步或用户询问“会提交到哪里”时读取,避免错误目录、错误分支和误推送。
- frontend-ui-work.md:涉及 UI、前端实现、原型、视觉还原、Figma / 截图 / URL 到代码、设计系统或用户界面改动时读取;普通非 UI 编码任务不要加载。
文档同步门禁(代码变更后的强制步骤)
代码不是本次交付的终点。每次完成源码、配置、SQL、接口、状态、页面或测试行为变更后,必须进行一次文档影响判断:
- 列出本次涉及的项目、模块、跨项目边界和外部调用方。
- 查找项目根
AGENTS.md/CLAUDE.md、README.md、docs/README.md、功能说明、接口契约、架构文档和 runbook;不要只凭文件名猜应该改哪份文档。 - 建立“变更 → 文档”映射,并更新真正受影响的文档:
- API、路由、请求/响应、错误码变化 → integration/API 文档、跨项目 contracts、路由清单;
- 数据库表、字段、索引、状态或迁移变化 → architecture/data model、SQL 说明、状态字典、runbook;
- 业务规则、资格、频控、计费、权益、用户可见行为变化 → 功能说明、PRD/规格、验收口径、App/Web 联调文档;
- 配置、环境变量、启动或排查方式变化 → 项目根约定、配置说明、runbook、部署文档;
- 模块入口、源码位置或职责变化 → 功能资产目录、module map、架构文档;
- 跨项目接口或状态变化 → 上游和下游项目的契约、接入指南和验收文档必须同时对齐。
- 只要需要修改、创建、归类、删除或审查项目文档,必须使用
neat-freak(/Users/javaclimber/.agents/skills/neat-freak/SKILL.md)执行文档同步流程。先完整读取该 skill,再按其“盘点现状 → 影响矩阵 → 实际修改 → 自检 → 变更摘要”执行;不能只在最终回复里描述“应该更新文档”。 - 文档同步应遵循:修改旧事实优先于追加重复说明;使用绝对日期;示例、路径、命令、字段和错误码必须能在当前代码中找到;区分 PRD、架构、接口、运维和交接文档的受众;不得把密钥、token、私有配置或无授权的绝对路径写入项目文档。
- 如果确认没有任何文档受到影响,仍需在最终交付中说明检查过的文档范围和“不需要更新”的理由。不能因为改动看起来很小就默认跳过判断。
文档同步不是无边界重写:只更新能解释本次变化、帮助接入/排查/交接的最小集合;不要为了满足数量要求复制全文或修改无关历史文档。
工程门禁
对任何非平凡代码改动,至少快速过一遍 8 个门禁:
- 真实需求与用户:这是真问题,还是用户给出的一个方案?
- 复杂度与代码经济性:能不能不写、少写、删旧逻辑或复用已有路径?
- 技术债与长期责任:新增债务是否可见、可追踪、可偿还?
- 故障与诊断纪律:是否有复现、根因、日志、降级、恢复或回归测试?
- 设计、重构与 ROI:重构是否明显值得,迁移成本是否可控?
- 数据、接口与领域语言:数据模型和公共接口是否清楚、稳定、难误用?
- 质量自动化与知识共享:测试、CI、文档、注释和 review 是否足够支撑维护?
- 专业信用与成长节奏:是否及时同步风险、承认不确定性、避免无边界加班式硬扛?
完整清单和 38 条来源映射见 maturity-checklist.md。当任务涉及架构、重构、故障、AI 生成代码、大范围变更或上线风险时,必须读取该 reference。
架构、模块拆分与设计模式门禁
普通需求不得默认映射为“一个需求 = 一个文件”。微小修改可以只改一个文件;除此之外,先按职责、变化原因和依赖方向拆出最小模块集合,再开始实现。多个需求也不得为了省事堆进同一个业务文件。
- 非微小需求开始实现前,先给出最小模块图或职责表,至少说明入口、业务编排、领域规则、外部适配、持久化、转换和测试边界;不要求每个需求机械地产生所有层,但必须说明哪些边界确实不需要。
- 一个模块只服务一个主要变化原因;接入、编排、规则、持久化、第三方调用和展示转换不得混成流水账文件。模块拆分的依据是变化原因、依赖方向和可验证行为,不是代码行数;不要为了通过行数门禁制造只有一层转发的服务。
- 主流程只负责按业务顺序编排;校验、策略选择、数据转换、外部调用和副作用下沉到有领域含义的模块或函数。禁止把几十个步骤顺序堆在一个方法中。
- 对存在多种算法、规则或可替换行为的场景,必须优先采用合适的 Strategy、Policy 或 State Machine;对第三方、协议、存储和 SDK 差异,必须收口到 Adapter / Integration;对需要按类型发现和扩展的实现,必须评估 Registry;对对象创建差异再使用 Factory。设计模式必须减少条件分支、隔离变化或降低依赖,禁止为“看起来高级”而套模式。
- 针对已有或合理预期的第二种实现或变化场景,检查新增变体是否只需注册或新增模块,而不是修改大量既有分支;没有真实变化点时不要预先抽象。
- 业务 Bean 的依赖图必须无直接和间接环。新增或修改注入关系前,先检查从该 Bean 可达的依赖路径;发现环时重画职责边界、下沉共享读取/写入能力或调整编排入口。
@Lazy、ObjectProvider、Service Locator 和延迟查找不能用于掩盖业务 Bean 循环依赖;改动命中既有@Lazy环时,应在本次边界调整中删除它。 - 一个需求可以跨越多个模块;拆分依据是职责和变化边界,不是机械地按行数切片,也不是把代码拆成没有领域含义的转发层。
Service 拆分准入
- 新建
Service/Provider/Application前,必须先说明它拥有的业务事实或一致性边界;并至少具备独立调用方、独立变化原因或独立测试面之一。答不清时保留在原模块,以有语义的私有方法组织代码。 - 拆分前必须回答四个问题:它负责什么业务事实;谁调用它;事务、外部调用和状态更新的边界是什么;删除它后系统失去什么独立能力。答案只是“减少行数”“复用几个方法”或“让原类更短”时,不得新建 Service。
- 禁止创建只有一层转发、只能被原 Service 单点调用且调用方仍需了解完整流程的 Service;禁止以
Manager、Helper、Utils等无领域含义名称包装原有调用。 - 查询快照、外部适配、交易或状态写入、入口展示编排应保持单向依赖。两个 Service 需要互相注入、互相回调或共享隐含调用顺序时,先合并错误边界或下沉共享能力,不能继续加中间 Service。
- 一条端到端业务命令只能有一个流程编排者。只有该编排者可以协调多个领域能力、事务和外部边界;下游 Service 不得反向调用入口或对等 Service。需要共享的能力应下沉为有明确所有权的查询、领域规则、端口或 Repository,而不是新增协调型 Service。
- 新增或修改 Bean 注入前,必须在模块职责表、设计说明或代码审查记录中写清调用者、被调用者、依赖类型和事务/状态所有权。默认依赖方向是“入口 -> 应用编排 -> 领域规则或查询端口 -> Repository / Adapter”;跳过层级或反向依赖必须有可验证的边界理由。
Adapter/Integration只负责第三方协议、SDK、HTTP、存储调用和外部事实的归一化,不得依赖套餐目录、权益、对账或其他业务编排 Service。外部结果如何映射为套餐、资格、状态或权益,必须由流程编排者或领域规则处理。
模式路由
设计模式只解决已经存在的变化源,不能作为拆分文件或展示“架构性”的理由:
| 真实变化源 | 优先结构 | 不适用情形 |
|---|---|---|
| 同一领域规则按套餐、地区、状态或资格选择 | Policy / Strategy |
只有一个稳定规则或仅为拆代码 |
| 第三方 SDK、HTTP 协议、存储实现差异 | Adapter / Integration |
内部 Service 的普通调用 |
| 有明确状态、合法迁移和终态约束 | State Machine | 只有少量局部条件且没有状态图 |
| 按类型发现多个可插拔实现 | Registry |
固定分支且没有扩展来源 |
| 对象创建随类型或配置变化 | Factory |
单纯构造 DTO 或单一实现 |
- 引入模式前写出被隔离的变化源、替代实现或状态迁移;无法指出时保持直接代码。
- 模式后的调用方不应知道具体实现或第三方细节;新增变体应只新增实现或注册,不应修改无关业务分支。
稳定性、可读性与可扩展性门禁
- 公共入口和模块接口必须明确输入、输出、异常、状态变化和副作用;固定协议使用类型或显式模型表达。
- 涉及外部依赖时,明确超时、重试、幂等、并发、事务、部分失败、回滚和兼容策略;不能只处理理想成功路径。
- 主流程按业务顺序从上到下可读;优先使用有领域含义的命名、早返回和小函数,避免
data、result、process、handle等无法表达意图的名称。 - 禁止用大量布尔参数、隐式全局状态、跨层共享可变对象或散落的字符串状态改变函数行为。
- 核心规则、策略和状态流转可独立测试;外部适配使用契约或集成测试;公共接口至少有一条端到端或行为验证路径。
- 扩展点必须有真实变化来源和清晰契约;新增实现不应迫使调用方了解第三方细节,也不应修改无关模块。
- Spring、CDI 等依赖注入改动必须补充最小真实上下文启动测试或等价容器测试,覆盖模块实际配置和被修改的端到端依赖链;外部 I/O 可以替换,但不得通过 mock、排除或手工替换业务 Bean 消除待验证的依赖边。单元测试中把直接协作者全部 mock 掉,不能证明 Bean 图无环。
复杂度与模块边界门禁
这组门禁优先约束新增代码和本次修改涉及的代码,不要求一次性重写历史存量。最终判断以职责数量、分支复杂度、依赖方向和副作用密度为准,业务代码行数不构成预警或拆分信号。
- 一个文件、类或模块只承担一个主要职责;接入、业务编排、持久化、第三方调用和展示转换应分属不同边界。
- 业务源码、类和方法的行数不能触发架构审查,也不能单独构成拆分、拒绝合并或要求例外说明的理由。只有已经因职责混杂、依赖方向、控制流复杂度或副作用密度进入审查时,才可将行数作为定位阅读范围的辅助信息;它不产生拆分结论。
- 圈复杂度超过 10、嵌套超过 3 层,或同一方法同时包含多次外部调用和状态更新时,优先审查是否应拆出策略、校验、转换或 Adapter;复杂度指标同样不是机械拆分命令。
- 不得为了降低行数制造没有领域含义的
Manager、Helper、Utils或纯转发层;新抽象必须减少职责、依赖或重复逻辑中的至少一项。 - Controller、Route、页面入口只负责接入和结果组合;Service/Provider/Application 负责业务规则和状态流转;DAO/Repository 只负责数据访问;第三方 SDK、HTTP、消息和文件系统调用收口在 Adapter/Integration 边界。
- 固定业务结构使用 DTO、VO、Pydantic model、TypedDict 或 TypeScript type;禁止用字符串 key 的裸 Map、
any或动态对象传播固定协议。 - 状态流转集中在显式 transition、policy 或 state machine 入口中;禁止在多个服务里散落状态字符串和重复终态判断。
- 禁止空
catch、catch-all 后静默继续、记录错误后伪装成功,以及没有语义说明的默认值或 fallback。降级必须说明触发条件、用户可见结果和恢复方式。 - 注释解释业务原因、兼容约束、性能取舍和失败处理,不重复代码表面行为;
TODO/FIXME必须带原因、责任人或可追踪任务。 - 生成代码、第三方代码、测试夹具、SQL seed、模板和构建产物不纳入业务源码行数指标,但必须通过各自的生成、格式或构建校验。
- 历史超大文件不要求立即拆完;后续修改不得继续向其中追加无关职责。因性能、协议兼容、代码生成或框架约束需要例外时,必须记录影响范围、验证方式和取消条件。
相关 Skill 与安装
本节只描述可选外部增强,不是本 skill 的执行依赖。
本 skill 已内置下列能力,默认直接读取本地 reference 执行,不因外部 skill 缺失而停止:
karpathy-guidelines:所有编码任务的底线纪律;先想清楚、简单优先、外科手术式修改、目标驱动验证。mattpocock-skills:tdd或tdd:新功能和行为变化。mattpocock-skills:diagnose或diagnose:bug、失败和性能回归。mattpocock-skills:request-refactor-plan或request-refactor-plan:用户要求规划重构或变更范围大到需要拆小提交。mattpocock-skills:review或本地 review 能力:审查分支、PR、工作区 diff 或 AI 生成代码。neat-freak:代码变更影响项目文档、接口契约、架构说明、运行手册、交接文档或文档目录时强制联动;负责文档盘点、同步、自检和摘要。
使用规则:
- 外部 skill 只有在用户显式点名、需要其专属工具集,或用户要求保持与上游流程一致时才叠加。
- 外部 skill 与本地规则冲突时,优先遵守用户要求、项目规则和本 skill 的安全边界。
- 只读 / 方案模式禁止为了补齐外部 skill 而安装插件、依赖或写入 issue。
- 相关外部 skill 不可用时,直接使用本 skill 的完整内置流程,不得只报告“缺少 skill”。
- 文档变更仍必须联动
neat-freak;其知识索引能力见该 skill 内置的knowledge-indexing.md。
需要安装来源、命令或回退策略细节时,读取 related-skills.md。
内置纪律
以下纪律无论外部 skill 是否安装都必须执行:
- Karpathy 底线:先说清假设和困惑;用最少代码解决问题;只改必须改的地方;先定义成功标准再验证。
- TDD 底线:行为变化优先通过公共接口验证;一次只做一个纵向切片;不要先批量写完所有测试再批量实现。
- Diagnose 底线:先建立可重复反馈循环;确认复现的是用户描述的问题;提出可证伪假设;只加能区分假设的观测;修复后补回归验证并清理调试代码。
- Refactor 底线:先确认 ROI、范围和不改什么;拆成每步可工作的微小变更;迁移完成后删除本次制造的旧路径和兼容债。
- Review 底线:按规范和需求两轴看 diff;先报风险和文件位置,再做摘要;区分确定 bug、风险、风格建议和测试缺口。
- Deep module 底线:优先小接口承载更多行为;用删除测试判断抽象是否真正减少复杂度;接口是调用方和测试的共同测试面。
- Domain modeling 底线:术语冲突要澄清,模糊词要具体化,代码与领域模型冲突要报告;稳定且难逆的取舍才记录 ADR。
- Spec / Grill / Tickets 底线:事实由 Agent 查询,决策由用户确认;tickets 以可验证行为纵向切片;大范围机械迁移使用 expand-contract。
- Architecture review 底线:编码完成后可以主动发现架构摩擦,但只能提出候选,不能在当前任务中偷偷重构。
- Handoff 底线:交接只记录继续工作所需的事实、证据、决策、下一步和风险,不重复已有文档,不泄露敏感信息。
交付护栏
从 Loom 风格交付 harness 吸收三条轻量规则,但不引入状态机或 .loom/ 目录:
- 权威来源:任务中如果有测试输出、CLI 返回、issue、PRD、错误日志、review 结果或用户明确指令,把它们当成当前权威来源;不要用聊天里的主观总结覆盖这些证据。
- 结果证据:非平凡任务结束前,必须能说明改了什么、验证了什么、证据在哪里、还剩什么风险。没有证据时不要宣称完成。
- 继续义务:如果当前模式已经创建了明确的下一步,例如失败测试、复现脚本、修复请求、审查问题或用户批准的计划,不要停在进度总结;继续执行到完成条件、用户决策点或真实阻塞。
- 只读优先:只读 / 方案模式优先于继续义务。即使发现明确下一步,也只能报告建议,不能自动执行。
轻量任务结果可以用最终回复承载,不要求写文件。内容至少包含:
- 结果:已完成、未完成、阻塞或只读结论。
- 改动:关键文件或无代码改动。
- 验证:运行过的测试、命令、复现路径或替代验证。
- 残余风险:未覆盖风险、没跑的检查或需要用户决策的点。
执行规则
- 优先用项目既有模式、工具和测试,不引入无关抽象。
- 对业务源码做复杂度检查时,优先运行
scripts/check_code_complexity.py;按项目语言和生成物边界传入--exclude,只将控制流、嵌套和副作用密度等结构性结果用于设计判断,不因纯行数指标触发拆分。 - 每一行改动都必须能追溯到用户请求或验证需要。
- 不顺手重构相邻代码,不删除用户或历史留下的无关改动。
- 行为变化优先补测试;没有正确测试缝时,要说明原因并给替代验证。
- 调试日志必须带唯一前缀,收尾时清掉。
- 使用 AI 生成代码时,把它当未审查补丁:检查复杂度、接口、测试、文档和可观测性后再合入。
- 非微小代码改动完成主行为验证后,按需读取 architecture-improvement-review.md,报告当前代码中值得改进的架构候选;候选必须由用户决定是否另行修改。
- 代码变更完成后,必须先完成文档影响判断;存在影响时,完成
neat-freak同步和自检后才能宣称任务完成。
完成标准
结束前确认:
- 用户要求的行为已实现或明确说明未完成原因。
- 运行了最快且相关的验证;如果没跑,说明原因。
- 没有留下临时调试代码、无用导入、死测试或示例文件。
- 已检查文档影响;受影响文档已同步,或明确记录了不需要更新的范围和理由。
- 跨项目变更已核对上下游契约、接入文档、架构说明和运维/验收文档。
- 最终回复包含改动摘要、关键文件和验证结果。
不能结束的情况:
- 还没有执行已经明确可运行的验证。
- 故障模式还没有复现或说明无法建立反馈循环。
- 行为变化还没有测试或替代验证。
- 审查已发现 P0/P1 问题但用户要求你继续修复,且修复仍在当前范围内。
- 当前工具或命令返回了明确的下一步,且该下一步不需要用户决策。