Files
.pouch/pouch/source-model.md
laily f3cd56b78e feat: rename skills/skiff to pouch and move ACK state under .pouch
Use ~/.pouch, the pouch CLI, and .pouch.yaml as the SSOT container.
Keep the inner skills/ packages, and store ACK project state in
.pouch/ack instead of docs/ack.
2026-08-25 15:20:02 +08:00

7.5 KiB
Raw Permalink Blame History

Skill 来源模型

背景

pouch 当前使用 owned 表示本仓库 skills/ 中维护的 Skill,同时还支持 registry 外部仓库和用户配置的 custom source。

这些名称混合了不同维度:

  • owned 表示所有权。
  • registry 表示来源配置存放在哪里。
  • external 表示内容不在当前仓库。
  • collection 表示一个来源中包含多个 Skill。

它们不能作为同一层级的互斥类型。例如 custom source 既可能来自外部 Git 仓库, 也可能是 collection;因此 customexternal 并不互斥。

本文建议将用户可见的来源注册方式统一为三类:

  • builtin:随当前 pouch 仓库提供的 Skill。
  • catalog:<name>:由 pouch 自带目录预先登记的来源。
  • custom:<name>:用户在本机显式配置的命名来源。

来源注册方式与获取方式、仓库布局相互独立。builtin、catalog 和 custom 中的任意 来源都可以包含一个或多个 Skill;除 builtin 外,catalog 和 custom 都可以使用 Git 仓库或本地目录。

迁移前模型

flowchart TD
    S[pouch 可发现的 Skills]

    S --> O["owned<br/>~/.pouch/skills/*"]
    S --> C["custom source<br/>~/.config/pouch/config.yaml"]
    S --> R["registry<br/>registry.yaml"]

    O --> O1["本仓库维护<br/>随 pouch 一起分发"]

    C --> C1["本地目录<br/>--local PATH"]
    C --> C2["指定 Git 仓库<br/>repo + skills_path"]

    R --> R1["外部单 Skill 仓库"]
    R --> R2["外部 Skill Collection"]
    R1 --> E["~/.local/share/pouch/externals/"]
    R2 --> E

迁移前实现中:

  • liststatus 支持 owned、registry 和 custom source。
  • resolve_skill_source 可以解析三种来源并处理同名歧义。
  • select 只组装 owned 和 registry 条目,尚未展示 custom source。
  • .pouch.yaml 默认将未声明来源的 Skill 解释为 owned
  • custom source 的 skills_path 已经可以包含多个 Skill,本质上也是 collection。

现行模型

flowchart TD
    A[Skill Provider]

    A --> B["builtin<br/>仓库内隐式注册"]
    A --> C["catalog:waza<br/>pouch 预置目录"]
    A --> D["custom:company<br/>用户本机配置"]

    B --> B1["skills/ack"]
    B --> B2["skills/pouch"]
    B --> B3["skills/builder"]

    C --> C1["Git 或本地目录"]
    C1 --> C2["单 Skill"]
    C1 --> C3["Collection"]
    C3 --> C4["waza/think"]
    C3 --> C5["waza/check"]

    D --> D1["Git 或本地目录"]
    D1 --> D2["单 Skill"]
    D1 --> D3["Collection"]
    D3 --> D4["company/security-review"]
    D3 --> D5["company/release"]

来源注册方式

类型 含义 配置来源 用户界面展示
builtin 随当前 pouch 仓库提供 skills/ builtin
catalog pouch 预先登记、所有用户可发现的来源 catalog.yaml catalog:<name>
custom 用户在本机显式注册的命名来源 ~/.config/pouch/config.yaml custom:<name>

builtinowned 更适合作为用户可见名称,因为它表达 Skill 的分发位置和可用 方式,而不是仓库的所有权关系。

catalogregistry 更准确:当前文件只是 pouch 随仓库维护的预置来源目录, 并不是远程注册中心,也不是一种 Skill 来源协议。

三个正交维度

每个 provider 应由三个维度描述:

