跳转到内容

跨 Harness 可移植性模型

跨 Harness 可移植性模型

学习目标

本章要解决什么问题:理解 ECC 如何将一套工作流适配到 Claude Code、Codex、Cursor、OpenCode、Gemini 等多种 AI 编码代理。

读完本章后,你将了解:

  • “工作流层 vs 执行表面”的架构分离
  • SKILL.md 作为最便携单元的设计原则
  • 各 Harness 的适配策略与可移植性差异
  • Hermes Operator Shell 的边界定义

前置知识

本章涉及插件系统和可移植性的通用原理,建议先阅读:

下文假设你已理解上述概念,直接聚焦 ECC 的具体实现。


项目实践

工作流层与执行表面的分离

ECC 的核心架构决策是将持久的行为逻辑Harness 特定的加载和执行机制分离:

ECC 的可移植性矩阵:

表面共享源Harness 适配可移植性
Skillsskills/*/SKILL.md各 Harness 打包格式高 — 主要是指令文本
Rulesrules/, AGENTS.md安装路径、格式中 — 支持但不完全相同
Hookshooks/hooks.json原生 vs 指令驱动中 — Claude 原生,Codex 指令
MCPs.mcp.json各 Harness MCP 导入高 — MCP 是标准协议
Commandscommands/斜杠命令 vs CLI中 — 语义各 Harness 不同
Sessions编排脚本TUI/daemon/worktree低 — Alpha 阶段

Harness 适配器合规矩阵

ECC 维护了一个详细的合规矩阵(scripts/lib/harness-adapter-compliance.js),追踪每个表面在各 Harness 中的支持状态:

SKILL.md 的便携性设计

ECC 的 246 个 SKILL.md 文件遵循统一的便携性约定:

---
name: tdd-workflow
description: 测试驱动开发工作流
origin: ECC # 来源标记:ECC(官方)或 community
---

便携性规则

  • 使用 YAML frontmatter 声明 namedescriptionorigin
  • 描述何时使用该技能(When to Activate)
  • 声明所需工具但不嵌入密钥
  • 示例保持仓库相对或通用
  • Harness 特定命令放在有明确标签的独立区块

适配层的实际目录结构

ECC 为每个 Harness 维护了独立的适配目录:

目录目标 Harness内容
.claude-plugin/Claude Code插件元数据(plugin.json
.codex-plugin/Codex插件配置 + 适配后的 codex.md
.opencode/OpenCodeOpenCode 插件格式的技能/命令
.cursor/Cursor翻译后的规则和设置
.gemini/Gemini指令驱动的兼容性表面
.zed/ZedZed 特定的规则翻译

Hermes 边界

Hermes 是 ECC 衍生的 Operator Shell,ECC 明确定义了其与公共仓库的边界:

应该交付

  • 净化的设置文档(docs/HERMES-SETUP.md
  • 仓库相对演示提示
  • 通用 Operator 技能
  • 不依赖私有凭证的示例

不交付

  • OAuth Token 或 API Key
  • 原始的 ~/.hermes 导出
  • 个人工作空间记忆
  • 私有数据集
  • 未经审查的本地自动化包

问题与规避

Harness 特定假设导致不可移植

问题:技能中使用 Claude 特定的 /compact 命令,在 Codex 中无效。

ECC 的规避:Harness 特定内容放在有明确标签的区块中。主流程使用通用描述。例如在 continuous-learning 技能中:

### If installed as a plugin (recommended):
No extra settings.json hook block is required.
### If installed manually:
Add this to your settings.json: ...

适配层过厚导致不一致

问题:为每个 Harness 维护一份行为逻辑副本,导致不一致。

ECC 的规避

  • 适配层只翻译加载机制,不翻译行为
  • 共享行为始终在源位置(skills/hooks/
  • CI 验证目录计数与 CHANGELOG 声明一致

钩子语义差异

问题:Claude 的 PreToolUse 钩子可以阻塞工具调用,Codex 没有等效机制。

ECC 的规避

  • 在支持原生钩子的 Harness 中使用阻塞钩子
  • 在不支持的 Harness 中使用指令描述 + 事后检查
  • 文档中明确标注哪些钩子有回退、哪些没有

设计取舍

为什么不做 Harness 无关的运行时?

构建统一的”超级插件”在所有 Harness 上运行:

  • 被考虑但放弃的原因:各 Harness 的插件 API 差异太大,维护统一运行时的成本超过收益
  • ECC 的选择:薄适配层 + 共享源文件。更简单、更容易调试

为什么共享源码而非分发产物?

ECC 选择共享源码(Markdown 文件)作为分发单位:

  • 优势:社区可直接阅读和贡献,适配可透明审计,技能可平滑演进
  • 代价:用户看到的是原始 Markdown,而非精美的文档
  • 替代方案:构建为静态文档站点或 npm 包。ECC 认为源码即文档更利于社区贡献

为什么 Hooks 在 Codex 中退化为指令?

Codex 没有原生钩子执行能力:

  • ECC 的选择:在 AGENTS.md 中以指令描述替代钩子
  • 效果:行为从”强制执行”退化为”建议遵守”
  • 权衡:不完全等效,但比完全没有好

参考来源

  • 源码验证: docs/architecture/cross-harness.md — 跨 Harness 架构文档
  • 源码验证: .codex-plugin/, .opencode/, .cursor/ 目录 — 各 Harness 适配
  • 源码验证: scripts/lib/harness-adapter-compliance.js — 合规矩阵
  • 跨 Harness 可移植性 — 通用可移植性设计模式