上一篇我把前端代码风格拆成了格式、结构、状态、契约和行为 5 个层次。

问题随之而来:

已经识别出的项目风格,哪些应该写成规则,让 Codex 每次都遵守?

最直接的做法,是把团队现有代码规范、开发手册、目录说明和历史经验全部整理进一个文件。

我不建议这样做。

规则越长,不代表约束越强。真正影响当前任务的内容可能被大量背景说明淹没;一些已经由格式化和 Lint 工具控制的要求被重复描述;只适合某个模块的写法被错误提升成全局规范;尚未形成共识的经验也可能被写成硬规则。

最后,Codex 读到了很多文字,却仍然不知道:

  • 当前任务允许改到哪里;

  • 应该参考哪一套实现;

  • 哪些公共契约不能动;

  • 异常和生命周期怎样处理;

  • 修改后必须拿出什么证据。

所以我现在筛选项目规则时,不问“这条规范重要不重要”,而问四个更具体的问题:

  1. 它是否会在多个任务中重复出现?

  2. 它是否已经稳定,不需要每次重新讨论?

  3. 它能否被写成明确动作或边界?

  4. 它是否有代码、配置或检查可以验证?

四个条件大致成立,才值得成为持久项目规则。

先分清:项目规则不等于团队所有知识

团队知识里至少有四种内容,它们不应该全部进入同一个规则文件。

稳定项目约束

例如必须使用现有请求封装、公共组件修改需要先查全部引用、当前目录使用指定检查脚本。这类内容适合成为项目规则。

当前任务约束

例如“本次不改接口协议”“只处理编辑弹窗,不重构列表”。它只对当前任务有效,应该写在任务卡或当前提示中。

背景说明和设计原因

例如某段架构为什么演进成现在这样。这些信息有助于理解,但不一定适合压缩成每次执行都加载的硬指令。可以放在专门文档中,由规则指向它。

尚未确定的选择

例如团队还在讨论使用局部状态还是全局状态。它应该被标成待决定问题,不能提前写成 Codex 必须遵守的标准。

如果这四类内容混在一起,规则文件很快会同时扮演规范、需求、架构文档和会议记录,最终谁也看不清哪些内容必须执行。

第一类规则:修改范围与禁止项

我最先写的不是代码写法,而是修改边界。

前端项目很容易因为一个局部需求牵出公共组件、全局样式、请求封装和状态模块。Codex 如果只知道“完成目标”,通常会选择一条自洽的实现路径;但这条路径不一定符合团队愿意接受的修改范围。

有效的范围规则应该说明:

  • 哪些位置默认允许修改;

  • 哪些公共位置修改前必须先说明影响;

  • 哪些目录属于生成代码或第三方代码,禁止直接编辑;

  • 哪些无关重构、格式化和依赖变化默认不允许;

  • 发现计划外文件时应该怎样暂停。

例如:

## 修改范围
- 业务页面任务默认只修改当前功能链上的文件。
- 修改公共组件、公共请求层、全局状态或路由守卫前,先列出调用方和兼容影响,不得直接扩大范围。
- 不编辑生成目录、构建产物和第三方代码。
- 不在功能修改中夹带无关重命名、全文件格式化、依赖升级或结构重构。
- 实际范围超过计划时,先更新计划和验收方式再继续。

这类规则能直接减少差异噪声。

它不会限制 Codex 发现问题。AI 仍然可以指出公共模块存在隐患,但“发现问题”和“顺手修复”应该是两件事。

第二类规则:参考实现与选择顺序

只写“遵守现有代码风格”太模糊,我会明确参考顺序。

有效的参考规则应该回答:

  • 当前模块优先参考哪些位置;

  • 哪些目录属于旧版或只能作为反例;

  • 多种写法冲突时按什么顺序判断;

  • 参考代码中的哪些部分可以迁移;

  • 没有可信参考时应该怎样处理。

例如:

## 参考实现
- 新增列表行为时,优先参考当前模块中仍在维护的同类页面,不以旧版目录或演示页面作为默认标准。
- 参考优先级:当前任务明确要求 > 当前目录规则 > 直接调用契约 > 当前模块稳定实现 > 其他模块实现 > 框架通用写法。
- 使用参考前说明相同点、差异和不能照搬的部分。
- 找到多种冲突模式时列出证据并暂停,不按文件数量自行选择。

这类规则把“模仿”改成了有来源的选择过程。

需要注意,规则不应固定某个临时文件路径。如果参考页面经常变化,更合适的写法是描述参考条件,并在当前任务中给出具体文件。

第三类规则:公共契约与职责边界

这类规则用于防止 Codex 为了方便局部实现,改变项目已经稳定的接口。

可以覆盖:

  • 页面、组件、状态和请求层的职责;

  • Props、Emits、插槽和暴露方法的基本约定;

  • 接口数据在哪里转换;

  • 类型定义的来源;

  • 公共组件和公共方法的兼容要求;

  • 新增抽象的条件。

例如:

