开源 Agent 套件 ECC 的三份状态上下文:开发、研究、评审各喂什么

2026-07-29

本文基于 ECC 仓库 commit 591ab5c(2026-07-29)梳理,该项目仍在高频迭代,具体行为以仓库 https://github.com/affaan-m/ECC 最新代码与文档为准。

同一个模型在你手里表现忽好忽坏,多数时候不是模型的问题,是你让它在写代码、查问题、审 PR 三种完全不同的状态下,读的是同一份系统提示。 ECC 这套装在编码 Agent 之上的增强件里,对这件事的处理粗暴得有点意外:它没有做状态机,没有做路由器,就是在仓库根目录开了一个 contexts/ 目录,往里放了三个 Markdown 文件,加起来七十来行。你 clone 下来打开就能看完。

这篇要做的事情很窄。站内已有的 上下文工程Agent 的上下文管理 讲的是通用方法论——预算怎么分、什么该留什么该丢;本篇不重复那一层,只把一个任何人都能当场 clone 下来逐行核对的项目拆开,看这套方法论具体落到了哪几个文件、几行字,以及落下去之后代价在哪。

一、这三个文件在哪、有多大、怎么被读进去

contexts/ 目录下只有三个文件:dev.mdresearch.mdreview.md。行数分别是 20、26、22。README 的目录结构里给这个目录的定位是 “Dynamic system prompt injection contexts (Longform Guide)“,也就是说它不属于常驻加载的那一层,而是启动时按需注入的。

怎么注入,写在仓库根目录的 the-longform-guide.md 里。那份文档给出的用法是三条 shell alias:

# Daily development
alias claude-dev='claude --system-prompt "$(cat ~/.claude/contexts/dev.md)"'

# PR review mode
alias claude-review='claude --system-prompt "$(cat ~/.claude/contexts/review.md)"'

# Research/exploration mode
alias claude-research='claude --system-prompt "$(cat ~/.claude/contexts/research.md)"'

这个形态本身就说明了几件事。状态是在启动命令里定死的,一条 alias 对应一个态,不存在会话跑到一半自动切换的机制。文件放在 ~/.claude/contexts/ 而不是项目里,所以它跟着你走、不跟着仓库走。同一份文档里还给了这套做法成立的前提:系统提示的内容权威高于用户消息,用户消息又高于工具返回结果。把行为约束放进系统提示,是为了让它压得住后面对话里的临时指令。

这跟 CLAUDE.md 那条路径是两回事。CLAUDE.md 每次会话都加载,装的是项目知识;这三个文件按状态加载,装的是行为偏好。两者混着写是常见毛病,具体分界可以对照 CLAUDE.md 怎么写 那篇。

组成部分它负责什么仓库位置你什么时候会碰到它
开发态上下文写代码时的行为顺序、优先级、工具偏好contexts/dev.md日常实现功能、改 bug
研究态上下文动手前的探索流程与输出顺序contexts/research.md接手陌生代码、定位根因
评审态上下文评审清单、严重度排序、输出分组方式contexts/review.md看 PR、做代码分析
注入方式说明三条 alias 与系统提示权威层级的说明the-longform-guide.md第一次配置的时候
目录定位说明contexts/ 标为动态注入层README.md 目录结构段想搞清它和常驻配置的区别时
项目当前真相记录分支、版本、活跃队列、约束WORKING-CONTEXT.md想给自己项目也做一份状态文件时

二、开发态:把「先跑起来」写进系统提示

dev.md 的 Behavior 段只有四条:先写代码后解释、能跑的方案优先于完美的方案、改完跑测试、提交保持原子。紧接着是一个三行的优先级排序:

## Priorities
1. Get it working
2. Get it right
3. Get it clean

这三行是整个文件里最值钱的部分。它不是在说「不要写干净的代码」,而是在给 Agent 一个冲突时的仲裁规则。Agent 在实现过程中天然会同时面对「这个函数能跑但难看」和「重构一下更好」两种冲动,没有排序它就会自己挑一个,而且不同轮次挑的还不一样——你会看到它这次直接改完,下次先给你重构一遍目录结构。把排序写死,冲突就有了确定的解法。

Tools to favor 那一段更能看出取向:Edit、Write 用于改代码,Bash 用于跑测试和构建,Grep、Glob 用于找代码。这个列表里没有 Read。 不是说开发态不能读文件,而是这份提示不去鼓励它读——它鼓励的是定位到位置就动手。

对你意味着什么:如果你发现自己的 Agent 在实现阶段总是啰嗦、总是先输出一大段方案再问你要不要继续,那多半不是模型的毛病,是没人告诉它现在这个状态里「解释」应该排在「代码」后面。这四条加一个排序,是可以直接抄的。

三、研究态与评审态:两种不同的「先别急」

