ly-workflow-codex 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ly-workflow-codex",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "packageManager": "pnpm@10.17.1",
6
6
  "description": "Codex 单 Agent 工作流 —— OpenSpec 生命周期 + 独立审查关卡 + GitFlow 发布管线",
7
7
  "author": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lyx-apply
3
- description: 'coding subagent 实施 tasks(subagent Agent 模式):主会话 spawn coding subagentfork 当前会话上下文 + 只实施 change 范围),逐任务实施+验证+勾选;结论与改动回传主会话,由主会话确认后统一提交 apply: <change-name>;失败原样呈报转人工(不重试不兜底)'
3
+ description: ' [codexHost] codingExecutor 决定实施主体:main(默认)= agent 直接实施;subagent = spawn coding subagent(非 fork spawn,只携带 TASK;经 change 目录 context.md 获取软上下文 + 只实施 change 范围)。两条路径均逐任务实施+验证+勾选,主会话确认后回写 context.md 并按共用隔离协议统一提交 apply 阶段 commit(CC 前缀 + Change-Stage: apply trailer);失败原样呈报转人工(不重试不兜底)'
4
4
  argument-hint: '[<change-name>]'
5
5
  ---
6
6
 
@@ -8,7 +8,12 @@ argument-hint: '[<change-name>]'
8
8
 
9
9
  > 调用方式:`@lyx-apply` mention 后跟随的自然语言即参数(如 `@lyx-apply` 带需求描述/选项);无参数时直接 `@lyx-apply`。
10
10
 
11
- 实施环节由 **coding subagent** 执行(subagent 多 Agent 模式):主会话 spawn 一个 coding subagent,fork 当前会话上下文并在任务中点名"只实施 change 范围";coding subagent 读取 tasks.md 逐任务实施 + 验证 + 勾选后,将改动与结果**回传主会话,不自行 commit**——`apply: <change-name>` 由主会话确认后统一提交,作为 `@lyx-review-code` 的审查对象。失败区分两阶段:**环境级不可用**(宿主无 subagent 能力、初始 spawn 失败)按回退口径回退当前会话直接实施,SHALL NOT 视为业务失败;**实施中/验证失败** SHALL 原样呈报转人工,不自动重试、不切回自实施、不自动兜底。隔离 worktree 的询问/新建统一收敛到 `@lyx-propose` 入口,apply 不触发任何 worktree 询问、不做隔离检测——直接在当前工作目录实施。
11
+ 实施主体由 `~/.codex/lyx/config.toml` `[codexHost] codingExecutor` 决定(未配置、空白或非法取值等价 `"main"`):
12
+
13
+ - **`"main"`(默认)**:主 agent SHALL 在当前会话直接实施——读取该 change 的 `tasks.md` 逐任务实施 + 验证 + 勾选;SHALL NOT spawn 子代理、SHALL NOT 读取 `codingModel` / `codingReasoningEffort`、SHALL NOT 产生 `[回退]` 标记。
14
+ - **`"subagent"`**:主会话 spawn 一个 coding subagent,**非 fork spawn**(只携带 TASK,软上下文经该 change 目录下的 `context.md` 到达)并在任务中点名"只实施 change 范围";模型按 `codingModel`、非空推理档按 `codingReasoningEffort` 传入。coding subagent 读取 tasks.md 逐任务实施 + 验证 + 勾选后,将改动与结果**回传主会话,不自行 commit**。
15
+
16
+ 两条路径共同遵守:主会话确认后回写 `context.md`(实施决策)并按共用 index 隔离协议统一提交 apply 阶段 commit(message 为 CC 前缀 + `Change-Stage: apply` + `Change-Name: <change-name>` trailer),作为 `@lyx-review-code` 的审查对象。失败区分两阶段:**环境级不可用**(仅 `subagent` 路径可能发生——宿主无 subagent 能力、初始 spawn 失败)按回退口径回退主 agent 直接实施,输出 `[回退] subagent 不可用: <原始报错>`,SHALL NOT 视为业务失败;**实施中/验证失败** SHALL 原样呈报转人工,不自动重试、不自动兜底。隔离 worktree 的询问/新建统一收敛到 `@lyx-propose` 入口,apply 不触发任何 worktree 询问、不做隔离检测——直接在当前工作目录实施。
12
17
 
13
18
  ## 步骤
14
19
 
@@ -22,28 +27,54 @@ argument-hint: '[<change-name>]'
22
27
 
23
28
  任一步骤无法唯一确定时,不得继续执行后续步骤。
24
29
 
25
- ### 2. spawn coding subagent 实施 tasks
30
+ ### 2. codingExecutor 实施 tasks
31
+
32
+ 读取 `~/.codex/lyx/config.toml` 的 `[codexHost] codingExecutor`(缺文件/解析错误 → 明确提示"无法读取配置,请运行 `lycx doctor` 检查",SHALL NOT 按"未配置"静默继承)。
33
+
34
+ **`"main"`(默认,含未配置)**:主 agent 在当前会话直接实施,跳过下方的 spawn 段,直接执行「实施规范」。
35
+
36
+ **`"subagent"`**:按下方指示 spawn coding subagent。模型 = `codingModel`(未配置或空白 → 继承当前会话模型);推理档 = `codingReasoningEffort`(trim 后非空才随 spawn 传入)。模型与推理档只写在任务指示里,SHALL NOT 依赖 shell 层模型参数,SHALL NOT 内置"模型名 → 推理档"的硬编码映射。
26
37
 
