ECC /evolve 本能进化实战:从会话观察物到技能、命令与 Agent 的持续学习闭环
本指南聚焦 ECC 项目中 Continuous Learning v2.1 的 evolve 命令(见 .opencode/commands/evolve.md 与 commands/evolve.md),讲解如何把会话过程中沉淀下来的"本能(instinct)"聚类、分析并进化为可复用的 skills、commands 与 agents。读完本文,你将掌握 evolve 的全部调用方式与参数语义、触发词聚类的底层算法与落盘产物格式,并能在自己的项目中跑通"观察 → 分析 → 进化 → 提升(promote)"的完整闭环。
/evolve 在知识体系中的位置:本能进化是持续学习的第四阶段
在 ECC 仓库中,skills/continuous-learning-v2/SKILL.md 将 v2 持续学习架构概括为四个阶段:基于 Hook 的观察捕获 → 后台 observer 分析循环 → 本能(instinct)评分与持久化 → 将本能进化为可复用的 skills/commands。而 docs/continuous-learning-v2-spec.md 也明确将其列为 v2 架构的稳定参考。evolve 命令负责的正是第四阶段——它把分散的、原子化的"本能"文件当作原料,按主题聚类,找出值得固化的模式,产出技能、命令与 Agent 三类可加载结构。
所谓"本能",是该体系对一段可复用经验的原子化封装:一条触发条件(trigger)、一条动作建议(action)、一个 0.3–0.9 的置信度评分、一个 domain 标签,以及 project/global 两种作用域。SKILL.md 给出的典型示例是:
---
id: prefer-functional-style
trigger: "when writing new functions"
confidence: 0.7
domain: "code-style"
source: "session-observation"
scope: project
project_id: "a1b2c3d4e5f6"
project_name: "my-react-app"
---
# Prefer Functional Style
## Action
Use functional patterns over classes when appropriate.
## Evidence
- Observed 5 instances of functional pattern preference
- User corrected class-based approach to functional on 2025-01-15
而 v2.1 的关键升级是引入了项目级作用域:React 项目的模式留在 React 项目,Python 项目的约定留在 Python 项目,只有诸如 "always validate input" 这类通用模式才进入全局。evolve 分析时默认同时读取项目级与全局级本能,再判断哪些簇(cluster)值得固化到哪一级目录,这正是 evolve 命令的 Behavior Notes 所描述的行为。
命令是什么、何时使用
evolve 命令的 frontmatter 将其描述为 "Analyze instincts and suggest or generate evolved structures",且由 agent: build 执行。它适合在以下场景被触发:
- 项目里已经累积了一批直觉/经验型本能,想看看它们能聚成哪些技能主题;
- 需要把重复出现的 workflow 本能固化成一条可斜杠调用的命令;
- 想为复杂、多步骤的模式沉淀出专职 Agent;
- 想了解哪些项目级本能达到了晋升全局(project → global)的标准。
它的本质是"只读的分析器 + 可选的文件生成器":不带参数时只做分析、不做任何写入;只有在追加 --generate 时才会真正把产物写到磁盘。
调用方式与参数语义
两个入口与两种安装形态
命令正文要求代理执行底层 CLI。插件化安装(推荐)时使用插件根目录变量定位脚本:
python3 "${CLAUDE_PLUGIN_ROOT}/skills/continuous-learning-v2/scripts/instinct-cli.py" evolve $ARGUMENTS
当 CLAUDE_PLUGIN_ROOT 不可用(即手动安装到 ~/.claude/skills 而非插件路径)时回退到:
python3 ~/.claude/skills/continuous-learning-v2/scripts/instinct-cli.py evolve $ARGUMENTS
两处路径中的 instinct-cli.py 在仓库中的对应实现是 skills/continuous-learning-v2/scripts/instinct-cli.py(约 2290 行,内置 status/import/export/evolve/promote/projects/prune 共 7 个子命令)。
支持的参数(v2.1)
| 调用形态 | 行为 |
|---|---|
evolve(无参数) |
仅做分析:列出技能/命令/Agent 候选与晋升候选,不产生任何写入 |
evolve --generate |
在分析之后,将候选写成文件,落盘于 evolved/{skills,commands,agents} |
此外,CLI 本身还支持一个文档正文未展开、但在源码解析器中可见的限额参数 --limit N:用于限制每类候选最多生成多少个(默认 0 表示全部生成,见 instinct-cli.py 的 evolve 子命令定义)。当限额导致丢弃候选时,CLI 会显式打印形如 Note: writing N of M ... candidates (--limit N); M-N skipped. 的提示,避免"静默丢文件"(该设计意图在 _generate_evolved 的 docstring 中有说明)。
$ARGUMENTS 是斜杠命令透传的用户参数:例如在会话中键入 /evolve --generate,命令体会携带 --generate 执行上方的 Python 调用。evolve 在入口处还有一个前置条件——分析的原料要足够:源码中若 load_all_instincts 数量小于 3,会打印 Need at least 3 instincts to analyze patterns. 并返回退出码 1(见 cmd_evolve)。换言之,要先让观察系统沉淀出至少 3 条本能,进化分析才有意义。
分析阶段输出:四类候选一目了然
执行无参 evolve 时,cmd_evolve 按以下顺序输出(此处为按源码打印格式还原的示意输出):
============================================================
EVOLVE ANALYSIS - 12 instincts
Project: my-react-app (a1b2c3d4e5f6)
Project-scoped: 9 | Global: 3
============================================================
High confidence instincts (>=80%): 4
Potential skill clusters found: 2
## SKILL CANDIDATES (2)
1. Cluster: "using react hooks state"
Instincts: 3
Avg confidence: 87%
Domains: code-style
Scopes: project
Instincts:
- use-react-hooks [project]
- prefer-hooks-over-classes [project]
- ...
## COMMAND CANDIDATES (2)
/run-tests-before-commit
From: always-run-tests [project]
Confidence: 85%
## AGENT CANDIDATES (1)
react-refactor-specialist
Covers 3 instincts
Avg confidence: 87%
============================================================
各阶段判定逻辑依次为(均可对应到源码):
- 原料盘点与域分组:先按
domain(code-style/testing/git/debugging/workflow等)分组,并统计置信度 ≥ 0.8 的"高置信"本能数量。 - 技能候选(skill candidates):对本能按 trigger 关键词重叠做贪心聚类,凡成员 ≥ 2 的簇,计算平均置信度、域集合与作用域集合,再按"簇规模降序 → 平均置信度降序"排序。
- 命令候选(command candidates):只取
domain == 'workflow'且confidence >= 0.7的本能,逐条建议一条命令;命令名由 trigger 降噪去词头(去掉when、implementing)后 slug 化。 - Agent 候选(agent candidates):在技能候选基础上加严——成员 ≥ 3 且平均置信度 ≥ 0.75,即"复杂多步骤模式"才配得上一个 Agent。
- 晋升候选(promotion candidates):调用
_show_promotion_candidates,提示哪些项目级本能符合 project → global 条件。
预览只展示各类的前 5 条(PREVIEW_LIMIT = 5),超出的部分会显式补一句 ... and N more skill clusters not shown 之类的说明,避免把抽样列表误读成全集(见 _print_preview_remainder)。
底层原理:关键词重叠聚类与命名去碰撞
为什么不能用 Jaccard
本能 trigger 是自由句式,平均约 7 个词,直接做全句归一化比较会让每条本能各自成桶、永远聚不出技能。源码注释明确解释了取舍:Jaccard 相似度在这里是错误指标——语义相关的句子间 Jaccard 也常常顶到 0.33 附近而永远无法归组。因此实现采用重叠系数 shared_keywords / min(len(A), len(B)),并配两道闸门(见 聚类相关常量与实现):
TRIGGER_SIMILARITY_THRESHOLD = 0.5:重叠系数须 ≥ 0.5;TRIGGER_MIN_SHARED_KEYWORDS = 2:至少要共享 2 个实词,防止一个偶然共词把无关本能拉拢;- 关键词先做小写化、剔除停用词、只保留长度 > 2 的词;
- 簇标签取成员共享关键词集中按字母序前 4 个;新本能加入簇后,簇关键词会被收缩为与它的交集,确保"一簇只讲一个主题"。
文件名 slug 的工程细节
进化产物要落盘为文件,而 trigger 是长句,于是需要 slug 化并截断。三类产物分别使用 EVOLVED_SKILL_SLUG_LENGTH=30、EVOLVED_COMMAND_SLUG_LENGTH=20、EVOLVED_AGENT_SLUG_LENGTH=20(见 slug 常量与截断逻辑)。截断必须落在词边界上,避免出现 investigating-comple 这类半截单词的难看文件名;只有首个单词本身就超长时才做硬切。同时用 _assign_unique_slugs 为候选分配去重后缀(如 base-2、base-3),防止两条 trigger 共享同一前缀时后生成的文件悄悄覆盖前者;预览与生成复用同一套 slug 函数与同一有序列表,保证"预览看到的文件名 = 实际写出的文件名"。
--generate 落盘产物:目录结构与三种格式
输出路径规则
是否加 --generate 直接决定写入目录。命令文档给出的路径规则是:
- 项目上下文:
~/.claude/homunculus/projects/<project-id>/evolved/ - 全局回退:
~/.claude/homunculus/evolved/
值得说明的是路径中的"默认数据目录"随 v2.1 发生了迁移:文档这里记录的 ~/.claude/homunculus 是 v2.0 的默认位置;当前实现中,CLI 通过 _resolve_homunculus_dir 按 ①环境变量 CLV2_HOMUNCULUS_DIR(必须是绝对路径)→ ②$XDG_DATA_HOME/ecc-homunculus → ③$HOME/.local/share/ecc-homunculus 的顺序解析数据根目录,旧的 ~/.claude/homunculus 用户可用 migrate-homunculus.sh 一次性迁移(具体解析优先级见 instinct-cli.py 目录解析)。目录骨架中 evolved/ 下恒有 skills/commands/agents 三个子目录,项目级与全局级各有一套。
生成时的目标目录由项目身份决定:项目 ID 非 global 时写 project["evolved_dir"](即项目哈希目录下),否则写全局 GLOBAL_EVOLVED_DIR。若某类候选为空或置信不足,则打印 No structures generated (need higher-confidence clusters).。
三类产物的文件格式
技能(skill):每个簇生成一个 <slug>/SKILL.md 目录,frontmatter 含 name 与 description;正文含"Evolved from N instincts (avg confidence: XX%)"、"## When to Apply"(写入簇 trigger)与"## Actions"(逐条本能提取其 ## Action 段作为列表项)。这类产物遵循 Agent Skills 规范——产物描述生成逻辑 特意说明:Claude Code 及任何符合规范的 Skills 客户端启动时只注入 name + description,缺了 frontmatter 的产物在磁盘上是"惰性"的、不会被加载。
命令(command):每个 workflow 本能生成 commands/<slug>.md,frontmatter 只含 description,正文把本能 ID、置信度与完整本能内容(含 Action/Evidence)原样嵌入。
Agent:每个复杂簇生成 agents/<slug>.md,frontmatter 除 name/description 外固定携带 model: sonnet 与 tools: Read, Grep, Glob,正文列出其来源本能清单与域标签。
另外生成器会对 description 做两重净化:把 : 替换为 -(冒号空格会破坏严格 YAML 解析器的无引号标量),把 </> 替换为圆括号(防止注入系统提示词),见 _evolved_description。
协同命令与完整工作流
本能家族 CLI 一览
evolve 并不孤立工作,instinct-cli.py 的全部子命令构成了一个闭环(对应仓库中的斜杠命令文档 instinct-status.md、instinct-export.md、instinct-import.md、promote.md、projects.md):
| 子命令 | 职责 | 关键参数(源码解析器) |
|---|---|---|
status |
展示项目级 + 全局本能及置信度 | 无 |
import |
从文件/URL 导入本能 | --dry-run、--force、--min-confidence、--scope(project/global) |
export |
导出本能(按域/置信度/作用域过滤) | --output/-o、--domain、--min-confidence、--scope |
evolve |
聚类并进化 | --generate、--limit N |
promote |
项目本能提升为全局 | [instinct_id]、--force、--dry-run |
projects |
列出已知项目与本能计数 | 子命令 delete/merge/gc |
prune |
清理过期 pending 本能 | --max-age、--dry-run、--quiet |
promote 与 evolve 的晋升建议共享同一组代码级阈值:同一本能 ID 出现在 ≥ 2 个项目且平均置信度 ≥ 0.8 即构成自动晋升候选(常量见 instinct-cli.py 阈值区)。交互式会话里则可直接 /evolve 查看建议、再对单个本能执行 python3 instinct-cli.py promote <id>。
从观察到进化的完整落地流程
- 启用观察 Hook:作为插件安装时无需手写
settings.json的 Hook 块,hooks/hooks.json已注册 observe.sh;手动安装到~/.claude/skills时才需在 settings.json 中补充PreToolUse/PostToolUse两个 matcher 为*的 Hook 块。观察数据写入数据根目录外的ecc-homunculus,避免被 Claude Code 的敏感路径守卫拦截。 - 打开后台 observer:编辑 skills/continuous-learning-v2/config.json(默认
observer.enabled=false),其三个配置项及默认值为:enabled=false(是否启用后台观察分析)、run_interval_minutes=5(分析频率)、min_observations_to_analyze=20(达到该观察条数才跑分析)。其余行为(观察捕获、本能阈值、项目作用域、晋升标准)由instinct-cli.py与observe.sh的代码默认值控制。 - 等待本能沉淀:observer 把用户纠正、错误修复、重复工作流固化为原子本能;置信度在 0.3(暂定,仅建议不强制)→ 0.5(相关时应用)→ 0.7(强,自动批准应用)→ 0.9(近乎确定,核心行为)之间随观察证据浮动。
- 运行
/evolve分析:确认至少 3 条本能后查看四类候选。 /evolve --generate生成:审阅预览无异议后落盘;产物默认为项目级(若当前不在任何项目中则回退全局)。- 复用、分享与收敛:把满意的命令/skill 纳入实际工作流;对跨项目重复出现的模式用
/promote升全局;用/instinct-export导出可分享子集、/instinct-import引入他人本能;过期未决本能由/prune按 30 天 TTL 清理。
项目作用域是怎么判定的
本能在产生时就要决定进项目还是全局。detect-project.sh(CLI 侧对应 Python 版 detect_project)按优先级判定当前项目:①环境变量 CLAUDE_PROJECT_DIR(显式覆盖,即使非 git 目录也按绝对路径哈希成独立项目)→ ②git remote get-url origin(哈希后跨机器可移植,同一仓库在不同机器上 ID 一致)→ ③git rev-parse --show-toplevel(按仓库路径兜底)→ ④全局回退。项目 ID 是 12 字符 SHA-256 短哈希,注册表 projects.json 负责把 ID 映射为人类可读名称,读写时用 fcntl 文件锁防止多会话并发写坏(Windows 上锁为 no-op)。remote URL 在哈希前会去除凭据、协议头、.git 后缀与尾部斜杠做归一化,确保同一远程仓库无论以哪种方式 clone 都得到同一个项目 ID;该项目作用域隔离的收益在于——React 约定不会污染 Python 项目,反之亦然。
作用域决策速查(对应 evolve 候选的作用域字段)
| 模式类型 | 建议作用域 | 例子 |
|---|---|---|
| 语言/框架约定 | 项目 | "Use React hooks"、Django REST 模式 |
| 文件结构偏好 | 项目 | 测试放 __tests__/、组件放 src/components/ |
| 代码风格 | 项目 | 函数式优先、偏好 dataclass |
| 错误处理策略 | 项目 | 用 Result 类型处理错误 |
| 安全实践 | 全局 | 校验用户输入、SQL 消毒 |
| 通用最佳实践 | 全局 | 先写测试、始终处理错误 |
| 工具工作流偏好 | 全局 | 先 grep 再 Edit、先 Read 再 Write |
| Git 实践 | 全局 | Conventional Commits、小而聚焦的提交 |
平台限制与注意事项
- 后台 observer 的平台前提:observer 需要 WSL2、Linux 或 macOS。在原生 Windows(Git Bash/MSYS2)上进程会随宿主 Hook 退出而被 Job Object 回收,
observer.enabled: true实际是空操作;observe.sh会在连续多次存活失败后向observer-start.log写解释性告警。可用环境变量ECC_OBSERVER_NOSURVIVE_WARN_AFTER(默认3)控制"连续不存活几次后告警"。注意该限制只针对后台 observer 分析;evolve本身是对已落盘本能文件的同步分析,不受此限。 - 隐私边界:观察数据全部保存在本机,项目级本能天然按项目隔离;可导出的只有"本能/模式",绝不包含原始观察或会话正文,导出与提升都由你掌控。
- 素材门槛:本能不足 3 条时
evolve会拒绝分析;聚类阈值、置信度阈值、promotion 阈值为代码默认值,不通过 config.json 暴露——想调整需要直接改 instinct-cli.py。 - 产物命名可预期:预览与落盘共用同一套 slug/去重逻辑,杜绝"预览名字 ≠ 实际文件名"的错位。
延伸阅读
- skills/continuous-learning-v2/SKILL.md:v2.1 架构总览(本能模型、观察管线、作用域决策、置信度模型、Hook 优于 Skill 的原因与向后兼容)
- docs/continuous-learning-v2-spec.md:v2 持续学习架构的稳定规范引用
- skills/continuous-learning-v2/scripts/instinct-cli.py:CLI 全部子命令与聚类/生成/晋升的完整实现
- .opencode/commands/evolve.md 与 commands/evolve.md:
/evolve斜杠命令的两种 harness 形态定义 - skills/continuous-learning-v2/config.json 与 skills/continuous-learning-v2/hooks/observe.sh:observer 配置与观察捕获入口
一句话总结这条链路:观察把"这次做对了什么"固化成原子本能,evolve 把零散本能变成能直接加载的技能、命令与 Agent——会话里的每一次纠错,最终都会成为团队与工具的长期能力。
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