registration: builtin | catalog | custom
transport:    bundled | local | git
layout:       single | collection

custom source 示例:

registration: custom
name:         company
transport:    local | git
layout:       single | collection

catalog entry 示例:

registration: catalog
name:         waza
transport:    local | git
layout:       single | collection

external 只适合描述物理位置,可作为 catalog 和部分 custom provider 的统称, 不应成为与 builtin、custom 并列的持久化类型。

select 展示

pouch select 应同时展示 builtin、catalog 和 custom Skill

[ ] ack                         builtin
[ ] builder                     builtin
[-] company                     custom source
    [ ] company/release         custom:company
    [ ] company/security-review custom:company
[-] waza                        catalog source
    [ ] waza/check              catalog:waza
    [ ] waza/think              catalog:waza

建议遵循以下规则:

  • builtin Skill 直接显示 Skill 名称。
  • catalog 和 custom collection 都使用来源名称作为父节点。
  • catalog 和 custom Skill 都使用 <source>/<skill> 作为选择器键。
  • 单 Skill 来源可以省略父节点,但仍显示注册方式和来源名称。
  • 不同来源安装后名称相同时,继续拒绝同时选择,避免覆盖同一安装路径。

配置表示

新写入的 .pouch.yaml 使用以下形式:

skills:
  - name: ack
    source: builtin
  - name: security-review
    source: company
  - name: think
    source: catalog:waza

custom source 在 manifest 中继续保存其逻辑名称,例如 company。这样不同机器可以 独立配置仓库地址,而项目只依赖稳定的来源名称。

兼容策略

用户可见术语已经调整,并保留以下读取兼容,避免已有项目立即失效:

  1. 对外文档、CLI 输出和 selector 统一使用 builtincatalog:<name>custom:<name>
  2. 新生成的 .pouch.yaml 对内置 Skill 写入 source: builtin
  3. 读取旧 manifest 时继续接受 source: owned,并在解析时归一化为 builtin
  4. CLI 参数在过渡期继续接受 --source owned,但帮助和输出只推荐 builtin
  5. 读取旧 manifest 中的 source: registryregistry: <name>,归一化为 catalog:<name>
  6. 主文件使用 catalog.yaml;不存在时兼容读取旧 registry.yaml
  7. custom source 的逻辑名称和现有 config.yaml 结构保持不变。
  8. builtincatalog 和兼容别名 ownedregistry 设为 custom source 保留字。
  9. select 同步接入 custom Skill,并让 custom collection 与 catalog collection 使用相同的父子展示逻辑。

实现范围

当前实现覆盖:

  • pouch/skills.py:来源解析、归一化和 builtin 命名。
  • pouch/project.py:manifest 默认值、序列化与旧值兼容。
  • pouch/sources.py:来源保留字。
  • pouch/catalog.pycatalog 配置、checkout 与 Skill 发现。
  • pouch/cli.pyliststatusaddselect 和输出文案。
  • pouch/selector.py:统一 catalog/custom collection 的父子展示。
  • CLI 与来源解析测试。
  • 根 README、pouch/README.mdskills/pouch/SKILL.md 和相关示例。

验证要求

实施完成后至少覆盖:

  • builtin Skill 可以通过新名称列出、选择、安装和写入 manifest。
  • 旧的 source: owned manifest 仍可同步。
  • custom local source 和 custom Git source 都出现在 selector 中。
  • catalog 单 Skill 和 Collection 都保持可选择。
  • custom 单 Skill 和 Collection 都保持可选择。
  • 多来源同名 Skill 必须显式指定来源。
  • 两个选择最终安装为同一个名称时,selector 拒绝冲突。
  • liststatusselect 对同一来源使用一致术语。

设计前提

迁移前 registry.yaml 的真实职责只是维护 pouch 预置的来源目录,而不是提供远程 发布、版本解析或可信签名等注册中心能力,因此现已改为 catalog.yaml。如果未来 实现真正的远程 registry,应单独定义其协议和与 catalog 的同步关系,不复用旧名称。