27
38
  主会话 spawn 一个 coding subagent(由运行环境的宿主 spawn 能力落实),并给它下述任务指示:
28
39
 
29
- 1. **模型** = `~/.ly/config.toml` 的 `[codexHost] codingModel`;未配置或空白 → 继承当前会话模型。模型指定只写在任务指示里,由宿主 spawn 能力执行,SHALL NOT 依赖任何 shell 层模型参数。
30
- 2. **fork 当前会话上下文**:coding subagent 以当前会话(含 propose 阶段上下文)fork 启动——关键决策、取舍、已知边界等"软上下文"随 fork 到达实施模型。
31
- 3. **范围点名(只实施 change 范围)**:任务点名"只实施 change 范围"——读取 `openspec/changes/<change-name>/tasks.md`,按需读取同目录 `proposal.md`/`design.md` 及任务引用的上下文文件,理解现有模式;SHALL NOT 改动范围外文件。
32
- 4. **实施规范**(coding subagent 内部执行):
40
+ **轮内纪律(主会话硬规则)**:
41
+
42
+ 1. **同轮等待结果**:spawn 之后 SHALL 在本轮内等待(wait)coding subagent 返回,收到结果先逐字转达再确认;SHALL NOT 在 spawn 后结束本轮回合,留下"子 agent 已返回但主会话已退出、结果无人消费"的断链状态。
43
+ 2. **禁止口头分发**:spawn / wait 都 SHALL 落到宿主的实际工具调用,SHALL NOT 仅以自然语言描述"已分发/将分发实施任务给 coding subagent"代替实际 spawn 与等待;出现"我将 spawn…"类描述而没有对应工具调用时,该输出不视为分发动作,不得据此结束本轮或进入下一步。
44
+ 3. **消费完即关闭**:coding subagent 结果消费完毕(主会话确认与提交决策完成)SHALL 关闭它,SHALL NOT 假设 subagent 跨用户回合存活。
45
+
46
+ **spawn 前记录工作区快照**:spawn coding subagent 前 SHALL 执行一次 `git status --porcelain` 并记录快照(覆盖工作区/暂存区全部现状,含与本次无关的既存改动),供步骤 3 的文件清单核对使用。
47
+
48
+ 1. **模型与推理档** = `~/.codex/lyx/config.toml` 的 `[codexHost] codingModel` 与 `codingReasoningEffort`;模型未配置或空白 → 继承当前会话模型,推理档先 trim,trim 后非空时把 trim 后的值作为宿主 spawn 的 `reasoning_effort` 随 `codingModel` 一并传入,trim 后为空 → 不传该参数。模型与推理档指定只写在任务指示里,由宿主 spawn 能力执行,SHALL NOT 依赖任何 shell 层模型参数,SHALL NOT 内置任何"模型名 → 推理档"的硬编码映射。
49
+ 2. **agent 模型需额外配置(含推理档;spawn 前确认字段,不做清单强校验)**:coding 模型能否 spawn 由运行环境实际能力决定,SHALL NOT 依赖任何硬编码清单或 `/models` 结果预判。spawn 前 SHALL 读取 `~/.codex/lyx/config.toml` 确认 `codingModel` 与 `codingReasoningEffort` 取值;读取失败(缺文件/解析错误)→ 视为**配置状态未知**:明确提示"无法读取配置,请运行 `lycx doctor` 检查",SHALL NOT 按"未配置"静默继承回退。模型留空 → 回退继承当前会话模型;推理档 trim 后为空 → 不传 `reasoning_effort`。spawn 失败报错原文含 `Unknown model` 与 `Available models: ...` 时如实展示,提示"该模型当前不支持 spawn,请改用报错中 Available models 列表内的模型";推理档被宿主/上游拒绝时同样如实展示报错原文并按既有 spawn 失败口径处理,SHALL NOT 把取值预判为"配置无效"——能否 spawn 以宿主实际报错为准,SHALL NOT 以配置猜测绕过。**验证某模型是否可 spawn 的示例 prompt**:让 Codex 用该模型 spawn 一个子代理执行简单任务(如回复 ok),报错原文即判定依据。
50
+ 3. **非 fork spawn + 软上下文经 context.md 到达**:coding subagent SHALL 以**非 fork** 方式 spawn——子代理只携带 TASK,SHALL NOT 携带父线程对话历史(宿主 V1 语义为 `fork_context: false` 默认值;V2 语义为 `fork_turns: none`;仅当宿主仅支持"最近 N 轮"fork 模式时取最小 N 近似并如实说明,SHALL NOT 全量 fork)。关键决策、取舍、已知边界等"软上下文"经 TASK 指示读取该 change 目录下的 `context.md`(`openspec/changes/<change-name>/context.md`)到达实施模型,SHALL NOT 在 TASK 中整段复制其内容;`context.md` 缺失时如实注明后继续,SHALL NOT 凭空虚构上下文。
51
+ 4. **范围点名(只实施 change 范围)**:任务点名"只实施 change 范围"——读取 `openspec/changes/<change-name>/tasks.md`,按需读取同目录 `proposal.md`/`design.md`/`context.md` 及任务引用的上下文文件,理解现有模式;SHALL NOT 改动范围外文件。
52
+ 5. **实施规范**(coding subagent 内部执行):
33
53
  - 自顶向下逐任务实施,每完成一个任务立即验证:只修改任务列出的文件,不添加任务之外的功能/重构/注释;按 tasks.md 指定的验证方式运行验证(如 typecheck/build/test),失败则修复后重试,每个任务最多 3 次修复尝试;验证通过后,把 tasks.md 中对应条目从 `- [ ]` 改为 `- [x]`,继续下一个任务。