## 契约与职责
- 页面负责连接用户入口和业务流程;请求参数转换保持在项目现有转换位置,不在展示组件中拼装接口协议。
- 子组件不得为了同步方便复制长期状态;状态唯一来源以当前模块现有实现为准。
- 修改公共 Props、Emits、类型或请求契约前,先查全部直接调用方并说明兼容策略。
- 单一调用点的局部逻辑默认不新增公共封装;确需抽取时说明复用对象和验证范围。

这里最好避免绝对化术语。

比如“所有状态都必须放 Pinia”通常不是好规则,因为表单临时状态、跨页面状态和服务器缓存并不属于同一种问题。更可执行的规则是说明什么状态属于公共层,什么状态应留在组件或页面,以及出现例外时需要什么理由。

第四类规则:异常、反馈与生命周期

很多项目规则只约束正常路径,导致 AI 生成代码的异常行为每次都不一样。

我会把高频行为写清:

  • Loading 的作用范围;

  • 重复提交怎样阻止;

  • 请求失败后保留还是恢复哪些状态;

  • 错误提示使用哪个项目能力;

  • 弹窗关闭、页面离开和重新进入时怎样清理;

  • 异步竞态怎样避免旧结果覆盖新状态;

  • 成功后由谁刷新数据。

例如:

## 异常与生命周期
- 提交动作使用项目现有按钮状态或请求状态能力,未结束前不得产生不受控的重复请求。
- 请求失败时按当前业务要求保留用户输入;是否关闭弹窗不能由实现自行决定。
- 打开、关闭和切换对象时,显式检查表单数据、校验信息、Loading 和未完成请求的处理。
- 成功后的刷新、页码和筛选状态由页面现有数据流决定,不在子组件中直接重建列表状态。

这类规则必须允许业务差异。

“失败时永远保留数据”或者“弹窗关闭时永远清空”都可能过度统一。项目规则应该写稳定原则,具体结果仍由任务验收标准决定。

第五类规则:验证和交付证据

没有验证规则,前四类规则很难知道是否真的执行。

我会明确:

  • 修改前需要确认什么基线;

  • 每类文件修改后运行哪个已有检查;

  • 哪些页面路径必须人工验证;

  • 完整差异要检查哪些越界信号;

  • 无法运行的检查怎样报告;

  • 交付说明至少包含什么。

例如:

## 验证与交付
- 优先运行仓库已有的类型、测试、Lint 和构建脚本,不自行假定检查范围。
- 页面行为变化必须列出正常、失败及与本次需求相关的连续操作路径。
- 交付前审查完整差异,确认没有计划外文件、无关格式化、临时日志和依赖变化。
- 结论分为已通过、未通过和未验证;环境无法执行的检查不得写成通过。
- 交付说明包含实际修改范围、检查结果、页面验证、已知限制和剩余风险。

验证规则的价值,是把“遵守项目规范”变成可以观察的结果。

我用四个字段写一条可执行规则

一条项目规则如果只有口号,很难约束实现。

我会尽量包含四个字段:

触发场景 + 要求动作 + 判断证据 + 例外处理

例如,把下面这句:

公共组件要谨慎修改。

改成:

当任务需要修改公共组件的 Props、Emits 或默认行为时:
1. 先查全部直接调用方;
2. 列出可能发生变化的现有行为;
3. 给出兼容方案和对应检查;
4. 未确认兼容策略前暂停修改。
仅内部实现且公开行为不变的局部修复,可以按普通组件任务处理,但仍需回归主要调用路径。

前一句表达态度,后一句才能指导动作。

再比如“遵守代码风格”可以改成:

新增页面逻辑前,先选择当前模块一个职责相同的稳定实现作为参考,说明结构、状态、契约和异常处理的相同点与差异;没有可信参考或参考冲突时,将其列为待确认项,不自行引入新模式。

规则越能指出何时触发、做什么、怎样证明以及何时暂停,越容易在任务中真正生效。

规则应该放在哪里,取决于它约束多大范围

OpenAI 的 Codex 文档说明,AGENTS.md 可以用于提供持久的项目指令;Codex 会从项目根目录沿当前工作目录读取指令,离当前目录更近的文件可以提供更具体的约束。因此我会按适用范围分层,而不是把所有内容放在仓库根目录。

仓库级规则

适合放:

  • 包管理和基础命令;

  • 全仓库禁止项;

  • 通用验证要求;

  • 公共模块修改流程;

  • 交付和审查要求。

应用或模块级规则

适合放:

  • 当前应用的目录职责;

  • 页面、状态和请求封装;

  • 该模块的参考实现;

  • 特定测试或构建方式;

  • 与其他应用不同的约束。

当前任务提示

适合放:

  • 本次目标;

  • 本次允许和禁止范围;

  • 当前需求中的例外;

  • 具体参考文件;

  • 本次验收路径。

规则离代码越近,不代表优先级可以无限覆盖业务要求。当前任务如果需要偏离稳定规则,应该显式说明原因和验收方式,而不是让两套指令暗中冲突。

