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.
Files changed (57) hide show
  1. package/README.md +62 -23
  2. package/README.zh.md +63 -25
  3. package/dist/cli.js +13 -39
  4. package/dist/cli.js.map +1 -1
  5. package/dist/domain/types.d.ts +12 -1
  6. package/dist/services/doctor-service.js +1 -1
  7. package/dist/services/doctor-service.js.map +1 -1
  8. package/dist/services/skill-flow.d.ts +16 -13
  9. package/dist/services/skill-flow.js +158 -5
  10. package/dist/services/skill-flow.js.map +1 -1
  11. package/dist/services/source-service.d.ts +11 -1
  12. package/dist/services/source-service.js +60 -18
  13. package/dist/services/source-service.js.map +1 -1
  14. package/dist/services/workflow-service.d.ts +2 -2
  15. package/dist/services/workflow-service.js +17 -4
  16. package/dist/services/workflow-service.js.map +1 -1
  17. package/dist/services/workspace-bootstrap-service.d.ts +25 -0
  18. package/dist/services/workspace-bootstrap-service.js +148 -0
  19. package/dist/services/workspace-bootstrap-service.js.map +1 -0
  20. package/dist/state/store.js +1 -0
  21. package/dist/state/store.js.map +1 -1
  22. package/dist/tests/skill-flow.test.js +1458 -0
  23. package/dist/tests/skill-flow.test.js.map +1 -1
  24. package/dist/tui/config-app.d.ts +3 -0
  25. package/dist/tui/config-app.js +61 -1
  26. package/dist/tui/config-app.js.map +1 -1
  27. package/dist/tui/find-app.d.ts +1 -1
  28. package/dist/tui/find-app.js +36 -4
  29. package/dist/tui/find-app.js.map +1 -1
  30. package/dist/utils/format.js +1 -1
  31. package/dist/utils/format.js.map +1 -1
  32. package/dist/utils/naming.d.ts +1 -0
  33. package/dist/utils/naming.js +7 -1
  34. package/dist/utils/naming.js.map +1 -1
  35. package/dist/utils/source-id.js +4 -0
  36. package/dist/utils/source-id.js.map +1 -1
  37. package/package.json +10 -1
  38. package/.gstack/browse-network.log +0 -1
  39. package/.gstack/browse.json +0 -7
  40. package/.gstack/qa-reports/base-branch.txt +0 -1
  41. package/.gstack/qa-reports/qa-report-skill-flow-cli-2026-03-22.md +0 -159
  42. package/.gstack/qa-reports/qa-report-skill-manager-2026-03-22.md +0 -60
  43. package/docs/DESIGN.md +0 -407
  44. package/docs/PRD/PRD-1.0.0.md +0 -1862
  45. package/docs/PRD/renew/PRD-0.0.0.md +0 -26
  46. package/docs/PRD/renew/PRD-0.0.1.md +0 -408
  47. package/docs/PRD/renew/PRD-0.0.2.md +0 -705
  48. package/docs/PRD/renew/PRD-0.0.3.md +0 -740
  49. package/docs/PRD/renew/PRD-0.0.4.md +0 -1494
  50. package/docs/README.md +0 -242
  51. package/docs/plan/PLAN_v1.0.0.md +0 -663
  52. package/docs/plan/PLAN_v1.0.1.md +0 -845
  53. package/docs/refrences/README.md +0 -9
  54. package/docs/refrences/agent-skill-paths.md +0 -274
  55. package/docs/refrences/config-state-reconciliation.md +0 -199
  56. package/docs/refrences/naming-dedupe-warning-rules.md +0 -482
  57. package/img/img-1.jpg +0 -0