34
54
  - 不询问——任务描述有歧义时按最简方案处理,直接落地并在回传结果中说明选择。
35
- 5. **回传不 commit**:coding subagent SHALL NOT 自行执行任何 git commit——实施完成后,将实际改动的文件清单、验证结果与逐任务完成情况回传主会话。
55
+ 6. **回传不 commit**:coding subagent SHALL NOT 自行执行任何 git commit——实施完成后,将实际改动的文件清单、验证结果与逐任务完成情况回传主会话。
36
56
 
37
- **环境级不可用回退**:若当前环境无 subagent spawn 能力或初始 spawn 失败,主会话回退为当前会话直接实施(实施规范同上),并如实报告"已回退,原因:subagent 不可用"——该回退 SHALL NOT 视为业务失败。
57
+ **环境级不可用回退**:若当前环境无 subagent spawn 能力或初始 spawn 失败,主会话回退为当前会话直接实施(实施规范同上),并输出**显式状态标记** `[回退] subagent 不可用: <原始报错>` 作为回退事实的唯一宣告——SHALL NOT 以其他自然语言描述代替该标记,SHALL NOT 在回退后以"实施已完成"之类结论冒充真实执行;该回退 SHALL NOT 视为业务失败。
38
58
 
39
59
  ### 3. 主会话确认并统一提交(全部任务完成时执行)
40
60
 
41
- 1. 主会话收到 coding subagent 回传的改动与结果后确认;确认时先检查 `git status --porcelain`:若实施前已存在与本次无关的预存改动,`git add` 范围仅限本次实际改动的文件,SHALL NOT 将预存改动一并暂存/提交,并在报告中说明"预存改动未被提交"。
42
- 2. `git add` 本次实际改动的文件后立即 `git commit -m "apply: <change-name>"`。
43
- 3. `apply: <change-name>` commit 即 `@lyx-review-code` 的审查对象。
44
- 4. 无可提交内容(如 tasks 本身无产出、或改动已在审查循环中被提交)则跳过,不创建空 commit。
45
- 5. `git commit` 失败,如实报告 Git 返回的原始错误,不重试不兜底。
61
+ 1. 主会话收到回传的改动与结果后确认(subagent 路径以 coding subagent 回传清单为对照;**环境级不可用回退的自实施路径无 subagent 回传清单,以主会话自己记录的实施改动文件清单——逐项列出并展示给用户——充当回传清单,快照与核对规则一致**)。确认前先识别 **partial apply**:残留判据限定为"改动路径落在本次实施目标文件集合内"——若步骤 2 快照中已存在的 dirty 路径 ∩ 本次实施目标文件集合(tasks.md 指向的 `templates/`、`src/` 等路径)≠ ∅,或该 change 目录下 tasks.md 已出现勾选但对应改动未提交,SHALL 判定 partial apply 并停止转人工(与本次实施无关的既存改动明确不算残留,交由快照差集与重叠规则处理)。随后确认时再执行一次 `git status --porcelain`,与步骤 2 spawn 前记录的快照**比对**:比对只针对快照之后新增/变化的路径——既存改动(快照中已存在的路径且状态未变)不参与比对、不纳入本次提交范围(保持"预存改动未被提交"口径,`git add` 范围仅限本次实际改动的文件,并在报告中说明"预存改动未被提交")。仅当**快照之后出现回传清单之外的改动**、或**回传清单中的文件实际未变动**时才判定不一致:不一致 SHALL 停止并逐项列出差异路径报告,不执行 commit、不照单全收,转人工确认。**快照前已 dirty 的路径出现在回传清单**(与本次改动重叠,无法机械区分同一文件内既存与本轮的 hunk)→ SHALL 停止转人工,不得猜测性提交,报告中 SHALL 回指 propose 步骤 1 的既存改动处置选择,说明该路径下既存改动与实施目标文件重叠会使 apply 停止。
62
+ 2. 确认一致后,**回写 context.md(实施软上下文)**:把实施阶段新产生的关键决策(实现取舍、对方案的偏差及理由、发现的坑)更新进 `openspec/changes/<change-name>/context.md`——增量追加或修订,SHALL NOT 重写或删除 propose 阶段已沉淀的内容(确已过时的条目标注"已过时"保留痕迹);实施无新增软上下文时保持原样不强行凑写。`context.md` 缺失(历史 change)时跳过回写并在报告中注明。**回写了 context.md 时 SHALL 把它并入"本次待提交文件清单"**(清单 = coding subagent 回传清单 ∪ 回写后的 `context.md`;自实施路径同理——主会话记录的实施改动清单 ∪ `context.md`),后续暂存与提交校验均以更新后的清单为准。
63
+ 3. 确认一致后提交,按共用 index 隔离协议执行(目标范围为本次待提交文件清单):
64
+ - `git add -- <本次待提交文件清单>`(不用 `git add -A`)。
65
+ - **步骤 2 快照中已存在 staged 内容时**:用 `git commit --only -m "<message>" -- <本次待提交文件清单>` 仅提交该清单(**`-m` 必须放在 `--` 之前**;清单含未跟踪新文件时**必须先 `git add`**,否则 `--only` 报 `pathspec ... did not match any file(s) known to git`;SHALL NOT 用全量 `git commit` 吞并 index 既存 staged 内容),或先 unstage 非本次文件、提交后恢复原暂存状态;范围外文件保留原暂存状态。
66
+ - 同一文件内既存 staged hunk 与本次 hunk 混合、无法机械分离时 → 无法安全隔离,SHALL 停止转人工,不猜测性提交。
67
+ - 快照中无 staged 内容时:直接 `git commit`。
68
+ - message 采用 Conventional Commits 前缀 + trailer 结构:`<cc-type>(<scope>): <subject>`(type 由主会话按本次实际改动判断,如 `feat` / `fix` / `refactor`;SHALL NOT 固定为某个 type),末尾带 `Change-Stage: apply` 与 `Change-Name: <change-name>` trailer。
69
+ - 提交后 SHALL 以 `git show --name-only` 校验该 apply 阶段 commit 的文件集合严格等于本次待提交清单(含回写的 `context.md`,如适用),不相等 SHALL 如实报告并修复,不得带着多余文件进入 apply 阶段 commit。
70
+ 4. apply 阶段 commit 即 `@lyx-review-code` 的审查对象(定位见 `@lyx-review-code` 的 trailer 优先规约)。
71
+ 5. 无可提交内容(如 tasks 本身无产出、或改动已在审查循环中被提交)则跳过,不创建空 commit。
72
+ 6. 若 `git commit` 失败,如实报告 Git 返回的原始错误,不重试不兜底。
46
73
 