research.mddev.md 几乎是对着写的。它的 Behavior 段是:结论之前先广泛地读、主动问澄清问题、边查边记录发现、理解清楚之前不要写代码。然后是一条五步流程——理解问题、探索相关代码与文档、形成假设、用证据验证、总结发现。文件末尾还单列了一行输出约束:findings first, recommendations second,先给发现,再给建议。

工具偏好这一栏最直白地体现了两个态的互斥关系。研究态偏好的是 Read(用于理解代码)、Grep 和 Glob(用于找模式)、WebSearch 与 WebFetch(用于查外部文档),以及用 Task 调 Explore agent 处理代码库层面的问题。开发态那份里出现的 Edit 和 Write,在这里一个都没有。

两个细节值得留意。一是「主动问澄清问题」只出现在研究态,开发态里没有——你在实现阶段不希望它每写三行就停下来确认一次,但在探索阶段你希望它把没搞明白的地方摊开。二是「边查边记录发现」,这一条针对的是探索型会话最典型的失败:读了二十个文件,最后上下文塞满了、结论也没落地。这类污染的成因和更完整的处理办法可以看 上下文污染

review.md 走的是第三条路。Behavior 段四条:评论之前先读透、按严重度排序(critical > high > medium > low)、给出修法而不只是指出问题、检查安全漏洞。然后是一份写死的清单:

## Review Checklist
- [ ] Logic errors
- [ ] Edge cases
- [ ] Error handling
- [ ] Security (injection, auth, secrets)
- [ ] Performance
- [ ] Readability
- [ ] Test coverage

最后一行是输出格式:按文件分组,严重度在前。

这份文件的设计取向和前两份不一样。开发态和研究态约束的是「怎么想」,评审态约束的是「输出长什么样」。理由不难猜:评审结果是要被人消费的——粘进 PR、分给不同的人、按优先级排期。输出结构不固定,你就得每次自己重排一遍。把「按文件分组、严重度在前」写进系统提示,本质上是在给一个下游流程定契约。

「给修法而不只是指出问题」这一条也不是客套话。它挡的是评审输出最没用的那种形态:列一堆「这里可能有问题」,每条都要人再去看一遍才知道该怎么办。要求带修法,等于强迫它在提出之前先把这个问题想到底——想不到修法的,多半本来就是伪问题。

四、状态上下文和项目上下文是两回事

搬这套思路到自己项目之前,得先把一个坑说清楚:ECC 仓库里还有另一个文件叫 WORKING-CONTEXT.md,它同样是「上下文」,但装的东西完全不同。

那个文件记的是项目当前真相:默认分支是什么、公开发布面对齐到哪个版本、当前活跃的工作队列有哪些、有哪些硬约束(比如不允许只凭标题或提交摘要就合并、不允许在交付面里引入任意外部运行时)、执行真相和公开真相分别在哪里。文件末尾还有一条 Update Rule,要求这份文件只保留当前冲刺、阻塞项和下一步动作,完成的工作要收拢到归档或仓库文档里。

这条更新规则不是随便写的。文件顶部标着 “Last updated: 2026-04-08”,里面记录的公开目录真相是 47 个 agent、79 个命令、181 个技能;而今天仓库里 agents/ 下有 67 个、commands/ 下有 94 个、skills/ 下有 281 个。项目状态文件会过期,而且过期得比你想的快。

这恰好解释了 contexts/ 那三个文件为什么写得那么短。它们里面没有一个字提到 ECC 自己:不提分支、不提版本、不提任何具体的构建命令。全是「什么排在什么前面」「优先用哪些工具」「输出按什么分组」这类跟项目无关的东西。不写项目知识,这三个文件就不会过期,也就能直接搬到任何仓库。 反过来,你一旦往状态上下文里塞了「本项目用 pnpm」「测试跑 npm test」,它就变成了一份需要维护的东西,而这类东西没人会记得维护。

所以照着做的时候,分工是这样的:

第一步,回想你最近一周里反复对 Agent 交代的话。不是项目知识那种(那些该进 CLAUDE.md 或项目规则),是行为偏好那种——「别解释了直接改」「先看完再说结论」「按严重程度排一下」。这些重复的话就是你的状态上下文原料。

第二步,一个状态一个文件,每个文件控制在几十行。写不下说明你混进了不该在这一层的东西。

第三步,只写偏好与禁止,工具偏好那一栏尤其要舍得留白——开发态不列 Read、研究态不列 Write,这种刻意的缺项比多写十条都管用。

五、边界与代价

这个设计放弃的东西相当多,说清楚才好判断要不要用。

没有会话内切换。 状态定在启动命令上,一条 alias 一个态。真实的开发流程是研究一会儿、动手一会儿、再回头查一下,而这套机制要求你在每次换挡时另起一个会话。代价是上下文断掉、之前读过的东西要重新捞。这是它换取「系统提示层级压得住」这个好处付出的价格。

