主要变更: - Skill Learning 闭环系统 (9/9 AC) - Opus 4.7 模型层接入 + adaptive thinking - Prompt 工程优化 (64 审计测试) - Agent Teams 简化门控 (默认启用) - Windows Terminal 后端修复 (EncodedCommand/WT_SESSION) - TF-IDF 技能搜索精准化 (字段加权/CJK 优化) - Autonomy 系统 (/autonomy 命令) - ACP 协议完整实现 - mock.module 泄漏修复 (CI 全绿) - 152+ lint/type 修复
85 KiB
Skill Learning — ECC 1:1 对比
原初稿基准:HEAD
5feb4103c34c41ea3547da137f184d45d340ef50on branchchore/lint-cleanup, 2026-04-17, ECCecc-universal v1.9.0(skills/continuous-learning-v2/内部版本2.1.0)。2026-04-17 Refresh 记录(工作树脏,未提交):在原初稿之后,Task #1~#11(P0 全部 + P1 全部 + P2 全部,共 11 条实施任务)已全部 land,
bun test2927 pass / 0 fail。Task #14(META-M)即本轮附录图产出。本次只刷新"项目侧对应实现"部分的行号与 FULL/PARTIAL/GAP 评级;ECC 侧描述保持不变。Refresh 后实际有效锚点见各章节的已更新 @ 2026-04-17标注。附录可视化图(两张 Mermaid,META-M 产出)直接追加在文档末尾"文档元信息"之前,与文中矩阵和差距章节配合阅读。
本文档按 team-lead 要求做 ECC 能力与项目实现的逐项对照。不做价值判断,不下"应否采纳 ECC"的结论,只负责提供可追溯的事实对比。对应任务:
docs/features/skill-learning-ecc-parity-tasks.mdTask #13 + Task #14。
Refresh 一览(对第二次核对的差异)
| 任务 | 状态 | 影响的评级条目 |
|---|---|---|
| #1 P0-1 gap 状态机 | completed | 差距 5(首次即 draft 风险)下调至 FULL,skillGapStore.ts:88-125 新增 pending→draft→active→rejected 四态机 |
| #2 P1-2 CJK bi-gram tokenizer | completed | /continuous-learning-v2 多语言维度、/evolve 聚类维度从 ❌/⚠️ 升为 ✅(localSearch.ts:158-194) |
| #3 P2-4 write-fixture 移除 | completed | /continuous-learning-v2 命令面移除 write-fixture case |
| #4 P0-2 outcome-aware confidence | completed | 置信度维度新增 outcome 加权(instinctStore.ts:79-107,success=+0.05/failure=-0.05/contradict=-0.1),evidenceOutcome 字段进入真实使用 |
| #5 P1-1 observer backend 接口 | completed | 差距 2 模式检测从单纯启发式升为 "启发式默认 + LLM backend 接口"(observerBackend.ts 71 行 + llmObserverBackend.ts stub),sessionObserver.ts:24-34 heuristicObserverBackend 作为默认 |
| #6 P1-4 draft 命中计数 | completed | prefetch.ts:206-212 接入 recordDraftHit,draft → active 晋升可由 2 次命中触发 |
| #7 P1-3 命令面补齐 | completed | skill-learning.ts:122-216 新增 promote(支持 gap <key> / instinct <id>)+ projects 两个 case,argumentHint 已含 promote|projects,write-fixture 早在 P2-4 已移除 |
| #8 P0-3 进化三路 | completed | 差距 3 从 GAP 升为 FULL(runtime),evolution.ts:83-135 三路 generator + commandGenerator.ts + agentGenerator.ts + skillLifecycle.ts:63-80 compareExistingArtifacts 泛化 + runtimeObserver.ts:97-135 三路全打通 |
| #9 P0-4 tool event hook | completed(接口层) | 差距 1 从 "只有 post-sampling" 升为 "tool event 优先 + post-sampling 兜底",toolEventObserver.ts 151 行 + runtimeObserver.ts:52-68;src/Tool.ts 主 dispatch 尚未 wire(见 toolEventObserver.ts:22-28 @todo),生产路径仍以 fallback 为主 |
| #10 P2-1 自动 promote | completed | promotion.ts:68+ checkPromotion,runtimeObserver.ts:138 在 autoEvolveLearnedSkills 尾部自动调用(session 内幂等),差距 4 从 ❌ 升为 ✅ |
| #11 P2-2 反重复治理 | completed | skillGenerator.ts:14/59-95 新增 DUPLICATE_SKILL_OVERLAP_THRESHOLD = 0.8 + generateOrMergeSkillDraft + appendInstinctEvidenceToSkill;runtimeObserver.ts:103 已换成 generateOrMergeSkillDraft,overlap ≥ 0.8 时走 append-evidence(把新 instinct 的 evidence 追加到现有 skill),否则走 create + decideSkillLifecycle |
目录
基准声明
| 基准项 | 值 |
|---|---|
| 项目 git SHA (HEAD) | 5feb4103c34c41ea3547da137f184d45d340ef50 |
| 项目分支 | chore/lint-cleanup |
| 项目最近 commit 主题 | feat: 整合功能恢复与技能学习闭环 (2026-04-16) |
| ECC 插件 | ecc-universal (C:\Users\12180\.claude\plugins\marketplaces\everything-claude-code\package.json) |
| ECC 插件版本 | 1.9.0 |
ECC continuous-learning-v2 内部版本 |
2.1.0 (见 skills/continuous-learning-v2/SKILL.md:5) |
ECC continuous-learning (v1) 内部版本 |
无 frontmatter version 字段 |
| 对照日期 | 2026-04-17 |
对照用到的 ECC 源文件清单(全部以 C:\Users\12180\.claude\plugins\marketplaces\everything-claude-code\ 为前缀):
skills/continuous-learning/SKILL.md(v1)skills/continuous-learning/config.json(v1)skills/continuous-learning/evaluate-session.sh(v1)skills/continuous-learning-v2/SKILL.md(v2.1)skills/continuous-learning-v2/config.json(v2.1)skills/continuous-learning-v2/hooks/observe.sh(429 行 Shell)skills/continuous-learning-v2/scripts/instinct-cli.py(1426 行 Python)skills/continuous-learning-v2/scripts/detect-project.shskills/continuous-learning-v2/agents/observer.mdskills/continuous-learning-v2/agents/observer-loop.shskills/continuous-learning-v2/agents/start-observer.shskills/continuous-learning-v2/agents/session-guardian.shcommands/learn.mdcommands/learn-eval.mdcommands/evolve.mdcommands/instinct-status.mdcommands/instinct-export.mdcommands/instinct-import.mdcommands/promote.mdcommands/skill-create.md
对照用到的项目源文件(均以 E:\Source_code\Claude-code-bast-test\ 为前缀):
src/services/skillLearning/types.tssrc/services/skillLearning/observationStore.tssrc/services/skillLearning/instinctStore.tssrc/services/skillLearning/instinctParser.tssrc/services/skillLearning/sessionObserver.tssrc/services/skillLearning/runtimeObserver.tssrc/services/skillLearning/evolution.tssrc/services/skillLearning/skillGenerator.tssrc/services/skillLearning/skillLifecycle.tssrc/services/skillLearning/skillGapStore.tssrc/services/skillLearning/projectContext.tssrc/services/skillLearning/promotion.tssrc/services/skillLearning/learningPolicy.tssrc/commands/skill-learning/index.tssrc/commands/skill-learning/skill-learning.ts
能力全景矩阵
横轴 = 8 个 ECC 能力(+swarm-auto-evolve 归为 ECC 运行时组合);纵轴 = 9 个维度。单元格填 ✅(完整对齐)/ ⚠️(部分对齐)/ ❌(缺失)。判定依据见后文各独立章节。
| 维度 \ ECC 能力 | /learn-eval | /continuous-learning (v1) | /continuous-learning-v2 | /skill-create | /evolve | /instinct-status | /instinct-import | /instinct-export | swarm-auto-evolve |
|---|---|---|---|---|---|---|---|---|---|
| 观察采集 | n/a | ⚠️ Stop hook→post-sampling TS hook | ⚠️ PreToolUse/PostToolUse shell hook→tool-hook 接口 + post-sampling fallback(toolEventObserver.ts 151 行 + runtimeObserver.ts:52-68,主路径尚未 wire 到 src/Tool.ts) |
❌ 从 git log 提取→无 | ⚠️ 读 instinct→读 instinct | ⚠️ 读 instinct+obs→读 obs | n/a | n/a | ⚠️ Haiku agent 分析 obs→无后台 agent,但 observer backend 接口已立(observerBackend.ts) |
| 模式检测 | ✅ 检查清单+holistic verdict | ⚠️ 主上下文启发式→启发式规则 | ⚠️ 后台 Haiku LLM→heuristicObserverBackend(默认)+ llmObserverBackend(stub)双 backend(sessionObserver.ts:24-34 + llmObserverBackend.ts) |
⚠️ git commit 正则→无 | ⚠️ trigger normalization 聚类→domain+trigger 聚类 | n/a | n/a | n/a | ⚠️ Haiku LLM 后台调用→LLM backend stub 已存在,未绑真实 LLM |
| instinct 存储 | n/a | ❌ 直接写 skill md→无独立 instinct 层 | ✅ YAML frontmatter+内容→JSON 文件 | ⚠️ 生成 YAML→无 | ✅ 读 YAML→读 JSON instinct | ✅ 显示 instincts→显示 instincts | ✅ YAML 写入 inherited/→JSON 写入 inherited 目录 | ✅ YAML 序列化→JSON 序列化 | ✅ YAML 写入→JSON 写入 |
| 置信度 | ❌ 不涉及 | ❌ 无 confidence 字段 | ⚠️ 0.3/0.5/0.7/0.85 初始 + 增/减/decay→0~1 范围 + outcome-aware 增/减(instinctStore.ts:79-107 success=+0.05/failure=-0.05/contradict=-0.1,仍无 decay) |
⚠️ 0.7~0.8 初始→无 | ⚠️ 0.8 阈值筛选→0.8 阈值筛选 | ✅ 显示 confidence bar→显示 | ✅ 比较 confidence→比较 | ✅ 过滤 min-confidence→过滤 | ✅ 均值≥0.8→均值≥0.8 |
| 进化目标(skill/cmd/agent) | n/a | ❌ 只生成 skill | ✅ skill/command/agent 三路→三路 generator 全接入(evolution.ts:83-135 + commandGenerator.ts + agentGenerator.ts + runtimeObserver.ts:90-122) |
⚠️ skill+instinct→无 | ✅ 三类 candidates→三路 candidates 已全部写入(P0-3 完成) | n/a | n/a | n/a | ✅ 三路→三路 |
| 跨项目提升 | n/a | ❌ 无 | ✅ 2+项目+avg≥0.8→checkPromotion(promotion.ts:68+)在 runtimeObserver.ts:125 自动调,P2-1 完成;会话内幂等 |
❌ 无 | ✅ 展示 promotion candidates→skill-learning.ts promote 子命令可列候选(skill-learning.ts:122-138) |
⚠️ 区分 project/global→区分 scope | ✅ 支持 --scope→支持 scope | ✅ 支持 --scope→支持 scope | ✅ /promote 手动 + observer 提示→checkPromotion 自动 + /skill-learning promote 手动 |
| 命令面 | ⚠️ /learn-eval 独立→/skill-learning evolve --review(未实现) |
⚠️ /learn 命令→/skill-learning ingest |
✅ 7 子命令→8 子命令(skill-learning.ts status/ingest/evolve/export/import/prune/promote/projects,P1-3 完成) |
❌ /skill-create→无 |
✅ /evolve→/skill-learning evolve |
✅ /instinct-status→/skill-learning status |
✅ /instinct-import→/skill-learning import |
✅ /instinct-export→/skill-learning export |
⚠️ 自动后台 Haiku+手动命令→无后台进程,但 runtime checkPromotion 自动 + 手动 /skill-learning promote |
| 质量门控 | ✅ checklist+4-verdict(Save/Improve/Absorb/Drop) | ⚠️ config.extraction_threshold | ⚠️ min_observations_to_analyze+confidence bucket | ⚠️ 人工检查 git 模式 | ⚠️ avg_confidence≥0.8 筛选 | n/a | ⚠️ confidence 比较保留高者 | ⚠️ min-confidence 过滤 | ❌ 无质量门控 |
| 多语言 | ❌ (指南性文档,无分词需求) | ❌ 无 | ✅ 无→ASCII + CJK bi-gram 混合分词(localSearch.ts:158-194,P1-2 完成) |
❌ 英文 regex | ⚠️ 英文 trigger keyword → normalizedTrigger ASCII only(evolve 聚类本身仍 ASCII,但上游搜索匹配已支持中文) |
❌ 英文 regex | ❌ 纯格式传递 | ❌ 纯格式传递 | ❌ 无 |
矩阵小图注:箭头左侧是 ECC 行为,右侧是项目行为。当项目侧与 ECC 存在结构/语义差异但"能跑出类似结果",记为 ⚠️;完全缺失记为 ❌;一致记为 ✅。后文每个能力章节给出字段级证据。
逐项 1:1 对照
1. /learn-eval
1.1 ECC 侧行为摘要
ECC 源:commands/learn-eval.md。
- 触发:用户手动
/learn-eval(mid-session)。 - 输入:当前会话的 assistant/tool 历史。
- 处理流水(该文件第 19-91 行):
- 浏览会话、识别可复用模式。
- 决定保存位置:Global(
~/.claude/skills/learned/) vs Project(.claude/skills/learned/)。 - 按模板起草 skill 文件(带 YAML frontmatter +
## Problem / ## Solution / ## When to Use)。 - 质量门控:5a checklist(grep 去重、检查 MEMORY.md 重叠、判断是否应合入现有 skill、确认可复用)+ 5b holistic verdict(
Save/Improve then Save/Absorb into [X]/Drop)。 - 按 verdict 进入不同确认流(
improve then save只允许一次再评估)。 - 最终写入 / 追加到目标位置。
- 存储产物:
SKILL.md文件,frontmatter 含name / description / user-invocable: false / origin: auto-extracted。 - 置信度字段:无。verdict 是哲学性判断,不量化。
- 产出物所属 scope:由步骤 3 的 Global/Project 二选一决定。
- 质量门控:5a checklist 强制,5b 四档 verdict 强制。设计理由(第 106-108 行):替代早期 5 维打分,用 holistic verdict 让前沿模型自己权衡。
1.2 项目侧对应实现
项目没有独立的 /learn-eval 实现。与之最接近的是 /skill-learning evolve [--generate](src/commands/skill-learning/skill-learning.ts:58-83)。
精确锚点:
src/commands/skill-learning/skill-learning.ts:58-83evolvecase。src/services/skillLearning/skillLifecycle.ts:67-116decideSkillLifecycle函数(基于 overlap 得分决定 create/merge/replace/archive/delete)。src/services/skillLearning/learningPolicy.ts:25-33shouldGenerateSkillFromInstincts(置信度均值阈值MIN_CONFIDENCE_TO_GENERATE_SKILL = 0.5)。src/services/skillLearning/evolution.ts:58-70generateSkillCandidates(过滤target === 'skill'+shouldGenerateSkillFromInstincts)。
现有流程:
loadInstincts()读当前项目 + 全局 instinct。generateSkillCandidates聚类出 skill 候选。- 如果
--generate,对每个候选调compareExistingSkills→decideSkillLifecycle→applySkillLifecycleDecision。 decideSkillLifecycle的 5 种 decision 类型(create / merge / replace / archive / delete,skillLifecycle.ts:20-25)类似 ECC 的 4-verdict,但决定依据是 term overlap score 而非 holistic verdict。
1.3 字段级对照
| 字段 / 维度 | ECC /learn-eval |
项目 /skill-learning evolve |
对齐 |
|---|---|---|---|
| 触发方式 | 用户手动 | 用户手动(+runtimeObserver.autoEvolveLearnedSkills 每轮自动) |
⚠️ 项目侧额外有自动触发 |
| 输入 | 当前会话上下文(由 LLM 理解) | 已持久化的 instinct 集合(机械聚类) | ⚠️ |
| 重复去重 | 5a checklist 第 1 步 grep 现有 skill | compareExistingSkills 基于 term overlap |
⚠️ 机制不同但同目的 |
| MEMORY.md 去重 | 5a checklist 第 2 步要求 | 无 | ❌ |
| 决定维度 | 5a checklist(4 项) + 5b holistic verdict | overlap score + confidence gap + content length | ⚠️ |
| verdict 枚举 | Save / Improve then Save / Absorb into [X] / Drop | create / merge / replace / archive / delete | ⚠️ 项目多两档(archive/delete) |
| 改进迭代限制 | Improve then Save 仅允许一次再评估 |
无 | ❌ |
| Scope 决定 | LLM 判断 Global vs Project | decideDefaultScope(learningPolicy.ts:76-82):security/git/workflow 且 instinct ≥ 2 判 global,否则 project |
⚠️ 项目更机械 |
| 用户确认流 | 必须(除 Drop 外) | 默认自动执行(applySkillLifecycleDecision) |
❌ |
| 产出 frontmatter | name/description/user-invocable:false/origin:auto-extracted |
name/description/origin:skill-learning/confidence |
⚠️ 字段不同但覆盖意图 |
1.4 行为差异具体例子
场景:会话中用户纠正了一次"用 async/await 而不是 callback"。
- ECC:用户运行
/learn-eval。LLM 识别出"用户纠正"类模式,起草 skill。5a checklist 逐条执行(grep、MEMORY.md 检查)。5b 给出 verdict,比如"Absorb intoerror-handling"。展示给用户确认,追加到已有 skill。 - 项目:runtimeObserver 每轮自动调
analyzeObservations,extractUserCorrections(sessionObserver.ts:32-59)用正则匹到"不要...用..."或"do not...use...",生成 instinct(confidence: 0.7),落到~/.claude/skill-learning/projects/<id>/instincts/personal/<id>.json。下一轮autoEvolveLearnedSkills把它和其它 instinct 一起聚类,可能生成 skill 草稿,走 overlap 决策,不弹用户确认。
1.5 对齐度评级
PARTIAL。
- 覆盖了 ECC 的"读会话/评估/决策/写入"四个阶段,但在决策依据(holistic verdict vs overlap 分数)、用户确认流(强制 vs 无)、改进迭代(一次 retry vs 无)、MEMORY.md 去重(有 vs 无)上有实质差异。
- 项目侧的 archive/delete 生命周期是 ECC
/learn-eval没有的额外能力。
2. /continuous-learning (v1)
2.1 ECC 侧行为摘要
ECC 源:skills/continuous-learning/SKILL.md、skills/continuous-learning/config.json、skills/continuous-learning/evaluate-session.sh。
- 触发:Stop hook,每次会话结束时运行
evaluate-session.sh。 - 输入判断:
min_session_length: 10(config.json)— 会话消息少于 10 条直接跳过。 - 处理流水(SKILL.md 第 20-27 行):
- 会话评估:消息数门槛。
- 模式检测:按
patterns_to_detect列表(error_resolution / user_corrections / workarounds / debugging_techniques / project_specific)。 - 技能提取:直接产出 skill md 文件到
~/.claude/skills/learned/。
- 没有 instinct 层。v1 是"session 结束 → 直接生成 skill"的单步流水。
- 配置字段:
min_session_length、extraction_threshold、auto_approve、learned_skills_path、patterns_to_detect、ignore_patterns。 - 置信度:无。
- 跨项目提升:无。
2.2 项目侧对应实现
项目没有 Stop hook 型的 v1 等价物。与之相关的入口是 ingestTranscript(src/services/skillLearning/observationStore.ts:181-198):
src/services/skillLearning/observationStore.ts:181-198ingestTranscript:从 JSONL transcript 文件读出 observations。src/commands/skill-learning/skill-learning.ts:42-57ingestcase:命令形式的调用。
即 v1 的"会话结束→读 transcript→提取模式"流,在项目侧等价于"手动跑 /skill-learning ingest <transcript.jsonl>"。
2.3 字段级对照
| 字段 / 维度 | ECC v1 | 项目 | 对齐 |
|---|---|---|---|
| 触发 | Stop hook 自动 | /skill-learning ingest 手动 |
⚠️ |
| 输入 | 当前会话消息流 | 外部 transcript.jsonl 路径 | ⚠️ |
| 会话长度门槛 | min_session_length: 10 |
无 | ❌ |
extraction_threshold |
medium(字符串) |
无对应 config;置信度阈值硬编码为 MIN_CONFIDENCE_TO_GENERATE_SKILL = 0.5(learningPolicy.ts:4) |
⚠️ |
auto_approve |
false default |
无;autoEvolveLearnedSkills 默认 auto |
❌ 项目直接 auto |
patterns_to_detect 列表 |
配置驱动(error_resolution 等 5 类) | 硬编码 4 类:extractUserCorrections / extractToolErrorResolutions / extractRepeatedToolSequences / extractProjectConventions(sessionObserver.ts:20-25) |
⚠️ 内容接近但不可配置 |
ignore_patterns 列表 |
配置驱动(simple_typos 等) | 无明确对应 | ❌ |
| 输出路径 | ~/.claude/skills/learned/ |
.claude/skills/<name> / ~/.claude/skills/<name>(skillGenerator.ts:62-75 getLearnedSkillPath) |
⚠️ 项目无"learned/"子目录 |
| instinct 层 | 无 | 有(instinctStore.ts + instinctParser.ts) |
额外能力,项目侧多一层 |
2.4 行为差异具体例子
场景:会话产生了 error_resolution 模式。
- ECC v1:会话结束时 Stop hook 跑
evaluate-session.sh,若消息≥10 触发,按extraction_threshold: medium判断"够重要",直接写~/.claude/skills/learned/<error-resolution-name>.md。过程不产出中间 instinct。 - 项目:用户必须跑
/skill-learning ingest <transcript.jsonl>;该命令走ingestTranscript→analyzeObservations→upsertInstinct(写 instinct 而不是直接 skill)。Skill 生成需要下一步/skill-learning evolve --generate。
2.5 对齐度评级
PARTIAL。
- 项目做了"更细"的分层(多了 instinct 层);ECC v1 是单步直达 skill。
- 自动触发(Stop hook)缺失,所有动作都要手动调命令。
- 配置化程度(min_session_length / patterns_to_detect / ignore_patterns)缺失。
3. /continuous-learning-v2
这是 ECC 体系中最核心的技能。逐维度深入对比。
3.1 ECC 侧行为摘要
ECC 源:
skills/continuous-learning-v2/SKILL.md(365 行,版本 2.1.0)skills/continuous-learning-v2/hooks/observe.sh(429 行 Shell)skills/continuous-learning-v2/scripts/instinct-cli.py(1426 行 Python)skills/continuous-learning-v2/scripts/detect-project.shskills/continuous-learning-v2/agents/observer.md(199 行)skills/continuous-learning-v2/agents/observer-loop.sh(272 行)skills/continuous-learning-v2/config.json
架构(SKILL.md:83-124 绘图):
Session Activity (in a git repo)
|--> Hooks capture prompts + tool use (100% reliable)
| + detect project context (git remote / repo path)
v
projects/<hash>/observations.jsonl
|
|--> Observer agent reads (background, Haiku)
v
PATTERN DETECTION
* User corrections / Error resolutions / Repeated workflows / Scope decision
|--> Creates/updates
v
projects/<hash>/instincts/personal/*.yaml + instincts/personal/*.yaml (GLOBAL)
|
|--> /evolve clusters + /promote
v
projects/<hash>/evolved/*.md + evolved/*.md
* commands/* / skills/* / agents/*
观察采集(hooks/observe.sh):
observe.sh:15HOOK_PHASE="${1:-post}":通过 shell 参数区分pre(PreToolUse)/post(PostToolUse)。observe.sh:22-28从 stdin 读 JSON,空则退出。observe.sh:60-76从 JSON 提cwd,然后用git -C <cwd> rev-parse --show-toplevel解到 repo root,导出CLAUDE_PROJECT_DIR。observe.sh:105-130五层过滤(Layer 1~5):- L1:
CLAUDE_CODE_ENTRYPOINT必须是cli或sdk-ts。 - L2:
ECC_HOOK_PROFILE=minimal跳过。 - L3:
ECC_SKIP_OBSERVE=1跳过。 - L4:有
agent_id字段(subagent session)跳过。 - L5:cwd 匹配
ECC_OBSERVE_SKIP_PATHS(默认含observer-sessions,.claude-mem)跳过。
- L1:
observe.sh:141source detect-project.sh:设置PROJECT_ID / PROJECT_NAME / PROJECT_ROOT / PROJECT_DIR。observe.sh:153-156自动清理:每天 purge 30 天前的observations-*.jsonl。observe.sh:160-207用 Python subprocess 解析 stdin JSON,提取tool_name/tool_input/tool_output/session_id/tool_use_id/cwd,event 根据HOOK_PHASE决定tool_start或tool_complete;输入输出各截 5000 字符。observe.sh:219-229秘密脱敏正则:api[_-]?key|token|secret|password|authorization|credentials?|auth+ 可选 auth scheme + 至少 8 位 token 内容,替换为[REDACTED]。observe.sh:234-241文件归档:>10MB 时 rename 到observations.archive/observations-<ts>-<pid>.jsonl(race-safe)。observe.sh:286-382lazy-start observer:若 config 启用但进程未起,用 flock/lockfile/mkdir 三种锁机制之一 nohup 启动start-observer.sh。observe.sh:387-426SIGUSR1 节流:每 20 次观察发一次 SIGUSR1 给 observer,防止 runaway parallel analysis。
项目识别(detect-project.sh,摘要 via instinct-cli.py:128-197 Python 等价物):
- 优先级:
CLAUDE_PROJECT_DIRenv >git rev-parse --show-toplevel。 - 项目 ID =
sha256(git_remote_url || project_root)[:12],12 字符。 - 注册表
~/.claude/homunculus/projects.json:{project_id: {name, root, remote, last_seen}},用fcntl.flock串行化读写(Python 实现)。
后台 observer(agents/observer.md + agents/observer-loop.sh):
- 模型:Haiku(
observer.md:5frontmatter)。 - 触发:启动条件
observer.enabled: true(config.json),默认false。 - 运行:
observer-loop.sh:258-271无限循环,每OBSERVER_INTERVAL_SECONDS跑一次analyze_observations;或被 SIGUSR1 打断(需 ≥ANALYSIS_COOLDOWN秒,默认 60s)。 - 空闲自退:
exit_if_idle_without_sessions(observer-loop.sh:70-84),IDLE_TIMEOUT_SECONDS默认 1800s。 - 分析样本:
observer-loop.sh:114-122用tail -n 500(可ECC_OBSERVER_MAX_ANALYSIS_LINES覆盖)限制 LLM payload。 - LLM 调用:
observer-loop.sh:192-194ECC_SKIP_OBSERVE=1 ECC_HOOK_PROFILE=minimal claude --model haiku --max-turns 10 --print --allowedTools "Read,Write" -p "<prompt>"。- 注意
ECC_SKIP_OBSERVE=1防止自己观察自己(self-loop guard)。
- 注意
- 分析完毕归档:
observer-loop.sh:219-221mv observations.jsonl → observations.archive/processed-<ts>-<pid>.jsonl。 - Windows 受
CLV2_IS_WINDOWS保护:默认跳过 Claude 分析,需ECC_OBSERVER_ALLOW_WINDOWS=true覆盖。 - LLM prompt 强约束(
observer-loop.sh:130-170):YAML frontmatter 必需、id(kebab-case)、trigger、confidence(按频次映射 3-5→0.5 / 6-10→0.7 / 11+→0.85)、domain枚举、scope默认project。明确禁止输出代码片段。
instinct 模型(SKILL.md:47-79 + observer.md:75-118):
- YAML 双 frontmatter 格式,正文 Markdown:
--- 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 ... ## Evidence ... - 5 个必备 frontmatter 字段:
id / trigger / confidence / domain / source,项目相关 2 个:scope+project_id+project_name。 - 存储位置:
~/.claude/homunculus/projects/<hash>/instincts/{personal,inherited}/<id>.yaml+~/.claude/homunculus/instincts/{personal,inherited}/<id>.yaml。
置信度(observer.md:137-148):
- 初始值按观察频次:1-2→0.3,3-5→0.5,6-10→0.7,11+→0.85。
- +0.05 per confirming,-0.1 per contradicting,-0.02 per week without observation(decay)。
- 阈值映射:0.3 Tentative / 0.5 Moderate / 0.7 Strong / 0.9 Near-certain(
SKILL.md:313-321)。
跨项目 promote(observer.md:150-157 + instinct-cli.py:881-1082):
- 门槛:同 ID 出现在 2+ 项目 + 均值 confidence ≥ 0.8。
_find_cross_project_instincts(instinct-cli.py:881-905)遍历PROJECTS_DIR下每个项目目录的instincts/{personal,inherited}/*.yaml,聚合同 ID。- 自动或手动,手动
/promote <id>,自动/promote无参。 - 提升后写到
~/.claude/homunculus/instincts/personal/<id>.yaml,scope 改为global,附加promoted_from/promoted_date。
pending instinct TTL(instinct-cli.py:55-60):
- 默认 30 天未 review 则删除。
- 存于
pending/子目录(~/.claude/homunculus/instincts/pending/+projects/<id>/instincts/pending/)。 - Observer 启动时跑一次
prune --quiet(observer-loop.sh:254-256)。
privacy / 脱敏(SKILL.md:350-355):
- Observations 只存本地。
- 只有 instincts(pattern)可导出,raw observations 不能。
observe.sh:219-229+observe.sh:266-276写入前做秘密脱敏。
3.2 项目侧对应实现
观察采集(src/services/skillLearning/runtimeObserver.ts):
runtimeObserver.ts:20-26initSkillLearning通过registerPostSamplingHook(runSkillLearningPostSampling)注册钩子。runtimeObserver.ts:28-50runSkillLearningPostSampling:- 跳过非
repl_main_thread查询(33 行),跳过agentId非空(34 行)。 - 解析 project(
resolveProjectContext(process.cwd()),35 行)。 - 从
context.messages中反推观察(observationsFromMessages,39 行)。 - 写 observation store(40 行)。
- 调
analyzeObservations、写 instinct store(45-47 行)。 - 调
autoEvolveLearnedSkills(49 行)。
- 跳过非
runtimeObserver.ts:69-135observationsFromMessages:遍历全部 messages,按消息 type 提取 user/assistant/tool_use/tool_result 块。- 特征:
- 已新增 tool-hook 优先路径(P0-4,
runtimeObserver.ts:52-68):若hasToolHookObservationsForTurn(sessionId, turn)返回 true,就复用readObservations()过滤source === 'tool-hook'的记录,跳过消息反推以避免双重计数。 - 但
toolEventObserver.ts:22-28的@todo注释明确写道:尚未 wire 到src/Tool.ts的公共 dispatch,目前 tool-hook 记录只由集成测试 / 未来的 tool middleware 主动写入。生产路径上仍以 post-sampling 反推为主。 - 时机仍是 post-sampling(模型响应之后),非真正的 Pre/PostToolUse hook。
- 无秘密脱敏(秘密脱敏由下游
observationStore.scrubObservation做)。
- 已新增 tool-hook 优先路径(P0-4,
已更新 @ 2026-04-17:P0-4 已完成接口层,P1-5 式的 tool dispatcher wiring 尚未发生。
秘密脱敏(src/services/skillLearning/observationStore.ts:65-118):
observationStore.ts:65-70SECRET_PATTERNS数组:/\b(?:sk|sk-ant|sk-proj|xox[baprs])-[A-Za-z0-9_-]{12,}\b/g, /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g, /\b(?:api[_-]?key|token|secret|password|authorization)\b\s*[:=]\s*["']?[^"',\s}]+/gi, /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/gi- 比 ECC 额外多了:
sk-*/ xoxb-* Slack token / email / Bearer token。 observationStore.ts:91-118scrubText+scrubObservation:字段级别脱敏 + 按 max_length 截断 + SHA256 contentHash。
项目识别(src/services/skillLearning/projectContext.ts):
projectContext.ts:43-101resolveProjectContext:- 优先级:
CLAUDE_PROJECT_DIRenv >git remote get-url origin>git rev-parse --show-toplevel>globalfallback。 - 项目 ID =
sha256(identity)[:16]加project-前缀(projectContext.ts:225-228),16 字符(ECC 是 12)。 - 注册表
<root>/projects.json(projectContext.ts:126-144),结构{version, updatedAt, projects: {id: record}}。 - 写注册表无文件锁(ECC Python 版用 fcntl)。
- 优先级:
- 存储路径:
~/.claude/skill-learning/projects/<id>/或<id>/global/(projectContext.ts:32-37)。- 目录名
skill-learning而非 ECC 的homunculus。
- 目录名
后台 observer / backend 接口:
- 后台进程仍不存在。项目内无独立 Haiku 分析进程,无 interval/cooldown/idle-timeout 机制。
- P1-1 完成 @ 2026-04-17:引入了 backend 接口层:
observerBackend.ts(71 行):ObserverBackend接口 +registry+setActiveObserverBackend+analyzeWithActiveBackend。- 环境变量
SKILL_LEARNING_OBSERVER_BACKEND可切换默认 backend。 heuristicObserverBackend(sessionObserver.ts:24-34heuristic analyze 四条规则重命名到 backend.analyze)作为默认实现。llmObserverBackend.ts(stub):预留 LLM backend 位置,尚未绑真实 LLM,接口name: 'llm',analyze 目前仍走 heuristic 兜底或返回空(详见文件)。
- 启发式规则(现包在
heuristicObserverBackend内)仍以:extractUserCorrections:正则匹配"不要 X 用 Y""do not X, use Y""should/must X"。extractToolErrorResolutions:滑窗找"tool_complete failure → 后续 5 条内同 toolName 的 tool_complete success"。extractRepeatedToolSequences:硬编码['Grep', 'Read', 'Edit']序列。extractProjectConventions:"项目约定|规范|必须|convention|always|must" 关键词。
- 仍缺真正的 LLM 语义分析(LLM backend 只立了接口,未接 Haiku)。仍无 5 层自我过滤。
instinct 格式(src/services/skillLearning/types.ts:57-72):
- JSON 文件(非 YAML),扩展名
.json(instinctStore.ts:61filter.json)。 - 字段:
interface Instinct { id: string; trigger: string; action: string; confidence: number; domain: InstinctDomain; source: InstinctSource; scope: SkillLearningScope; projectId?: string; projectName?: string; evidence: string[]; evidenceOutcome?: SkillObservationOutcome; createdAt: string; updatedAt: string; status: InstinctStatus; } - 与 ECC 对照:
- 多出
action(ECC 把 action 放 content body 的## Action)。 - 多出
createdAt / updatedAt / status。 - 多出
evidenceOutcome(P0-2 预留字段)。 - 少了 ECC 可选的
source_repo/imported_from(项目侧source只是枚举)。
- 多出
- 存储:
~/.claude/skill-learning/projects/<id>/instincts/personal/<id>.json(instinctStore.ts:23-32)。 instinctParser.ts:62-77buildInstinctId= kebab slug(48 char) + 10 char sha1 hash(与 ECC 的"人类可读 id"策略不同——ECC 由 Haiku 给出 id)。
置信度(src/services/skillLearning/instinctStore.ts:69-107 + instinctParser.ts:115-118):
- P0-2 完成 @ 2026-04-17:
upsertInstinct增量已改为 outcome-aware(instinctStore.ts:79-107):contradict→-0.1evidenceOutcome === 'failure'→-0.05- 其它情况(含 success / undefined)→
+0.05 - 通过
outcomeConfidenceDelta(incoming.evidenceOutcome)实现。
evidenceOutcome字段在normalizeInstinct合并时保留(instinctStore.ts:87)。- 仍无 decay(ECC
-0.02 / week)。 - 仍无初始值映射(ECC 按频次 0.3/0.5/0.7/0.85;项目侧初始值由 candidate 调用方写死)。
- 反向 instinct 识别:
isContradictingInstinct(instinctParser.ts:99-113)比较同 trigger 下avoid/prefer关键词翻转。 - 升档:
status: 'pending' → 'active'发生在confidence ≥ 0.8(instinctStore.ts:93-96)。
跨项目 promote(src/services/skillLearning/promotion.ts):
- 已更新 @ 2026-04-17(P2-1 完成)。
promotion.ts:32+findPromotionCandidates(instincts, minProjects=2, minConfidence=0.8):筛选函数保留。promotion.ts:68+新增checkPromotion(options):读取所有项目 instinct,筛选后写入 global scope 副本;同 session 幂等。runtimeObserver.ts:125在autoEvolveLearnedSkills末尾自动调用checkPromotion()。- 命令层:
skill-learning.ts:122-192新增promote [gap <key>|instinct <id>|<无参,列候选>]子命令。 - 与 ECC 对比:门槛阈值一致(2 项目 + 0.8 confidence);集成度基本补齐,不同点在于 ECC
/evolve本身会展示 promotion candidates,项目的展示走独立promote子命令。
命令面(src/commands/skill-learning/):
index.ts:8argumentHint已刷新到含promote|projects(P1-3 完成后)。skill-learning.ts:28-2168 个 case:status / ingest / evolve / export / import / prune / promote / projects。- P2-4 完成 @ 2026-04-17:
write-fixturecase 已移除(测试夹具迁至__tests__/直接函数调用)。 - P1-3 完成 @ 2026-04-17:新增
promote [gap <key>|instinct <id>](skill-learning.ts:122-192)+projects(skill-learning.ts:194-210,调listKnownProjects)。
pending instinct TTL:
instinctStore.ts:138-157prunePendingInstincts(maxAgeDays):已实现,但默认值来自调用方(skill-learning.ts:102默认 30 天)。- 无启动时自动 prune(ECC observer-loop 启动时自动跑一次)。
3.3 字段级对照表
| 维度 | ECC v2.1 | 项目侧 | 对齐 |
|---|---|---|---|
| 存储根目录 | ~/.claude/homunculus/ |
~/.claude/skill-learning/ |
⚠️ 名称不同 |
| 观察 hook 类型 | PreToolUse + PostToolUse(shell) | post-sampling(postSamplingHooks.ts) |
❌ 机制完全不同 |
| Hook 执行确定性 | 100%(hook 工具层) | 概率性(取决于 sampling 是否跑完) | ❌ |
| 观察记录粒度 | tool_start + tool_complete 成对 |
从 messages 反推,可能丢时序 | ⚠️ |
| 观察文件格式 | JSONL | JSONL | ✅ |
| 观察文件位置 | projects/<id>/observations.jsonl |
projects/<id>/observations.jsonl |
✅ |
| 观察字段 trigger / action | n/a(hook 不带语义) | n/a | ✅ |
| 观察字段 project_id | ✅ 12 字符 sha256 前缀 | ✅ 16 字符 sha256 前缀,带 project- 前缀 |
⚠️ 长度不同 |
| 观察字段 project_name | ✅ 基于 basename 或 remote | ✅ 基于 basename 或 remote | ✅ |
| 观察字段 timestamp | ✅ ISO-8601 Z | ✅ ISO-8601 Z | ✅ |
| 观察字段 session_id | ✅ 来自 Claude Code hook | ⚠️ 来自 context.sessionId 或 'runtime-session'(runtimeObserver.ts:73) |
⚠️ |
| 观察字段 input/output 截断长度 | 5000 字符 | 2000 字符(DEFAULT_MAX_FIELD_LENGTH,observationStore.ts:61) |
⚠️ |
| 秘密脱敏 | 单一 regex,含 auth scheme | 4 条 regex(sk-*, email, key=v, Bearer) | ⚠️ 机制不同 |
| 文件大小归档 | 10MB 阈值(observe.sh:149) |
1MB 阈值(observationStore.ts:62) |
⚠️ 项目更激进 |
| 旧观察 purge | 30 天(observe.sh:154) |
无自动 purge | ❌ |
| 后台 observer 进程 | 有(Haiku,独立 nohup) | 无 | ❌ |
| Observer 触发模式 | interval(5min 默认)+ SIGUSR1 | 每轮 post-sampling 内联 | ❌ 结构完全不同 |
| Observer 分析样本大小 | tail 500 行 | 全量 messages | ⚠️ 项目可能膨胀 |
| Observer 语义分析 | LLM(Haiku) | 正则启发式 | ❌ |
| Observer 自我过滤 | 5 层(entrypoint / profile / env / agent_id / path) | agentId 单层(runtimeObserver.ts:34) |
⚠️ 覆盖度低 |
| Windows 兼容性 | 默认跳过 LLM 分析,需手动启用 | 无 Windows 差异(全 TS 实现) | ⚠️ 不同的处理方式 |
| instinct 格式 | YAML(frontmatter + MD 正文) | JSON | ⚠️ 格式不同 |
| instinct id 生成 | LLM 给出(kebab-case) | slug(48)-sha1(10)(instinctParser.ts:62-77) |
⚠️ 项目更机械 |
| instinct 字段 trigger | ✅ 必需 | ✅ 必需 | ✅ |
| instinct 字段 action | ✅ 在正文 ## Action |
✅ 在 JSON 顶层 | ⚠️ 语义相同位置不同 |
| instinct 字段 confidence | ✅ 0.3~0.85 初始 | ✅ 任意 0~1 | ⚠️ 初始化策略不同 |
| instinct 字段 domain | ✅ 字符串(有建议枚举) | ✅ 严格枚举(InstinctDomain 7 种) |
⚠️ |
| instinct 字段 source | ✅ session-observation / inherited / auto-promoted / repo-analysis |
✅ session-observation / repo-analysis / imported(types.ts:23-26) |
⚠️ 项目少一类 |
| instinct 字段 scope | ✅ project / global |
✅ project / global |
✅ |
| instinct 字段 project_id / project_name | ✅ | ✅ | ✅ |
| instinct 字段 evidence | ✅ 正文 ## Evidence 列表 |
✅ evidence: string[] |
✅ |
| instinct 字段 createdAt/updatedAt | ❌ 无明确字段(仅 "Last observed" 描述) | ✅ | 额外 |
| instinct 字段 status | ❌(隐式,靠 confidence 阈值) | ✅ pending/active/stale/superseded/retired/archived(6 档) |
额外 |
| instinct 字段 evidenceOutcome | ❌ | ✅(P0-2 预留,目前未赋值) | 额外 |
| 置信度 +confirm | +0.05 | +0.05 | ✅ |
| 置信度 -contradict | -0.10 | -0.10 | ✅ |
| 置信度 decay | -0.02 / week | 无 | ❌ |
| 置信度 初始值映射 | 按观察频次 | 硬编码(多种值,视 extractor 而定) | ⚠️ |
| pending → active 阈值 | 隐式(0.5?0.7?未明确) | ≥ 0.8(instinctStore.ts:91) |
⚠️ |
| Pending TTL | 30 天(PENDING_TTL_DAYS),启动自动 prune |
30 天默认(prune --max-age),不自动 |
⚠️ |
| Pending 存储子目录 | instincts/pending/(instinct-cli.py:1217-1229) |
无独立 pending/,status: 'pending' 字段区分 |
⚠️ 物理布局不同 |
| 评进化触发 | /evolve 手动 + observer 后台 |
autoEvolveLearnedSkills 每轮自动(runtimeObserver.ts:49) |
⚠️ |
| 进化目标分类 | trigger keyword + workflow domain + cluster size | classifyEvolutionTarget(evolution.ts:40-52)基于正则 |
⚠️ 策略相似 |
| 进化目标 skill 产出 | ✅ evolved/skills/<name>/SKILL.md |
✅ .claude/skills/<name>/SKILL.md |
✅ |
| 进化目标 command 产出 | ✅ evolved/commands/<name>.md |
❌(evolution.ts:58-66 硬过滤 target === 'skill') |
❌ |
| 进化目标 agent 产出 | ✅ evolved/agents/<name>.md |
❌(同上) | ❌ |
| 跨项目 promote 门槛 | 2 项目 + 均值 ≥ 0.8 | 2 项目 + 均值 ≥ 0.8(promotion.ts:10) |
✅ 参数一致 |
| 跨项目 promote 接线 | /promote 命令 + /evolve 提示 + auto |
findPromotionCandidates 只是 helper,无调用方 |
❌ |
| scope 自动决策 | Haiku 按"是否普适"判断 | decideDefaultScope(learningPolicy.ts:76-82)基于 domain 白名单 |
⚠️ |
| 命令 status | /instinct-status → Python CLI |
/skill-learning status |
✅ |
| 命令 evolve | /evolve [--generate] |
/skill-learning evolve [--generate] |
✅ |
| 命令 export | /instinct-export + 过滤参数 |
/skill-learning export <path>,无过滤参数 |
⚠️ |
| 命令 import | /instinct-import + scope/dryrun/force/min-conf |
/skill-learning import <path>,无附加参数 |
⚠️ |
| 命令 promote | /promote [id] [--force] [--dry-run] |
缺 | ❌ |
| 命令 projects | /projects |
缺 | ❌ |
| 命令 prune | instinct-cli.py prune(隐式由 observer 启动触发) |
/skill-learning prune [--max-age] |
⚠️ 直接暴露命令 |
| 命令 write-fixture | n/a | 存在但不应在生产命令面 | 额外瑕疵 |
| privacy 观察本地化 | ✅ | ✅(无网络上报) | ✅ |
| privacy raw observations 不导出 | ✅(只允许 export instincts) | ⚠️ readObservations 可被 /skill-learning ingest 反读(但无直接 export 命令) |
⚠️ |
3.4 行为差异具体例子
例子 A:观察到"Grep → Read → Edit"序列 5 次
- ECC:
- 5 次 PreToolUse + 5 次 PostToolUse hook,共 ~30 条 JSONL 记录(每 tool 2 条),观察带成对
tool_start / tool_complete+ outcome。 - observer 后台 Haiku 分析 tail 500 行,发现
Grep→Read→Edit序列。 - Haiku 生成 YAML instinct 文件,id 由 LLM 起(如
grep-before-edit),confidence=0.7(6-10 次档),domain 由 LLM 判为workflow,scope 由 LLM 判为global(因是工具偏好,不限项目)。 - observation 文件 archive 走。
- 5 次 PreToolUse + 5 次 PostToolUse hook,共 ~30 条 JSONL 记录(每 tool 2 条),观察带成对
- 项目:
- 5 次 post-sampling hook,
observationsFromMessages从 context.messages 反推。每次触发重新处理全量 messages,可能产生同一 observation 的多条副本(已在 memory 中标注为 bug)。 extractRepeatedToolSequences硬编码['Grep', 'Read', 'Edit'],匹配计数 ≥ 2(默认)即触发。- 生成 JSON instinct,id =
when-changing-code-in-this-project-prefer-t-<sha1>,confidence=0.65(≥3 次档) 或 0.5,domain 硬编码workflow,scope 硬编码project(sessionObserver.ts:138)。 - observation 文件不 archive,继续追加。
- 5 次 post-sampling hook,
例子 B:同一 instinct 在 2 个不同项目中都达到 confidence 0.85
- ECC:
/evolve会显示 promotion candidates。- 用户运行
/promote <id>或/promote(auto)。 - instinct-cli 扫
PROJECTS_DIR找出该 id 在 2+ 项目,avg ≥ 0.8,写入~/.claude/homunculus/instincts/personal/<id>.yaml,frontmatter 改scope: global,附加promoted_from / promoted_date。
- 项目:
- 无命令面暴露 promote。
findPromotionCandidates只能由测试代码调用,运行时不触发。- 该 instinct 永远留在两个 project scope 下,不会提升。
例子 C:中文 prompt 触发学习
- ECC:Haiku LLM 有跨语言理解能力,可以识别"以后我们的 SDK 调用都要加超时"这类中文指导为 instinct。
- 项目:
extractUserCorrections的中文正则(?:不要|别|不应(?:该)?|不要再)可命中"不要"但命中面窄;extractProjectConventions含"项目约定|规范|必须|convention|always|must"关键词;非这些关键词的中文指导全部丢弃(例如"以后我们的 SDK 调用都要加超时"——"以后"不在 regex 里)。
3.5 对齐度评级
PARTIAL(结构对齐,语义和机制差异大)。
- 数据结构层面(types、存储布局、scope 概念)基本一一对应。
- 语义处理层面(LLM observer vs 正则规则)根本不同。
- 命令面缺 2 个(promote / projects),多 1 个(write-fixture)。
- 置信度缺 decay。
- 进化三路缺 2 路(command / agent)。
4. /skill-create
4.1 ECC 侧行为摘要
ECC 源:commands/skill-create.md。
- 触发:用户手动
/skill-create。 - 输入:本地 git 仓库历史。
- 处理流水(该文件 27-103 行):
git log --oneline -n 200 --name-only --pretty=format:...收集 commit + 文件变化。- 识别 5 类模式:commit convention 正则、文件共同变化、workflow 序列、架构(folder/命名)、testing pattern。
- 生成
SKILL.md,frontmatter 含name / description / version / source: local-git-analysis / analyzed_commits。 - 可选
--instincts:同时生成 instinct YAML。
- 置信度:生成的 instinct 默认 0.7~0.8,具体由分析代码决定(该 skill 文件只给模板)。
- 产出:
.claude/skills/<repo>-patterns/SKILL.md,可选 instinct YAML。 - 关联 GitHub App:
github.com/apps/skill-creator(advanced features)。
4.2 项目侧对应实现
不存在。项目内没有基于 git 历史的批量 skill 生成路径。
最接近的是:
src/services/skillLearning/skillGenerator.ts:17-43generateSkillDraft:从 instinct 集合生成 skill,不是从 git 历史。- 入口只能是 runtime observer → instinct → evolve → skill,无"一次性扫 git 批量生成"路径。
4.3 字段级对照
| 字段 | ECC | 项目 | 对齐 |
|---|---|---|---|
| 输入源 | git log | 无 | ❌ |
| 批量生成 | 一次扫 N commit 产多个 skill | 无 | ❌ |
| commit convention 检测 | 有 | 无 | ❌ |
| 文件共同变化检测 | 有 | 无 | ❌ |
| 架构模式提取 | 有 | 无 | ❌ |
| Test pattern 检测 | 有 | 无 | ❌ |
--instincts 选项 |
有 | 无 | ❌ |
| GitHub App 对接 | 有 | 无 | ❌ |
4.4 行为差异具体例子
场景:在一个 200-commit 的 TypeScript 项目中初次启用学习系统。
- ECC:
/skill-create用 15 分钟扫 git log,生成my-app-patterns/SKILL.md(含 commit 规范、目录结构、test 框架),附带 5~10 条 instinct yaml。用户在第一次使用时就能享受到"本项目 convention 已导入"的体验。 - 项目:无此能力。必须靠 runtime observer 在多轮使用中逐条累积 instinct,很长时间才能达到 ECC 初始化后的密度。
4.5 对齐度评级
NONE。项目完全没有这个能力。
5. /evolve
5.1 ECC 侧行为摘要
ECC 源:commands/evolve.md + scripts/instinct-cli.py:765-874。
- 触发:用户
/evolve[--generate]。 - 输入:所有 instinct(项目 + 全局,项目优先)。
- 处理流水:
- 按 domain / trigger 聚类(
instinct-cli.py:794-802)。 - 筛 cluster ≥ 2 作为 skill candidate(
instinct-cli.py:804-815);排序。 - 筛 workflow domain 且 confidence ≥ 0.7 作为 command candidate(
instinct-cli.py:837)。 - 筛 cluster ≥ 3 且 avg conf ≥ 0.75 作为 agent candidate(
instinct-cli.py:850)。 - 同时显示 promotion candidates(
_show_promotion_candidates,instinct-cli.py:908-941)。 --generate时分三路写:skills//SKILL.md、commands/.md、agents/.md(_generate_evolved,instinct-cli.py:1139-1210)。
- 按 domain / trigger 聚类(
- 阈值:
- skill cluster ≥ 2
- command workflow + conf ≥ 0.7
- agent cluster ≥ 3 + avg conf ≥ 0.75
5.2 项目侧对应实现
已更新 @ 2026-04-17 — P0-3 已完成,三路 generator 全部接入运行时。
入口:
src/commands/skill-learning/skill-learning.ts:62-87evolvecase(注意skill-learningCLI 当前仍只调generateSkillCandidates,command/agent 生成走的是 runtime 的autoEvolveLearnedSkills;命令面接入 command/agent 属 P1-3 范围)。src/services/skillLearning/evolution.ts:1-166:clusterInstincts(32-57 行):按${domain}:${normalizedTrigger(trigger)}聚类,过滤length >= 2 || confidence >= 0.8。classifyEvolutionTarget(59-77 行):文本匹配 regexuser asks|explicitly request|command|run→command;length >= 4 && /(debug|investigate|research|multi-step)/→agent;其余 →skill。generateSkillCandidates(83-99 行):过滤target === 'skill'+shouldGenerateSkillFromInstincts。- 新增
generateCommandCandidates(101-117 行):过滤target === 'command',调commandGenerator.generateCommandDraft。 - 新增
generateAgentCandidates(119-135 行):过滤target === 'agent',调agentGenerator.generateAgentDraft。 - 新增
generateAllCandidates(137-156 行):一次返回三类LearnedArtifactDraftunion。
src/services/skillLearning/commandGenerator.ts+src/services/skillLearning/agentGenerator.ts:对齐skillGenerator形状,分别产.claude/commands/<slug>.md/.claude/agents/<slug>.md。src/services/skillLearning/skillLifecycle.ts:63-80:compareExistingArtifacts(kind, draft, roots)泛化出kind: 'skill' | 'command' | 'agent',供 skill/command/agent 三路复用。src/services/skillLearning/runtimeObserver.ts:84-122autoEvolveLearnedSkills:- skill 路径保留 lifecycle decide / apply(90-100 行)。
- command 路径:调
compareExistingArtifacts('command', ...)后writeLearnedCommand(102-111 行),若已存在则跳过。 - agent 路径:调
compareExistingArtifacts('agent', ...)后writeLearnedAgent(113-122 行),若已存在则跳过。
5.3 字段级对照
| 字段 | ECC | 项目 | 对齐 |
|---|---|---|---|
| 聚类键 | trigger normalization(去除 when/creating/writing 等) |
${domain}:${trigger ASCII only 前6词} |
⚠️ 项目强制 domain 分组 |
| skill cluster 阈值 | ≥2 | ≥2 或 conf ≥0.8 | ✅ 基本一致 |
| command 识别 | workflow domain + conf ≥ 0.7 | trigger text 含 user asks / command / run |
⚠️ 机制不同 |
| agent 识别 | cluster ≥ 3 + avg conf ≥ 0.75 | length ≥ 4 + regex debug/investigate/research/multi-step |
⚠️ |
| Promotion 展示 | 自动展示 | 无 | ❌ |
--generate skill 输出 |
evolved/skills/<name>/SKILL.md |
.claude/skills/<name>/SKILL.md(project scope) 或 ~/.claude/skills/(global) |
⚠️ 路径不同 |
--generate command 输出 |
evolved/commands/<name>.md |
✅ .claude/commands/<name>.md(commandGenerator.ts + runtimeObserver.ts:102-111,P0-3 完成) |
✅ |
--generate agent 输出 |
evolved/agents/<name>.md |
✅ .claude/agents/<name>.md(agentGenerator.ts + runtimeObserver.ts:113-122,P0-3 完成) |
✅ |
| 生成文件 frontmatter | 含 evolved_from: [instinct ids] 列表 |
含 sourceInstinctIds 字段(types.ts:78)落到 draft 但不进 frontmatter(需看 skillGenerator.buildSkillContent) |
⚠️ |
| 生成 agent frontmatter model | sonnet 写死(instinct-cli.py:1198) |
需读 agentGenerator.ts 看 frontmatter 约定 |
⚠️ |
5.4 行为差异具体例子
已更新 @ 2026-04-17。场景:10 条 instinct,其中 4 条触发词含"debug"且 domain=debugging。
- ECC:
/evolve --generate会生成evolved/agents/debug-*-agent.md,frontmattermodel: sonnet。 - 项目:
classifyEvolutionTarget识别为agent,generateAgentCandidates现在过滤并调generateAgentDraft;runtimeObserver.autoEvolveLearnedSkills会在.claude/agents/下通过compareExistingArtifacts('agent', draft, roots)判断无重名后调writeLearnedAgent(draft)实际落盘。 - 仍存差异:
/skill-learning evolve --generate命令层只生成 skill(skill-learning.ts:62-87)。Runtime 每轮autoEvolveLearnedSkills会走三路,但命令入口尚未对称暴露(属 P1-3 范围)。
5.5 对齐度评级
已更新 @ 2026-04-17:PARTIAL → FULL(runtime 层);命令层仍 PARTIAL。
- 分类入口和阈值思路接近(无变化)。
- 三路 generator 已落地:skill / command / agent 在
autoEvolveLearnedSkills都会写文件。 - 命令入口仍只对 skill 输出(
skill-learning.ts:62-87),属 P1-3 覆盖范围。 - Promotion candidates 在 evolve 流中仍不展示(属 P2-1 覆盖范围)。
6. /instinct-status
6.1 ECC 侧行为摘要
ECC 源:commands/instinct-status.md + instinct-cli.py:397-496。
- 触发:用户
/instinct-status。 - 输入:项目 instinct + 全局 instinct,去重(项目优先)。
- 输出:
- 头部:总数、项目名/id、项目 instincts 数、全局 instincts 数(
cmd_status第 413-420 行)。 - 分 scope + 按 domain 分组打印(
_print_instincts_by_domain,第 467-495 行)。 - 每条显示 confidence bar(█/░ 10 字符)、百分数、id、scope tag、trigger、action 首行。
- Observations 数(读 JSONL 行数)。
- Pending instinct 数 + 5+ 告警 + 到期警告(7 天内)(第 443-461 行)。
- 头部:总数、项目名/id、项目 instincts 数、全局 instincts 数(
6.2 项目侧对应实现
src/commands/skill-learning/skill-learning.ts:28-41:
case 'status': {
const [observations, instincts] = await Promise.all([
readObservations(options),
loadInstincts(options),
])
return {
type: 'text',
value: [
`Skill Learning status for ${project.projectName} (${project.projectId})`,
`Observations: ${observations.length}`,
`Instincts: ${instincts.length}`,
].join('\n'),
}
}
只输出 3 行文本,无分组、无 confidence bar、无 pending 统计。
6.3 字段级对照
| 输出字段 | ECC | 项目 | 对齐 |
|---|---|---|---|
| 项目名 + id | ✅ | ✅ | ✅ |
| 项目 instincts 总数 | ✅ 分类 | ✅ 合计 | ⚠️ |
| 全局 instincts 总数 | ✅ 分类 | ❌ 合并 | ❌ |
| Observations 总数 | ✅ | ✅ | ✅ |
| 按 domain 分组 | ✅ | ❌ | ❌ |
| Confidence bar | ✅ █░ ASCII bar | ❌ | ❌ |
| Trigger / action 展示 | ✅ | ❌ | ❌ |
| Pending instincts 计数 | ✅ | ❌ | ❌ |
| Pending 到期警告 | ✅ 7 天内 | ❌ | ❌ |
6.4 行为差异具体例子
ECC /instinct-status 输出:
============================================================
INSTINCT STATUS - 12 total
============================================================
Project: my-app (a1b2c3d4e5f6)
Project instincts: 8
Global instincts: 4
## PROJECT-SCOPED (my-app)
### WORKFLOW (3)
███████░░░ 70% grep-before-edit [project]
trigger: when modifying code
action: Search with Grep, confirm with Read, then Edit
...
------------------------------------------------------------
Observations: 142 events logged
...
Pending instincts: 3 awaiting review
Expiring within 7 days:
- ephemeral-pattern-xyz (2d remaining)
项目 /skill-learning status 输出:
Skill Learning status for my-app (project-abc123...)
Observations: 142
Instincts: 12
信息密度相差数量级。
6.5 对齐度评级
PARTIAL(功能在,展示简陋)。
- 核心数据(observations、instincts 总数)一致。
- 展示层(分组、confidence bar、pending、domain 分类)全部缺失。
7. /instinct-import
7.1 ECC 侧行为摘要
ECC 源:commands/instinct-import.md + instinct-cli.py:502-685。
- 触发:
/instinct-import <file-or-url> [--dry-run] [--force] [--min-confidence 0.7] [--scope project|global]。 - 输入:本地 YAML 文件或 HTTPS URL。
- 处理:
- fetch(本地或
urllib.request.urlopen,第 514-532 行)。 - 解析(
parse_instinct_file,第 266-317 行 YAML frontmatter 风格)。 - 去重(按 ID,source 内取最高 confidence,第 554-560 行)。
- 三分类:NEW / UPDATE(import > existing conf) / SKIP(existing ≥ import)。
--min-confidence过滤。--dry-run只显示。- 写入
<scope>/inherited/<source-stem>-<ts>.yaml,删除被 update 替换的旧文件(cross-scope 保护,第 629-640 行)。 - source 字段置
inherited,附加imported_from/project_id/project_name/source_repo(可选)。
- fetch(本地或
7.2 项目侧对应实现
src/commands/skill-learning/skill-learning.ts:89-96:
case 'import': {
const input = parts[1]
if (!input) return { type: 'text', value: 'Usage: /skill-learning import <instincts.json>' }
const instincts = await importInstincts(input, options)
return { type: 'text', value: `Imported ${instincts.length} instincts.` }
}
底层 instinctStore.ts:126-136:
export async function importInstincts(inputPath, options) {
const parsed = JSON.parse(await readFile(inputPath, 'utf8')) as StoredInstinct[]
const saved: StoredInstinct[] = []
for (const instinct of parsed) {
saved.push(await upsertInstinct(normalizeInstinct(instinct), options))
}
return saved
}
7.3 字段级对照
| 维度 | ECC | 项目 | 对齐 |
|---|---|---|---|
| 输入格式 | YAML | JSON | ⚠️ 格式不同 |
| 从 URL 导入 | ✅ http:///https:// |
❌ 仅 readFile |
❌ |
--dry-run |
✅ | ❌ | ❌ |
--force |
✅ 跳过 prompt | ❌ 本就无 prompt | ⚠️ |
--min-confidence |
✅ | ❌ | ❌ |
--scope project|global |
✅(目标 scope 控制) | ⚠️ 由 options.scope 决定,无 CLI 参数 | ❌ |
| 去重策略 | 按 ID 保留最高 confidence;existing ≥ import → skip | upsertInstinct 每条都 merge(可能叠 confidence) |
⚠️ 语义不同 |
| source 字段 | 写 inherited |
保留 import 原值 | ❌ |
附加 imported_from |
✅ | ❌ | ❌ |
| 写入位置 | <scope>/inherited/<source>-<ts>.yaml |
<scope>/personal/<id>.json(instinctStore.ts:28-31) |
⚠️ 无 inherited 子目录 |
| 旧文件清理(cross-scope 保护) | ✅ | ❌ | ❌ |
7.4 行为差异具体例子
场景:团队 lead 分享 team-instincts.yaml 里有 8 条新 instinct + 1 条同 ID 但 confidence 更高的。
- ECC:
/instinct-import team-instincts.yaml→ 显示 NEW(8)/UPDATE(1)/SKIP(0) → y 确认 → 写inherited/team-instincts-<ts>.yaml,删旧文件,新 instinct frontmatter 带source: inherited, imported_from: "team-instincts.yaml"。 - 项目:
/skill-learning import team-instincts.json(假设转成 JSON) →upsertInstinct对 9 条都走 merge → 返回"Imported 9 instincts." 无摘要。同 ID 的那条会叠 evidence 并增 confidence +0.05,而非"替换成更高的"。
7.5 对齐度评级
PARTIAL(基本 I/O 能通,语义差异大)。
8. /instinct-export
8.1 ECC 侧行为摘要
ECC 源:commands/instinct-export.md + instinct-cli.py:692-758。
- 触发:
/instinct-export [--domain X] [--min-confidence N] [--output file] [--scope project|global|all]。 - 输入:按 scope 加载 instinct(
load_project_only_instincts/ global-only /load_all_instincts)。 - 过滤:
--domain、--min-confidence。 - 输出:YAML 多段 frontmatter(第 722-740 行),含
id / trigger / confidence / domain / source / scope / project_id / project_name / source_repo可选字段,和 Markdown 正文。 - 无 --output 时打印到 stdout。
8.2 项目侧对应实现
src/commands/skill-learning/skill-learning.ts:84-88:
case 'export': {
const output = parts[1] ?? 'skill-learning-instincts.json'
await exportInstincts(output, options)
return { type: 'text', value: `Exported instincts to ${output}` }
}
底层 instinctStore.ts:116-124:
export async function exportInstincts(outputPath, options) {
const instincts = await loadInstincts(options)
await mkdir(dirname(outputPath), { recursive: true })
await writeFile(outputPath, `${JSON.stringify(instincts, null, 2)}\n`)
return instincts
}
8.3 字段级对照
| 维度 | ECC | 项目 | 对齐 |
|---|---|---|---|
| 输出格式 | YAML(多段 frontmatter + MD) | JSON(数组) | ⚠️ |
--domain 过滤 |
✅ | ❌ | ❌ |
--min-confidence 过滤 |
✅ | ❌ | ❌ |
--scope 过滤 |
✅ | ❌ 由 options.scope 决定 | ❌ |
| 默认输出目标 | stdout | 文件 skill-learning-instincts.json |
⚠️ |
| 文件头注释(generated time / count) | ✅ | ❌ | ❌ |
| 不含 raw observation | ✅ | ✅ | ✅ |
8.4 行为差异具体例子
- ECC:
/instinct-export --scope project --domain testing --min-confidence 0.7 --output team-test-instincts.yaml→ 3 条 YAML 段。 - 项目:
/skill-learning export out.json→ 全量 JSON 数组,无过滤。
8.5 对齐度评级
PARTIAL(能导出,无过滤)。
9. swarm-auto-evolve(ECC 侧无独立技能,实为 observer agent + /evolve + /promote 的运行时组合)
9.1 ECC 侧行为摘要
ECC 插件中没有命名为 swarm-auto-evolve 的独立 skill。在 ECC 源树中 swarm 词仅出现在:
commands/sessions.md:19:"Use/sessions infowhen you need operator-surface context for a swarm: branch, worktree path, and session recency"(讲 swarm 会话的运维视图)。scripts/orchestrate-codex-worker.sh:58-59:"You are one worker in an ECC tmux/worktree swarm"(tmux 多 worktree 编排)。
这两处都与 skill learning 无关。
团队 lead 提到的"swarm-auto-evolve"在 ECC 体系内最合理的映射是 "自动化演进链路",即:
observe.sh 自动观察 → observer-loop.sh 后台定时 Haiku 分析 → observer 自动写 instinct → /evolve 聚类(--generate 写 skill/cmd/agent) → /promote 跨项目提升。
这是 ECC v2.1 的"观察到产出"闭环。关键属性:
- 自动触发:
observe.sh由 Hook 机制每 tool 调用都跑。 - 后台处理:
observer-loop.sh独立 nohup 进程。 - Haiku 分析:成本友好的 LLM 做模式识别。
- 节流/去重:SIGUSR1 每 20 次才发一次;flock 锁防重入;
ANALYSIS_COOLDOWN60s。 - 自我保护:5 层过滤防自己观察自己;
ECC_SKIP_OBSERVE环境变量。 - 存档归档:每次分析后
mv observations.jsonl → observations.archive/processed-<ts>.jsonl。 - 闲时退出:
IDLE_TIMEOUT_SECONDS30 分钟无活动自退。 - 手动覆盖:
/promote、/evolve --generate用户可显式触发。
9.2 项目侧对应实现
项目没有独立的后台 daemon。等价的"自动演进"由 runtimeObserver.runSkillLearningPostSampling(runtimeObserver.ts:28-50)每轮主动触发:
- Post-sampling hook 触发(每次 LLM 回复完成后)。
- 从 messages 反推 observations,写入 observationStore。
analyzeObservations(启发式)直接同步跑出 instinct。upsertInstinct写入。autoEvolveLearnedSkills(runtimeObserver.ts:52-67) — 每轮都跑:loadInstincts(全量读所有 instinct)。generateSkillCandidates(只 skill 目标)。compareExistingSkills→decideSkillLifecycle→applySkillLifecycleDecision。
没有 promote 自动触发。findPromotionCandidates(promotion.ts:9-43)不在此链路中。
9.3 字段级对照
| 维度 | ECC 自动演进链 | 项目 autoEvolveLearnedSkills |
对齐 |
|---|---|---|---|
| 触发频率 | 每 tool 调用有 observe;observer 每 5min 分析 | 每 LLM 轮有 observe + analyze + evolve | ⚠️ 粒度不同 |
| 执行线程 | 独立后台 nohup | 主线程内联 | ❌ 进程模型不同 |
| 分析模型 | Haiku LLM | 正则启发式 | ❌ |
| 自动 write skill | --generate 显式 + observer 自动写 instinct |
自动 lifecycle decide + write | ⚠️ 更激进 |
| 自动 write command | 有(_generate_evolved) |
❌(evolution.ts:63 filter skill) |
❌ |
| 自动 write agent | 有 | ❌ | ❌ |
| 自动 promote | /promote 或 observer 提示,不真自动写 |
❌ | ⚠️ ECC 本身也偏手动 |
| 冷却/节流 | SIGUSR1 每 20 次;cooldown 60s | ❌ 每轮都全量 | ❌ |
| 去重(session-level) | archive processed file | 每轮全量重处理 | ❌ |
| 自我观察防护 | 5 层(env/profile/agent_id/path/entrypoint) | 1 层(agent_id) | ⚠️ |
| 空闲退出 | 30min idle → process exit | n/a(进程绑 CLI 生命周期) | 不适用 |
| 手动覆盖 | /promote、/evolve --generate、/instinct-import |
/skill-learning evolve --generate |
⚠️ |
9.4 行为差异具体例子
场景:用户在 2 小时内与 Claude Code 交互 50 轮,每轮涉及 3~5 个 tool 调用。
- ECC:
- Hook 跑 200
300 次,产 300600 条 observations JSONL。 - Observer 每 5 分钟或 SIGUSR1(被节流到 ~15 次)触发分析。
- 后台 Haiku 分析 tail 500 行,生成若干 instinct。
- 分析后 observation archive。
- 用户某一刻跑
/evolve --generate把 cluster 转成 skill/cmd/agent;跑/promote把跨项目的提升到 global。
- Hook 跑 200
- 项目:
- Post-sampling hook 跑 50 次。
- 每次都:全量 messages → 反推 observations → 全量 analyze → upsert instinct → full evolve + lifecycle decide。
- 可能生成冗余 observation(同一消息反复反推),可能生成重复 instinct(id 相同但 evidence 增长)。
- 生成的只可能是 skill,不生成 command/agent。
- 2 小时内 50 轮自动 IO 密集,已在 memory 中标注性能 bug。
9.5 对齐度评级
GAP(无 ECC 自动演进链的成熟度)。
- 有"自动"形式(每轮触发),无"自动"实质(节流、分析质量、三路输出、跨项目提升)。
- 项目结构更简单(主线程内联),但缺多项关键特性。
最大差距总结
按对齐度严重性排序,以下是与 ECC v2.1 的 5 条最大差距:
差距 1:观察机制仍以 "post-sampling 反推" 为主,tool hook 接口已立但未 wire 到 dispatcher
已更新 @ 2026-04-17(P0-4 已完成,作为接口层)。
- ECC:PreToolUse + PostToolUse shell hook,每 tool 调用产成对 JSONL(
observe.sh:15,observe.sh:172)。100% 覆盖。 - 项目现状:
registerPostSamplingHook(runtimeObserver.ts:38)仍是主要入口。- 但
runSkillLearningPostSampling(runtimeObserver.ts:52-68)现在先查hasToolHookObservationsForTurn(sessionId, turn)(toolEventObserver.ts:47-52);命中就跳过消息反推,复用 tool-hook 观察。 toolEventObserver.ts:22-28@todo明确写:尚未 wire 到src/Tool.ts公共 dispatch。生产路径上hasToolHookObservationsForTurn默认返回 false,所以 fallback 路径仍是常态。
- 剩余差距:需要把
recordToolStart/recordToolComplete/recordToolError植入到src/Tool.ts的主 dispatch,才能真正让 tool-hook 路径生效。 - 涉及任务:P0-4 接口层已完成;后续 tool dispatcher wiring 不在现有 P*/META-* 任务列表中(若 lead 需要,建议新开 task)。
差距 2:模式检测默认仍是正则启发式,LLM backend 仅立接口未接模型
已更新 @ 2026-04-17(P1-1 已完成,接口 + stub)。
- ECC:Haiku 独立进程,
--max-turns 10跑 prompt 分析(observer-loop.sh:192-194)。可识别跨语言、跨工具序列的高层语义。 - 项目现状:
observerBackend.ts(71 行)定义ObserverBackend接口 + registry,可通过SKILL_LEARNING_OBSERVER_BACKENDenv 切换。heuristicObserverBackend(sessionObserver.ts:24-34)包裹四条启发式规则,作为默认。llmObserverBackend.ts:LLM backend stub,接口已注册但未绑真实 LLM。
- 剩余差距:LLM backend 的真实实现(调 Haiku 或其它模型)未落地。运行时默认仍走 heuristic。
- 涉及任务:P1-1 已完成接口;真 LLM 实现不在现有任务列表。
差距 3:进化三路已打通(skill + command + agent)
已更新 @ 2026-04-17(P0-3 已完成):从 GAP 升为 FULL(runtime 层)/ PARTIAL(命令层)。
- ECC:
_generate_evolved(instinct-cli.py:1139-1210)三路独立 generator,分别写evolved/{skills,commands,agents}/。 - 项目现状:
evolution.ts:83-99generateSkillCandidates、101-117generateCommandCandidates、119-135generateAgentCandidates、137-156generateAllCandidates(一次返回 union)。commandGenerator.ts+agentGenerator.ts分别实现generateCommandDraft/generateAgentDraft和writeLearnedCommand/writeLearnedAgent。skillLifecycle.ts:63-80compareExistingArtifacts(kind, ...)泛化,供 skill/command/agent 复用。runtimeObserver.ts:90-122autoEvolveLearnedSkills三路都跑:skill 走 lifecycle decide/apply,command/agent 走"若无重名就写盘"。
- 剩余差距:
/skill-learning evolve --generate命令行入口只调 skill(skill-learning.ts:62-87),命令层 command/agent 仍需 P1-3 范围后续补。 - 涉及任务:P0-3 完成;命令层对齐由 P1-3 完成。
差距 4:跨项目 promote 已接入运行时
已更新 @ 2026-04-17(P2-1 已完成):从 ❌ 升为 ✅。
- ECC:
/promote命令 +/evolve自动展示 candidates;门槛 2 项目 + 0.8 avg。 - 项目现状:
promotion.ts:68+新增checkPromotion(options)函数,使用findPromotionCandidates(门槛不变)筛选后写全局 instinct 副本。runtimeObserver.ts:125在autoEvolveLearnedSkills尾部调用checkPromotion()。- 测试
promotion.test.ts:100-119验证 "同一 session 内幂等"。 - 命令面
skill-learning.ts:122-192暴露promote [gap|instinct]子命令。
- 剩余差距:
/skill-learning evolve命令执行时 ECC 行为是同时展示 promotion candidates(text 展示而非写入);项目的promote子命令 + 自动 checkPromotion 是两条分离流。 - 涉及任务:P2-1 完成。
差距 5:首次 gap 即写 draft 的风险已解除(P0-1 已完成)
已更新 @ 2026-04-17(P0-1 已完成):从 PARTIAL → FULL。
- ECC:观察为先 → 满足频次/置信度门槛才聚类生成 skill。首次未匹配 prompt 不会产生 skill 文件。
- 项目现状:
SkillGapRecord.status为 4-态:pending / draft / active / rejected(types.ts:3)。- 默认
status是pending(skillGapStore.ts:93),首次recordSkillGap不再写 draft 文件。 shouldPromoteToDraft(skillGapStore.ts:184-188):count >= DRAFT_PROMOTION_COUNT(=2) || isStrongReusableSignal(prompt)。shouldPromoteToActive(skillGapStore.ts:190-196):需gap.draft存在且满足count >= ACTIVE_PROMOTION_COUNT(=4) || draftHits >= ACTIVE_PROMOTION_DRAFT_HITS(=2)。recordDraftHit(skillGapStore.ts:152-176)真实由prefetch.ts:206-212写入。rejectSkillGap(skillGapStore.ts:200+)支持用户显式否决。
- 剩余差距:
isStrongReusableSignal(skillGapStore.ts:198-202)仍存在——一次强信号 prompt 会跳过 pending 直接变 draft(不再变 active)。比 "只看 count" 更激进;但风险从 "一句话 → active skill" 降为 "一句话 → draft"。 - 涉及任务:P0-1 完成。
附录:可视化对比(Mermaid)
本附录含三张 Mermaid 图,基于 Task #1~#11 全部落地后的代码状态(锚点:
runtimeObserver.ts:35-139、evolution.ts:83-156、skillGenerator.ts:14-95、skillLifecycle.ts:63-80、skillGapStore.ts:88-216、instinctStore.ts:79-107、promotion.ts:68+、observerBackend.ts:1-71、toolEventObserver.ts:1-151、skill-learning.ts:28-216、localSearch.ts:158-208、prefetch.ts:206-212)。阅读时建议配合"能力全景矩阵"和"最大差距总结"对照。
- 图 1 = ECC 8 能力(+ swarm-auto-evolve)与项目实现的 1:1 对齐矩阵。
- 图 2 = 项目侧端到端闭环流程图(SEARCH → AUTO-LOAD → GAP → LEARN → EVOLVE → PROMOTE)。
- 图 3 = ECC v2.1 参考架构速写,供读图 1 时交叉对照。
图 1:ECC ↔ 项目 1:1 对齐矩阵
ECC 8 个能力(再加 "swarm-auto-evolve" 解作 observer+/evolve+/promote 链路)与本项目一对一对应。连线的线型 + 颜色代表对齐度:实线绿 = FULL,虚线橙 = PARTIAL,点线红 = GAP,粗虚线灰 = NONE。冷色为 ECC,暖色为项目。
flowchart LR
classDef ecc fill:#1e3a5f,stroke:#4a7fb0,color:#fff
classDef proj fill:#5f3a1e,stroke:#b07f4a,color:#fff
classDef none fill:#444,stroke:#888,color:#fff
subgraph ECC["ECC v2.1 能力"]
direction TB
E1["/learn-eval<br/>checklist + 4-verdict<br/>(Save/Improve/Absorb/Drop)"]
E2["/continuous-learning v1<br/>Stop hook → skill md"]
E3["/continuous-learning-v2<br/>Pre/PostToolUse hook +<br/>Haiku observer + instinct"]
E4["/skill-create<br/>git log → SKILL.md"]
E5["/evolve<br/>skill + command + agent<br/>三路 --generate"]
E6["/instinct-status<br/>confidence bar + domain 分组"]
E7["/instinct-import<br/>YAML + URL + filters"]
E8["/instinct-export<br/>YAML + filters"]
E9["swarm-auto-evolve<br/>observer + /evolve + /promote<br/>自动演进链"]
end
subgraph PROJ["项目实现"]
direction TB
P1["/skill-learning evolve<br/>compareExistingArtifacts +<br/>decideSkillLifecycle +<br/>generateOrMergeSkillDraft"]
P2["/skill-learning ingest<br/>transcript → observation → instinct"]
P3["runtimeObserver<br/>tool-hook(未 wire)+<br/>post-sampling fallback +<br/>observerBackend registry"]
P4["(无对应)"]
P5["autoEvolveLearnedSkills<br/>三路 skill/command/agent<br/>全部落盘"]
P6["/skill-learning status<br/>3 行文本摘要"]
P7["/skill-learning import<br/>JSON 本地文件"]
P8["/skill-learning export<br/>JSON 全量"]
P9["checkPromotion 自动 +<br/>/skill-learning promote 手动"]
end
E1 -.->|PARTIAL| P1
E2 -.->|PARTIAL| P2
E3 -.->|PARTIAL| P3
E4 -.->|NONE| P4
E5 ==>|FULL 运行时 · PARTIAL 命令层| P5
E6 -.->|PARTIAL| P6
E7 -.->|PARTIAL| P7
E8 -.->|PARTIAL| P8
E9 -.->|PARTIAL| P9
class E1,E2,E3,E4,E5,E6,E7,E8,E9 ecc
class P1,P2,P3,P5,P6,P7,P8,P9 proj
class P4 none
linkStyle 0 stroke:#ed6c02,stroke-width:2px,stroke-dasharray:6 4
linkStyle 1 stroke:#ed6c02,stroke-width:2px,stroke-dasharray:6 4
linkStyle 2 stroke:#ed6c02,stroke-width:2px,stroke-dasharray:6 4
linkStyle 3 stroke:#c62828,stroke-width:2px,stroke-dasharray:1 4
linkStyle 4 stroke:#2e7d32,stroke-width:3px
linkStyle 5 stroke:#ed6c02,stroke-width:2px,stroke-dasharray:6 4
linkStyle 6 stroke:#ed6c02,stroke-width:2px,stroke-dasharray:6 4
linkStyle 7 stroke:#ed6c02,stroke-width:2px,stroke-dasharray:6 4
linkStyle 8 stroke:#ed6c02,stroke-width:2px,stroke-dasharray:6 4
图 1 节点评级索引(精确依据见各章节 §1~§9):
| 连线 | 评级 | 剩余差距要点 |
|---|---|---|
| E1 ↔ P1 | PARTIAL | overlap score 驱动 vs LLM holistic verdict;无用户确认流;无 MEMORY.md 去重 |
| E2 ↔ P2 | PARTIAL | Stop hook 自动 vs 手动 /skill-learning ingest;项目多 instinct 中间层 |
| E3 ↔ P3 | PARTIAL | tool-hook 接口已立(P0-4)但 dispatcher 未 wire;LLM observer backend 仅 stub(P1-1) |
| E4 ↔ P4 | NONE | 无 git-log 批量生成路径 |
| E5 ↔ P5 | FULL(runtime)/ PARTIAL(命令层) | 运行时 autoEvolveLearnedSkills 三路均落盘;/skill-learning evolve --generate 命令入口仍只生 skill |
| E6 ↔ P6 | PARTIAL | 无 confidence bar / domain 分组 / pending 统计 |
| E7 ↔ P7 | PARTIAL | YAML→JSON;无 URL fetch / --dry-run / --min-confidence / --scope 参数 |
| E8 ↔ P8 | PARTIAL | YAML→JSON;无 --domain / --min-confidence / --scope 过滤 |
| E9 ↔ P9 | PARTIAL | 无后台进程 / 无真实 LLM observer;auto checkPromotion 已接但 /evolve 不自动展示 candidates |
图 2:项目侧学习闭环流程(SEARCH → LEARN → EVOLVE → PROMOTE)
项目侧端到端学习闭环:SEARCH → AUTO-LOAD → GAP(pending/draft/active/rejected)→ LEARN(heuristic default / llm stub)→ EVOLVE(skill / command / agent)→ PROMOTE(cross-project)→ 回 SEARCH。每个节点标注实际代码锚点(文件:函数 或 文件:行号)。
flowchart TD
Start([用户输入 prompt])
Start --> Search
subgraph S_SEARCH["SEARCH"]
Search["prefetch.collectSkillDiscoveryPrefetch<br/>localSearch.searchSkills<br/>TF-IDF + CJK bi-gram (P1-2)<br/>localSearch.ts:158-208"]
end
Search -->|命中 ≥ threshold| AutoLoad
Search -->|未命中 active skill| GapPending
subgraph S_AUTOLOAD["AUTO-LOAD"]
AutoLoad["prefetch 注入 skill_discovery<br/>attachment;若命中 draft skill →<br/>recordDraftHit(P1-4)<br/>prefetch.ts:206-212"]
end
subgraph S_GAP["GAP 四态机 (P0-1)<br/>skillGapStore.ts:88-216"]
direction TB
GapPending["pending<br/>recordSkillGap 首次<br/>shouldPromoteToDraft=false"]
GapDraft["draft<br/>writeSkillGapDraft<br/>count ≥ 2 或 isStrongReusableSignal"]
GapActive["active<br/>writeActiveSkillForGap<br/>count ≥ 4 或 draftHits ≥ 2"]
GapRejected["rejected<br/>rejectSkillGap"]
GapPending -->|"触发 shouldPromoteToDraft"| GapDraft
GapDraft -->|"触发 shouldPromoteToActive"| GapActive
GapPending -.->|"/skill-learning<br/>promote gap <key>"| GapDraft
GapPending -->|"rejectSkillGap"| GapRejected
GapDraft -->|"prefetch recordDraftHit"| GapActive
end
AutoLoad --> ModelTurn
GapPending --> ModelTurn
GapDraft --> ModelTurn
GapActive --> ModelTurn
ModelTurn[["模型响应 + 执行工具调用"]]
ModelTurn --> PostHook
subgraph S_LEARN["LEARN (P0-4 + P1-1 + P0-2)<br/>runtimeObserver.ts:41-78"]
direction TB
PostHook["registerPostSamplingHook<br/>runSkillLearningPostSampling"]
HookCheck{"hasToolHookObservationsForTurn?<br/>toolEventObserver.ts:47-52"}
UseToolHook["复用 tool-hook 观察<br/>filter source==='tool-hook'<br/>toolEventObserver.ts:81-140"]
Reconstruct["observationsFromMessages<br/>post-sampling 反推 (fallback)<br/>runtimeObserver.ts:141-192"]
Backend{"ObserverBackend registry<br/>observerBackend.ts"}
Heuristic["heuristicObserverBackend (默认)<br/>4 规则: userCorrections /<br/>toolErrorResolutions /<br/>repeatedSequences / conventions<br/>sessionObserver.ts:24-34"]
LLMStub["llmObserverBackend (stub)<br/>llmObserverBackend.ts<br/>env SKILL_LEARNING_OBSERVER_BACKEND=llm"]
Upsert["upsertInstinct<br/>outcome-aware confidence (P0-2)<br/>success=+0.05 / failure=-0.05 /<br/>contradict=-0.1<br/>instinctStore.ts:79-107"]
PostHook --> HookCheck
HookCheck -->|yes| UseToolHook
HookCheck -->|no · 生产默认| Reconstruct
UseToolHook --> Backend
Reconstruct --> Backend
Backend -->|default| Heuristic
Backend -->|env 切换| LLMStub
Heuristic --> Upsert
LLMStub --> Upsert
end
Upsert --> AutoEvolve
subgraph S_EVOLVE["EVOLVE 三路 (P0-3 + P2-2)<br/>runtimeObserver.ts:87-136"]
direction TB
AutoEvolve["autoEvolveLearnedSkills"]
Cluster["clusterInstincts<br/>by domain + normalizedTrigger<br/>evolution.ts:32-57"]
Classify{"classifyEvolutionTarget<br/>evolution.ts:59-77"}
SkillPath["generateOrMergeSkillDraft (P2-2)<br/>skillGenerator.ts:68-95"]
DedupCheck{"overlap ≥ 0.8?<br/>DUPLICATE_SKILL_OVERLAP_THRESHOLD"}
AppendEvidence["appendInstinctEvidenceToSkill<br/>skillGenerator.ts:97-120"]
Lifecycle["compareExistingArtifacts +<br/>decideSkillLifecycle<br/>create/merge/replace/archive/delete<br/>skillLifecycle.ts:63-80 + :82+"]
CmdPath["generateCommandCandidates +<br/>compareExistingArtifacts('command') +<br/>writeLearnedCommand<br/>runtimeObserver.ts:116-125"]
AgentPath["generateAgentCandidates +<br/>compareExistingArtifacts('agent') +<br/>writeLearnedAgent<br/>runtimeObserver.ts:127-136"]
AutoEvolve --> Cluster --> Classify
Classify -->|skill| SkillPath
Classify -->|command| CmdPath
Classify -->|agent| AgentPath
SkillPath --> DedupCheck
DedupCheck -->|yes| AppendEvidence
DedupCheck -->|no| Lifecycle
end
AppendEvidence --> Promote
Lifecycle --> Promote
CmdPath --> Promote
AgentPath --> Promote
subgraph S_PROMOTE["PROMOTE (P2-1)"]
Promote["checkPromotion<br/>findPromotionCandidates<br/>2+ 项目 + avg ≥ 0.8<br/>写 global scope 副本<br/>session 内幂等<br/>promotion.ts:68+, runtimeObserver.ts:138"]
end
Promote --> CacheInvalidate
CacheInvalidate["clearSkillIndexCache<br/>+ clearCommandsCache"]
CacheInvalidate --> LoopBack([下一轮 prompt])
LoopBack -.-> Start
Manual([手动命令入口<br/>/skill-learning<br/>status/ingest/evolve/export/import/prune/<br/>promote/projects<br/>skill-learning.ts:28-216])
Manual -.-> S_SEARCH
Manual -.-> S_GAP
Manual -.-> S_EVOLVE
Manual -.-> S_PROMOTE
classDef done fill:#2e7d32,stroke:#66bb6a,color:#fff
classDef stub fill:#6d4c41,stroke:#a1887f,color:#fff
class Heuristic,Upsert,GapPending,GapDraft,GapActive,GapRejected,SkillPath,DedupCheck,AppendEvidence,Lifecycle,CmdPath,AgentPath,Promote,UseToolHook done
class LLMStub,Reconstruct stub
图 2 状态色说明:
| 色 | 含义 |
|---|---|
| 绿(done) | P0-1 / P0-2 / P0-3 / P1-1(接口)/ P1-4 / P2-1 / P2-2 已全部落地,生产代码路径默认经过此节点 |
| 棕(stub / fallback-main) | P1-1 LLM backend 只立接口;P0-4 tool-event 接口已有但未 wire 到 dispatcher,生产仍走 observationsFromMessages 反推(HookCheck → no 分支) |
图 2 与文中差距章节的对应:
| 流程图节点 | 对应差距章节 | 剩余差距要点 |
|---|---|---|
HookCheck → Reconstruct(棕) |
差距 1 | src/Tool.ts dispatcher 未 wire recordToolStart/Complete/Error,生产路径仍是反推 |
Backend → LLMStub(棕) |
差距 2 | LLM backend 未接真实模型,仅接口占位 |
SkillPath / CmdPath / AgentPath(绿) |
差距 3 | runtime 三路已全绿;命令层 /skill-learning evolve --generate 仍只生 skill |
Promote(绿) |
差距 4 | 已打通,ECC /evolve 自动展示 candidates 未对齐(项目需单独调 promote) |
GapPending(绿) |
差距 5 | 四态机已落地;isStrongReusableSignal 仍可让单条中文告诫跳过 pending 直接到 draft(非 active) |
图 3:ECC v2.1 参考架构速写
ECC continuous-learning-v2 的 observe → analyze → evolve → promote 链路速写。用于读图 1 时交叉对照,帮助理解 ECC 侧 "hook 100% 确定观察 + Haiku 后台语义分析 + 三路产出" 的整体架构。文件锚点取自 C:\Users\12180\.claude\plugins\marketplaces\everything-claude-code\skills\continuous-learning-v2\,ECC 插件 ecc-universal v1.9.0。
flowchart TD
ECCStart([Claude Code tool call])
ECCStart --> ECCHook
subgraph ECC_OBSERVE["Observe(shell hook,确定性 100%)"]
direction TB
ECCHook["PreToolUse / PostToolUse<br/>hooks/observe.sh<br/>(HOOK_PHASE=pre|post)"]
ECCFilter["5 层过滤<br/>entrypoint / profile /<br/>ECC_SKIP_OBSERVE / agent_id /<br/>path exclusions<br/>observe.sh:105-130"]
ECCScrub["秘密脱敏 +<br/>size archive 10MB<br/>observe.sh:219-241"]
ECCWriteObs["projects/<hash>/<br/>observations.jsonl"]
ECCHook --> ECCFilter --> ECCScrub --> ECCWriteObs
end
ECCWriteObs --> ECCSignal["SIGUSR1 节流<br/>每 20 次发一次<br/>observe.sh:387-426"]
ECCSignal --> ECCObserver
subgraph ECC_LEARN["Analyze(Haiku 后台 observer)"]
direction TB
ECCObserver["agents/observer-loop.sh<br/>nohup 独立进程"]
ECCCooldown{"cooldown ≥ 60s<br/>&& idle < 30min?"}
ECCSample["tail 500 行 obs<br/>→ Haiku prompt<br/>observer-loop.sh:114-122"]
ECCAnalyze["claude --model haiku<br/>--max-turns 10 --print<br/>allowedTools Read,Write<br/>observer-loop.sh:192-194"]
ECCWriteInst["projects/<hash>/<br/>instincts/personal/*.yaml<br/>(YAML frontmatter +<br/>Markdown body)"]
ECCObserver --> ECCCooldown
ECCCooldown -->|yes| ECCSample --> ECCAnalyze --> ECCWriteInst
end
ECCWriteInst --> ECCEvolveCmd
subgraph ECC_EVOLVE["/evolve 三路聚类"]
direction TB
ECCEvolveCmd["cmd_evolve<br/>instinct-cli.py:765-874<br/>按 trigger/domain 聚类"]
ECCCluster{"筛选阈值"}
ECCWriteSkill["evolved/skills/<name>/<br/>SKILL.md<br/>(cluster ≥ 2)"]
ECCWriteCmd["evolved/commands/<name>.md<br/>(workflow domain<br/>+ conf ≥ 0.7)"]
ECCWriteAgent["evolved/agents/<name>.md<br/>frontmatter model: sonnet<br/>(cluster ≥ 3 + avg conf ≥ 0.75)"]
ECCEvolveCmd --> ECCCluster
ECCCluster -->|skill| ECCWriteSkill
ECCCluster -->|command| ECCWriteCmd
ECCCluster -->|agent| ECCWriteAgent
end
ECCWriteInst --> ECCPromoteCmd
subgraph ECC_PROMOTE["/promote 跨项目提升"]
direction TB
ECCPromoteCmd["cmd_promote<br/>instinct-cli.py:944+<br/>2+ 项目 && avg ≥ 0.8"]
ECCGlobal["~/.claude/homunculus/<br/>instincts/personal/*.yaml<br/>scope: global<br/>+ promoted_from / promoted_date"]
ECCPromoteCmd --> ECCGlobal
end
classDef eccBox fill:#1e3a5f,stroke:#4a7fb0,color:#fff
class ECCHook,ECCFilter,ECCScrub,ECCWriteObs,ECCSignal,ECCObserver,ECCSample,ECCAnalyze,ECCWriteInst,ECCEvolveCmd,ECCWriteSkill,ECCWriteCmd,ECCWriteAgent,ECCPromoteCmd,ECCGlobal eccBox
图 3 与图 2 的结构对照(供读者横向参考):
| ECC v2.1 阶段(图 3) | 项目对应阶段(图 2) | 主要差异 |
|---|---|---|
| Observe(Pre/Post hook, 100% 确定性) | SEARCH + AUTO-LOAD + LEARN 的 HookCheck 分支 | 项目 tool-hook 接口已立但未 wire,生产走 post-sampling 反推 |
| Haiku 后台分析(5min interval / SIGUSR1) | LEARN 的 Backend → Heuristic(默认)/ LLMStub(占位) | 项目无后台进程,用 observerBackend 注册表切换默认的启发式 4 规则 |
| /evolve 三路产出(skill/command/agent) | EVOLVE 三路(SkillPath + CmdPath + AgentPath) | runtime 层 FULL 对齐;/skill-learning evolve --generate 命令入口仅 skill |
| /promote 跨项目(手动 + auto-promote) | PROMOTE 的 checkPromotion(auto 每轮) + /skill-learning promote |
门槛参数一致(2 项目 + avg ≥ 0.8);集成风格不同(ECC 独立 /promote,项目嵌入 runtime 尾部) |
文档元信息
- 作者:researcher(skill-learning-ecc-parity 团队)
- 状态:Task #13 初稿 + Task #14 附录三图均已产出,供 META-V 验证。
- 不在本文档内:对差距的"应否补齐"价值判断 — 详见任务规范
docs/features/skill-learning-ecc-parity-tasks.md。 - 已知限制:
- Task #13 要求的 "swarm-auto-evolve" 在 ECC 源中无独立对应物(grep 确认),本文将其解为 "ECC 自动演进链路(observer agent + /evolve + /promote)" 进行对比。如团队 lead 所指是其它概念,需追问。
- ECC 部分行号取自
v1.9.0快照。ECC 后续版本可能调整,复核时以函数名为准。 - 项目侧行号锚点对应 2026-04-17 工作树状态。如后续代码移位,以函数名为准。Mermaid 源同步保留于
.swarm/teammate-notes/mermaid-draft.md。