47
74
  ### 失败处理(未全部完成时执行)
48
75
 
49
- **实施中/验证失败**(coding subagent 报告任务未完成或验证失败):主会话原样呈报失败详情转人工,不自动重试、不切回自实施、不 commit、不自动兜底。列出 tasks.md 中仍未勾选的条目,停止执行;改动可能已部分落地在工作区,保留原状,由用户决定后续处理。
76
+ **实施中/验证失败**(coding subagent 报告任务未完成或验证失败):主会话原样呈报失败详情转人工,不自动重试、不切回自实施、不 commit、不自动兜底。列出 tasks.md 中仍未勾选的条目,停止执行;改动可能已部分落地在工作区,保留原状,由用户决定后续处理。失败呈报的末尾 SHALL 附**下一步可用命令指引**,供用户在"断在明确节点、人工自行触发下一步"口径下续接,例如:
77
+
78
+ - 可用 `@lyx-apply <change-name>` 重跑实施(处理完失败原因后);
79
+ - `@lyx-review-code <change-name>` 暂缓(尚无完整的 apply 阶段 commit 作为审查对象);
80
+ - 已部分落地的改动保留在工作区未提交,可先 `git diff` / `git status` 查看。
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lyx-archive
3
- description: ' opsx:archive 编排流程归档完成的 change,完成后 commit'
3
+ description: '归档前先执行项目完整验证(测试/类型检查/构建),通过后按 opsx:archive 编排流程归档完成的 change,完成后 commit'
4
4
  argument-hint: '[<change-name>]'
5
5
  ---
6
6
 
@@ -10,13 +10,26 @@ argument-hint: '[<change-name>]'
10
10
 
11
11
  按 `@openspec-archive-change skill`(opsx archive 编排 prompt)定义的流程归档指定 change(`参数` 未指定时按 opsx:archive 流程的默认规则确定目标)。
12
12
 
13
+ ## 归档前完整验证(SHALL,先于任何归档动作)
14
+
15
+ 在委托 OpenSpec 归档流程**之前**,对当前工作区执行一次项目完整验证,覆盖测试 / 类型检查 / 构建三类:
16
+
17
+ - 按项目实际提供的脚本选择(例如 `package.json` 的 `scripts.test` / `scripts.typecheck` / `scripts.build`,或项目 README/AGENTS.md 声明的等价命令)。
18
+ - 项目未提供的类别 SHALL 跳过并在报告中注明(例如"未提供 typecheck 脚本"),SHALL NOT 因缺失判定失败。
19
+ - 全部通过才继续;任一类别失败 SHALL 停止归档,**不移动** `openspec/changes/<change-name>/`,如实报告失败的脚本与原始错误输出。
20
+
21
+ 该验证是慢验证的**唯一执行点**:审查关卡(`@lyx-review-plan` / `@lyx-review-code`)SHALL NOT 重复执行测试 / 类型检查 / 构建(`openspec validate` 仍由 review-plan 每轮执行,不属于本步范围)。
22
+
13
23
  ## 提交归档改动
14
24
 
15
25
  归档会把 `openspec/changes/<change-name>/` 移动到 `openspec/changes/archive/`,并可能同步更新 `openspec/specs/`。提交涉及的全部文件:
16
26
 
17
27
  ```bash
18
28
  git add -- openspec/
19
- git commit -m "archive: <change-name>"
29
+ git commit -m "chore(openspec): 归档 <change-name>" -m "Change-Stage: archive
30
+ Change-Name: <change-name>"
20
31
  ```
