ly-workflow-codex 0.2.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.
@@ -0,0 +1,190 @@
1
+ ---
2
+ name: lyx-review-code
3
+ description: '读取 git diff,双审查 subagent(fork 当前会话上下文,模型按 reviewModel/reviewModelB 分别指定)审查代码变更,审查-修复循环直到 Critical 清零或触发终止条件'
4
+ argument-hint: '[<change-name>] [--no-commit]'
5
+ ---
6
+
7
+ <!-- 双审查 subagent 执行约定(spawn 协议、任务构造、共识/分歧裁决)内联于本文件,无外部 shell 调用契约;
8
+ 模型指定经"模板指示 + 宿主能力"落实,见"步骤 2"与模板变量说明 -->
9
+
10
+ # Review Code - 代码审查
11
+
12
+ > 调用方式:`@lyx-review-code` mention 后跟随的自然语言即参数(如 `@lyx-review-code` 带需求描述/选项);无参数时直接 `@lyx-review-code`。
13
+
14
+ 审查当前代码变更,由 **2 个并行审查 subagent** 审查(subagent 多 Agent 模式,每个子会话 fork 当前会话上下文、任务点名"只审该 change 的代码变更"),输出 Critical/Warning/Info 分级结果。若存在 Critical,进入审查-修复循环:当前会话判断是否认可每条 Critical,认可则修复并自动重新审查,直到清零或触发终止条件。
15
+
16
+ 审查 subagent 模型按 `codexHost.reviewModel`(agent A)/ `codexHost.reviewModelB`(agent B)分别指定,未配置或空白时继承当前会话模型。两 agent 各自独立审查 → 交换结论 → 达成共识;意见分歧时主会话拍板并显式提示用户,主会话不能确认 → 判定 Critical。Critical 判定/修复由当前会话执行。
17
+
18
+ 循环执行期间默认不提交;仅当循环以"正常清零"结束时,才对审查目标全部文件(`git diff HEAD` 圈定的原始改动 + 循环修复一并暂存)统一提交一次。传入 `--no-commit` 时,连这次最终的统一提交也不做。
19
+
20
+ ## 步骤
21
+
22
+ ### 1. 判定审查范围(仅首轮执行一次,后续轮次复用)
23
+
24
+ 按目标 change 的最近一期 `apply:` commit 作为审查基线(编排方 `@lyx-apply` 在实施完成后立即提交,提交信息 `apply: <change-name>`):
25
+
26
+ 1. 解析目标 change(优先级同 `@lyx-apply`:`参数` 显式 change 名 → `openspec/changes/` 下唯一未归档 change → 询问用户)。
27
+ 2. `git log --grep="^apply: <change-name>"` 取 HEAD 侧最近一期匹配 commit:
28
+ - **存在** → 审查范围 = 该 `apply:` commit 差异(`git show <commit>`)+ 当前 `git diff HEAD`(循环修复)+ `git status --porcelain` 过滤 `??` 得到的未跟踪文件路径清单。工作区/暂存区干净时**仍按该 commit 审查**,不报"无变更可审查"。
29
+ - **不存在**(该 change 尚无 apply commit)→ 检查最近一次相关 `propose: <change-name>` commit(`git log --grep="^propose: <change-name>" -1`):存在 → 审查范围 = 该 `propose:` commit 差异 + 当前 `git diff HEAD` + `??` 未跟踪路径清单(工作区/暂存区干净时仍按该 commit 审查)。仍不存在(零 commit 仓库或该 change 尚无任何相关 commit)→ 退化为"有未提交变更"组合:`git diff HEAD`(覆盖已暂存+未暂存)+ `??` 未跟踪清单;仓库零 commit(`git rev-parse HEAD` 失败)→ 三条固定命令组合:`git diff --cached` + `git diff` + `??` 未跟踪路径清单。无未提交变更且也无相关 commit → 报告"无变更可审查",直接结束。
30
+
31
+ **无论哪种情况**,额外用 `git status --porcelain` 抓取 `??` 开头的未跟踪文件路径——避免新建但未 `git add` 的文件被漏审。
32
+
33
+ ```bash
34
+ git log --grep="^apply: <change-name>" -1 --format='%H' 2>/dev/null
35
+ git log --grep="^propose: <change-name>" -1 --format='%H' 2>/dev/null
36
+ git rev-parse HEAD >/dev/null 2>&1 && echo has_head || echo no_head
37
+ git status --porcelain | grep '^??'
38
+ ```
39
+
40
+ **首轮确定的审查范围(`git log --grep` 定位 commit / `git diff HEAD` / 零 commit 三条命令组合)必须记录下来,供首轮 TASK 使用**,不重新执行本步骤的分支选择逻辑。判定审查范围本身(选哪条分支、取哪个 commit)由当前会话完成,不下放给审查 subagent。
41
+
42
+ ### 2. spawn 双审查 subagent(首轮)
43
+
44
+ 本关卡审查由 **2 个并行审查 subagent** 执行(subagent 多 Agent 模式,不再走独立子进程 shell 调用)。审查 subagent 以 agentic 模式运行,具备自主执行 shell 命令、读取文件的能力。TASK 里 SHALL NOT 由当前会话预先读取 `git diff`/未跟踪文件内容拼进字符串;只传基线引用说明和未跟踪文件路径清单,指示审查 subagent 自行执行对应命令获取实际内容。主会话按以下指示 spawn,由运行环境的宿主 spawn 能力落实:
45
+
46
+ 1. **spawn 两个审查 subagent,并行独立审查**(互不见对方结论):
47
+ - **审查 agent A**:模型 = `~/.ly/config.toml` 的 `[codexHost] reviewModel`;未配置或空白 → 继承当前会话模型。
48
+ - **审查 agent B**:模型 = `[codexHost] reviewModelB`;未配置或空白 → 继承当前会话模型。
49
+ 2. **fork 当前会话上下文**:两个 agent 均 fork 当前会话上下文启动——主会话讨论中的关键决策、取舍、已知边界等"软上下文"随 fork 到达审查模型,避免关键信息丢失。模型指定只写在模板指示里(取哪个配置字段、未配置用当前会话模型),由宿主 spawn 能力执行,SHALL NOT 依赖任何 shell 层模型参数(无 `-m`/`--model` 类指令)。
50
+ 3. **TASK 范围点名(只审 change 范围)**:每个审查 subagent 的任务均点名"只审该 change 的下列代码变更",SHALL NOT 超出点名范围作业。TASK 先指示读取 ROLE_FILE(两个 agent 均用 `~/.ly/prompts/codex/reviewer.md`,角色词内容不重写),再给出审查范围说明(步骤 1 记录的基线引用说明或零 commit 场景组合)与未跟踪文件路径清单;**首轮不拼贴 diff 全文**——审查 subagent 自行执行对应命令获取实际内容(例如"运行 git diff HEAD 得到完整 diff"),不要假设范围。
51
+
52
+ OUTPUT 约束(写入每个审查 subagent 的任务):审查发现按严重度分级 Critical/Warning/Info,每条含位置(含可解析的文件相对路径)、问题、建议。
53
+
54
+ **两 agent 结论汇合(独立审 → 交换 → 共识)**:
55
+
56
+ 1. 两个 agent 独立审查完毕后,**由主会话将 A/B 结论互转给双方**(两 subagent 由宿主并行 spawn、不直连),各自针对对方结论给出最终意见后,主会话再归并共识。
57
+ 2. **共识归并**:两 agent 结论合并去重后作为本轮审查结论;部分重叠或冲突的条目 SHALL 一并列出交主会话判定,SHALL NOT 静默丢弃任一 agent 的独立发现。
58
+ 3. **意见分歧**(agent A 提出 Critical 而 agent B 未提出,或两者结论冲突)→ **主会话拍板**,且 SHALL **显式提示用户"这是审查分歧"**:主会话能确认 → 按确认结论处理;不能确认 → 判定该条为 Critical(red)进入修复循环。
59
+ 4. **分歧时序**:双 agent 首次分歧且主会话不能确认 → 判定 Critical 进入修复循环;下一轮复审双 agent 仍分歧且主会话仍不能确认 → 触发"分歧未决"终止条件(终止条件 5)。
60
+
61
+ **审查调用失败(区分两阶段)**:
62
+
63
+ - **运行期失败**(spawn 后超时、返回内容格式不符、审查 agent 未返回有效结论、双审查任一 agent 调用失败且无法按回退口径继续、回退不可行或回退后仍失败)→ 视为**独立终止条件**,如实报告原因(退出码/超时说明/原始输出片段)并停止循环,**不得**把失败等同于"本轮无 Critical"或视为清零通过。
64
+ - **环境级不可用**(宿主无 subagent 能力、初始 spawn 不可用)→ 按回退口径处理:回退为当前会话直接执行审查,并如实报告"已回退,原因:subagent 不可用",SHALL NOT 视为流程失败中断整体编排。
65
+ - **单一 agent 失败且另一 agent 结论完整** → 以完整一方结论继续审查,如实报告降级(含失败 agent 与原因),SHALL NOT 归入"分歧未决"(环境级失败非意见分歧);是否补跑/重试由主会话决定。
66
+
67
+ 本轮结束后,无论是否有 Critical,都先生成"本轮执行日志"(见"逐轮执行日志"一节),再判定:
68
+
69
+ 若本轮 Critical 数为 0 → 跳到步骤 4 输出报告,结束(不进入循环)。
70
+ 若本轮 Critical > 0 → 进入步骤 3 循环体。
71
+
72
+ ### 3. 审查-修复循环
73
+
74
+ 对本轮全部 Critical,逐条执行:
75
+
76
+ **3.1 当前会话先判断是否认可该 Critical**
77
+
78
+ 审查 subagent 的 Critical 不是必须执行的裁决。对每条 Critical:
79
+ - **认可**:判断问题确实存在,进入 3.2 修复。
80
+ - **不认可**:判断为误报、对上下文理解有误、或建议本身有问题,则不修复,但必须在本轮报告里写明反驳理由,不能沉默跳过或悄悄忽略。
81
+
82
+ **3.2 修复(仅针对认可的 Critical)**
83
+
84
+ 修复范围为"该 Critical 直接指向的文件/条目" + "修复它所必需的直接依赖条目"(例如一个跨文件的一致性问题需要同步改动多处才能真正修好);不得借机重构、格式化或改动与该 Critical 无关的内容。若改动涉及必需依赖条目(不只是 Critical 直接指向的位置),本轮报告必须逐项说明这些改动与该 Critical 的关联性。
85
+
86
+ **3.3 本轮验证**
87
+
88
+ 若项目存在对应的验证命令(测试/类型检查/构建),运行与本轮改动范围相称的验证。验证失败 → 立即停止循环,不再进行下一轮修复,报告本轮改动的文件清单及验证失败的具体信息,说明需要人工介入。
89
+
90
+ **3.4 记录本轮改动文件清单(不提交)**
91
+
92
+ 验证通过后,把本轮实际改动的文件相对路径清单写入本轮报告——这份清单是"路径清单"的一部分,供 3.5 步构造下一轮增量 TASK 直接复用,不得在后续轮次靠"当前 git 状态"反推(循环期间不逐轮 commit,但后续轮次还会继续修改文件、文件也可能被删除/重命名,仅凭某个时间点的 git 状态无法可靠还原"本轮具体改了什么")。本轮不执行任何 git commit——提交只发生在循环以正常清零结束之后(见步骤 4)。
93
+
94
+ **3.5 自动触发下一轮审查(增量传递;沿用同一批审查 subagent)**
95
+
96
+ 第 2 轮起,TASK SHALL NOT 重新拼贴完整基线 diff;改为仅包含:
97
+
98
+ 1. 上一轮审查 subagent(A/B)报告的全部 Critical 原文(逐字,不经改写,包含被判定"不认可"的条目——这些原文仍要传,用于"分歧未决"判定所需的比对)。
99
+ 2. 路径清单,必须覆盖"本轮实际修复改动的文件"(3.4 记录的清单)∪"上一轮全部 Critical 各自指向的文件"(即使某条因不认可而未被修改,其指向的文件路径也要纳入,否则审查 subagent 无法重新核实该问题是否仍存在)。若上一轮某条 Critical 指向的文件在本轮被删除或重命名,路径清单改用新路径(若有)并在 TASK 中说明该文件的状态变化,不让审查 subagent 尝试读取不存在的旧路径。
100
+
101
+ 路径清单之外的文件不重新整段传入。若某条上一轮 Critical 的位置字段缺失可解析路径(角色提示词未被遵守等异常情况),按"审查调用失败"终止条件处理(返回内容不符合可解析格式),不得静默丢弃该 Critical。
102
+
103
+ **第 2 轮起沿用同一批审查 subagent 会话**:fork 启动的 subagent 会话具备轮间记忆,第 2 轮继续使用同一批审查 subagent(A/B),无需重新 spawn 或整段重传基线——增量传递规则不变,会话记忆提供连续性,不代表 TASK 可省略逐字 Critical 原文。回到步骤 2 的执行方式(只是 TASK 内容换成上述增量内容,继续同一批审查 subagent),重新派发审查,不要求用户手动重新触发命令。生成本轮执行日志后再判定 Critical 是否清零。
104
+
105
+ ### 循环终止条件(任一命中即停止,转步骤 4)
106
+
107
+ 不设固定轮数上限作为主终止信号,但设一个**全局轮数上限(默认 5 轮)**作为最后兜底。**清零优先于轮数上限**:本轮先判 Critical 是否清零,清零则按正常清零处理结束;仅在本轮结果非清零时才检查是否已达到 5 轮上限,达到则无条件停止转人工,不管其余信号是否已触发。正常场景 2-3 轮就该清零或熔断,5 轮留出一点余量,不会在正常场景下提前打断。
108
+
109
+ 1. **正常清零**:某一轮审查 Critical 数为 0
110
+ 2. **熔断**:同一个 Critical(以"文件路径 + 问题类别 + 定位锚点(函数名/路由/调用点)"三者共同判定为同一问题,不要求文字完全一致)在相邻两轮审查中都被判定为存在,且上一轮当前会话对它是"认可"状态(已尝试修复但没修好)
111
+ 3. **无法安全自动修复**:某个 Critical 的修复需要产品/业务决策、依赖当前会话不具备的外部凭据、会改变已发布的公开 API/接口契约,或当前会话判断信息不足以给出确定性修复——命中时不得进行猜测性修改
112
+ 4. **修复后验证失败**:见 3.3
113
+ 5. **分歧未决**:当前会话对某条 Critical 上一轮判断"不认可"(未修复),下一轮审查 subagent 仍判定同一问题存在——区别于熔断(熔断是"尝试修复但没修好",分歧未决是"根本不认可");或双 agent 复审仍分歧且主会话仍不能确认(见步骤 2"分歧时序")
114
+ 6. **审查对象类型持续系统性误判**:连续 3 轮(含本轮)审查中,每一轮的全部 Critical 都被当前会话判定为同一大类系统性误判——即审查 subagent 反复以"该轮 Critical 所依据的判断类别不属于当前命令的审查范畴"为由被判定不认可,不要求这 3 轮之间 Critical 的文件/类别/锚点相互匹配,只要求"判定为不认可的理由类别"在这 3 轮中一致
115
+ 7. **达到全局轮数上限**(5 轮,独立于上面 1-6 的判定,见上段"清零优先于轮数上限")
116
+
117
+ 触发条件 2-6(或达到全局轮数上限)时,立即停止循环,不执行任何提交(改动留在工作区),报告中必须明确指出触发的具体条件、涉及的问题(文件/类别/锚点/判定依据),并说明需要人工介入,不得继续自动修复。"分歧未决"额外要求并列展示审查 subagent 每一轮的原始发现与当前会话每一轮的反驳理由;"审查对象类型持续系统性误判"同样要求并列展示,但展示连续 3 轮(而不是 2 轮)的原始发现与反驳理由。循环期间的 Warning/Info 发现不参与终止判定,只在最终报告列出**最后一轮**的结果,不跨轮次合并。
118
+
119
+ ### 逐轮执行日志
120
+
121
+ 每一轮审查 subagent 派发完成后(包括首轮 Critical 为 0、直接跳到步骤 4 结束的情况,不只是进入了循环体的轮次),都要在报告中包含一个独立区块,逐字展示该轮审查 subagent 返回的原始 Critical/Warning/Info 内容(不经概括、改写或合并),与当前会话对该轮每条 Critical 的认可/不认可判定并排列出(若该轮无 Critical,只展示原文,不需要并排判定)。这个区块在该轮审查返回之后即可呈现,不是审查 subagent 执行期间的流式展示。这是给需要核实细节的人看的补充材料;最终报告的主体是人话摘要(见步骤 4),二者并存,不互相替代。
122
+
123
+ **硬性约束(逐字性)**:该区块中的 Warning/Info 与 Critical 同样必须逐字完整贴出,**禁止用省略号("…"、"(同前)"等)改写或压缩**;清零轮(某轮 Critical 为 0)的判定仍需写明依据——对照前一轮各 Critical 的修复情况与验证结果说明"认可清零"的理由,不得仅以"无 Critical,正常清零"一句带过。
124
+
125
+ ### 4. 输出报告
126
+
127
+ **正常清零结束:**
128
+
129
+ 先执行统一提交:先 `git add` 审查范围内的全部文件(审查范围首轮判定的 `git diff HEAD` 圈定的文件 —— 原始改动与循环期间修复的改动一并暂存;未跟踪的新建文件,扫描 `??` 清单得到的路径同样 `git add`,直到审查目标内不再有未暂存的改动),再对审查目标执行一次统一 commit(不做审查范围外的 `git add`),提交信息形如 `fix: review-code (经 N 轮修复)`。审查对象本身就是"当前未提交的变更",原始改动与循环产生的修复是同一个待提交单元,不做隔离,一并提交。若循环全程没有任何 Critical 被认可修复(从未发生实际改动),不创建空 commit。若这次统一提交本身执行失败(Git hook 拒绝、身份未配置、锁文件冲突等),在报告中如实说明该失败,视为"清零但提交失败"的独立结果——不重新进入循环(已经清零),但要指出还需要人工手动完成这次提交。若传入 `--no-commit`,跳过这次统一提交,修复结果留给调用方或用户自行处理。
130
+
131
+ ```
132
+ 📋 代码审查报告
133
+
134
+ ## Critical(必须修复)
135
+ (本次已自动修复 N 个 Critical,或为空——若曾发现并修复过,必须写明"本次已自动修复 N 个 Critical",不得用"未发现问题"掩盖。每条用非技术人员能看懂的人话概括问题和已做的改动,不要只贴审查 subagent 原文技术措辞)
136
+
137
+ ## Warning(建议修复,最后一轮结果)
138
+ 1. [file:line] — <问题描述,人话>
139
+ 建议: <具体修复建议>
140
+
141
+ ## Info(供参考,最后一轮结果)
142
+ 1. [file:line] — <观察/建议,人话>
143
+
144
+ ## 逐轮执行日志
145
+ (见"逐轮执行日志"一节,按轮次顺序列出每轮审查 subagent 原文 + 当前会话判定,作为补充材料)
146
+
147
+ ---
148
+ 总轮次: [轮数]
149
+ 总计(最后一轮): [N] Critical, [M] Warning, [K] Info
150
+ 提交: [已提交 <commit信息> / 未提交(--no-commit)/ 提交失败:<原始错误>]
151
+ ```
152
+
153
+ **熔断/分歧未决/无法安全修复/验证失败/审查调用失败/达到轮数上限/审查对象类型持续系统性误判结束:**
154
+
155
+ 不执行任何提交,改动留在工作区。
156
+
157
+ ```
158
+ 📋 代码审查报告 — 循环终止:<触发条件>
159
+
160
+ ## 终止详情
161
+ <用人话说清楚发现了什么问题、卡在哪、涉及哪些文件>
162
+
163
+ ("分歧未决"额外展示,展示 2 轮)
164
+ ### 审查 subagent 各轮原始发现
165
+ 第 N 轮:<原文>
166
+ ### 当前会话各轮反驳理由
167
+ 第 N 轮:<理由>
168
+
169
+ ("审查对象类型持续系统性误判"额外展示,展示连续 3 轮)
170
+ ### 审查 subagent 各轮原始发现
171
+ 第 N 轮:<原文>
172
+ 第 N+1 轮:<原文>
173
+ 第 N+2 轮:<原文>
174
+ ### 当前会话各轮反驳理由
175
+ 第 N 轮:<理由>
176
+ 第 N+1 轮:<理由>
177
+ 第 N+2 轮:<理由>
178
+
179
+ ## 逐轮执行日志
180
+ (同上)
181
+
182
+ ## 需要人工介入
183
+ <人话说明,改动都留在工作区未提交,可用 git diff 查看>
184
+
185
+ ---
186
+ 总轮次: [轮数]
187
+ 本次未提交任何改动
188
+ ```
189
+
190
+ 如从未出现任何 Critical/Warning/Info,明确说明"未发现问题",不要保持沉默。
@@ -0,0 +1,196 @@
1
+ ---
2
+ name: lyx-review-plan
3
+ description: '读取 OpenSpec change 的 proposal/design/tasks,双审查 subagent(fork 当前会话上下文,模型按 reviewModel/reviewModelB 分别指定)分级审查方案合理性,审查-修复循环直到 Critical 清零或触发终止条件'
4
+ argument-hint: '[<change-name>] [--no-commit]'
5
+ ---
6
+
7
+ <!-- 双审查 subagent 执行约定(spawn 协议、任务构造、共识/分歧裁决)内联于本文件,无外部 shell 调用契约;
8
+ 模型指定经"模板指示 + 宿主能力"落实,见"步骤 3"与模板变量说明 -->
9
+
10
+ # Review Plan - 方案审查
11
+
12
+ > 调用方式:`@lyx-review-plan` mention 后跟随的自然语言即参数(如 `@lyx-review-plan` 带需求描述/选项);无参数时直接 `@lyx-review-plan`。
13
+
14
+ 审查当前 OpenSpec change 的方案是否合理,聚焦遗漏边界、范围不清晰、风险点——不是逐行代码风格。输出 Critical/Warning/Info 分级结果(与 `@lyx-review-code` 一致)。若存在 Critical,进入审查-修复循环:当前会话判断是否认可每条 Critical,认可则修改该 change 的 artifact 并自动重新审查,直到清零或触发终止条件。
15
+
16
+ 审查由 **2 个并行审查 subagent** 执行(subagent 多 Agent 模式):每个 subagent fork 当前会话上下文(关键决策、取舍、已知边界等软上下文不丢失),任务中点名"只审该 change 的产物范围";模型按 `codexHost.reviewModel`(agent A)/ `codexHost.reviewModelB`(agent B)分别指定,未配置或空白时继承当前会话模型。两 agent 各自独立审查 → 交换结论 → 达成共识;意见分歧时主会话拍板并显式提示用户,主会话不能确认 → 判定 Critical。Critical 判定/修复由当前会话执行。
17
+
18
+ 循环执行期间默认不提交;仅当循环以"正常清零"结束时,才对审查目标全部文件(该 change 的 artifact 与 delta spec,含编排方已暂存的产物与循环修复)统一提交一次(见步骤 5)。传入 `--no-commit` 时,连这次最终的统一提交也不做。
19
+
20
+ ## 步骤
21
+
22
+ ### 1. 解析目标 change
23
+
24
+ 按优先级:
25
+
26
+ 1. 若 `参数` 指定了 change 名称 → 使用该名称
27
+ 2. 否则枚举 `openspec/changes/` 下的目录,**排除 `archive/` 目录及其内容**
28
+ 3. 若恰好一个候选 → 直接使用
29
+ 4. 若多个候选且未指定 → 直接询问用户选哪个
30
+ 5. 若零个候选 → 询问用户要审查哪个 change,不要猜测
31
+
32
+ ```bash
33
+ ls -d openspec/changes/*/ 2>/dev/null | grep -v '/archive/'
34
+ ```
35
+
36
+ 审查对象是目标 change 的 `propose:` commit(编排方 `@lyx-propose` 在生成方案后立即提交,提交信息 `propose: <change-name>`)。审查基线 SHALL 用 `git log --grep="^propose: <change-name>"` 取 HEAD 侧最近一期匹配 commit,审查范围 = 该 commit 差异(`git show <commit>`)+ 当前 `git diff HEAD` + 未跟踪文件清单(`??`)——修复在审查-修复循环内未提交时不丢失。不存在 `propose:` commit(零 commit 仓库、或尚未生成方案提交)时,退化为 `git diff HEAD` + 未跟踪清单组合。审查期间新产生的修复改动(循环内每轮修复未提交)始终计入审查范围,不在中途产生新 commit(提交只发生在正常清零后的统一提交,见步骤 5)。
37
+
38
+ ### 2. 枚举工件路径(仅首轮执行一次;不读取内容)
39
+
40
+ 枚举该 change 目录下的 `proposal.md`、`design.md`、`tasks.md`(存在的部分即可,缺失的容错跳过,不报错)以及 `specs/**/*.md` 的全部 delta spec 文件路径(存在多份时全部枚举,不只取其中一份)。这一步只确定路径,不读取文件内容拼接成字符串——审查 subagent 具备自主读取文件的能力。
41
+
42
+ **基线 spec 引用检测**:检查每份 delta spec 文件是否有显式文字引用了基线 spec 中未被本次修改的既有 Requirement(例如"见……'某 Requirement 名'"这类指代,无论出现在 `## MODIFIED Requirements` 内还是外)。若有,额外把该基线能力对应的 `openspec/specs/<capability>/spec.md` 路径也纳入路径清单,并在 TASK 中说明该文件仅作审查上下文(用于核实引用是否准确),不属于修复对象。
43
+
44
+ ### 3. spawn 双审查 subagent(首轮)
45
+
46
+ 本关卡审查由 **2 个并行审查 subagent** 执行(subagent 多 Agent 模式,不再走独立子进程 shell 调用)。主会话按以下指示 spawn,由运行环境的宿主 spawn 能力落实:
47
+
48
+ 1. **spawn 两个审查 subagent,并行独立审查**(互不见对方结论):
49
+ - **审查 agent A**:模型 = `~/.ly/config.toml` 的 `[codexHost] reviewModel`;未配置或空白 → 继承当前会话模型。
50
+ - **审查 agent B**:模型 = `[codexHost] reviewModelB`;未配置或空白 → 继承当前会话模型。
51
+ 2. **fork 当前会话上下文**:两个 agent 均 fork 当前会话上下文启动——主会话讨论中的关键决策、取舍、已知边界等"软上下文"随 fork 到达审查模型,避免关键信息丢失。模型指定只写在模板指示里(取哪个配置字段、未配置用当前会话模型),由宿主 spawn 能力执行,SHALL NOT 依赖任何 shell 层模型参数(无 `-m`/`--model` 类指令)。
52
+ 3. **TASK 范围点名(只审 change 范围)**:每个审查 subagent 的任务均点名"只审该 change 的下列产物",SHALL NOT 超出点名范围作业。TASK 先指示读取 ROLE_FILE(两个 agent 均用 `~/.ly/prompts/codex/plan-reviewer.md`,角色词内容不重写),再列出路径清单(步骤 2 枚举的 artifact + delta spec;若步骤 2 检测到基线 spec 引用,同时说明基线路径仅作审查上下文、不属于修复对象)。**首轮只传路径清单,不拼贴文件全文**——审查 subagent 具备自主读取文件的能力,需要实际内容时自行读取。
53
+
54
+ TASK 核心约束(写入每个审查 subagent 的任务):
55
+ - 只审查该 change 目录下 artifact 之间的内在一致性和完整性(proposal vs design vs tasks vs spec 是否互相矛盾、是否有遗漏)
56
+ - 可做轻量代码库确认(确认 plan 列出的文件路径是否存在、grep 硬编码数字/常量是否遗漏关联文件),但不深入读源码实现、不做逐行代码审查——后者是 apply 后 code-review 的职责
57
+ - 不把'代码库尚未实现该方案条目'当作 Critical(方案审查阶段代码库本来就没有实现,这是正常状态)
58
+
59
+ OUTPUT 约束(写入每个审查 subagent 的任务):审查发现按严重度分级 Critical/Warning/Info,每条含位置/条目(含可解析的文件相对路径)、问题描述、建议。
60
+
61
+ **两 agent 结论汇合(独立审 → 交换 → 共识)**:
62
+
63
+ 1. 两个 agent 独立审查完毕后,**由主会话将 A/B 结论互转给双方**(两 subagent 由宿主并行 spawn、不直连),各自针对对方结论给出最终意见后,主会话再归并共识。
64
+ 2. **共识归并**:两 agent 结论合并去重后作为本轮审查结论;部分重叠或冲突的条目 SHALL 一并列出交主会话判定,SHALL NOT 静默丢弃任一 agent 的独立发现。
65
+ 3. **意见分歧**(agent A 提出 Critical 而 agent B 未提出,或两者结论冲突)→ **主会话拍板**,且 SHALL **显式提示用户"这是审查分歧"**:主会话能确认 → 按确认结论处理;不能确认 → 判定该条为 Critical(red)进入修复循环。
66
+ 4. **分歧时序**:双 agent 首次分歧且主会话不能确认 → 判定 Critical 进入修复循环;下一轮复审双 agent 仍分歧且主会话仍不能确认 → 触发"分歧未决"终止条件(终止条件 5)。
67
+
68
+ **审查调用失败(区分两阶段)**:
69
+
70
+ - **运行期失败**(spawn 后超时、返回内容格式不符、审查 agent 未返回有效结论、双审查任一 agent 调用失败且无法按回退口径继续、回退不可行或回退后仍失败)→ 视为**独立终止条件**,如实报告原因并停止循环,**不得**把失败等同于"本轮无 Critical"或视为清零通过。
71
+ - **环境级不可用**(宿主无 subagent 能力、初始 spawn 不可用)→ 按回退口径处理:回退为当前会话直接执行审查,并如实报告"已回退,原因:subagent 不可用",SHALL NOT 视为流程失败中断整体编排。
72
+ - **单一 agent 失败且另一 agent 结论完整** → 以完整一方结论继续审查,如实报告降级(含失败 agent 与原因),SHALL NOT 归入"分歧未决"(环境级失败非意见分歧);是否补跑/重试由主会话决定。
73
+
74
+ 本轮结束后,无论是否有 Critical,都先生成"本轮执行日志"(见"逐轮执行日志"一节),再判定:
75
+
76
+ 若本轮 Critical 数为 0 → 跳到步骤 5 输出报告,结束(不进入循环)。
77
+ 若本轮 Critical > 0 → 进入步骤 4 循环体。
78
+
79
+ ### 4. 审查-修复循环
80
+
81
+ 对本轮全部 Critical,逐条执行:
82
+
83
+ **4.1 当前会话先判断是否认可该 Critical**(同 `@lyx-review-code`)
84
+
85
+ - **认可**:判断问题确实存在,进入 4.2 修复。
86
+ - **不认可**:判断为误报、对上下文理解有误、或建议本身有问题,则不修改任何文件,但必须在本轮报告里写明反驳理由。
87
+
88
+ **4.2 修复(仅针对认可的 Critical)**
89
+
90
+ 修改该 change 的 `proposal.md`/`design.md`/`tasks.md`/`specs/**/*.md`(该 change 目录下的 delta spec 文件),修复范围为"Critical 直接指向的条目" + "修复它所必需的直接依赖条目"(例如"proposal 与 tasks 范围不一致"这类问题往往需要同步改动多处才能真正修好;"spec 未覆盖 proposal 的 What Changes"这类问题的修复方式就是编辑对应 delta spec 文件);不得借机改动无关内容。若改动涉及必需依赖条目,本轮报告必须逐项说明关联性。
91
+
92
+ **4.3 本轮验证**
93
+
94
+ 修复完成后运行一次 `openspec validate --changes <change-name>`。验证失败 → 立即停止循环,不再进行下一轮修复,报告本轮改动的文件清单及 `openspec validate` 的失败信息,说明需要人工介入。
95
+
96
+ **4.4 记录本轮改动文件清单(不提交)**
97
+
98
+ 验证通过后,把本轮实际改动的 artifact/delta spec 文件相对路径清单写入本轮报告——供 4.5 步构造下一轮增量 TASK 直接复用,不得靠"运行时的 git 状态"反推(后续轮次还会继续修改文件,仅凭某个时间点的 git 状态无法可靠还原"本轮具体改了什么")。本轮不执行任何 git commit——提交只发生在循环以正常清零结束之后(见步骤 5)。
99
+
100
+ **4.5 自动触发下一轮审查(增量传递;沿用同一批审查 subagent)**
101
+
102
+ 从第 2 轮起,TASK SHALL NOT 重新传整份 proposal/design/tasks/specs 内容;改为仅包含:
103
+
104
+ 1. 上一轮审查 subagent(A/B)报告的全部 Critical 原文(逐字,不经改写,包含被判定"不认可"的条目)。
105
+ 2. 路径清单,必须覆盖"本轮实际改动的 artifact/delta spec 文件"(4.4 记录的清单)∪"上一轮全部 Critical 各自指向的 artifact/delta spec 文件"(即使未被修改)。若上一轮某条 Critical 指向的文件已被删除或重命名,路径清单改用新路径(若有)并说明状态变化。
106
+
107
+ 路径清单之外的文件不重新整段传入。若某条上一轮 Critical 的位置字段缺失可解析路径,命令保守处理:将该 change 目录下全部 artifact/delta spec 路径纳入下一轮路径清单,并在报告中说明该情况(不得静默丢弃该 Critical)。
108
+
109
+ **第 2 轮起沿用同一批审查 subagent 会话**:fork 启动的 subagent 会话具备轮间记忆,第 2 轮继续使用同一批审查 subagent(A/B),无需重新 spawn 或整段重传基线——增量传递规则不变,会话记忆提供连续性,不代表 TASK 可省略逐字 Critical 原文。回到步骤 3 的执行方式(只是 TASK 内容换成上述增量内容),重新派发审查,不要求用户手动重新触发命令。生成本轮执行日志后再判定 Critical 是否清零。
110
+
111
+ ### 循环终止条件(任一命中即停止,转步骤 5)
112
+
113
+ 复用 `@lyx-review-code` 的同一套规则,全局轮数上限同样默认 5 轮(清零优先于轮数上限:本轮先判 Critical 是否清零,仅非清零时才检查是否达到 5 轮):
114
+
115
+ 1. **正常清零**:某一轮审查 Critical 数为 0
116
+ 2. **熔断**:同一个 Critical(以"文件路径 + 问题类别 + 定位锚点(artifact 内的具体条目/章节)"三者共同判定为同一问题)在相邻两轮审查中都被判定为存在,且上一轮当前会话对它是"认可"状态
117
+ 3. **无法安全自动修复**:需要产品/业务决策、依赖当前会话不具备的信息,或当前会话判断信息不足——不得进行猜测性修改
118
+ 4. **修复后验证失败**:见 4.3(`openspec validate` 未通过)
119
+ 5. **分歧未决**:当前会话上一轮判断"不认可"(未修改),下一轮审查 subagent 仍判定同一问题存在;或双 agent 复审仍分歧且主会话仍不能确认(见步骤 3"分歧时序")
120
+ 6. **审查对象类型持续系统性误判**:连续 3 轮(含本轮)审查中,每一轮的全部 Critical 都被当前会话判定为同一大类系统性误判——即审查 subagent 反复以"该轮 Critical 所依据的判断类别不属于方案审查范畴"为由被判定不认可(例如连续 3 轮的 Critical 均以"代码库尚未实现该方案条目"作为理由),不要求这 3 轮之间 Critical 的文件/类别/锚点相互匹配,只要求"判定为不认可的理由类别"在这 3 轮中一致
121
+ 7. **达到全局轮数上限**(5 轮,独立于上面 1-6 的判定)
122
+
123
+ 触发条件 2-6(或达到全局轮数上限)时,立即停止循环,不执行任何提交(改动留在工作区),报告中必须明确指出触发的具体条件、涉及的问题(文件/类别/章节/判定依据),并说明需要人工介入。"分歧未决"额外要求并列展示审查 subagent 每一轮的原始发现与当前会话每一轮的反驳理由;"审查对象类型持续系统性误判"同样要求并列展示,但展示连续 3 轮(而不是 2 轮)的原始发现与反驳理由。循环期间的 Warning/Info 不参与终止判定,只在最终报告列出**最后一轮**结果。
124
+
125
+ ### 逐轮执行日志
126
+
127
+ 每一轮审查 subagent 派发完成后(包括首轮 Critical 为 0、直接结束的情况),都要在报告中包含一个独立区块,逐字展示该轮审查 subagent 返回的原始 Critical/Warning/Info 内容(不经概括、改写或合并),与当前会话对该轮每条 Critical 的认可/不认可判定并排列出(若该轮无 Critical,只展示原文)。这个区块在该轮审查返回之后即可呈现,不是流式展示。这是给需要核实细节的人看的补充材料;最终报告的主体是人话摘要(见步骤 5),二者并存,不互相替代。
128
+
129
+ **硬性约束(逐字执行)**:该区块中的 Warning/Info 与 Critical 同样必须逐字完整贴出,**禁止用省略号("…"、"(同前)"等)压缩**;**清零轮(无 Critical)的判定仍需写明依据**——对照前一轮各 Critical 的修复/确认情况说明"认可清零"的理由,不得仅以"无 Critical,正常清零"一句带过。
130
+
131
+ ### 5. 输出报告
132
+
133
+ **正常清零结束:**
134
+
135
+ 先执行统一提交:先 `git add` 该 change 目录下的 `proposal.md`/`design.md`/`tasks.md` 及全部 delta spec 文件(审查目标全部文件——编排方(`@lyx-propose`)已暂存的产物与循环期间修复的改动一并暂存;若产物此前已在暂存区则保持,修复改动由本次 `git add` 覆盖进 index),再执行一次统一 commit(仅暂存并提交这些文件,不做范围外的 `git add`),提交信息形如 `fix: review-plan feedback (经 N 轮修复) - <change-name>`。**不存在"循环开始前已脏文件的隔离跳过"**——该 change 目录下的 artifact 与 delta spec 是合法审查对象,产物与修复是同一个待提交单元,全部一并提交。若循环全程没有任何 Critical 被认可修复(从未发生实际改动),不创建空 commit。若统一提交本身执行失败,在报告中如实说明该失败,视为"清零但提交失败"的独立结果——不重新进入循环(已经清零),但要指出还需要人工手动完成这次提交。若传入 `--no-commit`,跳过这次统一提交,修复结果留给调用方或用户自行处理。
136
+
137
+ ```
138
+ 📋 方案审查:<change-name>
139
+
140
+ ## Critical(必须修复)
141
+ (本次已自动修复 N 个 Critical,或为空——若曾发现并修复过,必须写明"本次已自动修复 N 个 Critical",不得用"未发现问题"掩盖。每条用非技术人员能看懂的人话概括问题和已做的改动)
142
+
143
+ ## Warning(建议修复,最后一轮结果)
144
+ 1. [proposal.md / design.md / tasks.md / specs/**/*.md] — <问题描述,人话>
145
+ 建议: <具体建议>
146
+
147
+ ## Info(供参考,最后一轮结果)
148
+ 1. [proposal.md / design.md / tasks.md / specs/**/*.md] — <观察/建议,人话>
149
+
150
+ ## 逐轮执行日志
151
+ (见"逐轮执行日志"一节,按轮次顺序列出每轮审查 subagent 原文 + 当前会话判定,作为补充材料)
152
+
153
+ ---
154
+ 总轮次: [轮数]
155
+ 总计(最后一轮): [N] Critical, [M] Warning, [K] Info
156
+ 提交: [已提交 <commit信息> / 未提交(--no-commit) / 无可提交内容 / 提交失败:<原始错误>]
157
+ ```
158
+
159
+ **熔断/分歧未决/无法安全修复/验证失败/审查调用失败/达到轮数上限/审查对象类型持续系统性误判结束:**
160
+
161
+ 不执行任何提交,改动留在工作区。
162
+
163
+ ```
164
+ 📋 方案审查:<change-name> — 循环终止:<触发条件>
165
+
166
+ ## 终止详情
167
+ <用人话说清楚发现了什么问题、卡在哪、涉及哪些文件/章节>
168
+
169
+ ("分歧未决"额外展示,展示 2 轮)
170
+ ### 审查 subagent 各轮原始发现
171
+ 第 N 轮:<原文>
172
+ ### 当前会话各轮反驳理由
173
+ 第 N 轮:<理由>
174
+
175
+ ("审查对象类型持续系统性误判"额外展示,展示连续 3 轮)
176
+ ### 审查 subagent 各轮原始发现
177
+ 第 N 轮:<原文>
178
+ 第 N+1 轮:<原文>
179
+ 第 N+2 轮:<原文>
180
+ ### 当前会话各轮反驳理由
181
+ 第 N 轮:<理由>
182
+ 第 N+1 轮:<理由>
183
+ 第 N+2 轮:<理由>
184
+
185
+ ## 逐轮执行日志
186
+ (同上)
187
+
188
+ ## 需要人工介入
189
+ <人话说明,改动都留在工作区未提交,可用 git diff 查看>
190
+
191
+ ---
192
+ 总轮次: [轮数]
193
+ 本次未提交任何改动
194
+ ```
195
+
196
+ 如从未出现任何 Critical/Warning/Info,明确说明"方案审查未发现问题",不要保持沉默。
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: lyx-rollback
3
+ description: '交互式 Git 回滚:安全回滚分支到历史版本,支持 reset/revert 模式'
4
+ argument-hint: '[--branch <branch>] [--target <rev>] [--mode reset|revert]'
5
+ ---
6
+
7
+ # Rollback - 交互式 Git 回滚
8
+
9
+ > 调用方式:`@lyx-rollback` mention 后跟随的自然语言即参数(如 `@lyx-rollback` 带需求描述/选项);无参数时直接 `@lyx-rollback`。
10
+
11
+ 安全地将分支回滚到指定历史版本,默认 dry-run 模式。
12
+
13
+ ## 使用方法
14
+
15
+ ```bash
16
+ @lyx-rollback [options]
17
+ ```
18
+
19
+ ## 选项
20
+
21
+ | 选项 | 说明 |
22
+ |------|------|
23
+ | `--branch <branch>` | 要回滚的分支 |
24
+ | `--target <rev>` | 目标版本(commit/tag/reflog) |
25
+ | `--mode reset\|revert` | 回滚模式 |
26
+ | `--depth <n>` | 列出最近 n 个版本(默认 20) |
27
+ | `--dry-run` | 只预览,不执行(**默认**) |
28
+ | `--yes` | 跳过确认直接执行 |
29
+
30
+ ---
31
+
32
+ ## 执行工作流
33
+
34
+ ### 🔍 阶段 1:同步远端
35
+
36
+ `[模式:准备]`
37
+
38
+ ```bash
39
+ git fetch --all --prune
40
+ ```
41
+
42
+ ### 📋 阶段 2:选择分支
43
+
44
+ `[模式:选择]`
45
+
46
+ 1. 列出本地 + 远端分支
47
+ 2. 过滤受保护分支
48
+ 3. 用户选择或使用 `--branch` 参数
49
+
50
+ ### 📜 阶段 3:选择版本
51
+
52
+ `[模式:选择]`
53
+
54
+ 1. 显示最近 N 个版本(`git log --oneline`)
55
+ 2. 显示相关 tags(`git tag --merged`)
56
+ 3. 用户选择或使用 `--target` 参数
57
+
58
+ ### ⚙️ 阶段 4:选择模式
59
+
60
+ `[模式:决策]`
61
+
62
+ | 模式 | 说明 | 推送方式 |
63
+ |------|------|----------|
64
+ | `reset` | 硬回滚,改变历史 | `--force-with-lease` |
65
+ | `revert` | 生成反向提交,保留历史 | 普通 push |
66
+
67
+ ### ⛔ 阶段 5:最终确认
68
+
69
+ `[模式:确认]`
70
+
71
+ 显示即将执行的命令,等待用户确认(除非 `--yes`)。
72
+
73
+ ### ✅ 阶段 6:执行回滚
74
+
75
+ `[模式:执行]`
76
+
77
+ **reset 模式**:
78
+ ```bash
79
+ git switch <branch>
80
+ git reset --hard <target>
81
+ ```
82
+
83
+ **revert 模式**:
84
+ ```bash
85
+ git switch <branch>
86
+ git revert --no-edit <target>..HEAD
87
+ ```
88
+
89
+ ---
90
+
91
+ ## 安全护栏
92
+
93
+ 1. **备份**:执行前自动记录当前 HEAD 到 reflog
94
+ 2. **保护分支**:`main`/`master`/`production` 需额外确认
95
+ 3. **dry-run 默认**:防止误操作
96
+ 4. **禁止 --force**:如需强推,手动执行
97
+
98
+ ---
99
+
100
+ ## 示例
101
+
102
+ ```bash
103
+ # 全交互模式(dry-run)
104
+ @lyx-rollback
105
+
106
+ # 指定分支
107
+ @lyx-rollback --branch dev
108
+
109
+ # 完整指定,一键执行
110
+ @lyx-rollback --branch main --target v1.2.0 --mode reset --yes
111
+
112
+ # 生成反向提交
113
+ @lyx-rollback --branch release/v2.1 --target v2.0.5 --mode revert
114
+ ```
115
+
116
+ ## 注意事项
117
+
118
+ - **reset vs revert**:reset 改变历史,需强推;revert 更安全
119
+ - **LFS/子模块**:回滚前确保状态一致
120
+ - **CI 触发**:回滚后可能自动触发流水线