第 8 章:选择性安装器——从复制文件到解析计划
为什么 ECC 需要 installer
ECC 资产多、目标多、安装级别多。直接 cp -R 会遇到:重复安装、宿主路径不一致、用户现有配置被覆盖、插件和手工安装叠加、版本漂移后无法 repair。新安装器因此采用“请求 → 解析 → 执行 → 状态”的四阶段。
三种 manifest
| 文件 | 角色 |
|---|---|
install-components.json | 面向用户的 81 个选择项,按 baseline / language / framework / capability / agent / skill / locale 分类 |
install-modules.json | 34 个实际安装单元,声明 kind、paths、targets、依赖、成本和稳定性 |
install-profiles.json | 7 个预设组合:minimal、opencode、core、developer、security、research、full |
component 是产品语言,例如 capability:security;module 是执行语言,例如 security。一个 component 可以映射到一个或多个 module,多个 component 也可以共享同一 module。这种间接层让用户选择不会被物理目录结构绑死。
解析依赖闭包
以 developer profile 为例,除了 rules、agents、commands、hooks、platform 和 workflow,还会带上 framework-language、database、orchestration。解析器需要:
- 读取 profile 的 module 列表。
- 递归补齐每个 module 的 dependencies。
- 去重并保持 resolution order。
- 按 target 过滤不支持当前宿主的 module。
- 将用户
--with/--without/--skills选择合并到请求。
profile / modules / components
↓
normalized request
↓
dependency closure
↓
target filtering
↓
ordered operations
Plan 与 Apply 分开
scripts/install-plan.js 是只读预览入口,可列出 profile、module、component,也可以输出 JSON。scripts/install-apply.js 才执行复制、合并和状态写入。CLI 的 --dry-run 会贯穿这条链路,适合在写入用户目录前检查结果。
安装计划里的 operation 不是简单的“源路径 → 目标路径”,还会记录策略和 ownership,例如递归复制、JSON merge、scaffold-only。对 OpenCode,生命周期还会在需要时构建 .opencode/dist payload。
Install-state 是可修复性的基础
状态 schema ecc.install.v1 记录:
{
"schemaVersion": "ecc.install.v1",
"target": {"id": "claude", "root": "...", "installStatePath": "..."},
"request": {"profile": "developer", "modules": [], "includeComponents": []},
"resolution": {"selectedModules": [], "skippedModules": []},
"source": {"repoVersion": "2.1.0", "manifestVersion": 1},
"operations": []
}
于是:doctor 可以判断 managed files 是否缺失或漂移;repair 可以从可信 repo source 恢复;uninstall 只删除状态中记录的 managed files。install-lifecycle.js 还会拒绝越过 trusted root 的 source path 和 final symlink,避免 repair 成为路径穿越或任意覆盖入口。
旧安装路径如何共存
install.sh 只是 legacy shell wrapper:解析自身真实路径、必要时安装 npm 依赖,然后把参数交给 scripts/install-apply.js。这样保留了 bash ./install.sh ... 的用户习惯,同时将真实逻辑集中到 Node runtime,获得 Windows/macOS/Linux 的一致性。