21
32
 
33
+ message 采用 Conventional Commits 前缀 + trailer 结构:CC 前缀固定 `chore(openspec)`,末尾带 `Change-Stage: archive` 与 `Change-Name: <change-name>` trailer(`-m` 分两段传入时,git 会在两段之间插入空行,trailer 块因此位于 message 末尾)。
34
+
22
35
  若无可提交内容或 `git commit` 失败,跳过提交,如实报告原始错误,不视为归档失败。
@@ -22,24 +22,21 @@ argument-hint: '<项目摘要或名称>'
22
22
 
23
23
  由当前会话直接生成/更新项目根目录的 `AGENTS.md`(单 Agent 模式,无外部技能委托):以 `参数`(项目摘要或名称)为线索,结合当前仓库结构,写清模块职责、入口与启动方式、核心类型、构建/测试命令、关键约定。已存在时增量更新,不推翻既有内容、不删除既有章节。
24
24
 
25
- ### 步骤 2:初始化 OpenSpec
25
+ ### 步骤 2:确保 OpenSpec 可用(共享检查/修复入口)
26
26
 
27
- 1. **检测 OpenSpec CLI**:
27
+ 1. **调用共享 ensure 入口**(当前工作目录下执行,禁止 `cd` 到其他路径;不确定当前目录先 `pwd` 确认):
28
28
  ```bash
29
- openspec --version
29
+ lycx openspec ensure --yes --json
30
30
  ```
31
- 2. **未安装则全局安装**:
31
+ `lycx` 不在 PATH,则回退:
32
32
  ```bash
33
- npm install -g @fission-ai/openspec@latest
34
- ```
35
- 3. **检查是否已初始化**:
36
- ```bash
37
- ls -la openspec/ 2>/dev/null || echo "Not initialized"
38
- ```
39
- 4. **未初始化则运行**(当前工作目录下执行,禁止 `cd` 到其他路径;不确定当前目录先 `pwd` 确认)——用 `--tools codex` 非交互指定 AI 工具为 Codex,避免卡在交互式选择上:
40
- ```bash
41
- openspec init --tools codex
33
+ npx -y ly-workflow-codex openspec ensure --yes --json
42
34
  ```
35
+ 2. **解析 JSON 结果**:读取 `cli.status`、`skills.status`、`skills.missing`、`root.status`、`actions` 与 `executed`。
36
+ - `skills.status === "global-only"`:输出 WARN 说明 skills 仅全局可用但命令可继续;不自动固化项目级。
37
+ - `cli.status !== "ok"`、`skills.status === "missing"` 或 `root.status` 为 `missing` / `unhealthy` 且 ensure 后仍未修复:停止,展示缺失 skill 清单与 `openspec doctor --json` 的 fix 建议。
38
+ - `root.status === "healthy"` 且 `skills.status` 为 `project-ready` 或 `global-only`:继续步骤 3。
39
+ 3. **不要自行复制 workflow → skill 检测逻辑**。CLI、skills、root 的检查与修复统一由 `lycx openspec ensure` 负责。
43
40
 
44
41
  ### 步骤 3:提交初始化产物
45
42
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lyx-propose
3
- description: '按 opsx:propose 编排流程生成方案;创建方案前先问隔离方式(worktree / 本项目切新分支 / 留在当前分支)与全自动/手动(各只一次);产物生成后 commit 前执行方案自审(闭环+全面性),自审修复随 propose: commit 一次落库;全自动 = 自动流水线到审完代码,手动 = 逐步确认'
3
+ description: '按 opsx:propose 编排流程生成方案;创建方案前先问隔离方式(worktree / 本项目切新分支 / 留在当前分支)与全自动/手动(各只一次);产物生成后 commit 前执行方案自审(闭环+全面性),自审修复随 propose 阶段 commit(CC 前缀 + Change-Stage: propose trailer)一次落库;全自动 = 自动流水线到审完代码,手动 = 逐步确认'
4
4
  argument-hint: '<需求描述>'
5
5
  ---
6
6
 
@@ -8,7 +8,7 @@ argument-hint: '<需求描述>'
8
8
 
9
9
  > 调用方式:`@lyx-propose` mention 后跟随的自然语言即参数(如 `@lyx-propose` 带需求描述/选项);无参数时直接 `@lyx-propose`。
10
10
 
11
- 收尾编排入口。创建方案前先问两件事(各只一次):本次开发的隔离方式(隔离 worktree / 本项目切新分支 / 留在当前分支,不在 worktree 内才问)、本次走全自动还是手动。产物生成后、commit 前由方案提出者执行一次方案自审(逻辑闭环 + 业务全面性,见步骤 5),自审修复随 `propose: <change-name>` commit 一次干净落库;全自动路径在同一会话内自动跑 review-plan → apply → review-code 直到审完代码,手动路径逐步确认。
11
+ 收尾编排入口。创建方案前先问两件事(各只一次):本次开发的隔离方式(隔离 worktree / 本项目切新分支 / 留在当前分支,不在 worktree 内才问)、本次走全自动还是手动。产物生成后、commit 前由方案提出者执行一次方案自审(逻辑闭环 + 业务全面性,见步骤 5)与 context.md 软上下文产出(见步骤 5.5),自审修复与 context.md 随 propose 阶段 commit(message 带 `Change-Stage: propose` 与 `Change-Name` trailer)一次干净落库;全自动路径在同一会话内自动跑 review-plan → apply → review-code 直到审完代码,手动路径逐步确认。
12
12
 
