跳转到内容

跨 Harness 可移植性模型

跨 Harness 可移植性模型

学习目标

读完本章后,你将能够:

  • 理解”工作流层 vs 执行表面”的架构分离原则
  • 识别哪些组件可以跨 Harness 共享、哪些需要适配
  • 设计可移植的 SKILL.md 格式
  • 评估适配层的厚度与边界

前置知识


1. 核心架构原则

1.1 工作流层 vs 执行表面

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

原则:共享行为属于 skills/rules/hooks/scripts/mcp-configs/。适配层应该保持薄。每个 Harness 的加载和强制执行行为不同,但共享的工作流描述应该保持一致。

1.2 可移植性矩阵

表面共享源Harness 适配可移植性
Skillsskills/*/SKILL.md各 Harness 的打包格式 — 主要是指令文本,格式一致
Rulesrules/, AGENTS.md安装路径、文件格式 — 支持但各 Harness 格式不完全相同
Hookshooks/hooks.json, scripts/原生钩子 vs 指令驱动 — Claude/OpenCode 有原生钩子,Codex 是指令驱动
MCPs.mcp.json, mcp-configs/各 Harness 的 MCP 导入 — MCP 是标准协议
Commandscommands/, CLI 脚本斜杠命令 vs CLI 入口点 — 命令语义各 Harness 不同
Sessions编排脚本, 状态存储TUI/daemon, tmux/worktree — 仍在 Alpha 阶段

2. 便携单元设计

2.1 SKILL.md 作为最便携的单元

一个良好的跨 Harness 技能应该:

  • 使用 YAML frontmatter 声明 namedescriptionorigin
  • 描述何时使用该技能
  • 声明所需工具或连接器,但不嵌入密钥
  • 保持示例与仓库相对或通用
  • 避免 Harness 特定的命令假设,除非该部分有明确标签

可移植技能示例结构

---
name: tdd-workflow
description: 测试驱动开发工作流,要求 80%+ 覆盖率
origin: ECC
---
# Test-Driven Development Workflow
## When to Activate
- Writing new features
- Fixing bugs
- Refactoring code
## Core Principles
1. Tests BEFORE Code
2. Minimum 80% coverage
3. Unit + Integration + E2E tests
## Workflow Steps
...(通用步骤,不绑定特定 Harness 命令)...

同一个源技能可以安装到多个 Harness,因为它主要是指令、约束和工作流形状。

2.2 什么保持不变

组件为什么可移植
SKILL.md 文本主要是自然语言指令,不依赖运行时
MCP 配置MCP 是标准协议,各 Harness 实现相同
规则文本编码风格、安全指南是通用知识
Node.js 脚本跨平台 Node.js 运行时保证兼容性

2.3 什么需要适配

组件适配需求示例
HooksClaude 有原生钩子执行,Codex 只能指令驱动hooks.json → AGENTS.md 中的说明文字
Commands各 Harness 的命令加载机制不同Claude 斜杠命令 → Codex 内置命令
安装路径各 Harness 的插件根目录不同~/.claude/plugins/ vs .agents/
会话管理各 Harness 的会话生命周期不同Claude 的 Stop 钩子 vs Codex 的会话结束检测

3. 适配层模式

3.1 指令驱动回退

当目标 Harness 不支持原生钩子时,钩子行为退化为指令描述

关键:适配层不应该复制行为逻辑。共享逻辑保持在 scripts/ 中,适配层只负责加载和触发方式。

3.2 薄适配原则

适配层应该:

  • 只翻译加载机制,不翻译行为
  • 保持共享行为在源位置(skills/hooks/
  • 避免在适配层中嵌入业务逻辑
  • 测试源技能与 Harness 元数据分别验证

厚的适配层反模式

# ❌ 坏:在适配层复制逻辑
# codex-adapter.js 中重写整个 TDD 工作流
# ✅ 好:适配层只负责加载
# codex-setup.md 中引用 skills/tdd-workflow/SKILL.md

4. Operator Shell 边界

4.1 Hermes 模式

Operator Shell(如 Hermes)不是公共运行时,而是消费 ECC 资产的壳

  • 将选定的 ECC 技能导入 Operator 技能目录
  • 使用 ECC 的 MCP 约定访问工具
  • 通过可复用的 ECC 模式路由聊天、CLI、定时任务和交接工作流
  • 将重复的本地 Operator 工作提炼为已净化的 ECC 技能

4.2 应该交付什么

交付不交付
净化的设置文档OAuth Token 或 API Key
仓库相对演示提示原始的本地 Operator 记忆
通用 Operator 技能个人工作空间记忆
不依赖私有凭证的示例私有数据集
未经审查的本地自动化包

5. 陷阱与对策

5.1 Harness 特定假设导致不可移植

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

对策:将 Harness 特定内容放在有明确标签的独立区块中,主流程使用通用描述。

5.2 适配层过厚

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

对策:适配层只翻译加载机制。行为逻辑始终引用共享源文件。定期运行适配一致性检查。

5.3 钩子语义差异

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

对策

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

6. 设计取舍

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

构建一个统一的、Harness 无关的运行时(类似一个”超级插件”在所有 Harness 上运行)看似理想,但:

  • 各 Harness 的插件 API 差异太大
  • 维护统一运行时的成本超过收益
  • 薄适配层更简单、更容易调试

为什么 SKILL.md 是最便携的单元?

因为 SKILL.md 本质上是自然语言指令,不依赖任何运行时。它只需要被加载到 Agent 的上下文中即可生效。相比之下,钩子需要原生执行支持,命令需要特定的加载机制。

共享源码 vs 分发产物

ECC 选择共享源码(skills/rules/ 目录中的 Markdown 文件)作为分发单位,而非编译后的分发产物。这使得:

  • 社区可以直接阅读和贡献
  • 每个 Harness 的适配可以透明地审计
  • 技能可以在不同版本间平滑演进

参考来源