create-specfuse 0.12.0 → 0.14.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 把 AI 编码从即兴发挥,改造成工程流水线。
4
4
 
5
- SpecFuse 不发明新工具。它把 OpenSpec(流程引擎)和 Superpowers(行为约束)编排成一条 **Think → Do → FuseReview → FuseQA → Verify** 五拍流水线,一条命令注入任何项目——它不产生新能力,它约束产出可靠性。
5
+ SpecFuse 不发明新工具。它把 OpenSpec(流程引擎)和 Superpowers(行为约束)编排成一条 **Think → Do → FuseReview → Verify** 四拍流水线,一条命令注入任何项目——它不产生新能力,它约束产出可靠性。端到端 QA 是独立的按需技能,不属于流水线。
6
6
 
7
7
  ## 快速开始
8
8
 
@@ -25,7 +25,7 @@ npm install -g @fission-ai/openspec # 流程引擎;装好后自动注册 /o
25
25
 
26
26
  ```
27
27
  my-app/
28
- ├── CLAUDE.md # 流水线调度协议(五拍规则全文)
28
+ ├── CLAUDE.md # 流水线调度协议(四拍规则全文)
29
29
  ├── .gitignore # 共享忽略规则
30
30
  ├── .claude/
31
31
  │ ├── settings.local.json # 权限白名单
@@ -36,7 +36,7 @@ my-app/
36
36
  │ ├── design-md/ # 设计令牌生成技能(含 16 个原型模板)
37
37
  │ ├── fusedoc/ # 文档标准技能(含 3 份参考文件)
38
38
  │ ├── fusereview/ # 实施后代码评审技能
39
- │ ├── fuseqa/ # 实施后端到端验收技能(含 4 份模板)
39
+ │ ├── fuseqa/ # 按需端到端验收技能(含 4 份模板;不属于流水线)
40
40
  │ └── openspec-*/ # OpenSpec 提供:随其 init 生成
41
41
  └── openspec/
42
42
  ├── config.yaml # spec 规则(流程约束)
@@ -46,7 +46,7 @@ my-app/
46
46
 
47
47
  项目目录会自动加入 Claude Code 信任列表。`commands/opsx/` 与 `openspec-*` 由 OpenSpec 自己的 `init` 产生,随其版本更新;`commands/specfuse.md` 与四个技能由 SpecFuse 写入,已存在则不覆盖;`CLAUDE.md` 按 FUSION 标记合并(见下文)。
48
48
 
49
- ## 五个阶段
49
+ ## 四个阶段
50
50
 
51
51
  在项目中启动 Claude Code,按这套节奏开发:
52
52
 
@@ -54,10 +54,11 @@ my-app/
54
54
  Think /opsx:new 或 /opsx:propose —— 方案设计与制品生成
55
55
  Do /opsx:apply —— TDD 实施
56
56
  FuseReview apply 收尾检查点 —— 冷读评审
57
- FuseQA apply 收尾检查点 —— 真实入口端到端验收
58
57
  Verify /opsx:verify → /opsx:archive —— 全量验收与归档
59
58
  ```
60
59
 
60
+ FuseQA 不在其中:它是按需技能,只有显式调用 `/fuseqa` 才执行。
61
+
61
62
  ### 无人值守:`/specfuse`
62
63
 
63
64
  需求已经明确、不想逐拍确认时,用一条命令跑完整条流水线:
@@ -66,7 +67,7 @@ Verify /opsx:verify → /opsx:archive —— 全量验收与归档
66
67
  /specfuse <需求描述>