13
13
  ## 步骤
14
14
 
@@ -51,7 +51,7 @@ argument-hint: '<需求描述>'
51
51
  2. 检查当前工作区未提交改动(`git status --porcelain`):非空时用一次三选一询问处置方式,各选项文案如实说明后果:
52
52
  - **提交(WIP commit)**:`git add -A && git commit -m "wip: 切分支前暂存工作区改动"` 后再切分支——新分支从含 WIP commit 的 HEAD 切出,改动固化为新分支上的提交,review-code 审查对象不受污染;
53
53
  - **Stash**:`git stash push -u` → 切分支 → `git stash pop`——如实说明"pop 回来后改动仍在工作区,stash 仅提供日志留底";
54
- - **原样保留**:不做任何处理——明示"改动会进入 review-code 审查范围(`git diff HEAD`),可能污染审查对象"
54
+ - **原样保留**:不做任何处理——明示"改动会进入 review-code 审查范围(`git diff HEAD`),可能污染审查对象";且若这些改动与后续 apply 的实施目标文件重叠,apply 会直接停止转人工(停止报告会回指此处处置选择)。
55
55
 
56
56
  三种选择均直接执行(风险已写入文案,不二次确认);处置动作失败(提交失败、stash 失败等)→ **如实报错停止编排,不自动兜底**。
57
57
  3. 执行 `git checkout -b <开发分支名>`(从当前 HEAD 建新分支并切换)。本路径**不运行 baseline 验证**(同一工作目录、同一 env、同一 node_modules,baseline 验证的"全新 worktree 可用性"前提不成立)、**不切换会话工作目录**、**不打印兜底续接命令**(无目录切换即无会话断链风险)。分支名已存在或非法导致 `git checkout -b` 失败时,**如实报错停止编排转人工**(不自动改名、不自动 stash),change 尚未生成。
@@ -96,22 +96,37 @@ argument-hint: '<需求描述>'
96
96
 
97
97
  自审 MUST 产出可见的**逐项结论清单**,对四项检查的每一子项(每条 What Change 的闭环情况、每个 Modified Capability 的基线波及情况、每个通用维度)分别标注四值结论之一:**通过 / 不适用(含理由)/ 已修复(含改动说明)/ 待用户决策(含问题)**。SHALL NOT 以"自审通过,无问题"之类的一句总结代替逐项清单;未写理由的静默跳过视为未执行该项。存在"待用户决策"项时 SHALL 在清单中列出完整问题再询问。
98
98
 
99
- **自审修改后验证**:自审产生任何 artifact 修改(尤其 delta spec)后,SHALL 运行 `openspec validate --changes <change-name>` 确认结构合法,再进入步骤 6
99
+ **自审修改后验证**:自审产生任何 artifact 修改(尤其 delta spec)后,SHALL 运行 `openspec validate --changes <change-name>` 确认结构合法,再进入步骤 5.5
100
+
101
+ ### 5.5 产出 context.md 软上下文 artifact(commit 前)
102
+
103
+ 在方案自审完成之后、步骤 6 commit 之前,由当前会话产出 `openspec/changes/<change-name>/context.md`(软上下文 artifact,详见 spec 能力 `review-context-artifact`):
104
+
105
+ 1. **收录内容**(只记文档之外的讨论结论):关键决策与理由、已否决的备选方案及否决理由、范围边界(明确做什么/不做什么)、已知坑与注意事项。与 proposal/design/tasks/delta spec 重复的内容以一句话引用指路,SHALL NOT 整段摘抄。
106
+ 2. **内容边界自检(产出质量关卡)**:产出时完成一次自检——(a) 无与 artifact 重复的整段内容;(b) 每条决策/否决理由可溯源到本 change 讨论或基线 artifact 对应条目;(c) 行数 ≤ 100 行(它是每次 subagent spawn 的固定读取成本)。自检不通过 → 修订后重检,SHALL NOT 带病产出。
107
+ 3. **无实质内容时**:仍产出仅含标题与一行说明的最小骨架文件,SHALL NOT 省略文件——审查/实施 subagent 的 TASK 引用固定路径,文件缺失会造成断链。
100
108
 
101
109
  ### 6. 暂存并立即 commit(每步 commit)
102
110
 
103
- 自审完成(含其修复)后执行。自审产生的 artifact 修复属于本次待提交内容——产物与自审修复是同一个待提交单元,随这次 commit 一次干净落库,不产生"commit + 未提交自审修复"的混合状态。
111
+ 自审完成(含其修复)与 context.md 产出后执行。自审产生的 artifact 修复与 context.md 属于本次待提交内容——产物、自审修复与 context.md 是同一个待提交单元,随这次 commit 一次干净落库,不产生"commit + 未提交自审修复"的混合状态。
104
112
 
