使用 /instinct-status 检视 ECC 项目级与全局级学习直觉:命令原理与输出深度解读
/instinct-status 是 ECC 的 Continuous Learning v2.1 体系中用于「盘点已学行为」的诊断命令,它把当前项目作用域与全局作用域中累积的 instincts(小型可复用行为)一次性列出,并按领域分组、附置信度条。本文以命令定义文档为骨架,结合仓库内 instinct-cli.py、resolve-ecc-root.js、homunculus-dir.sh 等源码,讲清它的执行链路、数据存放位置、输出格式的每个字段含义,以及如何据此决定后续的演化(/evolve)或提升(/promote)动作。读完你将能熟练解读一条 status 输出,并能在直觉文件缺失、遗留数据存在等异常场景下快速定位原因。
一、/instinct-status 在 ECC 学习体系中的定位
ECC(Everything Claude Code)以 continuous-learning-v2 技能承载"基于直觉的学习系统":通过 hooks 100% 可靠地观察会话,产出带置信度评分的原子化 instincts,再把它们聚类演化成 skills / commands / agents(详见 SKILL.md)。v2.1 引入了项目作用域直觉,让 React 的模式留在 React 项目里、Python 约定留在 Python 项目里,只有"总是校验用户输入"这类普适模式才进入全局。
在此体系中,与直觉生命周期相关的斜杠命令共六条,而 /instinct-status 是所有其余动作的前置体检:
| 命令 | 职责 |
|---|---|
/instinct-status |
展示当前项目 + 全局全部直觉及其置信度(本文主题) |
/evolve |
将相关直觉聚类为 skill / command / agent |
/instinct-export |
按 scope / domain 过滤导出直觉 |
/instinct-import |
带作用域控制地导入直觉 |
/promote |
把项目直觉提升为全局直觉 |
/projects |
列出已知项目及其直觉计数 |
对应实现文件为 commands/instinct-status.md 与其他同名命令定义文件。文档对其功能的概括只有一句话:"Shows learned instincts for the current project plus global instincts, grouped by domain"——把当前项目与全局直觉合并后,按 domain 分组展示。
二、命令解析:为什么先解析 ECC 根目录
/instinct-status 的"Implementation"一节强调了一个关键设计:运行 instinct CLI 之前,先以与 hooks/hooks.json 以及其他斜杠命令(/sessions、/skill-health)完全相同的方式解析出当前生效的 ECC 插件根目录。这是因为当 CLAUDE_PLUGIN_ROOT 未设置、而旧的 ~/.claude/skills/continuous-learning-v2/ 目录仍然存在时,直接调用会产生"跑错副本"的分叉问题(文档标注 issue #2037)。
文档给出的完整命令如下(保持原样,可直接执行):
ECC_ROOT="${CLAUDE_PLUGIN_ROOT:-$(node -e "var r=(function(){var p=require('path'),f=require('fs'),o=require('os');var e=process.env.CLAUDE_PLUGIN_ROOT;if(e&&e.trim())return e.trim();var d=p.join(o.homedir(),'.claude');function L(x){try{return require(p.join(x,'scripts','lib','resolve-ecc-root')).resolveEccRoot()}catch(_){return null}}var r=L(d);if(r)return r;var s=['ecc','ecc@ecc','marketplaces/ecc','everything-claude-code','everything-claude-code@everything-claude-code','marketplaces/everything-claude-code'];for(var i=0;i<s.length;i++){r=L(p.join(d,'plugins',s[i]));if(r)return r}try{var g=['ecc','everything-claude-code'];for(var j=0;j<g.length;j++){var c=p.join(d,'plugins','cache',g[j]);var O=f.readdirSync(c);for(var k=0;k<O.length;k++){var q=p.join(c,O[k]);var V=f.readdirSync(q);for(var m=0;m<V.length;m++){r=L(p.join(q,V[m]));if(r)return r}}}}catch(_){}return d})();console.log(r)")}"
python3 "$ECC_ROOT/skills/continuous-learning-v2/scripts/instinct-cli.py" status
这一段内嵌的单行 JS 是对 resolve-ecc-root.js 中 resolveEccRoot() 的压缩内联版本。为什么把这段逻辑塞进每条命令而不是外部脚本?代码注释给出的原因是:旧版把完整搜索逻辑(约 700 字符)复制到约 80 处命令文件中,其中的数组展开(spread)写法会因 shell 引号问题在 Windows 上执行失败(issue #2368)。现在的压缩形式不含 spread、不含嵌套数组字面量、不含转义双引号,因此能安全穿越 node -e "..." 在任意 shell 中的引号包裹。
resolveEccRoot() 本身按五级优先级探测:
CLAUDE_PLUGIN_ROOT环境变量——插件式安装下由 Claude Code 为 hooks / commands 注入,命中即返回(envRoot.trim()直接作为根);- 标准安装位
~/.claude/——当该目录同时存在脚本树探针scripts/lib/utils.js与哨兵技能skills/continuous-learning-v2时才认定是完整根,避免"只拷了脚本没拷技能"的半安装被误判为可用根(issue #2544); ~/.claude/plugins/下的已知插件根——依次探测ecc、ecc@ecc、marketplaces/ecc以及历史名everything-claude-code等六种布局,保留向后兼容;- 插件缓存自动探测——扫描
~/.claude/plugins/cache/{ecc,everything-claude-code}/下的<org>/<version>目录,适配 marketplace 安装; - 回退
~/.claude/——以上全部失败时的原始行为。
对 status 命令而言,resolveEccRoot() 只负责定位到根,真正的技能脚本路径再拼接 skills/continuous-learning-v2/scripts/instinct-cli.py,最后以 status 子命令调用 Python CLI。这也解释了为什么 CLAUDE_PLUGIN_ROOT 的一致性如此重要:任何一条命令用旧路径解析出的 ECC_ROOT,都会指向一个过时或无内容的目录,导致读不到当前累积的直觉。
三、status 子命令的完整执行链路
运行 python3 instinct-cli.py status 后(入口 main() 中 args.command == 'status' 分支,见 instinct-cli.py),cmd_status() 按文档"Usage / What to Do"列出的五步执行:
第 1 步:探测当前项目上下文(git remote / 路径哈希)
detect_project() 返回一个含 id、name、root、各子目录路径的字典,探测优先级如下:
- 环境变量
CLV2_NO_PROJECT=1时直接返回全局兜底项目(id="global"); CLAUDE_PROJECT_DIR显式指定目录——即便该目录不是 git 仓库也按其绝对路径哈希成项目身份(与detect-project.sh保持一致);- 否则用
git rev-parse --show-toplevel取仓库根;若仓库无 remote,则回退到git worktree list --porcelain定位主工作树路径; - 以上全部失败(非 git 目录、git 超时 5 秒、git 不存在)时落入
global兜底。
项目 ID 的生成值得注意:优先取 git remote get-url origin 的 URL——先剥离凭证(_strip_remote_credentials)、去掉 :// 协议前缀与 .git 后缀、统一小写(_normalize_remote_url),再对结果做 SHA-256 并截取前 12 个字符(_project_hash)。这意味着同一仓库在不同机器上会得到相同的项目 ID,直觉数据可以跨机延续;只有完全没有 remote 时才退回用机器相关的路径哈希。ID 冲突时 status 只依赖哈希寻址,无需用户干预。
第 2、3 步:读取项目直觉与全局直觉
load_all_instincts(project) 按目录加载。项目侧(project["id"] != "global" 时)依次读取 instincts_personal 与 instincts_inherited 两个子目录;全局侧读取 GLOBAL_PERSONAL_DIR 与 GLOBAL_INHERITED_DIR(关于这些目录的落盘位置见第五节)。目录扫描器 _load_instincts_from_dir() 只认扩展名 .yaml、.yml、.md(常量 ALLOWED_INSTINCT_EXTENSIONS),文件统一按 UTF-8 读取,并给每条直觉附加 _source_file、_source_type、_scope_label 三个内部标记;若 frontmatter 未写 scope 字段,则按所在目录的 scope_label 补默认值。
第 4 步:按优先级合并(project 覆盖 global)
这是 v2.1 作用域模型的核心语义:先收集项目直觉的 ID 集合,再遍历全局直觉,凡 ID 已被项目直觉占用的全局条目一律丢弃,从而保证"ID 冲突时项目直觉胜出"。测试 test_load_all_project_overrides_global 验证了这一点:同名直觉在项目中置信度 0.9、全局 0.3,合并后只剩项目版本且 scope 标记为 project。
第 5 步:分组渲染
合并结果进入渲染阶段:项目条目归入 PROJECT-SCOPED 区块、全局条目归入 GLOBAL 区块,各自内部再按 domain 聚类、按置信度降序排列。
四、输出格式逐字段解读
文档给出了典型输出骨架,这里完整保留并加注:
============================================================
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
## GLOBAL (apply to all projects)
### SECURITY (2)
█████████░ 85% validate-user-input [global]
trigger: when handling user input
对照 instinct-cli.py 中 cmd_status() 与 _print_instincts_by_domain() 的实现,各段含义如下:
- 头部横幅:
INSTINCT STATUS - N total,N为项目与全局合并去重后的总数(len(instincts)); - 项目与计数行:显示
Project:名称与 12 位项目哈希 ID,以及Project instincts/Global instincts各自数量。注意括号中的哈希正是"同仓库跨机器一致"的那个_project_hash结果; ## PROJECT-SCOPED (my-app)/## GLOBAL (apply to all projects):由_scope_label切分的两大区块,分别调用_print_instincts_by_domain();### DOMAIN (N):domain 取直觉 frontmatter 的domain字段,缺省为general,按名称升序;每个 domain 下的直觉再按confidence降序排列;- 置信度条
███████░░░ 70%:_confidence_bar()把置信度换算为 10 格条(filled = int(confidence * 10),截断到[0,10])。若当前 stdout 编码无法表达█/░(如 Windows cp1252),自动退化为#/.的 ASCII 形式,保证渲染不崩溃; [project]/[global]标签:来自直觉的scope字段或目录推导值;trigger:行:直觉的触发条件,来自 frontmattertrigger;action:行(实际输出的增强信息):实现还会用正则## Action\s*\n\s*(.+?)从正文中抽取 Action 小节的首行,截断到 60 字符展示,帮助一眼看出该直觉"要做什么"。文档示例省略了该行,实际 CLI 会打印。
输出不止于此。cmd_status() 还会在区块之后追加三类运维信息:
- 观测统计:若当前项目存在
observations.jsonl,会打印Observations: N events logged及其文件路径; - 待审直觉(pending):若存在
pending目录且有待审文件(_collect_pending_instincts()全局 + 各项目逐一扫描),打印Pending instincts: N awaiting review;数量 ≥ 5 时警告未审直觉将在 30 天后自动删除(PENDING_TTL_DAYS = 30);对剩余寿命不足 7 天(PENDING_EXPIRY_WARNING_DAYS = 7)的条目逐条列出(Nd remaining); - 遗留数据警告:
_warn_legacy_data()检测旧路径~/.claude/homunculus/是否仍含实质性文件(活动目录已迁走时),若存在则以!横幅提示运行迁移脚本migrate-homunculus.sh或设置CLV2_HOMUNCULUS_DIR指向旧路径。
若当前没有任何直觉,则输出兜底提示 No instincts found. 以及项目名 / 哈希、项目与全局数据目录的绝对路径——这一分支由测试 test_cmd_status_no_instincts 覆盖。因此,看到 status 输出变空时,先查这两条路径是否正确、有没有被误设的环境变量改写过。
五、直觉数据的落盘位置与目录解析优先级
值得注意的是,命令定义文档"Usage / What to Do"第 2、3 步写的是读取 ~/.claude/homunculus/projects/<project-id>/instincts/ 与 ~/.claude/homunculus/instincts/。但从 v2.1 的源码与 SKILL.md 的"Data Directory"一节可以确认:活动数据目录已从 ~/.claude/homunculus 迁移到 XDG 布局,旧路径只是供迁移读取的遗留位置。迁移原因在 SKILL.md 中有说明:把观测数据放到 ~/.claude 之外,可以避免 Claude Code 的敏感路径防护误拦截后台 instinct 写入。
活动目录按以下优先级解析(Python 侧见 _resolve_homunculus_dir(),shell 侧见 homunculus-dir.sh,两侧规则一致):
CLV2_HOMUNCULUS_DIR(设为绝对路径时优先生效,相对路径会被忽略并告警);$XDG_DATA_HOME/ecc-homunculus(同样要求绝对路径);- 兜底
$HOME/.local/share/ecc-homunculus。
status 渲染用到的实际目录因此是:
${XDG_DATA_HOME:-~/.local/share}/ecc-homunculus/
├── instincts/
│ ├── personal/ # 全局自动学习直觉
│ └── inherited/ # 全局导入直觉
├── observations.jsonl # 全局观测兜底
├── projects.json # 项目哈希 → 名称/路径/remote 注册表
└── projects/
└── <project-hash>/
├── observations.jsonl
├── instincts/
│ ├── personal/ # 项目专属自动学习直觉
│ └── inherited/ # 项目专属导入直觉
└── evolved/ # /evolve 产物(skills/commands/agents)
status 判断 scope 时并不看文件在"哪个用户的个人目录",而是看它落在 projects/<hash>/instincts/(project)还是顶层 instincts/(global)。老用户只需执行一次迁移即可把 ~/.claude/homunculus 数据搬入新布局:
bash skills/continuous-learning-v2/scripts/migrate-homunculus.sh
迁移前不妨先跑一次 /instinct-status——若末尾出现 LEGACY DATA DETECTED 横幅,正是告诉你旧路径仍有余留数据待迁移,或可通过 CLV2_HOMUNCULUS_DIR=~/.claude/homunculus 继续使用旧路径。
六、一条直觉在磁盘上长什么样
status 展示的每一条直觉,磁盘上就是一个独立文本文件。解析器 parse_instinct_file() 以成对 --- 作 YAML frontmatter 边界切分(正文如需水平分隔线,应使用 *** 或 ___ 以免被误判为边界),并要求每个切片带有 id 字段,否则整条丢弃(对应测试 test_parse_no_id_skipped)。一个典型文件如下(示例出自 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
与 status 输出直接对应的字段是:
confidence——解析为浮点数(0.0~1.0),决定置信度条的格数与排序;畸形值回退为默认0.5(对应测试test_parse_confidence_is_float);domain——决定归入哪个### DOMAIN分组,缺省general;scope——project或global,决定渲染在哪个大区块,缺省按所在目录推导;trigger——frontmatter 引号会被剥离,落在trigger:行;- 正文
## Action小节——其首行被提取为action:行。
所谓"instinct 原子性",就是这类文件始终"一个 trigger、一个 action、一份证据";status 只是把它们摊开成一张可按 domain 检索的清单。
七、测试如何为 status 的正确性背书
仓库以 pytest 覆盖 CLI 关键路径,测试文件 test_parse_instinct.py(通过 importlib 以 instinct_cli 模块名加载带连字符的 instinct-cli.py)中与 status 相关的断言包括:
test_cmd_status_no_instincts——空数据时输出No instincts found.且返回码为 0;test_cmd_status_with_instincts——写一个项目直觉 + 一个全局直觉后,输出含INSTINCT STATUS、Project instincts: 1、Global instincts: 1、PROJECT-SCOPED、GLOBAL等关键段;test_cmd_status_returns_int——cmd_status恒返回整数(正常路径 0);test_confidence_bar_uses_unicode_when_supported/test_confidence_bar_uses_ascii_when_stream_rejects_block_glyphs——UTF-8 流输出█×8 +░×2,cp1252 流退化为########..;test_print_instincts_by_domain_is_cp1252_safe——把 stdout 替换为 cp1252 包装流后渲染不抛异常且不含块形字符;test_load_all_project_overrides_global——项目直觉同 ID 覆盖全局的合并语义。
这些用例从"合并优先级""空态兜底""跨编码渲染健壮性"三个维度锁定了 status 的行为边界,也解释了为何在 Windows 原生终端里置信度条会以 #/. 形态出现——这是有意为之的降级,而非乱码。
八、看完 status 之后:从检视到演化的下一步
/instinct-status 是只读诊断命令,它本身不修改任何直觉,但它的输出直接决定后续动作:
- 同一 domain 下出现多条高度相似的直觉 → 用
/evolve聚类成 skill / command / agent(产物写入projects/<hash>/evolved/或全局evolved/); - 某条
[project]直觉已在多个项目以高置信度反复出现 → 用/promote提升为[global](自动提升门槛为:同一 ID 出现在 2+ 项目且平均置信度 ≥ 0.8,常量PROMOTE_MIN_PROJECTS = 2、PROMOTE_CONFIDENCE_THRESHOLD = 0.8); - 想跨机器或团队共享某领域直觉 → 用
/instinct-export导出、在目标侧用/instinct-import导入(对应命令定义见 instinct-export.md、instinct-import.md); - 输出末尾提示
N pending instincts awaiting review且临近 30 天 TTL → 及时评审或用/prune清理过期待审项(prune.md); - 想了解哪些项目被登记、各自有多少直觉 → 用
/projects(projects.md)。
上述命令定义、技能文档与可执行脚本均在本仓库中:入口技能见 continuous-learning-v2,CLI 实现见 instinct-cli.py,根目录与数据目录解析分别见 resolve-ecc-root.js 与 homunculus-dir.sh。实际使用前,建议先执行一次 /instinct-status 核对项目哈希与两个 scope 的计数是否符合预期——它是整个学习循环里成本最低、信息量最高的健康检查。
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证件照制作算法。Python09
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