它不带项目知识,所以它不知道你怎么跑测试。 dev.md 说 “Run tests after changes”,但没说测试命令是什么——那得靠 CLAUDE.md 或项目规则去补。这三个文件单独用是不完整的。

研究态默认会外联。 那份文件明确把 WebSearch 和 WebFetch 列进偏好工具。如果你的代码库有保密要求,或者所在环境不允许 Agent 主动出网,这一条要先删掉再用。

「能跑优先于完美」不是万能的。 dev.md 的这条偏好在做业务功能时省事,在改支付、权限、数据迁移这类地方就是负债。分不清场合就套用,你会得到一堆能跑但边界条件没处理的代码。

它明确不管的事: 模型怎么选、权限怎么收、成本怎么控、并发怎么编排。这些在 ECC 里由别的目录承担——agents、skills、commands、hooks 各管一摊。contexts/ 这一层只负责「同一个 Agent 在不同状态下的行为偏好」,别指望它解决其他问题。

套件类项目的通用代价,这个项目也有。 它会往你的用户目录写文件、会挂钩子(README 的目录结构里能看到 session-start、session-end、pre-compact 这些钩子实现)、还带一份 MCP 服务器配置。install.sh 本身只是个薄壳:从 clone 目录跑的时候,它检测到没有 node_modules 会自动执行 npm install,然后把活交给 Node 写的安装器。装之前把安装器要动哪些路径看一遍,是基本功课。钩子这一层的机制和风险,站内 Claude Code hooks 有单独一篇。

六、上手与避坑清单

坑一:以为装了 ECC 就有这三个文件可用。 为什么会踩:仓库里明明有 contexts/ 目录,很自然会以为安装脚本会把它铺到 ~/.claude/ 下。实际上仓库的 npm 发布面测试里,contexts/dev.md 被列在「不应包含」的断言中——这个目录不进发布包。 怎么避:把这三个文件手动拷到 ~/.claude/contexts/ 下,或者干脆直接从仓库路径 cat。配完先跑一次 cat ~/.claude/contexts/dev.md 确认文件真的在。

坑二:alias 配好了但状态没生效,还以为是文件写错了。 为什么会踩:alias 里是 $(cat ...),文件路径不存在时 cat 报错、命令替换出空串,Agent 照常启动,只是没带任何系统提示。表现上跟「配置不生效」一模一样,但原因是文件根本没读到。 怎么避:先单独执行一次 alias 里被 cat 的那条路径,看有没有输出,再去怀疑内容。

坑三:往状态文件里塞项目知识。 为什么会踩:写着写着会觉得「顺手把构建命令也写进去吧」。一旦开了这个口子,三个文件就都得跟着项目改,而且三份还会互相不一致。 怎么避:定一条硬规矩——状态上下文里不出现任何专有名词(仓库名、命令名、目录名)。写的时候违反了就说明这句该搬去 CLAUDE.md。

坑四:三个态各写各的,工具偏好互相打架。 为什么会踩:单看每一份都合理,合起来才发现开发态和研究态列的工具几乎一样,那分态就没有意义了。ECC 那三份之所以有效,靠的是刻意的缺项。 怎么避:三份写完,把 Tools to favor 三栏并排贴出来看一遍。如果三栏内容高度重合,回去删,删到每一栏都明显缺了点什么为止。

坑五:研究态没关外联就直接上生产仓库。 为什么会踩:research.md 原文就把 WebSearch、WebFetch 列在偏好里,照抄不改就等于默认允许。 怎么避:第一次用之前把工具偏好那一栏逐条过一遍,删掉你环境里不该出现的。这一栏是全文件最需要按环境改的地方。

坑六:拿三份文件当完整方案,指望它管住成本和权限。 为什么会踩:它们读起来很像「Agent 使用守则」,容易被当成总纲。 怎么避:明确它只覆盖行为偏好这一层。成本、权限、并发编排各有各的做法,别往这七十行里堆。

收尾

判断这套东西对你有没有用,三个问题就够了:你最近一周有没有反复对 Agent 交代同一句行为要求?这句要求在不同工作状态下是不是相反的?如果是,它现在写在哪里——是每次手打,还是塞在一份所有会话都加载的文件里?

三个问题里有两个答「是」,那么把 contexts/ 那三份抄下来改一改,成本是十几分钟。

顺序上建议先读 contexts/dev.md——它最短,二十来行,能最快看清这类文件该写到什么颗粒度。然后读 the-longform-guide.md 里讲动态系统提示注入的那一段,把注入机制和权威层级搞明白。最后读 WORKING-CONTEXT.md,重点不是它的内容,而是末尾那条 Update Rule 和文件顶部那个日期——那是关于「状态文件为什么必须短」最有说服力的一份反面材料。

本文属于 ECC 开源 Agent 套件专题(共 40 篇,从选择性安装一直拆到内部机制)。同一批还写了另一种取向的项目——不给你资产、只给你纪律的 superpowers 方法论专题

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。