官方文档还建议把规则写得简洁,说明需要识别的行为以及安全路径或例外,并把格式和 Lint 等机械检查交给持续集成或对应工具。这与我的使用感受一致:持久规则应该保留工程判断,机器已经能稳定判断的格式问题不必反复占用上下文。

哪些内容我不会写进持久规则

单次需求细节

某个字段是否必填、某次弹窗保存后是否关闭,只属于具体任务,除非它已经成为跨模块稳定约定。

没有共识的偏好

“我更喜欢这种写法”不能自动成为项目标准。先通过真实任务验证,再决定是否沉淀。

已由工具完整执行的格式要求

可以记录检查命令和范围,但没必要把格式配置翻译成几十条自然语言。

不能验证的效果承诺

例如“这样写性能更好”“这种结构更容易维护”。没有基线和适用条件时,它们只是判断,不是规则。

过度具体、很快失效的实现细节

把当前文件名、变量名和暂时目录结构写死,项目一调整,规则就会误导后续任务。

规则减少无关修改,需要同时设置“允许”和“停止”

很多规则只告诉 Codex 应该怎么写,没有说明什么时候不应该继续。

我会给关键规则配暂停条件:

触发情况 Codex 应做什么
需要修改计划外公共模块 列影响和调用方,暂停等待范围更新
同类实现存在冲突 说明差异和证据,不自行投票
规则与当前代码不一致 判断是旧代码、规则过期还是特例
检查无法运行 说明原因与替代验证,标记未验证
需求要求偏离项目惯例 明确偏离原因、范围和回归路径
发现可顺手修复的问题 记录建议,不混入当前差异

“允许做什么”控制实现方向,“什么时候停”控制风险扩散。

一份可以直接裁剪的前端项目规则模板

# 前端项目协作规则
​
## 1. 当前范围
- 本目录负责:
- 默认允许修改:
- 修改前需要确认:
- 禁止直接编辑:
- 不夹带的无关工作:
​
## 2. 参考顺序
- 当前模块参考条件:
- 旧版、示例和特殊实现:
- 多种写法冲突时:
- 没有可信参考时:
​
## 3. 职责与契约
- 页面、组件、状态和请求怎样分工:
- 公共 Props、Emits、类型和请求契约的修改要求:
- 状态唯一来源与数据转换位置:
- 新增公共抽象的条件:
​
## 4. 异常与生命周期
- Loading 与重复操作:
- 请求失败后的状态:
- 打开、关闭、离开和重入:
- 异步竞态:
- 成功后的刷新责任:
​
## 5. 验证与交付
- 仓库已有检查:
- 页面验证路径:
- 完整差异检查:
- 无法验证时的报告方式:
- 交付说明必须包含:
​
## 6. 暂停条件
- 计划外公共修改:
- 规则或参考冲突:
- 契约不明确:
- 验证能力缺失:

这份模板不是要求每个项目填满所有栏目。真正使用时,应该删除与当前目录无关的内容,只保留高频、稳定、可执行和可验证的规则。

写完规则后,我会做一次反向检查

它解决过真实重复问题吗

如果从未在项目中发生,也没有明确风险依据,先不要为了“完整”添加。

它能指导动作吗

“保持优雅”“注意性能”“合理拆分”都难以执行,需要补充触发场景和判断证据。

它是否放在正确范围

只适合一个业务模块的规则,不应影响整个仓库。

它是否与自动工具重复

机械格式交给工具,规则保留范围、契约、行为和验证要求。

它是否允许例外和暂停

没有例外的绝对规则很容易迫使 Codex 在特殊场景中做出错误统一。

写在最后

我用项目规则约束 Codex,不追求把团队所有知识都写进去。

我优先保留 5 类内容:

  1. 修改范围和禁止项;

  2. 参考实现与选择顺序;

  3. 公共契约和职责边界;

  4. 异常、反馈与生命周期;

  5. 验证方式和交付证据。

每条规则尽量包含触发场景、要求动作、判断证据和例外处理,再按仓库、应用或模块的作用范围放置。

这样做的目标不是让 Codex 机械复制现有代码,而是减少与当前需求无关的自由度:不随意选择参考、不顺手创造新模式、不扩大修改范围,也不在没有证据时宣布完成。

下一篇会进入第 2 周 Day 3:修改一个前端组件之前,为什么必须先查调用链。我会具体拆解入口、Props、Emits、插槽、暴露方法、状态和样式依赖,说明怎样判断一个看似局部的改动会影响到哪里。

本系列持续更新。后续会用调用链和影响范围继续检验这些项目规则,看看它们能否真正控制多文件修改,而不是只停留在文档中。

 每日好工具推荐:

在这里推荐一款超好用的图片压缩工具——“图压”在线图片压缩|免费压缩 JPG、PNG、WebP - 图压工具。同事安利给我的,用过后真的觉得太香了!支持批量压缩、调整压缩百分比,最关键的是它是离线程序,下载到本地就能反复用。我平时做自媒体和写前端时经常用到,再也不用去网上找在线压缩工具了。它也带在线压缩功能,很方便。

更多推荐