Files
.pouch/skiff/source-model.md
T
ace 47bd454fa3 feat(builder): merge deb-publisher + publish-docker-image into contract-driven builder skill
- skills/builder: SKILL.md, README.md, references/contract.md (make/publish
  contract v1), references/registry.md
- scripts/check.py: executable contract checker (make dry-run probes, secret
  scan, push thin-wrapper and script path checks; --build verifies real .deb)
- scripts/upload_deb.sh: migrated from deb-publisher, adds project .env
  auto-load and dirty-worktree publish gate
- scripts/publish_docker.sh: migrated from publish-docker-image publish.sh,
  now env-first (DOCKER_REGISTRY/REPOSITORY/IMAGE_TAG/PLATFORMS), refuses
  floating latest and multi-platform --load
- scripts/verify_deb.sh: metadata/content/sha256 verification with v-prefix
  normalization
- orc: deb+docker stages both route to $builder; routing table, DAGs,
  README, config untouched stage names; tests updated
- ack delivery.md + skiff source-model.md: reference builder
- remove skills/deb-publisher and skills/publish-docker-image
2026-08-24 12:52:53 +08:00

218 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Skill 来源模型
## 背景
skiff 当前使用 `owned` 表示本仓库 `skills/` 中维护的 Skill,同时还支持
`registry` 外部仓库和用户配置的 custom source。
这些名称混合了不同维度:
- `owned` 表示所有权。
- `registry` 表示来源配置存放在哪里。
- `external` 表示内容不在当前仓库。
- `collection` 表示一个来源中包含多个 Skill。
它们不能作为同一层级的互斥类型。例如 custom source 既可能来自外部 Git 仓库,
也可能是 collection;因此 `custom``external` 并不互斥。
本文建议将用户可见的来源注册方式统一为三类:
- `builtin`:随当前 skiff 仓库提供的 Skill。
- `catalog:<name>`:由 skiff 自带目录预先登记的来源。
- `custom:<name>`:用户在本机显式配置的命名来源。
来源注册方式与获取方式、仓库布局相互独立。builtin、catalog 和 custom 中的任意
来源都可以包含一个或多个 Skill;除 builtin 外,catalog 和 custom 都可以使用
Git 仓库或本地目录。
## 迁移前模型
```mermaid
flowchart TD
S[skiff 可发现的 Skills]
S --> O["owned<br/>~/.skills/skills/*"]
S --> C["custom source<br/>~/.config/skiff/config.yaml"]
S --> R["registry<br/>registry.yaml"]
O --> O1["本仓库维护<br/>随 skiff 一起分发"]
C --> C1["本地目录<br/>--local PATH"]
C --> C2["指定 Git 仓库<br/>repo + skills_path"]
R --> R1["外部单 Skill 仓库"]
R --> R2["外部 Skill Collection"]
R1 --> E["~/.local/share/skills/externals/"]
R2 --> E
```
迁移前实现中:
- `list``status` 支持 owned、registry 和 custom source。
- `resolve_skill_source` 可以解析三种来源并处理同名歧义。
- `select` 只组装 owned 和 registry 条目,尚未展示 custom source。
- `.skills.yaml` 默认将未声明来源的 Skill 解释为 `owned`
- custom source 的 `skills_path` 已经可以包含多个 Skill,本质上也是 collection。
## 现行模型
```mermaid
flowchart TD
A[Skill Provider]
A --> B["builtin<br/>仓库内隐式注册"]
A --> C["catalog:waza<br/>skiff 预置目录"]
A --> D["custom:company<br/>用户本机配置"]
B --> B1["skills/ack"]
B --> B2["skills/skiff"]
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` | 随当前 skiff 仓库提供 | `skills/` | `builtin` |
| `catalog` | skiff 预先登记、所有用户可发现的来源 | `catalog.yaml` | `catalog:<name>` |
| `custom` | 用户在本机显式注册的命名来源 | `~/.config/skiff/config.yaml` | `custom:<name>` |
`builtin``owned` 更适合作为用户可见名称,因为它表达 Skill 的分发位置和可用
方式,而不是仓库的所有权关系。
`catalog``registry` 更准确:当前文件只是 skiff 随仓库维护的预置来源目录,
并不是远程注册中心,也不是一种 Skill 来源协议。
### 三个正交维度
每个 provider 应由三个维度描述:
```text
registration: builtin | catalog | custom
transport: bundled | local | git
layout: single | collection
```
custom source 示例:
```text
registration: custom
name: company
transport: local | git
layout: single | collection
```
catalog entry 示例:
```text
registration: catalog
name: waza
transport: local | git
layout: single | collection
```
`external` 只适合描述物理位置,可作为 catalog 和部分 custom provider 的统称,
不应成为与 builtin、custom 并列的持久化类型。
## `select` 展示
`skiff select` 应同时展示 builtin、catalog 和 custom Skill
```text
[ ] 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 来源可以省略父节点,但仍显示注册方式和来源名称。
- 不同来源安装后名称相同时,继续拒绝同时选择,避免覆盖同一安装路径。
## 配置表示
新写入的 `.skills.yaml` 使用以下形式:
```yaml
skills:
- name: ack
source: builtin
- name: security-review
source: company
- name: think
source: catalog:waza
```
custom source 在 manifest 中继续保存其逻辑名称,例如 `company`。这样不同机器可以
独立配置仓库地址,而项目只依赖稳定的来源名称。
## 兼容策略
用户可见术语已经调整,并保留以下读取兼容,避免已有项目立即失效:
1. 对外文档、CLI 输出和 selector 统一使用 `builtin``catalog:<name>`
`custom:<name>`
2. 新生成的 `.skills.yaml` 对内置 Skill 写入 `source: builtin`
3. 读取旧 manifest 时继续接受 `source: owned`,并在解析时归一化为 `builtin`
4. CLI 参数在过渡期继续接受 `--source owned`,但帮助和输出只推荐 `builtin`
5. 读取旧 manifest 中的 `source: registry``registry: <name>`,归一化为
`catalog:<name>`
6. 主文件使用 `catalog.yaml`;不存在时兼容读取旧 `registry.yaml`
7. custom source 的逻辑名称和现有 `config.yaml` 结构保持不变。
8.`builtin``catalog` 和兼容别名 `owned``registry` 设为 custom source
保留字。
9. `select` 同步接入 custom Skill,并让 custom collection 与 catalog collection
使用相同的父子展示逻辑。
## 实现范围
当前实现覆盖:
- `skiff/skills.py`:来源解析、归一化和 builtin 命名。
- `skiff/project.py`:manifest 默认值、序列化与旧值兼容。
- `skiff/sources.py`:来源保留字。
- `skiff/catalog.py`catalog 配置、checkout 与 Skill 发现。
- `skiff/cli.py``list``status``add``select` 和输出文案。
- `skiff/selector.py`:统一 catalog/custom collection 的父子展示。
- CLI 与来源解析测试。
- 根 README、`skiff/README.md``skills/skiff/SKILL.md` 和相关示例。
## 验证要求
实施完成后至少覆盖:
- builtin Skill 可以通过新名称列出、选择、安装和写入 manifest。
- 旧的 `source: owned` manifest 仍可同步。
- custom local source 和 custom Git source 都出现在 selector 中。
- catalog 单 Skill 和 Collection 都保持可选择。
- custom 单 Skill 和 Collection 都保持可选择。
- 多来源同名 Skill 必须显式指定来源。
- 两个选择最终安装为同一个名称时,selector 拒绝冲突。
- `list``status``select` 对同一来源使用一致术语。
## 设计前提
迁移前 `registry.yaml` 的真实职责只是维护 skiff 预置的来源目录,而不是提供远程
发布、版本解析或可信签名等注册中心能力,因此现已改为 `catalog.yaml`。如果未来
实现真正的远程 registry,应单独定义其协议和与 catalog 的同步关系,不复用旧名称。