From 4ddae6be744749c2c8c5ac385df1b5061606728a Mon Sep 17 00:00:00 2001 From: lanyuanxiaoyao Date: Fri, 24 Apr 2026 18:12:23 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D=E6=96=87=E6=A1=A3=EF=BC=8C=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=E6=99=BA=E8=83=BD=E5=90=88=E5=B9=B6=E4=B8=8E=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=AE=A1=E6=9F=A5=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/prompts/README.md | 301 ++++++++++-- docs/prompts/prompt-apply-review.md | 127 +++-- docs/prompts/prompt-proposal-review.md | 87 +++- docs/prompts/prompt-smart-merge.md | 646 +++++++++++++++++++------ docs/prompts/prompt-spec-review.md | 139 ++++-- 5 files changed, 1032 insertions(+), 268 deletions(-) diff --git a/docs/prompts/README.md b/docs/prompts/README.md index 9f74edc..8dfff1f 100644 --- a/docs/prompts/README.md +++ b/docs/prompts/README.md @@ -1,61 +1,292 @@ # Prompts -面向 AI 大模型的提示词集合,每份提示词独立可用,完整复制给 AI 工具即可启动对应流程。 - -## 命名规则 - -文件名格式:`prompt-{action}.md`,`{action}` 使用明确无歧义的英文单词或短语,用连字符连接,例如 `prompt-smart-merge.md`、`prompt-spec-review.md`。 +面向 AI 大模型的执行型提示词集合。每份提示词都应能被单独复制使用,并驱动 AI 以一致的方式完成收集、分析、确认、执行和收尾。 ## 提示词 | 文件 | 用途 | | ---- | ---- | -| [prompt-smart-merge.md](prompt-smart-merge.md) | 批量合并 dev 分支到主干,含依赖分析、冲突处理、安全回退 | -| [prompt-spec-review.md](prompt-spec-review.md) | 审查和重构 openspec/specs/ 下的规范文件 | -| [prompt-proposal-review.md](prompt-proposal-review.md) | 审查 openspec 变更文档与讨论内容的一致性 | -| [prompt-apply-review.md](prompt-apply-review.md) | 审查代码实现与 openspec 变更文档的一致性 | +| [prompt-smart-merge.md](prompt-smart-merge.md) | 批量合并 `dev*` 分支到目标分支,含规则探测、依赖分析、冲突处理、安全回退 | +| [prompt-spec-review.md](prompt-spec-review.md) | 审查和整理 `openspec/specs/` 下的稳定规范,提升可检索性和一致性 | +| [prompt-proposal-review.md](prompt-proposal-review.md) | 审查 proposal/design/tasks/specs 与讨论、代码现状、OpenSpec 规范的一致性 | +| [prompt-apply-review.md](prompt-apply-review.md) | 审查 apply 后代码、测试、变更文档的一致性,并补齐遗漏或回写文档 | -## 书写原则 +## 设计目标 -### 面向 AI 而非人类 +从现有提示词提炼出的共同目标: -- 不写背景知识、适用场景、定期审查节奏等"补充说明",AI 只需要执行指令 -- 不写解释性注释(为什么用 merge 不用 rebase),直接作为约束声明 -- 不写示例输出模板,AI 自行推断格式 +- 面向执行,不面向讲解 +- 先收集证据,再做判断 +- 先计划和确认,再做有副作用的修改 +- 对缺失信息、规则冲突、上下文不足有降级路径 +- 对删除、重写、提交、回退、推送等高风险动作有明确授权边界 +- 执行后必须复核,形成闭环 -### 结构 +## 命名规则 -``` +文件名格式:`prompt-{action}.md` + +- `{action}` 使用明确、可搜索、无歧义的英文短语 +- 用连字符连接,不使用缩写、代号或过泛词 +- 优先体现动作和对象,如 `smart-merge`、`spec-review`、`apply-review` + +## 通用骨架 + +大多数提示词应遵循以下结构;按任务类型增删章节,但顺序尽量保持一致: + +```md 一句话描述任务目标 ## 约束 -全局不可违反的规则,顶部声明,不在步骤中重复 -## 1. 收集/准备 +## 1. 收集 / 准备 + ## 2. 分析 -## 3. 计划(用户确认) + +## 3. 报告 或 计划(用户确认) + ## 4. 执行(用户确认) -## 5. 清理/收尾 + +## 5. 清理 / 收尾 ``` -编号步骤,不用"第X步"(省 token)。步骤之间有确认节点的明确标注。 +适用方式: -### 精简 +- 审查型:`收集 → 分析 → 报告 → 计划 → 执行 → 收尾` +- 执行型:`准备 → 分析 → 计划 → 执行 → 清理` +- 纯报告型:可省略执行,但仍要保留“信息不足时如何降级”和“结果如何输出” -- 每句话只含一条指令,不嵌套子句 -- 表格优于列表,列表优于段落 -- 规则只声明一次,不在多处重复 -- 单文件控制在 150 行以内 +## 编写原则 -### 安全 +### 1. 面向 AI,不写背景说明 -- 破坏性操作(删除、重写、推送、合并提交)执行前必须用提问工具获得用户确认 -- 提供回退机制(安全锚点、备份标记、abort 路径) -- 危险命令的约束直接写在约束块中,不用"严禁""务必"等修饰词,用"禁止"即可 -- 信息展示分层渐进(概览 → 详情 → 原始数据),避免一次输出过多内容 +- 不写业务背景、适用场景、周期性说明、方法论阐释 +- 不写“为什么这么做”的长解释,直接写成规则或步骤 +- 不写示例输出模板,除非输出格式本身就是约束的一部分 -### 可操作性 +### 2. 证据先于结论 -- 给出具体命令或工具调用方式,不抽象描述("分析分支"→ "git diff --name-status target...branch") -- 标注并行/串行:可并行的步骤明确写"并行",有副作用的操作标注"串行" -- 用 `{占位符}` 标记需要 AI 替换的参数 +- 明确列出需要读取的文档、代码、测试、配置、命令结果 +- 能并行的步骤明确写“并行” +- 默认优先使用当前会话信息、现有文档和仓库规则 +- 只有在无法定位对象、范围或规则时,才引导 AI 向用户提问或运行补充命令 +- 不要求 AI 无差别全量扫描整个仓库;先建立索引,再做定向读取 + +### 3. 约束集中声明 + +- 全局不可违反的规则统一放在 `## 约束` +- 不在后续步骤反复重复同一条规则 +- 约束优先写边界、禁令、授权条件、同步要求、非目标 + +常见约束类型: + +- 只允许修改哪些对象,不允许修改哪些对象 +- 是否默认按某个 workflow 执行 +- 是否以代码、文档、讨论或用户确认为准 +- 何时必须使用提问工具确认 +- 删除、重写前是否必须备份 +- 改动后是否必须同步 README、测试、变更文档 + +### 4. 计划与执行分离 + +- 分析阶段只产出问题、风险、候选动作,不直接修改 +- 执行前必须先给出计划或批次方案 +- 批次计划必须能让用户看懂“改什么、为什么、影响什么、如何验证” +- 用户确认执行,不等于授权所有危险动作;额外高风险动作要单独确认 + +### 5. 闭环优先 + +- 执行后必须重新读取受影响对象并复核 +- 对代码修改要说明测试或验证方式 +- 对文档修改要检查相关文档之间是否同步一致 +- 收尾时要列出修改文件、备份文件、验证结果和残留风险 + +## 各章节写法 + +### 目标句 + +第一句只做三件事: + +- 说明任务对象 +- 说明最终目标 +- 说明执行方式或范围 + +要求: + +- 一句话写完 +- 不写背景铺垫 +- 尽量包含最终产物,如“生成计划”“回写文档”“整理稳定规范” + +### 约束 + +推荐写法: + +- 作用域边界:改什么,不改什么 +- 真相来源优先级:代码 / README / spec / 讨论 / 用户确认 +- 风险动作边界:删除、重写、提交、推送、回退、stash、merge 等 +- 同步要求:测试、README、变更文档、现有 spec 是否要同步 +- 降级规则:信息不足时如何处理 + +避免: + +- 在约束里塞步骤顺序 +- 同一规则在约束和执行里重复出现多次 + +### 收集 / 准备 + +要明确三类内容: + +- 读什么 +- 是否并行 +- 无法确定时如何补充定位 + +推荐做法: + +- 先读仓库规则来源,如 `README.md`、配置、架构文档、近期提交、任务入口 +- 先读直接相关 artifacts,再扩展到相关代码和测试 +- 需要探测时,要求 AI 先探测再决定,不把仓库结构写死在提示词里 + +### 分析 + +分析部分优先使用表格表达维度、优先级和判定规则。 + +推荐包含: + +- 优先级或维度表 +- 差异分类规则 +- 风险分级规则 +- 是否进入待确认清单的判定条件 + +常见分析模式: + +- `P0 / P1 / P2 / P3` 优先级 +- “过时 / 重复 / 冲突 / 错位 / 命名 / 格式” 维度 +- “文档要求未实现 / 代码修补未回写 / 双方冲突待确认” 差异分类 + +### 报告 / 计划 + +这是现有提示词最稳定的共性区块,建议固定包含: + +- 问题总览表 +- 逐项分析 +- 待确认清单 +- 分批执行方案 +- 预期结果或目录结构 + +若进入计划阶段,必须写清: + +- 改哪些文件或对象 +- 动作类型:删除、重命名、迁移、合并、拆分、补充、回写、修复 +- 修改原因 +- 预期影响 +- 验证方式 + +### 执行 + +执行部分要强调可操作性: + +- 明确顺序执行还是可并行执行 +- 明确每批执行前是否确认 +- 明确删除、重写、回退前是否要备份或创建锚点 +- 明确执行后最少要复核哪些点 + +推荐写法: + +- “逐批执行”或“逐项执行” +- “每批执行后重新读取受影响文件并复核” +- “若涉及删除或重写,先创建备份文件 `{file}.bak.{timestamp}`” + +### 清理 / 收尾 + +收尾要输出结果,不只说“完成”。 + +建议包含: + +- 修改文件清单 +- 备份文件清单 +- 测试 / 构建 / 验证命令与结果 +- 文档同步摘要 +- 残留问题、未验证项、待确认事项 + +## 交互与安全规范 + +### 必须确认的动作 + +以下动作默认都要在提示词中要求 AI 使用提问工具确认: + +- 删除文件或目录 +- 重写文件 +- 创建或恢复 stash +- 回退、reset、revert、abort +- 合并提交、推送、删分支、删远端分支、删 tag +- 任何会改变工作区现场且用户未明确授权的操作 + +### 授权边界要写清 + +提示词要明确区分: + +- “确认当前计划” +- “确认执行当前批次” +- “确认某个具体危险动作” + +不要把这些授权混为一谈。 + +### 回退路径要提前写好 + +对高风险流程,提示词应提供至少一种回退机制: + +- 备份文件 +- 安全锚点 tag +- `abort` 路径 +- 终止后的现场说明 + +## 表达与格式 + +- 优先使用表格表达规则、维度、状态、输出项 +- 列表优于段落 +- 每句话只写一条指令 +- 用 `{占位符}` 表示需要 AI 或用户填入的参数 +- 步骤编号使用 `## 1.`、`## 2.`,不用“第 X 步” +- 信息展示遵循“概览 → 详情 → 原始数据” + +## 仓库适配规则 + +- 若仓库文档已经定义命令、目录、提交格式、包管理器、工作流,提示词必须先遵守仓库文档 +- 若仓库未定义,再允许 AI 根据脚本、清单文件、近期提交历史推断 +- 不把当前仓库的偶然路径结构、命令名、分支名写死到所有提示词中 +- 只有当提示词本身就是为当前仓库的特定流程编写时,才写入仓库专属术语和路径 + +## 反模式 + +以下写法应避免: + +- 让 AI 一上来就全仓库无差别扫描 +- 在未分析前直接要求修改 +- 把代码现状直接当成唯一真相 +- 把历史变更文档直接当成稳定规范来源 +- 用抽象表述代替可执行动作 +- 把多个危险动作打包成一次默认授权 +- 没有备份、没有锚点、没有终止路径 +- 只要求“完成修改”,不要求复核和收尾 + +## 编写检查清单 + +编写完一份提示词后,至少自检以下问题: + +| 检查项 | 说明 | +| ---- | ---- | +| 目标是否单句明确 | 是否能一眼看出任务对象、目标和范围 | +| 约束是否集中 | 全局规则是否只在 `## 约束` 中声明 | +| 数据源是否具体 | 是否明确读哪些文档、代码、测试、命令结果 | +| 是否先分析再执行 | 是否存在独立的分析和计划阶段 | +| 是否有确认节点 | 高风险动作前是否要求提问工具确认 | +| 是否有降级路径 | change 不明、规则不明、上下文不足时是否有处理方式 | +| 是否可操作 | 是否给出命令、工具、路径或结构化动作 | +| 是否可验证 | 执行后是否定义复核或测试方式 | +| 是否能收尾 | 是否要求输出修改清单、备份、验证结果、残留风险 | + +## 维护原则 + +- 新增提示词前,先判断能否复用现有提示词的结构和术语 +- 修改提示词时,优先提炼共性,不为单次场景堆特例 +- 若某条规则已在多个提示词中稳定出现,应回收进本 README,作为统一编写规范 diff --git a/docs/prompts/prompt-apply-review.md b/docs/prompts/prompt-apply-review.md index d5a2c42..d2b9c91 100644 --- a/docs/prompts/prompt-apply-review.md +++ b/docs/prompts/prompt-apply-review.md @@ -1,71 +1,118 @@ -审查 openspec apply 完成后的实现是否与变更文档一致,按以下流程执行。 +审查 OpenSpec apply 完成后以及后续手动修补后的实际实现,判断代码、测试、变更文档是否一致,识别偏离、漏记和可优化点,并将确认后的实际变更同步回变更文档,按以下流程执行。 ## 约束 -- 仅审查代码和文档,不修改源码 -- 每批修改建议执行前用提问工具获得用户确认 -- 涉及删除/重写操作前必须备份原文件 +- 先审查再修复;未经用户确认,不修改代码或变更文档 +- 默认按 `spec-driven` workflow 审查;识别 change 后先确认 `schemaName`;若实际 schema 不同,说明差异,仅对实际存在的 artifacts 做审查 +- 优先使用当前会话中的实现说明、测试结论、手动修补记录和已生成的变更文档;仅在无法明确 change、`schemaName`、改动范围或修补来源时,再用提问工具或 OpenSpec 命令补充定位 +- 不要因为代码已经存在就自动以代码为准;先判断差异属于"文档要求未实现"、"测试后新增修补"还是"意外偏离/回归" +- 每批代码或文档修改执行前用提问工具获得用户确认 +- 删除/重写前用提问工具获得用户确认,并先备份原文件为 `{file}.bak.{timestamp}` +- 若修改代码涉及新逻辑、模块结构、API、实体或用户可见行为,同步更新测试、相关变更文档和 README ## 1. 收集 并行读取: -- 本次变更涉及的所有文档(proposal.md、design.md、tasks.md、specs/*.md) -- 实际变更的源码文件 -- 测试文件和测试结果 -- openspec/config.yaml +- 本次 change 的实际 artifacts;在 `spec-driven` 下通常包括 `proposal.md`、`design.md`、`tasks.md`、`specs/*.md` +- 当前会话中与本次变更相关的实现说明、apply 过程中的偏离、测试失败、手动修补原因、待确认事项 +- 与本次变更相关的代码和测试文件;优先依据 `git diff --name-only`、`git diff --name-only --cached`、`tasks.md`、Impact、失败测试栈定位;若工作区已干净,再结合文档和代码模块反推 +- 最近一次相关测试命令、测试结果、失败信息和修补后的验证结果 +- `openspec/config.yaml` +- 与本次改动相关的 README、架构文档,以及现有 `openspec/specs/**/spec.md` 中与本次变更相关的规范,相关性来源包括:`proposal.md` 的 `Capabilities` / `Modified Capabilities`、手动修补涉及的受影响能力、`design.md` / Impact 中提到的模块、相关代码对应的现有能力 + +若当前上下文无法明确 change 或文档路径: +- 先用提问工具让用户确认 change 名称或文档范围 +- 仍无法确认时,再执行 `openspec status --change "{name}" --json` 和 `openspec instructions apply --change "{name}" --json` 辅助定位 + +若已明确 change,但尚未确认 `schemaName`,先读取 change 元数据或执行 `openspec status --change "{name}" --json` 确认。 + +若缺少测试结果或手动修补记录,明确说明本次无法可靠判断部分差异的来源,仅能基于代码与文档现状审查。 ## 2. 分析 -根据上下文判断 apply 后是否有手动改动,将实现与文档双向对照: +按以下优先级检查: -| 维度 | 检查点 | -| ---- | ------ | -| 目标覆盖 | 代码实现是否覆盖 proposal 中的所有目标;是否有遗漏的功能点 | -| 方案一致性 | 实现是否与 design 中的技术方案一致;是否有偏离设计的地方 | -| 规范遵循 | 代码是否遵循 specs 中的规范要求;是否有违反 SHALL 约束的地方 | -| 任务完成度 | tasks 中每项任务是否真正完成;是否有未完成但标记完成的任务 | -| 测试完整性 | 测试是否覆盖所有场景;是否有跳过、取消、降低难度的测试;测试是否真正验证了功能 | -| 代码质量 | 是否有明显的代码问题(重复、复杂度过高、命名不清等);是否有可优化的地方 | +| 优先级 | 维度 | 检查点 | +| ---- | ---- | ------ | +| P0 | 实际实现与测试结论 | 当前代码的真实行为是什么;apply 后是否有手动改动或测试后修补;测试是否证明这些实现有效;若缺少测试结果,标记相关结论为"未验证";检查是否存在回归、未覆盖场景或被掩盖的问题 | +| P1 | 文档同步性 | 对实际存在的 artifacts 检查:已落地的实现、测试后新增修补、边界处理、异常路径、验证结论是否已同步回变更文档;若影响模块结构、API、实体或用户可见行为,再检查 README 是否同步 | +| P2 | 文档要求覆盖 | 对实际存在的 artifacts 检查:文档中承诺的目标、方案、Requirement、Scenario 是否都已实现;在 `spec-driven` 下重点检查 `proposal.md`、`design.md`、`specs/*.md`、`tasks.md` | +| P3 | 实现质量 | 代码结构、复用、命名、复杂度、错误处理、测试质量、与项目现有模式的一致性是否存在明显问题或可优化点 | + +分析时区分三类差异: +- 文档要求已明确,但代码未实现或实现不完整 → 需补充代码或测试 +- 代码因测试暴露问题、手动修补或合理落地细化而新增/变更 → 需回写文档 +- 代码与文档不一致,且无法判断应以哪边为准 → 列入待确认清单 + +不要把以下情况直接视为合理修补: +- 通过 `skip`、`only`、弱化断言、绕过错误处理来让测试通过 +- 为了贴合现有代码而降低已确认的 Requirement 或行为约束 +- 未经过讨论和验证就扩大功能范围 重点识别: -- 文档要求但未实现的功能 → 需补充代码 -- 实现与文档描述不一致的地方 → 根据上下文判断:apply 后手动改动则更新文档,否则确认修正方向 -- 实现了但文档未提及的功能 → 根据上下文判断:apply 后手动改动则补充文档,否则标记为未讨论的新增 -- 标记完成但实际未完成的任务 -- 掩盖错误的测试(skip、only、降低断言强度等) +- 文档要求但未落地的功能、场景、异常处理或验证步骤 +- apply 完成后新增的代码修补、边界处理、接口调整、行为变化未同步到文档 +- `tasks.md` 标记完成,但代码、测试或文档未闭环 +- `Modified Capabilities` 应更新但未更新的现有 spec +- 代码存在明显的重复、复杂度过高、命名不清、错误处理薄弱、测试质量不足等问题 输出审查结果: 1. **问题总览表**:问题类型 × 涉及文件数 -2. **逐项分析**:每个问题文件,说明问题、影响和建议 -3. **未覆盖清单**:哪些文档要求未在代码中实现(需补充代码) -4. **不一致清单**:哪些实现与文档描述不一致(需确认修正方向) -5. **需补充文档清单**:哪些代码改动未在文档中体现(需补充文档) -6. **任务问题清单**:哪些任务未真正完成或标记错误 -7. **测试问题清单**:哪些测试存在问题或掩盖了错误 -8. **优化建议清单**:哪些代码可以优化 +2. **实际改动与修补清单**:本次实现中已落地的主要功能、后续修补和验证结论;若缺少测试结果,对未验证部分单独标记 +3. **未覆盖清单**:文档要求但未在代码中实现或未充分验证的内容 +4. **需回写文档清单**:代码和测试中已确认、但文档未体现的实现、修补或约束变化 +5. **方向待确认清单**:代码与文档不一致,且无法判断应以哪边为准的事项 +6. **任务状态问题清单**:未真正完成、状态错误或需补充的新任务 +7. **测试问题清单**:缺失覆盖、掩盖错误、验证不足或修补后未回归验证的测试问题 +8. **代码质量/优化清单**:可优化的实现问题和建议 +9. **逐项分析**:每个问题说明位置、问题、影响、建议和建议修复方向 若所有清单均为空,输出"审查通过,未发现问题",跳至步骤 5。 ## 3. 计划(用户确认) -针对发现的问题,分类提出修复方案: +先针对"方向待确认清单"用提问工具逐项向用户确认。 -**需补充代码**:文档要求但未实现的功能,建议补充实现。 +再整理完整修复方案,按类别列出: +- 代码或测试补充:补实现、补异常处理、补回归测试、修复掩盖错误的测试 +- 文档回写:同步 `proposal.md`、`design.md`、`tasks.md`、`specs/*.md`、README 中遗漏或过时的内容 +- 任务状态修正:修正已完成/未完成状态,补充 apply 后新增但已完成的修补任务或验证任务 +- 代码质量优化:在不改变目标行为的前提下优化结构、复用、命名或可维护性 -**需补充文档**:代码已实现但文档未记录,且上下文确认为 apply 后手动改动,建议更新 proposal/design/tasks/specs。 - -**需确认修正方向**:实现与文档不一致,且上下文无法判断: -- 若为 apply 后手动改动 → 更新文档 -- 否则用提问工具确认以文档还是代码为准 - -**任务和测试问题**:逐项说明未完成原因、测试掩盖错误的风险,提出修复方案。 +对每个拟修改的文件说明: +- 修改内容 +- 修改原因 +- 预期影响 +- 验证方式 +- 若存在分支方案,分别说明适用前提 用提问工具展示完整修复方案,获得用户确认后执行。 ## 4. 执行 -逐项执行修复方案。 +逐项执行已确认的代码、测试和文档修复。 + +若涉及删除或重写: +- 先创建备份文件 `{file}.bak.{timestamp}` +- 再执行修改 + +若修改了代码或测试: +- 同步更新相关变更文档;若影响模块结构、API、实体或用户可见行为,再同步 README +- 运行相关测试;若修补影响范围较大,再补充执行受影响的回归测试 + +若修改了文档: +- 确认实际存在的变更文档之间保持一致;在 `spec-driven` 下重点检查 `proposal.md`、`design.md`、`tasks.md`、`specs/*.md` +- 若 apply 后新增修补改变了能力边界或行为约束,同步更新 `Capabilities` / `Modified Capabilities` + +执行后重新读取所有被修改的代码、测试和文档,并复核: +- "未覆盖清单" 是否已清空或已标注保留原因 +- "需回写文档清单" 是否已清空 +- "方向待确认清单" 是否已清空或已记录用户决策 +- "任务状态问题清单" 和 "测试问题清单" 是否已清空或已标注残留原因 +- "代码质量/优化清单" 中哪些已处理,哪些有意延期 ## 5. 收尾 -列出所有修改的文件和变更摘要。 +列出所有修改的文件、备份文件、测试命令与结果、文档同步摘要和剩余风险。 + +若本次因缺少测试结果、修补记录或上下文而降级执行,或有问题因信息不足暂未处理,单独说明。 diff --git a/docs/prompts/prompt-proposal-review.md b/docs/prompts/prompt-proposal-review.md index 75eed82..e6327fa 100644 --- a/docs/prompts/prompt-proposal-review.md +++ b/docs/prompts/prompt-proposal-review.md @@ -1,56 +1,91 @@ -审查 openspec 变更文档(proposal、design、tasks、specs)是否完整准确地记录技术方案,按以下流程执行。 +审查本次 OpenSpec 变更文档是否与前序讨论、当前代码现状和 OpenSpec 文档规范一致,识别遗漏、冲突和不合理假设,并给出可执行的补充建议,按以下流程执行。 ## 约束 -- 仅审查文档内容,不修改源码 -- 每批修改建议执行前用提问工具获得用户确认 -- 涉及删除/重写操作前必须备份原文件 +- 仅修改本次变更文档,不修改源码 +- 默认按 `spec-driven` workflow 审查;识别 change 后先确认 `schemaName`;若实际 schema 不同,说明差异,仅对实际存在的 artifacts 做审查 +- 优先使用当前会话中的讨论和已生成的变更文档;仅在无法明确 change、`schemaName` 或文档范围时,再用提问工具或 OpenSpec 命令补充定位 +- 每批文档修改建议执行前用提问工具获得用户确认 +- 删除/重写前用提问工具获得用户确认,并先备份原文件为 `{file}.bak.{timestamp}` ## 1. 收集 并行读取: -- 本次变更涉及的所有文档(proposal.md、design.md、tasks.md、specs/*.md) -- 之前上下文中讨论的内容 -- openspec/config.yaml -- 与变更规范有依赖关系的其他规范 +- 本次 change 的实际 artifacts;在 `spec-driven` 下通常包括 `proposal.md`、`design.md`、`tasks.md`、`specs/*.md` +- 当前会话中与本次变更相关的讨论、澄清、边界约束、非目标、待确认事项 +- 与本次变更直接相关的源码、测试、README、架构文档 +- `openspec/config.yaml` +- 现有 `openspec/specs/**/spec.md` 中与本次变更相关的规范,相关性来源包括:`proposal.md` 的 `Capabilities` / `Modified Capabilities`、讨论中提到的受影响能力、`design.md` / Impact 中提到的模块、相关代码对应的现有能力 + +若当前上下文无法明确 change 或文档路径: +- 先用提问工具让用户确认 change 名称或文档范围 +- 仍无法确认时,再执行 `openspec status --change "{name}" --json` 和 `openspec instructions apply --change "{name}" --json` 辅助定位 + +若已明确 change,但尚未确认 `schemaName`,先读取 change 元数据或执行 `openspec status --change "{name}" --json` 确认。 + +若缺少讨论记录,明确说明本次降级为"文档 + 代码现状审查",不做讨论一致性结论。 ## 2. 分析 -将文档与讨论内容逐项对照,检查: +按以下优先级检查: -| 文档 | 检查点 | -| ---- | ------ | -| proposal.md | 是否完整记录讨论确定的目标、范围、影响;是否遗漏决策点 | -| design.md | 是否覆盖讨论中所有技术方案;边界条件和异常处理是否与讨论一致 | -| tasks.md | 是否覆盖 design 中所有方案;任务划分是否合理;依赖关系是否明确 | -| specs/*.md | 是否严格遵循 OpenSpec 格式;术语是否一致;依赖声明是否完整;无实现细节混入 | +| 优先级 | 维度 | 检查点 | +| ---- | ---- | ------ | +| P0 | 讨论一致性 | 仅在存在讨论记录时检查:文档是否完整覆盖已确认的目标、范围、非目标、约束、边界条件、风险、决策点、待办事项;若无讨论记录,标记为"跳过" | +| P1 | 代码现实性 | 文档对当前模块、接口、数据结构、命名、依赖、目录结构、复用路径的描述是否准确;是否把"计划变更"误写成"当前现状";是否遗漏真实受影响的现有能力 | +| P2 | 文档内部一致性 | 对实际存在的 artifacts 检查是否互相支撑;在 `spec-driven` 下重点检查 `proposal.md`、`design.md`、`tasks.md`、`specs/*.md`;`Capabilities` / `Modified Capabilities` 是否完整;每个 capability 是否有对应 spec;`tasks.md` 是否覆盖 `design.md` 和 `specs/*.md` | +| P3 | OpenSpec 合规性 | 对实际存在的 artifacts 检查是否遵循 OpenSpec 格式和术语;`specs/*.md` 是否只描述行为与约束、不混入实现细节;`tasks.md` 是否一行一个任务;是否混入 git 操作任务 | + +分析时区分两类情况: +- 文档对当前代码现状的描述错误 +- 文档描述的是预期变更,本来就应当与当前代码不同 重点识别: -- 讨论中确定但文档未记录的内容 -- 文档描述与讨论不一致的地方 -- 文档新增但未在讨论中提及的内容 +- 讨论中已确定但文档未记录的内容 +- 文档基于错误现状做出的设计或任务拆分 +- 文档之间相互冲突的目标、方案、约束、任务 +- `proposal -> specs -> design -> tasks` 链路中的断点 +- `Modified Capabilities` 应更新但未更新的现有 spec 输出审查结果: 1. **问题总览表**:问题类型 × 涉及文档数 -2. **逐项分析**:每个问题文档,说明问题、影响和建议 -3. **缺失清单**:哪些技术方案/需求未在文档中体现 -4. **冲突清单**:哪些描述与其他文档或讨论结果不一致 -5. **待澄清清单**:哪些事项描述不明确,需要进一步确认 +2. **讨论遗漏清单**:讨论已确定但文档未体现的内容;若缺少讨论记录,标记为"未审查" +3. **现实性问题清单**:与当前代码现状不符的描述、假设或影响分析 +4. **文档冲突清单**:proposal、design、tasks、specs 之间的不一致 +5. **OpenSpec 规范问题清单**:格式、术语、结构问题 +6. **待澄清清单**:仅靠讨论和代码仍无法判断的事项 +7. **逐项分析**:每个问题说明位置、问题、影响、建议 +8. **补充建议方案**:按文件列出建议补充/修正的内容、原因和可选方案 若所有清单均为空,输出"审查通过,未发现问题",跳至步骤 5。 ## 3. 计划(用户确认) -针对发现的问题,提出修复方案(补充遗漏、修正冲突、优化表述)。 +先针对"待澄清清单"用提问工具逐项向用户确认。 -针对待澄清清单,用提问工具逐项向用户确认,根据反馈更新文档。 +再整理完整修复方案,按文件列出: +- 建议修改的文件 +- 需要补充或修正的内容 +- 修改原因 +- 若存在分支方案,分别说明适用前提 用提问工具展示完整修复方案,获得用户确认后执行。 ## 4. 执行 -逐项执行修复方案。 +逐项修改已确认的变更文档,不修改源码。 + +若涉及删除或重写: +- 先创建备份文件 `{file}.bak.{timestamp}` +- 再执行修改 + +执行后重新读取所有被修改的文档,并复核: +- "讨论遗漏清单" 是否已清空或已标注保留原因 +- "现实性问题清单" 是否已清空或已标注为预期变更 +- "文档冲突清单" 和 "OpenSpec 规范问题清单" 是否已清空 ## 5. 收尾 -列出所有修改的文件和变更摘要。 +列出所有修改的文件、备份文件和变更摘要。 + +若本次因缺少讨论记录而降级执行,或有问题因信息不足暂未处理,单独说明。 diff --git a/docs/prompts/prompt-smart-merge.md b/docs/prompts/prompt-smart-merge.md index 8089a20..1e8bf39 100644 --- a/docs/prompts/prompt-smart-merge.md +++ b/docs/prompts/prompt-smart-merge.md @@ -1,219 +1,595 @@ -将所有 `dev*` 分支智能合并到目标分支(默认 main),三阶段执行:计划审批(步骤1-3)→ 自动合并(步骤4)→ 汇总收尾(步骤5)。 +将所有 `dev*` 分支按计划合并到目标分支(默认 `main`),按准备→分析→计划→执行→清理执行;先探测当前仓库的规则、模块边界、验证命令和提交风格,再基于探测结果执行,避免写死仓库结构。 ## 约束 -- 全程仅使用 `git merge`,禁止 rebase -- `git add` 仅指定明确的文件路径,禁止 `git add .`/`git add -A` -- `git reset --hard` 仅配合安全锚点 tag 使用,禁止裸用 -- 冲突文件禁止 AI 自主决定写入内容;用户在冲突面板中选择方案后,AI 按选定方案执行写入,属于授权行为 -- 禁止自动 `git push` -- 合并提交的确认在步骤 3 一次性完成,分支删除的确认在步骤 5 一次性完成;阶段二仅在冲突/异常时中断 -- 语义审查的修复提交独立于合并提交,必要时可单独 revert -- 禁止使用 npm/npx/pnpm,前端命令统一使用 bun +- 全程仅使用 `git merge` 完成分支集成,禁止 `rebase` +- `git add` 仅允许明确文件路径,禁止 `git add .`、`git add -A` +- 不直接使用默认 `git pull`;同步目标分支时仅允许显式策略:`git fetch` + `git merge`,或 `git pull --no-rebase` +- `git reset --hard` 仅允许回到已记录的安全锚点 tag,且执行前必须再次确认 +- `git stash push`、`git stash apply`、`git stash drop`、`git revert`、`git branch -d`、`git push {remote} --delete {branch}` 执行前都必须再次确认 +- 禁止自动推送代码;远端分支删除仅在步骤 5 获得确认后执行 +- 冲突文件禁止 AI 自主决定写入内容 +- 用户选择 `--ours`、`--theirs`、保留删除的一侧、保留重命名的一侧等机械方案后,AI 可执行对应写入 +- 凡涉及“双保留”“重组逻辑”“补写缺失代码”等内容生成,必须逐文件展示最终结果并再次获得确认后写入 +- 步骤 3 的“确认执行”仅授权按计划执行正常 merge,不授权自动执行 `stash`、`reset --hard`、`revert`、`drop`、删除分支、远端删除、冲突内容重写 +- 合并提交与语义审查修复提交必须分离;语义审查修复允许拆成多条独立提交 +- 若仓库文档定义了命令、包管理器、提交格式、目录规范,优先遵守文档;若未定义,再根据清单文件、脚本和近期提交历史推断 +- 不把当前仓库的路径结构、技术栈、构建命令写死到流程里;一切按探测结果执行 +- 信息展示按“概览 → 详情 → 原始数据”分层输出,避免一次性输出全部 diff -## 安全锚点体系 +## 记录项 + +执行中持续维护以下记录,后续所有决策和总结都基于这些记录: + +| 记录项 | 内容 | +| ---- | ---- | +| `session_timestamp` | 本次流程唯一时间戳 | +| `target` | 目标分支名 | +| `target_upstream` | 目标分支上游,如 `{remote}/{target}`;无则记为空 | +| `target_remote` | 从 `target_upstream` 解析出的远端名;无上游则优先使用默认远端,否则为空 | +| `repo_rules` | 从 README、CONTRIBUTING、开发文档、脚本、清单文件中识别出的规则 | +| `commit_style` | 仓库现有提交信息风格和默认合并/修复提交模板 | +| `module_map` | 按当前仓库结构推断出的模块边界、公共目录、配置目录、基础设施目录 | +| `validation_commands` | 按模块或作用域归纳出的 lint/build/test 命令 | +| `auto_stashes[]` | 本流程创建的 stash 列表,记录唯一 message、创建时 ref、创建顺序、后续是否恢复/保留 | +| `created_local_tracking_branches[]` | 为远端独有 `dev*` 分支创建的本地跟踪分支 | +| `global_tag` | 全局安全锚点 | +| `branch_tags[]` | 每个待合并分支对应的分支级安全锚点 | +| `analysis[]` | 每个分支的分析快照:HEAD hash、提交数、变更文件、依赖、初始冲突预测、风险、语义审查模式 | +| `results[]` | 每个分支的最终状态:已合并、已跳过、已回退、失败原因、修复提交列表、验证结果 | + +## 安全锚点 | 锚点 | 创建时机 | 用途 | | ---- | -------- | ---- | -| `pre-merge-backup-{timestamp}` | 步骤 1,合并前目标分支 HEAD | 全局回退点,可撤销所有合并恢复到初始状态 | -| `merge-before-{分支名}-{timestamp}` | 步骤 4 每个分支合并前 | 分支级回退点,撤销单个分支的合并和修复 | +| `pre-merge-backup-{timestamp}` | 步骤 1 完成目标分支准备后 | 全局回退点,恢复到本轮合并开始前的目标分支状态 | +| `merge-before-{branch}-{timestamp}` | 步骤 4 每个分支正式 merge 前 | 分支级回退点,回退当前分支的合并提交和其后的语义修复提交 | -全局锚点在步骤 4 中不主动使用,仅在用户需要"全部重来"时手动使用:`git reset --hard pre-merge-backup-{timestamp}`。 +除非用户明确要求“全部回退”或“放弃当前分支并回到分支级锚点”,否则不主动使用 `git reset --hard`。 -## 1. 准备(自动) +## 1. 准备 -- `git status` 检查工作区 - - 不干净:`git stash push --include-untracked -m merge-auto-stash-{timestamp}`,记录 stash 引用,步骤 5 末尾恢复 -- 默认目标分支 main,用提问工具让用户确认或指定其他分支(选项:`main` / `develop` / 用户自定义,用户自定义时等待输入分支名) -- `git checkout {target}` - - 失败(分支不存在):用提问工具让用户选择其他分支或终止 -- `git pull` - - 失败:报告错误,用提问工具让用户选择:强制拉取(`git pull --rebase` 不允许,仅 `git fetch` + 手动合并)/ 终止 -- `git fetch --all` 拉取远端引用 -- 列出 dev 分支(本地 + 远端分开): - - 本地:`git branch --list 'dev*'` - - 远端仅存在:`git branch -r --list 'origin/dev*'`,对远端独有的分支执行 `git checkout -b {分支名} origin/{分支名}` 拉取到本地 - - 若本地已存在同名分支:报告冲突,用提问工具让用户选择:使用本地版本 / 重命名后拉取 / 跳过 - - 无任何 dev 分支则结束 -- 创建全局安全锚点:`git tag pre-merge-backup-{timestamp}` +### 1.1 仓库规则探测 + +并行收集当前仓库的规则来源: + +- 根目录文档:`README*`、`CONTRIBUTING*`、`DEVELOPMENT*`、`docs/**` 中与开发、构建、测试、提交流程有关的文档 +- 常见任务入口:`Makefile`、`justfile`、`Taskfile.yml`、`package.json`、工作区配置、CI 文件、脚本目录 +- 常见清单/锁文件:`package-lock.json`、`pnpm-lock.yaml`、`yarn.lock`、`bun.lock*`、`go.mod`、`Cargo.toml`、`pyproject.toml`、`pom.xml`、`build.gradle*` 等 +- 近期提交:`git log --oneline -20` + +探测目标: + +| 项目 | 识别方式 | 记录结果 | +| ---- | -------- | -------- | +| 包管理器/任务入口 | 文档、锁文件、任务文件、脚本 | 记录允许的执行方式和优先级 | +| 模块边界 | 顶层目录、工作区配置、语言清单文件、子项目 README | 记录 `module_map` | +| 公共/基础设施目录 | shared/common/lib/core/config/scripts/ci 等目录和根级配置文件 | 记录到 `module_map` | +| 验证命令 | 文档中的 lint/build/test 命令,或脚本中的标准任务 | 记录到 `validation_commands` | +| 提交风格 | 文档约束优先,否则看近期 `git log` | 记录 `commit_style` | + +识别规则: + +- 文档和脚本冲突时,以文档为准 +- 文档缺失时,以仓库当前可见的任务入口和近期提交习惯为准 +- 无法确定时,先在步骤 3 的计划表中展示“待确认规则”,由用户确认 + +### 1.2 初始化现场 + +- 执行 `git status --short --branch`,记录当前分支和工作区状态 +- 执行 `git remote -v`,记录可用远端 +- 用提问工具确认目标分支:`main` / `master` / `develop` / 用户自定义 + +### 1.3 处理非干净工作区 + +- 若 `git status --porcelain` 非空,先展示变更文件概览,再用提问工具让用户选择: + - `stash 后继续` + - `终止` +- 用户选择 `stash 后继续` 后,执行 `git stash push --include-untracked -m smart-merge-{timestamp}-precheck-{n}` +- 记录 stash 唯一 message 和创建时 ref 到 `auto_stashes[]` + +### 1.4 切换并校验目标分支 + +- 执行 `git checkout {target}` +- 若失败,使用提问工具让用户选择: + - `重新指定目标分支` + - `终止` + +### 1.5 解析上游并同步远端引用 + +- 执行 `git for-each-ref --format='%(upstream:short)' refs/heads/{target}` 获取 `target_upstream` +- 若存在 `target_upstream`: + - 解析 `target_remote` + - 执行 `git fetch {target_remote} --prune` + - 执行 `git rev-list --left-right --count {target}...{target_upstream}` 计算 ahead/behind +- 若不存在 `target_upstream`: + - 若仓库存在默认远端,记为 `target_remote` + - 否则 `target_remote` 置空 + +目标分支同步决策: + +| 状态 | 处理 | +| ---- | ---- | +| 无 upstream | 记录后继续,不自动同步 | +| 仅落后 upstream | 用提问工具选择:`快进同步` / `保持当前本地 HEAD` / `终止`;若选同步,执行 `git merge --ff-only {target_upstream}` | +| 仅领先 upstream | 记录后继续,不自动 push | +| 与 upstream 分叉 | 用提问工具选择:`保持当前本地 HEAD` / `终止`;不自动把 upstream merge 进 target | + +### 1.6 收集候选分支 + +- 本地分支:`git branch --list 'dev*'` +- 若 `target_remote` 非空,远端分支:`git branch -r --list '{target_remote}/dev*'` +- 过滤掉 `HEAD ->` 这类符号引用 +- 计算“远端存在、本地不存在”的分支列表 + +对远端独有分支,不直接 `checkout`,改为先展示清单,再用提问工具选择: + +- `全部创建本地跟踪分支` +- `选择部分创建` +- `仅使用已有本地分支` +- `终止` + +创建本地跟踪分支使用:`git branch --track {local_branch} {remote}/{remote_branch}` + +若本地已存在同名分支,使用提问工具逐项选择: + +- `使用现有本地分支` +- `改名创建跟踪分支` +- `跳过该远端分支` + +所有自动创建的本地跟踪分支都记录到 `created_local_tracking_branches[]`。 + +### 1.7 无候选分支时直接结束 + +- 若最终没有任何 `dev*` 分支,输出概览:目标分支、工作区状态、探测到的仓库规则、是否创建过 stash、是否创建过本地跟踪分支 +- 若本流程已创建 stash,进入步骤 5 的“工作区恢复” +- 否则直接结束 + +### 1.8 创建全局安全锚点 + +- 执行 `git tag pre-merge-backup-{timestamp}` +- 记录为 `global_tag` ## 2. 分析 ### 2.1 信息收集(并行) -对每个 dev 分支并行收集: +对每个候选分支并行收集以下信息: -| 维度 | 命令/方式 | -| ---- | --------- | -| 基础 | 分支名、`git rev-parse {branch}` 记录 HEAD commit hash、commit 数/消息、`git branch --merged` 判断是否已合并 | -| 变更 | `git diff --name-status {target}...{branch}`、按文件路径推断所属模块(如 `backend/api/` → API)、行数统计 | -| 依赖 | 收集各分支变更文件列表,求交集判断文件重叠;重叠文件涉及公共模块(共享类型、工具函数、配置)的标记为有依赖关系 | -| 公共文件清单 | 基于依赖分析,标记出主分支上的公共文件路径列表,供步骤 4 语义审查使用 | +| 维度 | 命令/方式 | 结果 | +| ---- | --------- | ---- | +| 基础 | `git rev-parse {branch}` | 记录分支 HEAD hash | +| 合并状态 | `git merge-base --is-ancestor {branch} {target}` | 判断该分支是否已完全被目标分支包含 | +| 提交范围 | `git log --oneline {target}..{branch}` | 记录独有提交数和提交消息,推断分支意图 | +| 变更范围 | `git diff --name-status {target}...{branch}` | 记录文件列表、状态、变更集中区域 | +| 行数统计 | `git diff --stat {target}...{branch}` | 估算改动体量 | +| 模块归属 | 按 `module_map` 归类;若未命中则按顶层目录或最近的语言清单文件归类 | 识别受影响模块 | -### 2.2 冲突预测(串行) +模块归类优先级: -`git merge --no-commit --no-ff` 会修改工作区和索引,禁止并行,逐个分支串行执行: +1. 仓库文档明确声明的子项目、包、服务、应用、库 +2. 工作区配置或语言清单文件定义的模块边界 +3. 顶层目录边界 +4. 根级共享文件、配置文件、脚本、CI 文件,统一归为 `shared/config/infra` -`git merge --no-commit --no-ff {branch}` → `git diff --name-only --diff-filter=U` 收集冲突文件 → `git merge --abort` +常见的 `shared/config/infra` 候选包括但不限于: -若 `git merge --abort` 失败,执行 `git reset --hard pre-merge-backup-{timestamp}` 恢复到全局安全锚点后继续。若 hard reset 也失败,报告严重错误,终止流程,提示用户手动处理。 +- 根目录配置文件、锁文件、工作区文件 +- 构建脚本、部署脚本、CI 配置、容器配置、基础设施配置 +- 公共库目录、共享类型目录、通用组件目录、公共工具目录 -### 2.3 分析结果汇总 +### 2.2 依赖判定 -汇总 2.1 和 2.2 的结果,产出每个分支的:基础信息(含 HEAD hash)、变更范围、依赖关系、冲突预测。供步骤 3 和步骤 4 使用。 +依赖同时从 ancestry 和文件重叠两个维度判断: -## 3. 计划(用户确认 — 阶段一唯一介入) +| 维度 | 方法 | 判定规则 | +| ---- | ---- | -------- | +| ancestry 依赖 | `git merge-base --is-ancestor {a} {b}` | 若 `a` 是 `b` 的祖先,记为 `b 依赖 a` | +| 文件重叠 | 比较各分支 `git diff --name-only {target}...{branch}` | 同一文件被多个分支修改,记为重叠 | +| 公共文件依赖 | 关注 `shared/config/infra` 范围和公共抽象 | 即使文件数少,也记为高优先级依赖 | -按优先级排序:已合并(跳过) → 公共/基础设施变更(变更文件仅涉及 2.1 标记的公共文件清单中的文件) → 独立模块 → 有依赖的 → 高冲突/跨模块。 +为每个分支输出: + +- `depends_on[]`:它依赖哪些分支 +- `blocks[]`:哪些分支依赖它 +- `shared_files[]`:与其他分支重叠的文件 +- `common_files[]`:被识别为公共/基础设施的文件 + +### 2.3 初始冲突预测(串行) + +仅对“未合并且有实际差异”的分支串行执行: + +1. 执行 `git merge --no-commit --no-ff {branch}` +2. 若工作区进入 merge 状态: + - 执行 `git diff --name-only --diff-filter=U` 记录冲突文件 + - 若存在 `MERGE_HEAD`,执行 `git merge --abort` +3. 若命令输出为 `Already up to date`、无 `MERGE_HEAD`、无冲突文件,记为“已包含或无差异”,不执行 `git merge --abort` +4. 若 `git merge --abort` 失败: + - 报告错误和当前状态 + - 用提问工具让用户选择: + - `回到全局锚点后继续分析`:执行 `git reset --hard {global_tag}` + - `终止` + - `reset --hard` 失败则终止并提示用户手动处理 + +### 2.4 风险分级与排序 风险评级: -- 低:无冲突且无依赖 -- 中:有冲突或跨模块依赖 -- 高:(冲突文件 ≥ 3 或冲突占比 ≥ 30%) 且 有跨模块依赖 -输出合并计划表(列:分支、状态、模块、文件数、依赖、预估冲突、风险、语义审查),用提问工具让用户确认,选项: +- 低:无预测冲突、无依赖、单一模块、小体量改动 +- 中:存在依赖,或存在预测冲突,或跨两个以上模块,或触及公共文件 +- 高:预测冲突文件 `>= 3`,或冲突占改动文件比例 `>= 30%`,或存在 ancestry 依赖且触及公共文件 / 根级配置 / 基础设施文件 -- **确认执行**:按当前计划顺序合并,语义审查设置不变 -- **调整顺序**:用户指定新的分支顺序 -- **排除分支**:用户指定不参与合并的分支名(支持多个) -- **调整语义审查**:用户指定关闭某些分支的审查(等待用户输入分支名) -- **终止**:取消整个流程 +初始排序规则: -用户选择"调整顺序""排除分支""调整语义审查"后,重新展示更新后的计划表,再次确认。可多次调整,直到用户选择"确认执行"或"终止"。 +1. 已合并 / 无差异(默认跳过,仅展示) +2. 被其他分支依赖的基础分支 +3. 仅改公共/基础设施文件的分支 +4. 独立、低风险分支 +5. 存在依赖或共享文件的分支 +6. 高风险、跨模块分支 -计划表中"语义审查"列默认全部开启。确认后进入步骤 4,不再逐分支确认。 +### 2.5 验证命令归纳 -## 4. 执行(自动,仅冲突/异常时中断) +根据步骤 1 探测结果,为后续语义修复和构建验证归纳命令: -对计划表中待合并分支依次执行。若全部已合并(无可合并分支),直接跳到步骤 5。 +| 作用域 | 优先级 | +| ---- | ---- | +| 模块级 lint/build/test | 优先使用模块文档或模块脚本中声明的命令 | +| 仓库级 lint/build/test | 若模块级命令缺失,使用仓库统一命令 | +| 无现成命令 | 记录为“无法自动验证”,步骤 3 显示给用户 | -### 合并前检查(自动) +归纳原则: -- `git status` 确认在目标分支且工作区干净 - - 不在目标分支:`git checkout {target}` - - 工作区不干净(非预期状态):报告异常,用提问工具让用户选择:`git stash` 后继续 / 终止 -- `git tag merge-before-{分支名}-{timestamp}` 创建分支级安全锚点(加时间戳防止重复) -- 检查分支 HEAD commit hash 是否与步骤 2.1 记录的一致 - - 不一致:报告分支有新提交,用提问工具让用户选择:重新分析该分支(回到 2.1+2.2 单分支分析,更新分析结果) / 按当前状态继续 / 跳过 +- 优先使用仓库文档明确写出的命令 +- 其次使用标准任务入口中的现有命令 +- 再其次使用就近模块的标准脚本 +- 不自行发明新的构建或测试命令 -### 合并 +### 2.6 分析结果汇总 -`git merge {分支} --no-ff -m "merge: {分支名} → {target}"` +为每个分支形成分析快照: -合并可能出现三种结果: +| 字段 | 内容 | +| ---- | ---- | +| `status` | 已合并 / 无差异 / 待合并 | +| `head` | 步骤 2 记录的 HEAD hash | +| `modules` | 受影响模块 | +| `files` | 改动文件数 | +| `depends_on` | 依赖分支 | +| `predicted_conflicts` | 初始冲突文件列表 | +| `risk` | 低 / 中 / 高 | +| `semantic_review_mode` | 默认 `仅报告` | +| `validation_scope` | 该分支后续优先使用的验证范围和命令 | -- **无冲突** → 跳到语义审查 -- **有冲突** → 进入冲突处理 -- **合并失败**(分支不存在、工作区锁定等非冲突错误)→ 报告错误,用提问工具让用户选择:跳过继续下一个 / 终止并输出进度 +## 3. 计划(用户确认) -### 冲突处理(中断点) +输出合并计划表,列至少包含: -`git diff --name-only --diff-filter=U` 列出冲突文件,展示冲突决策面板: +| 分支 | 状态 | 模块 | 文件数 | 依赖 | 预测冲突 | 风险 | 语义审查 | 验证命令 | +| ---- | ---- | ---- | ------ | ---- | -------- | ---- | -------- | -------- | -| # | 文件 | 冲突类型 | HEAD 改动 | 分支改动 | 推荐方案 | -| - | ---- | -------- | --------- | -------- | -------- | +默认规则: + +- `已合并`、`无差异` 分支仅展示,不进入执行队列 +- `待合并` 分支按步骤 2.4 的排序进入执行队列 +- `语义审查` 默认值为 `仅报告` +- 若某分支缺少可自动执行的验证命令,在计划表中明确标记 + +同时展示仓库级探测结果摘要: + +- 识别出的模块边界 +- 公共/基础设施范围 +- 识别出的验证命令 +- 提交风格摘要 +- 无法确定、需要用户补充的规则 用提问工具让用户选择: -- **按推荐方案全部处理**:所有文件执行推荐方案 -- **审查部分文件**:用户输入要审查的文件编号,未审查文件按推荐方案处理;对审查文件一次性展示上下文 diff + `<<<<<<<`/`=======`/`>>>>>>>` 原始标记,逐文件用提问工具选择方案(选项:双保留 / 保留目标(--ours) / 保留分支(--theirs) / 用户编辑) -- **放弃合并**:`git merge --abort`,跳过当前分支,继续下一个 +- `确认执行` +- `调整顺序` +- `排除分支` +- `调整语义审查模式` +- `补充或修正规则` +- `重新分析全部分支` +- `终止` -方案确定后执行: +语义审查模式仅允许三种: -- 双保留:AI 综合两侧变更生成合并后的文件内容,展示变更摘要(改了哪些函数、新增了哪些逻辑),用户确认后写入 -- --ours/--theirs:`git checkout --ours/--theirs {file}` -- 用户编辑:告知用户文件路径,等待用户回复"完成"后 `git add {file}` -- 逐文件 `git add {file}` -- `git commit --no-edit` 完成合并提交(使用合并时指定的 commit message) +- `关闭` +- `仅报告` +- `报告并修复` -### 语义审查(自动,计划中开启时执行) +若用户选择 `调整顺序`、`排除分支`、`调整语义审查模式`、`补充或修正规则`、`重新分析全部分支`,则更新计划表后再次确认,直到用户选择 `确认执行` 或 `终止`。 -合并提交后,分析 `git diff merge-before-{branch}-{timestamp}..HEAD` 的语义质量。 +最终确认后,记录最终执行队列。并明确提示: + +- 正常 merge 已获授权 +- 冲突内容重写、`stash`、`revert`、`reset --hard`、删除分支、远端删除仍需单独确认 + +## 4. 执行(顺序执行,冲突/异常时中断) + +对执行队列中的分支依次处理。若队列为空,直接进入步骤 5。 + +### 4.1 单分支合并前检查 + +每个分支开始前都执行以下检查: + +1. `git status --short --branch`,确认当前仍在 `{target}` +2. 若不在 `{target}`,执行 `git checkout {target}`;失败则中断并询问 +3. 若工作区非干净,展示异常文件,并用提问工具让用户选择: + - `stash 后继续` + - `终止` +4. 若用户选择 `stash 后继续`,执行 `git stash push --include-untracked -m smart-merge-{timestamp}-runtime-{n}`,记录到 `auto_stashes[]` +5. 检查分支是否仍存在;不存在则记录为 `已跳过:分支不存在` +6. 执行 `git rev-parse {branch}`,对比步骤 2 记录的 `head` +7. 若 HEAD 已变化,先对该分支重新执行步骤 2 的单分支分析,再更新计划快照 + +### 4.2 基于当前 HEAD 的动态复核 + +步骤 2 的分析基于初始目标分支;每次实际 merge 前都必须基于“当前最新 HEAD”重新复核当前分支: + +1. 执行 `git diff --name-status HEAD...{branch}`,获取当前变更文件列表 +2. 串行执行 `git merge --no-commit --no-ff {branch}` 做实时 dry-run +3. 若进入 merge 状态,收集 `git diff --name-only --diff-filter=U` 冲突文件后执行 `git merge --abort` +4. 若无 `MERGE_HEAD`,按实际结果记为“无冲突”或“已包含 / 无差异” +5. 将实时结果与步骤 3 的计划快照对比 + +视为“计划漂移”的情况: + +- 冲突文件集合发生变化 +- 改动文件数变化明显(以 `20%` 为阈值) +- 新出现公共文件 / 根级配置 / 基础设施文件 +- 原本 `无冲突` 变成 `有冲突` +- 原本模块级验证命令不再覆盖当前改动范围 + +若发生计划漂移,用提问工具让用户选择: + +- `按更新后的当前结果继续` +- `重新生成剩余分支计划`:对“当前分支 + 尚未处理的剩余分支”重新执行步骤 2,再回到步骤 3 +- `跳过当前分支` +- `终止` + +### 4.3 生成提交模板并创建分支级锚点 + +先根据 `commit_style` 生成本轮使用的提交模板: + +- 若仓库文档明确约束了提交格式,严格遵守 +- 若文档未约束,但近期提交风格稳定,沿用仓库现有风格 +- 若无法识别,合并提交使用 `chore: merge {branch} into {target}`,语义修复提交使用 `refactor: address post-merge issues in {branch}` + +然后: + +- 执行 `git tag merge-before-{branch}-{timestamp}` +- 记录到 `branch_tags[]` + +### 4.4 正式合并 + +- 执行正式合并:`git merge --no-ff -m "{merge_commit_message}" {branch}` + +正式合并结果分三类: + +- 无冲突:进入步骤 4.6 +- 有冲突:进入步骤 4.5 +- 非冲突错误:展示错误信息,用提问工具选择:`跳过当前分支` / `终止` + +### 4.5 冲突处理(中断点) + +先执行 `git diff --name-only --diff-filter=U` 获取冲突文件清单,再按文件生成冲突决策面板: + +| # | 文件 | 冲突类型 | HEAD 改动摘要 | 分支改动摘要 | 可批量机械处理 | 推荐方案 | +| - | ---- | -------- | ------------- | ------------ | -------------- | -------- | + +推荐方案规则: + +- 仅当解决方案明确等价于 `--ours`、`--theirs`、保留删除的一侧、保留重命名的一侧时,才允许给出“可批量机械处理”的推荐 +- 只要需要合并两边逻辑、补全缺失分支、重排代码顺序、解决同一函数 / 类 / 配置段双改,就标记为 `需逐文件确认` +- `需逐文件确认` 的文件不能被“全部按推荐方案”一键处理 + +用提问工具让用户选择: + +- `处理全部机械型冲突` +- `审查部分文件` +- `放弃当前合并` + +若用户选择 `审查部分文件`,先让用户输入文件编号,再对这些文件逐个展示: + +- 上下文 diff +- 原始冲突块 `<<<<<<<` / `=======` / `>>>>>>>` +- 当前建议与风险说明 + +逐文件可选方案: + +- `保留目标 (--ours)` +- `保留分支 (--theirs)` +- `AI 起草双保留结果` +- `用户手动编辑` + +执行规则: + +- `--ours` / `--theirs`:执行 `git checkout --ours/--theirs {file}` +- `AI 起草双保留结果`: + - 先生成完整最终结果或统一 diff + - 说明具体合并逻辑 + - 再次用提问工具确认后写入文件 +- `用户手动编辑`:告知文件路径,等待用户回复“完成”后再执行 `git add {file}` +- 所有冲突文件都必须逐文件 `git add {file}` +- 执行 `git diff --name-only --diff-filter=U`,确认已无未解决冲突 +- 再执行 `git commit --no-edit` + +若用户选择 `放弃当前合并`: + +- 用提问工具确认是否执行 `git merge --abort` +- 若 `abort` 成功,记录当前分支为 `已跳过:用户放弃合并` +- 若 `abort` 失败,再用提问工具确认是否执行 `git reset --hard merge-before-{branch}-{timestamp}` 回到分支级锚点 + +### 4.6 语义审查 + +语义审查基于 `git diff merge-before-{branch}-{timestamp}..HEAD`。 辅助数据源: | 数据 | 获取方式 | 用途 | | ---- | -------- | ---- | -| 合并 diff | `git diff merge-before-{branch}-{timestamp}..HEAD` | 本次合入的所有变更 | -| 主分支趋势 | `git log merge-before-{branch}-{timestamp} --oneline -20` + 对应 diff | 主分支的规范和架构方向 | -| 分支意图 | 步骤 2.1 已收集的 commit 消息 | 推断开发分支的业务目的 | -| 公共文件现状 | 步骤 2.1 标记的公共文件清单,读取这些文件在主分支上的当前内容 | 判断冗余实现 | +| 本次合入 diff | `git diff merge-before-{branch}-{timestamp}..HEAD` | 查看本次实际引入的改动 | +| 分支意图 | 步骤 2 的 commit 消息 | 推断业务目的 | +| 主干近期趋势 | `git log --oneline {target} -20` 及相关 diff | 识别近期重构、迁移、废弃方向 | +| 公共文件现状 | 步骤 2 标记的 `common_files[]` | 判断是否重复造轮子或遗漏基础设施 | +| 仓库规则 | `repo_rules`、`module_map`、`validation_commands` | 判断是否偏离当前仓库约定 | 审查维度: -| 维度 | 检测方法 | -| ---- | -------- | -| 代码冗余 | 提取合并 diff 中新增的函数签名和 import,与公共文件清单中的已有实现做语义匹配 | -| 过时模式 | 从主分支近期 commit message 中筛选含 refactor/deprecate/remove/migrate 的提交,对比这些提交的 diff 提取被替换的 API,检查合并 diff 中是否仍在使用 | -| 未集成基础设施 | 从主分支近期 diff 中识别新增的中间件/工具/配置项,检查合并 diff 新增的代码是否缺少对应引用 | -| 风格不一致 | 对比主分支近期代码的命名惯例、文件组织、注释风格与合并 diff 中的新增代码 | +| 维度 | 检查点 | +| ---- | ------ | +| 代码冗余 | 新增函数、组件、类型、工具、配置是否已在仓库公共位置存在等价实现 | +| 过时模式 | 是否继续使用近期已迁移、废弃、替换的 API、脚本、配置项、目录模式 | +| 基础设施遗漏 | 新代码是否绕过既有公共抽象、统一错误处理、统一日志、统一配置、统一数据访问、统一请求封装等既有基础设施 | +| 风格不一致 | 命名、文件组织、测试组织、错误处理、注释风格是否偏离当前主干 | +| 模块边界破坏 | 是否把本应落在公共层、共享层、基础设施层的逻辑塞进业务分支目录 | 输出审查结果表: | # | 类别 | 严重程度 | 文件 | 描述 | 建议修复方式 | | - | ---- | -------- | ---- | ---- | ------------ | -严重程度:问题(运行时风险或维护负担)/ 建议(不影响功能,影响一致性)。 +严重程度仅分两类: -无问题 → 跳到验证。有问题 → 用提问工具让用户选择: +- `问题`:有运行时风险、明显架构偏差或维护成本高 +- `建议`:功能可用,但与主干一致性较差 -- **全部修复**:按编号顺序逐个执行 -- **选择修复**:用户输入要修复的编号 -- **跳过**:不处理,进入验证 +按计划中的 `semantic_review_mode` 处理: -修复执行流程: +- `关闭`:跳过语义审查 +- `仅报告`:展示结果后直接进入步骤 4.7 +- `报告并修复`:展示结果后,用提问工具选择:`全部修复` / `选择修复` / `跳过` -1. 按编号顺序逐个修复,记录每个问题的修改内容(文件路径 + 变更范围) -2. 全部修复完成后,统一执行语法检查:`cd backend && go vet ./...` + `cd frontend && bunx tsc --noEmit` -3. 语法检查通过 → 独立提交:`refactor: 语义审查修复 - {分支名}` -4. 语法检查失败 → 逐个回退修改(按倒序,从最后一个修复开始 `git checkout -- {file}`),每回退一个重新检查,直到检查通过或全部回退 -5. 记录哪些修复成功、哪些被回退,在提交 message 中标注 +修复执行规则: -### 验证(自动) +1. 每个问题编号视为一个独立修复单元 +2. 一次只处理一个编号,避免回退时互相污染 +3. 每个修复单元只修改其必要文件,保持最小变更 +4. 修复完成后,按 `validation_commands` 和当前改动作用域执行最小充分检查: -- `cd backend && go build ./...` -- `cd frontend && bun run build` -- 成功 → 继续下一个分支 -- 失败(中断点),分级回退: - 1. 若有语义审查修复提交,先尝试 `git revert` 该提交;revert 成功则再次构建验证 - 2. revert 冲突或再次构建仍失败:`git reset --hard merge-before-{分支名}-{timestamp}`(合并提交和修复提交一并回退) - 3. 报告错误信息和当前 HEAD 位置,用提问工具让用户选择: - - **跳过**:放弃当前分支,继续下一个 - - **终止**:停止整个流程,输出当前进度摘要(见下方"终止处理") +| 作用域 | 检查策略 | +| ---- | -------- | +| 仅单模块 | 优先执行该模块的 lint 或等价静态检查 | +| 多模块 | 执行覆盖这些模块的仓库级检查或组合检查 | +| 触及 `shared/config/infra` | 执行受影响范围内最严格的可用检查 | +| 无自动检查命令 | 记录为“未自动验证”,并在结果中明确说明 | -终止处理:输出当前进度摘要(已成功合并的分支、已跳过的分支及原因、未处理的分支、当前 HEAD 位置、全局锚点标签名),提示用户可用 `git reset --hard pre-merge-backup-{timestamp}` 全部回退。 +5. 若检查通过,立即提交独立修复 commit,message 遵循 `commit_style` +6. 若检查失败,只回退当前修复单元的未提交修改:`git restore --staged --worktree --source=HEAD -- {files}` +7. 记录该编号为 `修复失败并已回退`,继续处理下一个编号 -### 断点(无) +### 4.7 构建验证 -分支间不暂停,自动继续下一个分支。 +根据当前分支实际引入的改动范围,从 `validation_commands` 中选择最小充分的构建 / 测试 / 检查命令: -## 5. 清理(用户确认 — 阶段三唯一介入) +| 改动范围 | 验证策略 | +| -------- | -------- | +| 单模块业务改动 | 优先运行该模块的 build / test / lint 组合 | +| 多模块改动 | 运行覆盖这些模块的聚合命令 | +| 触及共享层、配置、基础设施 | 优先运行仓库级验证或覆盖共享层的更高等级验证 | +| 仓库没有可自动执行命令 | 记录为“无法自动验证”,并向用户说明 | -输出合并汇总,用提问工具一次性确认所有清理操作: +构建成功: + +- 记录当前分支为 `已合并` +- 记录冲突处理方式、语义审查结果、修复提交列表、实际执行的验证命令 +- 继续下一个分支 + +构建失败: + +1. 展示失败命令和错误摘要 +2. 若当前分支存在语义修复提交,用提问工具让用户选择: + - `依次 revert 当前分支的语义修复提交后重试验证` + - `放弃当前分支并回到分支级锚点` + - `终止` +3. 若用户选择 revert: + - 按提交时间倒序执行 `git revert --no-edit {commit}` + - 每 revert 一条后重试验证,直到通过或全部 revert 完成 + - 若 revert 冲突,立即中断并询问:`回到分支级锚点` / `保留冲突现场并终止` +4. 若无语义修复提交,或全部 revert 后验证仍失败,用提问工具让用户选择: + - `git reset --hard merge-before-{branch}-{timestamp}` 放弃当前分支 + - `终止并保留当前现场` +5. 若用户确认回到分支级锚点,记录当前分支为 `已跳过:验证失败并回退` + +## 5. 清理(用户确认) + +所有分支处理完成后,输出汇总表: | 项目 | 内容 | | ---- | ---- | -| 合并结果 | 成功 / 失败(跳过) / 已合并(跳过) 数量 | -| 冲突统计 | 涉及冲突的文件数(含按推荐方案处理和用户审查处理的) | -| 语义审查 | 各分支发现的问题数和修复数(含修复失败数) | -| 删除本地分支 | 成功合并的分支列表,勾选确认 | -| 删除远端分支 | 有远端对应的分支列表,勾选确认 | -| 安全锚点 | 保留 / 删除 | +| 目标分支 | `{target}` | +| 当前 HEAD | 当前提交 hash | +| 合并结果 | 成功 / 跳过 / 已合并 / 无差异 数量 | +| 冲突统计 | 冲突分支数、冲突文件数、机械处理数、逐文件确认数 | +| 语义审查 | 每个分支的问题数、建议数、修复成功数、修复失败数 | +| 实际验证 | 每个分支实际执行了哪些验证命令,哪些未验证 | +| 已创建资源 | `global_tag`、`branch_tags[]`、`auto_stashes[]`、`created_local_tracking_branches[]` | +| 候选删除 | 可删除的本地分支、远端分支、可删除 tag | -选项:**确认清理**(按勾选执行)/ **调整**(用户指定保留的分支或锚点)/ **跳过清理**(仅保留汇总,不删除任何内容) +用提问工具一次性确认清理策略: -确认后执行清理: +- `确认清理` +- `调整清理范围` +- `跳过清理` -- 本地分支删除:`git branch -d {分支}`(git 安全机制:未完全合并的分支会拒绝删除) -- 远端分支删除:`git push origin --delete {分支}`,失败则报告错误,跳过该远端分支,继续处理其余 -- 锚点处理:按用户选择保留或删除 +清理项包括: -输出最终总结:目标分支、全局锚点标签、各分支最终状态(已合并+已删除 / 已合并+保留 / 跳过+原因)、冲突和语义审查统计。 +- 删除已成功合并的本地分支:`git branch -d {branch}` +- 删除已成功合并且用户确认的远端分支:`git push {remote} --delete {branch}` +- 删除用户明确不再保留的安全锚点 tag +- 删除本流程仅为分析/合并而创建、且最终不需要保留的本地跟踪分支 + +远端分支删除规则: + +- 优先删除该分支自己的 upstream remote +- 若分支无 upstream,但来自 `target_remote`,则删除 `target_remote/{branch}` +- 删除失败只记录错误,不影响其余清理项 ### 工作区恢复 -若步骤 1 有 stash:`git stash pop` +若 `auto_stashes[]` 非空,用提问工具让用户选择: -- 无冲突 → 结束 -- 有冲突 → 展示冲突决策面板(同步骤 4 冲突处理流程),用提问工具逐文件选择(选项:保留 stash 内容 / 保留当前内容 / 双保留 / 用户编辑 / 放弃恢复 `git stash drop`) +- `按顺序恢复全部 stash` +- `查看 stash 列表后选择恢复` +- `暂不恢复,保留 stash` + +恢复时按后进先出顺序处理。由于 `stash@{n}` 会随列表变化而漂移,先根据已记录的唯一 message 在 `git stash list` 中定位当前 ref,再对该 stash 执行 `git stash apply {ref}`,不直接 `pop`: + +1. `apply` 成功后,再询问是否 `git stash drop {ref}` +2. 若 `apply` 冲突,展示 stash 冲突决策面板,逐文件选择: + - `保留 stash 内容` + - `保留当前内容` + - `AI 起草双保留结果` + - `用户手动编辑` + - `放弃恢复该 stash` +3. 冲突解决完成后,再询问是否 `drop` 对应 stash + +输出最终总结:目标分支、当前 HEAD、探测到的仓库规则摘要、保留的锚点、各分支最终状态、未删除的远端分支、stash 恢复结果。 + +## 终止处理 + +任一步骤选择 `终止` 时,输出终止摘要: + +| 项目 | 内容 | +| ---- | ---- | +| 当前步骤 | 准备 / 分析 / 计划 / 执行 / 清理 | +| 当前 HEAD | 当前提交 hash | +| 已完成分支 | 成功合并的分支 | +| 已跳过分支 | 分支及原因 | +| 未处理分支 | 剩余执行队列 | +| 已创建资源 | `global_tag`、`branch_tags[]`、`auto_stashes[]`、`created_local_tracking_branches[]` | +| 已识别规则 | `repo_rules`、`module_map`、`validation_commands` | + +若终止时存在活动 merge 状态,再用提问工具让用户选择: + +- `执行 git merge --abort 并结束` +- `回到当前分支级锚点并结束` +- `保留当前冲突现场,交给用户手动处理` + +若终止时不存在活动 merge 状态,不自动变更现场;仅提示用户: + +- 全部回退可使用 `git reset --hard {global_tag}` +- 当前分支级回退可使用 `git reset --hard merge-before-{branch}-{timestamp}` +- 本流程创建的 stash 和本地跟踪分支仍保留,是否恢复/删除由步骤 5 或用户后续手动决定 diff --git a/docs/prompts/prompt-spec-review.md b/docs/prompts/prompt-spec-review.md index 503df52..6e19a67 100644 --- a/docs/prompts/prompt-spec-review.md +++ b/docs/prompts/prompt-spec-review.md @@ -1,58 +1,133 @@ -请对 openspec/specs/ 下所有规范文件进行审查和整理,按以下流程执行。 +请审查并整理 `openspec/specs/` 下的稳定规范,使其成为可搜索、边界清晰、无冗余、与当前业务一致的能力索引,按以下流程执行。 ## 约束 -- 规范描述"应该是什么",不含实现细节(具体文件路径、代码引用)和变更记录(ADDED/MODIFIED、"移除以下列"等措辞) -- 每批重构操作执行前用提问工具获得用户确认 -- 仅删除内容已完全覆盖在其他规范中的冗余规范,非冗余内容仅迁移/合并/重命名 +- `openspec/specs/` 描述长期稳定的业务能力、规则和外部行为,不记录变更过程、迁移说明、实现路径、内部类型名、组件 props、样式数值、层级分层等实现细节 +- 用户可感知或对外暴露的契约可以保留:公开 API 路径、请求/响应字段、协议名、错误码、数据约束、交互结果 +- `Requirement` 和 `Scenario` 应描述业务能力、外部行为或稳定约束,不以“使用某层/某组件/某库实现”作为标题或核心表述 +- 不把当前代码自动视为唯一真相;若代码、README、现有 spec 冲突且无法判断应以哪边为准,列入待确认清单,不直接改写规范 +- 仅删除内容已被其他规范完整覆盖且无独立检索价值的规范;非冗余内容仅迁移、合并、拆分或重命名 +- 每批重构执行前用提问工具获得用户确认;删除或重写前先备份原文件为 `{file}.bak.{timestamp}` +- 命名、Purpose、Requirement 标题都必须保留用户下一次最可能搜索的业务关键词 ## 1. 收集 -并行读取以下内容: -- `openspec/specs/` 每个子目录的 `spec.md` -- 项目源码(backend/、frontend/),理解实际实现 -- `openspec/config.yaml`,了解项目约束 +并行读取: +- `openspec/config.yaml` +- `README.md`,以及与模块结构、API、架构相关的 README 或文档 +- `openspec/specs/*/spec.md` + +默认不读取 `openspec/changes/**`、历史 proposal/design/tasks 作为稳定规范整理依据;仅在用户明确要求“连同历史变更一起校对”时再纳入。 + +先建立索引,不直接开始改写: + +| 索引 | 内容 | +| ---- | ---- | +| `spec_index[]` | 每个 spec 的目录名、Purpose、Requirement 摘要、关键词、外部契约、疑似重叠对象 | +| `domain_map[]` | 从 README、API、模块文档中提炼的核心业务域、横切能力和术语 | +| `term_map[]` | 同义词、旧名、缩写和推荐标准术语 | +| `suspects[]` | 需要进一步对照代码或测试确认的 spec | + +仅对 `suspects[]` 做定向读取: +- 读取与该 spec 对应的源码、测试、README 或架构文档 +- 不对 `backend/`、`frontend/` 做无差别逐文件扫描 + +判定依据优先级: +- 当前稳定 spec 与 README 共同支持的事实,可直接视为高置信度 +- 仅代码可见但 README 和 spec 未体现的内容,先判断它是稳定外部行为还是临时实现细节 +- 代码、README、现有 spec 互相冲突且无法自动定夺时,进入 `待确认清单` ## 2. 审查 -将每个规范与代码和命名约定对比,按以下维度逐项检查: +按 spec、Requirement、Scenario 三层检查: | 维度 | 检查点 | | ---- | ------ | -| 过时 | 描述的功能/组件是否仍存在于代码;引用的路径、类名、API 是否一致;交互流程是否匹配当前实现 | -| 重复 | 不同规范是否描述同一组件/功能/场景(场景级或概念级) | -| 错位 | 场景是否放错了功能域;Requirement 是否归属错误的规范 | -| 合并 | 同一主题是否分散在多个规范;某个规范是否是另一个的子集 | -| 命名 | 是否准确反映内容;是否符合命名约定(见下);是否暴露可搜索的业务关键词 | -| 格式 | 是否使用 SHALL/WHEN/THEN;是否混入变更记录或实现细节;是否有空目录 | +| 过时 | 描述的能力、术语、外部契约是否仍成立;是否存在 `TBD`、`TODO`、占位说明 | +| 冲突 | 不同规范是否对同一行为给出不同约束、命名或边界 | +| 重复/重叠 | 是否在文件级、Requirement 级、Scenario 级重复描述同一能力 | +| 错位 | 内容是否放错能力域;横切规则是否混入实体规范;平台实现是否混入通用能力规范 | +| 粒度 | 是否过大导致难检索,或过碎导致回答一个问题必须同时打开多个 spec | +| 术语 | 同一概念是否混用多个名字;旧名、别名、缩写是否需要归一并保留检索入口 | +| 命名/检索 | 目录名、Purpose、Requirement 标题是否准确;是否能被 README、API、业务术语直接命中 | +| 规范性 | 是否使用 SHALL/WHEN/THEN;是否混入变更记录、迁移说明、内部实现或 UI/代码细节 | +| 完整性 | Purpose 是否明确;是否存在空目录、非 spec 噪音文件、无清晰归属的孤立规范 | + +重构判定规则: +- 若两个 spec 回答的是同一个核心问题,或其中一个只是另一个的子集,优先合并 +- 若一个 spec 混合多个独立检索意图,或同时包含横切规则与业务流程,优先拆分 +- 若内容正确但目录名、Purpose 或 Requirement 标题不利于检索,优先重命名或改写标题 +- 若多个术语指向同一概念,统一到一个标准术语,并在 Purpose 或 Requirement 中保留必要别名以支持搜索 +- 若某段内容只是内部实现细节,且不影响外部行为理解,删除该段而不是为其单独保留 spec +- 若某个具体值同时属于外部契约与内部实现,按“是否对调用方可见、是否影响兼容性”判断是否保留 ### 命名约定 +命名优先复用仓库已存在的稳定术语,如 `provider`、`model`、`stats`、`protocol`、`proxy`、`logging`、`validation`、`migration`、`frontend`、`desktop`、`mysql`。 + | 类型 | 模式 | 示例 | | ---- | ---- | ---- | -| 平台专属 | `{平台}-{功能}` | admin-platform、console-my-skills | -| 跨平台组件 | `{类别}` | component-library、layout-system | -| 技能领域 | `skill-{方面}` | skill-market、skill-status-rules | -| 业务功能 | `{业务名词}` | account-management、chat-scenarios | +| 实体生命周期 | `{entity}-management` | `provider-management`、`model-management` | +| 横切能力 | `{concern}` 或 `{concern}-{qualifier}` | `error-handling`、`structured-logging` | +| 协议/适配 | `{protocol}-{capability}` 或 `protocol-adapter-{protocol}` | `openai-protocol-proxy`、`protocol-adapter-openai` | +| 运行面/入口 | `{surface}` 或 `{surface}-{capability}` | `frontend`、`desktop-app` | +| 基础设施 | `{resource}-{operation}` | `database-migration`、`mysql-driver` | -命名原则:统一平台前缀(admin-/console-/developer-)、统一领域前缀(skill-)、2-3 词、避免泛化词(display/basic/general/info/data)和实现模式词(crud/list/table)。 +命名原则: +- 1-4 个词,保持单一主题 +- 优先使用业务名词,不使用 `basic`、`general`、`misc`、`info`、`data` 等泛化词 +- 不使用 `crud`、`list`、`table`、`display` 等实现模式词,除非它本身就是外部契约的一部分 +- 同一主题的命名模式保持一致,不同时混用多套前后缀 ## 3. 报告 输出分析结果: 1. **问题总览表**:问题类型 × 涉及规范数 -2. **逐项分析**:每个有问题的规范,说明具体问题和建议(涉及文件、冲突点、推荐操作) -3. **重构方案**:按优先级分批: - - P0:删除空目录和完全冗余规范 - - P1:合并重复/子集规范到主规范 - - P2:重命名不精准的规范、拆分错位内容 - - P3:修正与代码不匹配的描述、清理实现细节和变更记录 -4. **重构后目录结构**:预期的新 specs/ 目录树 +2. **规范关系表**:每个 spec 的主主题、重叠对象、冲突对象、建议动作 +3. **术语归一表**:旧术语 / 别名 / 缩写 → 推荐标准术语 +4. **逐项分析**:每个有问题的规范说明位置、问题、影响、建议和目标规范 +5. **待确认清单**:代码、README、现有 spec 冲突且无法自动定夺的事项 +6. **重构方案**:按优先级分批 +7. **重构后目录结构**:预期的新 `openspec/specs/` 目录树 -## 4. 执行 +优先级建议: +- P0:删除空目录、非 spec 噪音文件、占位内容 +- P1:删除完全冗余规范;将其内容映射到主规范 +- P2:合并重复/子集规范;拆分错位或过大规范 +- P3:重命名目录、改写 Purpose 和 Requirement 标题以提升检索性 +- P4:修正过时描述,清理实现细节、迁移说明和变更记录 -逐批执行重构(P0→P3),每批执行前: -- 展示该批次的具体操作列表(源路径 → 目标路径、操作类型) -- 用提问工具获得用户确认 -- 执行后确认目录结构完整,规范文件可正常读取 +若所有问题清单为空,输出“审查通过,未发现问题”,跳至步骤 5。 + +## 4. 计划(用户确认) + +先针对 `待确认清单` 用提问工具逐项向用户确认。 + +再按批次展示完整重构计划,每批必须包含: +- 操作类型:删除、重命名、迁移、合并、拆分、改写 +- 路径变化:源路径 → 目标路径 +- 内容映射:源 spec 的 Requirement / Scenario 将迁移到哪里 +- 术语处理:哪些旧词保留为检索入口,哪些词统一替换 +- 执行原因:为什么这样做更利于检索、去重和边界清晰 +- 验证方式:如何确认没有丢失约束或引入新的冲突 + +用提问工具获得当前批次确认后再执行。 + +## 5. 执行 + +按 P0 → P4 逐批执行已确认的重构。 + +执行要求: +- 合并或拆分时先写目标 spec,再删除或重命名源 spec +- 删除前确认其 Requirement 和 Scenario 已被完整保留、迁移或判定为纯冗余 +- 每批执行后重新读取受影响的 spec,并复核结构和内容 + +每批执行后至少验证: +- 目录结构完整,`openspec/specs/*/spec.md` 可正常读取 +- 不存在未承接的 Requirement 或 Scenario +- Purpose、Requirement 标题、目录名可以直接表达主能力 +- 不再包含 `TBD`、变更记录、迁移说明、内部实现细节或噪音文件 +- 若本批涉及代码对照项,相关外部契约描述与当前仓库现状一致,或已列入残留待确认 + +收尾时输出:修改文件清单、备份文件清单、最终目录树、残留待确认事项和整理摘要。