@@ -1,1494 +0,0 @@
1
- # skill-flow PRD + 工程实施文档
2
-
3
- > 版本:v1.1
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
- # 二、skill-flow 定型版 PRD
176
-
177
- ## 1. 产品定义
178
-
179
- `skill-flow` 是一个面向 Agent Skills 生态的 macOS CLI。它统一管理多来源 skills,把上游内容下载到 `~/.skillflow/source/`,扫描出合法的 `SkillLeaf`,在 `~/.skillflow/skills/` 建立 canonical skill 集合,再将用户选中的 skill 以适配渠道的方式分发到 Claude Code、OpenCode、Codex、OpenClaw 与通用 `.agents/skills`。其核心职责是**索引与投影**,不是执行 skill。
180
-
181
- ## 2. 目标与非目标
182
-
183
- ### 2.1 目标
184
-
185
- MVP 要完成六件事:
186
-
187
- 1. 支持 Git Source 与 ClawHub Source 的添加、扫描、更新、卸载。
188
- 2. 支持“单 source 多 skill”的两层树状模型。
189
- 3. 支持 `skill-flow config` 的树形多选 TUI。
190
- 4. 支持按 channel 投影:Claude Code、OpenCode、Codex、OpenClaw、`.agents/skills`。
191
- 5. 支持 `manifest.json + lock.json` 双层状态。
192
- 6. 支持 `doctor` 做冲突、漂移、路径和兼容性检查。
193
-
194
- ### 2.2 非目标
195
-
196
- MVP 不做以下事情:
197
-
198
- 1. 不执行 skill 中的脚本。
199
- 2. 不修改上游 `SKILL.md`。
200
- 3. 不做 GUI。
201
- 4. 不做通用 project-scope 管理;只有 OpenClaw 因官方工作区模型原因,保留 workspace 渠道。
202
-
203
- ## 3. 用户与典型场景
204
-
205
- 目标用户是同时使用多个 AI coding agent 的开发者。他们的高频动作是:
206
-
207
- - 从 GitHub 或 ClawHub 获取 skills
208
- - 统一查看一个 source 里有哪些 skill
209
- - 把其中部分 skill 应用到某个或全部渠道
210
- - 后续更新 source,并同步刷新多个渠道
211
- - 卸载整个 source,或仅取消某个 channel 的启用状态
212
-
213
- ## 4. 领域模型
214
-
215
- ### 4.1 Source
216
-
217
- 一个可更新的上游单位。
218
-
219
- 字段建议:
220
-
221
- - `sourceId`
222
- - `sourceType`
223
- - `locator`
224
- - `displayName`
225
- - `storageRoot`
226
- - `updateStrategy`
227
-
228
- ### 4.2 SourceSnapshot
229
-
230
- Source 在某一时刻的解析快照。
231
-
232
- - git:`remote + branch + commit SHA`
233
- - clawhub:`slug + version + contentHash`
234
- - future well-known:`baseUrl + indexHash/etag`
235
-
236
- ### 4.3 SkillLeaf
237
-
238
- 真正可安装的 skill 单元。满足条件:
239
-
240
- - 存在 `SKILL.md`
241
- - frontmatter 可解析
242
- - `name`
243
- - `description`
244
-
245
- 字段建议:
246
-
247
- - `skillId`
248
- - `sourceId`
249
- - `name`
250
- - `description`
251
- - `relativeRoot`
252
- - `contentHash`
253
- - `hasScripts`
254
- - `hasReferences`
255
- - `hasAssets`
256
- - `riskFlags[]`
257
-
258
- ### 4.4 Channel
259
-
260
- 一个目标适配器,而不是路径。
261
-
262
- 字段建议:
263
-
264
- - `channelId`
265
- - `displayName`
266
- - `resolvedPath`
267
- - `strategy`
268
- - `pathSource`
269
- - `healthStatus`
270
-
271
- ### 4.5 Deployment
272
-
273
- SkillLeaf 到 Channel 的一次投影关系。
274
-
275
- 字段建议:
276
-
277
- - `deploymentId`
278
- - `skillId`
279
- - `channelId`
280
- - `strategy`
281
- - `targetPath`
282
- - `status`
283
- - `lastAppliedAt`
284
-
285
- ## 5. 文件系统布局
286
-
287
- ```text
288
- ~/.skillflow/
289
- source/
290
- git/
291
- <sourceId>/
292
- clawhub/
293
- <sourceId>/
294
- skills/
295
- <sourceId>/
296
- <skillName>/ -> ../../source/...
297
- state/
298
- manifest.json
299
- lock.json
300
- channels.json
301
- history.ndjson
302
- cache/
303
- tmp/
304
- logs/
305
- ```
306
-
307
- ## 6. Source 策略
308
-
309
- ### 6.1 Git Source(MVP 必做)
310
-
311
- 输入支持:
312
-
313
- - GitHub `owner/repo`
314
- - 任意 git URL
315
- - 本地 git 路径
316
-
317
- ### 6.2 ClawHub Source(MVP 必做)
318
-
319
- 输入支持:
320
-
321
- - `clawhub:<slug>`
322
- - `clawhub:<slug>@<version>`
323
-
324
- MVP 实现:
325
-
326
- - 优先采用 **CLI bridge**:shell-out `clawhub install/update/list`
327
- - 将版本与来源信息同步到 `skill-flow lock`
328
-
329
- ### 6.3 Well-known Skills Discovery(P1)
330
-
331
- 只做接口预留,不进 MVP。
332
-
333
- ## 7. Source 命名与展示规则
334
-
335
- ### 外显 display 规则
336
-
337
- - Git 仓库:显示仓库名
338
- - 非 Git 且可识别作者:显示作者名
339
- - 无法识别:显示 `single`
340
-
341
- ### 内部 storage 规则
342
-
343
- - Git:`<host>__<owner>__<repo>`
344
- - ClawHub:`clawhub__<slug>`
345
- - Generic single:`single__<hash>`
346
-
347
- ## 8. Skill 扫描与索引规则
348
-
349
- 扫描逻辑:
350
-
351
- 1. 递归搜索包含 `SKILL.md` 的目录
352
- 2. 跳过 `.git`、`node_modules`、构建产物
353
- 3. 解析 frontmatter
354
- 4. 生成 `SkillLeaf` 索引项
355
- 5. 建立 `skills/<sourceId>/<skillName>` canonical 入口
356
-
357
- 校验等级:
358
-
359
- ### 标准校验
360
-
361
- - `SKILL.md` 存在
362
- - YAML 可解析
363
- - `name`
364
- - `description`
365
-
366
- ### 严格校验
367
-
368
- - `name` 与目录名匹配
369
- - 命名合法
370
- - `description` 长度合理
371
- - 相对路径引用可达
372
-
373
- ## 9. Channel 适配与默认策略
374
-
375
- ### 9.1 Claude Code
376
-
377
- - 默认路径:`~/.claude/skills`
378
- - 默认策略:`symlink`
379
- - 兜底策略:`copy`
380
-
381
- ### 9.2 OpenCode
382
-
383
- - 默认路径:`~/.config/opencode/skills`
384
- - 默认策略:`symlink`
385
-
386
- ### 9.3 Codex
387
-
388
- - 默认路径:`~/.agents/skills`
389
- - 默认策略:`symlink`
390
-
391
- ### 9.4 OpenClaw
392
-
393
- - 默认路径:`<workspace>/skills`,备选 `~/.openclaw/skills`
394
- - 默认策略:`copy`
395
-
396
- ### 9.5 通用 `.agents/skills`
397
-
398
- - 默认路径:`~/.agents/skills`
399
- - 默认策略:`symlink`
400
-
401
- ## 10. 命令设计
402
-
403
- 正式命令集:
404
-
405
- ```bash
406
- skill-flow add <source>
407
- skill-flow search <query>
408
- skill-flow list
409
- skill-flow config
410
- skill-flow update [--all | <sourceId>]
411
- skill-flow uninstall [<sourceId>...]
412
- skill-flow doctor
413
- ```
414
-
415
- ## 11. 状态文件设计
416
-
417
- ### `manifest.json`
418
-
419
- 记录用户意图:
420
-
421
- - sources
422
- - naming policy
423
- - selected skills by channel
424
- - user overrides
425
-
426
- ### `lock.json`
427
-
428
- 记录解析结果:
429
-
430
- - source snapshots
431
- - skill leaf inventory
432
- - deployments
433
- - content hashes
434
- - timestamps
435
- - schemaVersion
436
-
437
- ### `channels.json`
438
-
439
- 记录本机探测与 path override:
440
-
441
- - detected channels
442
- - resolved path
443
- - available strategies
444
- - health flags
445
-
446
- ### `history.ndjson`
447
-
448
- 记录审计事件:
449
-
450
- - add
451
- - update
452
- - config-apply
453
- - uninstall
454
- - doctor-warning
455
-
456
- ## 12. 冲突与一致性规则
457
-
458
- ### 12.1 同 channel 同名 skill
459
-
460
- 默认阻止,不静默覆盖。
461
-
462
- ### 12.2 目标路径已有非本工具管理文件
463
-
464
- 默认不接管,标记 `foreign-existing`。
465
-
466
- ### 12.3 Source 内同名 leaf
467
-
468
- 扫描时直接判定 source inventory 非法,需要用户缩小范围或忽略。
469
-
470
- ### 12.4 原子性
471
-
472
- 所有 state 文件写入采用:
473
-
474
- - `tmp write`
475
- - `fsync`
476
- - `rename`
477
-
478
- 所有 deployment 采用 staged apply;失败时不提交 lock 的成功状态。
479
-
480
- ## 13. 安全要求
481
-
482
- MVP 安全要求:
483
-
484
- 1. 永不执行 skill 脚本
485
- 2. 扫描时做 frontmatter 与路径校验
486
- 3. 拒绝 root 外 realpath 投影
487
- 4. 风险标记:
488
- - `has-scripts`
489
- - `invalid-frontmatter`
490
- - `name-dir-mismatch`
491
- - `external-symlink`
492
- - `foreign-existing`
493
- - `openclaw-root-risk`
494
- 5. 默认提示审计,`--yes` 才跳过确认
495
-
496
- ## 14. 技术栈
497
-
498
- ### 14.1 运行时与语言
499
-
500
- - **Node.js 24 LTS**
501
- - **TypeScript 5.x**
502
-
503
- ### 14.2 包管理与构建
504
-
505
- - **pnpm**
506
- - 发布到 **npm**
507
-
508
- ### 14.3 CLI 与 TUI
509
-
510
- - **oclif**
511
- - **Ink**
512
-
513
- ### 14.4 Schema 与状态验证
514
-
515
- - **Zod**
516
-
517
- ### 14.5 Git 访问
518
-
519
- - **system git**
520
- - **simple-git**
521
-
522
- ### 14.6 测试
523
-
524
- - **Vitest**
525
- - fixture-based filesystem integration tests
526
-
527
- ### 14.7 建议工程结构
528
-
529
- ```text
530
- src/
531
- commands/
532
- tui/
533
- domain/
534
- adapters/
535
- source/
536
- channel/
537
- services/
538
- scan/
539
- deploy/
540
- update/
541
- doctor/
542
- state/
543
- utils/
544
- ```
545
-
546
- ## 15. 里程碑
547
-
548
- ### Milestone 1
549
- - Git Source
550
- - 扫描器
551
- - manifest/lock
552
- - list/add/update
553
-
554
- ### Milestone 2
555
- - config TUI
556
- - Claude/OpenCode/Codex/agents 投影
557
- - doctor
558
-
559
- ### Milestone 3
560
- - OpenClaw copy deployment
561
- - ClawHub adapter
562
- - uninstall
563
-
564
- ### Milestone 4
565
- - search
566
- - diff
567
- - schema migration
568
- - alias conflict handling
569
-
570
- ### Milestone 5(P1)
571
- - well-known discovery
572
- - project-scope support
573
- - Homebrew tap
574
- - advanced channel overrides
575
- - external plugin SDK
576
-
577
- ---
578
-
579
- # 三、工程实施文档
580
-
581
- ## 1. 实施目标
582
-
583
- 这一部分不是再讨论“做什么”,而是明确“怎么落地”。目标是让工程团队在没有额外口头补充的情况下,直接进入:
584
-
585
- 1. 仓库初始化
586
- 2. 核心模块搭建
587
- 3. 命令实现
588
- 4. 端到端测试
589
- 5. 首个可发布 MVP
590
-
591
- ---
592
-
593
- ## 2. MVP 工程范围切片
594
-
595
- ### 2.1 必须在首发版本完成
596
-
597
- - Git Source Adapter
598
- - ClawHub Source Adapter(CLI bridge 方案)
599
- - Skill Scanner
600
- - Manifest/Lock/Channels 三类状态文件
601
- - Claude/OpenCode/Codex/Agents 四个 symlink channel
602
- - OpenClaw copy channel
603
- - `add / list / config / update / uninstall / doctor`
604
- - TUI 树状多选界面
605
- - 冲突检测、路径校验、原子写入、日志落盘
606
-
607
- ### 2.2 可以延后到 P1
608
-
609
- - well-known registry adapter
610
- - alias 命名策略
611
- - Homebrew tap 自动发布
612
- - project-scope 管理
613
- - 自定义 channel adapter SDK
614
- - 远程 diff 预览
615
-
616
- ---
617
-
618
- ## 3. 工程仓库建议结构
619
-
620
- ```text
621
- skill-flow/
622
- package.json
623
- pnpm-lock.yaml
624
- tsconfig.json
625
- vitest.config.ts
626
- README.md
627
- src/
628
- index.ts
629
- cli.ts
630
- commands/
631
- add.ts
632
- search.ts
633
- list.ts
634
- config.ts
635
- update.ts
636
- uninstall.ts
637
- doctor.ts
638
- tui/
639
- app.tsx
640
- screens/
641
- channel-select.tsx
642
- skill-tree.tsx
643
- apply-preview.tsx
644
- components/
645
- tree-node.tsx
646
- checkbox.tsx
647
- footer-hints.tsx
648
- status-pill.tsx
649
- domain/
650
- source.ts
651
- snapshot.ts
652
- skill.ts
653
- channel.ts
654
- deployment.ts
655
- errors.ts
656
- adapters/
657
- source/
658
- git.ts
659
- clawhub.ts
660
- registry.ts
661
- channel/
662
- claude.ts
663
- opencode.ts
664
- codex.ts
665
- openclaw.ts
666
- agents.ts
667
- services/
668
- detect/
669
- channels.ts
670
- scan/
671
- scanner.ts
672
- parser.ts
673
- validators.ts
674
- state/
675
- manifest.ts
676
- lock.ts
677
- channels.ts
678
- migrations.ts
679
- deploy/
680
- planner.ts
681
- symlink.ts
682
- copy.ts
683
- applier.ts
684
- source/
685
- resolve.ts
686
- fetch.ts
687
- update.ts
688
- doctor/
689
- checks.ts
690
- logging/
691
- history.ts
692
- logger.ts
693
- utils/
694
- fs.ts
695
- hash.ts
696
- path.ts
697
- prompt.ts
698
- time.ts
699
- ids.ts
700
- fixtures/
701
- repos/
702
- channels/
703
- snapshots/
704
- tests/
705
- unit/
706
- integration/
707
- e2e/
708
- ```
709
-
710
- 设计原则:
711
-
712
- - `commands/` 只做参数解析与 orchestration
713
- - `domain/` 只放模型和不依赖 IO 的规则
714
- - `adapters/` 隔离第三方系统差异
715
- - `services/` 承担业务编排
716
- - `tui/` 不直接触碰磁盘;通过 service 层读写
717
-
718
- ---
719
-
720
- ## 4. 命令参数规范
721
-
722
- ## 4.1 `skill-flow add`
723
-
724
- ```bash
725
- skill-flow add <source>
726
- [--name <displayName>]
727
- [--branch <branch>]
728
- [--ref <ref>]
729
- [--channel <channel...>]
730
- [--yes]
731
- [--json]
732
- ```
733
-
734
- ### 行为定义
735
-
736
- - `<source>` 支持:
737
- - `owner/repo`
738
- - `https://...git`
739
- - `git@...`
740
- - 本地路径
741
- - `clawhub:<slug>`
742
- - `clawhub:<slug>@<version>`
743
- - 若指定 `--channel`,则在 `add` 后直接触发一次 apply
744
- - 若指定 `--ref`,优先锁定对应 tag/commit
745
- - `--yes` 跳过来源确认与风险确认
746
-
747
- ## 4.2 `skill-flow search`
748
-
749
- ```bash
750
- skill-flow search <query>
751
- [--source git|clawhub|all]
752
- [--limit <n>]
753
- [--json]
754
- ```
755
-
756
- ### 行为定义
757
-
758
- - `--source clawhub`:正式支持
759
- - `--source git`:MVP 仅做 repo 级搜索或 locator 解析辅助
760
- - `--source all`:按 adapter 聚合结果
761
-
762
- ## 4.3 `skill-flow list`
763
-
764
- ```bash
765
- skill-flow list
766
- [--sources]
767
- [--skills]
768
- [--deployments]
769
- [--channel <channel>]
770
- [--source-id <id>]
771
- [--json]
772
- ```
773
-
774
- ### 行为定义
775
-
776
- - 默认输出 `sources + skills + deployment summary`
777
- - `--skills` 展示 skill leaf 明细
778
- - `--deployments` 展示按 channel 的启用状态
779
-
780
- ## 4.4 `skill-flow config`
781
-
782
- ```bash
783
- skill-flow config
784
- [--channel <channel...>]
785
- [--source-id <id>]
786
- [--non-interactive]
787
- [--json]
788
- ```
789
-
790
- ### 行为定义
791
-
792
- - 默认进入 TUI
793
- - `--non-interactive` 预留给脚本模式,MVP 可只支持有限 flag 驱动
794
- - 未传 `--channel` 时先展示 channel 多选
795
-
796
- ## 4.5 `skill-flow update`
797
-
798
- ```bash
799
- skill-flow update
800
- [--all]
801
- [--source-id <id>...]
802
- [--apply]
803
- [--dry-run]
804
- [--json]
805
- ```
806
-
807
- ### 行为定义
808
-
809
- - `--all` 更新所有 source
810
- - `--apply` 更新完成后重新部署受影响 channel
811
- - `--dry-run` 仅展示可更新项和变更摘要
812
-
813
- ## 4.6 `skill-flow uninstall`
814
-
815
- ```bash
816
- skill-flow uninstall <sourceId...>
817
- [--yes]
818
- [--json]
819
- ```
820
-
821
- ### 行为定义
822
-
823
- - 卸载 source 及其 canonical skills 与所有 deployments
824
- - 不删除其他来源产生的同名 skill
825
-
826
- ## 4.7 `skill-flow doctor`
827
-
828
- ```bash
829
- skill-flow doctor
830
- [--channel <channel...>]
831
- [--source-id <id>...]
832
- [--fix]
833
- [--json]
834
- ```
835
-
836
- ### 行为定义
837
-
838
- - 默认只检查不修改
839
- - `--fix` 仅修复确定性问题:断链重建、缺失 state 目录、历史文件 rotate
840
- - 冲突覆盖不属于自动修复范围
841
-
842
- ---
843
-
844
- ## 5. 状态文件 Schema
845
-
846
- ## 5.1 `manifest.json`
847
-
848
- 作用:记录用户意图。
849
-
850
- ```json
851
- {
852
- "$schema": "https://skill-flow.dev/schema/manifest-v1.json",
853
- "schemaVersion": 1,
854
- "sources": [
855
- {
856
- "sourceId": "github__vercel-labs__skills",
857
- "sourceType": "git",
858
- "locator": "vercel-labs/skills",
859
- "displayName": "skills",
860
- "options": {
861
- "ref": null,
862
- "branch": "main"
863
- }
864
- }
865
- ],
866
- "bindings": [
867
- {
868
- "channelId": "claude",
869
- "skillSelections": [
870
- {
871
- "sourceId": "github__vercel-labs__skills",
872
- "skillIds": ["frontend-design", "skill-creator"]
873
- }
874
- ]
875
- }
876
- ],
877
- "overrides": {
878
- "channels": {
879
- "openclaw": {
880
- "path": null,
881
- "strategy": "copy"
882
- }
883
- }
884
- }
885
- }
886
- ```
887
-
888
- ### 约束
889
-
890
- - `schemaVersion` 必填
891
- - `bindings` 只描述“期望启用哪些 skill 到哪些 channel”
892
- - 不记录部署是否成功;那是 lock 的职责
893
-
894
- ## 5.2 `lock.json`
895
-
896
- 作用:记录解析结果与当前落地状态。
897
-
898
- ```json
899
- {
900
- "$schema": "https://skill-flow.dev/schema/lock-v1.json",
901
- "schemaVersion": 1,
902
- "generatedAt": "2026-03-21T12:00:00.000Z",
903
- "sources": [
904
- {
905
- "sourceId": "github__vercel-labs__skills",
906
- "sourceType": "git",
907
- "snapshot": {
908
- "remote": "https://github.com/vercel-labs/skills.git",
909
- "branch": "main",
910
- "commit": "abc123"
911
- },
912
- "contentHash": "sha256:..."
913
- }
914
- ],
915
- "skills": [
916
- {
917
- "skillId": "frontend-design",
918
- "sourceId": "github__vercel-labs__skills",
919
- "name": "frontend-design",
920
- "description": "...",
921
- "relativeRoot": "skills/frontend-design",
922
- "canonicalPath": "~/.skillflow/skills/github__vercel-labs__skills/frontend-design",
923
- "contentHash": "sha256:...",
924
- "riskFlags": []
925
- }
926
- ],
927
- "deployments": [
928
- {
929
- "deploymentId": "dep_001",
930
- "skillId": "frontend-design",
931
- "channelId": "claude",
932
- "strategy": "symlink",
933
- "targetPath": "~/.claude/skills/frontend-design",
934
- "status": "applied",
935
- "lastAppliedAt": "2026-03-21T12:00:00.000Z"
936
- }
937
- ]
938
- }
939
- ```
940
-
941
- ### 约束
942
-
943
- - lock 必须可重建本地部署视图
944
- - `deployments.status` 允许:`planned | applied | stale | broken | removed`
945
- - `contentHash` 用于 update 后判断是否需要重投影
946
-
947
- ## 5.3 `channels.json`
948
-
949
- 作用:记录本机探测结果与 override。
950
-
951
- ```json
952
- {
953
- "$schema": "https://skill-flow.dev/schema/channels-v1.json",
954
- "schemaVersion": 1,
955
- "detected": [
956
- {
957
- "channelId": "claude",
958
- "path": "/Users/alice/.claude/skills",
959
- "pathSource": "default",
960
- "available": true,
961
- "preferredStrategy": "symlink"
962
- },
963
- {
964
- "channelId": "openclaw",
965
- "path": "/Users/alice/.openclaw/workspace/skills",
966
- "pathSource": "detected-workspace",
967
- "available": true,
968
- "preferredStrategy": "copy"
969
- }
970
- ]
971
- }
972
- ```
973
-
974
- ## 5.4 `history.ndjson`
975
-
976
- 每行一个事件,方便审计与排障。
977
-
978
- ```json
979
- {"ts":"2026-03-21T12:00:00.000Z","event":"add","sourceId":"github__vercel-labs__skills"}
980
- {"ts":"2026-03-21T12:01:00.000Z","event":"config-apply","channelId":"claude","count":2}
981
- ```
982
-
983
- ---
984
-
985
- ## 6. Domain Model TypeScript Interface
986
-
987
- ```ts
988
- export type SourceType = "git" | "clawhub" | "registry";
989
- export type ChannelId = "claude" | "opencode" | "codex" | "openclaw" | "agents";
990
- export type DeployStrategy = "symlink" | "copy";
991
- export type DeploymentStatus = "planned" | "applied" | "stale" | "broken" | "removed";
992
-
993
- export interface Source {
994
- sourceId: string;
995
- sourceType: SourceType;
996
- locator: string;
997
- displayName: string;
998
- storageRoot: string;
999
- updateStrategy: "git-pull" | "registry-sync" | "custom";
1000
- }
1001
-
1002
- export interface SourceSnapshot {
1003
- sourceId: string;
1004
- versionRef: string;
1005
- contentHash: string;
1006
- metadata: Record<string, unknown>;
1007
- }
1008
-
1009
- export interface SkillLeaf {
1010
- skillId: string;
1011
- sourceId: string;
1012
- name: string;
1013
- description: string;
1014
- relativeRoot: string;
1015
- canonicalPath: string;
1016
- contentHash: string;
1017
- riskFlags: string[];
1018
- }
1019
-
1020
- export interface Channel {
1021
- channelId: ChannelId;
1022
- displayName: string;
1023
- resolvedPath: string;
1024
- preferredStrategy: DeployStrategy;
1025
- available: boolean;
1026
- }
1027
-
1028
- export interface Deployment {
1029
- deploymentId: string;
1030
- skillId: string;
1031
- channelId: ChannelId;
1032
- strategy: DeployStrategy;
1033
- targetPath: string;
1034
- status: DeploymentStatus;
1035
- lastAppliedAt?: string;
1036
- }
1037
- ```
1038
-
1039
- ---
1040
-
1041
- ## 7. Adapter 接口规范
1042
-
1043
- ## 7.1 Source Adapter
1044
-
1045
- ```ts
1046
- export interface ResolvedSource {
1047
- sourceType: "git" | "clawhub" | "registry";
1048
- locator: string;
1049
- normalizedId: string;
1050
- metadata?: Record<string, unknown>;
1051
- }
1052
-
1053
- export interface FetchResult {
1054
- source: Source;
1055
- snapshot: SourceSnapshot;
1056
- storageRoot: string;
1057
- }
1058
-
1059
- export interface DiscoveredSkill {
1060
- name: string;
1061
- description: string;
1062
- relativeRoot: string;
1063
- contentHash: string;
1064
- riskFlags: string[];
1065
- }
1066
-
1067
- export interface SourceAdapter {
1068
- kind: "git" | "clawhub" | "registry";
1069
- probe(input: string): boolean;
1070
- resolve(input: string): Promise<ResolvedSource>;
1071
- fetch(source: ResolvedSource): Promise<FetchResult>;
1072
- update(source: Source, snapshot: SourceSnapshot): Promise<FetchResult>;
1073
- scan(storageRoot: string): Promise<DiscoveredSkill[]>;
1074
- }
1075
- ```
1076
-
1077
- ### Git Adapter 额外职责
1078
-
1079
- - 支持 branch/ref/commit
1080
- - 提供远程变化检查
1081
- - 在公开 GitHub 来源下可使用 API 预览树结构,但正式下载仍以 git 为准
1082
-
1083
- ### ClawHub Adapter 额外职责
1084
-
1085
- - shell-out 调用 `clawhub`
1086
- - 读取安装结果与 lock 信息
1087
- - 将 registry version 映射为 `versionRef`
1088
-
1089
- ## 7.2 Channel Adapter
1090
-
1091
- ```ts
1092
- export interface DeploymentPlanItem {
1093
- skillId: string;
1094
- channelId: ChannelId;
1095
- strategy: DeployStrategy;
1096
- canonicalPath: string;
1097
- targetPath: string;
1098
- action: "create" | "replace" | "remove" | "skip";
1099
- reason?: string;
1100
- }
1101
-
1102
- export interface DeploymentPlan {
1103
- channelId: ChannelId;
1104
- items: DeploymentPlanItem[];
1105
- warnings: string[];
1106
- }
1107
-
1108
- export interface DoctorFinding {
1109
- code: string;
1110
- severity: "info" | "warn" | "error";
1111
- message: string;
1112
- target?: string;
1113
- }
1114
-
1115
- export interface ChannelAdapter {
1116
- kind: ChannelId;
1117
- detect(): Promise<Channel | null>;
1118
- plan(skills: SkillLeaf[], channel: Channel): Promise<DeploymentPlan>;
1119
- apply(plan: DeploymentPlan): Promise<Deployment[]>;
1120
- diagnose(channel: Channel): Promise<DoctorFinding[]>;
1121
- }
1122
- ```
1123
-
1124
- ---
1125
-
1126
- ## 8. 关键算法规范
1127
-
1128
- ## 8.1 Skill Scanner 算法
1129
-
1130
- ### 输入
1131
-
1132
- - `sourceRoot`
1133
- - `scanOptions`
1134
-
1135
- ### 伪代码
1136
-
1137
- ```text
1138
- walk(sourceRoot)
1139
- ignore directories: .git, node_modules, dist, build, .next, target
1140
- if currentDir contains SKILL.md:
1141
- parse frontmatter
1142
- validate required fields
1143
- emit SkillLeaf candidate
1144
- do not recurse into nested skill roots unless explicit nested mode enabled
1145
- ```
1146
-
1147
- ### 规则
1148
-
1149
- - 默认不允许“skill 中嵌 skill”自动递归安装
1150
- - 若一个目录命中 `SKILL.md`,把它视为 leaf 边界
1151
- - 生成 `contentHash` 时应基于 leaf root 下所有受管文件
1152
-
1153
- ## 8.2 Deployment Planner 算法
1154
-
1155
- ### 输入
1156
-
1157
- - 目标 channel
1158
- - manifest 中该 channel 的选中 skill 列表
1159
- - 当前 lock 中已存在的 deployments
1160
- - 磁盘实际状态
1161
-
1162
- ### 输出
1163
-
1164
- - `DeploymentPlan`
1165
-
1166
- ### 规则
1167
-
1168
- 1. 先构建 desired set
1169
- 2. 再读取 current set
1170
- 3. 求 diff:
1171
- - desired - current => create
1172
- - current - desired => remove
1173
- - desired ∩ current 且 hash 变化 => replace
1174
- - desired ∩ current 且一致 => skip
1175
- 4. 若遇到 foreign-existing,计划项变为 `skip` 并附 reason
1176
-
1177
- ## 8.3 Copy Deploy 算法(OpenClaw)
1178
-
1179
- ```text
1180
- for each plan item:
1181
- stage copy into SM_HOME/tmp/<deploymentId>
1182
- verify realpath(target parent) within configured root
1183
- rename staged dir -> final target
1184
- fsync parent dir
1185
- ```
1186
-
1187
- ## 8.4 Symlink Deploy 算法
1188
-
1189
- ```text
1190
- for each plan item:
1191
- ensure target parent exists
1192
- if target exists and managed-by-us -> remove/replace
1193
- if target exists and foreign -> skip with warning
1194
- ln -s canonicalPath targetPath
1195
- ```
1196
-
1197
- ## 8.5 Update 算法
1198
-
1199
- ```text
1200
- resolve sources to update
1201
- for each source:
1202
- fetch/update snapshot
1203
- rescan skills
1204
- rebuild canonical entries for changed skills only
1205
- recompute deployments for affected channels
1206
- if --apply then apply plans
1207
- commit new lock atomically
1208
- ```
1209
-
1210
- ---
1211
-
1212
- ## 9. TUI 详细交互规范
1213
-
1214
- ## 9.1 页面流转
1215
-
1216
- ```text
1217
- Start
1218
- -> ChannelSelectScreen
1219
- -> SkillTreeScreen
1220
- -> ApplyPreviewScreen
1221
- -> ApplyResultScreen
1222
- -> Exit
1223
- ```
1224
-
1225
- ## 9.2 `ChannelSelectScreen`
1226
-
1227
- ### 展示字段
1228
-
1229
- - channel 名称
1230
- - 是否检测到
1231
- - 目标路径
1232
- - 默认策略
1233
- - 健康状态
1234
-
1235
- ### 操作键
1236
-
1237
- - `↑ / ↓`:移动
1238
- - `Space`:切换选中
1239
- - `a`:全选 / 全不选
1240
- - `Enter`:进入下一屏
1241
- - `Esc`:退出
1242
-
1243
- ## 9.3 `SkillTreeScreen`
1244
-
1245
- ### 展示结构
1246
-
1247
- - 一级:source display root
1248
- - 二级:skill leaf
1249
-
1250
- ### 状态
1251
-
1252
- - `[ ]`:未选
1253
- - `[-]`:部分选中
1254
- - `[x]`:全部选中
1255
-
1256
- ### 操作键
1257
-
1258
- - `↑ / ↓`:移动
1259
- - `Space`:选中/取消
1260
- - `Tab`:展开/收起一级节点
1261
- - `Enter`:进入预览
1262
- - `Backspace`:返回上一屏
1263
-
1264
- ## 9.4 `ApplyPreviewScreen`
1265
-
1266
- ### 展示字段
1267
-
1268
- - channels 数量
1269
- - skills 数量
1270
- - create / replace / remove / skip 计数
1271
- - warnings 列表
1272
- - conflicts 列表
1273
-
1274
- ### 操作键
1275
-
1276
- - `Enter`:确认应用
1277
- - `Backspace`:返回树选择
1278
- - `q`:取消
1279
-
1280
- ---
1281
-
1282
- ## 10. 错误码规范
1283
-
1284
- 错误码统一形式:`SM_<DOMAIN>_<CODE>`
1285
-
1286
- ### 10.1 Source 相关
1287
-
1288
- - `SM_SOURCE_UNSUPPORTED`:无法识别来源
1289
- - `SM_SOURCE_RESOLVE_FAILED`:来源解析失败
1290
- - `SM_SOURCE_FETCH_FAILED`:下载或拉取失败
1291
- - `SM_SOURCE_UPDATE_CONFLICT`:更新过程中发现本地 source 被手工修改
1292
-
1293
- ### 10.2 Scan 相关
1294
-
1295
- - `SM_SCAN_SKILL_MD_MISSING`:未发现合法 `SKILL.md`
1296
- - `SM_SCAN_FRONTMATTER_INVALID`:frontmatter 无法解析
1297
- - `SM_SCAN_NAME_DIR_MISMATCH`:name 与目录名不一致
1298
- - `SM_SCAN_DUPLICATE_SKILL`:同一 source 内发现重名 skill
1299
-
1300
- ### 10.3 Deployment 相关
1301
-
1302
- - `SM_DEPLOY_TARGET_EXISTS_FOREIGN`:目标路径已存在非受管文件
1303
- - `SM_DEPLOY_BROKEN_SYMLINK`:存在断链
1304
- - `SM_DEPLOY_COPY_OUTSIDE_ROOT`:copy 目标越出受允根目录
1305
- - `SM_DEPLOY_STRATEGY_UNSUPPORTED`:channel 不支持该分发策略
1306
-
1307
- ### 10.4 State 相关
1308
-
1309
- - `SM_STATE_SCHEMA_UNKNOWN`:schemaVersion 不识别
1310
- - `SM_STATE_MIGRATION_FAILED`:状态迁移失败
1311
- - `SM_STATE_LOCK_WRITE_FAILED`:lock 原子写入失败
1312
-
1313
- ### 10.5 Doctor 相关
1314
-
1315
- - `SM_DOCTOR_CHANNEL_UNAVAILABLE`:渠道不可用
1316
- - `SM_DOCTOR_REALPATH_RISK`:realpath 风险
1317
- - `SM_DOCTOR_DRIFT_DETECTED`:manifest/lock/磁盘三者漂移
1318
-
1319
- ---
1320
-
1321
- ## 11. 日志与可观测性
1322
-
1323
- ### 11.1 控制台日志级别
1324
-
1325
- - `info`
1326
- - `warn`
1327
- - `error`
1328
- - `debug`
1329
-
1330
- ### 11.2 日志文件
1331
-
1332
- 建议:
1333
-
1334
- ```text
1335
- ~/.skillflow/logs/
1336
- current.log
1337
- previous.log
1338
- ```
1339
-
1340
- ### 11.3 审计事件
1341
-
1342
- `history.ndjson` 必须可回答这些问题:
1343
-
1344
- - 某个 source 何时被添加
1345
- - 某个 skill 何时被应用到某个 channel
1346
- - 某次 update 改了哪些 snapshot
1347
- - 某次 doctor 发现了什么问题
1348
-
1349
- ---
1350
-
1351
- ## 12. 安全与防御式实现要求
1352
-
1353
- 1. **默认不执行第三方脚本**
1354
- 2. **所有路径操作先做 `realpath` 校验**
1355
- 3. **受管 symlink 通过 sidecar 元数据或 lock 映射识别**
1356
- 4. **删除操作只删除受管目标**
1357
- 5. **copy 部署使用临时目录,完成后 rename 提交**
1358
- 6. **风险 flag 在 UI 和 JSON 输出中都必须可见**
1359
- 7. **外部 CLI bridge(如 ClawHub)必须收集 exit code、stdout、stderr**
1360
-
1361
- ---
1362
-
1363
- ## 13. 测试计划
1364
-
1365
- ## 13.1 单元测试
1366
-
1367
- 覆盖:
1368
-
1369
- - source parser
1370
- - id normalizer
1371
- - frontmatter parser
1372
- - manifest/lock validator
1373
- - planner diff 逻辑
1374
- - 错误码映射
1375
-
1376
- ## 13.2 集成测试
1377
-
1378
- ### 用例 A:Git 单仓多 skill
1379
-
1380
- 1. add git repo
1381
- 2. scan 出 3 个 leaf
1382
- 3. config 到 Claude + Codex
1383
- 4. 验证 symlink 数量与 lock deployments
1384
-
1385
- ### 用例 B:OpenClaw copy
1386
-
1387
- 1. 检测 workspace
1388
- 2. apply 到 openclaw
1389
- 3. 验证复制后的 skill realpath 在 workspace root 内
1390
-
1391
- ### 用例 C:更新后重投影
1392
-
1393
- 1. 初始安装 skill A
1394
- 2. 上游变更 skill A 内容
1395
- 3. update --apply
1396
- 4. lock 中 hash 更新,deployment 状态回到 `applied`
1397
-
1398
- ### 用例 D:foreign-existing
1399
-
1400
- 1. 在目标目录预先创建同名非受管文件夹
1401
- 2. apply
1402
- 3. 返回 `SM_DEPLOY_TARGET_EXISTS_FOREIGN`
1403
-
1404
- ### 用例 E:卸载
1405
-
1406
- 1. 安装 source X
1407
- 2. 投影到多个 channel
1408
- 3. uninstall X
1409
- 4. 验证 source、canonical、deployments 被清理
1410
-
1411
- ## 13.3 E2E 测试
1412
-
1413
- - 在临时 HOME 下运行完整 CLI
1414
- - 验证 state 文件与磁盘结构一致
1415
- - 验证 JSON 模式输出可供脚本消费
1416
-
1417
- ---
1418
-
1419
- ## 14. 发布流程建议
1420
-
1421
- ## 14.1 首发发布
1422
-
1423
- - npm package:`skill-flow`
1424
- - 可执行入口:`bin/skill-flow`
1425
- - README 包含 quickstart 与 channel caveats
1426
-
1427
- ## 14.2 CI 流程
1428
-
1429
- - install
1430
- - lint
1431
- - test
1432
- - build
1433
- - package smoke test
1434
- - draft release
1435
-
1436
- ## 14.3 P1 发布补充
1437
-
1438
- - Homebrew tap
1439
- - shell completion
1440
- - upgrade notice
1441
-
1442
- ---
1443
-
1444
- ## 15. 首个 Sprint 建议拆解
1445
-
1446
- ### Sprint 1(基础骨架)
1447
-
1448
- - 初始化 oclif + TypeScript + pnpm + Vitest
1449
- - 建立 domain model
1450
- - state 文件读写与 schema 验证
1451
- - Git adapter 最小实现
1452
-
1453
- ### Sprint 2(扫描与列表)
1454
-
1455
- - scanner
1456
- - parser
1457
- - list
1458
- - canonical skill 构建
1459
-
1460
- ### Sprint 3(分发与 TUI)
1461
-
1462
- - Channel adapters
1463
- - planner / applier
1464
- - config TUI
1465
- - doctor 初版
1466
-
1467
- ### Sprint 4(更新与卸载)
1468
-
1469
- - update
1470
- - uninstall
1471
- - drift detection
1472
- - e2e 测试
1473
-
1474
- ### Sprint 5(ClawHub 与打磨)
1475
-
1476
- - ClawHub adapter
1477
- - JSON 输出模式
1478
- - 文档与发布流程
1479
-
1480
- ---
1481
-
1482
- ## 16. 最终实施结论
1483
-
1484
- 这份文档的最终工程结论如下:
1485
-
1486
- 1. **先做全局级 manager,再做项目级 manager**。
1487
- 2. **先做 Git + ClawHub 两类 source,再做 registry discovery**。
1488
- 3. **先做 per-channel strategy 自动化,再开放高级 override**。
1489
- 4. **坚持 manifest/lock 双层状态,不做无状态运行**。
1490
- 5. **坚持 OpenClaw 默认 copy,其他主渠道默认 symlink**。
1491
- 6. **坚持状态原子写入、部署 staged apply、删除只删受管内容**。
1492
- 7. **坚持 TUI 作为主配置界面,而不是靠长 flag 拼装体验**。
1493
-
1494
- 这已经足够作为研发启动、任务拆解和首轮工程评审的直接输入文档。