105
- 1. 检查整个 Git index(`git diff --cached --name-only`):若存在该 change 目录之外的已暂存内容,**停止**,报告"检测到该 change 目录外的已暂存内容,请先处理(unstage 或另行提交)后重试",不执行 `git add` 也不 commit。
106
- 2. index 干净后:`git add -- openspec/changes/<change-name>/`(该目录含 `.openspec.yaml` 元数据、proposal/design/tasks 与全部 delta spec,集群暂存,不用 `git add -A`)。
107
- 3. **立即 commit**:
113
+ 1. `git add -- openspec/changes/<change-name>/`(该目录含 `.openspec.yaml` 元数据、proposal/design/tasks、context.md 与全部 delta spec,集群暂存,不用 `git add -A`)。
114
+ 2. **按共用 index 隔离协议提交**——目标范围为 `openspec/changes/<change-name>/` 目录,协议分支:
115
+ - index 中无该目录外的已暂存内容 → 直接 commit(见第 3 步命令)。
116
+ - index 中存在该目录外的已暂存内容、且与目标范围无文件重叠 → 用 `git commit --only -m "<message>" -- openspec/changes/<change-name>/` 隔离提交(**`-m` 必须放在 `--` 之前**;目标范围含未跟踪新文件时**必须先 `git add`**,否则 `--only` 报 `pathspec ... did not match any file(s) known to git`),或先 unstage 非目标文件、提交后恢复原暂存状态;范围外文件保留原暂存状态。
117
+ - 同一文件内既存 staged hunk 与本次 hunk 混合、无法机械分离时 → **停止转人工**,如实报告,不猜测性提交。
118
+ 3. **立即 commit**,message 采用 Conventional Commits 前缀 + trailer 结构:
108
119
  ```
109
- git commit -m "propose: <change-name>"
120
+ docs(openspec): <subject>
121
+
122
+ Change-Stage: propose
123
+ Change-Name: <change-name>
110
124
  ```
111
- 4. `git show --name-only --format=` 校验这次 commit 的实际文件集合严格属于 `openspec/changes/<change-name>/` 目录(含 `.openspec.yaml`)。
112
- 5. 若该目录下无可提交内容、`git commit` 失败,或校验发现文件集合超出该目录范围,**停止后续自动化步骤**,报告具体原因。
125
+ (subject 用一句人话概括本次方案;`Change-Stage` 固定 `propose`。)
126
+ 4. 用 `git show --name-only --format=` 校验这次 commit 的实际文件集合严格等于目标范围(该目录全部应提交文件,含 `.openspec.yaml` 与 `context.md`)——不许超出、不许漏项。
127
+ 5. 若该目录下无可提交内容、`git commit` 失败,或校验发现文件集合与目标范围不相等,**停止后续自动化步骤**,报告具体原因。
113
128
 
114
- `propose: <change-name>` commit(含自审修复)即 `@lyx-review-plan` 的审查对象(见 `@lyx-review-plan` 的审查范围判定:`git log --grep="^propose: <change-name>"` 取 HEAD 侧最近一期,`git show <commit>` + `git diff HEAD` + 未跟踪清单)。
129
+ propose 阶段 commit(含自审修复)即 `@lyx-review-plan` 的审查对象(见 `@lyx-review-plan` 的审查范围判定:按 trailer 定位 `Change-Stage: propose` + `Change-Name: <change-name>`,`git show <commit>` + `git diff HEAD` + 未跟踪清单;trailer 未命中时回退旧前缀 `^propose: <change-name>` 并打印 DEPRECATED 兼容通道提示)。
115
130
 
116
131
  ### 7. 按第 2 步选择分支
117
132
 
@@ -122,24 +137,29 @@ argument-hint: '<需求描述>'
122
137
 
123
138
  **全程无隔离方式询问、不自动 archive。**
124
139
 
125
- 1. 自动执行 `@lyx-review-plan <change-name>` 编排流程(完整指示见 `@lyx-review-plan skill 的指示`,按其指示逐轮执行审查-修复循环;审查由**双审查 subagent** 执行——fork 当前会话上下文 + 范围点名 + 独立审 交换 共识,模型按 `reviewModel`/`reviewModelB` 分别指定;审查对象为 `propose:` commit,清零时由循环统一提交修复)。
140
+ **执行者语义(自 switchable-executor-flow 起)**:流水线每一步的主体按配置决定,不由本模板写死——review-plan / review-code `[codexHost] reviewExecutor`(`main` = 主 agent 直接审查,默认;`subagent` = spawn 审查 subagent),apply `[codexHost] codingExecutor`(`main` = agent 直接实施,默认;`subagent` = spawn coding subagent)。**慢验证(测试 / 类型检查 / 构建)SHALL NOT 在流水线内的审查循环执行**——统一由 `@lyx-archive` 的归档前完整验证关卡执行一次。
141
+
142
+ 1. 自动执行 `@lyx-review-plan <change-name>` 编排流程(完整指示见 `@lyx-review-plan skill 的指示`,按其指示逐轮执行审查-修复循环;审查对象为 propose 阶段 commit(带 `Change-Stage: propose` trailer),清零时由循环统一提交修复)。
126
143
  - Critical 清零 → 进入下一步。
