ECC 编码风格规则(Cursor 版):不可变性与代码质量检查清单如何在 Agent 驱动开发中落地
本文以 .cursor/rules/common-coding-style.md 为核心,逐条拆解 ECC 为 Cursor 场景定制的通用编码风格规则——不可变性(CRITICAL 级别)、文件组织、错误处理、输入验证与提交前代码质量检查清单,并结合仓库中同源的 rules/common/coding-style.md 和 TypeScript 专属规则 .cursor/rules/typescript-coding-style.md,说明这套规则如何被 alwaysApply 机制自动注入会话,以及它如何约束 AI Agent 在生成、修改代码时的行为边界。
一、规则文件的定位:一份始终生效的 Agent 行为约束
common-coding-style.md 是 ECC 仓库 .cursor/rules/ 目录下的通用编码风格规则,服务的是「Agent 在 Cursor 中写代码时必须遵守的风格底线」。它的 YAML frontmatter 只有两个字段,但语义非常关键(见 .cursor/rules/common-coding-style.md):
---
description: "ECC coding style: immutability, file organization, error handling, validation"
alwaysApply: true
---
description用一句话概括了规则覆盖的四个主题域:不可变性、文件组织、错误处理、验证;alwaysApply: true意味着该规则不依赖文件通配符匹配,会在 Cursor 会话中始终作为上下文注入,而不是像带globs的规则那样只在编辑特定文件时才生效。
这与同目录下的语言专属规则形成分层结构。以 .cursor/rules/typescript-coding-style.md 为例,其 frontmatter 是 globs: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"] + alwaysApply: false,且文件开头明确声明 “This file extends the common coding style rule with TypeScript/JavaScript specific content”——即 common 规则是基座,语言规则按文件类型叠加。整个 .cursor/rules/ 目录按此模式组织:common-* 系列(coding-style、patterns、hooks、security、testing、performance、agents、development-workflow、git-workflow)加上 golang、kotlin、php、python、swift、typescript 六种语言各自的 coding-style / hooks / patterns / security / testing 五件套。
需要说明的适用前提:Cursor 平台的规则加载行为可能随 Cursor 版本变化。README 中对该适配器的描述是「Project-local .cursor/ adapter」,可通过 ./install.sh --profile minimal --target cursor 将 ECC 规则选择性安装到目标项目的 .cursor/ 下(见 README.md 的 Platform Support 与安装章节)。因此本文的规则解读以当前仓库中 .cursor/rules/ 的静态内容为准。
二、规则一:不可变性(CRITICAL)——创建新对象,绝不原地修改
这是全文档中标注级别最高的一条(标题直接带 “(CRITICAL)”),原文的表述是(.cursor/rules/common-coding-style.md):
// Pseudocode
WRONG: modify(original, field, value) → changes original in-place
CORRECT: update(original, field, value) → returns new copy with change
规则给出的三条理由:不可变数据消除隐藏副作用、让调试更容易、并支撑安全的并发。用伪代码而不是具体语言书写,正是为了让这条规则跨越所有语言生效。
具体到 TypeScript/JavaScript 场景,ECC 在同目录的 .cursor/rules/typescript-coding-style.md 中把这条抽象规则落成了可执行的写法——用展开运算符(spread operator)做不可变更新:
// WRONG: Mutation
function updateUser(user, name) {
user.name = name // MUTATION!
return user
}
// CORRECT: Immutability
function updateUser(user, name) {
return {
...user,
name
}
}
从源码结构看,ECC 自身对「不可变」的执行也贯彻到了配置数据层面:仓库中状态存储相关模块(如 scripts/lib/install-state.js、scripts/lib/state-store/ 系列)普遍采用「读出—构造新对象—整体写回」而非原地改字段的模式,这与规则本身的要求形成呼应。对 Agent 工作流而言,这条规则的价值在于:当 LLM 生成的代码反复读写同一可变对象时,人很难在 Review 中定位「谁在什么时候改的」;而不可变写法下,每个引用都是一份可追溯的快照,错误处理与并发场景(见下文)都因此变得更可控。
三、规则二:文件组织——多小文件优于少大文件
原文给出四条硬性约束(.cursor/rules/common-coding-style.md):
- MANY SMALL FILES > FEW LARGE FILES:总原则是「多而小」胜过「少而大」;
- High cohesion, low coupling:高内聚、低耦合;
- 200-400 lines typical, 800 max:典型文件 200~400 行,上限 800 行;
- Extract utilities from large modules:从大模块中抽离工具函数;
- Organize by feature/domain, not by type:按功能/领域组织目录,而不是按「所有组件放一起、所有工具放一起」的类型化组织。
仓库中平台无关的孪生文件 rules/common/coding-style.md 对 800 行上限补充了更精细的边界说明:800 行是「source files 的软性可维护性天花板(soft maintainability ceiling)」,而 测试、生成代码、vendored 文件在规模由其角色正当化时可以超出该上限。这一补充很实用——如果 Agent 机械地对所有文件执行 800 行限制,可能反而把合理的测试夹具或生成产物拆碎。
「按领域组织」这条同样有仓库内可对照的实例:ECC 自身的规则体系就按「语言/领域」而非「类型」切分目录,如 rules/python/、rules/golang/、rules/react/ 等;脚本层则按能力域划分(scripts/lib/ 下的 install、session、memory、state-store 等子域)。这些目录结构本身即可作为「200-400 行典型 + 按功能组织」原则的参考样本。
四、规则三:错误处理——每一层显式处理,绝不静默吞掉
原文的 Error Handling 章节要求(.cursor/rules/common-coding-style.md):
- 在每一层显式处理错误(Handle errors explicitly at every level);
- 面向 UI 的代码提供用户友好的错误消息;
- 服务端记录详细的错误上下文(Log detailed error context on the server side);
- 绝不静默吞掉错误(Never silently swallow errors)。
TypeScript 专属规则把前两条具象为「async/await + try-catch 的标准骨架」(.cursor/rules/typescript-coding-style.md):
try {
const result = await riskyOperation()
return result
} catch (error) {
console.error('Operation failed:', error)
throw new Error('Detailed user-friendly message')
}
这个骨架体现了该规则的一个关键分工:详细上下文走日志通道(console.error 记录原始错误),对上层抛出的则是用户可读、可行动的消息。此外,同文件还要求生产代码中不出现 console.log,应使用正式日志库,并指出「See hooks for automatic detection」——即规则不止是文档约定,ECC 还配了 hook 机制做自动检测(Cursor 侧的 hook 适配见 .cursor/hooks/adapter.js 与 .cursor/hooks.json)。对 Agent 而言,「永不静默吞错误」尤其重要:LLM 生成代码时常见的 catch {} 空块,正是这类规则要在会话过程中提前拦截的模式。
五、规则四:输入验证——在系统边界处验证,快速失败
Input Validation 章节的原文要求(.cursor/rules/common-coding-style.md):
- 处理前验证所有用户输入;
- 可用时优先使用基于 Schema 的验证;
- 快速失败(Fail fast)并给出清晰的错误消息;
- 永不信任外部数据——API 响应、用户输入、文件内容一视同仁。
「外部数据一律不信任」是面向 Agent 时代的安全底线:Agent 生成的代码经常直接消费 API 响应或解析文件,若边界验证缺失,坏数据会沿调用链扩散,且故障点远离污染源、难以归因。仓库中的 TypeScript 规则给出的标准答案是用 Zod 做 schema 验证(.cursor/rules/typescript-coding-style.md):
import { z } from 'zod'
const schema = z.object({
email: z.string().email(),
age: z.number().int().min(0).max(150)
})
const validated = schema.parse(input)
这段示例同时覆盖了「快速失败」的语义:schema.parse 对不合法输入直接抛错,而不是返回「默认值掩盖问题」,与规则中 “Fail fast with clear error messages” 逐字对应。ECC 仓库自身也在用「schema 化 + 边界验证」的实践佐证这一风格:仓库根目录 schemas/ 下维护了 hooks.schema.json、memory.schema.json、install-state.schema.json 等一批 JSON Schema,用于约束安装与运行时数据的结构,这正是“Use schema-based validation where available”在配置层面的体现。
六、代码质量检查清单:七项可机械校验的完成标准
文档最后给出了一份「标记工作完成之前」必须自查的清单(.cursor/rules/common-coding-style.md),完整保留如下:
- [ ] 代码可读且命名良好(Code is readable and well-named)
- [ ] 函数足够小(<50 行)
- [ ] 文件聚焦(<800 行)
- [ ] 无深层嵌套(不超过 4 层)
- [ ] 错误处理到位
- [ ] 无硬编码值(使用常量或配置)
- [ ] 无原地修改(使用了不可变模式)
这份清单的设计意图值得注意:七项中除了第一、五项偏主观判断外,其余五项(函数行数、文件行数、嵌套深度、硬编码值、mutation)都是可被静态分析机械判定的指标。这使它天然适合作为 Agent 自评环节的检查表——LLM 在宣告 “任务完成” 前逐项核销,比开放式自查更不容易漏项。前文提到的 800 行文件上限、50 行函数上限,正是在清单中被二次锚定的硬阈值,形成「正文规则 + 清单」双重约束。
孪生文件 rules/common/coding-style.md 在同样清单之外还补充了三类与清单直接配套的规则,可作为理解清单阈值的背景:
- KISS / DRY / YAGNI 三原则:DRY 强调「重复是真实存在时才抽抽象,不做推测性抽象」,与 YAGNI 互为约束,避免 Agent 过度设计;
- 命名规范:变量与函数
camelCase;布尔值优先is/has/should/can前缀;接口/类型/组件PascalCase;常量UPPER_SNAKE_CASE;自定义 hook 以use前缀; - 代码坏味道:深嵌套(改用 early return)、魔法数字(改用命名常量)、长函数(拆分为职责单一的片段)。
七、这套规则在 Agent 工作流中如何起作用
把以上各节串起来,common-coding-style.md 在 ECC 体系中的实际角色是:
- 会话级常开约束:因
alwaysApply: true,它与语言规则的globs条件加载不同,无论 Agent 正在编辑哪类文件,这四个主题域的要求都在上下文中生效;语言专属规则(如 TypeScript 的 spread 更新、try-catch 骨架、Zod 验证、禁用console.log)再按文件类型叠加细节。 - 从约定到检测:规则不止停留在提示词层面。README 说明 Cursor 侧通过
.cursor/hooks/下的 hook 脚本(如adapter.js、stop.js等)把 Cursor 的 20 个 hook 事件适配为可复用执行,规则中「See hooks for automatic detection」即指这条自动检测链路。 - 与模式库互补:同目录的
.cursor/rules/common-patterns.md规定了 Repository Pattern 与统一 API 响应包络等结构性模式,coding-style 管「代码怎么写」,patterns 管「结构怎么搭」,两者同属alwaysApply层,共同构成 ECC 在 Cursor 下的代码生成基线。
八、适用前提与限制
- 本文所述规则内容均以当前仓库
.cursor/rules/与rules/common/的实际文件为准;.cursor/rules/common-coding-style.md与rules/common/coding-style.md存在内容差异(后者多出 KISS/DRY/YAGNI、命名规范与坏味道章节,且对 800 行上限有测试/生成文件豁免),引用时应以对应文件版本为准。 - 规则的运行时行为(何时注入、hook 何时触发)依赖 Cursor 平台版本与 ECC 安装器(
--target cursor)的安装结果,Cursor 的规则/Agent 加载行为可能随版本变化,这一点 README 的 Cursor 适配章节已明确提示。 - 规则本身是「行为约束 + 检查清单」,不包含可执行代码;文中展示的 TypeScript 示例均来自
.cursor/rules/typescript-coding-style.md,作为规则的参考实现而非独立库。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00