Skip to content
Apothem
架构

集合打包契约

集合打包与插件清单的稳定、可供下游使用的契约——枚举集合并解析其按工具划分的原生目标,无需重新推导映射。

集合打包契约

本文档规定集合打包与插件清单的稳定、可供下游使用的契约。消费方读取本契约,以枚举集合并解析其按工具划分的原生目标,而无需重新推导映射。

工件

工件角色
src/apothem/schemas/cohort.schema.json集合清单文档的 JSON Schema。
src/apothem/schemas/cohort-manifest.yaml集合清单实例——全部六个集合(core、developer、security、research、ai-engineering、full)均已填入各自的成员集;full 是其他五个集合的并集。
src/apothem/schemas/plugin.schema.json每个包的插件清单(plugin.json)的 JSON Schema。
src/apothem/lib/propagation-manifest.yaml按工具划分的原生目标的权威来源。

集合清单形态

集合清单是一个包含三个键的顶层对象:

  • version——清单的 SemVer 字符串。
  • cohorts[]——每个集合一个条目。每个条目包含 id(取自封闭集 core | developer | security | research | ai-engineering | full)、name、description 和 members(一个按目录类型对成员标识符分组的对象:skills / agents / commands / rules / hooks)。
  • per_harness_targets——解析契约(见下文)。

每个成员标识符都是一个稳定的 kebab-case 名称,对应 src/apothem/ 下的一个真实工件(skills/<name>/、agents/<name>.md、commands/<name>.md、rules/<name>.md,或一个钩子条目——要么是可执行的 hooks/<name>.py,要么是位于 hooks/messages/<name>.md、经由分派器投递的建议性消息上下文)。

枚举集合

消费方加载 cohort-manifest.yaml,依据 cohort.schema.json 对其进行校验,然后遍历 cohorts[]。对每个集合,它读取 members.<type>,以获取每种目录类型的成员标识符。

解析按工具划分的原生目标(不重新推导)

集合清单不会重述工具映射。相反,per_harness_targets.source 指向唯一的权威来源 lib/propagation-manifest.yaml。解析规则如下:

对于目录类型为 T(skills、agents、commands、rules、hooks 之一)的集合成员,以及目标工具 H(per_harness_targets.harnesses 中列出的工具之一),原生插件目标是 lib/propagation-manifest.yaml 中 harnesses.H.install 下、其 source 匹配 T/ 的那个条目的 target 字段。

例如,为 claude_code 安装的一个 core 集合技能,经由 harnesses.claude_code.install 中带有 source: "skills/" 的条目解析为 target: "${HARNESS_ROOT}/skills/"。同一技能对于 opencode 解析为 ${HARNESS_ROOT}/skills/;对于 gemini_cli 解析为 ${PROJECT_ROOT}/.gemini/skills/。消费方从不自行编造工具目标——它们会去查找。

${HARNESS_ROOT} / ${PROJECT_ROOT} 占位符由各工具适配器在安装时解析;集合消费方按原样使用解析后的 target。

插件清单的角色

plugin.schema.json 描述一个 plugin.json——一个自描述的目录成员包(skills / commands / agents / hooks / rules),带有必需的 name、SemVer version 和 description。可选元数据包括 displayName(代替 name 显示的名称)以及插件目录收录字段:documentationUrl、supportUrl、privacyPolicyUrl 和 termsOfServiceUrl,每个都是一个 https:// URL,另有插件内部的一个 icon 路径。生成的 Claude Code 包设置了 displayName、documentationUrl 和 supportUrl。Anthropic 的目录会读取这些收录字段,而 Claude Code 在加载时忽略它们。claude.ai 市场同步会把这两个链接报告为无法识别的键并将其剥离,因此那里的市场会显示“1 with warnings”。该警告属于预期情况,插件照常加载、不受影响。插件清单是工具适配器物化到其原生插件表面的单元;集合选择插件携带哪些成员,而传播清单解析这些成员在每个工具中的落地位置。

打包决策——一个总括包,逻辑集合

集合是一个逻辑选择层(即本清单),而不是一组彼此分离、可独立安装的包。Apothem 提供一个总括包,承载完整目录;集合清单让消费方挑选一个连贯的子集,而传播清单解析每个被选中的成员在每个工具中的落地位置。

将目录拆分为彼此分离的按集合划分的包(例如 developer / security / research 每个家族一个包)无需仓库级重复即可实现,方式是采用主要分发表面所记录的元插件符号链接模式:一个市场目录列出若干集合插件,每个集合插件目录中存放的是指向单一来源共享目录的符号链接,而不是副本。安装某个集合时,工具会解引用每个市场内部的符号链接——将目标的内容复制到该集合的缓存中——因此已安装的集合是自包含的,而仓库保留一个由符号链接连接起来的唯一权威来源(以连接取代冗余,正是去重纪律所偏好的做法)。早先认为集合包会“机械地复制”目录的解读,混淆了安装时缓存的重复(工具正常的按插件复制)与仓库的重复;符号链接模式避免的是后者。

Apothem 目前提供一个总括包,是因为这是最简单的分发表面,而不是因为集合在机制上不可行。采用按集合划分的形式是一项真实的 UX 与维护权衡,而不是对去重的违背:好处是更细粒度的“只安装这个家族”体验;代价是维护 N 个集合符号链接目录及其市场条目、更大的合规 / 测试 / 黄金基准表面,以及按集合的安装时缓存副本。上述逻辑集合层已经从单一包中实现了“只安装你需要的”这一选择结果;每当需要更细粒度的安装 UX 时,按集合的打包就是下一步。

On this page