diff --git a/skills/ack/SKILL.md b/skills/ack/SKILL.md index 41ba86d..5c6494f 100644 --- a/skills/ack/SKILL.md +++ b/skills/ack/SKILL.md @@ -1,97 +1,58 @@ --- name: ack description: >- - 初始化、检查并运行 ACK 三角色协作闭环。仅在用户显式调用 /ack 或 $ack,并要求 - 初始化 ACK、检查 .pouch/ack 配置、按 ACK 规划需求或修复 bug、指挥 - Coordinator/Developer/Test 工作,配置测试环境与发版方式,重新部署测试环境 - (内部调用 deployer),发布版本,或运行回归测试时使用。 + 初始化、检查并运行 ACK 三角色闭环。仅在用户显式调用 /ack 或 $ack,并要求 + 初始化 ACK、检查 .pouch/ack、按 ACK 做需求或修 bug、指挥 + Coordinator/Developer/Test、配置或运行测试环境与发版、或跑回归时使用。 --- # ACK 项目协作入口 -本 Skill 是 ACK 的完整能力包:`references/` 保存通用规范,`templates/` 保存项目 -状态模板,`scripts/` 保存校验工具。目标项目只在 `.pouch/ack/` 保存 `project.md`、 -`tasks.yaml`、`knowledge.yaml`、默认关闭的 `delivery.yaml` 和空的 -`regression.yaml`,不要复制或链接 Skill 内容。 +项目只在 `.pouch/ack/` 保存 `project.md`、`tasks.yaml`、`knowledge.yaml`、 +`delivery.yaml` 和 `regression.yaml`。不要复制 Skill 内容,不要修改 `AGENTS.md`、 +`CLAUDE.md`。 -开始时解析当前 `SKILL.md` 所在目录,记为 ``。所有通用规范、模板和 -脚本都相对此目录访问,不依赖固定的全局安装路径。 +开始时解析当前 `SKILL.md` 所在目录为 ``。优先 +`git rev-parse --show-toplevel` 作为项目根。 ## 选择模式 -- 用户要求初始化、接入或安装 ACK:执行“初始化”。 -- 用户要求检查 ACK 是否可用、配置是否完整:执行“检查”。 -- 用户要求用 ACK 做需求、修复 bug 或继续任务:执行“工作”。修 bug 不写大 PRD; - 飞书收件仍走本模式。 -- 用户用自然语言说明怎么部署测试环境、怎么发布版本,或要求增加、修改、关闭交付 - 流程:执行“交付配置维护”。测试环境绑定 deployer,发版写在同一份 - `.pouch/ack/delivery.yaml`。 -- 用户要求部署、重新部署测试环境,或按已配置方式开始测试:执行“运行测试环境”。 - 内部加载 deployer skill,不在 ACK 里复制 compose/rsync 命令。 -- 用户要求发布版本:执行“运行版本发布”。 -- 用户要求回归、跑回归测试:执行“运行回归”。先布测试环境,再派 Test 按 - `.pouch/ack/regression.yaml` 用浏览器或 API 执行。 +- 初始化、接入 ACK:执行「初始化」。 +- 检查配置是否完整:执行「检查」。 +- 做需求、修 bug 或继续任务:执行「工作」。修 bug 不写大 PRD。 +- 增改关闭交付、说明怎么布测试环境或发版:执行「交付配置维护」。 +- 部署或重布测试环境:执行「运行测试环境」(加载 deployer,不复制 compose)。 +- 发布版本:执行「运行版本发布」。回归:执行「运行回归」。 +- 任务板使用 Orca 时,编排命令见 [orca-adapter.md](references/orca-adapter.md)。 -始终先解析真实项目根目录。优先使用 `git rev-parse --show-toplevel`;不是 Git -项目时使用用户指定目录或当前目录。不要修改项目的 `AGENTS.md`、`CLAUDE.md` -或其它 Agent 指令文件。 +## 边界 + +- 不覆盖已有 `.pouch/ack`;除用户确认的任务或 delivery profile 外,不擅自提交、推送、创建终端、新 worktree、发布或部署。 +- 不猜测命令、地址、worker handle 或模型名;无法确定写 `n/a`。 +- 不把完整 `tasks.yaml` / `knowledge.yaml` / `regression.yaml` 注入上下文;用对应 `select_*.py`。写回前跑完整校验。 +- 只有 Coordinator 写任务板、知识库、回归目录、`deliveryRuns` 和 `regressionRuns`。`delivery.yaml` 只在「交付配置维护」中改。见 [roles-and-permissions.md](references/roles-and-permissions.md)。 +- 知识检查只经 `run_verification.py` 的 registry ID;不把知识正文拼成 shell。 +- 自动 worker 禁止 full-access、bypass、关闭 sandbox、Grok `--yolo` / bypassPermissions。OMP `--approval-mode yolo` 只用于 OMP 审批(workspace-write → yolo,read-only → always-ask),禁止 `--auto-approve`,不适用于其它 backend。 +- 无清理证明不复用 worker;无密钥 `receiptHash` 或 Orca live metadata 不能授权复用。当前 Orca 走 fresh。`indeterminate` / `reconcile required` 不直接重试。 +- 产品失败才占三轮;环境失败写 `environmentIncidents`。见 [optimization-method.md](references/optimization-method.md) §4。 ## 初始化 -1. 确认 `pouch` 可执行,并检查 `/.pouch/ack` 是否存在。 -2. 不存在时执行: +1. 确认 `pouch` 可执行。`.pouch/ack` 不存在则 `pouch init ack --project `;已存在则不覆盖、转入「检查」。 +2. 按 [init-new-project.md](references/init-new-project.md) 完善项目状态。不从 README/CI 猜测并启用交付或知识;初始化 **不** 自动初始化 deployer 或 builder。 +3. 运行: - ```bash - pouch init ack --project - ``` +```bash +python3 /scripts/validate_tasks.py .pouch/ack/tasks.yaml +python3 /scripts/validate_knowledge.py .pouch/ack/knowledge.yaml \ + --tasks .pouch/ack/tasks.yaml +python3 /scripts/validate_delivery.py .pouch/ack/delivery.yaml \ + --tasks .pouch/ack/tasks.yaml --project-root +python3 /scripts/validate_regression.py .pouch/ack/regression.yaml \ + --tasks .pouch/ack/tasks.yaml +``` - 该命令从本 Skill 的 `templates/` 生成项目状态,不会在项目中创建 Skill - 软链接或资源副本。 -3. 如果 `.pouch/ack` 已存在,不重复初始化、不覆盖文件;转入“检查”。旧项目只有 - `project.md` 与 `tasks.yaml` 时,先报告缺少 `knowledge.yaml`。用户授权后, - 从 `templates/knowledge.template.yaml` 生成这个缺失文件并替换项目名和时间;若 - `tasks.yaml` 尚无 `project.knowledgeFile`,同时只补 - `.pouch/ack/knowledge.yaml` 这一项。不要重跑 `pouch init`,也不要改写其它已有 - 项目状态。 -4. 读取项目的公开配置和文档,例如 README、语言清单、包管理清单、测试配置与 - CI,确定项目名、技术栈、源码/规格/测试路径及真实可执行命令。 -5. 完善 `.pouch/ack/project.md`: - - 用实际项目值替换全部占位符。 - - 无服务地址时把 Base URL 写为 `n/a`,不要虚构端口。 - - 无法从项目证据确定的命令写为 `n/a`,并在结果中列为待配置项。 - - 只写项目差异,不复制 `references/` 中的通用规范。 -6. 完善 `.pouch/ack/tasks.yaml` 的项目信息。纯初始化且用户没有提供真实任务时, - 删除模板示例任务并保留 `tasks: []`;不要虚构需求或缺陷。 - 项目状态固定从当前项目根的 `.pouch/ack/` 推导,不写入 `repoPath` 或 `devWorktree`; - worker 默认在 `--project-root`(权威状态目录)工作,不再配置 - `allowedWorktrees` 白名单(v0.19 起废弃);需要隔离 worktree 时由 Coordinator 在 - 派发时显式指定。旧任务板中的 `repoPath`、`devWorktree` 仅兼容读取。 -7. 检查 `.pouch/ack/knowledge.yaml`。新项目没有已验证的项目经验时保留 - `verificationRegistry: {}` 与 `entries: []`,不从聊天、README 或单次失败中 - 猜测并激活知识。 -8. 检查 `.pouch/ack/delivery.yaml`。新项目保留 `enabled: false`、空能力表和空 profile; - 不从 README 或 CI 猜测、启用交付。旧项目没有该文件时仍可继续使用原 ACK - 闭环;只有用户明确要求配置交付时,才按“交付配置维护”补齐。 -9. 检查 `.pouch/ack/regression.yaml`。新项目保留 `cases: []`。旧项目没有该文件时仍 - 可继续原闭环;用户授权后从 `templates/regression.template.yaml` 生成,并只补 - `project.regressionFile` 与顶层 `regressionRuns: []`。不要从聊天虚构用例。 -10. 更新 `updatedAt`,并运行: - - ```bash - python3 /scripts/validate_tasks.py .pouch/ack/tasks.yaml - python3 /scripts/validate_knowledge.py .pouch/ack/knowledge.yaml \ - --tasks .pouch/ack/tasks.yaml - python3 /scripts/validate_delivery.py .pouch/ack/delivery.yaml \ - --tasks .pouch/ack/tasks.yaml --project-root - python3 /scripts/validate_regression.py .pouch/ack/regression.yaml \ - --tasks .pouch/ack/tasks.yaml - ``` - -11. 检查 `project.md`、`tasks.yaml`、`knowledge.yaml`、`delivery.yaml` 与 - `regression.yaml` 是否仍有 `<...>` 占位符。 -12. 按下面格式报告。结构校验通过且必填项目事实完整时才称「完成」;否则称 - 「部分完成」或「阻塞」并列出待配置项。除非用户明确要求,不提交、不推送。 - 初始化 ACK **不**自动初始化 deployer 或 builder。 +4. 检查上述文件是否仍有 `<...>` 占位符。结构校验通过且必填项目事实完整才称「完成」。除非用户明确要求,不提交、不推送。 ```text ## ack 初始化:完成 | 部分完成 | 阻塞 @@ -104,237 +65,42 @@ description: >- ## 检查 -1. 检查以下路径: - - `.pouch/ack/project.md` - - `.pouch/ack/tasks.yaml` - - `.pouch/ack/knowledge.yaml` - - `.pouch/ack/delivery.yaml`(旧项目可无;存在或被任务板引用时必须校验) - - `.pouch/ack/regression.yaml`(旧项目可无;存在或被任务板引用时必须校验) - 需要查看任务内容时,使用 `/scripts/select_tasks.py` 解析完整任务板并 - 只输出项目配置、摘要和可工作任务;不要用 `cat`、整文件 `sed` 或等价方式把完整 - `tasks.yaml` 注入上下文。完整性仍由校验器检查。 -2. 读取 `/VERSION`,对比 `tasks.yaml` 的 `ackVersion`。旧项目只有 - `kitVersion` 时仍可读取,但建议迁移为 `ackVersion`。`ackVersion` 必须是合法 - SemVer;从 `0.10.0` 起 `project.orchestration` 与顶层 `workerReceipts` 必须同时 - 存在。 -3. 查找未替换占位符,并核对项目根、覆盖层路径、Developer 白盒命令、Test - 黑盒命令和 Base URL。 -4. 使用 `/scripts/validate_tasks.py` 校验任务板,使用 - `/scripts/validate_knowledge.py .pouch/ack/knowledge.yaml --tasks - .pouch/ack/tasks.yaml` 校验项目知识和跨文件引用。如果存在交付配置或任务板声明了 - `project.deliveryFile`,再使用 `/scripts/validate_delivery.py - .pouch/ack/delivery.yaml --tasks .pouch/ack/tasks.yaml --project-root ` - 校验交付能力、顺序、安全边界和跨文件引用。如果存在回归目录或任务板声明了 - `project.regressionFile`,再使用 `/scripts/validate_regression.py - .pouch/ack/regression.yaml --tasks .pouch/ack/tasks.yaml` 校验用例与跨文件引用。 - 只报告证据明确的问题,不因旧项目缺少可选交付或回归配置而宣称失败。 -5. 若存在 `project.bugIntake`,运行 - `python3 /scripts/feishu_bug_intake.py check .pouch/ack/tasks.yaml`。 - 它只接受 `feishu-base` 和显式 profile;详细的飞书配置、凭据初始化和读取方式见 - `references/feishu-bug-intake.md`。 -6. 检查知识引用能解析到固定 revision,candidate 仍留在任务证据中,且 - `stale`、`superseded` 和 `archived` 不会被当作可派发的 `active` 知识。 -7. 若存在 `project.orchestration`,检查 profile、model allowlist、默认 profile、 - 允许 worktree、顶层 `workerReceipts` 与 `dispatch.developer/test` 的引用;receipt - 必须绑定当前 ACK task、同一 role/profile/attempt,`receiptId` 与 `attemptId` - 必须同时为空或同时填写。 - 缺少结构化路由的旧任务板只能使用手动模式,不能自动创建 worker。 -8. 检查不会自动修复或覆盖现有配置;用户明确要求修复后再修改。 -9. 若 `delivery.yaml` 已把 `intents.testEnvironment` 写成 `{via: deployer, env: }`, - 只读运行已安装 deployer skill 的 `scripts/deploy/check.py --project `。 - 未通过时列入待配置,加载 deployer skill 的「检查」说明;不要在 ACK 里复制 - compose/rsync 命令,也不要静默初始化 deployer。 -10. 用与「初始化」相同的报告格式,标题改为 `## ack 检查:…`。 +只读,不自动修复。核对清单见 [adoption-checklist.md](references/adoption-checklist.md)。用 `select_tasks.py` 看配置;跑与「初始化」相同的四个校验器。对比 `VERSION` 与 `ackVersion`(旧 `kitVersion` 仍可读);从 `0.10.0` 起 `project.orchestration` 与 `workerReceipts` 必须同时存在。旧项目可无 delivery/regression,存在或被引用时必须校验。若有 `bugIntake` 再跑 `feishu_bug_intake.py check`。若测试环境走 deployer,只读跑其 `check.py`;未通过列入待配置,不要复制 compose 或静默初始化 deployer。用同一报告格式,标题改为 `## ack 检查:…`。 ## 工作 -1. 若 `.pouch/ack` 不存在,停止并建议先用 `/ack` 初始化;不要静默初始化。 -2. 依次读取: - - `.pouch/ack/project.md` - - 运行 `python3 /scripts/select_tasks.py .pouch/ack/tasks.yaml`,只读取 - `project`、`summary` 和默认可工作状态的任务;已知当前任务时传 - `--task-id `。选择器会解析并校验完整任务板,并只附带选中任务引用的 - receipt 与 delivery run。命中超过默认预算时用 `--task-id` / `--status` 缩小, - 不直接回退为输出完整 `tasks.yaml`。 - - 通过 `/scripts/select_knowledge.py` 从 - `.pouch/ack/knowledge.yaml` 选择的当前任务相关 `active` 条目 - - `/references/kickoff.md` - - kickoff 指定且与当前任务相关的 references 文件 - - 若 `tasks.yaml.project.deliveryFile` 存在,再读取该 `delivery.yaml` 和 - `/references/delivery.md` - - 若 `tasks.yaml.project.regressionFile` 存在,再读取该 `regression.yaml` 和 - `/references/regression.md` -3. 当前会话担任 Coordinator,遵守项目覆盖层中的命令、路径权限、模型路由和 - worker 启动规则。项目覆盖层优先于通用示例命令。按 scope 推荐相关 `active` - 知识,经确认后把固定 revision 的显式 `knowledgeRefs` 写入当前任务上下文; - 不全量注入知识库。 - `project.bugIntake.workflow` 为 `clarified-writeback-v1`(推荐)或 - `reviewed-writeback-v1`(兼容旧项目)时,按 - `references/feishu-bug-intake.md` 把飞书作为审核前的唯一协作区:先运行 check/plan, - 读取用户填写的 Bug。新工作流中,用户只维护标题、详细描述和附件;Coordinator 根据 - 来源事实与项目上下文整理问题说明、期望效果和可观测验收标准,不在收件箱写修复逻辑, - 只通过安全适配器写回同一飞书记录并回读确认。用户反馈后继续只在飞书修订。 - 用户针对当前 `draftRevision` 明确审核通过并亲自在飞书把状态改为 `已确认` 前,不创建 - 或刷新 `tasks.yaml` 任务、不启动 worker、不派发 Developer/Test,也不修改应用代码。 - Coordinator 不得自行写入 `已确认`。审核通过后重新读取,要求 revision 与批准值完全 - 一致,才通过 `import-approved` 生成规范 `taskDraft`,原样写入最终版本、 - `source.workflow`、`source.approvedRevision` 与 `source.approvedPayloadHash`;校验器重算 - payload hash 通过后,再用 `mark-imported` 把最终任务 ID 与同一 revision 写回飞书, - 才进入三角色闭环。未声明 workflow 的旧八字段配置只按 - `read-only-v1` 兼容,不得写回; - 标题、详细描述和附件是来源事实,不得把 Coordinator 推断伪装成用户原文;整行空白 - 记录按批次 warning 跳过。 - 按每条记录的 `sourceRef` 去重:仅 `open` 任务可刷新描述; - `dispatched`、`fixed_by_dev`、`retesting`、`failed_retest`、`verified`、`blocked` 和 - `leftover` 只报告来源漂移,绝不覆盖;来源消失或读取失败时绝不删除已有任务。 -4. 新需求先写产品文档、任务拆分与可观测验收信号,更新 `tasks.yaml` 并校验, - 然后交给用户确认。修 bug 写短问题说明、复现步骤和可观测验收,不写大 PRD; - Developer 先补会失败的用例再修。若启用了交付,必须默认把 `defaultProfile`、 - 目标、停止点和需要审批的步骤放入同一份计划,不能静默省略。用户可明确取消 - 本轮交付;确认前不派发实现,也不执行交付。 -5. 创建或更换 worker 时,只使用 - `/scripts/launch_worker.py plan|launch` 读取 - `tasks.yaml.project.orchestration` 的 profile。不得直接执行 - `orca terminal create --command`,不得接受或拼接自由 command、额外 argv、 - executable、env 或 cwd。必须先审阅 `plan.launchFingerprint`,再把它作为 - `launch --expected-launch-fingerprint` 传入。派发前先寻找同一 ACK 运行内的空闲 - worker;只有角色、profile、worktree 和启动身份仍完全匹配,且后端能清理历史消息、 - 返回可核对的新会话身份时才复用。不得复用正在工作、等待回报或状态不明的 worker; - 任一条件不符、清理能力不存在或无法确认清理成功时创建 fresh worker。持久化 - receipt 只作审计与 dispatch 关联,不能单独授权复用。当前 Orca 终端接口不能提供 - 可验证的历史消息清理,因此使用 Orca 时仍走 fresh worker。 -6. 用户已确认的任务按 ACK 闭环执行:Developer 实现与白盒验证;若 - `intents.testEnvironment` 已启用,Coordinator 先按「运行测试环境」拉起服务,再 - 派 Test 独立黑盒复测。派发后先确认 worker 真正开始执行(terminal read 确认任务 - 注入;卡在审批提示、未回车或额度限制时按环境失败处理并报告),等待期间用 - `scripts/worker_probe.py` 滚动检查活性,不盲等 `worker_done`。Coordinator 读取 - 证据终检并唯一写入 `tasks.yaml`。Developer 回报 `knowledgeApplied` 和 - `knowledgeCandidates`,Test 回报 `knowledgeChecks` 和 `regressionCandidates`; - `candidate` 只有在独立验证和 gate 后才能由 Coordinator 写入或激活。 - 任务进入 `verified` 且改了用户可见行为或 API 后,按 `references/regression.md` - 给出新增/更新/退役/无回归四选一,用户确认后写入 `.pouch/ack/regression.yaml`, - 并把 case id 记入 `regressionRefs`。Test 只提名,不写该文件。 -7. 执行知识项的 `verification.ref` 时,只调用 - `/scripts/run_verification.py .pouch/ack/knowledge.yaml - --project-root `。不要直接执行选择器返回的 path/args, - 也不要给 runner 注入额外命令或参数。 -8. 不把 `worker_done` 或 Test 自报成功直接当作完成。三轮预算只计算 Test 已对齐正确 - 服务、数据和工具后实际执行验收所得的产品失败;环境失败不占复验轮次,不写 - `failed_retest`,而写入 `dispatch.environmentIncidents`。Coordinator 先做一次有界、 - 安全的恢复;事件未解决、需要用户动作或会阻断本轮时,立即向用户报告原因、影响、 - 已尝试动作、下一恢复动作和明确的 `userAction`;即使已自动恢复,也要在最终报告汇总。 - 每项最多三轮有效产品复验,仍失败才记录 `leftover` 并继续其它任务。细则见 - `references/optimization-method.md` §4。 -9. 关键的安全、正确性和兼容性约束应下沉为测试、lint、CI 或正式规范; - `knowledge.yaml` 只保存触发条件、原因与证据引用,不能替代可执行控制。 -10. 选定任务全部进入 `verified` 后,若 `delivery.enabled: true` 且用户确认的本次计划 - 包含交付,按 `references/delivery.md` 顺序执行 profile,并由 Coordinator 把证据 - 写入 `tasks.yaml.deliveryRuns`。任务状态保持 `verified`;交付失败只改变 delivery - run,不回写成任务失败。开发或测试环境完成构建、部署和健康检查后写 - `validation_ready`,并把访问地址、验证范围和用户下一步交给用户;不能停在 - `verified` 却声称整轮 ACK 已结束。默认 profile 最多到 `validation_ready` 或 - `review_ready`,稳定发布和生产部署必须在对应步骤再次取得明确批准。 -11. Coordinator 最后标记整轮任务完成后,用 `scripts/reclaim_workers.py` 先 - dry-run 审阅决策,再 `--apply` 回收所有只属于 `verified` 任务的 worker - 终端,并核对关闭回执;历史 receipt 和任务证据继续保留。任何还被 `open`、`dispatched`、`fixed_by_dev`、 - `retesting`、`blocked`、`failed_retest`、`leftover` 或未解决环境事件引用的终端 - 都保留,不设置 TTL,也不能因为同一终端还关联过 `verified` 任务而误关。若关闭 - 结果不确定,记录并报告,不重复关闭或伪报已回收。 +1. `.pouch/ack` 不存在:停止并建议先 `/ack` 初始化;不要静默初始化。 +2. 读 `project.md`;用 `select_tasks.py`(已知任务加 `--task-id`)和 `select_knowledge.py` 取当前任务相关 `active` 条目。超预算时缩小选择,不回退为完整 yaml。 +3. 新需求或尚未确认的计划:读 [kickoff.md](references/kickoff.md)。修 bug 写短问题说明、复现和可观测验收,不写大 PRD。 +4. 用户已确认后按 [closed-loop.md](references/closed-loop.md) 执行。当前会话担任 Coordinator,不亲自写代码或跑测试。 +5. 存在 `project.bugIntake` 时先完成「飞书收件」。创建或更换 worker 走「启动 worker」。若 `intents.testEnvironment` 已启用,派 Test 前先走「运行测试环境」。 +6. 知识 `verification.ref` 只经 `run_verification.py`。不把 `worker_done` 或 Test 自报成功当作完成。环境失败先有界恢复并报告 `userAction`;三轮产品失败记 `leftover`。 +7. 任务 `verified` 且改了可见行为或 API 后,转入「运行回归」收获用例。若本次计划含交付,再走对应交付模式;默认最多到 `validation_ready` 或 `review_ready`。 +8. 整轮完成后 `reclaim_workers.py` 先 dry-run 再 `--apply`,只回收仅属于 `verified` 任务的 worker。关闭结果不确定则记录,不伪报。 + +## 飞书收件 + +若存在 `project.bugIntake`,读 [feishu-bug-intake.md](references/feishu-bug-intake.md)。用户针对当前 `draftRevision` 明确审核通过并亲自把飞书状态改为 `已确认` 前:不创建或刷新任务、不启动 worker、不派发、不改应用代码。Coordinator 不得自行写入 `已确认`。未声明 workflow 的旧配置只按 `read-only-v1`,不得写回。来源消失或读取失败时不删除已有任务。 + +## 启动 worker + +只使用 `scripts/launch_worker.py plan|launch`。不得直接 `orca terminal create --command`,不得拼接自由 command、argv、executable、env 或 cwd。读 [model-routing.md](references/model-routing.md)。先审阅 `plan.launchFingerprint`,再作为 `launch --expected-launch-fingerprint` 传入。派发文案用 [prompt-templates.md](references/prompt-templates.md)。派发后 terminal read 确认已开始;卡在审批、未回车或额度限制按环境失败处理。等待期间用 `scripts/worker_probe.py`,不盲等 `worker_done`。 ## 交付配置维护 -1. 读取 `references/delivery.md`、deployer skill、模板、schema、现有 - `delivery.yaml`、项目构建/发布入口和 CI。测试环境写成 - `intents.testEnvironment: {via: deployer, env: }`。若 - `.pouch/deployer/` 不存在或 deployer `check.py` 未通过:停止,加载 - deployer skill 的「初始化」,不要在 ACK 里复制 compose/rsync 命令。发版仍指向 - 本文件的 profile。不要拆成第二份文档。配置只引用仓库内脚本或声明式工具 - target,不保存 shell。本地 `npm run dev` / `go run` 写在 `project.md` 的 - Developer 白盒命令里,不算测试环境部署。 -2. 若旧项目首次启用,生成 `.pouch/ack/delivery.yaml`,在 `tasks.yaml.project` 增加 - `deliveryFile: .pouch/ack/delivery.yaml`,并增加顶层 `deliveryRuns: []`;不改写其它 - 项目状态。首次生成保持 `enabled: false`,先展示 diff 和解析出的执行顺序。 -3. 运行 delivery、tasks 和跨文件校验;需要的脚本不存在、不可执行、引用不完整或 - 涉及凭据正文时 fail closed。凭据只写 secret 名称,值由外部环境提供。 -4. 用户确认后才把配置设为启用。配置修改只影响下一次 delivery run;已确认或正在 - 执行的 run 使用开始时审阅的 commit/config revision 快照,不能借当前分支修改 - 扩大权限。 +读 [delivery.md](references/delivery.md)。测试环境写成 `{via: deployer, env: }`;`.pouch/deployer/` 未就绪则停止并加载 deployer「初始化」,不在 ACK 里复制 compose。发版写在同一份 `delivery.yaml`,不保存 shell。本地 `npm run dev` / `go run` 不算测试环境。旧项目首次启用只补文件指针与 `deliveryRuns: []`,保持 `enabled: false`,用户确认后才启用。进行中的 run 使用开始时的 commit/config 快照。 ## 运行测试环境 -1. 读取 `.pouch/ack/delivery.yaml`、`references/delivery.md` 和 deployer skill 的 - `SKILL.md`。 -2. `enabled` 不为 true,或 `intents.testEnvironment` 为 null:停止,请用户说明如何 - 部署测试环境,转入交付配置维护。不猜测编译或启动命令。 -3. `intents.testEnvironment` 必须是 `{via: deployer, env: }`。若仍是旧的 - profile ID 字符串:停止,展示迁移说明,转入交付配置维护。不要执行 ACK - delivery profile 来布测试环境。 -4. 不要求任务已 `verified`。按 deployer 的项目内环境布局操作 - `.pouch/deployer/`:list 确认服务,再按服务 sync + up(或用户要求的 - recreate),并用 ps/logs/健康检查验证。不要复制 deployer 脚本,不要发明 - 第二套 compose 命令。 -5. 把访问地址交给用户或随后的 Test 黑盒。证据写入 `deliveryRuns`, - `intent: testEnvironment`,`profile` 记 `deployer-`,`taskIds` 可为空。 -6. 派发 Test 前若该 intent 已启用,必须先完成本步骤。deployer 未安装、环境目录 - 不存在或 `check.py` 未通过:停止,加载 deployer skill 的「初始化」,报告 - `userAction`,不把环境失败写成产品失败,也不要在 ACK 里发明 compose 命令。 - 健康检查失败同样 fail closed。 +读 `delivery.yaml` 与 [delivery.md](references/delivery.md),并加载 deployer。`enabled` 非 true 或 intent 为 null:停止,转入交付配置维护。intent 必须是 `{via: deployer, env: }`;旧 profile ID 字符串要先迁移。不要用 ACK delivery profile 布环境,不猜测启动命令。不要求任务已 `verified`。对 `.pouch/deployer/` 按 deployer:list → 按服务 sync+up → 健康检查。证据写入 `deliveryRuns`(`intent: testEnvironment`,`profile: deployer-`)。未安装、缺目录、`check.py` 失败或健康检查失败:fail closed,报告 `userAction`,不记产品失败。 ## 运行回归 -1. 若 `.pouch/ack` 不存在,停止并建议先初始化。 -2. 若没有 `.pouch/ack/regression.yaml` 或 `project.regressionFile`:停止,用户授权后 - 从模板生成空文件并只补任务板指针与 `regressionRuns: []`。 -3. 用 `scripts/select_regression.py` 读取 active 用例(默认 `--suite smoke`;用户 - 指定 full 或 case id 时缩小范围)。没有命中用例时停止并说明先收获用例。 - 不要把完整 `regression.yaml` 注入上下文。细则见 `references/regression.md`。 -4. 先执行「运行测试环境」。 -5. 当前会话担任 Coordinator:按 Test profile 启动独立 Test worker,派发回归清单、 - Base URL 和每条 case 的 surface/steps/expected。Coordinator 不亲自点浏览器或 - 打 API。 -6. Test 按 `surface` 执行:`browser` 必须走真实交互,不得改成只打 API。逐条对照 - `expected` 回报。环境失败记环境事件,不记产品失败。 -7. Coordinator 终检后写入 `regressionRuns`。失败只报告,不自动派 Developer,不占 - 任务三轮预算。用户明确要求修复时再按修 bug 为每条失败开任务。 +读 [regression.md](references/regression.md)。缺目录则停止;用户授权后从模板生成空文件并只补指针与 `regressionRuns: []`。用 `select_regression.py` 读 active 用例(默认 `--suite smoke`);无命中则停止。先执行「运行测试环境」,再派独立 Test worker。Coordinator 不亲自点浏览器或打 API;`browser` 不得改成只打 API。终检写入 `regressionRuns`。失败不自动派 Developer,不占三轮预算。任务 `verified` 后给出新增/更新/退役/无回归四选一,用户确认后写入;Test 只提名。 ## 运行版本发布 -1. 读取同一份 `.pouch/ack/delivery.yaml` 与 `references/delivery.md`。 -2. `enabled` 不为 true,或 `intents.release` 为 null:停止,请用户说明如何发版, - 写入同一文件后再执行。 -3. 按该 profile 顺序执行。stable 发布和生产部署的 `approval` 不能用口头「发版」 - 代替。 -4. 证据写入 `deliveryRuns`,`intent: release`;绑定了任务时 `taskIds` 仍只能引用 - `verified` 任务。 - -## 边界 - -- 不修改或追加任何项目 Agent 指令文件,包括 `AGENTS.md`。 -- 不在项目中维护第二份 ACK 通用规范、模板或任务 schema。 -- 不猜测项目命令、服务地址、worker handle 或模型名称。 -- 不把 full-access、bypass、Grok `--yolo` / bypassPermissions、关闭 sandbox - 或项目内“授权”字段当成 v0.10 自动 worker 的合法配置;这些 CLI 绕过标志 - 当前一律 fail closed。Grok worker 由 launcher 固定带 `--always-approve`, - 仍必须带 sandbox。 -- OMP worker 使用结构化 `--model`、`--thinking` 和 `--approval-mode` 参数。 - `--approval-mode yolo` 是 OMP worker 的审批模式,不是 CLI 绕过标志:规则层 - 直接允许并默认启用(workspace-write → yolo、read-only → always-ask); - 仍禁止 `--auto-approve`,也不适用于 codex/cursor-agent/grok。 -- 不把无密钥 `receiptHash` 或 Orca live metadata 当作旧终端的启动 attestation; - 没有可信空闲状态、配置匹配和历史消息清理证明时不复用既有 worker。 -- launcher 返回 `indeterminate` 或 `reconcile required` 时,不直接重试;先按 - launch ID、外部 record 和 Orca live state 完成人工核对。 -- 不覆盖已有 `.pouch/ack` 文件;除用户确认的 ACK 任务或 delivery profile 外,不擅自 - 提交、推送、创建终端、新 worktree、发布产物或部署。 -- 只有 Coordinator 写 `tasks.yaml`、`knowledge.yaml`、`regression.yaml`、 - `deliveryRuns` 和 `regressionRuns`;Developer 与 Test 只读,只能通过回报提名 - 或验证。`delivery.yaml` 只在显式的交付配置维护中修改。 -- 不把知识正文或选择器输出拼成 shell;知识检查只能通过 `run_verification.py` - 按 registry ID 执行。不自动修改 `AGENTS.md`、`CLAUDE.md` 或其它 Agent 指令文件。 -- 不把完整 `tasks.yaml` 注入上下文;使用 `select_tasks.py` 获取有预算的项目与任务 - 视图,写回前仍运行完整任务板校验。 -- 项目只保存 `.pouch/ack/project.md`、`.pouch/ack/tasks.yaml`、 - `.pouch/ack/knowledge.yaml`、可选的 `.pouch/ack/delivery.yaml` 和可选的 - `.pouch/ack/regression.yaml`;通用资源始终从当前 ACK Skill 目录读取。 -- 不把完整 `regression.yaml` 注入上下文;使用 `select_regression.py` 获取有预算的 - 用例视图,写回前仍运行完整校验。 +1. 读同一份 `delivery.yaml` 与 [delivery.md](references/delivery.md)。 +2. `enabled` 不为 true,或 `intents.release` 为 null:停止,先做交付配置维护。 +3. 按该 profile 顺序执行。stable 发布和生产部署的 `approval` 不能用口头「发版」代替。 +4. 证据写入 `deliveryRuns`,`intent: release`;绑定了任务时 `taskIds` 仍只能引用 `verified` 任务。 diff --git a/skills/ack/references/kickoff.md b/skills/ack/references/kickoff.md index 15c7268..e0c9637 100644 --- a/skills/ack/references/kickoff.md +++ b/skills/ack/references/kickoff.md @@ -1,6 +1,8 @@ # 如何开始一个需求(Kickoff) -从零开一个需求的启动手册。角色/权限见 `roles-and-permissions.md`,闭环见 `closed-loop.md`,模型见 `model-routing.md`。 +从零开一个需求的启动手册。本文件只覆盖确认前的产品文档、任务拆分与验收信号。 +用户确认后的三角色闭环、飞书收件、启动 worker、交付和回归由 `SKILL.md` 按条件加载, +不要在本文件开头预读其它规范。 --- @@ -18,15 +20,15 @@ ```text 我要做一个新需求:<一句话需求>。 -你作为 ack 的 Coordinator(PM),按 ACK Skill 的 references 规范执行: +你作为 ack 的 Coordinator(PM),按 ACK Skill 执行: 1. 先读 .pouch/ack/project.md,并用 `scripts/select_tasks.py .pouch/ack/tasks.yaml` 读取有预算的 project、summary 和可工作任务;已知任务时传 `--task-id`,不要把 完整 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 与 - references/delivery.md,但不要把配置本身当作执行授权。 + `scripts/select_knowledge.py` 只读取当前任务相关的 active 条目。 + 本 kickoff 只做确认前的产品文档与任务拆分;用户确认后的闭环、飞书、启动 + worker、交付和回归按 ACK Skill 的模式路由按条件加载,不要在本步预读其它 + references。配置本身不是执行授权。 2. 写产品文档到 docs/(PRD / 交互 / 验收),把需求拆成任务,每个任务的验收写成可观测信号(可见文本 / API 结果 / 交互结果)。 3. 按任务 scope 从 knowledge.yaml 推荐 active 知识,确认后把固定 revision 的 knowledgeRefs 写入任务;不要派发 candidate 或全量知识库。 @@ -41,7 +43,7 @@ dispatch 测试独立复测 → 你读证据终检 → 回写 tasks.yaml; 每个任务最多三轮有效产品复验,三轮不过记 leftover 并升级我复盘;环境失败单独 记录、恢复并告诉我下一步,不占产品复验轮次。 -7. 所选任务都 verified 后,按 regression.md 给出新增/更新/退役/无回归,确认后写入 +7. 所选任务都 verified 后,按 SKILL.md「运行回归」给出新增/更新/退役/无回归,确认后写入 .pouch/ack/regression.yaml。只有本次计划包含交付时才按 profile 顺序执行并写 deliveryRuns;启用 delivery 时不能省略 defaultProfile,默认停在 validation_ready 或 review_ready,stable/production 步骤再次向我确认。 @@ -52,7 +54,7 @@ ## 第 1 步:Coordinator 产出(确认前) 1. 产品文档 → `docs/PRD-.md` 等(Coordinator R/W)。 -2. 任务板 → `.pouch/ack/tasks.yaml`,每条任务带 `expected` + `verification`,验收写成可观测信号(见 `optimization-method.md` §1)。 +2. 任务板 → `.pouch/ack/tasks.yaml`,每条任务带 `expected` + `verification`,验收写成可观测信号(可见文本 / API 结果 / 交互结果)。 3. 项目知识 → 从 `.pouch/ack/knowledge.yaml` 按 component、path、dependency、version 和 tag 推荐 `active` 条目,Coordinator 确认后写入固定 revision 的显式 `knowledgeRefs`。candidate 不参与选择。 @@ -86,10 +88,9 @@ python3 /scripts/select_tasks.py .pouch/ack/tasks.yaml \ ## 第 2 步:决定 worktree -见 `closed-loop.md` §「子任务放哪」: - - 需求大 / 要并行 / 要保基线分支干净 → 新建隔离 worktree。 - 小改动 / 串行修复 → 当前 worktree 起子 agent。 +用户确认后的闭环步骤由 SKILL.md「工作」加载,不要在本步预读其它规范。 --- @@ -99,7 +100,7 @@ python3 /scripts/select_tasks.py .pouch/ack/tasks.yaml \ terminal 不能单独授权复用。复用候选必须属于同一轮 ACK、处于空闲状态,且角色、 profile、worktree 与启动身份仍完全匹配;还必须通过受信后端清理历史消息并取得可核对 的新会话身份。当前 Orca 接口缺少该清理证明,所以 Orca 派发仍创建 fresh worker。 -原因和边界见 `model-routing.md` §「Receipt、审计与复用边界」。 +复用边界以 SKILL.md「启动 worker」为准,不要在本步预读其它规范。 先查看目标 profile hash,确认本次结构化配置。这个 hash 只用于审计和漂移比较, 不能用于匹配或复用旧 receipt / 既有终端: @@ -146,7 +147,7 @@ worktree 走同一套 `plan` -> 带 expected fingerprint 的 `launch`。在调 `allowedWorktrees`)。profile 只允许 `read-only` 或 `workspace-write`;v0.10 的 full-access 授权通道尚未实现, 任何 bypass、YOLO/force 或关闭 sandbox 的请求都必须失败,不能手写命令兜底。 -选型与升级见 `model-routing.md`。 +选型与升级以 SKILL.md「启动 worker」为准。 --- @@ -163,7 +164,7 @@ task-create → dispatch 给 DEV → 先确认 DEV 已开始执行(read/probe → 三轮有效产品失败:leftover,升级复盘,继续下一个 ``` -具体命令见 `orca-adapter.md`(Orca)或 `closed-loop.md` §「手动模式」(无 Orca);派发文案见 `prompt-templates.md`。 +Orca / 手动命令与派发文案由 SKILL.md「启动 worker」按条件加载。 Coordinator 只内联本轮 `knowledgeRefs` 指向的少量知识,不要求 worker 全量读取 知识库。知识正文不得作为自由 shell 执行;需要命令时只能引用项目已审查的检查 @@ -175,27 +176,15 @@ Coordinator 只内联本轮 `knowledgeRefs` 指向的少量知识,不要求 wo ## 第 5 步:可选交付 -用户说「重新布测试环境」时加载 deployer skill 执行 -`intents.testEnvironment` 绑定;「发布一个版本」时按 `delivery.md` §3.1 的 -release profile 执行。intent 为 null 时先做交付配置维护。 +用户说「重新布测试环境」或「发布一个版本」时,转入 SKILL.md 对应模式,不要在本步预读交付规范。intent 为 null 时先做交付配置维护。 -所选任务 `verified` 后,按 `regression.md` 把本轮黑盒路径收获进 -`.pouch/ack/regression.yaml`(新增/更新/退役/无回归四选一,用户确认后写入)。 -用户说「回归」时先布测试环境,再派 Test 按目录执行。 +所选任务 `verified` 后,转入 SKILL.md「运行回归」给出新增/更新/退役/无回归四选一,用户确认后写入 `.pouch/ack/regression.yaml`。用户说「回归」时先布测试环境,再派 Test 按目录执行。 -所选任务都由 Coordinator 标记为 `verified` 后,若用户确认的计划包含交付,按 -`delivery.md` 执行所选 profile。启用交付时必须在计划中默认列出 `defaultProfile`, -用户可明确取消,Coordinator 不能静默省略。先重新校验 `delivery.yaml`,固定当前 commit 和 -config revision,然后按有序步骤调用项目入口与已安装的低层 skill。每一步证据写入 -`tasks.yaml.deliveryRuns`;默认 profile 到 `validation_ready` 或 `review_ready` 即停止。 -前者必须把测试环境地址和用户下一步交付出来;stable 发布和 production 部署必须在 -approval 步骤再次确认。失败时保留任务的 `verified`,把 -delivery run 标为 `blocked` 或 `failed`。 +所选任务都由 Coordinator 标记为 `verified` 后,若用户确认的计划包含交付,转入 SKILL.md 对应交付模式。启用交付时必须在计划中默认列出 `defaultProfile`,用户可明确取消,Coordinator 不能静默省略。先重新校验 `delivery.yaml`,固定当前 commit 和 config revision,然后按有序步骤调用项目入口与已安装的低层 skill。每一步证据写入 `tasks.yaml.deliveryRuns`;默认 profile 到 `validation_ready` 或 `review_ready` 即停止。前者必须把测试环境地址和用户下一步交付出来;stable 发布和 production 部署必须在 approval 步骤再次确认。失败时保留任务的 `verified`,把 delivery run 标为 `blocked` 或 `failed`。 ## 第 6 步:收尾 -一轮结束时 Coordinator 必须能回答 `optimization-method.md` §「结束条件」的问题: -哪些 verified、哪些 leftover、各失败几轮、工作树是否干净、还有没有未处理项。 +一轮结束时 Coordinator 必须能回答:哪些 verified、哪些 leftover、各失败几轮、工作树是否干净、还有没有未处理项。复验轮次争议以 SKILL.md「边界」为准。 Coordinator 最后标记整轮任务完成后,用 `scripts/reclaim_workers.py` 先 dry-run 审阅决策、再 `--apply` 关闭所有只关联 `verified` 任务的 Developer/Test 终端并核对 回执;receipt 和落盘证据继续保留。仍关联 `blocked`、`failed_retest`、`leftover` diff --git a/skills/builder/SKILL.md b/skills/builder/SKILL.md index 740b1bd..2861961 100644 --- a/skills/builder/SKILL.md +++ b/skills/builder/SKILL.md @@ -1,20 +1,14 @@ --- name: builder description: >- - 初始化或检查项目是否满足 DEB/Docker 构建发布契约,再按契约构建并发布: - 先校验 makefile.builder(check.py),再 make -f makefile.builder 构建产物, - 经授权后用 skill 自带脚本上传并验证。触发词:初始化 builder、接入 builder、 - 检查 makefile.builder、构建 deb、发布 deb、上传 deb、推送 apt 仓库、打 Debian - 包、构建镜像、发布镜像、推送 Docker 镜像、make push。仅分析打包逻辑或只构建 - 不上传时也可使用;不会在未获授权时执行任何上传。Docker 轨道保持显式触发: - 用户点名(builder/publish docker)时才走镜像发布。 + 初始化或检查 makefile.builder 契约,再构建或发布 deb/镜像。触发词:初始化 + builder、检查 makefile.builder、构建/发布 deb、推送 apt、构建/发布 Docker + 镜像、make push。未授权不上传。Docker 仅用户点名镜像时才走。 --- # Builder:DEB / Docker 构建发布 -复用项目已有发布约定,安全地完成"校验 → 构建 → 检查 → 授权 → 上传 → 验证"。 - -分工原则:**make 管构建,skill 脚本管发布,本 SKILL.md 只留脚本做不了的决策。** +**make 管构建,skill 脚本管发布,本 SKILL.md 只留脚本做不了的决策。** 项目状态是根目录 `makefile.builder` 与发布用 `.env.builder`,不要创建 `.pouch/builder/`,不要改用户的 `Makefile` / `makefile` / `.env`。 @@ -23,46 +17,20 @@ description: >- ## 选择模式 -- 用户要求初始化、接入 builder,或新项目还没有 `makefile.builder`:执行“初始化”。 -- 用户要求检查 builder 契约或发布配置是否齐全:执行“检查”。 -- 用户要求构建、发布、上传:执行“工作流”。不要静默初始化。 - -## 何时使用 - -- 用户要求初始化或接入 builder。 -- 用户要求构建、发布、上传 `.deb` 包或 Docker/OCI 镜像。 -- 用户要求检查 `makefile.builder` 是否符合 builder 契约。 -- 用户要求梳理或接通项目现有的 DEB/镜像发布流程。 - -不适用:本地安装/卸载 DEB;RPM/APK/语言包管理器;从零设计全新打包体系(先出方案); -普通编码与 Dockerfile 编辑。 +- 初始化、接入 builder,或还没有 `makefile.builder`:执行「初始化」。 +- 检查契约或发布配置:执行「检查」。 +- 构建、发布、上传:执行「工作流」。不要静默初始化。 +- 不适用:本地安装/卸载 DEB;RPM/APK/语言包;从零设计打包体系(先出方案);普通编码与 Dockerfile 编辑。 +- 改本 skill 自身:契约先改 `scripts/check.py`,再同步 [contract.md](references/contract.md) 与 templates;不在生产上传上试脚本。 ## 初始化 -1. 确认项目根。探测 `makefile.builder`、`.env.builder`、用户 `Makefile`/`makefile` - (只当抄 build 配方的证据,不改)、`Dockerfile`、`debian/`、语言清单。 - `.env.builder` 只看键是否存在且非空,不读、不打印值。不要读取用户 `.env`。 -2. 判定轨道:有 Dockerfile → docker;有 deb 信号或用户要打 deb → deb;都不清则问。 - 不要猜测 registry、token 或仓库名。 -3. 没有 `makefile.builder`:把 `/templates/makefile.builder` 拷到项目根。 - 按轨道删掉未使用的 deb/docker/push* 段,把 `build` 的 TODO 换成仓库里已有的 - 真实编译命令(可从用户 Makefile 抄配方,但不要 `include` 或递归调用它)。 - `include` builder 的 `scripts/version.mk`。双产物把 `push` 改成 - `push: push-deb push-docker`。不要改用户的 `Makefile` / `makefile`。 -4. 已有 `makefile.builder`:跑检查;按 FAIL 给出修补说明。不覆盖该文件,除非 - 用户明确要求按契约改。不要调用 create-makefile(其版本规则与本契约冲突)。 -5. 没有 `.env.builder`:把 `/templates/env.builder` 拷到项目根为 - `.env.builder`(注释键,不含值)。不要改、不要读取用户 `.env`。缺发布键时在 - 报告里给出可粘贴示例,并说明把 `.env.builder` 加入 `.gitignore`,不要提交。 -6. 运行: - - ```bash - python3 -I -S /scripts/check.py --ready - ``` - -7. 按下面格式报告。结构校验通过且当前轨道能构建时才能称「完成」;只缺发布 - 键是「部分完成」(可构建,不可发布)。契约 FAIL 或轨道工具缺失是「阻塞」。 - 除非用户明确要求,不提交、不推送、不上传。 +1. 确认项目根。探测 `makefile.builder`、`.env.builder`、用户 Makefile(只当抄配方的证据,不改)、`Dockerfile`、`debian/`。`.env.builder` 只看键是否存在且非空,不读、不打印值。不要读取用户 `.env`。 +2. 判定轨道:有 Dockerfile → docker;有 deb 信号或用户要打 deb → deb;都不清则问。不要猜测 registry、token 或仓库名。 +3. 没有 `makefile.builder`:把 `/templates/makefile.builder` 拷到项目根。按轨道删掉未使用的 deb/docker/push* 段,把 `build` 的 TODO 换成仓库里已有的真实编译命令(可从用户 Makefile 抄配方,但不要 `include` 或递归调用它)。`include` builder 的 `scripts/version.mk`。双产物把 `push` 改成 `push: push-deb push-docker`。不要改用户 Makefile。 +4. 已有 `makefile.builder`:跑检查;按 FAIL 给出修补说明。不覆盖该文件,除非用户明确要求按契约改。不要调用 create-makefile(版本规则冲突)。 +5. 没有 `.env.builder`:把 `/templates/env.builder` 拷到项目根(注释键,不含值)。缺发布键时在报告里给出可粘贴示例,并把 `.env.builder` 加入 `.gitignore`,不要提交。 +6. 运行 `python3 -I -S /scripts/check.py --ready`。结构校验通过且当前轨道能构建才称「完成」;只缺发布键是「部分完成」。契约 FAIL 或轨道工具缺失是「阻塞」。除非用户明确要求,不提交、不推送、不上传。 ```text ## builder 初始化:完成 | 部分完成 | 阻塞 @@ -73,10 +41,8 @@ description: >- 下一步: 一句话 ``` -发布键示例(只示范键名): - ```text -# .env.builder +# .env.builder 键名示例 DEB_SERVER_URL=https://deb.example.com DEB_REPOSITORY=main DEB_TOKEN= @@ -85,121 +51,15 @@ DOCKER_REGISTRY=registry.example.com ## 检查 -只读。运行 `check.py --ready`,用同一报告格式,标题改为 -`## builder 检查:…`。不写 `makefile.builder` / `.env.builder`,不改用户 Makefile -或 `.env`。用户明确要求修复后再转入初始化。 +只读。运行 `check.py --ready`,用同一报告格式,标题改为 `## builder 检查:…`。不写 `makefile.builder` / `.env.builder`,不改用户 Makefile 或 `.env`。用户明确要求修复后再转入初始化。 ## 工作流 -### 0. 校验契约 +契约见 [contract.md](references/contract.md)。Docker 的 registry/tag 不明确时再读 [registry.md](references/registry.md)。 -```bash -python3 -I -S /scripts/check.py # 静态检查 -python3 -I -S /scripts/check.py --ready # 含工具链与发布键 -python3 -I -S /scripts/check.py --build # 额外实构 deb 并核对产物 -``` - -契约 FAIL 或轨道工具缺失:停下,转入「初始化」按契约补齐 `makefile.builder`, -不要绕过校验继续发布,不要改用户 Makefile。只缺发布键:允许构建,禁止上传。 -完整要求见 [contract.md](references/contract.md)。存量项目未接契约时走 -「存量项目 fallback」;成功交付一次后引导用户迁到 `makefile.builder`。 - -### 1. 确认发布边界 - -上传是外部写操作。仅当用户明确要求发布、上传或提交时执行;只要求查看、诊断或构建 -则停在相应阶段。 - -执行上传前确认: - -- 目标服务和仓库来自项目配置(`.env.builder`)或用户输入,不猜测生产端点。 -- 认证令牌已通过环境变量或密钥系统提供;绝不写入命令输出、文件、提交或回复, - 不用 `set -x` 执行含凭据的命令。 -- 相同版本是否允许覆盖;无法确认且可能覆盖时,先询问。 -- Docker 轨道需要已确定 registry/repository;tag 未给出时按契约「版本号」推导。 - -脏工作树默认拒绝发布;用户明确接受时设置 `ALLOW_UNCOMMITTED=1` 并在汇报中注明 -包含的未提交修改。 - -### 2. 构建 - -```bash -make -f makefile.builder build ARCH= VERSION= # 主产物 -make -f makefile.builder deb ARCH= # DEB 项目 -``` - -版本缺省按契约「版本号」从 Git 祖先稳定 tag 推导(正式 = HEAD exact-match -的 `vX.Y.Z`;测试 = `X.Y.Z~分支.距离+gSHA`)。不要调用 manage-release 来算 -产物版本,不要用全仓库最新 tag。构建目标若会自动上传而当前仅获构建授权,改用 -纯构建目标。执行前确认所需工具可用(docker、dpkg-deb 等)。不得擅自清理宽泛 -目录;脚本含 `rm -rf` 时先解析确认为受限构建目录。 - -### 3. 上传前检查 - -```bash -find $(DIST_DIR) -maxdepth 2 -type f -name '*.deb' -print -/scripts/verify_deb.sh [期望版本] [期望架构] -``` - -verify_deb.sh 输出元数据、关键内容清单和 SHA-256。匹配到多个包时不凭文件时间猜测, -向用户确认唯一产物。镜像轨道无需单独校验步骤(publish_docker.sh 自带远端 inspect)。 - -### 4. 发布 - -优先 `make -f makefile.builder push[-deb|-docker]`(契约要求的薄包装);直接调用等价: - -```bash -DEB_SERVER_URL=… DEB_TOKEN=… DEB_REPOSITORY=… \ - /scripts/upload_deb.sh - -DOCKER_REGISTRY=… \ - /scripts/publish_docker.sh # env 优先,flag 可覆盖 -``` - -环境变量缺失时脚本会加载项目 `.env.builder`(shell 显式值优先),不读 `.env`。不把 token -作为命令行参数;不把脚本复制进项目。upload_deb.sh 默认请求 `/api/v2/upload/package` -(multipart 字段 `package`/`token`/`repository_name`,接受 200/201),协议不符时设 -`DEB_UPLOAD_PATH` 或改用项目专属逻辑。publish_docker.sh 用 buildx 一步完成构建+推送, -多平台只能走它,不能拆进 make。 - -### 5. 验证与汇报 - -发布成功不能只依据"curl 已执行"/"push 已执行"。综合检查: - -- 上传命令退出码为零,HTTP 状态与响应体明确成功;镜像以 `imagetools inspect` - 的远端 digest 为准。 -- 若仓库提供查询/索引/下载地址,确认该版本已可见;索引异步时报告 - "上传已接受,索引尚待更新",不声称完全可用。 - -最终回复给出:包名/镜像引用、版本、架构/platform、产物路径与 SHA-256 或远端 digest、 -源 commit 与工作区状态、各阶段验证结果、未完成项或覆盖风险。 - -## 存量项目 fallback(legacy) - -从项目根目录查找,不预设文件位置: - -```bash -rg -n -i --hidden --glob '!.git' \ - 'build-deb|upload-deb|publish-deb|dpkg-deb|debuild|curl.*deb|\.deb\b|aptly|reprepro' -``` - -重点检查用户 Makefile、CI 配置、`debian/`、构建脚本和发布文档中的入口、变量传递方式、 -端点与认证方式。优先复用已有构建入口;上传仍用 builder 脚本。交付后引导迁移到 -`makefile.builder`(`templates/makefile.builder` + `check.py` 通过为准)。 - -## 修改 builder 自身时 - -- 上传/发布脚本是 SSOT:通用行为修改落在 `skills/builder/scripts/`,不同步复制到 - 业务项目。产物版本只通过 `scripts/version.sh` 推导,不要在 `makefile.builder` 内联 - `git describe` 或 `sort -V`。 -- 契约变更先改 `scripts/check.py`,再同步 `references/contract.md`、 - `templates/makefile.builder` 与 `templates/env.builder`。 -- 可用 `bash -n` 检查脚本语法;有 ShellCheck 时一并运行。 -- 不通过真实生产上传测试脚本,除非用户明确授权并给出测试版本/仓库。 - -## 完成标准 - -- 初始化/检查:报告为完成、部分完成或阻塞;待配置项含文件、字段和示例。 -- 仅分析:入口、调用链、配置来源和风险已被准确说明。 -- 仅校验:check.py 结果逐条可解释,修复建议明确。 -- 仅构建:产物已生成并通过 verify_deb.sh,未发生上传。 -- 发布:构建检查通过,服务端接受上传,仓库可见性已验证或准确标记为待更新。 +1. 跑 `check.py `;需要工具链与发布键时加 `--ready`;要实构 deb 时加 `--build`。契约 FAIL 或轨道工具缺失:停下,转入「初始化」,不要绕过校验,不要改用户 Makefile。只缺发布键:允许构建,禁止上传。未接契约的存量项目按 contract.md §6 发现已有入口,上传仍用 builder 脚本;成功交付一次后引导迁到 `makefile.builder`。 +2. 仅当用户明确要求发布、上传或提交时才上传。不猜测生产端点;不把 token 写入输出、文件、提交或回复;不用 `set -x` 跑含凭据的命令。可能覆盖同版本时先问。脏工作树默认拒绝发布;用户明确接受时设 `ALLOW_UNCOMMITTED=1` 并注明未提交修改。 +3. 构建:`make -f makefile.builder build ARCH= VERSION=`;DEB 再 `make -f makefile.builder deb ARCH=<...>`。版本按契约从 Git 祖先稳定 tag 推导,不要调用 manage-release,不要用全仓库最新 tag。仅获构建授权时不要走会自动上传的目标。脚本含 `rm -rf` 时先确认为受限构建目录。 +4. DEB 上传前:`verify_deb.sh `。多个包时不凭文件时间猜测。镜像轨道由 `publish_docker.sh` 自带远端 inspect。 +5. 发布优先 `make -f makefile.builder push[-deb|-docker]`,或直接调 `upload_deb.sh` / `publish_docker.sh`。脚本缺环境变量时加载 `.env.builder`(shell 显式值优先),不读 `.env`。不把 token 当命令行参数;不把脚本复制进项目。多平台镜像只能走 `publish_docker.sh`,不能拆进 make。 +6. 发布成功不能只看「curl/push 已执行」。要有退出码、HTTP 成功或远端 digest;索引异步时报告「上传已接受,索引尚待更新」。最终回复给出包名/镜像引用、版本、架构、SHA-256 或 digest、源 commit、工作区状态和未完成项。 diff --git a/skills/builder/references/contract.md b/skills/builder/references/contract.md index af93297..1aaf74d 100644 --- a/skills/builder/references/contract.md +++ b/skills/builder/references/contract.md @@ -148,6 +148,13 @@ clone 到 `~/.pouch`。 ## 6. 存量项目(legacy fallback) 未接入契约的项目:builder 仍可按发现流程工作——从用户 `Makefile`、CI 配置、`debian/` -与发布文档中找已有构建/上传入口,优先复用;上传仍使用 builder 脚本。完成一次成功 -交付后应引导用户按 `templates/makefile.builder` 写入项目根 `makefile.builder`,之后以 -check.py 为准。不把契约目标合并进用户 Makefile。 +与发布文档中找已有构建/上传入口,优先复用;上传仍使用 builder 脚本。从项目根查找, +不预设文件位置: + +```bash +rg -n -i --hidden --glob '!.git' \ + 'build-deb|upload-deb|publish-deb|dpkg-deb|debuild|curl.*deb|\.deb\b|aptly|reprepro' +``` + +完成一次成功交付后应引导用户按 `templates/makefile.builder` 写入项目根 +`makefile.builder`,之后以 check.py 为准。不把契约目标合并进用户 Makefile。 diff --git a/skills/deployer/SKILL.md b/skills/deployer/SKILL.md index c8a9340..d45f749 100644 --- a/skills/deployer/SKILL.md +++ b/skills/deployer/SKILL.md @@ -1,23 +1,15 @@ --- name: deployer description: >- - 初始化或检查项目部署配置,并管理两类部署:多机 Docker Compose(仓库存 - compose.yaml 与静态配置,本 skill 脚本同步到 SSH 节点后 docker compose 应用), - 以及 Argo CD GitOps(改 GitOps 仓库清单、开 PR/MR,用户合并后由 Argo CD 同步)。 - 当用户要求初始化 deployer、接入测试/生产环境、检查 .pouch/deployer 是否齐全; - 或部署、同步、升级、重启远程 Compose 服务,向节点装 deb,新增/迁移/下线服务, - 梳理节点清单,make deploy TGT、_config.yaml、rsync、tar over SSH、NAS 部署失败; - 或要求 ArgoCD / GitOps / K8s 部署、更新 Application、升镜像 tag、开 MR 让用户 - 合并部署;或 ACK 要求拉起/重布项目测试环境时使用。 + 初始化或检查项目部署配置;管理多机 Docker Compose(脚本同步后远程 + compose)与 Argo CD GitOps(改清单开 MR,用户合并后同步)。触发词:初始化 + deployer、部署、sync、升级、装 deb、ArgoCD、GitOps;ACK 拉起测试环境时也可使用。 --- # deployer:Compose 节点与 Argo CD GitOps -两条轨道,配置都在仓库里,方法由本 skill 提供。 - - **Compose**:本地改 `compose.yaml` → 脚本同步到 SSH 节点 → 远程 `docker compose`。 -- **Argo CD**:改 GitOps 仓库清单 → 开 PR/MR → 用户合并 → Argo CD 同步。不要用 - Compose 的 `sync.py`/`remote.py` 去推集群。 +- **Argo CD**:改 GitOps 仓库清单 → 开 PR/MR → 用户合并 → Argo CD 同步。不要用 Compose 的 `sync.py`/`remote.py` 去推集群。 开始时解析当前 `SKILL.md` 所在目录,记为 ``。优先 `git rev-parse --show-toplevel` 解析项目根。不要创建 `.pouch/deployer/` 之外的 @@ -25,114 +17,39 @@ description: >- ## 选择模式 -- 用户要求初始化、接入 deployer,或给新项目建测试/生产环境:执行“初始化”。 -- 用户要求检查 `.pouch/deployer`、node、compose 是否齐全:执行“检查”。 -- 用户要求部署、同步、升级、重启、装 deb、开 GitOps MR:执行下面对应轨道步骤。 - 发现不了服务或解析不出 node 时停止,转入“初始化”。不要静默初始化。 +- 初始化、接入 deployer,或给新项目建测试/生产环境:执行「初始化」。 +- 检查 `.pouch/deployer`、node、compose 是否齐全:执行「检查」。 +- 部署、同步、升级、重启、装 deb、新增/下线服务:执行「Compose 操作」。发现不了服务或解析不出 node 时停止,转入「初始化」。不要静默初始化。 +- ArgoCD / GitOps / 开 MR 部署:执行「Argo CD」。步骤见 [argocd.md](references/argocd.md)。 +- 两者都有且意图不清:先问。 +- 不适用:单机 docker、Nomad、常规 `kubectl apply`、构建并推送镜像(走 builder)。 -## 何时使用 +## 边界 -- 部署 / 同步 / 升级 / 重启某个远程 Docker Compose 服务 -- 向节点安装 deb 包:scp 上传本地 .deb 后 dpkg/apt 安装,或从 URL 远程拉取安装 -- 新增、迁移、下线一个服务;梳理「哪台机器跑什么」 -- sync 失败排查、证书丢失、改了配置不生效等运维问题 -- 提到 `make deploy TGT=...`、`TGT=`、`_config.yaml`、rsync/tar 同步 -- Argo CD / GitOps / 集群部署:新增 Application、改清单、升镜像 tag、开 MR 等用户合并 -- ACK Coordinator 拉起或重布项目测试环境(`.pouch/deployer/`) -- 初始化 deployer、给项目接上 test/prod、检查部署配置缺什么 - -## 不适用 - -- 单机 docker 日常使用(无多机同步诉求) -- Nomad,或绕过 GitOps 用 `kubectl apply` 当常规发布 -- 构建并推送镜像(走 builder);本 skill 只改 GitOps 里对该镜像的引用 - ---- - -## 核心模型(先读懂再动手) - -### 轨道选择 - -| 信号 | 轨道 | -|------|------| -| ArgoCD / GitOps / 集群 / 开 MR 部署 / 项目有 `.pouch/deployer/argocd.yaml` | Argo CD,见 [argocd.md](references/argocd.md) | -| sync、`TGT=`、某台机器、`compose.yaml` | Compose(下文布局与步骤) | -| 两者都有且意图不清 | 先问 | - -### Compose - -- **仓库只放数据**:`compose.yaml`、Caddyfile、Traefik 动态配置等静态配置进 Git; - 运行时数据(证书、数据库、上传文件)永不进 Git,也永不参与同步范围。 -- **每个可部署服务目录必须有 `compose.yaml`**,且能解析出目标节点 `node` - (来自该目录、部署根或祖先目录的 `_config.yaml`,或父目录名恰为 SSH Host 别名)。 -- **`node` 即 SSH Host 别名**(`~/.ssh/config`),支持 `user@host` 形式。 -- `unused/` 下不参与自动发现与部署。 - -### Argo CD - -源项目 `.pouch/deployer/argocd.yaml`:`repo` 写 Git 地址(部署时浅 clone),或加 `repo_dir` 用已有 checkout。 -改 GitOps 清单,不要改 Compose 脚本。密钥不入库。两种接法见 skill README,步骤见 [argocd.md](references/argocd.md)。 - -### 两种 Compose 布局 - -**A. 独立配置中心仓库**(如 app00):仓库根即部署根, -`DEPLOYER_ROOT=/path/to/repo` 指定后按仓库内相对路径操作: - -``` -repo/ -├── _config.yaml # 可选,全局默认 -├── vyyo1/_config.yaml # node: vyyo1(主机目录) -│ └── naiveproxy/ # 服务目录:compose.yaml + 可选 _config.yaml -└── unused/ -``` - -远程目录名 = 目录末级名:`vyyo1/naiveproxy` → `/opt/app/naiveproxy`。 - -**B. 项目内环境布局**:项目根放 `.pouch/deployer/{prod,test,dev}/`, -每个环境一个目录。从项目内任意位置运行脚本即自动发现(也可用 `DEPLOYER_ROOT` -显式指定),无需环境变量: - -``` -my-project/ -├── src/ ... # 项目本体 -└── .pouch/deployer/ - ├── _config.yaml # 三个环境共享默认(node/base_path 等) - ├── argocd.yaml # 可选,Argo CD 指针(不是 compose 环境) - ├── prod/ - │ ├── compose.yaml # 生产 compose 与配置 - │ └── _config.yaml # 环境级覆盖 - ├── test/compose.yaml - └── dev/compose.yaml -``` - -项目模式下远程目录名自动加项目前缀 `{git仓库名}-{env}` -(如 `my-project-prod`),防止同主机多项目的同名环境互相覆盖; -`_config.yaml` 写 `name:` 可显式指定。 +- 所有 sync/up/recreate/upgrade/restart 必须按单服务执行,禁止节点级批量。 +- `rsync` 带 `--delete`:运行时数据必须在 `data/`、`_data/` 或远程绝对路径挂载,否则会被清掉。 +- 仓库只放静态配置;证书、数据库、上传文件不进 Git,也不进同步范围。`unused/` 不参与发现与部署。 +- `node` 是 `~/.ssh/config` 的 Host 别名(可用 `user@host`)。用户没给别名就不要写假 node。 +- 密钥不入库。Compose 优先放远程 `.env`;Argo CD 的 dockerconfigjson / TLS 私钥只存在集群 Secret。 +- 不 `--force` 推送、不硬 reset,除非用户明确要求。Argo CD 不直接推默认分支。 +- 镜像固定 tag,不用 `:latest`;成对升级的服务要同步升。 +- ACK 调用不能把范围扩到生产环境、Argo 合入或节点级批量。 ## 初始化 -独立配置中心仓库(已设 `DEPLOYER_ROOT`)只做检查,不要改成项目内布局。 +独立配置中心仓库(已设 `DEPLOYER_ROOT`)只做检查,不要改成项目内布局。`_config.yaml` 字段见 [config-reference.md](references/config-reference.md)。 -1. 探测:`.pouch/deployer/`、根目录 `compose.yaml`/`docker-compose.yml`、 - `Dockerfile`、ACK `intents.testEnvironment`、`.pouch/deployer/argocd.yaml`。 +1. 探测:`.pouch/deployer/`、根目录 compose、`Dockerfile`、ACK `intents.testEnvironment`、`argocd.yaml`。 2. Compose 与 Argo 都有且意图不清:先问。两边都要也可以,必须分开确认。 -3. **Compose / 新项目**(ACK 默认需要 `test`): - - 问环境:默认只建 `test`。`prod`/`dev` 用户点名再加。不默默建空的 prod。 - - 问 SSH Host 别名(必须在 `~/.ssh/config`)。没给就**不要写假 node**; - 目录可以建,`_config.yaml` 列为待配置。 - - 有根目录 compose:提议迁到 `.pouch/deployer//`,确认后才动。 - - 只有 Dockerfile:可给**单服务** compose 草稿(镜像名来自仓库名),用户确认 - 后写入。不发明多服务网格。 -4. **Argo**:只问 GitOps `repo`(或 `repo_dir`),写 `.pouch/deployer/argocd.yaml`。 - 不 clone、不开 MR、不 `kubectl apply`。 +3. Compose / 新项目(ACK 默认需要 `test`):默认只建 `test`;`prod`/`dev` 用户点名再加。问 SSH Host 别名;没给不要写假 node,目录可建、列为待配置。有根目录 compose:提议迁到 `.pouch/deployer//`,确认后才动。只有 Dockerfile:可给单服务 compose 草稿,用户确认后写入,不发明多服务网格。 +4. Argo:只问 GitOps `repo`(或 `repo_dir`),写 `.pouch/deployer/argocd.yaml`。不 clone、不开 MR、不 `kubectl apply`。 5. 运行(不 SSH、不 up): - ```bash - python3 -I -S /scripts/deploy/check.py --project - ``` +```bash +python3 -I -S /scripts/deploy/check.py --project +``` -6. 按下面格式报告。缺 `node` / compose / ssh 别名 = 部分完成或阻塞。 - 不覆盖已有 compose/`_config.yaml`。除非用户明确要求,不部署、不提交。 +6. 缺 `node` / compose / ssh 别名 = 部分完成或阻塞。不覆盖已有 compose/`_config.yaml`。除非用户明确要求,不部署、不提交。 ```text ## deployer 初始化:完成 | 部分完成 | 阻塞 @@ -143,194 +60,18 @@ my-project/ 下一步: 一句话 ``` -`_config.yaml` 示例(`node` 必须是用户给出的 SSH Host 别名): - -```yaml -# .pouch/deployer/_config.yaml -node: my-vps -base_path: /opt/app -``` - ## 检查 -只读。运行 `scripts/deploy/check.py --project `,用同一报告格式, -标题改为 `## deployer 检查:…`。不写文件、不 SSH 连接。用户明确要求修复后再转入 -初始化。 +只读。运行 `scripts/deploy/check.py --project `,用同一报告格式,标题改为 `## deployer 检查:…`。不写文件、不 SSH。用户明确要求修复后再转入初始化。 ## 被 ACK 调用 -ACK 的「运行测试环境」和回归前布环境会加载本 skill,对项目 -`.pouch/deployer/`(通常是 `test`)按下面 Compose 轨道执行。ACK 只负责何时 -布、把访问地址写入 `deliveryRuns`;不要把本 skill 的脚本复制进 ACK。生产环境、 -Argo CD 合入和节点级批量操作仍须用户明确要求,不能因为 ACK 调用就扩大范围。 +ACK 的「运行测试环境」和回归前布环境会加载本 skill,对 `.pouch/deployer/`(通常是 `test`)按「Compose 操作」执行。ACK 只负责何时布、把访问地址写入 `deliveryRuns`;不要把本 skill 的脚本复制进 ACK。生产环境、Argo CD 合入和节点级批量仍须用户明确要求。 -## 步骤 +## Compose 操作 -### Compose 轨道 +读 [compose.md](references/compose.md)。用 `list.py` 摸底,再按意图对**单个服务**执行 sync/up/recreate/upgrade/restart。解析 `_config.yaml` 见 [config-reference.md](references/config-reference.md)。sync 报错但 ssh 正常时,按 compose.md 的 NAS 兜底处理。每次操作后 `remote.py ps` / `logs` 验证。 -#### 0. 定位部署根 +## Argo CD -skill 目录下的 `scripts/deploy/` 是通用部署工具链(lib/sync/remote/list), -不依赖具体项目路径。部署根按以下顺序解析: - -1. 环境变量 `DEPLOYER_ROOT` 显式指定(独立配置中心仓库用这个) -2. 从当前目录向上找 `.pouch/deployer/`(项目内环境布局自动发现) -3. skill 安装位置兜底(仅用于查看,没有可部署服务) - -```bash -# = 本 SKILL.md 所在目录,先解析出来记下 -# 布局 A:显式指定仓库根 -export DEPLOYER_ROOT=/path/to/your-compose-repo -python3 /scripts/deploy/list.py - -# 布局 B:在项目内直接跑即可(cwd 在项目里) -python3 /scripts/deploy/list.py -``` - -#### 1. 摸底:列出服务与节点 - -上一步的 `list.py` 输出全部服务与节点分布;新增环境/服务后重跑确认被发现。 -项目布局下 `prod/test/dev` 各显示为 `{项目名}-{env}`。`argocd.yaml` 不会被 list.py 当成 compose 服务。 - -#### 2. 解析单个服务 - -```bash -# 查看 node、远程路径、排除规则(sync.py 干跑会打印这些信息) -python3 /scripts/deploy/sync.py -``` - -或直接读服务目录及祖先的 `_config.yaml`。 - -#### 3. 命令选择(语义严格区分) - -| 意图 | 命令 | -|------|------| -| 只同步文件,不动容器 | `sync.py ` | -| 应用 compose/配置变更 | `sync.py && remote.py up` | -| 改配置后强制重建 | `remote.py recreate`(配合前置 sync) | -| 镜像 tag 变更升级 | `sync.py && remote.py upgrade` | -| 仅重启,不同步文件 | `remote.py restart` | -| 排查 | `remote.py ps` / `remote.py logs` | - -#### 4. 项目侧 Makefile(可选薄封装) - -若项目有 Makefile 封装,命令形如 `make deploy TGT=<服务路径>`。 -没有 Makefile 时直接调 python 脚本即可,不要新建封装层。 - -#### 5. 新增服务 / 环境 checklist - -独立仓库布局: - -1. 在合适分类目录创建服务文件夹,写 `compose.yaml` -2. 在服务目录或祖先目录放 `_config.yaml`(至少能解析出 `node`) -3. 有运行时目录 → 加进 `sync_exclude` -4. 远程首次建目录:`ssh "mkdir -p /"` -5. 首次部署:sync + up -6. 验证:ps + logs,必要时 curl/ssh 检查端口 - -项目环境布局: - -1. 项目根建 `.pouch/deployer/{env}/`(env 通常为 prod/test/dev) -2. 每个环境写 `compose.yaml`;三个环境共享的 node/base_path 放 - `.pouch/deployer/_config.yaml` -3. 环境有差异(不同主机、不同排除项)→ 在该环境的 `_config.yaml` 覆盖 -4. 同名冲突或需要固定远程目录名 → `_config.yaml` 写 `name:` -5. 首次部署前确认目标主机的远程目录不存在旧内容(rsync `--delete` 会清掉) - -#### 6. 下线服务 - -独立仓库布局:配置移入 `unused/`(自动脱离发现体系),远程按需手动清理: -`ssh "cd / && docker compose down"`,数据卷按需保留或删除。 -项目环境布局:删除对应 `.pouch/deployer/{env}/` 目录即可脱离发现体系,远程清理同上。 - -#### 7. 向节点安装 deb 包 - -`deb.py` 把 deb 包发到节点并安装。目标两种写法:仓库内目录 -(复用 `_config.yaml` 继承链解析 node/port/identity_file,如 `hosts/web1`), -或裸 SSH 别名 / `user@host`(须在 `~/.ssh/config` 中,可加 `--port`/`--identity`)。 - -```bash -# 本地 .deb → scp 上传 → 远程 apt 安装(失败自动 apt -f 修依赖),成功后删暂存包 -python3 /scripts/deploy/deb.py push ./foo_1.0_amd64.deb --yes - -# 仅上传到远程暂存目录(默认 {base_path}/.debs;裸主机为 /tmp/deployer-debs) -python3 /scripts/deploy/deb.py scp ./foo_1.0_amd64.deb - -# 安装该节点暂存目录里已上传的全部 .deb(配合 scp 分步操作) -python3 /scripts/deploy/deb.py dpkg --yes - -# 远程直接从 URL 下载安装(机器能出网时免上传) -python3 /scripts/deploy/deb.py apt https://example.com/foo_1.0_amd64.deb --yes -``` - -- 非 root 用户走 `sudo -n`(需配好免密 sudo);`--yes` 传 `-y` 免交互, - 无终端交互能力,没配 sudo 免密/密钥时会直接失败。 -- 升级同版本号前想先看包信息:`ssh "dpkg -I <暂存路径>"`; - 装完验证:`ssh "dpkg -l | grep "`。 - -### Argo CD 轨道 - -完整步骤与 `argocd.yaml` 字段见 [argocd.md](references/argocd.md)。 - -1. 读项目 `.pouch/deployer/argocd.yaml`(无则只问 Git 地址,写成 `repo:`)。 - 有 `repo_dir` 则用该目录;否则把 `repo` 浅 clone 到临时目录,用完删除。 -2. 在工作副本里按**已有应用惯例**新增 Application,或只改镜像 tag / 清单。 -3. 从最新默认分支拉出分支,commit、push,用 `glab`/`gh`/`tea` 开 MR;CLI 对项目 404 则把 - `git push` 给出的网页建单链接交给用户。 -4. **停在 MR**,不合并、不 `kubectl apply` 工作负载。 -5. 无 app-of-apps 时提醒用户首次 `kubectl apply` 那份 `application.yaml`。 -6. Harbor 拉镜像 Secret、TLS Secret 不入库;只在工作负载所在 ns 准备,可从其他 ns 拷贝。 - ---- - -## 注意事项 - -- **禁止节点级批量操作**:所有 sync/up/recreate/upgrade/restart 必须按单服务执行。 - 批量升级风险过高,逐个来。 -- **rsync 带 `--delete`**:远程多余文件会被删除。运行时数据必须放在 - 默认排除的 `data/`、`_data/`,或 compose 挂载的远程绝对路径 - (如 `/data01/docker//`),否则会被清掉。 -- **镜像固定 tag**,不用 `:latest` 漂移;成对升级的服务(如 proxy 客户端/服务端)要同步升。 -- **密钥**:Compose 优先放远程 `.env`;Argo CD 的 dockerconfigjson / TLS 私钥只存在集群 Secret。 - 不要提交新密钥进 Git。 -- **Git 安全**:不 `--force` 推送、不硬 reset,除非用户明确要求。Argo CD 轨道不直接推默认分支。 -- **NAS / Synology 特例**:部分 NAS 的 SSH 用户禁用 rsync 协议(Permission denied)。 - 表现是 sync 报错但 ssh 正常。处理顺序: - 1. 该节点 `_config.yaml` 写真实 `base_path`(如 `/volume1/docker`,避开符号链接路径) - 2. 仍失败则手动 tar over SSH 推送: - - ```bash - tar czf - -C <服务目录> . --exclude='data' --exclude='_data' \ - | ssh "mkdir -p / && cd / && tar xzf -" - ssh "cd / && /usr/local/bin/docker compose up -d" - ``` - - tar 不会删除远程多余文件;需清理旧文件时手动 SSH 删除。 - 3. Synology 上 docker 路径可能是 `/usr/local/bin/docker` - -## 验证 - -- Compose:`list.py` 输出全部服务与节点分布,数量与预期一致 -- 每次 sync/deploy 后 `remote.py ps` 容器 Up、`logs` 无报错 -- 升级后额外确认镜像 tag 与 compose.yaml 一致 -- 改 Traefik/Caddy 路由后 curl 对应域名验证生效 -- Argo CD:MR 可打开且含本次清单;用户合并后 Application Synced;有 Ingress 则 curl healthz - -## scripts/ - - -| 文件 | 用途 | -|------|------| -| `scripts/deploy/lib.py` | 解析服务目录、合并继承 `_config.yaml`、SSH/rsync/scp 参数构造 | -| `scripts/deploy/sync.py` | rsync -avz --delete 同步;无 rsync 时 tar over SSH 兜底 | -| `scripts/deploy/remote.py` | SSH 远程 docker compose:up/recreate/restart/upgrade/ps/logs | -| `scripts/deploy/deb.py` | deb 包分发安装:push(scp+apt)/scp/dpkg/apt(URL) | -| `scripts/deploy/list.py` | 扫描全部可部署服务 | -| `scripts/deploy/check.py` | 只读就绪检查:布局、compose、node、ssh config、工具链 | - -## references/ - -| 文件 | 用途 | -|------|------| -| `references/config-reference.md` | `_config.yaml` 字段完整说明与继承合并规则 | -| `references/argocd.md` | Argo CD 轨道:`argocd.yaml`、新增/升级、开 MR、ns 级 Secret | +读 [argocd.md](references/argocd.md)。读 `.pouch/deployer/argocd.yaml`(无则只问 Git 地址写成 `repo:`)。按已有应用惯例改清单,从默认分支拉出分支开 MR。**停在 MR**,不合并、不 `kubectl apply` 工作负载。无 app-of-apps 时提醒用户首次 apply 那份 `application.yaml`。Harbor / TLS Secret 不入库。 diff --git a/skills/deployer/references/compose.md b/skills/deployer/references/compose.md new file mode 100644 index 0000000..d27d48c --- /dev/null +++ b/skills/deployer/references/compose.md @@ -0,0 +1,161 @@ +# Compose 轨道 + +同步文件、远程 `docker compose`、装 deb、新增/下线服务。Argo CD 不走本文件。 + +## 目录 + +- [两种布局](#两种布局) +- [定位部署根](#定位部署根) +- [列出服务](#列出服务) +- [命令选择](#命令选择) +- [新增服务 / 环境](#新增服务--环境) +- [下线服务](#下线服务) +- [安装 deb](#安装-deb) +- [NAS / rsync 失败](#nas--rsync-失败) +- [验证](#验证) + +## 两种布局 + +**A. 独立配置中心仓库**:仓库根即部署根,`DEPLOYER_ROOT=/path/to/repo` 指定后按仓库内相对路径操作: + +``` +repo/ +├── _config.yaml # 可选,全局默认 +├── vyyo1/_config.yaml # node: vyyo1(主机目录) +│ └── naiveproxy/ # 服务目录:compose.yaml + 可选 _config.yaml +└── unused/ +``` + +远程目录名 = 目录末级名:`vyyo1/naiveproxy` → `/opt/app/naiveproxy`。 + +**B. 项目内环境布局**:项目根放 `.pouch/deployer/{prod,test,dev}/`,每个环境一个目录。从项目内任意位置运行脚本即自动发现(也可用 `DEPLOYER_ROOT` 显式指定): + +``` +my-project/ +├── src/ ... +└── .pouch/deployer/ + ├── _config.yaml # 三个环境共享默认(node/base_path 等) + ├── argocd.yaml # 可选,Argo CD 指针(不是 compose 环境) + ├── prod/ + │ ├── compose.yaml + │ └── _config.yaml # 环境级覆盖 + ├── test/compose.yaml + └── dev/compose.yaml +``` + +项目模式下远程目录名自动加项目前缀 `{git仓库名}-{env}`(如 `my-project-prod`);`_config.yaml` 写 `name:` 可显式指定。 + +## 定位部署根 + +`scripts/deploy/` 是通用工具链,不依赖具体项目路径。部署根顺序: + +1. 环境变量 `DEPLOYER_ROOT`(独立配置中心仓库用这个) +2. 从当前目录向上找 `.pouch/deployer/`(项目内环境布局) +3. skill 安装位置兜底(仅查看,没有可部署服务) + +```bash +# = 本 skill 的 SKILL.md 所在目录 +# 布局 A +export DEPLOYER_ROOT=/path/to/your-compose-repo +python3 /scripts/deploy/list.py + +# 布局 B:cwd 在项目里即可 +python3 /scripts/deploy/list.py +``` + +## 列出服务 + +`list.py` 输出全部服务与节点分布;新增环境/服务后重跑确认被发现。项目布局下 `prod/test/dev` 各显示为 `{项目名}-{env}`。`argocd.yaml` 不会被当成 compose 服务。 + +查看单个服务的 node、远程路径、排除规则: + +```bash +python3 /scripts/deploy/sync.py +``` + +或读服务目录及祖先的 `_config.yaml`。 + +## 命令选择 + +语义严格区分,必须按**单服务**执行: + +| 意图 | 命令 | +|------|------| +| 只同步文件,不动容器 | `sync.py ` | +| 应用 compose/配置变更 | `sync.py && remote.py up` | +| 改配置后强制重建 | `remote.py recreate`(配合前置 sync) | +| 镜像 tag 变更升级 | `sync.py && remote.py upgrade` | +| 仅重启,不同步文件 | `remote.py restart` | +| 排查 | `remote.py ps` / `remote.py logs` | + +若项目有 Makefile 封装,命令形如 `make deploy TGT=<服务路径>`。没有 Makefile 时直接调 python 脚本,不要新建封装层。 + +`sync.py` 使用 `rsync -avz --delete`;本机无 rsync 时 tar over SSH 兜底。运行时数据必须放在默认排除的 `data/`、`_data/`,或 compose 挂载的远程绝对路径,否则会被清掉。 + +## 新增服务 / 环境 + +独立仓库布局: + +1. 在合适分类目录创建服务文件夹,写 `compose.yaml` +2. 在服务目录或祖先目录放 `_config.yaml`(至少能解析出 `node`) +3. 有运行时目录 → 加进 `sync_exclude` +4. 远程首次建目录:`ssh "mkdir -p /"` +5. 首次部署:sync + up +6. 验证:ps + logs,必要时 curl/ssh 检查端口 + +项目环境布局: + +1. 项目根建 `.pouch/deployer/{env}/`(env 通常为 prod/test/dev) +2. 每个环境写 `compose.yaml`;共享的 node/base_path 放 `.pouch/deployer/_config.yaml` +3. 环境有差异 → 在该环境的 `_config.yaml` 覆盖 +4. 同名冲突或需要固定远程目录名 → `_config.yaml` 写 `name:` +5. 首次部署前确认目标主机的远程目录不存在旧内容(rsync `--delete` 会清掉) + +## 下线服务 + +独立仓库布局:配置移入 `unused/`(自动脱离发现体系),远程按需手动清理: +`ssh "cd / && docker compose down"`,数据卷按需保留或删除。 +项目环境布局:删除对应 `.pouch/deployer/{env}/` 目录即可脱离发现体系,远程清理同上。 + +## 安装 deb + +`deb.py` 把 deb 包发到节点并安装。目标两种写法:仓库内目录(复用 `_config.yaml` 继承链解析 node/port/identity_file,如 `hosts/web1`),或裸 SSH 别名 / `user@host`(须在 `~/.ssh/config` 中,可加 `--port`/`--identity`)。 + +```bash +# 本地 .deb → scp 上传 → 远程 apt 安装(失败自动 apt -f 修依赖),成功后删暂存包 +python3 /scripts/deploy/deb.py push ./foo_1.0_amd64.deb --yes + +# 仅上传到远程暂存目录(默认 {base_path}/.debs;裸主机为 /tmp/deployer-debs) +python3 /scripts/deploy/deb.py scp ./foo_1.0_amd64.deb + +# 安装该节点暂存目录里已上传的全部 .deb +python3 /scripts/deploy/deb.py dpkg --yes + +# 远程直接从 URL 下载安装 +python3 /scripts/deploy/deb.py apt https://example.com/foo_1.0_amd64.deb --yes +``` + +- 非 root 用户走 `sudo -n`(需免密 sudo);`--yes` 传 `-y`。没配 sudo 免密时会直接失败。 +- 升级同版本号前可 `ssh "dpkg -I <暂存路径>"`;装完验证:`ssh "dpkg -l | grep "`。 + +## NAS / rsync 失败 + +部分 NAS 的 SSH 用户禁用 rsync 协议(Permission denied)。表现是 sync 报错但 ssh 正常。处理顺序: + +1. 该节点 `_config.yaml` 写真实 `base_path`(如 `/volume1/docker`,避开符号链接路径) +2. 仍失败则手动 tar over SSH: + +```bash +tar czf - -C <服务目录> . --exclude='data' --exclude='_data' \ + | ssh "mkdir -p / && cd / && tar xzf -" +ssh "cd / && /usr/local/bin/docker compose up -d" +``` + +tar 不会删除远程多余文件;需清理旧文件时手动 SSH 删除。Synology 上 docker 路径可能是 `/usr/local/bin/docker`。 + +## 验证 + +- `list.py` 输出全部服务与节点分布,数量与预期一致 +- 每次 sync/deploy 后 `remote.py ps` 容器 Up、`logs` 无报错 +- 升级后额外确认镜像 tag 与 `compose.yaml` 一致 +- 改 Traefik/Caddy 路由后 curl 对应域名验证生效