skill-flow 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -23
- package/README.zh.md +63 -25
- package/dist/cli.js +13 -39
- package/dist/cli.js.map +1 -1
- package/dist/domain/types.d.ts +12 -1
- package/dist/services/doctor-service.js +1 -1
- package/dist/services/doctor-service.js.map +1 -1
- package/dist/services/skill-flow.d.ts +16 -13
- package/dist/services/skill-flow.js +158 -5
- package/dist/services/skill-flow.js.map +1 -1
- package/dist/services/source-service.d.ts +11 -1
- package/dist/services/source-service.js +60 -18
- package/dist/services/source-service.js.map +1 -1
- package/dist/services/workflow-service.d.ts +2 -2
- package/dist/services/workflow-service.js +17 -4
- package/dist/services/workflow-service.js.map +1 -1
- package/dist/services/workspace-bootstrap-service.d.ts +25 -0
- package/dist/services/workspace-bootstrap-service.js +148 -0
- package/dist/services/workspace-bootstrap-service.js.map +1 -0
- package/dist/state/store.js +1 -0
- package/dist/state/store.js.map +1 -1
- package/dist/tests/skill-flow.test.js +1458 -0
- package/dist/tests/skill-flow.test.js.map +1 -1
- package/dist/tui/config-app.d.ts +3 -0
- package/dist/tui/config-app.js +61 -1
- package/dist/tui/config-app.js.map +1 -1
- package/dist/tui/find-app.d.ts +1 -1
- package/dist/tui/find-app.js +36 -4
- package/dist/tui/find-app.js.map +1 -1
- package/dist/utils/format.js +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/naming.d.ts +1 -0
- package/dist/utils/naming.js +7 -1
- package/dist/utils/naming.js.map +1 -1
- package/dist/utils/source-id.js +4 -0
- package/dist/utils/source-id.js.map +1 -1
- package/package.json +10 -1
- package/.gstack/browse-network.log +0 -1
- package/.gstack/browse.json +0 -7
- package/.gstack/qa-reports/base-branch.txt +0 -1
- package/.gstack/qa-reports/qa-report-skill-flow-cli-2026-03-22.md +0 -159
- package/.gstack/qa-reports/qa-report-skill-manager-2026-03-22.md +0 -60
- package/docs/DESIGN.md +0 -407
- package/docs/PRD/PRD-1.0.0.md +0 -1862
- package/docs/PRD/renew/PRD-0.0.0.md +0 -26
- package/docs/PRD/renew/PRD-0.0.1.md +0 -408
- package/docs/PRD/renew/PRD-0.0.2.md +0 -705
- package/docs/PRD/renew/PRD-0.0.3.md +0 -740
- package/docs/PRD/renew/PRD-0.0.4.md +0 -1494
- package/docs/README.md +0 -242
- package/docs/plan/PLAN_v1.0.0.md +0 -663
- package/docs/plan/PLAN_v1.0.1.md +0 -845
- package/docs/refrences/README.md +0 -9
- package/docs/refrences/agent-skill-paths.md +0 -274
- package/docs/refrences/config-state-reconciliation.md +0 -199
- package/docs/refrences/naming-dedupe-warning-rules.md +0 -482
- package/img/img-1.jpg +0 -0
package/docs/PRD/PRD-1.0.0.md
DELETED
|
@@ -1,1862 +0,0 @@
|
|
|
1
|
-
# skill-flow PRD + 工程实施文档(Discovery / Find Skills 修订版)
|
|
2
|
-
|
|
3
|
-
> 版本:v1.2
|
|
4
|
-
> 文档性质:定型版 PRD + 工程实施规范
|
|
5
|
-
> 产出方式:基于 Martin Fowler / Isaac Z. Schlueter / Mitchell Hashimoto 三人视角多轮讨论后收敛
|
|
6
|
-
> 平台:macOS(MVP)
|
|
7
|
-
> 启动命令:`skill-flow`
|
|
8
|
-
> 数据目录:`~/.skillflow/`
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# 一、三人多轮讨论纪要
|
|
13
|
-
|
|
14
|
-
## 第一轮:先定边界,这到底是不是“包管理器”?
|
|
15
|
-
|
|
16
|
-
### Martin Fowler
|
|
17
|
-
“它不是一个下载器。下载只是入口。真正的产品边界应该是:`Source → SkillLeaf → Channel → Deployment`。只要这个边界不清,后面 `config`、`update`、`uninstall` 都会混成文件搬运。”
|
|
18
|
-
|
|
19
|
-
### Isaac Z. Schlueter
|
|
20
|
-
“如果没有锁定层,它就不是 manager,只是 installer。你一旦要支持多来源、多技能仓库、多渠道分发,就必须记录用户意图和解析结果,否则更新、回滚、恢复安装都不可靠。”
|
|
21
|
-
|
|
22
|
-
### Mitchell Hashimoto
|
|
23
|
-
“CLI 不是把能力堆成命令。真正的主流程只有一个:`add source -> inspect inventory -> choose channels -> apply deployments`。用户不该理解内部状态文件,但状态文件必须非常强。”
|
|
24
|
-
|
|
25
|
-
### 本轮结论
|
|
26
|
-
|
|
27
|
-
1. 产品正式定义为:**一个面向 Agent Skills 生态的 CLI 包管理器与渠道投影器**。
|
|
28
|
-
2. 系统边界只负责:**获取、扫描、校验、索引、锁定、分发、更新、卸载、诊断**。
|
|
29
|
-
3. 系统明确**不负责执行 skill**,也不对 skill 脚本做运行时沙箱承诺。
|
|
30
|
-
4. 数据模型固定为:`Source / SourceSnapshot / SkillLeaf / Channel / Deployment / Manifest / Lock`。
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## 第二轮:Source 怎么建模,仓库和 skill 的关系是什么?
|
|
35
|
-
|
|
36
|
-
### Martin Fowler
|
|
37
|
-
“仓库不是 skill。仓库是 source root,skill 才是 leaf。否则你没法表达一个仓库里多个技能,也没法做你要的一级/二级树选择。”
|
|
38
|
-
|
|
39
|
-
### Isaac Z. Schlueter
|
|
40
|
-
“更新也必须以 source 为单位,而不是 skill 为单位。因为上游版本边界属于 source。你可以按 skill 选择是否部署,但不能按 skill 伪造上游版本。”
|
|
41
|
-
|
|
42
|
-
### Mitchell Hashimoto
|
|
43
|
-
“UI 上可以把 source 展示成一级目录,把 skill 展示成二级节点;但内部一定要有稳定的 `sourceId` 和 `skillId`,不能依赖展示名。”
|
|
44
|
-
|
|
45
|
-
### 本轮结论
|
|
46
|
-
|
|
47
|
-
1. **Source 是上游单位**:Git 仓库、ClawHub slug、未来的 well-known URL。
|
|
48
|
-
2. **SkillLeaf 是可安装单位**:一个合法 skill root。
|
|
49
|
-
3. **Source 与 SkillLeaf 是一对多关系**。
|
|
50
|
-
4. “两层结构”正式进入领域模型,而不是只作为 UI 细节。
|
|
51
|
-
5. internal id 与 display label 分离:
|
|
52
|
-
- internal:稳定、不可读也没关系
|
|
53
|
-
- display:仓库名 / 作者名 / `single`
|
|
54
|
-
|
|
55
|
-
---
|
|
56
|
-
|
|
57
|
-
## 第三轮:Channel 不是路径字符串,而是适配器
|
|
58
|
-
|
|
59
|
-
### Martin Fowler
|
|
60
|
-
“Channel 必须是 adapter,不是 path。因为 Claude、OpenCode、Codex、OpenClaw 的发现规则、优先级、兼容路径、以及对 symlink 的容忍度都不一样。”
|
|
61
|
-
|
|
62
|
-
### Isaac Z. Schlueter
|
|
63
|
-
“同一个 leaf 投影到不同 channel,可以是不同 strategy。manager 的任务不是追求实现统一,而是追求状态统一。”
|
|
64
|
-
|
|
65
|
-
### Mitchell Hashimoto
|
|
66
|
-
“用户界面里可以看到都是‘一个目标’,但产品内部必须知道:Claude 默认是 per-skill symlink,OpenClaw 默认要 copy。”
|
|
67
|
-
|
|
68
|
-
### 本轮结论
|
|
69
|
-
|
|
70
|
-
正式把 Channel 定义为:
|
|
71
|
-
|
|
72
|
-
- 一个**目标目录解析器**
|
|
73
|
-
- 一个**发现规则集合**
|
|
74
|
-
- 一个**分发策略集合**
|
|
75
|
-
- 一个**诊断器**
|
|
76
|
-
|
|
77
|
-
而不是一个简单路径。
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## 第四轮:锁文件要不要做成“一等公民”?
|
|
82
|
-
|
|
83
|
-
### Isaac Z. Schlueter
|
|
84
|
-
“必须,而且不是一个文件,而是两个层级:manifest 记录用户意图,lock 记录解析结果。否则用户选了哪些 channel、哪些 skill,是‘期望状态’;上游实际解析到的 commit/version/hash,是‘已解析状态’。这两个不能混。”
|
|
85
|
-
|
|
86
|
-
### Martin Fowler
|
|
87
|
-
“同意。manifest 是 policy,lock 是 materialized view。”
|
|
88
|
-
|
|
89
|
-
### Mitchell Hashimoto
|
|
90
|
-
“从 CLI 体验上,这意味着 `config` 改的是 manifest,`apply/update` 刷的是 lock。这样 `doctor` 才能告诉用户:你的意图没变,但当前部署漂移了。”
|
|
91
|
-
|
|
92
|
-
### 本轮结论
|
|
93
|
-
|
|
94
|
-
MVP 固定采用双文件状态:
|
|
95
|
-
|
|
96
|
-
- `manifest.json`:用户意图
|
|
97
|
-
- `lock.json`:解析结果与部署状态
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## 第五轮:MVP 里到底支持哪些 Source?
|
|
102
|
-
|
|
103
|
-
### Martin Fowler
|
|
104
|
-
“从建模上要预留 `SourceAdapter`,但 MVP 不要把来源铺太大。”
|
|
105
|
-
|
|
106
|
-
### Isaac Z. Schlueter
|
|
107
|
-
“Git 一定要是第一优先级,因为它天然有 snapshot。ClawHub 可以做第二优先级,因为它已经有 version/store/lock 语义。”
|
|
108
|
-
|
|
109
|
-
### Mitchell Hashimoto
|
|
110
|
-
“`search` 的体验不能太弱,但 GitHub 关键词搜索的结果质量不一定稳定。MVP 里要区分:`add` 支持显式 locator,`search` 则优先做有结构化结果的来源。”
|
|
111
|
-
|
|
112
|
-
### 本轮结论
|
|
113
|
-
|
|
114
|
-
MVP Source 范围定为:
|
|
115
|
-
|
|
116
|
-
1. **Git Source**
|
|
117
|
-
- 必做
|
|
118
|
-
- 支持 GitHub repo / 任意 git URL / 本地 git 路径
|
|
119
|
-
2. **ClawHub Source**
|
|
120
|
-
- 必做
|
|
121
|
-
- 作为注册表来源
|
|
122
|
-
3. **Well-known Skills Discovery**
|
|
123
|
-
- 只预留接口,P1 再做
|
|
124
|
-
|
|
125
|
-
---
|
|
126
|
-
|
|
127
|
-
## 第六轮:分发策略拍板
|
|
128
|
-
|
|
129
|
-
### Martin Fowler
|
|
130
|
-
“要遵循渠道现实,不要为了‘统一’牺牲兼容。”
|
|
131
|
-
|
|
132
|
-
### Isaac Z. Schlueter
|
|
133
|
-
“中心化 canonical store 没问题,但投影策略必须 per-channel。”
|
|
134
|
-
|
|
135
|
-
### Mitchell Hashimoto
|
|
136
|
-
“用户应该默认感知不到复杂性,所以策略要自动选,只在 `doctor` 和 advanced config 里解释。”
|
|
137
|
-
|
|
138
|
-
### 本轮结论
|
|
139
|
-
|
|
140
|
-
- Claude Code:**per-skill symlink** 默认,copy 兜底
|
|
141
|
-
- OpenCode:**symlink** 默认
|
|
142
|
-
- Codex:**symlink** 默认
|
|
143
|
-
- 通用 `.agents/skills`:**symlink** 默认
|
|
144
|
-
- OpenClaw:**copy** 默认,不走跨根 symlink
|
|
145
|
-
|
|
146
|
-
---
|
|
147
|
-
|
|
148
|
-
## 第七轮:技术栈正式定型
|
|
149
|
-
|
|
150
|
-
### Mitchell Hashimoto
|
|
151
|
-
“既然 `config` 是树状 TUI,终端 UI 就不是附属品,而是主界面。Ink 很合适。”
|
|
152
|
-
|
|
153
|
-
### Isaac Z. Schlueter
|
|
154
|
-
“如果你选 Node,就选当前 LTS 主线,不要用已进入 maintenance 的版本。”
|
|
155
|
-
|
|
156
|
-
### Martin Fowler
|
|
157
|
-
“技术栈要服务模型稳定和 schema 演进,所以 Zod、atomic writes、fixture-based tests 都该是正式要求,不是实现偏好。”
|
|
158
|
-
|
|
159
|
-
### 本轮结论
|
|
160
|
-
|
|
161
|
-
正式技术栈:
|
|
162
|
-
|
|
163
|
-
- Runtime:**Node.js 24 LTS**
|
|
164
|
-
- Language:**TypeScript 5.x**
|
|
165
|
-
- Package manager:**pnpm**
|
|
166
|
-
- CLI framework:**oclif**
|
|
167
|
-
- TUI:**Ink**
|
|
168
|
-
- Schema validation:**Zod**
|
|
169
|
-
- Git wrapper:**system git + simple-git**
|
|
170
|
-
- Test:**Vitest**
|
|
171
|
-
- Distribution:**npm first,Homebrew tap in P1**
|
|
172
|
-
|
|
173
|
-
---
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
## 第八轮:`find skills` 不是附属命令,而是一条完整 Discovery 工作流
|
|
177
|
-
|
|
178
|
-
### Martin Fowler
|
|
179
|
-
“你现在的文档把 install / update / deploy 写清楚了,但 discover / recommend 还不是一等能力。`search` 只是命令,不是领域流程。真正缺的是:搜索结果模型、来源分层、推荐依据、安装前解释、安装后反馈。”
|
|
180
|
-
|
|
181
|
-
### Isaac Z. Schlueter
|
|
182
|
-
“只要做 discovery,就必须把 catalog、trust、installed state、install method 纳入状态模型。否则 `search` 出来的只是字符串,不是 package candidate。”
|
|
183
|
-
|
|
184
|
-
### Mitchell Hashimoto
|
|
185
|
-
“用户真正的问题通常不是 ‘给我一个 repo URL’,而是 ‘我想做 X,有没有 skill 能解决?哪个值得信?我装过没有?能不能现在直接装?装完要不要刷新客户端?’ 所以 CLI 需要 `find -> inspect -> install/apply` 这条一等路径。”
|
|
186
|
-
|
|
187
|
-
### 本轮结论
|
|
188
|
-
|
|
189
|
-
1. `search` 正式升级为 **Discovery 工作流**,并新增主命令 `find`,`search` 保留为兼容别名。
|
|
190
|
-
2. Discovery 必须有自己的领域输出:`SkillCandidate`,而不是直接返回 source 文本。
|
|
191
|
-
3. PRD 必须补齐:
|
|
192
|
-
- Discovery Goals / Non-Goals
|
|
193
|
-
- Discovery Source Tiers
|
|
194
|
-
- Search Result Schema & Ranking
|
|
195
|
-
- Quick Install / Direct Install
|
|
196
|
-
- Installed Annotations & Post-Install Feedback
|
|
197
|
-
- Channel Feature Compatibility Matrix
|
|
198
|
-
- Source Inventory Index
|
|
199
|
-
4. 产品正式从 **manager / installer / deployer** 扩展为 **finder / recommender / installer / deployer / manager**。
|
|
200
|
-
|
|
201
|
-
# 二、skill-flow 定型版 PRD
|
|
202
|
-
|
|
203
|
-
## 1. 产品定义
|
|
204
|
-
|
|
205
|
-
`skill-flow` 是一个面向 Agent Skills 生态的 macOS CLI。它既是统一的 Skills 包管理器,也是一个 Discovery / Find Skills 入口。它统一管理多来源 skills,把上游内容下载到 `~/.skillflow/source/`,扫描出合法的 `SkillLeaf`,在 `~/.skillflow/skills/` 建立 canonical skill 集合,再将用户选中的 skill 以适配渠道的方式分发到 Claude Code、OpenCode、Codex、OpenClaw 与通用 `.agents/skills`。其核心职责是**索引与投影**,不是执行 skill。
|
|
206
|
-
|
|
207
|
-
## 2. 目标与非目标
|
|
208
|
-
|
|
209
|
-
### 2.1 目标
|
|
210
|
-
|
|
211
|
-
MVP 要完成六件事:
|
|
212
|
-
|
|
213
|
-
1. 支持 Git Source 与 ClawHub Source 的添加、扫描、更新、卸载。
|
|
214
|
-
2. 支持“单 source 多 skill”的两层树状模型。
|
|
215
|
-
3. 支持 `skill-flow config` 的树形多选 TUI。
|
|
216
|
-
4. 支持按 channel 投影:Claude Code、OpenCode、Codex、OpenClaw、`.agents/skills`。
|
|
217
|
-
5. 支持 `manifest.json + lock.json` 双层状态。
|
|
218
|
-
6. 支持 `doctor` 做冲突、漂移、路径和兼容性检查。
|
|
219
|
-
|
|
220
|
-
### 2.2 非目标
|
|
221
|
-
|
|
222
|
-
MVP 不做以下事情:
|
|
223
|
-
|
|
224
|
-
1. 不执行 skill 中的脚本。
|
|
225
|
-
2. 不修改上游 `SKILL.md`。
|
|
226
|
-
3. 不做 GUI。
|
|
227
|
-
4. 不做通用 project-scope 管理;只有 OpenClaw 因官方工作区模型原因,保留 workspace 渠道。
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
### 2.3 Discovery 目标
|
|
231
|
-
|
|
232
|
-
MVP 的 Discovery 能力要解决五件事:
|
|
233
|
-
|
|
234
|
-
1. 当用户只有“能力诉求”而没有具体来源时,帮助其找到可安装候选。
|
|
235
|
-
2. 区分“已安装 / 未安装 / 已内置 / 已预装”状态,避免重复推荐。
|
|
236
|
-
3. 把来源可信度、安装量、官方属性、支持渠道、风险提示纳入结果展示。
|
|
237
|
-
4. 支持从候选结果直接安装单个 skill 或整个 source。
|
|
238
|
-
5. 在安装完成后给出下一步动作:是否需要刷新、重启、重新扫描或执行 `config`。
|
|
239
|
-
|
|
240
|
-
### 2.4 Discovery 非目标
|
|
241
|
-
|
|
242
|
-
MVP Discovery 不做以下事情:
|
|
243
|
-
|
|
244
|
-
1. 不做自然语言生成式推荐排名模型;先采用显式规则排序。
|
|
245
|
-
2. 不承诺全网搜索;优先覆盖结构化来源与本地 inventory。
|
|
246
|
-
3. 不把 commands / agents / plugins 全部纳入统一安装对象;MVP 只管理合法 `SKILL.md` skill。
|
|
247
|
-
4. 不把内部 inventory index 对外承诺为开放标准。
|
|
248
|
-
|
|
249
|
-
## 3. 用户与典型场景
|
|
250
|
-
|
|
251
|
-
目标用户是同时使用多个 AI coding agent 的开发者。他们的高频动作是:
|
|
252
|
-
|
|
253
|
-
- 从 GitHub 或 ClawHub 获取 skills
|
|
254
|
-
- 统一查看一个 source 里有哪些 skill
|
|
255
|
-
- 把其中部分 skill 应用到某个或全部渠道
|
|
256
|
-
- 后续更新 source,并同步刷新多个渠道
|
|
257
|
-
- 卸载整个 source,或仅取消某个 channel 的启用状态
|
|
258
|
-
|
|
259
|
-
## 4. 领域模型
|
|
260
|
-
|
|
261
|
-
### 4.1 Source
|
|
262
|
-
|
|
263
|
-
一个可更新的上游单位。
|
|
264
|
-
|
|
265
|
-
字段建议:
|
|
266
|
-
|
|
267
|
-
- `sourceId`
|
|
268
|
-
- `sourceType`
|
|
269
|
-
- `locator`
|
|
270
|
-
- `displayName`
|
|
271
|
-
- `storageRoot`
|
|
272
|
-
- `updateStrategy`
|
|
273
|
-
|
|
274
|
-
### 4.2 SourceSnapshot
|
|
275
|
-
|
|
276
|
-
Source 在某一时刻的解析快照。
|
|
277
|
-
|
|
278
|
-
- git:`remote + branch + commit SHA`
|
|
279
|
-
- clawhub:`slug + version + contentHash`
|
|
280
|
-
- future well-known:`baseUrl + indexHash/etag`
|
|
281
|
-
|
|
282
|
-
### 4.3 SkillLeaf
|
|
283
|
-
|
|
284
|
-
真正可安装的 skill 单元。满足条件:
|
|
285
|
-
|
|
286
|
-
- 存在 `SKILL.md`
|
|
287
|
-
- frontmatter 可解析
|
|
288
|
-
- `name`
|
|
289
|
-
- `description`
|
|
290
|
-
|
|
291
|
-
字段建议:
|
|
292
|
-
|
|
293
|
-
- `skillId`
|
|
294
|
-
- `sourceId`
|
|
295
|
-
- `name`
|
|
296
|
-
- `description`
|
|
297
|
-
- `relativeRoot`
|
|
298
|
-
- `contentHash`
|
|
299
|
-
- `hasScripts`
|
|
300
|
-
- `hasReferences`
|
|
301
|
-
- `hasAssets`
|
|
302
|
-
- `riskFlags[]`
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
### 4.4 SkillCandidate
|
|
306
|
-
|
|
307
|
-
Discovery 过程中返回的候选对象,用于连接“搜索结果”和“安装动作”。
|
|
308
|
-
|
|
309
|
-
字段建议:
|
|
310
|
-
|
|
311
|
-
- `candidateId`
|
|
312
|
-
- `sourceType`
|
|
313
|
-
- `sourceLocator`
|
|
314
|
-
- `publisher`
|
|
315
|
-
- `repo`
|
|
316
|
-
- `skillPath`
|
|
317
|
-
- `title`
|
|
318
|
-
- `summary`
|
|
319
|
-
- `verified`
|
|
320
|
-
- `official`
|
|
321
|
-
- `installCount`
|
|
322
|
-
- `stars`
|
|
323
|
-
- `alreadyInstalled`
|
|
324
|
-
- `installedInChannels[]`
|
|
325
|
-
- `supportedChannels[]`
|
|
326
|
-
- `installMethods[]`
|
|
327
|
-
- `riskFlags[]`
|
|
328
|
-
- `score`
|
|
329
|
-
|
|
330
|
-
候选对象不等于 `SkillLeaf`。前者代表“可安装建议”,后者代表“已经被本地解析并纳入索引的技能实体”。
|
|
331
|
-
|
|
332
|
-
### 4.5 Channel
|
|
333
|
-
|
|
334
|
-
一个目标适配器,而不是路径。
|
|
335
|
-
|
|
336
|
-
字段建议:
|
|
337
|
-
|
|
338
|
-
- `channelId`
|
|
339
|
-
- `displayName`
|
|
340
|
-
- `resolvedPath`
|
|
341
|
-
- `strategy`
|
|
342
|
-
- `pathSource`
|
|
343
|
-
- `healthStatus`
|
|
344
|
-
|
|
345
|
-
### 4.6 Deployment
|
|
346
|
-
|
|
347
|
-
SkillLeaf 到 Channel 的一次投影关系。
|
|
348
|
-
|
|
349
|
-
字段建议:
|
|
350
|
-
|
|
351
|
-
- `deploymentId`
|
|
352
|
-
- `skillId`
|
|
353
|
-
- `channelId`
|
|
354
|
-
- `strategy`
|
|
355
|
-
- `targetPath`
|
|
356
|
-
- `status`
|
|
357
|
-
- `lastAppliedAt`
|
|
358
|
-
|
|
359
|
-
## 5. 文件系统布局
|
|
360
|
-
|
|
361
|
-
```text
|
|
362
|
-
~/.skillflow/
|
|
363
|
-
source/
|
|
364
|
-
git/
|
|
365
|
-
<sourceId>/
|
|
366
|
-
clawhub/
|
|
367
|
-
<sourceId>/
|
|
368
|
-
skills/
|
|
369
|
-
<sourceId>/
|
|
370
|
-
<skillName>/ -> ../../source/...
|
|
371
|
-
state/
|
|
372
|
-
manifest.json
|
|
373
|
-
lock.json
|
|
374
|
-
channels.json
|
|
375
|
-
history.ndjson
|
|
376
|
-
cache/
|
|
377
|
-
tmp/
|
|
378
|
-
logs/
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
## 6. Source 策略
|
|
382
|
-
|
|
383
|
-
### 6.1 Git Source(MVP 必做)
|
|
384
|
-
|
|
385
|
-
输入支持:
|
|
386
|
-
|
|
387
|
-
- GitHub `owner/repo`
|
|
388
|
-
- 任意 git URL
|
|
389
|
-
- 本地 git 路径
|
|
390
|
-
|
|
391
|
-
### 6.2 ClawHub Source(MVP 必做)
|
|
392
|
-
|
|
393
|
-
输入支持:
|
|
394
|
-
|
|
395
|
-
- `clawhub:<slug>`
|
|
396
|
-
- `clawhub:<slug>@<version>`
|
|
397
|
-
|
|
398
|
-
MVP 实现:
|
|
399
|
-
|
|
400
|
-
- 优先采用 **CLI bridge**:shell-out `clawhub install/update/list`
|
|
401
|
-
- 将版本与来源信息同步到 `skill-flow lock`
|
|
402
|
-
|
|
403
|
-
### 6.3 Well-known Skills Discovery(P1)
|
|
404
|
-
|
|
405
|
-
只做接口预留,不进 MVP。
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
## 6.4 Discovery Source Tiers
|
|
409
|
-
|
|
410
|
-
当执行 `find` 时,来源优先级采用分层策略,而不是把所有来源混在一起:
|
|
411
|
-
|
|
412
|
-
### Tier 0:Installed / Bundled / System
|
|
413
|
-
|
|
414
|
-
- 已安装到 `skill-flow` 的 source / skill
|
|
415
|
-
- 目标渠道已启用的 skill
|
|
416
|
-
- 各渠道自带或预装的 bundled / system skill
|
|
417
|
-
|
|
418
|
-
用途:避免重复推荐,优先提示“你已经有了”。
|
|
419
|
-
|
|
420
|
-
### Tier 1:Official Curated Registry
|
|
421
|
-
|
|
422
|
-
- ClawHub 等官方注册表
|
|
423
|
-
- 未来可接入的官方 curated catalog
|
|
424
|
-
|
|
425
|
-
用途:默认优先展示,因其通常带版本、发布者和更强的信任信号。
|
|
426
|
-
|
|
427
|
-
### Tier 2:Public Ecosystem Directory / Leaderboard
|
|
428
|
-
|
|
429
|
-
- skills.sh 这类目录型来源
|
|
430
|
-
- 公开榜单、安装量与聚合索引
|
|
431
|
-
|
|
432
|
-
用途:补齐“广度发现”和“受欢迎技能”的判断。
|
|
433
|
-
|
|
434
|
-
### Tier 3:Direct Git Repositories
|
|
435
|
-
|
|
436
|
-
- GitHub / GitLab / 任意 git 仓库
|
|
437
|
-
- 已知 repo path 的直接安装
|
|
438
|
-
|
|
439
|
-
用途:作为高覆盖兜底来源,也支撑精准 repo/path 输入。
|
|
440
|
-
|
|
441
|
-
### Tier 4:Manual / Local / Custom URL
|
|
442
|
-
|
|
443
|
-
- 本地目录
|
|
444
|
-
- 自定义 URL
|
|
445
|
-
- 企业内部镜像
|
|
446
|
-
|
|
447
|
-
用途:满足高级用户与私有来源场景。
|
|
448
|
-
|
|
449
|
-
`find` 默认按 Tier 0 -> Tier 1 -> Tier 2 -> Tier 3 -> Tier 4 的顺序组织结果与解释。
|
|
450
|
-
|
|
451
|
-
## 7. Source 命名与展示规则
|
|
452
|
-
|
|
453
|
-
### 外显 display 规则
|
|
454
|
-
|
|
455
|
-
- Git 仓库:显示仓库名
|
|
456
|
-
- 非 Git 且可识别作者:显示作者名
|
|
457
|
-
- 无法识别:显示 `single`
|
|
458
|
-
|
|
459
|
-
### 内部 storage 规则
|
|
460
|
-
|
|
461
|
-
- Git:`<host>__<owner>__<repo>`
|
|
462
|
-
- ClawHub:`clawhub__<slug>`
|
|
463
|
-
- Generic single:`single__<hash>`
|
|
464
|
-
|
|
465
|
-
## 8. Skill 扫描与索引规则
|
|
466
|
-
|
|
467
|
-
扫描逻辑:
|
|
468
|
-
|
|
469
|
-
1. 递归搜索包含 `SKILL.md` 的目录
|
|
470
|
-
2. 跳过 `.git`、`node_modules`、构建产物
|
|
471
|
-
3. 解析 frontmatter
|
|
472
|
-
4. 生成 `SkillLeaf` 索引项
|
|
473
|
-
5. 建立 `skills/<sourceId>/<skillName>` canonical 入口
|
|
474
|
-
|
|
475
|
-
校验等级:
|
|
476
|
-
|
|
477
|
-
### 标准校验
|
|
478
|
-
|
|
479
|
-
- `SKILL.md` 存在
|
|
480
|
-
- YAML 可解析
|
|
481
|
-
- `name`
|
|
482
|
-
- `description`
|
|
483
|
-
|
|
484
|
-
### 严格校验
|
|
485
|
-
|
|
486
|
-
- `name` 与目录名匹配
|
|
487
|
-
- 命名合法
|
|
488
|
-
- `description` 长度合理
|
|
489
|
-
- 相对路径引用可达
|
|
490
|
-
|
|
491
|
-
## 9. Channel 适配与默认策略
|
|
492
|
-
|
|
493
|
-
### 9.1 Claude Code
|
|
494
|
-
|
|
495
|
-
- 默认路径:`~/.claude/skills`
|
|
496
|
-
- 默认策略:`symlink`
|
|
497
|
-
- 兜底策略:`copy`
|
|
498
|
-
|
|
499
|
-
### 9.2 OpenCode
|
|
500
|
-
|
|
501
|
-
- 默认路径:`~/.config/opencode/skills`
|
|
502
|
-
- 默认策略:`symlink`
|
|
503
|
-
|
|
504
|
-
### 9.3 Codex
|
|
505
|
-
|
|
506
|
-
- 默认路径:`~/.agents/skills`
|
|
507
|
-
- 默认策略:`symlink`
|
|
508
|
-
|
|
509
|
-
### 9.4 OpenClaw
|
|
510
|
-
|
|
511
|
-
- 默认路径:`<workspace>/skills`,备选 `~/.openclaw/skills`
|
|
512
|
-
- 默认策略:`copy`
|
|
513
|
-
|
|
514
|
-
### 9.5 通用 `.agents/skills`
|
|
515
|
-
|
|
516
|
-
- 默认路径:`~/.agents/skills`
|
|
517
|
-
- 默认策略:`symlink`
|
|
518
|
-
|
|
519
|
-
## 10. 命令设计
|
|
520
|
-
|
|
521
|
-
正式命令集:
|
|
522
|
-
|
|
523
|
-
```bash
|
|
524
|
-
skill-flow add <source>
|
|
525
|
-
skill-flow find [query]
|
|
526
|
-
skill-flow search [query] # `find` 的兼容别名
|
|
527
|
-
skill-flow install <candidate-or-source>
|
|
528
|
-
skill-flow list
|
|
529
|
-
skill-flow config
|
|
530
|
-
skill-flow update [--all | <sourceId>]
|
|
531
|
-
skill-flow uninstall [<sourceId>...]
|
|
532
|
-
skill-flow doctor
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
### 10.1 `find`
|
|
536
|
-
|
|
537
|
-
`find` 是 Discovery 主命令。它既支持明确 query,也支持无 query 的交互式发现。
|
|
538
|
-
|
|
539
|
-
典型用法:
|
|
540
|
-
|
|
541
|
-
```bash
|
|
542
|
-
skill-flow find react performance
|
|
543
|
-
skill-flow find postgres backups
|
|
544
|
-
skill-flow find
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
行为定义:
|
|
548
|
-
|
|
549
|
-
1. 先检查 Tier 0:本地已安装 / 已启用 / 已内置能力。
|
|
550
|
-
2. 再检查 Tier 1:ClawHub 等官方 registry。
|
|
551
|
-
3. 再检查 Tier 2:目录 / leaderboard / popularity signals。
|
|
552
|
-
4. 最后检查 Tier 3:git 级来源与 repo path。
|
|
553
|
-
5. 返回 `SkillCandidate[]`,而不是直接执行安装。
|
|
554
|
-
|
|
555
|
-
### 10.2 `install`
|
|
556
|
-
|
|
557
|
-
`install` 是 Discovery 到安装的快速闭环,支持“直接从候选安装”和“直接从 source / repo path 安装”两种模式。
|
|
558
|
-
|
|
559
|
-
典型用法:
|
|
560
|
-
|
|
561
|
-
```bash
|
|
562
|
-
skill-flow install clawhub:publisher/skill@1.2.3
|
|
563
|
-
skill-flow install github:vercel-labs/skills --skill react-best-practices
|
|
564
|
-
skill-flow install github:openai/skills --path skills/.curated/pdf
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
行为定义:
|
|
568
|
-
|
|
569
|
-
1. 若入参是候选对象,按候选携带的最优安装方法执行。
|
|
570
|
-
2. 若入参是 source,则进入 add / scan / optional apply 流程。
|
|
571
|
-
3. 安装完成后刷新 manifest / lock / inventory index。
|
|
572
|
-
4. 视 channel 给出后续提示,如 `config`、重扫或重启客户端。
|
|
573
|
-
|
|
574
|
-
### 10.3 `add`
|
|
575
|
-
|
|
576
|
-
`add` 保留为“把 source 纳入 skill-flow 管理”的正式入口。与 `install` 的区别是:`add` 偏 source-first,`install` 偏 candidate-first。
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
## 10.4 Discovery 工作流
|
|
580
|
-
|
|
581
|
-
当用户只有“能力诉求”时,`find` 的完整流程如下:
|
|
582
|
-
|
|
583
|
-
1. **Intent Normalize**
|
|
584
|
-
从用户描述抽取 capability、domain、toolchain、约束条件。
|
|
585
|
-
|
|
586
|
-
2. **Query Expansion**
|
|
587
|
-
生成一组用于 registry / directory / git 的查询词,包括领域词、同义词与技术栈词。
|
|
588
|
-
|
|
589
|
-
3. **Tiered Retrieval**
|
|
590
|
-
按来源分层召回候选:已安装 -> registry -> leaderboard -> git。
|
|
591
|
-
|
|
592
|
-
4. **Candidate Enrichment**
|
|
593
|
-
填充安装量、来源、publisher、stars、是否已安装、支持渠道、风险标记。
|
|
594
|
-
|
|
595
|
-
5. **Rule-based Ranking**
|
|
596
|
-
依据显式规则排序,而不是黑盒推荐。
|
|
597
|
-
|
|
598
|
-
6. **Presentation**
|
|
599
|
-
至少展示:名称、用途、来源、安装量/可信信号、安装方式、详情入口。
|
|
600
|
-
|
|
601
|
-
7. **Action**
|
|
602
|
-
用户可选择:
|
|
603
|
-
- 立即安装
|
|
604
|
-
- 添加为 source 后再配置
|
|
605
|
-
- 仅保存为候选
|
|
606
|
-
- 忽略
|
|
607
|
-
|
|
608
|
-
## 10.5 Search Result Schema & Ranking
|
|
609
|
-
|
|
610
|
-
`find` 返回的每个结果至少要包含:
|
|
611
|
-
|
|
612
|
-
- `title`
|
|
613
|
-
- `summary`
|
|
614
|
-
- `sourceType`
|
|
615
|
-
- `sourceLocator`
|
|
616
|
-
- `publisher`
|
|
617
|
-
- `skillPath`
|
|
618
|
-
- `installMethods[]`
|
|
619
|
-
- `alreadyInstalled`
|
|
620
|
-
- `installedInChannels[]`
|
|
621
|
-
- `verified`
|
|
622
|
-
- `official`
|
|
623
|
-
- `installCount`
|
|
624
|
-
- `stars`
|
|
625
|
-
- `riskFlags[]`
|
|
626
|
-
- `score`
|
|
627
|
-
|
|
628
|
-
默认排序规则:
|
|
629
|
-
|
|
630
|
-
1. Tier 优先级
|
|
631
|
-
2. `alreadyInstalled` 命中时置顶,并标注“已安装”
|
|
632
|
-
3. `official / verified` 优先
|
|
633
|
-
4. 安装量 / 使用量
|
|
634
|
-
5. GitHub stars / repo 活跃度
|
|
635
|
-
6. 精确名称匹配
|
|
636
|
-
7. 描述语义匹配
|
|
637
|
-
8. 新近性
|
|
638
|
-
|
|
639
|
-
### 10.6 Installed Annotation & Post-Install Feedback
|
|
640
|
-
|
|
641
|
-
Discovery 与安装结果必须回流到 UX:
|
|
642
|
-
|
|
643
|
-
- 搜索结果标出 `already installed`
|
|
644
|
-
- 搜索结果标出 `installed in channels: [...]`
|
|
645
|
-
- 对 bundled / system / preinstalled 条目标出 `preinstalled`
|
|
646
|
-
- 安装完成后给出 channel-specific next steps:
|
|
647
|
-
- 需要执行 `config`
|
|
648
|
-
- 需要重扫
|
|
649
|
-
- 建议重启客户端
|
|
650
|
-
- 可热加载,无需重启
|
|
651
|
-
|
|
652
|
-
### 10.7 Non-Skill Artifact Handling
|
|
653
|
-
|
|
654
|
-
MVP 扫描器与 Discovery 索引器只管理合法 `SKILL.md` skill root。对同一仓库中的以下对象:
|
|
655
|
-
|
|
656
|
-
- `.claude/commands/`
|
|
657
|
-
- `agents/`
|
|
658
|
-
- `plugins/`
|
|
659
|
-
- 其他非 skill 工件
|
|
660
|
-
|
|
661
|
-
统一策略为:
|
|
662
|
-
|
|
663
|
-
1. 默认忽略,不作为可安装 skill。
|
|
664
|
-
2. 若检测到与 skill 高度相似的目录结构,记 warning。
|
|
665
|
-
3. 后续若扩展到 commands / agents 管理,再通过新 artifact kind 建模,而不是复用 `SkillLeaf`。
|
|
666
|
-
|
|
667
|
-
## 11. 状态文件设计
|
|
668
|
-
|
|
669
|
-
### `manifest.json`
|
|
670
|
-
|
|
671
|
-
记录用户意图:
|
|
672
|
-
|
|
673
|
-
- sources
|
|
674
|
-
- naming policy
|
|
675
|
-
- selected skills by channel
|
|
676
|
-
- user overrides
|
|
677
|
-
|
|
678
|
-
### `lock.json`
|
|
679
|
-
|
|
680
|
-
记录解析结果:
|
|
681
|
-
|
|
682
|
-
- source snapshots
|
|
683
|
-
- skill leaf inventory
|
|
684
|
-
- deployments
|
|
685
|
-
- content hashes
|
|
686
|
-
- timestamps
|
|
687
|
-
- schemaVersion
|
|
688
|
-
|
|
689
|
-
### `channels.json`
|
|
690
|
-
|
|
691
|
-
记录本机探测与 path override:
|
|
692
|
-
|
|
693
|
-
- detected channels
|
|
694
|
-
- resolved path
|
|
695
|
-
- available strategies
|
|
696
|
-
- health flags
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
### `inventory-index.json`
|
|
701
|
-
|
|
702
|
-
记录每个 source 解析出的 Discovery 友好索引,供 `find`、`config`、`diff`、`doctor` 快速读取。
|
|
703
|
-
|
|
704
|
-
建议字段:
|
|
705
|
-
|
|
706
|
-
- `sourceId`
|
|
707
|
-
- `snapshotRef`
|
|
708
|
-
- `skills[]`
|
|
709
|
-
- `name`
|
|
710
|
-
- `description`
|
|
711
|
-
- `path`
|
|
712
|
-
- `tags`
|
|
713
|
-
- `riskFlags`
|
|
714
|
-
- `contentHash`
|
|
715
|
-
- `generatedAt`
|
|
716
|
-
|
|
717
|
-
说明:
|
|
718
|
-
|
|
719
|
-
- 这是 `skill-flow` 的内部缓存格式,不对外承诺为开放标准。
|
|
720
|
-
- 它解决大型 source 在反复 `find` / `config` 时的性能问题。
|
|
721
|
-
|
|
722
|
-
### `discovery-cache.json`
|
|
723
|
-
|
|
724
|
-
记录外部来源的候选缓存,降低频繁请求 registry / leaderboard / git API 的成本。
|
|
725
|
-
|
|
726
|
-
建议字段:
|
|
727
|
-
|
|
728
|
-
- `query`
|
|
729
|
-
- `sourceTier`
|
|
730
|
-
- `candidates[]`
|
|
731
|
-
- `fetchedAt`
|
|
732
|
-
- `expiresAt`
|
|
733
|
-
- `etag`
|
|
734
|
-
|
|
735
|
-
### `history.ndjson`
|
|
736
|
-
|
|
737
|
-
记录审计事件:
|
|
738
|
-
|
|
739
|
-
- add
|
|
740
|
-
- update
|
|
741
|
-
- config-apply
|
|
742
|
-
- uninstall
|
|
743
|
-
- doctor-warning
|
|
744
|
-
|
|
745
|
-
## 12. 冲突与一致性规则
|
|
746
|
-
|
|
747
|
-
### 12.1 同 channel 同名 skill
|
|
748
|
-
|
|
749
|
-
默认阻止,不静默覆盖。
|
|
750
|
-
|
|
751
|
-
### 12.2 目标路径已有非本工具管理文件
|
|
752
|
-
|
|
753
|
-
默认不接管,标记 `foreign-existing`。
|
|
754
|
-
|
|
755
|
-
### 12.3 Source 内同名 leaf
|
|
756
|
-
|
|
757
|
-
扫描时直接判定 source inventory 非法,需要用户缩小范围或忽略。
|
|
758
|
-
|
|
759
|
-
### 12.4 原子性
|
|
760
|
-
|
|
761
|
-
所有 state 文件写入采用:
|
|
762
|
-
|
|
763
|
-
- `tmp write`
|
|
764
|
-
- `fsync`
|
|
765
|
-
- `rename`
|
|
766
|
-
|
|
767
|
-
所有 deployment 采用 staged apply;失败时不提交 lock 的成功状态。
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
## 12.5 Channel Feature Compatibility Matrix
|
|
771
|
-
|
|
772
|
-
不同渠道对前端元数据和技能语义的支持并不等价。MVP 需要最少维护一张兼容矩阵:
|
|
773
|
-
|
|
774
|
-
| 能力 / 字段 | Agent Skills 通用 | Claude Code | OpenCode | Codex | OpenClaw | `skill-flow` 导入策略 |
|
|
775
|
-
|---|---|---|---|---|---|---|
|
|
776
|
-
| `name` / `description` | 支持 | 支持 | 支持 | 支持 | 支持 | 必填 / 缺失则失败 |
|
|
777
|
-
| `references/` / `assets/` / `scripts/` | 支持 | 支持 | 支持 | 支持 | 支持 | 扫描但不执行脚本 |
|
|
778
|
-
| `allowed-tools` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样,非支持渠道仅 warning |
|
|
779
|
-
| `user-invocable` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样 |
|
|
780
|
-
| `disable-model-invocation` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样 |
|
|
781
|
-
| `argument-hint` | 非通用 | 支持 | 未承诺 | 未承诺 | 未承诺 | 保留原样 |
|
|
782
|
-
| nested discovery | 非通用 | 支持 | 项目向上查找 | repo/user/admin/system | workspace 优先 | 仅在 channel adapter 层处理 |
|
|
783
|
-
| commands 兼容 | 非通用 | 与 skills 合流 | 未纳入 MVP | 未纳入 MVP | 未纳入 MVP | 默认忽略 commands |
|
|
784
|
-
|
|
785
|
-
策略说明:
|
|
786
|
-
|
|
787
|
-
1. `skill-flow` 不重写 source 内容。
|
|
788
|
-
2. 对未知 frontmatter 保留原样,不主动删除。
|
|
789
|
-
3. 对渠道已知但不受支持的字段,在 `doctor` 中给 warning。
|
|
790
|
-
|
|
791
|
-
## 13. 安全要求
|
|
792
|
-
|
|
793
|
-
MVP 安全要求:
|
|
794
|
-
|
|
795
|
-
1. 永不执行 skill 脚本
|
|
796
|
-
2. 扫描时做 frontmatter 与路径校验
|
|
797
|
-
3. 拒绝 root 外 realpath 投影
|
|
798
|
-
4. 风险标记:
|
|
799
|
-
- `has-scripts`
|
|
800
|
-
- `invalid-frontmatter`
|
|
801
|
-
- `name-dir-mismatch`
|
|
802
|
-
- `external-symlink`
|
|
803
|
-
- `foreign-existing`
|
|
804
|
-
- `openclaw-root-risk`
|
|
805
|
-
5. 默认提示审计,`--yes` 才跳过确认
|
|
806
|
-
|
|
807
|
-
## 14. 技术栈
|
|
808
|
-
|
|
809
|
-
### 14.1 运行时与语言
|
|
810
|
-
|
|
811
|
-
- **Node.js 24 LTS**
|
|
812
|
-
- **TypeScript 5.x**
|
|
813
|
-
|
|
814
|
-
### 14.2 包管理与构建
|
|
815
|
-
|
|
816
|
-
- **pnpm**
|
|
817
|
-
- 发布到 **npm**
|
|
818
|
-
|
|
819
|
-
### 14.3 CLI 与 TUI
|
|
820
|
-
|
|
821
|
-
- **oclif**
|
|
822
|
-
- **Ink**
|
|
823
|
-
|
|
824
|
-
### 14.4 Schema 与状态验证
|
|
825
|
-
|
|
826
|
-
- **Zod**
|
|
827
|
-
|
|
828
|
-
### 14.5 Git 访问
|
|
829
|
-
|
|
830
|
-
- **system git**
|
|
831
|
-
- **simple-git**
|
|
832
|
-
|
|
833
|
-
### 14.6 测试
|
|
834
|
-
|
|
835
|
-
- **Vitest**
|
|
836
|
-
- fixture-based filesystem integration tests
|
|
837
|
-
|
|
838
|
-
### 14.7 建议工程结构
|
|
839
|
-
|
|
840
|
-
```text
|
|
841
|
-
src/
|
|
842
|
-
commands/
|
|
843
|
-
tui/
|
|
844
|
-
domain/
|
|
845
|
-
adapters/
|
|
846
|
-
source/
|
|
847
|
-
channel/
|
|
848
|
-
services/
|
|
849
|
-
scan/
|
|
850
|
-
deploy/
|
|
851
|
-
update/
|
|
852
|
-
doctor/
|
|
853
|
-
state/
|
|
854
|
-
utils/
|
|
855
|
-
```
|
|
856
|
-
|
|
857
|
-
## 15. 里程碑
|
|
858
|
-
|
|
859
|
-
### Milestone 1
|
|
860
|
-
- Git Source
|
|
861
|
-
- 扫描器
|
|
862
|
-
- manifest/lock
|
|
863
|
-
- list/add/update
|
|
864
|
-
|
|
865
|
-
### Milestone 2
|
|
866
|
-
- config TUI
|
|
867
|
-
- Claude/OpenCode/Codex/agents 投影
|
|
868
|
-
- doctor
|
|
869
|
-
|
|
870
|
-
### Milestone 3
|
|
871
|
-
- OpenClaw copy deployment
|
|
872
|
-
- ClawHub adapter
|
|
873
|
-
- uninstall
|
|
874
|
-
|
|
875
|
-
### Milestone 4
|
|
876
|
-
- search
|
|
877
|
-
- diff
|
|
878
|
-
- schema migration
|
|
879
|
-
- alias conflict handling
|
|
880
|
-
|
|
881
|
-
### Milestone 5(P1)
|
|
882
|
-
- well-known discovery
|
|
883
|
-
- project-scope support
|
|
884
|
-
- Homebrew tap
|
|
885
|
-
- advanced channel overrides
|
|
886
|
-
- external plugin SDK
|
|
887
|
-
|
|
888
|
-
---
|
|
889
|
-
|
|
890
|
-
# 三、工程实施文档
|
|
891
|
-
|
|
892
|
-
## 1. 实施目标
|
|
893
|
-
|
|
894
|
-
这一部分不是再讨论“做什么”,而是明确“怎么落地”。目标是让工程团队在没有额外口头补充的情况下,直接进入:
|
|
895
|
-
|
|
896
|
-
1. 仓库初始化
|
|
897
|
-
2. 核心模块搭建
|
|
898
|
-
3. 命令实现
|
|
899
|
-
4. 端到端测试
|
|
900
|
-
5. 首个可发布 MVP
|
|
901
|
-
|
|
902
|
-
---
|
|
903
|
-
|
|
904
|
-
## 2. MVP 工程范围切片
|
|
905
|
-
|
|
906
|
-
### 2.1 必须在首发版本完成
|
|
907
|
-
|
|
908
|
-
- Git Source Adapter
|
|
909
|
-
- ClawHub Source Adapter(CLI bridge 方案)
|
|
910
|
-
- Skill Scanner
|
|
911
|
-
- Manifest/Lock/Channels 三类状态文件
|
|
912
|
-
- Claude/OpenCode/Codex/Agents 四个 symlink channel
|
|
913
|
-
- OpenClaw copy channel
|
|
914
|
-
- `add / list / config / update / uninstall / doctor`
|
|
915
|
-
- TUI 树状多选界面
|
|
916
|
-
- 冲突检测、路径校验、原子写入、日志落盘
|
|
917
|
-
|
|
918
|
-
### 2.2 可以延后到 P1
|
|
919
|
-
|
|
920
|
-
- well-known registry adapter
|
|
921
|
-
- alias 命名策略
|
|
922
|
-
- Homebrew tap 自动发布
|
|
923
|
-
- project-scope 管理
|
|
924
|
-
- 自定义 channel adapter SDK
|
|
925
|
-
- 远程 diff 预览
|
|
926
|
-
|
|
927
|
-
---
|
|
928
|
-
|
|
929
|
-
## 3. 工程仓库建议结构
|
|
930
|
-
|
|
931
|
-
```text
|
|
932
|
-
skill-flow/
|
|
933
|
-
package.json
|
|
934
|
-
pnpm-lock.yaml
|
|
935
|
-
tsconfig.json
|
|
936
|
-
vitest.config.ts
|
|
937
|
-
README.md
|
|
938
|
-
src/
|
|
939
|
-
index.ts
|
|
940
|
-
cli.ts
|
|
941
|
-
commands/
|
|
942
|
-
add.ts
|
|
943
|
-
search.ts
|
|
944
|
-
list.ts
|
|
945
|
-
config.ts
|
|
946
|
-
update.ts
|
|
947
|
-
uninstall.ts
|
|
948
|
-
doctor.ts
|
|
949
|
-
tui/
|
|
950
|
-
app.tsx
|
|
951
|
-
screens/
|
|
952
|
-
channel-select.tsx
|
|
953
|
-
skill-tree.tsx
|
|
954
|
-
apply-preview.tsx
|
|
955
|
-
components/
|
|
956
|
-
tree-node.tsx
|
|
957
|
-
checkbox.tsx
|
|
958
|
-
footer-hints.tsx
|
|
959
|
-
status-pill.tsx
|
|
960
|
-
domain/
|
|
961
|
-
source.ts
|
|
962
|
-
snapshot.ts
|
|
963
|
-
skill.ts
|
|
964
|
-
channel.ts
|
|
965
|
-
deployment.ts
|
|
966
|
-
errors.ts
|
|
967
|
-
adapters/
|
|
968
|
-
source/
|
|
969
|
-
git.ts
|
|
970
|
-
clawhub.ts
|
|
971
|
-
registry.ts
|
|
972
|
-
channel/
|
|
973
|
-
claude.ts
|
|
974
|
-
opencode.ts
|
|
975
|
-
codex.ts
|
|
976
|
-
openclaw.ts
|
|
977
|
-
agents.ts
|
|
978
|
-
services/
|
|
979
|
-
detect/
|
|
980
|
-
channels.ts
|
|
981
|
-
scan/
|
|
982
|
-
scanner.ts
|
|
983
|
-
parser.ts
|
|
984
|
-
validators.ts
|
|
985
|
-
state/
|
|
986
|
-
manifest.ts
|
|
987
|
-
lock.ts
|
|
988
|
-
channels.ts
|
|
989
|
-
migrations.ts
|
|
990
|
-
deploy/
|
|
991
|
-
planner.ts
|
|
992
|
-
symlink.ts
|
|
993
|
-
copy.ts
|
|
994
|
-
applier.ts
|
|
995
|
-
source/
|
|
996
|
-
resolve.ts
|
|
997
|
-
fetch.ts
|
|
998
|
-
update.ts
|
|
999
|
-
doctor/
|
|
1000
|
-
checks.ts
|
|
1001
|
-
logging/
|
|
1002
|
-
history.ts
|
|
1003
|
-
logger.ts
|
|
1004
|
-
utils/
|
|
1005
|
-
fs.ts
|
|
1006
|
-
hash.ts
|
|
1007
|
-
path.ts
|
|
1008
|
-
prompt.ts
|
|
1009
|
-
time.ts
|
|
1010
|
-
ids.ts
|
|
1011
|
-
fixtures/
|
|
1012
|
-
repos/
|
|
1013
|
-
channels/
|
|
1014
|
-
snapshots/
|
|
1015
|
-
tests/
|
|
1016
|
-
unit/
|
|
1017
|
-
integration/
|
|
1018
|
-
e2e/
|
|
1019
|
-
```
|
|
1020
|
-
|
|
1021
|
-
设计原则:
|
|
1022
|
-
|
|
1023
|
-
- `commands/` 只做参数解析与 orchestration
|
|
1024
|
-
- `domain/` 只放模型和不依赖 IO 的规则
|
|
1025
|
-
- `adapters/` 隔离第三方系统差异
|
|
1026
|
-
- `services/` 承担业务编排
|
|
1027
|
-
- `tui/` 不直接触碰磁盘;通过 service 层读写
|
|
1028
|
-
|
|
1029
|
-
---
|
|
1030
|
-
|
|
1031
|
-
## 4. 命令参数规范
|
|
1032
|
-
|
|
1033
|
-
## 4.1 `skill-flow add`
|
|
1034
|
-
|
|
1035
|
-
```bash
|
|
1036
|
-
skill-flow add <source>
|
|
1037
|
-
[--name <displayName>]
|
|
1038
|
-
[--branch <branch>]
|
|
1039
|
-
[--ref <ref>]
|
|
1040
|
-
[--channel <channel...>]
|
|
1041
|
-
[--yes]
|
|
1042
|
-
[--json]
|
|
1043
|
-
```
|
|
1044
|
-
|
|
1045
|
-
### 行为定义
|
|
1046
|
-
|
|
1047
|
-
- `<source>` 支持:
|
|
1048
|
-
- `owner/repo`
|
|
1049
|
-
- `https://...git`
|
|
1050
|
-
- `git@...`
|
|
1051
|
-
- 本地路径
|
|
1052
|
-
- `clawhub:<slug>`
|
|
1053
|
-
- `clawhub:<slug>@<version>`
|
|
1054
|
-
- 若指定 `--channel`,则在 `add` 后直接触发一次 apply
|
|
1055
|
-
- 若指定 `--ref`,优先锁定对应 tag/commit
|
|
1056
|
-
- `--yes` 跳过来源确认与风险确认
|
|
1057
|
-
|
|
1058
|
-
## 4.2 `skill-flow search`
|
|
1059
|
-
|
|
1060
|
-
```bash
|
|
1061
|
-
skill-flow search <query>
|
|
1062
|
-
[--source git|clawhub|all]
|
|
1063
|
-
[--limit <n>]
|
|
1064
|
-
[--json]
|
|
1065
|
-
```
|
|
1066
|
-
|
|
1067
|
-
### 行为定义
|
|
1068
|
-
|
|
1069
|
-
- `--source clawhub`:正式支持
|
|
1070
|
-
- `--source git`:MVP 仅做 repo 级搜索或 locator 解析辅助
|
|
1071
|
-
- `--source all`:按 adapter 聚合结果
|
|
1072
|
-
|
|
1073
|
-
## 4.3 `skill-flow list`
|
|
1074
|
-
|
|
1075
|
-
```bash
|
|
1076
|
-
skill-flow list
|
|
1077
|
-
[--sources]
|
|
1078
|
-
[--skills]
|
|
1079
|
-
[--deployments]
|
|
1080
|
-
[--channel <channel>]
|
|
1081
|
-
[--source-id <id>]
|
|
1082
|
-
[--json]
|
|
1083
|
-
```
|
|
1084
|
-
|
|
1085
|
-
### 行为定义
|
|
1086
|
-
|
|
1087
|
-
- 默认输出 `sources + skills + deployment summary`
|
|
1088
|
-
- `--skills` 展示 skill leaf 明细
|
|
1089
|
-
- `--deployments` 展示按 channel 的启用状态
|
|
1090
|
-
|
|
1091
|
-
## 4.4 `skill-flow config`
|
|
1092
|
-
|
|
1093
|
-
```bash
|
|
1094
|
-
skill-flow config
|
|
1095
|
-
[--channel <channel...>]
|
|
1096
|
-
[--source-id <id>]
|
|
1097
|
-
[--non-interactive]
|
|
1098
|
-
[--json]
|
|
1099
|
-
```
|
|
1100
|
-
|
|
1101
|
-
### 行为定义
|
|
1102
|
-
|
|
1103
|
-
- 默认进入 TUI
|
|
1104
|
-
- `--non-interactive` 预留给脚本模式,MVP 可只支持有限 flag 驱动
|
|
1105
|
-
- 未传 `--channel` 时先展示 channel 多选
|
|
1106
|
-
|
|
1107
|
-
## 4.5 `skill-flow update`
|
|
1108
|
-
|
|
1109
|
-
```bash
|
|
1110
|
-
skill-flow update
|
|
1111
|
-
[--all]
|
|
1112
|
-
[--source-id <id>...]
|
|
1113
|
-
[--apply]
|
|
1114
|
-
[--dry-run]
|
|
1115
|
-
[--json]
|
|
1116
|
-
```
|
|
1117
|
-
|
|
1118
|
-
### 行为定义
|
|
1119
|
-
|
|
1120
|
-
- `--all` 更新所有 source
|
|
1121
|
-
- `--apply` 更新完成后重新部署受影响 channel
|
|
1122
|
-
- `--dry-run` 仅展示可更新项和变更摘要
|
|
1123
|
-
|
|
1124
|
-
## 4.6 `skill-flow uninstall`
|
|
1125
|
-
|
|
1126
|
-
```bash
|
|
1127
|
-
skill-flow uninstall <sourceId...>
|
|
1128
|
-
[--yes]
|
|
1129
|
-
[--json]
|
|
1130
|
-
```
|
|
1131
|
-
|
|
1132
|
-
### 行为定义
|
|
1133
|
-
|
|
1134
|
-
- 卸载 source 及其 canonical skills 与所有 deployments
|
|
1135
|
-
- 不删除其他来源产生的同名 skill
|
|
1136
|
-
|
|
1137
|
-
## 4.7 `skill-flow doctor`
|
|
1138
|
-
|
|
1139
|
-
```bash
|
|
1140
|
-
skill-flow doctor
|
|
1141
|
-
[--channel <channel...>]
|
|
1142
|
-
[--source-id <id>...]
|
|
1143
|
-
[--fix]
|
|
1144
|
-
[--json]
|
|
1145
|
-
```
|
|
1146
|
-
|
|
1147
|
-
### 行为定义
|
|
1148
|
-
|
|
1149
|
-
- 默认只检查不修改
|
|
1150
|
-
- `--fix` 仅修复确定性问题:断链重建、缺失 state 目录、历史文件 rotate
|
|
1151
|
-
- 冲突覆盖不属于自动修复范围
|
|
1152
|
-
|
|
1153
|
-
---
|
|
1154
|
-
|
|
1155
|
-
## 5. 状态文件 Schema
|
|
1156
|
-
|
|
1157
|
-
## 5.1 `manifest.json`
|
|
1158
|
-
|
|
1159
|
-
作用:记录用户意图。
|
|
1160
|
-
|
|
1161
|
-
```json
|
|
1162
|
-
{
|
|
1163
|
-
"$schema": "https://skill-flow.dev/schema/manifest-v1.json",
|
|
1164
|
-
"schemaVersion": 1,
|
|
1165
|
-
"sources": [
|
|
1166
|
-
{
|
|
1167
|
-
"sourceId": "github__vercel-labs__skills",
|
|
1168
|
-
"sourceType": "git",
|
|
1169
|
-
"locator": "vercel-labs/skills",
|
|
1170
|
-
"displayName": "skills",
|
|
1171
|
-
"options": {
|
|
1172
|
-
"ref": null,
|
|
1173
|
-
"branch": "main"
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
],
|
|
1177
|
-
"bindings": [
|
|
1178
|
-
{
|
|
1179
|
-
"channelId": "claude",
|
|
1180
|
-
"skillSelections": [
|
|
1181
|
-
{
|
|
1182
|
-
"sourceId": "github__vercel-labs__skills",
|
|
1183
|
-
"skillIds": ["frontend-design", "skill-creator"]
|
|
1184
|
-
}
|
|
1185
|
-
]
|
|
1186
|
-
}
|
|
1187
|
-
],
|
|
1188
|
-
"overrides": {
|
|
1189
|
-
"channels": {
|
|
1190
|
-
"openclaw": {
|
|
1191
|
-
"path": null,
|
|
1192
|
-
"strategy": "copy"
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
```
|
|
1198
|
-
|
|
1199
|
-
### 约束
|
|
1200
|
-
|
|
1201
|
-
- `schemaVersion` 必填
|
|
1202
|
-
- `bindings` 只描述“期望启用哪些 skill 到哪些 channel”
|
|
1203
|
-
- 不记录部署是否成功;那是 lock 的职责
|
|
1204
|
-
|
|
1205
|
-
## 5.2 `lock.json`
|
|
1206
|
-
|
|
1207
|
-
作用:记录解析结果与当前落地状态。
|
|
1208
|
-
|
|
1209
|
-
```json
|
|
1210
|
-
{
|
|
1211
|
-
"$schema": "https://skill-flow.dev/schema/lock-v1.json",
|
|
1212
|
-
"schemaVersion": 1,
|
|
1213
|
-
"generatedAt": "2026-03-21T12:00:00.000Z",
|
|
1214
|
-
"sources": [
|
|
1215
|
-
{
|
|
1216
|
-
"sourceId": "github__vercel-labs__skills",
|
|
1217
|
-
"sourceType": "git",
|
|
1218
|
-
"snapshot": {
|
|
1219
|
-
"remote": "https://github.com/vercel-labs/skills.git",
|
|
1220
|
-
"branch": "main",
|
|
1221
|
-
"commit": "abc123"
|
|
1222
|
-
},
|
|
1223
|
-
"contentHash": "sha256:..."
|
|
1224
|
-
}
|
|
1225
|
-
],
|
|
1226
|
-
"skills": [
|
|
1227
|
-
{
|
|
1228
|
-
"skillId": "frontend-design",
|
|
1229
|
-
"sourceId": "github__vercel-labs__skills",
|
|
1230
|
-
"name": "frontend-design",
|
|
1231
|
-
"description": "...",
|
|
1232
|
-
"relativeRoot": "skills/frontend-design",
|
|
1233
|
-
"canonicalPath": "~/.skillflow/skills/github__vercel-labs__skills/frontend-design",
|
|
1234
|
-
"contentHash": "sha256:...",
|
|
1235
|
-
"riskFlags": []
|
|
1236
|
-
}
|
|
1237
|
-
],
|
|
1238
|
-
"deployments": [
|
|
1239
|
-
{
|
|
1240
|
-
"deploymentId": "dep_001",
|
|
1241
|
-
"skillId": "frontend-design",
|
|
1242
|
-
"channelId": "claude",
|
|
1243
|
-
"strategy": "symlink",
|
|
1244
|
-
"targetPath": "~/.claude/skills/frontend-design",
|
|
1245
|
-
"status": "applied",
|
|
1246
|
-
"lastAppliedAt": "2026-03-21T12:00:00.000Z"
|
|
1247
|
-
}
|
|
1248
|
-
]
|
|
1249
|
-
}
|
|
1250
|
-
```
|
|
1251
|
-
|
|
1252
|
-
### 约束
|
|
1253
|
-
|
|
1254
|
-
- lock 必须可重建本地部署视图
|
|
1255
|
-
- `deployments.status` 允许:`planned | applied | stale | broken | removed`
|
|
1256
|
-
- `contentHash` 用于 update 后判断是否需要重投影
|
|
1257
|
-
|
|
1258
|
-
## 5.3 `channels.json`
|
|
1259
|
-
|
|
1260
|
-
作用:记录本机探测结果与 override。
|
|
1261
|
-
|
|
1262
|
-
```json
|
|
1263
|
-
{
|
|
1264
|
-
"$schema": "https://skill-flow.dev/schema/channels-v1.json",
|
|
1265
|
-
"schemaVersion": 1,
|
|
1266
|
-
"detected": [
|
|
1267
|
-
{
|
|
1268
|
-
"channelId": "claude",
|
|
1269
|
-
"path": "/Users/alice/.claude/skills",
|
|
1270
|
-
"pathSource": "default",
|
|
1271
|
-
"available": true,
|
|
1272
|
-
"preferredStrategy": "symlink"
|
|
1273
|
-
},
|
|
1274
|
-
{
|
|
1275
|
-
"channelId": "openclaw",
|
|
1276
|
-
"path": "/Users/alice/.openclaw/workspace/skills",
|
|
1277
|
-
"pathSource": "detected-workspace",
|
|
1278
|
-
"available": true,
|
|
1279
|
-
"preferredStrategy": "copy"
|
|
1280
|
-
}
|
|
1281
|
-
]
|
|
1282
|
-
}
|
|
1283
|
-
```
|
|
1284
|
-
|
|
1285
|
-
## 5.4 `history.ndjson`
|
|
1286
|
-
|
|
1287
|
-
每行一个事件,方便审计与排障。
|
|
1288
|
-
|
|
1289
|
-
```json
|
|
1290
|
-
{"ts":"2026-03-21T12:00:00.000Z","event":"add","sourceId":"github__vercel-labs__skills"}
|
|
1291
|
-
{"ts":"2026-03-21T12:01:00.000Z","event":"config-apply","channelId":"claude","count":2}
|
|
1292
|
-
```
|
|
1293
|
-
|
|
1294
|
-
---
|
|
1295
|
-
|
|
1296
|
-
## 6. Domain Model TypeScript Interface
|
|
1297
|
-
|
|
1298
|
-
```ts
|
|
1299
|
-
export type SourceType = "git" | "clawhub" | "registry";
|
|
1300
|
-
export type ChannelId = "claude" | "opencode" | "codex" | "openclaw" | "agents";
|
|
1301
|
-
export type DeployStrategy = "symlink" | "copy";
|
|
1302
|
-
export type DeploymentStatus = "planned" | "applied" | "stale" | "broken" | "removed";
|
|
1303
|
-
|
|
1304
|
-
export interface Source {
|
|
1305
|
-
sourceId: string;
|
|
1306
|
-
sourceType: SourceType;
|
|
1307
|
-
locator: string;
|
|
1308
|
-
displayName: string;
|
|
1309
|
-
storageRoot: string;
|
|
1310
|
-
updateStrategy: "git-pull" | "registry-sync" | "custom";
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
export interface SourceSnapshot {
|
|
1314
|
-
sourceId: string;
|
|
1315
|
-
versionRef: string;
|
|
1316
|
-
contentHash: string;
|
|
1317
|
-
metadata: Record<string, unknown>;
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
export interface SkillLeaf {
|
|
1321
|
-
skillId: string;
|
|
1322
|
-
sourceId: string;
|
|
1323
|
-
name: string;
|
|
1324
|
-
description: string;
|
|
1325
|
-
relativeRoot: string;
|
|
1326
|
-
canonicalPath: string;
|
|
1327
|
-
contentHash: string;
|
|
1328
|
-
riskFlags: string[];
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
export interface Channel {
|
|
1332
|
-
channelId: ChannelId;
|
|
1333
|
-
displayName: string;
|
|
1334
|
-
resolvedPath: string;
|
|
1335
|
-
preferredStrategy: DeployStrategy;
|
|
1336
|
-
available: boolean;
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
export interface Deployment {
|
|
1340
|
-
deploymentId: string;
|
|
1341
|
-
skillId: string;
|
|
1342
|
-
channelId: ChannelId;
|
|
1343
|
-
strategy: DeployStrategy;
|
|
1344
|
-
targetPath: string;
|
|
1345
|
-
status: DeploymentStatus;
|
|
1346
|
-
lastAppliedAt?: string;
|
|
1347
|
-
}
|
|
1348
|
-
```
|
|
1349
|
-
|
|
1350
|
-
---
|
|
1351
|
-
|
|
1352
|
-
## 7. Adapter 接口规范
|
|
1353
|
-
|
|
1354
|
-
## 7.1 Source Adapter
|
|
1355
|
-
|
|
1356
|
-
```ts
|
|
1357
|
-
export interface ResolvedSource {
|
|
1358
|
-
sourceType: "git" | "clawhub" | "registry";
|
|
1359
|
-
locator: string;
|
|
1360
|
-
normalizedId: string;
|
|
1361
|
-
metadata?: Record<string, unknown>;
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
export interface FetchResult {
|
|
1365
|
-
source: Source;
|
|
1366
|
-
snapshot: SourceSnapshot;
|
|
1367
|
-
storageRoot: string;
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
export interface DiscoveredSkill {
|
|
1371
|
-
name: string;
|
|
1372
|
-
description: string;
|
|
1373
|
-
relativeRoot: string;
|
|
1374
|
-
contentHash: string;
|
|
1375
|
-
riskFlags: string[];
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
export interface SourceAdapter {
|
|
1379
|
-
kind: "git" | "clawhub" | "registry";
|
|
1380
|
-
probe(input: string): boolean;
|
|
1381
|
-
resolve(input: string): Promise<ResolvedSource>;
|
|
1382
|
-
fetch(source: ResolvedSource): Promise<FetchResult>;
|
|
1383
|
-
update(source: Source, snapshot: SourceSnapshot): Promise<FetchResult>;
|
|
1384
|
-
scan(storageRoot: string): Promise<DiscoveredSkill[]>;
|
|
1385
|
-
}
|
|
1386
|
-
```
|
|
1387
|
-
|
|
1388
|
-
### Git Adapter 额外职责
|
|
1389
|
-
|
|
1390
|
-
- 支持 branch/ref/commit
|
|
1391
|
-
- 提供远程变化检查
|
|
1392
|
-
- 在公开 GitHub 来源下可使用 API 预览树结构,但正式下载仍以 git 为准
|
|
1393
|
-
|
|
1394
|
-
### ClawHub Adapter 额外职责
|
|
1395
|
-
|
|
1396
|
-
- shell-out 调用 `clawhub`
|
|
1397
|
-
- 读取安装结果与 lock 信息
|
|
1398
|
-
- 将 registry version 映射为 `versionRef`
|
|
1399
|
-
|
|
1400
|
-
## 7.2 Channel Adapter
|
|
1401
|
-
|
|
1402
|
-
```ts
|
|
1403
|
-
export interface DeploymentPlanItem {
|
|
1404
|
-
skillId: string;
|
|
1405
|
-
channelId: ChannelId;
|
|
1406
|
-
strategy: DeployStrategy;
|
|
1407
|
-
canonicalPath: string;
|
|
1408
|
-
targetPath: string;
|
|
1409
|
-
action: "create" | "replace" | "remove" | "skip";
|
|
1410
|
-
reason?: string;
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
export interface DeploymentPlan {
|
|
1414
|
-
channelId: ChannelId;
|
|
1415
|
-
items: DeploymentPlanItem[];
|
|
1416
|
-
warnings: string[];
|
|
1417
|
-
}
|
|
1418
|
-
|
|
1419
|
-
export interface DoctorFinding {
|
|
1420
|
-
code: string;
|
|
1421
|
-
severity: "info" | "warn" | "error";
|
|
1422
|
-
message: string;
|
|
1423
|
-
target?: string;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
export interface ChannelAdapter {
|
|
1427
|
-
kind: ChannelId;
|
|
1428
|
-
detect(): Promise<Channel | null>;
|
|
1429
|
-
plan(skills: SkillLeaf[], channel: Channel): Promise<DeploymentPlan>;
|
|
1430
|
-
apply(plan: DeploymentPlan): Promise<Deployment[]>;
|
|
1431
|
-
diagnose(channel: Channel): Promise<DoctorFinding[]>;
|
|
1432
|
-
}
|
|
1433
|
-
```
|
|
1434
|
-
|
|
1435
|
-
---
|
|
1436
|
-
|
|
1437
|
-
## 8. 关键算法规范
|
|
1438
|
-
|
|
1439
|
-
## 8.1 Skill Scanner 算法
|
|
1440
|
-
|
|
1441
|
-
### 输入
|
|
1442
|
-
|
|
1443
|
-
- `sourceRoot`
|
|
1444
|
-
- `scanOptions`
|
|
1445
|
-
|
|
1446
|
-
### 伪代码
|
|
1447
|
-
|
|
1448
|
-
```text
|
|
1449
|
-
walk(sourceRoot)
|
|
1450
|
-
ignore directories: .git, node_modules, dist, build, .next, target
|
|
1451
|
-
if currentDir contains SKILL.md:
|
|
1452
|
-
parse frontmatter
|
|
1453
|
-
validate required fields
|
|
1454
|
-
emit SkillLeaf candidate
|
|
1455
|
-
do not recurse into nested skill roots unless explicit nested mode enabled
|
|
1456
|
-
```
|
|
1457
|
-
|
|
1458
|
-
### 规则
|
|
1459
|
-
|
|
1460
|
-
- 默认不允许“skill 中嵌 skill”自动递归安装
|
|
1461
|
-
- 若一个目录命中 `SKILL.md`,把它视为 leaf 边界
|
|
1462
|
-
- 生成 `contentHash` 时应基于 leaf root 下所有受管文件
|
|
1463
|
-
|
|
1464
|
-
## 8.2 Deployment Planner 算法
|
|
1465
|
-
|
|
1466
|
-
### 输入
|
|
1467
|
-
|
|
1468
|
-
- 目标 channel
|
|
1469
|
-
- manifest 中该 channel 的选中 skill 列表
|
|
1470
|
-
- 当前 lock 中已存在的 deployments
|
|
1471
|
-
- 磁盘实际状态
|
|
1472
|
-
|
|
1473
|
-
### 输出
|
|
1474
|
-
|
|
1475
|
-
- `DeploymentPlan`
|
|
1476
|
-
|
|
1477
|
-
### 规则
|
|
1478
|
-
|
|
1479
|
-
1. 先构建 desired set
|
|
1480
|
-
2. 再读取 current set
|
|
1481
|
-
3. 求 diff:
|
|
1482
|
-
- desired - current => create
|
|
1483
|
-
- current - desired => remove
|
|
1484
|
-
- desired ∩ current 且 hash 变化 => replace
|
|
1485
|
-
- desired ∩ current 且一致 => skip
|
|
1486
|
-
4. 若遇到 foreign-existing,计划项变为 `skip` 并附 reason
|
|
1487
|
-
|
|
1488
|
-
## 8.3 Copy Deploy 算法(OpenClaw)
|
|
1489
|
-
|
|
1490
|
-
```text
|
|
1491
|
-
for each plan item:
|
|
1492
|
-
stage copy into SM_HOME/tmp/<deploymentId>
|
|
1493
|
-
verify realpath(target parent) within configured root
|
|
1494
|
-
rename staged dir -> final target
|
|
1495
|
-
fsync parent dir
|
|
1496
|
-
```
|
|
1497
|
-
|
|
1498
|
-
## 8.4 Symlink Deploy 算法
|
|
1499
|
-
|
|
1500
|
-
```text
|
|
1501
|
-
for each plan item:
|
|
1502
|
-
ensure target parent exists
|
|
1503
|
-
if target exists and managed-by-us -> remove/replace
|
|
1504
|
-
if target exists and foreign -> skip with warning
|
|
1505
|
-
ln -s canonicalPath targetPath
|
|
1506
|
-
```
|
|
1507
|
-
|
|
1508
|
-
## 8.5 Update 算法
|
|
1509
|
-
|
|
1510
|
-
```text
|
|
1511
|
-
resolve sources to update
|
|
1512
|
-
for each source:
|
|
1513
|
-
fetch/update snapshot
|
|
1514
|
-
rescan skills
|
|
1515
|
-
rebuild canonical entries for changed skills only
|
|
1516
|
-
recompute deployments for affected channels
|
|
1517
|
-
if --apply then apply plans
|
|
1518
|
-
commit new lock atomically
|
|
1519
|
-
```
|
|
1520
|
-
|
|
1521
|
-
---
|
|
1522
|
-
|
|
1523
|
-
## 9. TUI 详细交互规范
|
|
1524
|
-
|
|
1525
|
-
## 9.1 页面流转
|
|
1526
|
-
|
|
1527
|
-
```text
|
|
1528
|
-
Start
|
|
1529
|
-
-> ChannelSelectScreen
|
|
1530
|
-
-> SkillTreeScreen
|
|
1531
|
-
-> ApplyPreviewScreen
|
|
1532
|
-
-> ApplyResultScreen
|
|
1533
|
-
-> Exit
|
|
1534
|
-
```
|
|
1535
|
-
|
|
1536
|
-
## 9.2 `ChannelSelectScreen`
|
|
1537
|
-
|
|
1538
|
-
### 展示字段
|
|
1539
|
-
|
|
1540
|
-
- channel 名称
|
|
1541
|
-
- 是否检测到
|
|
1542
|
-
- 目标路径
|
|
1543
|
-
- 默认策略
|
|
1544
|
-
- 健康状态
|
|
1545
|
-
|
|
1546
|
-
### 操作键
|
|
1547
|
-
|
|
1548
|
-
- `↑ / ↓`:移动
|
|
1549
|
-
- `Space`:切换选中
|
|
1550
|
-
- `a`:全选 / 全不选
|
|
1551
|
-
- `Enter`:进入下一屏
|
|
1552
|
-
- `Esc`:退出
|
|
1553
|
-
|
|
1554
|
-
## 9.3 `SkillTreeScreen`
|
|
1555
|
-
|
|
1556
|
-
### 展示结构
|
|
1557
|
-
|
|
1558
|
-
- 一级:source display root
|
|
1559
|
-
- 二级:skill leaf
|
|
1560
|
-
|
|
1561
|
-
### 状态
|
|
1562
|
-
|
|
1563
|
-
- `[ ]`:未选
|
|
1564
|
-
- `[-]`:部分选中
|
|
1565
|
-
- `[x]`:全部选中
|
|
1566
|
-
|
|
1567
|
-
### 操作键
|
|
1568
|
-
|
|
1569
|
-
- `↑ / ↓`:移动
|
|
1570
|
-
- `Space`:选中/取消
|
|
1571
|
-
- `Tab`:展开/收起一级节点
|
|
1572
|
-
- `Enter`:进入预览
|
|
1573
|
-
- `Backspace`:返回上一屏
|
|
1574
|
-
|
|
1575
|
-
## 9.4 `ApplyPreviewScreen`
|
|
1576
|
-
|
|
1577
|
-
### 展示字段
|
|
1578
|
-
|
|
1579
|
-
- channels 数量
|
|
1580
|
-
- skills 数量
|
|
1581
|
-
- create / replace / remove / skip 计数
|
|
1582
|
-
- warnings 列表
|
|
1583
|
-
- conflicts 列表
|
|
1584
|
-
|
|
1585
|
-
### 操作键
|
|
1586
|
-
|
|
1587
|
-
- `Enter`:确认应用
|
|
1588
|
-
- `Backspace`:返回树选择
|
|
1589
|
-
- `q`:取消
|
|
1590
|
-
|
|
1591
|
-
---
|
|
1592
|
-
|
|
1593
|
-
## 10. 错误码规范
|
|
1594
|
-
|
|
1595
|
-
错误码统一形式:`SM_<DOMAIN>_<CODE>`
|
|
1596
|
-
|
|
1597
|
-
### 10.1 Source 相关
|
|
1598
|
-
|
|
1599
|
-
- `SM_SOURCE_UNSUPPORTED`:无法识别来源
|
|
1600
|
-
- `SM_SOURCE_RESOLVE_FAILED`:来源解析失败
|
|
1601
|
-
- `SM_SOURCE_FETCH_FAILED`:下载或拉取失败
|
|
1602
|
-
- `SM_SOURCE_UPDATE_CONFLICT`:更新过程中发现本地 source 被手工修改
|
|
1603
|
-
|
|
1604
|
-
### 10.2 Scan 相关
|
|
1605
|
-
|
|
1606
|
-
- `SM_SCAN_SKILL_MD_MISSING`:未发现合法 `SKILL.md`
|
|
1607
|
-
- `SM_SCAN_FRONTMATTER_INVALID`:frontmatter 无法解析
|
|
1608
|
-
- `SM_SCAN_NAME_DIR_MISMATCH`:name 与目录名不一致
|
|
1609
|
-
- `SM_SCAN_DUPLICATE_SKILL`:同一 source 内发现重名 skill
|
|
1610
|
-
|
|
1611
|
-
### 10.3 Deployment 相关
|
|
1612
|
-
|
|
1613
|
-
- `SM_DEPLOY_TARGET_EXISTS_FOREIGN`:目标路径已存在非受管文件
|
|
1614
|
-
- `SM_DEPLOY_BROKEN_SYMLINK`:存在断链
|
|
1615
|
-
- `SM_DEPLOY_COPY_OUTSIDE_ROOT`:copy 目标越出受允根目录
|
|
1616
|
-
- `SM_DEPLOY_STRATEGY_UNSUPPORTED`:channel 不支持该分发策略
|
|
1617
|
-
|
|
1618
|
-
### 10.4 State 相关
|
|
1619
|
-
|
|
1620
|
-
- `SM_STATE_SCHEMA_UNKNOWN`:schemaVersion 不识别
|
|
1621
|
-
- `SM_STATE_MIGRATION_FAILED`:状态迁移失败
|
|
1622
|
-
- `SM_STATE_LOCK_WRITE_FAILED`:lock 原子写入失败
|
|
1623
|
-
|
|
1624
|
-
### 10.5 Doctor 相关
|
|
1625
|
-
|
|
1626
|
-
- `SM_DOCTOR_CHANNEL_UNAVAILABLE`:渠道不可用
|
|
1627
|
-
- `SM_DOCTOR_REALPATH_RISK`:realpath 风险
|
|
1628
|
-
- `SM_DOCTOR_DRIFT_DETECTED`:manifest/lock/磁盘三者漂移
|
|
1629
|
-
|
|
1630
|
-
---
|
|
1631
|
-
|
|
1632
|
-
## 11. 日志与可观测性
|
|
1633
|
-
|
|
1634
|
-
### 11.1 控制台日志级别
|
|
1635
|
-
|
|
1636
|
-
- `info`
|
|
1637
|
-
- `warn`
|
|
1638
|
-
- `error`
|
|
1639
|
-
- `debug`
|
|
1640
|
-
|
|
1641
|
-
### 11.2 日志文件
|
|
1642
|
-
|
|
1643
|
-
建议:
|
|
1644
|
-
|
|
1645
|
-
```text
|
|
1646
|
-
~/.skillflow/logs/
|
|
1647
|
-
current.log
|
|
1648
|
-
previous.log
|
|
1649
|
-
```
|
|
1650
|
-
|
|
1651
|
-
### 11.3 审计事件
|
|
1652
|
-
|
|
1653
|
-
`history.ndjson` 必须可回答这些问题:
|
|
1654
|
-
|
|
1655
|
-
- 某个 source 何时被添加
|
|
1656
|
-
- 某个 skill 何时被应用到某个 channel
|
|
1657
|
-
- 某次 update 改了哪些 snapshot
|
|
1658
|
-
- 某次 doctor 发现了什么问题
|
|
1659
|
-
|
|
1660
|
-
---
|
|
1661
|
-
|
|
1662
|
-
## 12. 安全与防御式实现要求
|
|
1663
|
-
|
|
1664
|
-
1. **默认不执行第三方脚本**
|
|
1665
|
-
2. **所有路径操作先做 `realpath` 校验**
|
|
1666
|
-
3. **受管 symlink 通过 sidecar 元数据或 lock 映射识别**
|
|
1667
|
-
4. **删除操作只删除受管目标**
|
|
1668
|
-
5. **copy 部署使用临时目录,完成后 rename 提交**
|
|
1669
|
-
6. **风险 flag 在 UI 和 JSON 输出中都必须可见**
|
|
1670
|
-
7. **外部 CLI bridge(如 ClawHub)必须收集 exit code、stdout、stderr**
|
|
1671
|
-
|
|
1672
|
-
---
|
|
1673
|
-
|
|
1674
|
-
## 13. 测试计划
|
|
1675
|
-
|
|
1676
|
-
## 13.1 单元测试
|
|
1677
|
-
|
|
1678
|
-
覆盖:
|
|
1679
|
-
|
|
1680
|
-
- source parser
|
|
1681
|
-
- id normalizer
|
|
1682
|
-
- frontmatter parser
|
|
1683
|
-
- manifest/lock validator
|
|
1684
|
-
- planner diff 逻辑
|
|
1685
|
-
- 错误码映射
|
|
1686
|
-
|
|
1687
|
-
## 13.2 集成测试
|
|
1688
|
-
|
|
1689
|
-
### 用例 A:Git 单仓多 skill
|
|
1690
|
-
|
|
1691
|
-
1. add git repo
|
|
1692
|
-
2. scan 出 3 个 leaf
|
|
1693
|
-
3. config 到 Claude + Codex
|
|
1694
|
-
4. 验证 symlink 数量与 lock deployments
|
|
1695
|
-
|
|
1696
|
-
### 用例 B:OpenClaw copy
|
|
1697
|
-
|
|
1698
|
-
1. 检测 workspace
|
|
1699
|
-
2. apply 到 openclaw
|
|
1700
|
-
3. 验证复制后的 skill realpath 在 workspace root 内
|
|
1701
|
-
|
|
1702
|
-
### 用例 C:更新后重投影
|
|
1703
|
-
|
|
1704
|
-
1. 初始安装 skill A
|
|
1705
|
-
2. 上游变更 skill A 内容
|
|
1706
|
-
3. update --apply
|
|
1707
|
-
4. lock 中 hash 更新,deployment 状态回到 `applied`
|
|
1708
|
-
|
|
1709
|
-
### 用例 D:foreign-existing
|
|
1710
|
-
|
|
1711
|
-
1. 在目标目录预先创建同名非受管文件夹
|
|
1712
|
-
2. apply
|
|
1713
|
-
3. 返回 `SM_DEPLOY_TARGET_EXISTS_FOREIGN`
|
|
1714
|
-
|
|
1715
|
-
### 用例 E:卸载
|
|
1716
|
-
|
|
1717
|
-
1. 安装 source X
|
|
1718
|
-
2. 投影到多个 channel
|
|
1719
|
-
3. uninstall X
|
|
1720
|
-
4. 验证 source、canonical、deployments 被清理
|
|
1721
|
-
|
|
1722
|
-
## 13.3 E2E 测试
|
|
1723
|
-
|
|
1724
|
-
- 在临时 HOME 下运行完整 CLI
|
|
1725
|
-
- 验证 state 文件与磁盘结构一致
|
|
1726
|
-
- 验证 JSON 模式输出可供脚本消费
|
|
1727
|
-
|
|
1728
|
-
---
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
## 13.4 Discovery 专项测试
|
|
1732
|
-
|
|
1733
|
-
需要新增以下测试矩阵:
|
|
1734
|
-
|
|
1735
|
-
### 用例 F:`find` 命中已安装技能
|
|
1736
|
-
|
|
1737
|
-
- 本地 inventory 已存在 `react-best-practices`
|
|
1738
|
-
- 查询 `react performance`
|
|
1739
|
-
- 结果首屏应标注 `already installed`
|
|
1740
|
-
|
|
1741
|
-
### 用例 G:registry + leaderboard + git 混合召回
|
|
1742
|
-
|
|
1743
|
-
- registry 返回 1 个 verified 候选
|
|
1744
|
-
- leaderboard 返回 2 个热门候选
|
|
1745
|
-
- git 搜索返回 3 个普通候选
|
|
1746
|
-
- 排序应遵守 tier 与 trust 规则
|
|
1747
|
-
|
|
1748
|
-
### 用例 H:repo path 直装
|
|
1749
|
-
|
|
1750
|
-
- 输入 `github:openai/skills --path skills/.curated/pdf`
|
|
1751
|
-
- 应直接完成 source 导入、定位 leaf、生成 lock
|
|
1752
|
-
|
|
1753
|
-
### 用例 I:非 skill 工件忽略
|
|
1754
|
-
|
|
1755
|
-
- source 同时包含 `skills/`、`commands/`、`agents/`
|
|
1756
|
-
- 扫描器只纳入 skill,其他仅 warning
|
|
1757
|
-
|
|
1758
|
-
### 用例 J:安装后反馈
|
|
1759
|
-
|
|
1760
|
-
- 对需要刷新 / 重启的渠道,安装完成后应给出提示
|
|
1761
|
-
- 对可热加载渠道,不应误提示必须重启
|
|
1762
|
-
|
|
1763
|
-
## 14. 发布流程建议
|
|
1764
|
-
|
|
1765
|
-
## 14.1 首发发布
|
|
1766
|
-
|
|
1767
|
-
- npm package:`skill-flow`
|
|
1768
|
-
- 可执行入口:`bin/skill-flow`
|
|
1769
|
-
- README 包含 quickstart 与 channel caveats
|
|
1770
|
-
|
|
1771
|
-
## 14.2 CI 流程
|
|
1772
|
-
|
|
1773
|
-
- install
|
|
1774
|
-
- lint
|
|
1775
|
-
- test
|
|
1776
|
-
- build
|
|
1777
|
-
- package smoke test
|
|
1778
|
-
- draft release
|
|
1779
|
-
|
|
1780
|
-
## 14.3 P1 发布补充
|
|
1781
|
-
|
|
1782
|
-
- Homebrew tap
|
|
1783
|
-
- shell completion
|
|
1784
|
-
- upgrade notice
|
|
1785
|
-
|
|
1786
|
-
---
|
|
1787
|
-
|
|
1788
|
-
## 15. 首个 Sprint 建议拆解
|
|
1789
|
-
|
|
1790
|
-
### Sprint 1(基础骨架)
|
|
1791
|
-
|
|
1792
|
-
- 初始化 oclif + TypeScript + pnpm + Vitest
|
|
1793
|
-
- 建立 domain model
|
|
1794
|
-
- state 文件读写与 schema 验证
|
|
1795
|
-
- Git adapter 最小实现
|
|
1796
|
-
|
|
1797
|
-
### Sprint 2(扫描与列表)
|
|
1798
|
-
|
|
1799
|
-
- scanner
|
|
1800
|
-
- parser
|
|
1801
|
-
- list
|
|
1802
|
-
- canonical skill 构建
|
|
1803
|
-
|
|
1804
|
-
### Sprint 3(分发与 TUI)
|
|
1805
|
-
|
|
1806
|
-
- Channel adapters
|
|
1807
|
-
- planner / applier
|
|
1808
|
-
- config TUI
|
|
1809
|
-
- doctor 初版
|
|
1810
|
-
|
|
1811
|
-
### Sprint 4(更新与卸载)
|
|
1812
|
-
|
|
1813
|
-
- update
|
|
1814
|
-
- uninstall
|
|
1815
|
-
- drift detection
|
|
1816
|
-
- e2e 测试
|
|
1817
|
-
|
|
1818
|
-
### Sprint 5(ClawHub 与打磨)
|
|
1819
|
-
|
|
1820
|
-
- ClawHub adapter
|
|
1821
|
-
- JSON 输出模式
|
|
1822
|
-
- 文档与发布流程
|
|
1823
|
-
|
|
1824
|
-
---
|
|
1825
|
-
|
|
1826
|
-
## 16. 最终实施结论
|
|
1827
|
-
|
|
1828
|
-
这份文档的最终工程结论如下:
|
|
1829
|
-
|
|
1830
|
-
1. **先做全局级 manager,再做项目级 manager**。
|
|
1831
|
-
2. **先做 Git + ClawHub 两类 source,再做 registry discovery**。
|
|
1832
|
-
3. **先做 per-channel strategy 自动化,再开放高级 override**。
|
|
1833
|
-
4. **坚持 manifest/lock 双层状态,不做无状态运行**。
|
|
1834
|
-
5. **坚持 OpenClaw 默认 copy,其他主渠道默认 symlink**。
|
|
1835
|
-
6. **坚持状态原子写入、部署 staged apply、删除只删受管内容**。
|
|
1836
|
-
7. **坚持 TUI 作为主配置界面,而不是靠长 flag 拼装体验**。
|
|
1837
|
-
|
|
1838
|
-
这已经足够作为研发启动、任务拆解和首轮工程评审的直接输入文档。
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
---
|
|
1842
|
-
|
|
1843
|
-
## 附录 A:本次修订重点
|
|
1844
|
-
|
|
1845
|
-
v1.2 相比 v1.1 新增或明确了以下内容:
|
|
1846
|
-
|
|
1847
|
-
1. 把 `search` 提升为正式 `find` Discovery 工作流。
|
|
1848
|
-
2. 新增 `SkillCandidate` 领域对象。
|
|
1849
|
-
3. 新增 Discovery Source Tiers 与排序规则。
|
|
1850
|
-
4. 新增 `install` 直装模式,支持 repo path / curated item / registry item。
|
|
1851
|
-
5. 新增 installed annotation 与安装后反馈要求。
|
|
1852
|
-
6. 新增 `inventory-index.json` 与 `discovery-cache.json`。
|
|
1853
|
-
7. 新增 Channel Feature Compatibility Matrix。
|
|
1854
|
-
8. 明确非 skill 工件默认忽略,不纳入 MVP 安装对象。
|
|
1855
|
-
|
|
1856
|
-
## 附录 B:参考资料
|
|
1857
|
-
|
|
1858
|
-
- https://andrew.ooo/posts/openclaw-skills-sources-guide/
|
|
1859
|
-
- https://github.com/openai/skills/blob/main/skills/.system/skill-installer/SKILL.md
|
|
1860
|
-
- https://code.claude.com/docs/en/skills
|
|
1861
|
-
- https://github.com/vercel-labs/skills/blob/main/skills/find-skills/SKILL.md
|
|
1862
|
-
- https://github.com/alirezarezvani/claude-skills/blob/main/INSTALLATION.md
|