From 9f2bda28a0d447236090959bbbee8e6b60aba2eb Mon Sep 17 00:00:00 2001 From: lanrtop Date: Mon, 21 Sep 2026 12:55:02 +0900 Subject: [PATCH] chore(agent): add project workflow skills --- .agents/skills/architect/SKILL.md | 79 ++++++++++++ .agents/skills/catchup/SKILL.md | 65 ++++++++++ .agents/skills/retro-catchup/SKILL.md | 125 +++++++++++++++++++ .agents/skills/source-command-envoy/SKILL.md | 73 +++++++++++ .agents/skills/splitter/SKILL.md | 90 +++++++++++++ 5 files changed, 432 insertions(+) create mode 100644 .agents/skills/architect/SKILL.md create mode 100644 .agents/skills/catchup/SKILL.md create mode 100644 .agents/skills/retro-catchup/SKILL.md create mode 100644 .agents/skills/source-command-envoy/SKILL.md create mode 100644 .agents/skills/splitter/SKILL.md diff --git a/.agents/skills/architect/SKILL.md b/.agents/skills/architect/SKILL.md new file mode 100644 index 0000000..441d8c9 --- /dev/null +++ b/.agents/skills/architect/SKILL.md @@ -0,0 +1,79 @@ +--- +name: architect +description: 针对复杂新功能做架构分析,输出设计决策文档,为 splitter 提供输入。Use for L-complexity tasks before writing any code. +allowed-tools: Read, Glob, Grep, Bash(git log *), Bash(git diff *) +--- + +# 架构分析 + +在写任何代码之前,先理解现有结构,再做设计决策。 + +## 步骤 + +### 1. 读取项目上下文 +- 读取 `AGENTS.md` 了解技术栈和目录结构 +- 若存在 `.blueprint/manifest.yaml`,读取它了解模块全景和依赖关系 + +### 2. 分析现有实现模式 +根据需求涉及的层次读取核心文件: +- 数据层入口(数据库 schema、model 定义) +- 后端服务层(API / command 注册列表) +- 前端调用层(API 封装、状态管理) +- 相关功能模块的现有实现(同类功能参考) + +### 3. 识别系统边界 +确认本次需求涉及的层次变更: +- 是否需要新增数据表或字段 +- 是否需要新增后端接口 / command +- 前后端数据流如何变化 + +### 3.5 声明验证路径载体 + +读取项目 AGENTS.md 的「agent 按钮与验证路径」章节(若存在),按载体就近原则确认本功能的验证载体: + +| 项目类型 | 优先验证载体 | +|---------|------------| +| 桌面应用(Tauri) | 直接调用 command 函数(vitest / cargo test) | +| Web 服务 | HTTP API 端点(curl / supertest) | +| CLI / 脚本 | 命令行 / npm scripts | +| UI 呈现层 | Playwright 驱动真界面(最后手段,仅关键路径) | + +写一条示例验证步骤:`[载体类型] 调用/请求什么(参数) → 断言什么`。 + +### 4. 输出设计文档 + +``` +## 设计决策:<功能名> + +### 背景 +<关联的现有模块> + +### 方案选择 +<2-3 个方案及取舍,标注选定方案> + +### 受影响文件 +- 新增:<路径> — <用途> +- 修改:<路径> — <改动说明> + +### 系统边界变更 +<新增接口 / 数据表 / 字段定义> + +### 验证路径 +- 载体:<选定的验证载体(Tauri command / HTTP API / CLI / Playwright)> +- 示例:[载体] <具体调用>(<参数示例>) → <断言预期结果> + +### 风险点 +- <风险>:<规避方式> + +### 拆解建议 +建议拆为 N 张任务卡,依赖顺序:卡A → 卡B → 卡C +``` + +### 5. 更新蓝图(若项目有 .blueprint/) +- 若需要新模块,在 `manifest.yaml` 新增(status: concept) +- 创建对应 `modules/.md` 骨架 + +## 原则 +- **不写任何代码**,只输出设计文档 +- 设计文档要足够具体,让 splitter 能直接产出可派发任务卡 +- 需求不清晰时先向用户确认,再开始分析 diff --git a/.agents/skills/catchup/SKILL.md b/.agents/skills/catchup/SKILL.md new file mode 100644 index 0000000..064ecdf --- /dev/null +++ b/.agents/skills/catchup/SKILL.md @@ -0,0 +1,65 @@ +--- +name: catchup +description: 新会话快速续接:读取蓝图状态,找出中断任务,告诉你现在在哪、该干嘛。Use at the start of a new session to resume where you left off. +allowed-tools: Read, Glob, Grep +--- + +# 会话续接(Catch Up) + +新会话开始时快速还原上下文,找到中断点,给出明确的下一步。 + +## 步骤 + +### 1. 读取项目全景 + +读取 `.blueprint/manifest.yaml`,统计: +- 总模块数 / done / in_progress / planned / concept +- 总任务卡数 / done / in_progress(🔵)/ todo(📋)/ blocked(🔴) + +### 2. 找出中断任务(🔵) + +遍历所有 `modules/*.md`,找到前缀为 🔵 的任务卡(status: in_progress)。 + +对每张 🔵 卡: +1. 读取 `files` 字段列出的文件,查看当前代码实际状态 +2. 对比任务卡的 `acceptance` 验收标准 +3. 判断:已完成多少、还差什么 + +### 3. 找出可派发任务(📋) + +列出所有前缀为 📋 的任务卡(status: todo,有 files + acceptance),按模块分组。 + +### 4. 找出阻塞任务(🔴) + +列出所有前缀为 🔴 的任务卡,摘录 `blocked_reason`。 + +### 5. 输出续接报告 + +用以下格式输出,**简洁优先**: + +``` +## 当前状态 +X/Y 模块完成,Z 个进行中 + +## 中断任务(需要续接) +### 🔵 <任务卡标题> — <模块名> +- 已完成:<根据代码判断已实现的部分> +- 还差:<未完成的部分> +- 建议:从 <具体位置/函数> 继续 + +## 可立即派发(📋) +- <模块名> / <任务卡标题>(complexity: S/M) +... + +## 阻塞中(🔴) +- <任务卡标题>: +``` + +若没有中断任务,直接列出可派发任务和建议的下一步。 + +## 原则 + +- **不写任何代码**,只做状态诊断 +- 中断任务的判断依据是代码实际状态,不是任务卡写的 +- 若 🔵 任务的代码已经全部实现,直接说"可以关锁(标 ✅)" +- 输出要短,能让用户 30 秒内决定下一步 diff --git a/.agents/skills/retro-catchup/SKILL.md b/.agents/skills/retro-catchup/SKILL.md new file mode 100644 index 0000000..9f82e90 --- /dev/null +++ b/.agents/skills/retro-catchup/SKILL.md @@ -0,0 +1,125 @@ +--- +name: retro-catchup +description: 为项目中所有已完成但缺少复盘笔记的 M/L 任务卡补写历史复盘笔记,并通过 MCP append_project_note 写入炼境。Use when a project has completed M/L tasks but zero or few retrospective notes. +allowed-tools: Read, Glob, Grep, Bash(git log *), Bash(git diff *), Bash(python *), Bash(python3 *), mcp__lian* +--- + +# 复盘笔记补写(Retro Catch-Up) + +为已完成的 M/L 任务卡补写事后重建版复盘笔记,推动飞轮数据积累。 + +> ⚠️ 这些笔记是**事后重建**,基于任务卡内容 + git 历史推断,比实时记录精度低。但对识别高频模式仍然有价值。 + +## 写入通道(三级降级) + +每次调用 `append_project_note` 时,按以下顺序尝试,成功即停止: + +**① 原生 MCP**:若 `append_project_note` 工具可用,直接调用。 + +**② Python HTTP 直调**:若原生 MCP 不可用(Codex 与炼境握手失败的已知问题),读取项目 `.Codex/liangjing.json` 取 project_id 与端口,用 Python 直接 POST 炼境单一全局服务器: + +```python +import urllib.request, json, sys + +# 从 .Codex/liangjing.json 提取 project_id 和端口 +with open('.Codex/liangjing.json') as f: + ctx = json.load(f) +PROJECT_ID = ctx['project_id'] +port = ctx.get('mcp_port', 27190) + +url = f'http://localhost:{port}/mcp' + +def mcp_call(method, params={}): + payload = json.dumps({'jsonrpc':'2.0','id':1,'method':method,'params':params}).encode() + req = urllib.request.Request(url, data=payload, method='POST') + req.add_header('Content-Type', 'application/json') + req.add_header('Accept', 'application/json') + with urllib.request.urlopen(req, timeout=10) as r: + return json.loads(r.read().decode('utf-8', errors='replace')) + +# 调用示例 +result = mcp_call('tools/call', { + 'name': 'append_project_note', + 'arguments': {'project_id': PROJECT_ID, 'content': NOTE_CONTENT} +}) +``` + +**③ 本地文件兜底**:若炼境未运行(连接超时),将所有笔记追加写入 `.blueprint/retro-notes.md`,格式与正式笔记相同,头部加注 ``。 + +## 步骤 + +### 1. 确认写入通道 + 项目 ID + +按以下顺序确定: + +1. 检测 `append_project_note` 是否在可用工具中 → 是则用**通道①** +2. 否则检测 `localhost:27190` 是否可达(`curl -s --max-time 2 http://localhost:27190` 或 Python urlopen)→ 可达则用**通道②**,读取 `.Codex/liangjing.json` 直接获取 `project_id` 与端口 +3. 均不可达 → 用**通道③**,无需 project_id + +告知用户当前使用哪个通道,例如:`使用通道②(Python HTTP 直调)`。 + +### 2. 扫描所有已完成 M/L 任务卡 + +遍历 `.blueprint/modules/*.md`,收集满足以下条件的任务卡: +- 前缀为 ✅(status: done) +- complexity 为 `M` 或 `L` + +输出扫描结果:共找到 N 张,列出标题 + 所属模块。 + +### 3. 逐卡重建复盘笔记 + +对每张任务卡按顺序处理: + +**3a. 读取证据** +- 读取任务卡的 `files` 字段列出的所有文件(当前代码状态) +- 执行 `git log --oneline -- ` 查看相关文件的提交历史 +- 若提交数 > 1,执行 `git diff ^.. -- ` 了解变更量 + +**3b. 推断执行情况** +根据证据推断: +- **实际轮数**:相关文件的提交次数(粗估) +- **是否返工**:若同一文件有多次修改且 message 含 fix/修复/重新/又 等关键词 +- **返工原因**:从 commit message 或代码变更中推断 +- **有效策略**:从最终实现方式中提取关键设计决策 + +**3c. 写入笔记** + +按步骤 1 确定的通道调用 `append_project_note`,内容格式: + +``` +【复盘·重建】<任务标题> +任务类型: 后端命令 | 前端组件 | 数据层 | MCP工具 | 架构调整 +复杂度: M | L +实际轮数: N轮(事后推断,基于 git 提交数) +是否返工: 是/否/不确定 +返工原因: <若返工,从 commit message 推断> +有效策略: <从最终实现中提取的关键做法> +遗留风险: <若代码中有明显 TODO 或边界情况未处理> +备注: 此笔记为事后重建,非实时记录 +``` + +每写完一张,告知用户"✅ 已写入:<任务标题>"。 + +### 4. 输出汇总 + +``` +## 复盘补写完成 + +共处理 N 张 M/L 任务卡: +- ✅ 成功写入:X 张 +- ⏭️ 跳过(无足够证据):Y 张 + +飞轮状态:累计复盘笔记 Z 条 +``` + +## 跳过条件 + +以下情况跳过该任务卡,不强行写入: +- `files` 字段为空,且 git 中找不到相关提交 +- 任务卡内容过于简单(S 级错标为 M 的情况) + +## 原则 + +- 笔记头部必须标注 `【复盘·重建】` 与 `备注: 此笔记为事后重建`,与实时笔记区分 +- 宁可跳过,不要捏造。证据不足时注明"信息不足,无法推断" +- 每张卡独立处理,写入失败不影响后续 diff --git a/.agents/skills/source-command-envoy/SKILL.md b/.agents/skills/source-command-envoy/SKILL.md new file mode 100644 index 0000000..b47371c --- /dev/null +++ b/.agents/skills/source-command-envoy/SKILL.md @@ -0,0 +1,73 @@ +--- +name: "source-command-envoy" +description: "Migrated source command `envoy`" +--- + +# source-command-envoy + +Use this skill when the user asks to run the migrated source command `envoy`. + +## Command Template + + + +你是**炼境使者**——在子项目会话里代表炼境执行现场感知与回传。 + +直接执行以下步骤,无需用户提供任何输入。 + +## Step 1:读取项目身份 + +用 Read 工具读取 `.Codex/liangjing.json`,获取 `project_id` 和项目名称。 +若文件不存在:输出 `⚠️ 未找到 .Codex/liangjing.json,该项目未接入炼境` 并停止。 + +## Step 2:扫描本次会话 + +回顾本次会话的完整对话,识别有价值的洞察。 +跳过:纯代码实现细节、具体 bug 修复、一次性操作记录。 + +> ⚠️ **炼境定位讨论不得漏判**:凡涉及「炼境自身定位 / 缺口 / 演进方向 / 与其他工具的对比」的讨论,即便看起来像聊天而非技术实现,**默认视为体系级洞察,列入带回候选清单**。此类内容在历史会话中曾被漏传(判定为聊天),经用户追问才补发。 + +## Step 3:分类每条洞察 + +**前置硬门槛(先于一切分类判断)**:问自己——**任何有经验的工程师是否会提前想到这一点?** +- 会(常识性设计知识,如"外键优于业务字段关联")→ 一律归「留本项目」,不得回传 +- 触发条件过窄的 corner case(复现依赖本项目特定组合)→ 同样归「留本项目」 +- 只有**非显而易见、且跨项目可复用**的教训才有资格进入下方分类 + +**📦 带回炼境**(通过硬门槛后,满足任一条): +- 炼境分发的模板 / 约定 / 接入包有 bug 或可改进 +- 某工作流或实践有明确代价或验证结果(有具体证据) +- 会影响多个项目的体系级改进(哪怕还是假设) + +**🏠 留本项目**(同时满足以下所有): +- 只影响本项目的具体实现 +- 无任何跨项目复用价值 +- 纯猜测、零证据 + +## Step 4:发回炼境 + +对每条「带回」洞察,单独调用一次 `mcp__lian-jing__append_project_note`。 + +> **MCP 不可用时的降级**:若 `mcp__lian-jing__append_project_note` 报连接错误,重试 1~2 次仍失败,则将所有待回传内容按 Step 4 格式整理成一段文本,输出到对话让用户看到,并提示:「MCP 断连,请复制以上内容到炼境会话手动执行 `/envoy` 回传,或重连后重跑本命令」。 +- `project_id`:来自 Step 1 +- `content` 格式(严格遵守): + + 【炼境使者回传】来源: {项目名} + 类型: template_bug | validated_practice | workflow_hypothesis + 置信度: confirmed | under_validation + 影响范围: this_project | project_type:{类型} | all_projects + 内容: {一句话精确描述} + 建议炼境: fix_template | update_convention | log_for_review + +**`confirmed` 的门槛**:必须能陈述至少一条具体代价或验证结果(如"导致 N% 时间损耗"、"在 X 场景实测有效")。 +无法陈述具体证据的,一律标 `under_validation`,不得标 `confirmed`。 + +## Step 5:输出摘要 + +📦 已发回炼境 N 条 + · {标题}({置信度} · {影响范围}) + +🏠 留本项目 M 条 + · {标题} — {一句说明} + +若本次会话无任何体系级洞察,直接输出:`✅ 本次会话无需回传,无体系级洞察。` diff --git a/.agents/skills/splitter/SKILL.md b/.agents/skills/splitter/SKILL.md new file mode 100644 index 0000000..aaa49db --- /dev/null +++ b/.agents/skills/splitter/SKILL.md @@ -0,0 +1,90 @@ +--- +name: splitter +description: 将 architect 的设计文档拆解为任务卡,若项目有 .blueprint/ 则写入蓝图文件。Use after /architect for L-complexity tasks. +allowed-tools: Read, Edit, Write, Glob +--- + +# 任务拆解 + +将架构设计拆解为可独立执行的任务卡。 + +## 前提 +当前对话中应已有 `/architect` 输出的设计文档,包含受影响文件和拆解建议。 + +## 步骤 + +### 1. 确认任务管理方式 +- 若项目存在 `.blueprint/manifest.yaml` → 写入蓝图文件 +- 若不存在 → 以 Markdown 列表输出到对话,由用户决定放哪里 + +### 2. 拆解原则 + +**粒度控制** +- 每张卡 complexity 必须是 `S` 或 `M`,不允许 L +- S:单文件改动,逻辑简单,独立可完成 +- M:跨 2-3 个文件,有业务逻辑,但边界清晰 +- 拆出来还是 L → 继续细拆 + +**依赖顺序** +- 数据层(schema / model)→ 后端接口 → 前端封装 → UI 组件 +- 有依赖的卡填写 `depends` 字段 + +**可派发标准(每张卡必须满足)** +- `files`:明确列出涉及文件的相对路径 +- `acceptance`:**可执行验证路径**,格式:`[载体] 调用/运行什么(参数) → 断言什么` + - **载体来源(优先级)**: + 1. 先读 `.blueprint/manifest.yaml` 的 `agent_button_carrier` 字段 + 2. 无此字段时,从当前对话中 `/architect` 的「验证路径」声明继承 + 3. 两者都没有时,就近推断:Tauri 桌面应用 → `cargo test`,Web 服务 → HTTP API,CLI → 命令行 + - 断言要具体(检查字段值、返回码、文件存在、数量 > 0),不写模糊的"功能正常" + - 示例:`[Tauri command] apply_onboarding_pack(project_id) → 返回 written≥1,磁盘上文件存在` + - 示例:`[HTTP API] POST /api/projects → 201,body.id 非空` + - 示例:`[cargo test] cargo test parse_conventional → 6 个 case 全通过` +- `complexity`:S 或 M + +### 3a. 写入蓝图(有 .blueprint/ 时) + +读取 `.blueprint/modules/.md`,在末尾追加任务卡: + +```markdown +### 📋 <任务标题> +- status: todo +- complexity: S|M +- files: src/path/to/file.tsx, src-tauri/src/commands/xxx.rs +- depends: <依赖模块id>(可选) +- acceptance: "[载体] 调用什么(参数) → 断言什么" +``` + +然后更新 `manifest.yaml`:status → `planned`,`updated` 改为今天日期。 + +### 3b. 输出到对话(无 .blueprint/ 时) + +```markdown +## 任务拆解:<功能名> + +### 📋 <卡名>(S) +- files: ... +- acceptance: "[载体] 调用什么(参数) → 断言什么" + +### 📋 <卡名>(M) +- files: ... +- acceptance: "[载体] 调用什么(参数) → 断言什么" +- depends: 上一张卡 +``` + +### 4. 输出拆解摘要 + +``` +共 N 张任务卡,执行顺序: +1. 📋 <卡名>(S)— <一句话说明> +2. 📋 <卡名>(M)— <一句话说明> +3. 📋 <卡名>(M)— <一句话说明,depends: 卡2> +``` + +## 质量检查 +写完后逐张确认: +- [ ] 每张卡有 `files` +- [ ] 每张卡有 `acceptance` +- [ ] complexity 全部是 S 或 M +- [ ] 有依赖的卡填了 `depends` +- [ ] 任务卡按执行顺序排列