67
68
  ```
68
69
 
69
- brainstorm、`/design-md` 问卷、模型切换与两个收尾检查点都由模型按推荐答案自答,并记录在最终报告中:模型切换默认不切换,FuseReview 自动进入,FuseQA 记录为跳过,verify 全部通过后 archive,全程不 commit、不 push。verify 仍失败时不 archive,保留变更目录并把失败写进报告。默认的 `/opsx:*` 交互行为不受影响。
70
+ brainstorm、`/design-md` 问卷、模型切换与收尾检查点都由模型按推荐答案自答,并记录在最终报告中:模型切换默认不切换,FuseReview 自动进入,FuseQA 不进入,verify 全部通过后 archive,全程不 commit、不 push。verify 仍失败时不 archive,保留变更目录并把失败写进报告。默认的 `/opsx:*` 交互行为不受影响。
70
71
 
71
72
  ### Think
72
73
 
@@ -79,22 +80,20 @@ brainstorm、`/design-md` 问卷、模型切换与两个收尾检查点都由模
79
80
  - 逐任务红绿循环,严格遵守 TDD。
80
81
  - **铁律:`NO COMPLETION CLAIMS WITHOUT FRESH VERIFICATION EVIDENCE`** —— 每个任务完成前必须粘贴终端原始输出作为证据。
81
82
 
82
- ### FuseReview(第三拍)
83
+ ### FuseReview
83
84
 
84
85
  - apply 完成后必须询问是否评审(禁止静默跳过);呈报任务数、涉及模块等事实,由你决定是否执行。
85
86
  - 评审者不参与实现,以冷读方式审查 `基线..HEAD` 的累积 diff,按十一项检查逐条走(测试强度、缺失检测、范围契合、真实入口、接口两侧、生命周期与并发、强制路径、配置选择、能力与消费者契合、借用状态、边界值)。
86
87
  - Blocking 发现走 TDD 修复;修复后只复审修复 diff,不进行第二轮全量评审。
87
88
  - 跳过评审必须记录在收尾报告中留痕。
88
89
 
89
- ### FuseQA(第四拍)
90
+ ### FuseQA(按需,不属于流水线)
90
91
 
91
- - apply 完成后必须询问是否验收。**与 FuseReview 是两问**:前一问答什么都不影响这一问必问,禁止合并成一问。
92
- - 单测覆盖源码,冷读评审不运行系统,全量测试跑的还是单测——**没人以用户身份运行过制品**。这一拍补的就是这个缺口。
93
- - 用例从 specs 的 Scenario 派生,重建为真实入口(子进程 / HTTP 请求 / 浏览器),被测物是构建产物而非 `src/`;禁止 `import ../src/`(机械可查)。
94
- - 用例落 `tests/e2e/<capability>/`,与 `openspec/specs/<capability>/` 同名对齐,因此**回归零成本成立**——它已是全量测试的一部分。
95
- - 发现按**归因**分级而非按红:实现缺陷 Blocking,spec 漏洞默认 Suggestion,假红记为用例债并须写明代码为何正确。
96
- - 用例是项目资产,新增/修正/剔除都要留理由——剔除尤其,否则「删掉红用例」和「掩盖缺陷」在台账上无从区分。
97
- - **收尾报告必须同时记录 FuseReview 与 FuseQA 两条决定**,缺一条即 apply 未完成。
92
+ - 只有显式调用 `/fuseqa` 才执行;没有检查点,不进入 apply 收尾,也不影响 verify。
93
+ - 适合能在本地完整部署和验证的小项目:CLI、小型服务、库、本地 Web 应用。
94
+ - 分布式系统在本地复现不了真实拓扑、网络分区与共享状态竞争,应在 CI/CD 中运行等价检查,而不是在开发阶段做本地 QA。
95
+ - 方法仍完整保留:从 specs 的 Scenario 派生用例、真实入口、构建产物而非 `src/`、归因分级、用例台账。
96
+ - 用例落 `tests/e2e/<capability>/`,随全量测试在 verify 阶段回归。
98
97
 
99
98
  ### Verify
100
99
 
@@ -103,7 +102,7 @@ brainstorm、`/design-md` 问卷、模型切换与两个收尾检查点都由模
103
102
 
104
103
  ## 文档标准:FuseDoc
105
104
 
106
- `/fusedoc` 是贯穿全链路的文档标准,**不属于五拍中的任何一拍**:无检查点、无强制提问、不进 apply 收尾序列,由产出散文的各阶段按需调用。
105
+ `/fusedoc` 是贯穿全链路的文档标准,**不属于四拍中的任何一拍**:无检查点、无强制提问、不进 apply 收尾序列,由产出散文的各阶段按需调用。
107
106
 
108
107
  它管三件事——一段话必须说什么、读起来是从仓库出发还是从写作会话出发、一个事实该放在哪一层。派上用场的典型场合:写 README 和注释、审计一份文档、判断某个事实该落在决策记录还是使用指南。
109
108
 
@@ -128,11 +127,13 @@ brainstorm、`/design-md` 问卷、模型切换与两个收尾检查点都由模
128
127
  | `.claude/skills/*` | 已存在 → 不覆盖 |
129
128
  | `.claude/commands/specfuse.md` | 已存在 → 不覆盖 |
130
129
 
130
+ 技能与命令已存在时不会被覆盖。已有项目升级到四拍时,先删除 `.claude/skills/fuseqa/SKILL.md`、`.claude/skills/fusereview/SKILL.md` 和 `.claude/commands/specfuse.md`,再运行 scaffolder:`CLAUDE.md` 的 FUSION 块会被替换,这三个文件会按新模板重写。其它用户自定义技能不受影响。
131
+
131
132
  删除 `CLAUDE.md` 里的 FUSION 块,项目即回到无调度状态——整套编排零侵入、可逆。
132
133
 
133
134
  ## 与技术栈无关
134
135
 
135
- SpecFuse 是流程,不是栈选择器。五拍对 Rust、React 或一个裸脚本完全一致,所以初始化时不会问你用什么栈,也不生成栈特化内容:
136
+ SpecFuse 是流程,不是栈选择器。四拍对 Rust、React 或一个裸脚本完全一致,所以初始化时不会问你用什么栈,也不生成栈特化内容:
136
137
 
137
138
  - `CLAUDE.md` 不含 Tech Stack 段落,验证指令写作「项目的测试命令」「项目的 linter」——由项目自己的工具链定义。
138
139
  - `.gitignore` 只给 IDE / OS / env / 日志这些共享模式,构建产物模式留给首次提交时判断。
package/dist/index.js CHANGED
@@ -10,7 +10,8 @@ const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'u
10
10
  export const program = new Command();
11
11
  program
12
12
  .name('create-specfuse')
13
- .description('SpecFuse — AI engineering pipeline scaffolder.\n\nInjects OpenSpec workflow + Superpowers discipline into any project.\nThink → Do → FuseReview → FuseQA → Verify, one command at a time.')
13
+ .description('SpecFuse — AI engineering pipeline scaffolder.\n\nInjects OpenSpec workflow + Superpowers discipline into any project.\nThink → Do → FuseReview → Verify, one command at a time.')
14
+ .addHelpText('after', '\nRepository: https://github.com/wayhomeke/specfuse\nDocumentation: https://github.com/wayhomeke/specfuse/blob/main/README.md\n')
14
15
  .version(pkg.version)
15
16
  .argument('[project-name]', 'Target directory (omit or use "." to init in current directory)')
16
17
  .option('-y, --yes', 'Non-interactive mode (use defaults, CI-friendly)')
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAExF,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAErC,OAAO;KACJ,IAAI,CAAC,iBAAiB,CAAC;KACvB,WAAW,CAAC,2LAA2L,CAAC;KACxM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;KACpB,QAAQ,CAAC,gBAAgB,EAAE,iEAAiE,CAAC;KAC7F,MAAM,CAAC,WAAW,EAAE,kDAAkD,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,WAA+B,EAAE,IAAuB,EAAE,EAAE;IACzE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,YAAa,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,4EAA4E;AAC5E,kFAAkF;AAClF,iFAAiF;AACjF,8EAA8E;AAC9E,SAAS,YAAY;IACnB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,YAAY,EAAE,EAAE,CAAC;IACnB,OAAO,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAExF,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAErC,OAAO;KACJ,IAAI,CAAC,iBAAiB,CAAC;KACvB,WAAW,CAAC,kLAAkL,CAAC;KAC/L,WAAW,CACV,OAAO,EACP,iIAAiI,CAClI;KACA,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;KACpB,QAAQ,CAAC,gBAAgB,EAAE,iEAAiE,CAAC;KAC7F,MAAM,CAAC,WAAW,EAAE,kDAAkD,CAAC;KACvE,MAAM,CAAC,KAAK,EAAE,WAA+B,EAAE,IAAuB,EAAE,EAAE;IACzE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,YAAa,GAAa,CAAC,OAAO,IAAI,CAAC,CAAC;QACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,4EAA4E;AAC5E,kFAAkF;AAClF,iFAAiF;AACjF,8EAA8E;AAC9E,SAAS,YAAY;IACnB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,YAAY,EAAE,EAAE,CAAC;IACnB,OAAO,CAAC,KAAK,EAAE,CAAC;AAClB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import type { TemplateContext } from "../types.js";
2
2
  export declare function renderApplyPhase(): string;
3
3
  export declare function renderApplyFuseReview(): string;
4
- export declare function renderFuseQA(): string;
4
+ export declare function renderFuseQAOnDemand(): string;
5
5
  export declare function renderFuseDocStandard(): string;
6
6
  export declare function renderAutoMode(): string;
7
7
  export declare function renderVerifyPhase(): string;
@@ -1 +1 @@
1
- {"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAyFnD,wBAAgB,gBAAgB,IAAI,MAAM,CA0DzC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CA2B9C;AAED,wBAAgB,YAAY,IAAI,MAAM,CA+BrC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAY9C;AAED,wBAAgB,cAAc,IAAI,MAAM,CAwBvC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAU1C;AAiBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAsC7D"}
1
+ {"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAyFnD,wBAAgB,gBAAgB,IAAI,MAAM,CA0DzC;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CA2B9C;AAED,wBAAgB,oBAAoB,IAAI,MAAM,CAkB7C;AAED,wBAAgB,qBAAqB,IAAI,MAAM,CAY9C;AAED,wBAAgB,cAAc,IAAI,MAAM,CAwBvC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAU1C;AAiBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAsC7D"}
@@ -142,7 +142,7 @@ When \`/opsx:apply\` is invoked:
142
142
  export function renderApplyFuseReview() {
143
143
  return `### Phase 2.5: FuseReview Checkpoint (Post-Apply)
144
144
 
145
- FuseReview is the post-apply review: Think reviews direction, Do produces code, **FuseReview reviews the implementation**, FuseQA verifies the artifact through real entry points, Verify validates the whole. The full review method lives in \`.claude/skills/fusereview/SKILL.md\`.
145
+ FuseReview is the post-apply review: Think reviews direction, Do produces code, **FuseReview reviews the implementation**, Verify validates the whole. The full review method lives in \`.claude/skills/fusereview/SKILL.md\`.
146
146
 
147
147
  **Baseline:** At apply start, record the current HEAD commit in the change's state as the review baseline. The review object is \`baseline..HEAD\`. If no baseline was recorded, fall back to the merge-base of the current branch and the trunk, and annotate the fallback in the report.
148
148
 
@@ -163,41 +163,28 @@ FuseReview is the post-apply review: Think reviews direction, Do produces code,
163
163
 
164
164
  **Merge gate (subagent mode):** in subagent mode the second stage of the two-stage review executes the FuseReview skill on each subagent's diff before merge, automatically, without a user checkpoint.
165
165
 
166
- **Declining does not end the apply exit sequence:** answering "no" here dismisses FuseReview only. The FuseQA checkpoint that follows remains mandatory.
166
+ **Declining does not end the apply exit sequence:** recording the skip is the required trace; Verify follows. The apply exit sequence has one checkpoint, so there is no second decision to answer.
167
167
 
168
168
  **Manual invocation:** the user may invoke the FuseReview skill explicitly at any time, independent of the checkpoint.`;
169
169
  }
170
- export function renderFuseQA() {
171
- return `### Phase 2.6: FuseQA Checkpoint (Post-Apply E2E)
170
+ export function renderFuseQAOnDemand() {
171
+ return `### On-Demand: FuseQA (E2E Verification)
172
172
 
173
- FuseQA is the post-apply verification: Think reviews direction, Do produces code, FuseReview reviews the implementation, **FuseQA verifies the artifact through real entry points**, Verify validates the whole. The full method lives in \`.claude/skills/fuseqa/SKILL.md\`.
173
+ FuseQA verifies the built artifact through real user entry points. It is **not part of the pipeline — not a pipeline beat — and has no checkpoint**: no phase, checkpoint, or auto-mode decision invokes it, and neither apply completion nor entry to Verify depends on a FuseQA decision. Run it explicitly with \`/fuseqa\` when local end-to-end verification is meaningful.
174
174
 
175
- **Why this beat exists:** unit tests cover source, FuseReview reads a diff without running anything, and the Verify phase runs the same unit suite. A defect can therefore pass every gate and still reach users — an entry-guard bug that works when the built file is called by its real path but does nothing when called through a symlinked bin shim passes typecheck, unit tests and cold-read review alike. Nobody runs the artifact as a user until this beat.
175
+ **Applicability.** Use it when the artifact can be deployed and exercised locally — a CLI, a small service, a library, a local web app. A distributed system cannot be meaningfully exercised on one machine; run equivalent checks in CI/CD rather than in the development phase.
176
176
 
177
- **Checkpoint (mandatory question):** After the last task in \`tasks.md\` passes verification, the AI MUST ask the user whether to enter FuseQA. Silent advancement to \`/opsx:verify\` or \`/opsx:archive\` is forbidden — the question may be answered "no", but it may never be skipped.
177
+ **Scope.** Author E2E cases for the current change's entry-point behavior and handle what those new cases expose. Executing the existing E2E suite belongs to the Verify phase full test run; there is no separate red-diagnosis stage — a new case failing on first run is the TDD RED step, and an existing case turning red is a regression caught by Verify.
178
178
 
179
- **Independent of FuseReview:** the apply exit sequence contains TWO checkpoint questions, asked in order (FuseReview, then FuseQA). **Any FuseReview answer — accept or decline — leaves the FuseQA question mandatory.** The two MUST NOT be merged into a single question: they gate different things, and one "no" must never dismiss both.
179
+ **Findings are graded by attribution.** Attribute a red case first, then grade it:
180
+ - **Implementation defect → Blocking.** The red case IS the failing test that catches the defect; fix the implementation directly.
181
+ - **Spec gap → Suggestion** by default; escalate to Blocking when the undefined behavior causes user-visible breakage.
182
+ - **False red → case debt**, outside the grading. Fix or remove the case and record why the implementation is correct, with evidence.
183
+ - **Attribution exceeding its time box → Suggestion.** It MUST NOT hold up completion.
180
184
 
181
- **Apply completion requires both decisions on record:** the apply completion report MUST record the FuseReview decision AND the FuseQA decision. A report missing either record means apply is **not complete**, and \`/opsx:verify\` MUST NOT be entered. A declined FuseQA is recorded together with the change facts, so the skip is auditable rather than invisible.
185
+ **Cases are project assets with a recorded lifecycle.** Cases live in \`tests/e2e/<capability>/\`, the capability name matching \`openspec/specs/<capability>/\`. Addition records its source (the spec Scenario or the escaped defect); correction records why the prior judgment was wrong; removal records why the case is no longer valid. Without a reason, "deleting a red case" and "hiding a defect" are indistinguishable in the ledger.
182
186
 
183
- **Present facts, do not judge:** the question lists whether the change touched a user-observable entry point, which capabilities are affected, and the current E2E case count. A recommendation may be attached, but the decision belongs to the user. There are no automatic trigger thresholds of any kind.
184
-
185
- **Scope — two things only:** author E2E cases for this change's entry-point changes, and handle what those new cases expose.
186
- - **Regression execution is NOT part of this beat.** Running the existing E2E suite belongs to the Verify phase full test run.
187
- - **There is no separate red-diagnosis stage.** A new case failing on first run is the TDD RED step; an existing case turning red is a regression the Verify gate catches.
188
-
189
- **Findings are graded by attribution, not by redness.** A red case carries evidence (it went red) but its cause is undetermined, so attribute first, then grade:
190
- - **Implementation defect → Blocking.** The red case IS the failing test that catches the defect, so fix the implementation directly. This grade does not bend — it is the entire reason this beat exists.
191
- - **Spec gap → Suggestion** by default: behavior the spec never defined means the product is not wrong. Escalate to Blocking when the undefined behavior causes user-visible breakage.
192
- - **False red → case debt, outside the Blocking/Suggestion grading.** Fix or remove the case, and record in the ledger why the implementation is correct, with evidence. Never just "the test was wrong".
193
- - **Attribution exceeding its time box → downgrade to Suggestion.** It MUST NOT hold up apply completion.
194
-
195
- **Cases are project assets with a recorded lifecycle.** Cases live in \`tests/e2e/<capability>/\`, the capability name matching \`openspec/specs/<capability>/\`.
196
- - **Addition** records its source: the spec Scenario it derives from, or the escaped defect it was written for.
197
- - **Correction** records why the original judgment was wrong.
198
- - **Removal** records why the case is no longer valid. Without a reason, "deleting a red case" and "hiding a defect" are indistinguishable in the ledger.
199
-
200
- **Manual invocation:** the user may invoke the FuseQA skill explicitly at any time, independent of the checkpoint.`;
187
+ The full method lives at \`.claude/skills/fuseqa/SKILL.md\`.`;
201
188
  }
202
189
  export function renderFuseDocStandard() {
203
190
  return `### Documentation Standard: FuseDoc
@@ -222,12 +209,12 @@ export function renderAutoMode() {
222
209
  - **Design tokens:** when the three-gate test triggers \`/design-md\`, answer the questionnaire with recommended values; never overwrite an existing \`DESIGN-TOKENS.md\`.
223
210
  - **Model switch:** record \`continue with current model\`; do not switch and do not ask.
224
211
  - **FuseReview:** record \`auto: entered\` and run the review.
225
- - **FuseQA:** record \`auto: declined\`; do not enter the beat.
212
+ - **FuseQA:** not part of the pipeline; do not invoke it. It remains available only through an explicit \`/fuseqa\` request.
226
213
  - **Path B pace control:** generate all artifacts in one pass; do not stop between artifacts for review.
227
214
 
228
215
  **Execution order.** Brainstorming decisions → proposal → specs → design → tasks → apply under \`test-driven-development\` and \`verification-before-completion\` → FuseReview → verify → archive. The command definition at \`.claude/commands/specfuse.md\` carries the full procedure.
229
216
 
230
- **Exit sequence.** Auto mode enters FuseReview and skips FuseQA. The apply completion report still records both decisions — \`auto: entered\` and \`auto: declined\` — so the dual-record rule is satisfied without a question.
217
+ **Exit sequence.** Auto mode enters FuseReview. The apply completion report records the FuseReview decision only. FuseQA is not part of the pipeline: it is not invoked and no FuseQA decision is recorded; it remains an explicit \`/fuseqa\` invocation outside the pipeline.
231
218
 
232
219
  **Verify gates archive.** Archive only after \`/opsx:verify\`, the project's full test suite, and the project's linter pass. If any check still fails after best-effort repair, do not archive; keep the change directory and write each failure with its raw output into the final report.
233
220
 
@@ -235,7 +222,7 @@ export function renderAutoMode() {
235
222
 
236
223
  **Prohibitions.** Never run \`git commit\`, \`git push\`, or \`git merge\`. Auto mode does not waive TDD, verification evidence, or the documentation standard.
237
224
 
238
- **Interactive rules unchanged.** The checkpoints in Phase 2, Phase 2.5, and Phase 2.6 still require their questions for \`/opsx:apply\`. Auto mode removes the question, not the decision record.`;
225
+ **Interactive rules unchanged.** The model-switch and FuseReview checkpoints in Phase 2 and Phase 2.5 still require their questions for \`/opsx:apply\`. Auto mode removes the question, not the decision record.`;
239
226
  }
240
227
  export function renderVerifyPhase() {
241
228
  return `### Phase 3: Verify / Archive
@@ -292,10 +279,10 @@ export function composeCLAUDEmd(_ctx) {
292
279
  "",
293
280
  renderApplyFuseReview(),
294
281
  "",
295
- renderFuseQA(),
296
- "",
297
282
  renderVerifyPhase(),
298
283
  "",
284
+ renderFuseQAOnDemand(),
285
+ "",
299
286
  renderGeneralRules(),
300
287
  "<!-- FUSION:END -->",
301
288
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAEA,SAAS,sBAAsB;IAC7B,OAAO;;iCAEwB,CAAC;AAClC,CAAC;AAED,SAAS,uBAAuB;IAC9B,OAAO;;;;;;;;;;;;;oJAa2I,CAAC;AACrJ,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;;;;;;;;;;;;;;;;+DAgBsD,CAAC;AAChE,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;4EAwBmE,CAAC;AAC7E,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO;;;;;;;;;;;;qGAY4F,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gDAwDuC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;uHAyB8G,CAAC;AACxH,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mHA6B0G,CAAC;AACpH,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;wHAU+G,CAAC;AACzH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO;;;;;;;;;;;;;;;;;;;;;;kMAsByL,CAAC;AACnM,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO;;;;;;;;0MAQiM,CAAC;AAC3M,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO;;;;;;;2EAOkE,CAAC;AAC5E,CAAC;AAED,2EAA2E;AAC3E,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAAC,IAAqB;IACnD,MAAM,QAAQ,GAAG;QACf,qBAAqB;QACrB,EAAE;QACF,sBAAsB,EAAE;QACxB,EAAE;QACF,uBAAuB,EAAE;QACzB,EAAE;QACF,KAAK;QACL,EAAE;QACF,uBAAuB;QACvB,0DAA0D;QAC1D,EAAE;QACF,4EAA4E;QAC5E,sDAAsD;QACtD,EAAE;QACF,qBAAqB,EAAE;QACvB,EAAE;QACF,cAAc,EAAE;QAChB,EAAE;QACF,WAAW,EAAE;QACb,EAAE;QACF,WAAW,EAAE;QACb,EAAE;QACF,iBAAiB,EAAE;QACnB,EAAE;QACF,gBAAgB,EAAE;QAClB,EAAE;QACF,qBAAqB,EAAE;QACvB,EAAE;QACF,YAAY,EAAE;QACd,EAAE;QACF,iBAAiB,EAAE;QACnB,EAAE;QACF,kBAAkB,EAAE;QACpB,qBAAqB;KACtB,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACpC,CAAC"}
1
+ {"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/templates/claude-md.ts"],"names":[],"mappings":"AAEA,SAAS,sBAAsB;IAC7B,OAAO;;iCAEwB,CAAC;AAClC,CAAC;AAED,SAAS,uBAAuB;IAC9B,OAAO;;;;;;;;;;;;;oJAa2I,CAAC;AACrJ,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;;;;;;;;;;;;;;;;+DAgBsD,CAAC;AAChE,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;4EAwBmE,CAAC;AAC7E,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO;;;;;;;;;;;;qGAY4F,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gDAwDuC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;uHAyB8G,CAAC;AACxH,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO;;;;;;;;;;;;;;;;6DAgBoD,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO;;;;;;;;;;wHAU+G,CAAC;AACzH,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO;;;;;;;;;;;;;;;;;;;;;;kNAsByM,CAAC;AACnN,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO;;;;;;;;0MAQiM,CAAC;AAC3M,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO;;;;;;;2EAOkE,CAAC;AAC5E,CAAC;AAED,2EAA2E;AAC3E,8EAA8E;AAC9E,0EAA0E;AAC1E,8EAA8E;AAC9E,MAAM,UAAU,eAAe,CAAC,IAAqB;IACnD,MAAM,QAAQ,GAAG;QACf,qBAAqB;QACrB,EAAE;QACF,sBAAsB,EAAE;QACxB,EAAE;QACF,uBAAuB,EAAE;QACzB,EAAE;QACF,KAAK;QACL,EAAE;QACF,uBAAuB;QACvB,0DAA0D;QAC1D,EAAE;QACF,4EAA4E;QAC5E,sDAAsD;QACtD,EAAE;QACF,qBAAqB,EAAE;QACvB,EAAE;QACF,cAAc,EAAE;QAChB,EAAE;QACF,WAAW,EAAE;QACb,EAAE;QACF,WAAW,EAAE;QACb,EAAE;QACF,iBAAiB,EAAE;QACnB,EAAE;QACF,gBAAgB,EAAE;QAClB,EAAE;QACF,qBAAqB,EAAE;QACvB,EAAE;QACF,iBAAiB,EAAE;QACnB,EAAE;QACF,oBAAoB,EAAE;QACtB,EAAE;QACF,kBAAkB,EAAE;QACpB,qBAAqB;KACtB,CAAC;IACF,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AACpC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fuseqa-skill.d.ts","sourceRoot":"","sources":["../../src/templates/fuseqa-skill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CA8GhE"}
1
+ {"version":3,"file":"fuseqa-skill.d.ts","sourceRoot":"","sources":["../../src/templates/fuseqa-skill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAgHhE"}
@@ -1,16 +1,18 @@
1
1
  export function composeFuseQASkill(_ctx) {
2
2
  return `---
3
3
  name: fuseqa
4
- description: Use when performing post-apply E2E verification (FuseQA) — derives end-to-end cases for the current change from its specs and drives them through real user entry points against the built artifact; also runs when the user asks to "write e2e tests", "end-to-end tests", "QA acceptance", or to add test cases for a change.
4
+ description: Use only when the user explicitly asks for local end-to-end verification (FuseQA) — derives end-to-end cases for the current change from its specs and drives them through real user entry points against the built artifact. Not part of the default pipeline; never invoked automatically. Also handles "write e2e tests", "end-to-end tests", "QA acceptance", or adding test cases for a change.
5
5
  ---
6
6
 
7
- # FuseQA — Post-Apply E2E Verification
7
+ # FuseQA — On-Demand E2E Verification
8
8
 
9
- Think reviews direction, Do produces code, FuseReview reviews the implementation, **FuseQA verifies the artifact through real entry points**, Verify validates the whole.
9
+ FuseQA verifies the artifact through real entry points. It is **not part of the default pipeline and has no checkpoint**: no phase, checkpoint, or automatic decision invokes it, and neither apply completion nor entry to Verify depends on it. Run it explicitly with \`/fuseqa\` when local end-to-end verification is meaningful.
10
10
 
11
- This beat authors E2E cases for the current change and handles what those cases expose. It **does not execute the existing regression suite** — that belongs to the Verify phase full test run. A new case failing on first run is the TDD RED step, not a diagnosis stage.
11
+ It authors E2E cases for the current change and handles what those cases expose. It **does not execute the existing regression suite** — that belongs to the Verify phase full test run. A new case failing on first run is the TDD RED step, not a diagnosis stage. An existing case turning red is a regression caught by the Verify gate.
12
12
 
13
- **What makes this beat necessary:** unit tests cover source, cold-read review runs nothing, and the Verify phase runs the same unit suite. A defect can pass all of them and still reach users. The canonical shape: an entry-guard that compares a resolved module path against an unresolved \`argv[1]\` works when the built file is invoked by its real path and silently does nothing when invoked through a symlinked bin shim — typecheck, unit tests and diff review all pass.
13
+ **When local E2E fits:** FuseQA is useful when the artifact can be deployed and exercised on one machine — a CLI, a small service, a library, a local web app. It cannot reproduce a distributed topology: service discovery, network partitions, shared-state races across nodes, or production data. For distributed systems, run equivalent checks in CI/CD rather than in the development phase; a local green suite there proves very little.
14
+
15
+ **What local E2E catches that the other gates cannot:** unit tests cover source, cold-read review runs nothing, and the Verify phase runs the same unit suite. A defect can pass all of them and still reach users. The canonical shape: an entry-guard that compares a resolved module path against an unresolved \`argv[1]\` works when the built file is invoked by its real path and silently does nothing when invoked through a symlinked bin shim — typecheck, unit tests and diff review all pass.
14
16
 
15
17
  ---
16
18
 
@@ -43,7 +45,7 @@ Every case declares five fields (schema: \`templates/_case-schema.yaml\`):
43
45
  Two hard rules, both mechanically checkable:
44
46
 
45
47
  - **No importing project source.** A case that imports from \`../src/\` is not a FuseQA case — it is a unit test wearing a costume. This is grep-checkable, so it is checked.
46
- - **The artifact under test is the build output, not the source.** TDD covers \`src/\`; FuseQA covers what ships. The bin-shim entry-guard defect above passes at source level and fails as a built artifact — that gap is this beat's whole subject.
48
+ - **The artifact under test is the build output, not the source.** TDD covers \`src/\`; FuseQA covers what ships. The bin-shim entry-guard defect above passes at source level and fails as a built artifact — that gap is this skill's whole subject.
47
49
 
48
50
  ---
49
51
 
@@ -94,7 +96,7 @@ A red case carries evidence but its cause is undetermined. Attribution is usuall
94
96
  - **Implementation defect → Blocking.** The red case IS the failing test; fix the implementation.
95
97
  - **Spec gap → Suggestion** by default; escalate to Blocking if the undefined behavior breaks something users see.
96
98
  - **False red → case debt**, outside the grading. Fix or remove the case and record **why the implementation is correct**, with evidence. "The test was wrong" alone is not an attribution.
97
- - **Attribution over its time box → Suggestion.** Never hold up apply completion on an unresolved attribution.
99
+ - **Attribution over its time box → Suggestion.** Never hold up the change's completion on an unresolved attribution.
98
100
 
99
101
  ---
100
102
 
@@ -1 +1 @@
1
- {"version":3,"file":"fuseqa-skill.js","sourceRoot":"","sources":["../../src/templates/fuseqa-skill.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,IAAqB;IACtD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4GR,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"fuseqa-skill.js","sourceRoot":"","sources":["../../src/templates/fuseqa-skill.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAAC,IAAqB;IACtD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8GR,CAAC;AACF,CAAC"}
@@ -6,7 +6,7 @@ description: Use when performing the post-apply code review (FuseReview) — rev
6
6
 
7
7
  # FuseReview — Post-Apply Code Review
8
8
 
9
- Think reviews direction, Do produces code, **FuseReview reviews the implementation**, FuseQA verifies the artifact through real entry points, Verify validates the whole. This skill is guidance, not a checklist: follow the code, keep judgment active, and prefer one substantiated blocker over a list of nits.
9
+ Think reviews direction, Do produces code, **FuseReview reviews the implementation**, Verify validates the whole. This skill is guidance, not a checklist: follow the code, keep judgment active, and prefer one substantiated blocker over a list of nits.
10
10
 
11
11
  This skill is **self-contained**. The review method below is complete within this file; it does not route to documents that may not exist in this project.
12
12
 
@@ -27,7 +27,7 @@ Do not call AskUserQuestion at any decision point. Answer each with the recommen
27
27
  - **Design tokens:** when the three-gate test triggers \`/design-md\`, answer the questionnaire with recommended values and generate \`DESIGN-TOKENS.md\`; never overwrite an existing \`DESIGN-TOKENS.md\`.
28
28
  - **Model switch:** record \`continue with current model\`; do not switch and do not ask.
29
29
  - **FuseReview:** record \`auto: entered\` and run the review.
30
- - **FuseQA:** record \`auto: declined\`; do not enter the beat.
30
+ - **FuseQA:** not part of the pipeline; do not invoke it. It remains available only through an explicit \`/fuseqa\` request.
31
31
  - **Pace control:** do not stop between artifacts for review.
32
32
 
33
33
  ## Execution order
@@ -73,7 +73,7 @@ When a Git Worktree trigger condition is met, the worktree is selected in step 0
73
73
 
74
74
  ## Final report
75
75
 
76
- State the change name and location, the artifacts written, the task count, verification output, the FuseReview decision (\`auto: entered\`), the FuseQA decision (\`auto: declined\`), the archive outcome, any worktree path, every automatic decision with its rationale, and that no commit and no push were performed.
76
+ State the change name and location, the artifacts written, the task count, verification output, the FuseReview decision (\`auto: entered\`), the archive outcome, any worktree path, every automatic decision with its rationale, and that no commit and no push were performed. FuseQA is not part of the pipeline, so no FuseQA decision is recorded.
77
77
  `;
78
78
  }
79
79
  //# sourceMappingURL=specfuse-command.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-specfuse",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "description": "Scaffold projects with OpenSpec + Superpowers fusion methodology",
5
5
  "type": "module",
6
6
  "bin": {