127
- - 其余任一种终止(熔断、分歧未决、无法安全修复、验证失败、审查调用失败、达到轮数上限)→ **停止流水线**,复用该循环已产出的终止报告(不重新生成或重复一份)报告终止原因,结束,不执行后续步骤。
128
- 2. 自动执行 `@lyx-apply <change-name>` 编排流程(完整指示见 `@lyx-apply skill 的指示`;实施由 **coding subagent** 执行——fork 当前会话上下文 + 只实施 change 范围,模型按 `codexHost.codingModel` 指定、未配置回退当前会话模型;实施完成回传主会话,主会话确认后统一提交 `apply: <change-name>`)。
129
- 3. 自动执行 `@lyx-review-code <change-name>` 编排流程(完整指示见 `@lyx-review-code skill 的指示`;审查同样由**双审查 subagent** 执行;审查对象为 `apply:` commit,清零时由循环统一提交修复)。
144
+ - 其余任一种终止(熔断、驳回硬线、无法安全修复、验证失败、审查调用失败、达到轮数上限)→ **停止流水线**,复用该循环已产出的终止报告(不重新生成或重复一份)报告终止原因,结束,不执行后续步骤。
145
+ 2. **节点前置校验(进入 apply 前)**:进入 apply 之前 SHALL 校验 review-plan 是否以"正常清零"收尾——判据为**本会话记录的 review-plan 循环终止类型 == 正常清零**且无未决人工介入项(不依赖清零报告文件等会话外 artifact)。校验 SHALL 在该节点显式打印一行校验结论(含依据:终止类型、是否无未决项);校验不过(终止类型为熔断/驳回硬线/无法安全修复/验证失败/审查调用失败/轮数上限,或存在未决项)SHALL 停在该节点,复用 review-plan 已产出的终止报告说明阻断原因,SHALL NOT 硬闯 apply
146
+ 3. 自动执行 `@lyx-apply <change-name>` 编排流程(完整指示见 `@lyx-apply skill 的指示`;实施主体按 `codingExecutor` 决定,实施完成后由主会话确认、回写 `context.md`(实施决策)并统一提交 apply 阶段 commit——message 为 CC 前缀(type 由主会话按实际改动判断)+ `Change-Stage: apply` + `Change-Name: <change-name>` trailer)。
147
+ 4. **节点前置校验(进入 review-code 前)**:apply 实施完成并提交时 SHALL 以 `git rev-parse HEAD` 记录本次 apply 提交后的 HEAD SHA;进入 review-code 之前 SHALL 按 trailer 优先定位最近一期 apply 阶段 commit 的 SHA(`git log --grep="^Change-Stage: apply$" --grep="^Change-Name: <change-name>$" --all-match -1 --format=%H`;未命中时回退旧前缀 `git log --grep="^apply: <change-name>" -1 --format=%H` 并打印 DEPRECATED 兼容通道提示),并校验其等于本次记录(**历史存在旧 apply commit 不得绕过本次校验**)。校验 SHALL 在该节点显式打印一行校验结论(含依据:本次记录的 SHA、最近一期 apply 阶段 commit SHA、是否相等)。校验不过(SHA 不等、commit 缺失或实施阶段未正常收尾)SHALL 停在该节点如实报告实施收尾失败详情,SHALL NOT 以旧 commit 作为本次审查对象进入 review-code。
148
+ 5. 自动执行 `@lyx-review-code <change-name>` 编排流程(完整指示见 `@lyx-review-code skill 的指示`;审查主体按 `reviewExecutor` 决定;审查对象为 apply 阶段 commit(带 `Change-Stage: apply` trailer),清零时由循环统一提交修复)。
130
149
  - Critical 清零 → 流水线结束,提示可手动 `@lyx-archive` 归档。
131
150
  - 其余任一种终止 → **停止流水线**,复用该循环已产出的终止报告报告终止原因,结束。
132
- 4. 流水线执行过程中任一环节 `git commit` 失败:如实报告 Git 原始错误,停止流水线。
151
+ 6. 流水线执行过程中任一环节 `git commit` 失败:如实报告 Git 原始错误,停止流水线。
133
152
 
134
153
  ### 9. 手动:逐步确认
135
154
 
136
- 1. `propose: <change-name>` commit 完成后,询问:
155
+ 1. propose 阶段 commit(带 `Change-Stage: propose` trailer)完成后,询问:
137
156
  ```
138
157
  "要不要现在跑一次 review-plan 审查循环?"
139
158
  ```
159
+ 询问时 SHALL 附带当前状态摘要:当前阶段(propose 阶段 commit 已完成)与下一步(选"是"将调用 `@lyx-review-plan <change-name>`,审查对象为该 commit),保证选"是"后的续接无歧义。
140
160
  - **否** → 编排结束。方案已 commit;日后由用户自行 `@lyx-apply` 实施、`@lyx-review-code` 审查。
141
161
  - **是** → 继续步骤 2。
142
- 2. 执行 `@lyx-review-plan <change-name>` 编排流程(审查由**双审查 subagent** 执行;审查对象为 `propose:` commit,清零时由循环统一提交修复)。
162
+ 2. 执行 `@lyx-review-plan <change-name>` 编排流程(审查由**单审查 subagent**(非 fork)执行;审查对象为 propose 阶段 commit,清零时由循环统一提交修复)。
143
163
  3. 循环终止(无论何种原因)后编排结束,**不再询问隔离方式、不再询问提交、不自动衔接 apply**——日后的实施与代码审查由用户另行 `@lyx-apply`、`@lyx-review-code` 触发。
144
164
 
145
165
  ---