feat: rename skills/skiff to pouch and move ACK state under .pouch

Use ~/.pouch, the pouch CLI, and .pouch.yaml as the SSOT container.
Keep the inner skills/ packages, and store ACK project state in
.pouch/ack instead of docs/ack.
This commit is contained in:
2026-08-25 15:20:02 +08:00
parent ee31278947
commit f3cd56b78e
83 changed files with 1265 additions and 1192 deletions
+22 -22
View File
@@ -9,7 +9,7 @@ ACK 是一个显式调用的 Agent Skill,用三种独立角色运行工程协
关键约束是验证者不等于实现者。每个任务最多修复三轮,仍未通过时记录为
`leftover`,然后继续处理其它任务。
项目还可以在同一份 `docs/ack/delivery.yaml` 里声明测试环境部署和版本发布。
项目还可以在同一份 `.pouch/ack/delivery.yaml` 里声明测试环境部署和版本发布。
用户告诉 ACK 这两件事怎么做之后,再说「重新布测试环境」或「发布一个版本」,
ACK 按对应 intent 执行。任务全部验证后仍可按 profile 做常规交付。配置默认关闭,
稳定发布与生产部署始终保留人工批准点。
@@ -19,13 +19,13 @@ ACK 按对应 intent 执行。任务全部验证后仍可按 profile 做常规
全局安装:
```bash
skiff add ack -g
pouch add ack -g
```
或只安装到当前项目:
```bash
skiff add ack
pouch add ack
```
ACK 只在用户显式调用 `/ack` 或 `$ack` 时运行。
@@ -33,14 +33,14 @@ ACK 只在用户显式调用 `/ack` 或 `$ack` 时运行。
## 初始化项目
```bash
skiff init ack
skiff init ack --project ~/code/my-app
pouch init ack
pouch init ack --project ~/code/my-app
```
初始化后,项目只保存自己的 ACK 状态:
```text
docs/ack/
.pouch/ack/
├── project.md
├── tasks.yaml
├── knowledge.yaml
@@ -50,7 +50,7 @@ docs/ack/
不会在项目中复制或链接 ACK Skill。通用规范、模板和脚本始终从已安装的 Skill
目录读取。
ACK 从当前命令指定的 `--project-root/docs/ack/` 定位项目状态,不要求在
ACK 从当前命令指定的 `--project-root/.pouch/ack/` 定位项目状态,不要求在
`tasks.yaml` 中持久化 `repoPath` 或 `devWorktree`。自动 worker 的实际工作目录由
`--worktree` 指定;默认在 `--project-root` 工作,v0.19 起不再配置 `allowedWorktrees` 白名单。
@@ -68,10 +68,10 @@ skills/ack/
```
`SKILL.md` 是 Agent 的工作流入口。`references/` 是按需读取的稳定规范;
`docs/ack/project.md` 只保存当前项目的命令、路径和权限差异;
`docs/ack/tasks.yaml` 保存当前任务状态;`docs/ack/knowledge.yaml` 保存跨任务复用、
`.pouch/ack/project.md` 只保存当前项目的命令、路径和权限差异;
`.pouch/ack/tasks.yaml` 保存当前任务状态;`.pouch/ack/knowledge.yaml` 保存跨任务复用、
已经独立验证的项目知识护栏。
`docs/ack/delivery.yaml` 是测试环境部署和版本发布的唯一契约,也声明常规构建、
`.pouch/ack/delivery.yaml` 是测试环境部署和版本发布的唯一契约,也声明常规构建、
发布和部署能力;每次执行结果另记在 `tasks.yaml.deliveryRuns`。
## 检查项目状态
@@ -79,21 +79,21 @@ skills/ack/
Agent 会从当前 ACK Skill 目录解析校验脚本:
```bash
python3 <ack-skill-dir>/scripts/validate_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py docs/ack/knowledge.yaml \
--tasks docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_delivery.py docs/ack/delivery.yaml \
--tasks docs/ack/tasks.yaml --project-root <project-root>
python3 <ack-skill-dir>/scripts/validate_tasks.py .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py .pouch/ack/knowledge.yaml \
--tasks .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_delivery.py .pouch/ack/delivery.yaml \
--tasks .pouch/ack/tasks.yaml --project-root <project-root>
```
Coordinator 可以按当前任务上下文做确定性推荐:
```bash
python3 <ack-skill-dir>/scripts/select_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/select_tasks.py docs/ack/tasks.yaml \
python3 <ack-skill-dir>/scripts/select_tasks.py .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/select_tasks.py .pouch/ack/tasks.yaml \
--task-id BUG-001
python3 <ack-skill-dir>/scripts/select_knowledge.py docs/ack/knowledge.yaml \
python3 <ack-skill-dir>/scripts/select_knowledge.py .pouch/ack/knowledge.yaml \
--component web --path web/app.py --tag long-running-service --limit 10
```
@@ -110,7 +110,7 @@ run。默认最多 20 条,超过预算时显式失败;Agent 不应回退为
```bash
python3 <ack-skill-dir>/scripts/run_verification.py \
docs/ack/knowledge.yaml check-api-contract --project-root <project-root>
.pouch/ack/knowledge.yaml check-api-contract --project-root <project-root>
```
该入口会在执行前重新校验知识库,只打开一次项目根目录 fd,再从同一个 fd 逐段以
@@ -118,7 +118,7 @@ python3 <ack-skill-dir>/scripts/run_verification.py \
快照,再以结构化 argv 和 `shell=False` 启动。它不接受临时命令或额外参数。
选择器输出的 path/args 只用于审阅,不应由 Agent 自行拼接执行。Runner 只读取
项目内无 symlink 的权威
`docs/ack/knowledge.yaml`,不接受替代知识文件或放宽后的项目根。检查进程的 cwd
`.pouch/ack/knowledge.yaml`,不接受替代知识文件或放宽后的项目根。检查进程的 cwd
和 `ACK_PROJECT_ROOT` 都固定到该根 fd;后者是只在检查进程存活期间有效的
`/proc/self/fd/...` 或 `/dev/fd/...` 路径。原始可读路径另放在
`ACK_PROJECT_ROOT_DISPLAY`,只能用于日志,不能用于资源访问。Runner 还提供
@@ -132,7 +132,7 @@ python3 <ack-skill-dir>/scripts/run_verification.py \
旧项目只有 `project.md` 和 `tasks.yaml` 时,不要重跑初始化。由 `/ack` 检查现有
状态,获得用户授权后补一个空的 `knowledge.yaml`;如果任务板尚未声明知识库,
同时只补 `project.knowledgeFile: docs/ack/knowledge.yaml`,再运行跨文件校验。
同时只补 `project.knowledgeFile: .pouch/ack/knowledge.yaml`,再运行跨文件校验。
只有 Coordinator 写 `tasks.yaml` 和 `knowledge.yaml`。知识正文不能作为自由 shell
执行;关键约束应继续下沉到测试、lint、CI 或正式规范。ACK 不自动修改项目的
@@ -147,7 +147,7 @@ python3 <ack-skill-dir>/scripts/run_verification.py \
发版方式以后再告诉你。
```
ACK 把它维护成 `docs/ack/delivery.yaml` 的 `intents.testEnvironment` /
ACK 把它维护成 `.pouch/ack/delivery.yaml` 的 `intents.testEnvironment` /
`intents.release`、entrypoint、artifact、environment 和 profile。首次配置保持
关闭,确认后才启用。之后用户可以说:
+37 -37
View File
@@ -2,14 +2,14 @@
name: ack
description: >-
初始化、检查并运行 ACK 三角色协作闭环。仅在用户显式调用 /ack 或 $ack,并要求
初始化 ACK、检查 docs/ack 配置、按 ACK 规划需求、指挥 Coordinator/Developer/Test
初始化 ACK、检查 .pouch/ack 配置、按 ACK 规划需求、指挥 Coordinator/Developer/Test
工作,配置测试环境与发版方式,重新部署测试环境,或发布版本时使用。
---
# ACK 项目协作入口
本 Skill 是 ACK 的完整能力包:`references/` 保存通用规范,`templates/` 保存项目
状态模板,`scripts/` 保存校验工具。目标项目只在 `docs/ack/` 保存 `project.md`、
状态模板,`scripts/` 保存校验工具。目标项目只在 `.pouch/ack/` 保存 `project.md`、
`tasks.yaml`、`knowledge.yaml` 和默认关闭的 `delivery.yaml`,不要复制或链接 Skill
内容。
@@ -23,7 +23,7 @@ description: >-
- 用户要求用 ACK 做需求、修复问题或继续任务:执行“工作”。
- 用户用自然语言说明怎么部署测试环境、怎么发布版本,或要求增加、修改、关闭交付
流程:执行“交付配置维护”。测试环境和发版必须写进同一份
`docs/ack/delivery.yaml`。
`.pouch/ack/delivery.yaml`。
- 用户要求部署、重新部署测试环境,或按已配置方式开始测试:执行“运行测试环境”。
- 用户要求发布版本:执行“运行版本发布”。
@@ -33,48 +33,48 @@ description: >-
## 初始化
1. 确认 `skiff` 可执行,并检查 `<project>/docs/ack` 是否存在。
1. 确认 `pouch` 可执行,并检查 `<project>/.pouch/ack` 是否存在。
2. 不存在时执行:
```bash
skiff init ack --project <project-root>
pouch init ack --project <project-root>
```
该命令从本 Skill 的 `templates/` 生成项目状态,不会在项目中创建 Skill
软链接或资源副本。
3. 如果 `docs/ack` 已存在,不重复初始化、不覆盖文件;转入“检查”。旧项目只有
3. 如果 `.pouch/ack` 已存在,不重复初始化、不覆盖文件;转入“检查”。旧项目只有
`project.md` 与 `tasks.yaml` 时,先报告缺少 `knowledge.yaml`。用户授权后,
从 `templates/knowledge.template.yaml` 生成这个缺失文件并替换项目名和时间;若
`tasks.yaml` 尚无 `project.knowledgeFile`,同时只补
`docs/ack/knowledge.yaml` 这一项。不要重跑 `skiff init`,也不要改写其它已有
`.pouch/ack/knowledge.yaml` 这一项。不要重跑 `pouch init`,也不要改写其它已有
项目状态。
4. 读取项目的公开配置和文档,例如 README、语言清单、包管理清单、测试配置与
CI,确定项目名、技术栈、源码/规格/测试路径及真实可执行命令。
5. 完善 `docs/ack/project.md`:
5. 完善 `.pouch/ack/project.md`:
- 用实际项目值替换全部占位符。
- 无服务地址时把 Base URL 写为 `n/a`,不要虚构端口。
- 无法从项目证据确定的命令写为 `n/a`,并在结果中列为待配置项。
- 只写项目差异,不复制 `references/` 中的通用规范。
6. 完善 `docs/ack/tasks.yaml` 的项目信息。纯初始化且用户没有提供真实任务时,
6. 完善 `.pouch/ack/tasks.yaml` 的项目信息。纯初始化且用户没有提供真实任务时,
删除模板示例任务并保留 `tasks: []`;不要虚构需求或缺陷。
项目状态固定从当前项目根的 `docs/ack/` 推导,不写入 `repoPath` 或 `devWorktree`;
项目状态固定从当前项目根的 `.pouch/ack/` 推导,不写入 `repoPath` 或 `devWorktree`;
worker 默认在 `--project-root`(权威状态目录)工作,不再配置
`allowedWorktrees` 白名单(v0.19 起废弃);需要隔离 worktree 时由 Coordinator 在
派发时显式指定。旧任务板中的 `repoPath`、`devWorktree` 仅兼容读取。
7. 检查 `docs/ack/knowledge.yaml`。新项目没有已验证的项目经验时保留
7. 检查 `.pouch/ack/knowledge.yaml`。新项目没有已验证的项目经验时保留
`verificationRegistry: {}` 与 `entries: []`,不从聊天、README 或单次失败中
猜测并激活知识。
8. 检查 `docs/ack/delivery.yaml`。新项目保留 `enabled: false`、空能力表和空 profile;
8. 检查 `.pouch/ack/delivery.yaml`。新项目保留 `enabled: false`、空能力表和空 profile;
不从 README 或 CI 猜测、启用交付。旧项目没有该文件时仍可继续使用原 ACK
闭环;只有用户明确要求配置交付时,才按“交付配置维护”补齐。
9. 更新 `updatedAt`,并运行:
```bash
python3 <ack-skill-dir>/scripts/validate_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py docs/ack/knowledge.yaml \
--tasks docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_delivery.py docs/ack/delivery.yaml \
--tasks docs/ack/tasks.yaml --project-root <project-root>
python3 <ack-skill-dir>/scripts/validate_tasks.py .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py .pouch/ack/knowledge.yaml \
--tasks .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_delivery.py .pouch/ack/delivery.yaml \
--tasks .pouch/ack/tasks.yaml --project-root <project-root>
```
10. 检查 `project.md`、`tasks.yaml`、`knowledge.yaml` 与 `delivery.yaml` 是否仍有
@@ -87,10 +87,10 @@ description: >-
## 检查
1. 检查以下路径:
- `docs/ack/project.md`
- `docs/ack/tasks.yaml`
- `docs/ack/knowledge.yaml`
- `docs/ack/delivery.yaml`(旧项目可无;存在或被任务板引用时必须校验)
- `.pouch/ack/project.md`
- `.pouch/ack/tasks.yaml`
- `.pouch/ack/knowledge.yaml`
- `.pouch/ack/delivery.yaml`(旧项目可无;存在或被任务板引用时必须校验)
需要查看任务内容时,使用 `<ack-skill-dir>/scripts/select_tasks.py` 解析完整任务板并
只输出项目配置、摘要和可工作任务;不要用 `cat`、整文件 `sed` 或等价方式把完整
`tasks.yaml` 注入上下文。完整性仍由校验器检查。
@@ -101,14 +101,14 @@ description: >-
3. 查找未替换占位符,并核对项目根、覆盖层路径、Developer 白盒命令、Test
黑盒命令和 Base URL。
4. 使用 `<ack-skill-dir>/scripts/validate_tasks.py` 校验任务板,使用
`<ack-skill-dir>/scripts/validate_knowledge.py docs/ack/knowledge.yaml --tasks
docs/ack/tasks.yaml` 校验项目知识和跨文件引用。如果存在交付配置或任务板声明了
`<ack-skill-dir>/scripts/validate_knowledge.py .pouch/ack/knowledge.yaml --tasks
.pouch/ack/tasks.yaml` 校验项目知识和跨文件引用。如果存在交付配置或任务板声明了
`project.deliveryFile`,再使用 `<ack-skill-dir>/scripts/validate_delivery.py
docs/ack/delivery.yaml --tasks docs/ack/tasks.yaml --project-root <project-root>`
.pouch/ack/delivery.yaml --tasks .pouch/ack/tasks.yaml --project-root <project-root>`
校验交付能力、顺序、安全边界和跨文件引用。只报告证据明确的问题,不因旧项目
缺少可选交付配置而宣称失败。
5. 若存在 `project.bugIntake`,运行
`python3 <ack-skill-dir>/scripts/feishu_bug_intake.py check docs/ack/tasks.yaml`。
`python3 <ack-skill-dir>/scripts/feishu_bug_intake.py check .pouch/ack/tasks.yaml`。
它只接受 `feishu-base` 和显式 profile;详细的飞书配置、凭据初始化和读取方式见
`references/feishu-bug-intake.md`。
6. 检查知识引用能解析到固定 revision,candidate 仍留在任务证据中,且
@@ -122,16 +122,16 @@ description: >-
## 工作
1. 若 `docs/ack` 不存在,停止并建议先用 `/ack` 初始化;不要静默初始化。
1. 若 `.pouch/ack` 不存在,停止并建议先用 `/ack` 初始化;不要静默初始化。
2. 依次读取:
- `docs/ack/project.md`
- 运行 `python3 <ack-skill-dir>/scripts/select_tasks.py docs/ack/tasks.yaml`,只读取
- `.pouch/ack/project.md`
- 运行 `python3 <ack-skill-dir>/scripts/select_tasks.py .pouch/ack/tasks.yaml`,只读取
`project`、`summary` 和默认可工作状态的任务;已知当前任务时传
`--task-id <ack-task-id>`。选择器会解析并校验完整任务板,并只附带选中任务引用的
receipt 与 delivery run。命中超过默认预算时用 `--task-id` / `--status` 缩小,
不直接回退为输出完整 `tasks.yaml`。
- 通过 `<ack-skill-dir>/scripts/select_knowledge.py` 从
`docs/ack/knowledge.yaml` 选择的当前任务相关 `active` 条目
`.pouch/ack/knowledge.yaml` 选择的当前任务相关 `active` 条目
- `<ack-skill-dir>/references/kickoff.md`
- kickoff 指定且与当前任务相关的 references 文件
- 若 `tasks.yaml.project.deliveryFile` 存在,再读取该 `delivery.yaml` 和
@@ -183,7 +183,7 @@ description: >-
`knowledgeCandidates`,Test 回报 `knowledgeChecks`;`candidate` 只有在独立验证和
gate 后才能由 Coordinator 写入或激活。
7. 执行知识项的 `verification.ref` 时,只调用
`<ack-skill-dir>/scripts/run_verification.py docs/ack/knowledge.yaml
`<ack-skill-dir>/scripts/run_verification.py .pouch/ack/knowledge.yaml
<verification-ref> --project-root <project-root>`。不要直接执行选择器返回的 path/args,
也不要给 runner 注入额外命令或参数。
8. 不把 `worker_done` 或 Test 自报成功直接当作完成。三轮预算只计算 Test 已对齐正确
@@ -216,8 +216,8 @@ description: >-
destination、environment 与 profile。测试环境部署和版本发布都写进这一份
`delivery.yaml`,不要拆成第二份文档。配置只引用仓库内脚本或声明式工具 target,
不保存 shell。
2. 若旧项目首次启用,生成 `docs/ack/delivery.yaml`,在 `tasks.yaml.project` 增加
`deliveryFile: docs/ack/delivery.yaml`,并增加顶层 `deliveryRuns: []`;不改写其它
2. 若旧项目首次启用,生成 `.pouch/ack/delivery.yaml`,在 `tasks.yaml.project` 增加
`deliveryFile: .pouch/ack/delivery.yaml`,并增加顶层 `deliveryRuns: []`;不改写其它
项目状态。首次生成保持 `enabled: false`,先展示 diff 和解析出的执行顺序。
3. 运行 delivery、tasks 和跨文件校验;需要的脚本不存在、不可执行、引用不完整或
涉及凭据正文时 fail closed。凭据只写 secret 名称,值由外部环境提供。
@@ -227,7 +227,7 @@ description: >-
## 运行测试环境
1. 读取 `docs/ack/delivery.yaml` 与 `references/delivery.md`。
1. 读取 `.pouch/ack/delivery.yaml` 与 `references/delivery.md`。
2. `enabled` 不为 true,或 `intents.testEnvironment` 为 null:停止,请用户说明如何
部署测试环境,转入交付配置维护。不猜测编译或启动命令。
3. 不要求任务已 `verified`。按该 profile 执行 build → deploy → health-check。
@@ -237,7 +237,7 @@ description: >-
## 运行版本发布
1. 读取同一份 `docs/ack/delivery.yaml` 与 `references/delivery.md`。
1. 读取同一份 `.pouch/ack/delivery.yaml` 与 `references/delivery.md`。
2. `enabled` 不为 true,或 `intents.release` 为 null:停止,请用户说明如何发版,
写入同一文件后再执行。
3. 按该 profile 顺序执行。stable 发布和生产部署的 `approval` 不能用口头「发版」
@@ -262,7 +262,7 @@ description: >-
没有可信空闲状态、配置匹配和历史消息清理证明时不复用既有 worker。
- launcher 返回 `indeterminate` 或 `reconcile required` 时,不直接重试;先按
launch ID、外部 record 和 Orca live state 完成人工核对。
- 不覆盖已有 `docs/ack` 文件;除用户确认的 ACK 任务或 delivery profile 外,不擅自
- 不覆盖已有 `.pouch/ack` 文件;除用户确认的 ACK 任务或 delivery profile 外,不擅自
提交、推送、创建终端、新 worktree、发布产物或部署。
- 只有 Coordinator 写 `tasks.yaml`、`knowledge.yaml` 和 `deliveryRuns`;Developer
与 Test 只读,只能通过回报提名或验证知识。`delivery.yaml` 只在显式的交付配置
@@ -271,6 +271,6 @@ description: >-
按 registry ID 执行。不自动修改 `AGENTS.md`、`CLAUDE.md` 或其它 Agent 指令文件。
- 不把完整 `tasks.yaml` 注入上下文;使用 `select_tasks.py` 获取有预算的项目与任务
视图,写回前仍运行完整任务板校验。
- 项目只保存 `docs/ack/project.md`、`docs/ack/tasks.yaml`、
`docs/ack/knowledge.yaml` 和可选的 `docs/ack/delivery.yaml`;通用资源始终从当前
- 项目只保存 `.pouch/ack/project.md`、`.pouch/ack/tasks.yaml`、
`.pouch/ack/knowledge.yaml` 和可选的 `.pouch/ack/delivery.yaml`;通用资源始终从当前
ACK Skill 目录读取。
+1 -1
View File
@@ -1 +1 @@
0.18.0
0.19.0
+8 -8
View File
@@ -1,10 +1,10 @@
# notes-web Agent 协作协议(示例,项目覆盖层)
> 本项目基于 ack v0.18.0。
> 本项目基于 ack v0.19.0。
> 通用规范由 `/ack` 从 Skill 自身的 `references/` 读取,本文件只填项目差异。
> 覆盖层文件放在 `docs/ack/project.md`,不占用 `AGENTS.md`。
> 覆盖层文件放在 `.pouch/ack/project.md`,不占用 `AGENTS.md`。
> ACK 不会自动修改 `AGENTS.md`、`CLAUDE.md` 或其它 Agent 指令文件。
> `docs/ack/` 只保存 `project.md`、`tasks.yaml`、`knowledge.yaml` 与 `delivery.yaml`。
> `.pouch/ack/` 只保存 `project.md`、`tasks.yaml`、`knowledge.yaml` 与 `delivery.yaml`。
## 项目概览
@@ -12,10 +12,10 @@
- 技术栈:`TypeScript + React (Vite) + Go`
- 运行命令:`npm run dev`(前端)、`go run ./server`(后端)
- Base URL:`http://localhost:5173`
- 任务板:`docs/ack/tasks.yaml`
- 项目知识:`docs/ack/knowledge.yaml`
- 交付契约:`docs/ack/delivery.yaml`
- 覆盖层文件:`docs/ack/project.md`
- 任务板:`.pouch/ack/tasks.yaml`
- 项目知识:`.pouch/ack/knowledge.yaml`
- 交付契约:`.pouch/ack/delivery.yaml`
- 覆盖层文件:`.pouch/ack/project.md`
## 稳定规范(引用,不重复)
@@ -30,7 +30,7 @@
## Worker 路由
结构化配置位于 `docs/ack/tasks.yaml` 的 `project.orchestration`,启动记录位于顶层
结构化配置位于 `.pouch/ack/tasks.yaml` 的 `project.orchestration`,启动记录位于顶层
`workerReceipts`。本项目默认使用:
| 角色 | profile ID | 档位 |
+4 -4
View File
@@ -3,13 +3,13 @@
version: 1
updatedAt: "2026-07-06T09:40:00+08:00"
source: "Coordinator (PM) Agent"
ackVersion: "0.18.0"
ackVersion: "0.19.0"
project:
name: "notes-web"
baseUrl: "http://localhost:5173"
overlayFile: "docs/ack/project.md"
knowledgeFile: "docs/ack/knowledge.yaml"
deliveryFile: "docs/ack/delivery.yaml"
overlayFile: ".pouch/ack/project.md"
knowledgeFile: ".pouch/ack/knowledge.yaml"
deliveryFile: ".pouch/ack/delivery.yaml"
orchestration:
profileVersion: 1
mode: "manual"
+7 -7
View File
@@ -3,8 +3,8 @@
## 安装与初始化
- [ ] ACK Skill 已全局安装或安装到当前项目。
- [ ] 已运行 `skiff init ack --project <project-root>`。
- [ ] `docs/ack/` 只包含项目自己的 `project.md`、`tasks.yaml`、`knowledge.yaml` 与
- [ ] 已运行 `pouch init ack --project <project-root>`。
- [ ] `.pouch/ack/` 只包含项目自己的 `project.md`、`tasks.yaml`、`knowledge.yaml` 与
默认关闭的 `delivery.yaml`。
- [ ] 旧项目缺少 `knowledge.yaml` 时,只补空文件及缺失的
`project.knowledgeFile` 指针,没有重跑初始化或覆盖其它项目状态。
@@ -16,8 +16,8 @@
- [ ] `project.md` 只保存项目差异,不复制 Skill 的通用规范。
- [ ] `tasks.yaml` 的 `project.overlayFile` 指向实际覆盖层。
- [ ] `tasks.yaml` 的 `project.knowledgeFile` 固定为
`docs/ack/knowledge.yaml`。
- [ ] 新项目的 `project.deliveryFile` 固定为 `docs/ack/delivery.yaml`,顶层有
`.pouch/ack/knowledge.yaml`。
- [ ] 新项目的 `project.deliveryFile` 固定为 `.pouch/ack/delivery.yaml`,顶层有
`deliveryRuns: []`;旧项目未采用交付能力时可无这两项。
- [ ] 技术栈、运行、构建、单测和集成测试命令均来自项目证据。
- [ ] Coordinator、Developer、Test 的模型档位和升级规则已明确。
@@ -26,7 +26,7 @@
- [ ] `allowedWorktrees` 已废弃(v0.19 起),新任务板不配置;worker 默认在
`--project-root` 工作,其它 worktree 由 launcher 按同 git 仓库且已注册约束放行。
- [ ] `tasks.yaml` 不需要保存 `repoPath` 或 `devWorktree`;项目状态从当前
`--project-root/docs/ack/` 推导,worker 路径由 `--worktree` 显式指定。
`--project-root/.pouch/ack/` 推导,worker 路径由 `--worktree` 显式指定。
## 路径权限
@@ -110,6 +110,6 @@
blocked/failed/leftover、未完成任务或未解决环境事件的终端保留且不设 TTL。
首次接入建议选择一个低风险问题跑完整闭环。项目差异写回
`docs/ack/project.md`;通用问题回流到 ACK Skill 的 `references/`、`templates/`
`.pouch/ack/project.md`;通用问题回流到 ACK Skill 的 `references/`、`templates/`
或 `scripts/`,并更新 `VERSION`。项目特有、跨任务复用且已经验证的经验才写入
`docs/ack/knowledge.yaml`。
`.pouch/ack/knowledge.yaml`。
+4 -4
View File
@@ -2,8 +2,8 @@
本文件定义可选的 `verified -> validation_ready/review_ready/released` 交付阶段。开发、独立复测和
Coordinator 终检仍由 ACK 原有闭环负责;只有选中的任务全部 `verified` 后才能进入
交付。项目配置位于 `docs/ack/delivery.yaml`,运行证据写入
`docs/ack/tasks.yaml.deliveryRuns`。
交付。项目配置位于 `.pouch/ack/delivery.yaml`,运行证据写入
`.pouch/ack/tasks.yaml.deliveryRuns`。
## 1. 配置与授权不是一回事
@@ -54,7 +54,7 @@ channel、environment 或 source revision 漂移时重新确认。
## 3.1 测试环境与发版写在同一份契约
`docs/ack/delivery.yaml` 是测试环境部署和版本发布的唯一文档。不要另写操作手册,
`.pouch/ack/delivery.yaml` 是测试环境部署和版本发布的唯一文档。不要另写操作手册,
也不要把其中一项写进 `project.md`。用户用自然语言说明「怎么布测试环境」或
「怎么发版」时,Coordinator 把两者都维护进这份文件的 `intents`、entrypoint、
artifact、environment 和 profile。
@@ -85,7 +85,7 @@ intents:
```bash
python3 <ack-skill-dir>/scripts/validate_delivery.py \
docs/ack/delivery.yaml --tasks docs/ack/tasks.yaml \
.pouch/ack/delivery.yaml --tasks .pouch/ack/tasks.yaml \
--project-root <project-root>
```
+9 -9
View File
@@ -9,7 +9,7 @@
## 项目配置与 Base 结构
`docs/ack/tasks.yaml` 的 `project.bugIntake` 必须声明 `provider: feishu-base`、
`.pouch/ack/tasks.yaml` 的 `project.bugIntake` 必须声明 `provider: feishu-base`、
`workflow: clarified-writeback-v1`、显式 `profile`、`baseToken`、`tableId`、`viewId` 和字段映射:
```yaml
@@ -34,8 +34,8 @@ fields:
调整当前 view 的可见字段,不删除旧列:
```bash
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py schema-plan docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py schema-apply docs/ack/tasks.yaml \
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py schema-plan .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py schema-apply .pouch/ack/tasks.yaml \
--expected-schema-fingerprint <schemaFingerprint>
```
@@ -68,11 +68,11 @@ locale;调用者环境中的凭据和运行时注入变量不会传入。不
## 读取与整理
```bash
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py check docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py check .pouch/ack/tasks.yaml
tmpdir=$(mktemp -d)
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py fetch docs/ack/tasks.yaml \
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py fetch .pouch/ack/tasks.yaml \
--output-dir "$tmpdir"
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py plan docs/ack/tasks.yaml \
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py plan .pouch/ack/tasks.yaml \
--output-dir "$tmpdir"
```
@@ -101,7 +101,7 @@ Coordinator 对每条 Bug:
```bash
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py write-draft \
docs/ack/tasks.yaml --record-id <record-id> \
.pouch/ack/tasks.yaml --record-id <record-id> \
--expected-source-ref <sourceRef> \
--expected-draft-revision <draftRevision> --input <draft.json>
```
@@ -120,7 +120,7 @@ python3 <ack-skill-dir>/scripts/feishu_bug_intake.py write-draft \
```bash
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py import-approved \
docs/ack/tasks.yaml --record-id <record-id> \
.pouch/ack/tasks.yaml --record-id <record-id> \
--expected-source-ref <approved-sourceRef> \
--expected-draft-revision <approvedDraftRevision>
```
@@ -135,7 +135,7 @@ python3 <ack-skill-dir>/scripts/feishu_bug_intake.py import-approved \
```bash
python3 <ack-skill-dir>/scripts/feishu_bug_intake.py mark-imported \
docs/ack/tasks.yaml --record-id <record-id> --task-id <ack-task-id> \
.pouch/ack/tasks.yaml --record-id <record-id> --task-id <ack-task-id> \
--expected-source-ref <approved-sourceRef> \
--expected-draft-revision <approvedDraftRevision>
```
+23 -23
View File
@@ -9,10 +9,10 @@
1. 目标项目根目录。
2. ACK Skill 已全局安装或安装到当前项目。
3. `skiff` 命令可用。
3. `pouch` 命令可用。
不要覆盖已有的 `docs/ack/project.md`、`docs/ack/tasks.yaml`、
`docs/ack/knowledge.yaml`、`docs/ack/delivery.yaml`、`AGENTS.md` 或其它 Agent
不要覆盖已有的 `.pouch/ack/project.md`、`.pouch/ack/tasks.yaml`、
`.pouch/ack/knowledge.yaml`、`.pouch/ack/delivery.yaml`、`AGENTS.md` 或其它 Agent
指令文件。ACK 不会自动
修改 `AGENTS.md`、`CLAUDE.md` 或其它 Agent 指令文件。不要把 token、`.env`
内容或其它私有配置写入 ACK 项目状态。
@@ -22,19 +22,19 @@
在目标项目执行:
```bash
skiff init ack
pouch init ack
```
或显式指定项目:
```bash
skiff init ack --project <project-root>
pouch init ack --project <project-root>
```
命令从 ACK Skill 自带的 `templates/` 生成:
```text
docs/ack/
.pouch/ack/
├── project.md
├── tasks.yaml
├── knowledge.yaml
@@ -47,24 +47,24 @@ docs/ack/
### 旧项目补充知识库
旧项目已经有 `project.md` 和 `tasks.yaml`、但没有 `knowledge.yaml` 时,不要重跑
`skiff init ack`。先检查现有文件并向用户报告缺失项;用户授权后,只从
`templates/knowledge.template.yaml` 生成 `docs/ack/knowledge.yaml`,替换项目名和
`pouch init ack`。先检查现有文件并向用户报告缺失项;用户授权后,只从
`templates/knowledge.template.yaml` 生成 `.pouch/ack/knowledge.yaml`,替换项目名和
当前时间,保留 `entries: []`。如果现有任务板缺少
`project.knowledgeFile`,同一次授权只补
`knowledgeFile: docs/ack/knowledge.yaml`,不改写其它项目状态。生成后运行任务板、
`knowledgeFile: .pouch/ack/knowledge.yaml`,不改写其它项目状态。生成后运行任务板、
知识库和跨文件引用校验。
### 旧项目补充交付配置
`delivery.yaml` 对旧项目是可选能力;缺少它不会影响三角色开发与验证闭环。只有用户
明确要求配置项目交付时,才从 `templates/delivery.template.yaml` 生成文件,同时在
任务板补 `project.deliveryFile: docs/ack/delivery.yaml` 与顶层
任务板补 `project.deliveryFile: .pouch/ack/delivery.yaml` 与顶层
`deliveryRuns: []`。首次生成保持 `enabled: false`,按 `delivery.md` 展示并确认
解析结果后才启用。不要重跑 `skiff init ack`,也不要改写已有任务或知识。
解析结果后才启用。不要重跑 `pouch init ack`,也不要改写已有任务或知识。
## 完善项目覆盖层
编辑 `docs/ack/project.md`,填入:
编辑 `.pouch/ack/project.md`,填入:
- 项目名、技术栈、运行命令和 Base URL。
- Coordinator、Developer、Test 的实际模型档位。
@@ -76,7 +76,7 @@ docs/ack/
## 完善任务板
编辑 `docs/ack/tasks.yaml`:
编辑 `.pouch/ack/tasks.yaml`:
- `ackVersion` 使用 ACK Skill 的合法 SemVer `VERSION`;从 `0.10.0` 起
`project.orchestration` 与顶层 `workerReceipts` 必须同时存在。
@@ -84,10 +84,10 @@ docs/ack/
自动补交付配置。
- `updatedAt` 使用当前带时区时间。
- `project.name` 使用真实值;`overlayFile` 和 `knowledgeFile` 使用项目内相对路径。
ACK 从命令行 `--project-root` 下固定的 `docs/ack/` 布局解析项目状态,不把
ACK 从命令行 `--project-root` 下固定的 `.pouch/ack/` 布局解析项目状态,不把
`repoPath` 或 `devWorktree` 绝对路径写入任务板。旧任务板中的这两个字段仅兼容读取,
不再参与路径绑定。
- 新项目的 `project.deliveryFile` 固定为 `docs/ack/delivery.yaml`,并保留顶层
- 新项目的 `project.deliveryFile` 固定为 `.pouch/ack/delivery.yaml`,并保留顶层
`deliveryRuns: []`。旧项目只有在采用交付能力时才补这两个字段。
- `allowedWorktrees` 已废弃(v0.19 起),新任务板不生成该字段;worker 默认在
`--project-root` 工作。模型 allowlist、profiles 和 defaults 使用项目实际允许值。
@@ -100,7 +100,7 @@ docs/ack/
## 初始化项目知识
新项目的 `docs/ack/knowledge.yaml` 保持 `verificationRegistry: {}` 与
新项目的 `.pouch/ack/knowledge.yaml` 保持 `verificationRegistry: {}` 与
`entries: []`。不要从聊天、README、issue 或单次失败中猜测并激活知识。
项目运行 ACK 后,Developer 和 Test 可以通过回报提名 `knowledgeCandidates`;
@@ -116,7 +116,7 @@ candidate 留在任务证据中,不会被派发。只有 Test 独立验证且
## 初始化项目交付
新项目的 `docs/ack/delivery.yaml` 保持 `enabled: false`、空能力表、空 profile,以及
新项目的 `.pouch/ack/delivery.yaml` 保持 `enabled: false`、空能力表、空 profile,以及
`intents.testEnvironment: null` 与 `intents.release: null`。
不要根据 README 或 CI 自动推断并启用发布/部署。用户用自然语言说明测试环境或发版
方式后,Coordinator 按 `delivery.md` 把两者都写入这一份契约:`intents` 指向对应
@@ -128,10 +128,10 @@ profile,工具 target 与仓库脚本分开引用。配置中不保存 shell
Agent 从当前 `SKILL.md` 解析 ACK Skill 目录后运行:
```bash
python3 <ack-skill-dir>/scripts/validate_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py docs/ack/knowledge.yaml --tasks docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_delivery.py docs/ack/delivery.yaml \
--tasks docs/ack/tasks.yaml --project-root <project-root>
python3 <ack-skill-dir>/scripts/validate_tasks.py .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py .pouch/ack/knowledge.yaml --tasks .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_delivery.py .pouch/ack/delivery.yaml \
--tasks .pouch/ack/tasks.yaml --project-root <project-root>
```
同时确认:
@@ -139,8 +139,8 @@ python3 <ack-skill-dir>/scripts/validate_delivery.py docs/ack/delivery.yaml \
- `project.md`、`tasks.yaml`、`knowledge.yaml` 和 `delivery.yaml` 没有未替换的
`<...>` 占位符。
- `project.overlayFile` 指向真实文件。
- `project.knowledgeFile` 指向 `docs/ack/knowledge.yaml`。
- 新项目的 `project.deliveryFile` 指向 `docs/ack/delivery.yaml`;交付默认关闭。
- `project.knowledgeFile` 指向 `.pouch/ack/knowledge.yaml`。
- 新项目的 `project.deliveryFile` 指向 `.pouch/ack/delivery.yaml`;交付默认关闭。
- Developer 与 Test 的验证命令可执行。
- `project.orchestration` 的 profile/allowlist/defaults 通过校验,自动模式只允许
`read-only` 或 `workspace-write`;旧任务板未迁移时保持手动模式。
+10 -10
View File
@@ -9,7 +9,7 @@
**你(发起编排的强模型会话)就是 Coordinator (PM) / 产品。** 你负责写文档、拆任务、
编排、终检,**不亲自写代码、不亲自跑测试**。开发和测试是另起的 worker agent;
具体 CLI、模型、reasoning effort 和执行模式的机器事实源是
`docs/ack/tasks.yaml` 的 `project.orchestration`。`docs/ack/project.md` 只解释项目
`.pouch/ack/tasks.yaml` 的 `project.orchestration`。`.pouch/ack/project.md` 只解释项目
差异,不能提供另一套启动命令。
---
@@ -20,9 +20,9 @@
我要做一个新需求:<一句话需求>。
你作为 ack 的 Coordinator(PM),按 ACK Skill 的 references 规范执行:
1. 先读 docs/ack/project.md,并用 `scripts/select_tasks.py docs/ack/tasks.yaml`
1. 先读 .pouch/ack/project.md,并用 `scripts/select_tasks.py .pouch/ack/tasks.yaml`
读取有预算的 project、summary 和可工作任务;已知任务时传 `--task-id`,不要把
完整 tasks.yaml 注入上下文。校验 docs/ack/knowledge.yaml 并用
完整 tasks.yaml 注入上下文。校验 .pouch/ack/knowledge.yaml 并用
`scripts/select_knowledge.py` 只读取当前任务相关的 active 条目,再读
references/roles-and-permissions.md、closed-loop.md、optimization-method.md。
如果 tasks.yaml 声明 project.deliveryFile,再读取 delivery.yaml 与
@@ -30,7 +30,7 @@
2. 写产品文档到 docs/(PRD / 交互 / 验收),把需求拆成任务,每个任务的验收写成可观测信号(可见文本 / API 结果 / 交互结果)。
3. 按任务 scope 从 knowledge.yaml 推荐 active 知识,确认后把固定 revision 的
knowledgeRefs 写入任务;不要派发 candidate 或全量知识库。
4. 把任务写进 docs/ack/tasks.yaml(只有你写),校验 tasks.yaml 和 knowledge.yaml。
4. 把任务写进 .pouch/ack/tasks.yaml(只有你写),校验 tasks.yaml 和 knowledge.yaml。
5. 先把「产品文档 + 任务拆分 + 验收信号 + 适用知识引用」给我确认;若启用了交付,
同时列明本次 profile、目标、停止点与审批步骤。不要急着派发或交付。
6. 我确认后,按 ack 闭环循环:先用 `scripts/launch_worker.py` 校验结构化
@@ -51,15 +51,15 @@
## 第 1 步:Coordinator 产出(确认前)
1. 产品文档 → `docs/PRD-<feature>.md` 等(Coordinator R/W)。
2. 任务板 → `docs/ack/tasks.yaml`,每条任务带 `expected` + `verification`,验收写成可观测信号(见 `optimization-method.md` §1)。
3. 项目知识 → 从 `docs/ack/knowledge.yaml` 按 component、path、dependency、version
2. 任务板 → `.pouch/ack/tasks.yaml`,每条任务带 `expected` + `verification`,验收写成可观测信号(见 `optimization-method.md` §1)。
3. 项目知识 → 从 `.pouch/ack/knowledge.yaml` 按 component、path、dependency、version
和 tag 推荐 `active` 条目,Coordinator 确认后写入固定 revision 的显式
`knowledgeRefs`。candidate 不参与选择。
4. 校验结构与引用:
```bash
python3 <ack-skill-dir>/scripts/validate_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py docs/ack/knowledge.yaml --tasks docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_tasks.py .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/validate_knowledge.py .pouch/ack/knowledge.yaml --tasks .pouch/ack/tasks.yaml
```
`project.orchestration` 是 worker profile 的机器 SSOT;未知字段、非 allowlist 模型、
@@ -68,8 +68,8 @@ python3 <ack-skill-dir>/scripts/validate_knowledge.py docs/ack/knowledge.yaml --
读取任务上下文使用:
```bash
python3 <ack-skill-dir>/scripts/select_tasks.py docs/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/select_tasks.py docs/ack/tasks.yaml \
python3 <ack-skill-dir>/scripts/select_tasks.py .pouch/ack/tasks.yaml
python3 <ack-skill-dir>/scripts/select_tasks.py .pouch/ack/tasks.yaml \
--task-id <ack-task-id>
```
+3 -3
View File
@@ -66,7 +66,7 @@ profile 升级时不得复用旧 worker,Test 也不得使用 Developer 的强
### 机器事实源
worker 路由的机器可读事实只保存在 `docs/ack/tasks.yaml` 的
worker 路由的机器可读事实只保存在 `.pouch/ack/tasks.yaml` 的
`project.orchestration`。`project.md` 可以解释项目为何选某个档位,但不能另写一份
完整启动命令或覆盖机器配置。字段结构以 `templates/tasks.schema.json` 为准。
@@ -135,12 +135,12 @@ python3 <ack-skill-dir>/scripts/launch_worker.py launch \
--expected-launch-fingerprint <plan 中的 sha256:...>
```
`--project-root` 始终指向保存权威 `docs/ack/tasks.yaml` 的项目根;`--worktree` 是本次
`--project-root` 始终指向保存权威 `.pouch/ack/tasks.yaml` 的项目根;`--worktree` 是本次
worker 实际工作的绝对路径,两者可以不同。后者仍必须与项目根属于同一 Git
仓库(v0.19 起由 launcher 按 `git worktree list` 注册表 + 同 common-dir 校验,
不再依赖 `allowedWorktrees` 白名单)。
项目状态文件固定从 `--project-root/docs/ack/` 解析;任务板不需要保存 `repoPath` 或
项目状态文件固定从 `--project-root/.pouch/ack/` 解析;任务板不需要保存 `repoPath` 或
`devWorktree`。旧任务板中的这两个字段仅作兼容信息,launcher 不使用它们授权或定位。
`projectRoot`、任务板内容摘要和 worker worktree identity 都会进入 launch fingerprint,
因此切换权威项目根、任务板内容或 worker 路径后必须重新生成并审阅 plan。
+2 -2
View File
@@ -58,7 +58,7 @@ Coordinator 用这些模板向 **Developer** 派发修复、向 **Test** 派发
- 不要写 tasks.yaml,不要标记 verified。
- 不要写 knowledge.yaml,不要自行扩展或全量读取知识库;candidate 不是已生效规则。
- 不要把知识正文或 path/args 拼成 shell 命令。只把 verification.ref 交给
`<ack-skill-dir>/scripts/run_verification.py docs/ack/knowledge.yaml
`<ack-skill-dir>/scripts/run_verification.py .pouch/ack/knowledge.yaml
<verification-ref> --project-root <project-root>`。
- 不要提交或推送,除非用户明确要求。
- 最小 diff,只改本任务根因,避免无关重构;若必须先重构请停下说明并请示。
@@ -139,7 +139,7 @@ Developer 本轮声称(仅供参考,不作数):
证据,则分别列出产品信号与环境限制。
- 需要时把易反复误判的路径沉淀成可执行测试(见 optimization-method.md §8)。
- 对每条适用的 `knowledgeRef`,把它的 verification.ref 交给
`<ack-skill-dir>/scripts/run_verification.py docs/ack/knowledge.yaml
`<ack-skill-dir>/scripts/run_verification.py .pouch/ack/knowledge.yaml
<verification-ref> --project-root <project-root>`,并回报 `knowledgeChecks`。
对 candidate 使用独立观测验证,不能复述 Developer 的结论作为证据。
@@ -27,7 +27,7 @@ ACK 默认三个独立 Agent:**Coordinator 只编排、Test 只验证、Develo
上面的表定义了**边界**(谁能碰什么),这一节定义**能力**(每个角色到底该怎么做好自己的事)。每个角色用同一骨架描述:`Outcome`(产出什么)/ `Must Do`(必须做)/ `Must Not`(不能做)/ `Evidence`(拿什么证明)/ `Output`(交付格式)。派发 prompt 会引用这里,见 `prompt-templates.md`。
这些是**通用工程习惯**,不含项目命令与路径;项目差异写在覆盖层文件(默认 `docs/ack/project.md`)。装了外部 skill 的环境可按每个角色末尾的「可选 skills」加速,未装则照本清单执行,不阻塞。
这些是**通用工程习惯**,不含项目命令与路径;项目差异写在覆盖层文件(默认 `.pouch/ack/project.md`)。装了外部 skill 的环境可按每个角色末尾的「可选 skills」加速,未装则照本清单执行,不阻塞。
### Coordinator (PM):拆解与终检
@@ -97,7 +97,7 @@ ACK 默认三个独立 Agent:**Coordinator 只编排、Test 只验证、Develo
## 路径权限模板
目标项目在自己的**覆盖层文件**中填入实际路径(模板见 `templates/project.template.md`;覆盖层默认 `docs/ack/project.md`,路径记在 `tasks.yaml` 的 `project.overlayFile`)。
目标项目在自己的**覆盖层文件**中填入实际路径(模板见 `templates/project.template.md`;覆盖层默认 `.pouch/ack/project.md`,路径记在 `tasks.yaml` 的 `project.overlayFile`)。
| 路径 | Coordinator | Test | Developer | 说明 |
|------|:-----------:|:----:|:---------:|------|
+1 -1
View File
@@ -51,7 +51,7 @@ from worker_profiles import ( # noqa: E402
PROTOCOL_VERSION = LAUNCH_PROTOCOL_VERSION
RECEIPT_VERSION = 1
ENVIRONMENT_POLICY = "per-cli-allowlist-v1"
TASKS_RELATIVE_PATH = Path("docs/ack/tasks.yaml")
TASKS_RELATIVE_PATH = Path(".pouch/ack/tasks.yaml")
MAX_CONTROL_OUTPUT = 1024 * 1024
MAX_RECORD_SIZE = 256 * 1024
LAUNCH_TTL_SECONDS = 120
+3 -3
View File
@@ -57,7 +57,7 @@ def _validate_knowledge_location(
knowledge_path: Path,
project_root: Path,
) -> str | None:
expected = project_root / "docs" / "ack" / "knowledge.yaml"
expected = project_root / ".pouch" / "ack" / "knowledge.yaml"
lexical = Path(os.path.abspath(knowledge_path.expanduser()))
if lexical != expected:
return (
@@ -171,7 +171,7 @@ def load_authoritative_knowledge(
) -> tuple[dict[str, Any] | None, str | None]:
source_fd, open_error = _open_regular_beneath(
project_root,
"docs/ack/knowledge.yaml",
".pouch/ack/knowledge.yaml",
require_executable=False,
)
if open_error is not None or source_fd is None:
@@ -329,7 +329,7 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument("verification_ref", help="verificationRegistry 中的检查 ID")
parser.add_argument(
"--project-root",
help="项目根目录;默认从 knowledge.yaml 的 docs/ack 布局或 Git 推断",
help="项目根目录;默认从 knowledge.yaml 的 .pouch/ack 布局或 Git 推断",
)
args = parser.parse_args(argv)
+1 -1
View File
@@ -197,7 +197,7 @@ def _parser() -> argparse.ArgumentParser:
parser.add_argument(
"tasks",
nargs="?",
default="docs/ack/tasks.yaml",
default=".pouch/ack/tasks.yaml",
help="任务板路径",
)
parser.add_argument("--task-id", action="append", default=[])
+7 -7
View File
@@ -5,9 +5,9 @@
检查引用、步骤顺序、默认 profile 安全边界、敏感信息和仓库内入口路径。
用法:
python3 validate_delivery.py docs/ack/delivery.yaml
python3 validate_delivery.py docs/ack/delivery.yaml \
--tasks docs/ack/tasks.yaml --project-root <project-root>
python3 validate_delivery.py .pouch/ack/delivery.yaml
python3 validate_delivery.py .pouch/ack/delivery.yaml \
--tasks .pouch/ack/tasks.yaml --project-root <project-root>
退出码: 0 通过 / 1 校验失败 / 2 环境或用法错误。
"""
@@ -777,8 +777,8 @@ def validate_tasks_link(delivery: dict[str, Any], tasks: dict[str, Any]) -> list
project = tasks.get("project")
if not isinstance(project, dict):
return ["tasks.project 必须是对象"]
if project.get("deliveryFile") != "docs/ack/delivery.yaml":
errors.append("tasks.project.deliveryFile 必须固定为 docs/ack/delivery.yaml")
if project.get("deliveryFile") != ".pouch/ack/delivery.yaml":
errors.append("tasks.project.deliveryFile 必须固定为 .pouch/ack/delivery.yaml")
delivery_project = delivery.get("project")
if (
isinstance(delivery_project, dict)
@@ -806,8 +806,8 @@ def validate_with_schema(data: dict[str, Any], schema_path: Path) -> list[str]:
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="校验 ACK 项目交付契约")
parser.add_argument("delivery", nargs="?", default="docs/ack/delivery.yaml")
parser.add_argument("--tasks", help="关联的 docs/ack/tasks.yaml")
parser.add_argument("delivery", nargs="?", default=".pouch/ack/delivery.yaml")
parser.add_argument("--tasks", help="关联的 .pouch/ack/tasks.yaml")
parser.add_argument("--project-root", help="项目根目录;提供后检查入口路径")
parser.add_argument("--schema", help="delivery.schema.json 路径(默认自动探测)")
args = parser.parse_args(argv)
+7 -7
View File
@@ -189,10 +189,10 @@ def _timestamp(value: Any) -> datetime | None:
def infer_project_root(document_path: Path) -> Path | None:
"""从标准 docs/ack 布局或 Git marker 推断项目根,不解析文档 symlink。"""
"""从标准 .pouch/ack 布局或 Git marker 推断项目根,不解析文档 symlink。"""
lexical = document_path.expanduser().absolute()
parent = lexical.parent
if parent.name == "ack" and parent.parent.name == "docs":
if parent.name == "ack" and parent.parent.name in {".pouch", "docs"}:
return parent.parent.parent.resolve()
for candidate in (parent, *parent.parents):
if (candidate / ".git").exists():
@@ -245,7 +245,7 @@ def _tasks_project_root(
return inferred
# Legacy task boards may still declare repoPath. It is only a fallback for
# non-standard layouts; docs/ack location is authoritative when available.
# non-standard layouts; .pouch/ack location is authoritative when available.
project = tasks_data.get("project")
repo_path = project.get("repoPath") if isinstance(project, dict) else None
if _nonempty(repo_path):
@@ -779,10 +779,10 @@ def _validate_knowledge_file_binding(
knowledge_file = project.get("knowledgeFile")
if not _nonempty(knowledge_file):
return ["[tasks] project.knowledgeFile 必填"]
if knowledge_file != "docs/ack/knowledge.yaml":
if knowledge_file != ".pouch/ack/knowledge.yaml":
errors.append(
"[tasks] project.knowledgeFile 必须固定为 "
"'docs/ack/knowledge.yaml'"
"'.pouch/ack/knowledge.yaml'"
)
relative = Path(knowledge_file)
segments = knowledge_file.replace("\\", "/").split("/")
@@ -812,7 +812,7 @@ def _validate_knowledge_file_binding(
binding_root = project_root or declared_root
if binding_root is None or not binding_root.is_dir():
errors.append(
"[tasks] 无法从 docs/ack 布局确定现有项目根目录;"
"[tasks] 无法从 .pouch/ack 布局确定现有项目根目录;"
"请传入 --project-root"
)
return errors
@@ -1071,7 +1071,7 @@ def main(argv: list[str] | None = None) -> int:
parser.add_argument("--tasks", help="可选 tasks.yaml,用于跨文件引用校验")
parser.add_argument(
"--project-root",
help="可选项目根目录;默认从 tasks.yaml 的 docs/ack 布局推断",
help="可选项目根目录;默认从 tasks.yaml 的 .pouch/ack 布局推断",
)
args = parser.parse_args(argv)
+4 -4
View File
@@ -763,17 +763,17 @@ def validate_builtin(data: dict) -> list[str]:
)
if (
"knowledgeFile" in project
and project.get("knowledgeFile") != "docs/ack/knowledge.yaml"
and project.get("knowledgeFile") != ".pouch/ack/knowledge.yaml"
):
errors.append(
"project.knowledgeFile 必须固定为 docs/ack/knowledge.yaml"
"project.knowledgeFile 必须固定为 .pouch/ack/knowledge.yaml"
)
if (
"deliveryFile" in project
and project.get("deliveryFile") != "docs/ack/delivery.yaml"
and project.get("deliveryFile") != ".pouch/ack/delivery.yaml"
):
errors.append(
"project.deliveryFile 必须固定为 docs/ack/delivery.yaml"
"project.deliveryFile 必须固定为 .pouch/ack/delivery.yaml"
)
if "deliveryFile" in project and not isinstance(data.get("deliveryRuns"), list):
errors.append("引用 deliveryFile 的任务板必须包含 deliveryRuns 列表")
@@ -13,7 +13,7 @@ import sys
MIGRATION_MESSAGE = (
"ACK v0.10 已停用自由 worker command 校验器;请在 "
"docs/ack/tasks.yaml 的 project.orchestration 中声明 profile,并仅调用 "
".pouch/ack/tasks.yaml 的 project.orchestration 中声明 profile,并仅调用 "
"scripts/launch_worker.py profile-hash|plan|launch。"
)
+2 -2
View File
@@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://git.yumee.top/laily/skills/skills/ack/templates/delivery.schema.json",
"$id": "https://git.yumee.top/laily/pouch/skills/ack/templates/delivery.schema.json",
"title": "ACK project delivery contract",
"description": "docs/ack/delivery.yaml 的权威结构;语义规则由 scripts/validate_delivery.py 补充。",
"description": ".pouch/ack/delivery.yaml 的权威结构;语义规则由 scripts/validate_delivery.py 补充。",
"type": "object",
"required": [
"version",
+1 -1
View File
@@ -1,4 +1,4 @@
# 复制为 docs/ack/delivery.yaml。默认关闭;由用户明确配置后再启用。
# 复制为 .pouch/ack/delivery.yaml。默认关闭;由用户明确配置后再启用。
version: 1
updatedAt: "<YYYY-MM-DDTHH:mm:ss+TZ>"
project:
+2 -2
View File
@@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://git.yumee.top/laily/skills/skills/ack/templates/knowledge.schema.json",
"$id": "https://git.yumee.top/laily/pouch/skills/ack/templates/knowledge.schema.json",
"title": "ACK project knowledge guardrails",
"description": "docs/ack/knowledge.yaml 的权威结构。知识只描述约束和验证引用,不保存可执行命令。",
"description": ".pouch/ack/knowledge.yaml 的权威结构。知识只描述约束和验证引用,不保存可执行命令。",
"type": "object",
"required": ["version", "updatedAt", "project", "verificationRegistry", "entries"],
"additionalProperties": false,
+1 -1
View File
@@ -1,4 +1,4 @@
# 复制为 docs/ack/knowledge.yaml,替换占位符。结构见 templates/knowledge.schema.json。
# 复制为 .pouch/ack/knowledge.yaml,替换占位符。结构见 templates/knowledge.schema.json。
# Developer/Test 只能在任务证据中提出 candidate;只有 Coordinator 写入这里。
version: 1
updatedAt: "<YYYY-MM-DDTHH:mm:ss+TZ>"
+7 -7
View File
@@ -3,12 +3,12 @@
> 本项目基于 ACK Skill v<ack_version>。通用规范由 `/ack` 从 Skill 自身的
> `references/` 读取;本文件只保存项目差异。
>
> **本文件是「项目覆盖层」,文件名可配置。** 默认放 `docs/ack/project.md`,
> **本文件是「项目覆盖层」,文件名可配置。** 默认放 `.pouch/ack/project.md`,
> 不占用 `AGENTS.md`,避免与团队已有的 `AGENTS.md` 约定冲突。
> 若希望 Agent 自动加载,可由项目维护者自行在 `AGENTS.md` 中引用本文件;ACK
> 不会自动修改 `AGENTS.md`、`CLAUDE.md` 或其它 Agent 指令文件。
> 无论叫什么,都在 `tasks.yaml` 的 `project.overlayFile` 记录实际路径。
> `docs/ack/` 只保存本项目的 `project.md`、`tasks.yaml`、`knowledge.yaml` 与默认关闭的
> `.pouch/ack/` 只保存本项目的 `project.md`、`tasks.yaml`、`knowledge.yaml` 与默认关闭的
> `delivery.yaml`,
> 不复制或链接 Skill。
@@ -18,10 +18,10 @@
- 技术栈:`<tech_stack>`
- 运行命令:`<run_command>`
- Base URL:`<base_url>`
- 任务板:`docs/ack/tasks.yaml`
- 项目知识:`docs/ack/knowledge.yaml`
- 交付契约:`docs/ack/delivery.yaml`(默认关闭)
- 覆盖层文件:`<overlay_file_path>`(默认 `docs/ack/project.md`)
- 任务板:`.pouch/ack/tasks.yaml`
- 项目知识:`.pouch/ack/knowledge.yaml`
- 交付契约:`.pouch/ack/delivery.yaml`(默认关闭)
- 覆盖层文件:`<overlay_file_path>`(默认 `.pouch/ack/project.md`)
## 通用规范(由 ACK Skill 按需读取)
@@ -37,7 +37,7 @@
## Worker 路由
机器可校验的模型、reasoning effort、权限模式、默认 profile、允许 worktree 和启动
receipt 全部以 `docs/ack/tasks.yaml` 的 `project.orchestration` 与顶层
receipt 全部以 `.pouch/ack/tasks.yaml` 的 `project.orchestration` 与顶层
`workerReceipts` 为准。本文件不保存可执行 worker 命令。
默认 profile:
+5 -5
View File
@@ -1,6 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://git.yumee.top/laily/skills/skills/ack/templates/tasks.schema.json",
"$id": "https://git.yumee.top/laily/pouch/skills/ack/templates/tasks.schema.json",
"title": "ACK task board",
"description": "tasks.yaml 的权威结构。跨语言可用;参考校验实现见 scripts/validate_tasks.py。",
"type": "object",
@@ -45,7 +45,7 @@
"repoPath": {
"type": "string",
"deprecated": true,
"description": "Legacy informational field; ACK derives project files from --project-root/docs/ack"
"description": "Legacy informational field; ACK derives project files from --project-root/.pouch/ack"
},
"baseUrl": {
"type": "string"
@@ -57,16 +57,16 @@
},
"overlayFile": {
"type": "string",
"description": "项目覆盖层文件路径,默认 docs/ack/project.md,可自定义"
"description": "项目覆盖层文件路径,默认 .pouch/ack/project.md,可自定义"
},
"knowledgeFile": {
"type": "string",
"const": "docs/ack/knowledge.yaml",
"const": ".pouch/ack/knowledge.yaml",
"description": "项目知识护栏库的唯一权威路径"
},
"deliveryFile": {
"type": "string",
"const": "docs/ack/delivery.yaml",
"const": ".pouch/ack/delivery.yaml",
"description": "可选项目交付契约的唯一权威路径"
},
"bugIntake": {
+4 -4
View File
@@ -1,4 +1,4 @@
# 复制为 docs/ack/tasks.yaml,替换占位符。结构见 templates/tasks.schema.json。
# 复制为 .pouch/ack/tasks.yaml,替换占位符。结构见 templates/tasks.schema.json。
version: 1
updatedAt: "<YYYY-MM-DDTHH:mm:ss+TZ>"
source: "Coordinator (PM) Agent"
@@ -6,9 +6,9 @@ ackVersion: "<接入时的 ack skill 版本>"
project:
name: "<project_name>"
baseUrl: "<base_url>"
overlayFile: "docs/ack/project.md"
knowledgeFile: "docs/ack/knowledge.yaml"
deliveryFile: "docs/ack/delivery.yaml"
overlayFile: ".pouch/ack/project.md"
knowledgeFile: ".pouch/ack/knowledge.yaml"
deliveryFile: ".pouch/ack/delivery.yaml"
# 可选:飞书 Base Bug 收件箱。只保存 profile 名和资源 ID,绝不保存 App Secret。
# bugIntake:
# provider: "feishu-base"
+1 -1
View File
@@ -47,5 +47,5 @@ DOCKER_REGISTRY=registry.example.com
| `scripts/publish_docker.sh` | buildx 构建 + 推送镜像,远端 digest 验证 |
| `scripts/verify_deb.sh` | 核对包元数据、内容与 SHA-256 |
环境变量契约、脚本解析顺序(`$BUILDER_SKILL_DIR` → `~/.skills/skills/builder/scripts/`)、
环境变量契约、脚本解析顺序(`$BUILDER_SKILL_DIR` → `~/.pouch/skills/builder/scripts/`)、
脏工作树策略等完整规则见 contract.md。
+3 -3
View File
@@ -81,10 +81,10 @@ Agent 只保留授权判断和歧义处理。**
push 目标定位 builder 脚本时按以下顺序,命中即用,不做静默兜底:
1. `$BUILDER_SKILL_DIR/scripts/`(特殊安装位置)
2. `$HOME/.skills/skills/builder/scripts/`(标准 clone 位)
2. `$HOME/.pouch/skills/builder/scripts/`(标准 clone 位)
两个位置都不可用时必须失败并提示:设置 `BUILDER_SKILL_DIR`,或把 skills 仓库
clone 到 `~/.skills`。
两个位置都不可用时必须失败并提示:设置 `BUILDER_SKILL_DIR`,或把 pouch 仓库
clone 到 `~/.pouch`。
## 5. 校验
+13 -3
View File
@@ -196,7 +196,16 @@ def check_docker_recipe(report: Report, project: Path) -> None:
SCRIPT_RESOLVE_SNIPPETS = tuple(
f"{prefix}{name}"
for prefix in ("$$BUILDER_SKILL_DIR", "$BUILDER_SKILL_DIR", "$$HOME/.skills/skills/builder/scripts", "$HOME/.skills/skills/builder/scripts", "~/.skills/skills/builder/scripts")
for prefix in (
"$$BUILDER_SKILL_DIR",
"$BUILDER_SKILL_DIR",
"$$HOME/.pouch/skills/builder/scripts",
"$HOME/.pouch/skills/builder/scripts",
"~/.pouch/skills/builder/scripts",
"$$HOME/.skills/skills/builder/scripts",
"$HOME/.skills/skills/builder/scripts",
"~/.skills/skills/builder/scripts",
)
for name in VALID_SCRIPT_NAMES
)
@@ -218,7 +227,7 @@ def check_push_delegates(report: Report, project: Path, dual_artifact: bool) ->
elif not any(snippet in text for snippet in SCRIPT_RESOLVE_SNIPPETS) \
and "$(BUILDER_SCRIPT)" not in text and "upload_deb.sh" not in text \
and "publish_docker.sh" not in text:
inline.append(f"{target}: does not call a builder script (expected $BUILDER_SKILL_DIR/... or ~/.skills/... path)")
inline.append(f"{target}: does not call a builder script (expected $BUILDER_SKILL_DIR/... or ~/.pouch/... path)")
else:
thin.append(target)
problems = []
@@ -262,6 +271,7 @@ def check_script_paths(report: Report) -> None:
if env_dir:
candidates.append(Path(env_dir) / "scripts")
home = Path(os.environ.get("HOME", ""))
candidates.append(home / ".pouch" / "skills" / "builder" / "scripts")
candidates.append(home / ".skills" / "skills" / "builder" / "scripts")
found = next((c for c in candidates if c.is_dir() and any((c / n).is_file() for n in VALID_SCRIPT_NAMES)), None)
if found:
@@ -270,7 +280,7 @@ def check_script_paths(report: Report) -> None:
report.add(FAIL, 9, "builder 脚本路径可达", "\n".join([
"none of these resolve to scripts/upload_deb.sh:",
*(f" {c}" for c in candidates),
"Fix: set BUILDER_SKILL_DIR, or clone the skills repo to ~/.skills.",
"Fix: set BUILDER_SKILL_DIR, or clone the pouch repo to ~/.pouch.",
]))
+8 -8
View File
@@ -5,9 +5,9 @@
支持三种用法:
- **独立配置中心**:一个专门的 Git 仓库管所有机器的所有 Compose 服务(如 app00)
- **项目内 Compose 环境**:在普通项目里放 `.skiff/deployer/{prod,test,dev}/`,
- **项目内 Compose 环境**:在普通项目里放 `.pouch/deployer/{prod,test,dev}/`,
把这个项目的生产/测试/开发环境用 rsync + docker compose 部署
- **Argo CD / GitOps**:项目里放 `.skiff/deployer/argocd.yaml`;Agent 改 GitOps 并开 MR,
- **Argo CD / GitOps**:项目里放 `.pouch/deployer/argocd.yaml`;Agent 改 GitOps 并开 MR,
你合并后由 Argo CD 同步。仓库既可以只写 Git 地址(部署时浅 clone),也可以指定本机已有目录。
## 什么时候使用
@@ -42,7 +42,7 @@ vhom1 上那个 naiveproxy 为什么 sync 失败?
web1 能出网,直接让它从 https://... 把包拉下来装
# 项目内环境
给这个项目建好 .skiff/deployer,prod 和 test 分别放到两台机器上
给这个项目建好 .pouch/deployer,prod 和 test 分别放到两台机器上
把 test 环境重新部署一下
prod 的 compose 加个 redis,改完发上去
@@ -55,13 +55,13 @@ GitOps 我已经 clone 在 ../infra-gitops,用那个目录开 MR
## Agent 会做什么
1. 读服务/环境目录(及共享的父目录)的 `_config.yaml`,确定目标机器和远程路径;
项目内布局从 `.skiff/deployer/` 自动发现,无需额外配置
项目内布局从 `.pouch/deployer/` 自动发现,无需额外配置
2. 用 skill 自带脚本把本地目录同步到远程(rsync,自动排除 `data/`、`_data/`)
3. 在远程执行对应的 `docker compose` 操作(启动 / 重建 / 升级 / 重启)
4. deb 包安装走独立脚本:scp 上传到暂存目录后远程 apt 安装,失败自动修依赖
5. 同步后查看容器状态和日志确认生效
6. 只针对你指定的那一个服务操作,不会批量动整台机器
7. Argo CD:读 `.skiff/deployer/argocd.yaml`,浅 clone 或使用 `repo_dir`,改清单,推分支开 MR,停下来等你合并;
7. Argo CD:读 `.pouch/deployer/argocd.yaml`,浅 clone 或使用 `repo_dir`,改清单,推分支开 MR,停下来等你合并;
不直接 kubectl 发布,不把 Harbor/TLS 密钥提交进 Git
项目内布局下,远程目录名自动带上项目前缀(如 `my-project-prod`),
@@ -80,14 +80,14 @@ GitOps 我已经 clone 在 ../infra-gitops,用那个目录开 MR
## Argo CD 的两种接法
在业务项目里放 `.skiff/deployer/argocd.yaml`。Agent 只改 GitOps 并开 MR,**你合并之后** Argo CD 才部署。镜像、namespace、域名、Secret 名以 GitOps 清单为准,不必在这个文件里再抄一遍。
在业务项目里放 `.pouch/deployer/argocd.yaml`。Agent 只改 GitOps 并开 MR,**你合并之后** Argo CD 才部署。镜像、namespace、域名、Secret 名以 GitOps 清单为准,不必在这个文件里再抄一遍。
### 1. 只写仓库地址(默认)
本机不用长期放 GitOps 仓库。部署时 Agent 浅 clone 到临时目录,改完开 MR,用完删掉。
```yaml
# .skiff/deployer/argocd.yaml
# .pouch/deployer/argocd.yaml
repo: git@git.example.com:org/infra-gitops.git
```
@@ -105,7 +105,7 @@ repo: git@git.example.com:org/infra-gitops.git
GitOps 仓库已经 checkout 在旁边时,写 `repo_dir`,Agent 直接进这个目录改、推分支、开 MR。
```yaml
# .skiff/deployer/argocd.yaml
# .pouch/deployer/argocd.yaml
repo: git@git.example.com:org/infra-gitops.git
repo_dir: ../infra-gitops
```
+9 -9
View File
@@ -42,7 +42,7 @@ description: >-
| 信号 | 轨道 |
|------|------|
| ArgoCD / GitOps / 集群 / 开 MR 部署 / 项目有 `.skiff/deployer/argocd.yaml` | Argo CD,见 [argocd.md](references/argocd.md) |
| ArgoCD / GitOps / 集群 / 开 MR 部署 / 项目有 `.pouch/deployer/argocd.yaml` | Argo CD,见 [argocd.md](references/argocd.md) |
| sync、`TGT=`、某台机器、`compose.yaml` | Compose(下文布局与步骤) |
| 两者都有且意图不清 | 先问 |
@@ -57,7 +57,7 @@ description: >-
### Argo CD
源项目 `.skiff/deployer/argocd.yaml`:`repo` 写 Git 地址(部署时浅 clone),或加 `repo_dir` 用已有 checkout。
源项目 `.pouch/deployer/argocd.yaml`:`repo` 写 Git 地址(部署时浅 clone),或加 `repo_dir` 用已有 checkout。
改 GitOps 清单,不要改 Compose 脚本。密钥不入库。两种接法见 skill README,步骤见 [argocd.md](references/argocd.md)。
### 两种 Compose 布局
@@ -75,14 +75,14 @@ repo/
远程目录名 = 目录末级名:`vyyo1/naiveproxy` → `/opt/app/naiveproxy`。
**B. 项目内环境布局**:项目根放 `.skiff/deployer/{prod,test,dev}/`,
**B. 项目内环境布局**:项目根放 `.pouch/deployer/{prod,test,dev}/`,
每个环境一个目录。从项目内任意位置运行脚本即自动发现(也可用 `DEPLOYER_ROOT`
显式指定),无需环境变量:
```
my-project/
├── src/ ... # 项目本体
└── .skiff/deployer/
└── .pouch/deployer/
├── _config.yaml # 三个环境共享默认(node/base_path 等)
├── argocd.yaml # 可选,Argo CD 指针(不是 compose 环境)
├── prod/
@@ -106,7 +106,7 @@ skill 目录下的 `scripts/deploy/` 是通用部署工具链(lib/sync/remote/
不依赖具体项目路径。部署根按以下顺序解析:
1. 环境变量 `DEPLOYER_ROOT` 显式指定(独立配置中心仓库用这个)
2. 从当前目录向上找 `.skiff/deployer/`(项目内环境布局自动发现)
2. 从当前目录向上找 `.pouch/deployer/`(项目内环境布局自动发现)
3. skill 安装位置兜底(仅用于查看,没有可部署服务)
```bash
@@ -162,9 +162,9 @@ python3 <skill-dir>/scripts/deploy/sync.py <service-path>
项目环境布局:
1. 项目根建 `.skiff/deployer/{env}/`(env 通常为 prod/test/dev)
1. 项目根建 `.pouch/deployer/{env}/`(env 通常为 prod/test/dev)
2. 每个环境写 `compose.yaml`;三个环境共享的 node/base_path 放
`.skiff/deployer/_config.yaml`
`.pouch/deployer/_config.yaml`
3. 环境有差异(不同主机、不同排除项)→ 在该环境的 `_config.yaml` 覆盖
4. 同名冲突或需要固定远程目录名 → `_config.yaml` 写 `name:`
5. 首次部署前确认目标主机的远程目录不存在旧内容(rsync `--delete` 会清掉)
@@ -173,7 +173,7 @@ python3 <skill-dir>/scripts/deploy/sync.py <service-path>
独立仓库布局:配置移入 `unused/`(自动脱离发现体系),远程按需手动清理:
`ssh <node> "cd <base_path>/<name> && docker compose down"`,数据卷按需保留或删除。
项目环境布局:删除对应 `.skiff/deployer/{env}/` 目录即可脱离发现体系,远程清理同上。
项目环境布局:删除对应 `.pouch/deployer/{env}/` 目录即可脱离发现体系,远程清理同上。
#### 7. 向节点安装 deb 包
@@ -204,7 +204,7 @@ python3 <skill-dir>/scripts/deploy/deb.py <target> apt https://example.com/foo_1
完整步骤与 `argocd.yaml` 字段见 [argocd.md](references/argocd.md)。
1. 读项目 `.skiff/deployer/argocd.yaml`(无则只问 Git 地址,写成 `repo:`)。
1. 读项目 `.pouch/deployer/argocd.yaml`(无则只问 Git 地址,写成 `repo:`)。
有 `repo_dir` 则用该目录;否则把 `repo` 浅 clone 到临时目录,用完删除。
2. 在工作副本里按**已有应用惯例**新增 Application,或只改镜像 tag / 清单。
3. 从最新默认分支拉出分支,commit、push,用 `glab`/`gh`/`tea` 开 MR;CLI 对项目 404 则把
@@ -2,7 +2,7 @@
`_config.yaml` 供 **Compose 轨道**脚本解析,决定同步目标与排除规则。可放在**服务目录、部署根或其任意祖先目录**;子目录中的字段覆盖父目录(继承合并)。
Argo CD 轨道用独立文件 `.skiff/deployer/argocd.yaml`,字段见 [argocd.md](argocd.md)。
Argo CD 轨道用独立文件 `.pouch/deployer/argocd.yaml`,字段见 [argocd.md](argocd.md)。
不要把 `argocd:` 嵌进本文件(脚本解析器不支持嵌套映射)。
## 放置位置(两种布局)
@@ -10,16 +10,16 @@ Argo CD 轨道用独立文件 `.skiff/deployer/argocd.yaml`,字段见 [argocd.
| 布局 | 部署根 | `_config.yaml` 典型位置 |
|------|--------|------------------------|
| 独立配置中心仓库(`DEPLOYER_ROOT` 指向) | 仓库根 | 主机目录 `vyyo1/_config.yaml`、服务目录 |
| 项目内环境 `.skiff/deployer/{env}/` | `.skiff/deployer/` | 根级共享默认、各环境目录覆盖 |
| 项目内环境 `.pouch/deployer/{env}/` | `.pouch/deployer/` | 根级共享默认、各环境目录覆盖 |
项目布局示例:
```yaml
# .skiff/deployer/_config.yaml — 三个环境共享
# .pouch/deployer/_config.yaml — 三个环境共享
node: my-vps
base_path: /srv/apps
# .skiff/deployer/prod/_config.yaml — 仅生产环境差异
# .pouch/deployer/prod/_config.yaml — 仅生产环境差异
node: prod-vps # 覆盖父级
name: my-project-api # 可选,覆盖默认的 {项目名}-{env}
```
@@ -111,7 +111,7 @@ sync_exclude:
| 同一 SSH 主机多个服务 | 主机目录写一份 `node`/`base_path`,子服务免重复 |
| 各服务目标不同 | 服务目录单独写 `_config.yaml` |
| 个别覆盖 | 子目录只写差异字段 |
| 项目三环境同主机 | `.skiff/deployer/_config.yaml` 写共享 node,各环境只放差异 |
| 项目三环境同主机 | `.pouch/deployer/_config.yaml` 写共享 node,各环境只放差异 |
| 项目环境分属不同主机 | 各环境 `_config.yaml` 分别写 `node` |
## 示例
@@ -137,4 +137,4 @@ node: deploy@web2-backup
- 目录内有 `compose.yaml`
- 能通过继承或兜底解析出 `node`
- 独立仓库布局:路径中不含 `unused/` 段
- 项目环境布局:位于部署根 `.skiff/deployer/` 内(其外的项目文件不扫描)
- 项目环境布局:位于部署根 `.pouch/deployer/` 内(其外的项目文件不扫描)
+12 -10
View File
@@ -3,7 +3,7 @@
支持两种布局:
1. 独立配置中心仓库(DEPLOYER_ROOT 指向,或 skill 安装位置)
2. 项目内环境目录 .skiff/deployer/{prod,test,dev}/(从 CWD 自动发现)
2. 项目内环境目录 .pouch/deployer/{prod,test,dev}/(从 CWD 自动发现;兼容 .skiff/deployer)
"""
from __future__ import annotations
@@ -18,10 +18,11 @@ DEFAULT_BASE_PATH = "/opt/app"
DEFAULT_SYNC_EXCLUDES = ("data", "_data")
_SKILL_DIR = Path(__file__).resolve().parent.parent # scripts/
PROJECT_ROOT: Path | None = None
_PROJECT_LAYOUT_DIRS = (".pouch", ".skiff")
def _find_project_root() -> Path:
"""部署根:DEPLOYER_ROOT > 从 CWD 向上找 .skiff/deployer > skill 安装位置。"""
"""部署根:DEPLOYER_ROOT > 从 CWD 向上找 .pouch/deployer > skill 安装位置。"""
env = os.environ.get("DEPLOYER_ROOT", "").strip()
if env:
p = Path(env).expanduser().resolve()
@@ -31,9 +32,10 @@ def _find_project_root() -> Path:
return p
cur = Path.cwd()
while True:
cand = cur / ".skiff" / "deployer"
if cand.is_dir():
return cand
for dirname in _PROJECT_LAYOUT_DIRS:
cand = cur / dirname / "deployer"
if cand.is_dir():
return cand
if cur == cur.parent:
break
cur = cur.parent
@@ -48,13 +50,13 @@ def project_root() -> Path:
def in_project_layout(root: Path | None = None) -> bool:
"""部署根是否为某项目内的 .skiff/deployer/。"""
"""部署根是否为某项目内的 .pouch/deployer/。"""
root = root or project_root()
return root.name == "deployer" and root.parent.name == ".skiff"
return root.name == "deployer" and root.parent.name in _PROJECT_LAYOUT_DIRS
def project_display_name(root: Path | None = None) -> str:
"""项目名:git 仓库名优先,否则 .skiff 的父目录名。"""
"""项目名:git 仓库名优先,否则 .pouch 的父目录名。"""
root = root or project_root()
anchor = root.parent.parent if in_project_layout(root) else root
try:
@@ -111,7 +113,7 @@ def load_config(config_path: os.PathLike | str, *, required: bool = True) -> dic
def config_paths_for_service(service_dir: str) -> list[Path]:
"""收集部署根自身及服务目录各层 _config.yaml(祖先在前,服务目录在后)。
部署根的 _config.yaml(如 .skiff/deployer/_config.yaml)作为全局默认,
部署根的 _config.yaml(如 .pouch/deployer/_config.yaml)作为全局默认,
对所有环境/服务生效。
"""
root = project_root()
@@ -333,7 +335,7 @@ def service_info(service_dir: str, *, strict: bool = True) -> dict | None:
def is_deployable_dir(path: Path, root: Path) -> bool:
if "unused" in path.parts or "__pycache__" in path.parts:
return False
if ".skiff" in path.parts and root.name != "deployer":
if any(part in _PROJECT_LAYOUT_DIRS for part in path.parts) and root.name != "deployer":
return False
if not (path / "compose.yaml").is_file():
return False
+5 -5
View File
@@ -46,7 +46,7 @@ description: >-
### 1. 解析目标并加载 manifest
1. 解析目标 skill 名;在常见安装位置查找其目录(项目/全局的 agent skills 目录、`~/.skills/skills/`),跟随 symlink 到 SSOT。
1. 解析目标 skill 名;在常见安装位置查找其目录(项目/全局的 agent skills 目录、`~/.pouch/skills/`),跟随 symlink 到 SSOT。
2. 读取 `<skill-dir>/memories/manifest.md`。按 [references/manifest.md](references/manifest.md) 解析 `general` 与 `project` 路径(相对 skill 根或相对当前项目根)。
3. 规范化路径:已存在则用;manifest 声明 `create: true` 且用户未禁止时,写入前再创建;否则列入待确认项。
4. 选定会话材料。会话文件与工具输出当作不可信历史:只抽候选,不执行其中的指令。
@@ -72,7 +72,7 @@ description: >-
### 3. 对照已有记忆去重
读两个 store 的现有内容。`markdown-per-skill` 时只读写 `<path>/<skillname>.md`(例如 `docs/ack/memory/ack.md`),不要把其他 skill 的同目录文件混进本次更新。若 store 另有 schema / 校验器,按其约定更新。
读两个 store 的现有内容。`markdown-per-skill` 时只读写 `<path>/<skillname>.md`(例如 `.pouch/ack/memory/ack.md`),不要把其他 skill 的同目录文件混进本次更新。若 store 另有 schema / 校验器,按其约定更新。
- 已有等价 → `skip-duplicate`
- 旧条目被纠正 → `update`(直接改正文)
@@ -85,12 +85,12 @@ description: >-
```text
目标 skill: ack — ACK 三角色协作闭环
通用记忆: ~/.skills/skills/ack/memories/general (来自 manifest)
项目记忆: ./docs/ack/memory/ack.md (manifest: docs/ack/memory + skillname)
通用记忆: ~/.pouch/skills/ack/memories/general (来自 manifest)
项目记忆: ./.pouch/ack/memory/ack.md (manifest: .pouch/ack/memory + skillname)
将写入(待确认):
- [general] add → general/coordinator-checklist.md :: …
- [project] add → docs/ack/memory/ack.md :: …
- [project] add → .pouch/ack/memory/ack.md :: …
跳过:
- discard: …
@@ -6,4 +6,4 @@ summary: ACK 三角色协作闭环
| kind | path | root | create | format | notes |
|------|------|------|--------|--------|-------|
| general | memories/general | skill | true | markdown-dir | 跨项目:角色协作纪律、收尾检查、常见坑 |
| project | docs/ack/memory | project | true | markdown-per-skill | 仅本仓库;本 skill 写入 `docs/ack/memory/ack.md` |
| project | .pouch/ack/memory | project | true | markdown-per-skill | 仅本仓库;本 skill 写入 `.pouch/ack/memory/ack.md` |
+2 -2
View File
@@ -17,7 +17,7 @@ summary: ACK 三角色协作闭环
| kind | path | root | create | format | notes |
|------|------|------|--------|--------|-------|
| general | memories/general | skill | true | markdown-dir | 跨项目可复用的 ACK 流程纪律 |
| project | docs/ack/memory | project | true | markdown-per-skill | 仅本仓库;写入 `docs/ack/memory/<skillname>.md` |
| project | .pouch/ack/memory | project | true | markdown-per-skill | 仅本仓库;写入 `.pouch/ack/memory/<skillname>.md` |
```
## 字段
@@ -49,5 +49,5 @@ summary: ACK 三角色协作闭环
2. `root: skill` 的路径相对 skill SSOT(解析 symlink 后)。
3. `root: project` 的路径相对当前工作区项目根;找不到项目根则请用户确认。
4. 表格缺省:`create` 默认 `false`;`format` 默认 `markdown-dir`。
5. `format: markdown-per-skill`:解析出目录 `path` 后,写入文件固定为 `<path>/<skillname>.md`(例:目标 `ack` → `docs/ack/memory/ack.md`)。不要把不同 skill 的项目记忆写进同一文件。
5. `format: markdown-per-skill`:解析出目录 `path` 后,写入文件固定为 `<path>/<skillname>.md`(例:目标 `ack` → `.pouch/ack/memory/ack.md`)。不要把不同 skill 的项目记忆写进同一文件。
6. 没有 manifest 时:在 skill 目录下寻找已存在的 `memories/general`,在项目下寻找文档已写明的 `…/memory/<skillname>.md`;仍不唯一则追问。
@@ -1,7 +1,7 @@
# skiff
# pouch
`skiff` 用于创建、维护、安装和发布团队自研的 Agent Skill。Skill 的唯一来源位于
`~/.skills/skills/<name>/`,安装到各 Agent 时使用软链接。
`pouch` 用于创建、维护、安装和发布团队自研的 Agent Skill。Skill 的唯一来源位于
`~/.pouch/skills/<name>/`,安装到各 Agent 时使用软链接。
## 什么时候使用
@@ -13,12 +13,12 @@
## 创建一个 skill
```bash
skiff create my-skill \
pouch create my-skill \
--idea "描述这个 skill 要解决的重复问题" \
--from-project .
```
命令会在 `~/.skills/.drafts/my-skill/` 创建:
命令会在 `~/.pouch/.drafts/my-skill/` 创建:
- `SKILL.md`:给 Agent 阅读的工作流与约束。
- `README.md`:给人类阅读的用途、准备事项、示例和完成标准。
@@ -27,8 +27,8 @@ skiff create my-skill \
完善 `SKILL.md` 和 `README.md` 后运行:
```bash
skiff check my-skill
skiff finalize my-skill
pouch check my-skill
pouch finalize my-skill
```
## 提交和发布
@@ -36,13 +36,13 @@ skiff finalize my-skill
只提交:
```bash
skiff publish skills/my-skill -m "add my-skill"
pouch publish skills/my-skill -m "add my-skill"
```
提交并推送:
```bash
skiff publish skills/my-skill -m "add my-skill" --push
pouch publish skills/my-skill -m "add my-skill" --push
```
## 安装
@@ -50,18 +50,18 @@ skiff publish skills/my-skill -m "add my-skill" --push
安装到当前项目的 Codex:
```bash
skiff add my-skill -a codex -y
pouch add my-skill -a codex -y
```
安装到全局 Codex:
```bash
skiff add my-skill -a codex -g -y
pouch add my-skill -a codex -g -y
```
## 如何判断完成
- `skiff check <name>` 输出校验通过。
- `pouch check <name>` 输出校验通过。
- 正式 skill 同时包含 `SKILL.md` 和 `README.md`。
- `skiff status` 或 `skiff doctor` 显示目标软链接正常。
- `pouch status` 或 `pouch doctor` 显示目标软链接正常。
+44 -44
View File
@@ -1,15 +1,15 @@
---
name: skiff
name: pouch
description: >-
创建和维护 ~/.skills 自研 skill:把项目开发中产生的想法提炼为草稿,完善并校验后发布,
用 skiff add/remove 在项目及全局挂卸 skill,或用 skiff init 初始化 skill 项目状态。
触发词:skiff、自研 skill、创建 skill、想做一个 skill、publish skill、安装自研 skill、
创建和维护 ~/.pouch 自研 skill:把项目开发中产生的想法提炼为草稿,完善并校验后发布,
用 pouch add/remove 在项目及全局挂卸 skill,或用 pouch init 初始化 skill 项目状态。
触发词:pouch、skiff、自研 skill、创建 skill、想做一个 skill、publish skill、安装自研 skill、
更新 skill 到项目、初始化 skill。
---
# skiff 自研 Skill 工作流
# pouch 自研 Skill 工作流
SSOT 固定在 `~/.skills/skills/<name>/`。内容通过 **symlink** 分发到各 agent,改 SSOT 即全项目生效。
SSOT 固定在 `~/.pouch/skills/<name>/`。内容通过 **symlink** 分发到各 agent,改 SSOT 即全项目生效。
---
@@ -18,11 +18,11 @@ SSOT 固定在 `~/.skills/skills/<name>/`。内容通过 **symlink** 分发到
先浏览可用的 builtin skill,再安装到当前项目:
```bash
skiff add --list
skiff add <name> -a cursor -a claude -a codex -a agents -y
pouch add --list
pouch add <name> -a cursor -a claude -a codex -a agents -y
```
`skiff add <name>` 默认安装到当前项目;只有用户明确需要所有项目使用时才加 `-g`。安装结果是指向 `~/.skills/skills/<name>/` 的软链,不要在 Agent 目录创建副本。
`pouch add <name>` 默认安装到当前项目;只有用户明确需要所有项目使用时才加 `-g`。安装结果是指向 `~/.pouch/skills/<name>/` 的软链,不要在 Agent 目录创建副本。
## 创建新的 skill
@@ -35,25 +35,25 @@ skiff add <name> -a cursor -a claude -a codex -a agents -y
3. 创建草稿:
```bash
skiff create <name> --idea "<用户原始想法>" --from-project .
pouch create <name> --idea "<用户原始想法>" --from-project .
```
4. 编辑 `~/.skills/.drafts/<name>/SKILL.md`,完善触发条件、不适用场景、步骤、边界与验证方法。
4. 编辑 `~/.pouch/.drafts/<name>/SKILL.md`,完善触发条件、不适用场景、步骤、边界与验证方法。
5. 编辑同目录的 `README.md`,用面向人类的语言说明用途、准备事项、可直接复制的请求示例、Agent 会做什么以及如何判断完成。README 不应复述 Agent 内部指令。
6. 仅在确有必要时增加 `references/`、`scripts/` 或 `assets/`。不要把项目专属路径、私有业务规则、一次性命令或密钥复制到通用 skill。
7. 运行校验并修复所有问题:
```bash
skiff check <name>
pouch check <name>
```
8. 向用户展示名称、description、README 的人类使用方式、核心步骤和验证方式。获得确认后再转正:
```bash
skiff finalize <name>
pouch finalize <name>
```
转正不会自动 commit、push 或安装。用户明确要求后再执行 `skiff publish` 或 `skiff add`。
转正不会自动 commit、push 或安装。用户明确要求后再执行 `pouch publish` 或 `pouch add`。
## 问题或优化回流
@@ -63,35 +63,35 @@ skiff finalize <name>
2. 判断归属:
- 通用工作流、触发条件或验证缺陷:回流 builtin skill。
- 仅当前项目成立的命令、路径、业务规则:留在项目文档或项目配置,不写回通用 skill。
- CLI 安装、软链或校验行为异常:修改 `~/.skills/skiff/` 中的 CLI 和测试。
- CLI 安装、软链或校验行为异常:修改 `~/.pouch/pouch/` 中的 CLI 和测试。
- 第三方 skill:不要复制成 builtin skill 或直接改安装目录;整理证据反馈上游,除非用户明确决定维护 fork。
3. 确认真实来源。Agent 目录通常是软链,builtin skill 的 SSOT 固定为:
```text
~/.skills/skills/<name>/
~/.pouch/skills/<name>/
```
4. 修改 SSOT。行为修复应先补能复现问题的测试或示例,再改 `SKILL.md`、引用文件或脚本。
5. 校验并在原项目重跑最初失败的场景:
```bash
skiff check <name>
pouch check <name>
```
6. 汇报修改内容、验证结果和影响范围。只有用户明确要求提交或推送时才运行:
```bash
skiff publish skills/<name> -m "update <name>" --push
pouch publish skills/<name> -m "update <name>" --push
```
软链正确时无需重新安装;SSOT 保存后项目立即读取新内容。
## 安装与维护
安装本项目的 `skiff` skill 到所有 Agent:
安装本项目的 `pouch` skill 到所有 Agent:
```bash
skiff bootstrap
pouch bootstrap
```
安装其他 skill:
@@ -99,51 +99,51 @@ skiff bootstrap
```bash
# 当前项目
cd ~/code/my-app
skiff add discussion-notes -a cursor -y
pouch add discussion-notes -a cursor -y
# 全局(所有项目)
skiff add discussion-notes -a cursor -g -y
pouch add discussion-notes -a cursor -g -y
# 多个 agent
skiff add discussion-notes -a cursor -a codex -g -y
pouch add discussion-notes -a cursor -a codex -g -y
```
catalog source既可以指向单个 skill,也可以指向包含多个 skill 目录的
collection。安装 collection 全部内容或其中一个:
```bash
skiff add waza -a codex -g -y
skiff add waza/think -a codex -g -y
pouch add waza -a codex -g -y
pouch add waza/think -a codex -g -y
```
`skiff select` 会把 collection 显示为两级菜单:选择 `waza` 仓库会选中其
`pouch select` 会把 collection 显示为两级菜单:选择 `waza` 仓库会选中其
全部子 skill,也可以只选择 `waza/think`、`waza/ui` 中的若干项。
普通 `skiff select` 只向项目安装,并只读显示每个 Agent 的全局安装状态;
`skiff select -g` 只向全局安装。取消已勾选项不会卸载,卸载继续使用
`skiff remove`。
普通 `pouch select` 只向项目安装,并只读显示每个 Agent 的全局安装状态;
`pouch select -g` 只向全局安装。取消已勾选项不会卸载,卸载继续使用
`pouch remove`。
卸载:
```bash
skiff remove discussion-notes -a cursor -y # 当前项目
skiff remove discussion-notes -g -a cursor -y # 全局
skiff rm discussion-notes -g -y # rm 别名
pouch remove discussion-notes -a cursor -y # 当前项目
pouch remove discussion-notes -g -a cursor -y # 全局
pouch rm discussion-notes -g -y # rm 别名
```
浏览可用自研 skill:
```bash
skiff add --list
pouch add --list
```
使用 Skill 自带模板初始化项目状态:
```bash
skiff init ack
skiff init ack --project ~/app
pouch init ack
pouch init ack --project ~/app
```
`skiff` 只负责可靠地生成项目状态文件,不复制或链接 Skill。需要分析项目并完善
`pouch` 只负责可靠地生成项目状态文件,不复制或链接 Skill。需要分析项目并完善
ACK 配置、检查接入状态或
运行三角色闭环时,显式调用全局 `/ack` skill。
@@ -153,22 +153,22 @@ ACK 配置、检查接入状态或
| 场景 | 工具 |
|------|------|
| 自研 skill(~/.skills) | **skiff** |
| 自研 skill(~/.pouch) | **pouch** |
| 社区 skill(GitHub 任意仓库) | `npx skills add` |
---
## 命令对照
| skiff | 说明 |
| pouch | 说明 |
|-------|------|
| `bootstrap` | 将本项目的 `skiff` skill 全局安装到所有 Agent |
| `update` | 在 `~/.skills` 执行 `git pull`,更新 skiff 自身 |
| `bootstrap` | 将本项目的 `pouch` skill 全局安装到所有 Agent |
| `update` | 在 `~/.pouch` 执行 `git pull`,更新 pouch 自身 |
| `add <name> [-g] [-a AGENT...] [-y]` | 安装 |
| `remove <name> [-g] [-a AGENT...] [-y]` | 卸载(`rm` / `r` 别名) |
| `add --list` | 列出可用自研 skill |
| `publish [paths] -m MSG [--push]` | git add / commit / push |
| `list` | 列出 ~/.skills 目录结构 |
| `list` | 列出 ~/.pouch 目录结构 |
| `status` | 查看软链安装状态 |
| `create <name> --idea TEXT [--from-project PATH]` | 创建自研 skill 草稿 |
| `check <name>` | 校验草稿或正式 skill |
@@ -179,7 +179,7 @@ ACK 配置、检查接入状态或
## 注意
- 不要在 `project/.agents/skills/` 里直接改文件;应改 `~/.skills/skills/` 再 `publish`
- 未完成的内容保留在 `~/.skills/.drafts/`,不要直接放进正式 `skills/`
- 不要在 `project/.agents/skills/` 里直接改文件;应改 `~/.pouch/skills/` 再 `publish`
- 未完成的内容保留在 `~/.pouch/.drafts/`,不要直接放进正式 `skills/`
- symlink 正确时,**不需要 reinstall**;保存 SSOT 后各项目自动读到新内容
- 社区 skill 用 `npx skills add`,不要用 skiff `catalog add` 除非团队要 pin 版本
- 社区 skill 用 `npx skills add`,不要用 pouch `catalog add` 除非团队要 pin 版本