ECC × OpenCode:一份可执行的工程纪律指南 —— 拆解 `.opencode/instructions/INSTRUCTIONS.md` 的安全、TDD 与 Agent 编排实践
技术文章导读:
INSTRUCTIONS.md是 ECC(Agent Harness Performance Optimization System)面向 OpenCode 使用场景整合的核心规则文档。本文以该文档为骨架,逐节解读其在提交前安全审查、不可变编码风格、80%+ 覆盖率 TDD、Git 提交与 PR 工作流、模型选型与上下文管理等方面的具体约定,并结合仓库中 .opencode/opencode.json、.opencode/plugins/ecc-hooks.ts 与 .opencode/commands/ 等实现,说明这些规则在 OpenCode 会话中如何被加载、被命令调用并被自动化插件落地。读完你既能直接复用这套规则约束任意 OpenCode 项目,也能理解 ECC 把 Claude Code 时代积累的工程经验移植到 OpenCode 的完整思路。
一、这份文档是什么:Claude Code 规则在 OpenCode 侧的整合
ECC 仓库本身面向 Claude Code、Codex、Opencode、Cursor 等多种 Agent 运行时。.opencode/ 目录承载了专为 OpenCode 设计的插件、命令、Agent 提示词与指令文件,而 .opencode/instructions/INSTRUCTIONS.md 扮演的角色是"把 Claude Code 配置中的核心规则与指南整合起来,供 OpenCode 使用"。
从配置加载路径可以直观看到它的地位。查看 .opencode/opencode.json 的 instructions 数组:
"instructions": [
"AGENTS.md",
"CONTRIBUTING.md",
"instructions/INSTRUCTIONS.md",
"skills/tdd-workflow/SKILL.md",
"skills/security-review/SKILL.md",
"skills/coding-standards/SKILL.md",
"skills/frontend-patterns/SKILL.md",
"skills/frontend-slides/SKILL.md",
"skills/backend-patterns/SKILL.md",
"skills/e2e-testing/SKILL.md",
"skills/verification-loop/SKILL.md",
"skills/api-design/SKILL.md",
"skills/strategic-compact/SKILL.md",
"skills/eval-harness/SKILL.md"
]
也就是说,每当 OpenCode 会话启动并加载默认 agent 时,这份 INSTRUCTIONS 都会与其他指令、Skill 一起进入上下文,成为模型行为的常驻约束——安全红线、代码风格、测试纪律与 Git 规范都以"始终在场"的方式生效,而非靠用户临时口头提醒。这也解释了为什么文档里有大量 ALWAYS / NEVER / CRITICAL / MANDATORY 这类强约束措辞:指令文本本身就是发给 LLM 的可执行策略。
文档正文划分为七条主线:安全指南、编码风格、测试要求、Git 工作流、Agent 编排、性能优化、常见模式,最后是 OpenCode 专属注意事项与成功度量。下文逐条展开,并在对应小节补充仓库源码层面的落地证据。
二、安全指南(CRITICAL):提交前的强制检查与密钥管理
2.1 提交前强制安全清单
文档要求在任何 commit 之前逐项核对以下八条("Before ANY commit"):
- [x] 无硬编码密钥(API Key、密码、Token)
- [x] 所有用户输入均已校验
- [x] SQL 注入防护(参数化查询)
- [x] XSS 防护(HTML 净化)
- [x] 启用 CSRF 防护
- [x] 认证/授权已核验
- [x] 所有端点限流
- [x] 错误信息不泄漏敏感数据
这并非空泛清单——在仓库的 OpenCode 侧,它被两类机制落到实处。一是专用命令与 Agent:.opencode/commands/security.md 对应 /security 斜杠命令,绑定 security-reviewer Agent(见 .opencode/opencode.json 中 command.security 配置,其 prompt 来自 .opencode/prompts/agents/security-reviewer.txt);二是自定义工具 .opencode/tools/security-audit.ts 提供扫描能力。全仓库还设有 security-review Skill(skills/security-review/SKILL.md)作为长驻知识。
2.2 密钥管理:环境变量取代硬编码
文档给出的正反示例是 TypeScript/Node 场景最常见的坑:
// NEVER: Hardcoded secrets
const apiKey = "sk-proj-xxxxx"
// ALWAYS: Environment variables
const apiKey = process.env.OPENAI_API_KEY
if (!apiKey) {
throw new Error('OPENAI_API_KEY not configured')
}
值得注意的配套细节:即便走环境变量,也要显式判空并快速失败,避免"看起来配好了、实际是 undefined"的静默问题。这与仓库中"静默失败猎手"(silent-failure-hunter)等 Agent 的理念一致:让配置缺失尽早暴露,而不是运行到一半才崩溃。
2.3 安全事件响应协议
一旦发现安全问题,文档规定五步流程:
- 立即停止(STOP immediately)
- 使用 security-reviewer Agent
- 先修复 CRITICAL 级问题再继续
- 轮换所有已暴露的密钥
- 在整个代码库中排查同类问题
第五步强调"排查同类问题"而非只修一处,是防止同一错误模式(比如另一种硬编码、另一个未转义输入)在项目其他地方复发。对应实现上,仓库的 agents 目录与 .opencode/prompts/agents/ 均包含 security-reviewer 的完整提示词(如 .opencode/prompts/agents/security-reviewer.txt)。
三、编码风格:不可变、小文件、强错误处理
3.1 不可变性(CRITICAL)
规则核心一句话:"ALWAYS create new objects, NEVER mutate"(永远创建新对象,绝不原地修改):
// WRONG: Mutation
function updateUser(user, name) {
user.name = name // MUTATION!
return user
}
// CORRECT: Immutability
function updateUser(user, name) {
return {
...user,
name
}
}
正确写法用对象展开(spread)返回新对象,保证原对象不被污染。这在 React 状态管理、并发场景与可预测测试中价值尤其明显——配合后文"输入校验"一节,等于把数据流塑造成"不可变 + 边界校验"的管道。
3.2 文件组织原则
文档明确倾向"多个小文件优于少量大文件",核心参数:
- 高内聚、低耦合(High cohesion, low coupling)
- 单文件典型 200–400 行,上限 800 行
- 从大型组件中抽取工具函数/工具模块
- 按功能/领域组织,而非按类型组织(feature/domain 优先,而不是把全部 utils、全部 components 堆在一起)
最后一条是对扁平"类型目录"结构的直接否定,与 ECC 中 code-architect、code-simplifier 等 Agent 的评审口径一致。
3.3 错误处理
"ALWAYS handle errors comprehensively"——任何可能失败的操作都要兜底:
try {
const result = await riskyOperation()
return result
} catch (error) {
console.error('Operation failed:', error)
throw new Error('Detailed user-friendly message')
}
注意两个细节:console.error 记录原始错误用于排查,但抛给上层的是对用户友好、信息详细的异常消息——呼应 2.1 清单中"错误信息不泄漏敏感数据"。
3.4 输入校验:Zod Schema 化
外部输入一律经过校验:
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)
zod 的 .parse() 在数据不合法时会抛出带结构化问题的异常,天然与服务边界、表单验证、CLI 参数解析衔接。
3.5 代码质量自检清单
完成任务标记"完成"前逐项过:
- [ ] 代码可读、命名良好
- [ ] 函数短小(< 50 行)
- [ ] 文件聚焦(< 800 行)
- [ ] 无深层嵌套(> 4 层禁止)
- [ ] 错误处理到位
- [ ] 无
console.log残留 - [ ] 无硬编码值
- [ ] 无原地修改(使用不可变模式)
其中"无 console.log"这一条在 OpenCode 场景被插件进一步自动化,详见第八章。
四、测试要求:80% 覆盖率下限与强制 TDD
4.1 最低覆盖率 80%,三类测试全要
文档要求三类测试全部具备:
- 单元测试——单个函数、工具、组件
- 集成测试——API 端点、数据库操作
- E2E 测试——关键用户流程(Playwright)
配套的命令层有 .opencode/commands/test-coverage.md(/test-coverage,绑定 tdd-guide Agent)、.opencode/commands/e2e.md(/e2e,绑定 e2e-runner Agent);工具层则提供 .opencode/tools/run-tests.ts 与 .opencode/tools/check-coverage.ts,前者执行测试套件,后者分析覆盖率——这让"80% 覆盖率"不是一个口号,而是一个可被命令触发的量化检查点。从仓库目录结构看,根目录与 tests/ 下也确实分布着大量 .test.js、.test.ts 与 Python test_*.py 用例,与规则自洽。
4.2 TDD 强制工作流(RED → GREEN → REFACTOR)
文档用六步定义了 Mandatory workflow:
- 先写测试(RED)
- 运行测试——应当失败
- 写最小实现(GREEN)
- 运行测试——应当通过
- 重构(IMPROVE)
- 核验覆盖率(80%+)
这套"先红后绿"的顺序对 LLM Agent 尤其关键:先写测试等于先固化行为契约,避免模型"自证正确"地跳过验证。仓库提供了专门承载这套方法的 Skill(skills/tdd-workflow/SKILL.md),并在 .opencode/commands/tdd.md 中封装为 /tdd 命令。
4.3 测试失败排障路径
测试挂了按序处理:
- 使用 tdd-guide Agent
- 检查测试隔离性(是否相互污染)
- 核验 Mock 是否正确
- 修复实现而非测试(除非测试本身就是错的)
第 4 条是原则性提醒:测试失败首先怀疑实现缺陷,防止"为了让测试变绿而篡改断言"的作弊式开发。
五、Git 工作流:提交格式、PR 与功能开发流程
5.1 提交信息格式
<type>: <description>
<optional body>
允许的 type 集合:feat, fix, refactor, docs, test, chore, perf, ci——即 Conventional Commits 标准子集。仓库根目录配套了 commitlint.config.js,把该格式固化为 commit-msg 阶段的硬校验。
5.2 PR 工作流要点
创建 PR 时:
- 分析完整提交历史(不能只看最新一次提交)
- 用
git diff [base-branch]...HEAD查看全部变更 - 撰写全面的 PR 摘要
- 附带含 TODO 的测试计划
- 新分支推送时加
-u参数(git push -u origin <branch>)
5.3 功能开发四阶段
- 先规划(Plan First):调用 planner Agent 制定实现计划,识别依赖与风险,拆分为多个阶段
- TDD 推进:由 tdd-guide Agent 引导,RED → GREEN → IMPROVE,并核验 80%+ 覆盖率
- 代码评审:写完代码立刻交给 code-reviewer Agent;CRITICAL 与 HIGH 问题必须处理,MEDIUM 尽量处理
- 提交与推送:详细提交信息 + Conventional Commits
"写码即评审"的时机要求("immediately after writing code")值得强调——评审越贴近编码现场,修复成本越低。仓库中对应 Agent 的提示词位于 .opencode/prompts/agents/(含 code-reviewer.txt、planner.txt、tdd-guide.txt 等)。
六、Agent 编排:角色表与"无需提示词"的调用时机
6.1 可用 Agent 一览(文档口径)
| Agent | 用途 | 何时使用 |
|---|---|---|
| planner | 实现规划 | 复杂功能、重构 |
| architect | 系统设计 | 架构决策 |
| tdd-guide | 测试驱动开发 | 新功能、缺陷修复 |
| code-reviewer | 代码评审 | 写完代码之后 |
| security-reviewer | 安全分析 | 提交之前 |
| build-error-resolver | 修复构建错误 | 构建失败时 |
| e2e-runner | E2E 测试 | 关键用户流程 |
| refactor-cleaner | 死代码清理 | 代码维护 |
| doc-updater | 文档 | 更新文档 |
| go-reviewer | Go 代码评审 | Go 项目 |
| go-build-resolver | Go 构建错误 | Go 构建失败 |
| database-reviewer | 数据库优化 | SQL、Schema 设计 |
6.2 在 OpenCode 配置中的实现形态
把 .opencode/opencode.json 的 agent 段与上表对照可以看到规则的落地方式:每个 Agent 被声明为 mode: "subagent" 的子 Agent,并通过 prompt: "{file:prompts/agents/<name>.txt}" 指向独立提示词文件。多数只读评审型 Agent(如 code-reviewer、architect、planner)仅开放 read 与 bash、关闭 write/edit,从工具权限上杜绝评审者顺手改代码;而执行型 Agent(如 tdd-guide、security-reviewer、doc-updater)则开放读写。主 Agent build 是 mode: "primary",默认启用 write/edit/bash/read 及 changed-files 工具。
"评审者不可写、执行者可写"的权限分层,是这套编排能跑起来而不互相踩踏的关键设计。
6.3 即时调用:无需用户输入
文档强调以下场景应自动触发,不必等用户开口:
- 复杂功能需求 → 用 planner
- 刚写完/刚改完代码 → 用 code-reviewer
- 缺陷修复或新功能 → 用 tdd-guide
- 架构决策 → 用 architect
七、性能优化:模型分层与上下文预算
7.1 模型选型策略
文档按成本与能力把模型分成三档:
Haiku(宣称具备 Sonnet 约 90% 的能力、成本约为其三分之一):
- 高频调用的轻量 Agent
- 结对编程与代码生成
- 多 Agent 系统中的 Worker 角色
Sonnet(最佳编码模型):
- 主要开发工作
- 编排多 Agent 工作流
- 复杂编码任务
Opus(推理最深):
- 复杂架构决策
- 对推理能力要求最高的任务
- 研究与分析任务
(注:以上能力/成本描述为 INSTRUCTIONS 文档中的选型指导口径,实际能力与价格请以所接模型供应商当前公开信息为准。)
ECC 的设计把"模型策略"与"规则文档"解耦:查看 .opencode/README.md 可知,参考配置刻意把模型选择留给 OpenCode——主 Agent 使用你在 OpenCode 里全局选定的模型,其 subagent 继承调用方主 Agent 的模型。也就是说,上面的分层策略是通过"为不同任务路由到不同复杂度的子流程"来实践的,而非写死在配置里。
7.2 上下文窗口管理
避免在上下文窗口最后 20% 内执行高认知负荷操作,例如:
- 大规模重构
- 跨多文件的特性实现
- 复杂交互的调试
这条建议本质上是在窗口"尾部"仍保证足够的推理余量,防止模型在上下文近满、早期信息开始被挤压时做出质量下滑的决策。
7.3 构建失败处置
构建挂了按四步推进:先用 build-error-resolver Agent → 分析错误信息 → 增量修复 → 每步修复后验证。强调"一次修一点、修完就验",避免堆积性大改导致错误互相遮蔽。
八、Common Patterns:可复用的工程模板
文档沉淀了三类可直接套用的模式,正文给出完整模板代码。
8.1 统一 API 响应格式
interface ApiResponse<T> {
success: boolean
data?: T
error?: string
meta?: {
total: number
page: number
limit: number
}
}
把"成功/失败"显式建模,错误与分页元数据都走约定结构,客户端与服务端共享同一契约。
8.2 自定义 Hooks 模式(防抖)
export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value)
useEffect(() => {
const handler = setTimeout(() => setDebouncedValue(value), delay)
return () => clearTimeout(handler)
}, [value, delay])
return debouncedValue
}
典型的 React 防抖封装:effect 清理函数保证每次 value/delay 变化都重置计时器,避免内存泄漏与竞态。
8.3 Repository 模式
interface Repository<T> {
findAll(filters?: Filters): Promise<T[]>
findById(id: string): Promise<T | null>
create(data: CreateDto): Promise<T>
update(id: string, data: UpdateDto): Promise<T>
delete(id: string): Promise<void>
}
五个标准 CRUD 方法构成最小仓储契约,数据访问与业务逻辑解耦,便于替换实现与单元测试打桩。
九、OpenCode 专属落地:手动清单、可用命令与自动化插件
9.1 曾经的取舍:OpenCode 无 hooks 时的手动操作
INSTRUCTIONS.md 明确了一个背景事实:早期 OpenCode 不支持 hooks,因此在 Claude Code 中被自动化的一些动作,迁移到 OpenCode 后需手动执行——
写完/编辑完代码后:
prettier --write <file>格式化 JS/TS 文件npx tsc --noEmit检查 TypeScript 错误- 检查并移除
console.log
提交前:
- 手动运行安全检查
- 确认代码中无密钥
- 运行完整测试套件
9.2 现状:仓库已提供插件化 hooks 层
需要说明的是,当前仓库的 .opencode 侧已演进出一个插件实现来弥补这一缺口。查看 .opencode/plugins/index.ts 与 .opencode/plugins/ecc-hooks.ts:后者注册了 file.edited(在 strict 档自动跑 prettier --write、并对 JS/TS 做 console.log 告警)、tool.execute.after(编辑 TS 后跑 npx tsc --noEmit)、session.idle(对本次会话编辑过的文件做 console.log 审计并触发跨平台桌面通知)等钩子。文件头注释给出了 Claude Code 事件到 OpenCode 事件的映射关系:
| Claude Code | OpenCode |
|---|---|
| PreToolUse | tool.execute.before |
| PostToolUse | tool.execute.after |
| Stop | session.idle |
| SessionStart | session.created |
| SessionEnd | session.deleted |
插件还支持运行时控制:ECC_HOOK_PROFILE(minimal/standard(默认)/strict)与 ECC_DISABLED_HOOKS(逗号分隔的钩子 ID 禁用列表),并可注入 PROJECT_ROOT、PACKAGE_MANAGER、DETECTED_LANGUAGES、ECC_VERSION 等环境变量到 shell 会话(见 ecc-hooks.ts 中的 shell.env 实现)。因此在使用该仓库时,9.1 的手动项在很大程度上已由插件代劳;若你只是把 INSTRUCTIONS.md 拷到不支持 hooks 的裸 OpenCode 项目,则仍需按 9.1 的手动清单执行。
9.3 OpenCode 可用命令
文档列出的命令对应 .opencode/commands/ 下的模板文件,多数在 .opencode/opencode.json 的 command 段中绑定到对应 Agent 并以 subtask 方式执行:
| 命令 | 作用 | 实现文件 |
|---|---|---|
/plan |
制定实现计划 | .opencode/commands/plan.md(planner) |
/tdd |
强制 TDD 工作流 | .opencode/commands/tdd.md(tdd-guide) |
/code-review |
评审代码变更 | .opencode/commands/code-review.md(code-reviewer) |
/security |
运行安全评审 | .opencode/commands/security.md(security-reviewer) |
/build-fix |
修复构建错误 | .opencode/commands/build-fix.md(build-error-resolver) |
/e2e |
生成并运行 E2E 测试 | .opencode/commands/e2e.md(e2e-runner) |
/refactor-clean |
清理死代码 | .opencode/commands/refactor-clean.md(refactor-cleaner) |
/orchestrate |
多 Agent 工作流 | .opencode/commands/orchestrate.md(planner) |
(注:配置中 /build-fix 等命令指向的命令文件与 prompts 文件,需在对应目录中按需补齐;以仓库当前实际存在的 .opencode/commands/ 与 .opencode/prompts/agents/ 文件为准。)
十、成功度量:什么才算"做得对"
文档用五条标准定义成功,可直接作为 Agent 每次交付的验收口径:
- 所有测试通过(覆盖率 80%+)
- 无安全漏洞
- 代码可读、可维护
- 性能可接受
- 满足用户需求
十一、如何在自己项目里使用这份规则
仓库是只读参考,你不需要修改它就能复用这套工程纪律,常见做法有三:
- 直接模式:在仓库目录内启动 OpenCode,
.opencode/opencode.json会自动把 INSTRUCTIONS.md 与各 Skill 装入上下文,随时可用/plan、/tdd、/code-review、/security等命令。 - npm 插件模式:
npm install ecc-universal后在项目的opencode.json里加"plugin": ["ecc-universal"],获得插件 hooks 与自定义工具(run-tests、check-coverage、security-audit 等,详见 .opencode/README.md)。 - 挑选移植:把 .opencode/instructions/INSTRUCTIONS.md(连同需要的 Skill 与 Agent 定义)复制到自有项目的
.opencode/下,按需裁剪安全清单、文件行数上限与 TDD 覆盖率,即可让这套纪律作用于任何代码库。
无论哪种方式,核心不变:把安全、风格、测试与 Git 的规则文本化、进上下文、可被命令触发——这正是 Agent 时代工程规范从"写在 wiki 里"走向"运行在每次会话里"的关键一步。
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 StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00