--- name: comet-open description: '创建 Classic change,整理需求并请用户确认。在用户调用 /comet-open,或 Classic 进入 Open、恢复初始化时使用。' --- # Comet 阶段 1:开启(Open) 开始或恢复任务前,必须先读取并遵守 `comet-classic/reference/classic-layout.md`。本文件中的 OpenSpec CLI 调用必须通过适配器执行,文件路径必须基于该协议绑定的 `` 逻辑根目录。 ## 前置条件 - 无活跃 change,或用户希望创建新 change ## 步骤 ### 0. 设置输出语言 向 OpenSpec 传递提问和文档生成要求时,都必须明确指定 Comet 配置的产物语言,使用 `en`、`zh-CN` 这类规范化 ID。`.comet.yaml` 尚不存在时,依次读取项目 `.comet/config.yaml` 和全局 `~/.comet/config.yaml` 的 `classic.language`;change 初始化后,使用 `comet state get language` 读取。没有配置语言时,才采用当前用户请求的语言。生成的 `proposal.md`、`design.md`、`tasks.md` 必须以该语言为主。 ### 0a. 当前 change 绑定 恢复已有 change 时先检查 `/.comet.yaml`: - 状态文件存在且可解析:先运行 `comet classic workspace resolve --json`,进入返回的 `projectRoot` 后再选择 change - 状态文件缺失但 change 目录有效:先使用所选隔离方式准备工作区,再进入返回的 `projectRoot` 运行 `comet state init full --isolation `,最后选择 change - 状态文件格式异常:停止并报告解析错误;根据版本控制、备份或能够核实的产物人工修复后再继续,不得用 `state set` 覆盖损坏文件 ```bash comet classic workspace resolve --json # 进入返回的 projectRoot comet state select ``` 创建新 change 时,必须先初始化 `.comet.yaml`,再立即运行上述 select 命令;状态文件尚不存在时,不得手工写入 change 选择记录。 ### 0b. Open 前工作区决策与准备 创建 Classic change 时,读取 `comet-classic/reference/workspace.md`。必须先确定工作区,再创建 OpenSpec 产物和 `.comet.yaml`,不能推迟到 Build: - 用户明确要求并行工作时,直接使用 `worktree`;先准备好独立工作区,再创建 OpenSpec 产物和 state - 用户未指定隔离方式时,按参考文档处理:需要用户选择时,展示可用的 `current`、`branch`、`worktree` 选项,推荐理由不能代替用户选择 - 用户选择 `current` 或 `branch` 时,仍应串行工作,不得将其描述为适合多个会话同时使用 新 change 在运行 OpenSpec `new` 前准备工作区: ```bash comet classic workspace prepare --isolation --json # 进入返回的 projectRoot;后续 OpenSpec、state 和产物写入都必须在该目录执行 ``` 准备命令会复用已登记且分支匹配的 Worktree;分支仍在但已登记的 Worktree 被移除时,会重建 Worktree。只有分支已重命名、被用户用于其他工作,或无法确认归属时,才暂停,请用户明确确认 rebind。 ### 0c. OpenSpec 兼容性检查 首次使用或上游安装发生变化时运行一次,记录用于排错的版本: ```bash comet classic openspec -- --version ``` 兼容性必须通过实际能力检查,不能只凭版本号判断。status 必须提供 `changeRoot`、`applyRequires`,以及每个产物的 `requires`、`outputPath`、`status`;instructions 必须提供可用的 `resolvedOutputPath`。当前适配已核对 OpenSpec 1.11.0/1.12.0 的状态接口要求,不保证兼容所有历史版本。命令不可用、返回非零或缺少必需能力时,停止并展示错误和升级建议,不自动升级用户环境。 创建 change 后,由 `comet state artifacts --json` 校验路径、全部必需依赖和实际文件。该命令会展开 `applyRequires` 和 Classic 必需的 proposal/tasks 的所有依赖,形成完整依赖闭包。闭包要求生成 design 时,不能因为 instructions 称其“可选”就跳过;闭包不要求 design 时,不强制生成。 只有需求不涉及行为规格变更、`.openspec.yaml` 明确设置了 `skip_specs: true`,且没有冲突的规格文件时,才允许跳过 specs。当前支持 proposal/specs/design/tasks 角色;遇到不支持的必需角色或输出模式时,必须明确报告,不能自行猜测处理方式。 ### 1. 探索想法与需求澄清 **立即执行:** 使用 Skill 工具加载 `openspec-explore` 技能。禁止跳过此步骤。 **外部 OpenSpec Skill 适配规则:** 加载后只采用其探索方法,不执行其中直接运行官方 CLI、切换到固定 cwd,或读写写死的 OpenSpec 目录的指令。所有 CLI 调用改用 `comet classic openspec -- `,所有文件路径改用本轮绑定的 `` 逻辑根目录。 技能加载后,先复用用户提供的 PRD、设计与已确认事实,围绕下列内容检查缺口并形成澄清摘要。只对会改变范围、方案或验收的未知项提问;信息已足够时可以不追加问答,不设置最低澄清轮数: - 目标:用户真正要解决的问题和期望结果 - 非目标:本次明确不做的内容 - 范围边界:涉及/不涉及的模块、用户、平台或数据 - 关键未知项:仍不确定的假设、风险或依赖 - 验收场景草案:至少覆盖核心成功场景和关键边界场景 澄清摘要必须包含:目标、非目标、范围边界、关键未知项、验收场景草案。 需要向用户澄清时,必须先读取 `comet-classic/reference/decision-point.md`,以明确问题、推荐及理由、各选项影响的形式提问,并优先使用可用的 `AskUserQuestion`。只询问当前缺口;事实或素材无法提供真实选项时说明缺失内容后请求补充。外部探索 Skill 的提问也应用该协议,不能因加载了探索方法而省略选项或替用户选择。 引用完整 PRD 时,给出文件路径和相关章节,不复制全文。已确认的事实不重复征求同意;发现矛盾时,只澄清矛盾点。OpenSpec 技能仍是必需依赖,探索结束后必须返回 Comet,不能由外部 Skill 自行进入设计、实施或归档。探索中的确认不能代替 Open 最后的产物确认。 ### 1a. 创建前确认是否拆分 PRD 用户提供大型 PRD、路线图或完整产品方案,或澄清摘要显示包含多个独立功能、模块、用户操作流程或里程碑时,必须先评估是否需要拆分为多个 change,再创建 OpenSpec 产物。 拆分预检必须基于已澄清的信息,输出候选拆分清单。每个候选拆分项必须包含: - 建议 change 名称 - 目标与范围边界 - 明确非目标 - 依赖关系或推荐执行顺序 - 对应的核心验收场景 满足任一条件时,应推荐拆分: - PRD 包含多个可以独立设计、构建、验证和归档的功能 - 涉及多个模块或用户路径,且其中一部分可独立交付 - 存在明显分阶段里程碑 - 多个 delta spec 对应可分别验收与交付的独立目标;文档或任务数量本身不决定拆分 - 任一部分失败或延期不应阻塞其他部分进入后续阶段 如推荐拆分,必须按 `comet-classic/reference/decision-point.md` 的协议暂停并等待用户选择。 用户选择必须包含: - 「创建多个 OpenSpec changes」— 按候选拆分逐个创建独立 change - 「保持为一个 change」— 继续单 change 流程,并在 proposal/design/tasks 中记录不拆分原因 - 「调整拆分方案后继续」— 用户说明调整方向后,重新输出候选拆分清单并再次确认 每个被接受的拆分项都必须通过 `/comet-open` 创建独立 change,不得直接调用 `/opsx:new`。`/comet-open` 负责同时创建 OpenSpec 产物和 `.comet.yaml`,确保每个 change 都由 Comet 状态机管理。 不得在用户完成 PRD 拆分选择前创建 proposal.md、design.md 或 tasks.md。若用户选择创建多个 change,当前 `/comet-open` 调用只负责完成拆分确认与调度,随后按用户确认的顺序分别进入每个拆分项的 `/comet-open`。 用户确认创建多个 changes 后,必须立即把确认结果保存到 `.comet/batches/.json`。`batch-id` 使用固定的 kebab-case 标识。文件至少记录 `version`、原始目标摘要、创建时间、按顺序排列的 change 名称,以及每项的目标、范围、非目标、验收场景和 `pending|open-complete|selected` 状态。每创建或完成一个拆分项,都要原子更新该文件。这份清单用于记录批量创建顺序和进度,不替代各 change 的 `.comet.yaml`。 批量拆分模式下,进入每个拆分项的 `/comet-open` 时,必须明确标注「已确认拆分项」,并传入该项的目标、范围、非目标和验收场景。已确认的拆分项默认跳过 PRD 拆分预检,除非该项本身仍明显包含多个独立功能。 批量拆分模式下,单个拆分项完成 open 阶段后,不得自动进入 `/comet-design`。拆分完成后,必须暂停,请用户选择从哪一个 change 开始。只将用户选中的 change 推进到 `/comet-design`;其他 change 保持未归档状态,稍后通过 `/comet-classic` 恢复。 **逐项检查批量创建结果(不得跳过)**:全部拆分项完成各自的 open 阶段后,对用户确认清单中的每个 `` 逐个运行: ```bash comet state check design --json ``` 该入口已检查 OpenSpec 的全部必需依赖、实际输出和 Comet 状态,不再额外重复查询 status。`isComplete` 仅用于诊断,非必需产物不会阻止流程继续。检查失败时,再查询 status,找出尚未生成的依赖,或处理已报告的路径错误、缺少必需能力等问题。 任一拆分项未通过检查时,不能宣告拆分完成,也不能询问用户开始哪个 change。应停止后续推进,从该 change 的第一个 `ready` 或 `blocked` 产物恢复 `/comet-open`。OpenSpec 检查通过、但 Comet state 检查失败时,必须先修复 `.comet.yaml` 初始化或 phase,再重新执行整批检查。 只有所有拆分项都通过入口检查后,才暂停,请用户选择从哪一个 change 开始。用户选择后,将批量清单中的该项标记为 `selected`,只推进该 change 进入 `/comet-design`;其他 change 保持未归档状态,稍后通过 `/comet-classic` 恢复。 中断后恢复时,先读取 `.comet/batches/.json`,再对清单中已创建且未归档的 changes 运行上述 CLI 检查。已完整通过的拆分项不得重复创建;未通过的拆分项,从 OpenSpec 返回的第一个 `ready` 产物继续。尚未创建的项,按已保存的清单继续创建。清单缺失或损坏时,停止并请用户重建或确认,不能从目录列表猜测原来这一批包含哪些 change。 ### 1b. 整理需求并确定 Change 名称 创建 OpenSpec 产物前,把 Step 1 的澄清结果整理为需求摘要(resolved brief),包括目标、非目标、范围边界、关键未知项和验收场景草案。根据这份摘要,拟定一个能准确表达范围的 kebab-case 英文 change 名称。 - **范围与命名都明确时直接继续**,不得仅为了让用户批准摘要或名称而创建停顿点;最终审视会统一确认 change 名称、范围和产物内容 - 用户已经提供名称时,规范化为 kebab-case 并在进度说明中回显;规范化不改变含义时无需再次确认 - 已确认批量拆分项直接复用批量清单中的摘要与名称;检测到范围漂移或清单信息缺失时,才重新澄清 - 只有仍需在不同范围或不同目标 change 之间作出选择时,才按 `comet-classic/reference/decision-point.md` 将相关问题合并提问;不能仅因命名偏好而单独暂停 OpenSpec change 名称必须是 kebab-case 英文(小写字母、数字、单连字符)。名称冲突但目标仍明确时,拟定一个不冲突且含义一致的名称,然后继续。只有无法判断应复用现有 change 还是创建新 change 时,才交给用户选择。 resolved brief 或 change 名称仍不明确时不得运行 `comet classic openspec -- new change`,也不得创建 proposal/design/tasks;继续澄清或处理真正的用户决策后再进入 Step 2。 ### 2. 创建 Change 结构 + 初始化状态 **立即执行:** 使用 Skill 工具加载 `openspec-new-change` 技能。禁止跳过此步骤。 **外部 OpenSpec Skill 适配规则:** 加载后只采用其创建 change 的方法,不执行其中直接运行官方 CLI、切换到固定 cwd,或把 change 写到固定 OpenSpec 根目录的指令。创建、status 与 instructions 全部改用 `comet classic openspec -- `,文件路径全部改用 `` 等本轮逻辑根目录。 完整 `/comet-classic` 流程默认不得使用 Skill 工具加载 `openspec-propose` 技能;只有用户明确要求一次性生成提案和其他产物时,才允许加载。 **外部 OpenSpec Skill 适配规则:** 使用 `openspec-propose` 时,同样不能直接运行官方 CLI、采用固定 cwd 或读写固定 OpenSpec 目录。命令必须通过适配器执行,产物必须写入路径解析器返回的 `` 逻辑根目录。 技能加载后,按其指引创建 change 的基础目录和文件。Step 1b 已形成范围明确的 resolved brief 时,不再执行其中的 "STOP and wait for user direction",直接继续,避免重复询问。 直接使用 Step 1b 的 resolved brief 填充产物内容。只有 brief 仍有会改变范围的歧义时,才回退到技能的提问流程。 change 的基础目录和文件创建后,立即初始化状态,以便中断后恢复;不能等所有产物都生成后再写 `.comet.yaml`(入口状态验证统一在 Step 3 执行,这里不重复): ```bash comet state init full --isolation comet state select ``` 任一命令失败都停止。随后运行一次 `comet classic openspec --agent-json -- status --change "" --json` 并执行兼容性预检: - `changeRoot` 解析后必须等于路径解析器绑定的 ``,`planningHome`(如存在)也必须位于当前仓库;不支持仓库外的产物路径 - `artifacts` 必须包含 Classic 必需 ID `proposal`、`tasks`,其他要求沿 `requires` 递归展开 - `applyRequires` 必须是可解析的产物 ID 列表;直接引用和间接依赖的产物都必须存在,且不能循环依赖 - 返回数据缺少字段、路径越界或必需 ID 缺失时,立即停止,不能改用猜测的固定模板 预检通过后,按 OpenSpec CLI 返回的 schema 和依赖图生成实施所需的产物: Agent JSON 模式下,从 `data.upstream.data` 读取上游字段。下一步必须使用 `data.nextAction` 返回的完整 argv,并在其指定的 cwd 执行;上游原始 nextSteps 仅用于诊断。 **根据 OpenSpec 状态逐项生成产物**: 1. 首轮复用 Step 2 兼容性预检刚返回的 status;后续复用上一轮写入后刷新的 status。只有恢复或外部产物变化时重新运行 `comet classic openspec --agent-json -- status --change "" --json`,从 `data.upstream.data` 读取完整上游 JSON。 2. 展开 `applyRequires` 加 proposal/tasks 的完整依赖闭包。闭包中每项都为 `done` 或合法 `skipped` 时运行 `comet state artifacts --json`,仅校验通过才退出循环;顶层 tasks 已完成不能掩盖未完成依赖。`isComplete` 只作诊断。 3. 在尚未完成、状态为 `status: "ready"` 的产物中,优先处理 `applyRequires` 所需的依赖,并遵循 CLI 返回的顺序。不得写死生成顺序,也不能假设 schema 只有 proposal/design/tasks。 4. 对每个 ready 的 `` 获取实时指令: ```bash comet classic openspec --agent-json -- instructions --change "" --json ``` 5. 根据返回的 JSON 指令,必须完成以下操作: - 读取 `dependencies` 中列出的每个已完成依赖产物 - 以 `template` 作为产物结构 - 遵循 `instruction` 的指引 - 遵守 `context` 和 `rules` 中的约束,**不得将这些内容复制到产物中** - 写入 `resolvedOutputPath`;通配输出必须按 instruction 创建每个实际文件 - 验证 CLI 返回的实际输出文件存在且非空 6. 每创建一个产物后,用 `comet state artifacts --json` 做本地闭包校验(不启动 OpenSpec 子进程),仅当它报告依赖缺失或顺序错误、需要新的实时指令时,才刷新一次 status 并再次校验路径与完整依赖闭包。已经变为 `done` 的项不得重复生成;只处理闭包中新增的 ready 项,不额外生成无关的可选产物。 **阻塞与失败处理**:`applyRequires` 尚未全部完成、但其所需依赖中已没有 ready 产物时,必须报告相关 `blocked` 产物的 `missingDeps`,然后停止。不得猜测生成顺序或跳过依赖。适配器的 `status` / `instructions` 调用失败、返回无效 JSON、产物路径超出仓库,或未提供可用的 `resolvedOutputPath` 时,也必须立即停止并报告 OpenSpec 错误,不能改用写死的文档结构。 **核对名称和变更范围**:change name 必须使用 Step 1b 解析出的 kebab-case 英文名,不得使用非 kebab-case(如中文)名称。变更范围必须与 resolved brief 和用户描述一致,不得自行扩大或缩小。 确认以下产物已创建: ``` / ├── .openspec.yaml ├── .comet.yaml ├── proposal.md # Why + What:问题、目标、范围 ├── design.md # 仅在依赖要求或实际需要时创建,保存技术决策,不复制到第二份设计文档 └── tasks.md # 任务清单(勾选框) ``` ### 3. 入口状态验证 验证状态机已正确初始化: ```bash comet state check open ``` 验证通过后继续 Step 4。验证失败时脚本会输出具体失败原因。 **恢复未完成的创建步骤**:open 阶段的操作允许安全重试;恢复时按以下顺序识别已完成的部分,只补未完成的工作: 1. 状态文件缺失时先使用所选隔离方式准备工作区,再进入返回的 `projectRoot` 运行 `comet state init full --isolation `;格式异常时停止并修复,不得覆盖。随后选择 change 并运行 `comet state check open`。 2. 运行 `comet classic openspec --agent-json -- status --change "" --json`,重新验证 `changeRoot`、核心 ID、`applyRequires`、`artifacts` 和 `missingDeps`。 3. `done`:该产物已完成,保持原文件不变,不重复生成。 4. `ready`:依赖已经满足,可以生成。先运行 `comet classic openspec --agent-json -- instructions --change "" --json`,按返回内容写入;写完后用 `comet state artifacts --json` 做本地闭包校验,不重新运行 status。 5. `blocked`:读取 `missingDeps`,先完成属于 `applyRequires` 依赖闭包的依赖产物;每完成一个依赖用 `comet state artifacts --json` 校验,仅在报告新问题时重新运行 status,不能直接生成 blocked 产物。 6. 重复上述处理,直到完整必需闭包为 done 或合法 skipped,且 `comet state artifacts --json` 校验通过。 如果必需依赖仍无法完成,必须列出相关 blocked 产物及其 `missingDeps`,然后停止并报告。不能仅凭目录或三个固定文件存在,就替代 CLI 的检查结论;也不能因为 `isComplete: false`,就让不属于 `applyRequires` 的可选产物阻止流程进入实施阶段。 ### 4. 内容完整性检查 使用最近一次 `comet state artifacts --json` 的成功结果核对必需产物;文件或 schema 变化后必须重新运行。任一问题未解决时,不得进入 Step 5 或执行阶段守卫。 随后检查关键产物的内容:proposal 应说明问题、目标、范围和非目标;design 应说明高层决策与数据流;tasks 应列出明确任务。schema 返回 specs 等其他产物时,也必须按对应的 instructions 检查内容,不能因为 proposal、design、tasks 三个文件已经存在就跳过。 ### 5. 请用户确认产物 全部 OpenSpec 产物完成且内容完整性检查通过后,**必须按 `comet-classic/reference/decision-point.md` 的协议暂停并等待用户确认**。不得在用户确认前执行阶段守卫或自动进入下一阶段。 最终审视同时确认 change 名称、范围和产物内容;不得因 Step 1b 已完成解析而省略,也不得在此之前再增加一次常规摘要/命名确认。 用户确认问题必须以单选题形式呈现,包含以下摘要和选项: **摘要内容**: - **change 名称与 resolved brief**:最终名称、目标、非目标、范围边界和关键未知项 - **proposal.md**:问题背景、目标、范围 - **schema 要求的 specs 等产物**:功能、需求和关键验收场景 - **design.md**:高层架构决策、方案选型 - **tasks.md**:任务数量和关键任务描述 **选项**: - 「确认,继续下一阶段」— 产物符合预期,执行阶段守卫流转 - 「需要调整」— 附带调整说明,修改后重新请求确认 用户选择「确认」后继续执行退出条件。用户选择「需要调整」时,按其说明修改对应文件,然后重新请求确认。 ## 退出条件 - `comet state artifacts --json` 通过:完整必需闭包已完成或合法跳过,所需实际输出非空 - **用户已确认** 全部 OpenSpec 产物的内容符合预期 - **阶段守卫**:运行 `comet guard open --apply`,全部 PASS 后由守卫推进到下一阶段(此步骤更新 `phase` 字段,与 `auto_transition` 无关) 退出前必须使用 `--apply`,否则 `.comet.yaml` 仍停留在 `phase: open`,下一阶段入口检查会失败。 ```bash comet guard open --apply ``` 完整流程会自动更新为 `phase: design`;hotfix/tweak 预设会自动更新为 `phase: build`。 ## 自动衔接下一阶段 按 `comet-classic/reference/auto-transition.md` 和成功结果中的 `agent.continuation` 继续。已有仍然有效的状态信息时,不重复 next、select 或 check。只有丢失上下文后恢复任务、外部状态变化,或旧结果未提供这些信息时,才运行: ```bash comet state next ``` - `NEXT: auto` → 调用 `SKILL` 指向的 skill 进入下一阶段 - `NEXT: manual` → 不调用下一 skill,按 `HINT` 交还控制权并结束当前调用;不再创建确认点 - `NEXT: done` → 流程已完成,无需继续 hotfix/tweak 预设由对应预设 Skill 控制后续流转(phase 直接进入 build),其 `next` 会返回对应预设 Skill。