@localsummer/incspec 0.0.7 → 0.0.8

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
@@ -12,7 +12,7 @@
12
12
 
13
13
  ![IncSpec 全局介绍](./assets/incspec.jpeg)
14
14
 
15
- IncSpec 通过**增量规范驱动开发**让人类与 AI 编程助手保持一致 - 这是一个 6+1 步工作流(6 步开发 + 归档),在修改代码前先捕获代码流程基线。**无需 API 密钥。**
15
+ IncSpec 通过**增量规范驱动开发**让人类与 AI 编程助手保持一致 - 这是一个 7 步工作流,在修改代码前先捕获代码流程基线。**无需 API 密钥。**
16
16
 
17
17
  ## 为什么选择 IncSpec?
18
18
 
@@ -30,7 +30,7 @@ AI 编程助手在处理复杂前端代码库时常常力不从心,因为 API
30
30
  ## IncSpec 对比一览
31
31
 
32
32
  - **前端专注**:专为 API 数据流程分析和组件依赖设计。
33
- - **6+1 步循环**:分析 → 收集需求 → 收集依赖 → 设计 → 应用 → 合并 → 归档。
33
+ - **7 步循环**:分析 → 收集需求 → 收集依赖 → 设计 → 应用 → 合并 → 归档。
34
34
  - **基线管理**:每个循环产出新基线,作为下一轮迭代的起点。
35
35
  - **与 OpenSpec 对比**:OpenSpec 擅长 0→1 功能规范。incspec 擅长理解和修改现有前端代码库(1→n),特别是 API 流程和状态管理复杂的场景。
36
36
 
@@ -38,6 +38,10 @@ AI 编程助手在处理复杂前端代码库时常常力不从心,因为 API
38
38
 
39
39
  ## 工作原理
40
40
 
41
+ ### 完整模式 (7步)
42
+
43
+ 适用于复杂功能开发,需要完整的 UI 依赖分析和增量设计。
44
+
41
45
  ```
42
46
  ┌────────────────────┐
43
47
  │ 1. 分析 │ 分析现有代码流程
@@ -91,6 +95,48 @@ AI 编程助手在处理复杂前端代码库时常常力不从心,因为 API
91
95
  └───────────┘
92
96
  ```
93
97
 
98
+ ### 快速模式 (5步)
99
+
100
+ 适用于 Bug 修复、简单功能、不涉及复杂 UI 依赖的变更。
101
+
102
+ ```
103
+ ┌────────────────────┐
104
+ │ 1. 分析 │ 分析现有代码流程
105
+ │ 代码流程 │ 生成基线快照
106
+ └────────┬───────────┘
107
+
108
+
109
+ ┌────────────────────┐
110
+ │ 2. 收集 │ 捕获结构化需求
111
+ │ 需求 │ 5 列表格格式
112
+ └────────┬───────────┘
113
+
114
+ │ (跳过步骤 3 UI依赖采集)
115
+ │ (跳过步骤 4 增量设计)
116
+
117
+
118
+ ┌────────────────────┐
119
+ │ 5. 应用 │ 基于需求文档
120
+ │ 变更 │ 直接实现代码变更
121
+ └────────┬───────────┘
122
+
123
+
124
+ ┌────────────────────┐
125
+ │ 6. 合并 │ 重新分析代码
126
+ │ 到基线 │ 生成新基线
127
+ └────────┬───────────┘
128
+
129
+
130
+ ┌────────────────────┐
131
+ │ 7. 归档 │ 归档本轮产出
132
+ │ 产出 │ 清空工作区
133
+ └────────────────────┘
134
+ ```
135
+
136
+ **模式选择建议:**
137
+ - **完整模式**: 复杂 UI 功能、多组件交互、需要详细设计审查
138
+ - **快速模式**: Bug 修复、简单功能、不涉及 UI 依赖变更
139
+
94
140
  > **提示**: 如果已有基准报告,可使用 `incspec analyze --baseline=<file>` 直接跳过分析步骤,快速进入后续工作流。
95
141
 
96
142
  ## 快速开始
@@ -197,6 +243,14 @@ $ incspec status # 检查当前工作流状态
197
243
  $ incspec analyze src/views/Home --complete # 标记步骤 1 完成
198
244
  ```
199
245
 
246
+ **启动快速模式** (5步流程):
247
+
248
+ 适用于 Bug 修复或简单功能变更:
249
+ ```bash
250
+ $ incspec analyze src/views/Home --quick # 启动快速模式工作流
251
+ ```
252
+ 快速模式跳过步骤 3 (UI依赖采集) 和步骤 4 (增量设计),直接从需求进入代码应用。
253
+
200
254
  **使用现有基准报告** (跳过分析):
201
255
 
202
256
  如果已有基准报告文件,可直接使用,跳过分析步骤:
@@ -275,7 +329,7 @@ AI:我将增量合并到新基线。
275
329
 
276
330
  ### 7. 归档已完成的工作
277
331
 
278
- 完成 6 步工作流后,使用归档命令保存本轮产出:
332
+ 完成步骤 1-6 后,使用归档命令保存本轮产出:
279
333
 
280
334
  ```text
281
335
  你:归档本轮工作流产出
@@ -304,7 +358,7 @@ $ incspec archive -y # 归档所有工作流产出,跳过确认
304
358
 
305
359
  在以下情况下执行归档:
306
360
 
307
- 1. **6 步工作流全部完成** - 代码已应用,新基线已生成
361
+ 1. **步骤 1-6 全部完成** - 代码已应用,新基线已生成
308
362
  2. **功能已验证通过** - 确认变更符合预期
309
363
  3. **准备开始下一轮迭代** - 需要清空当前工作区
310
364
 
@@ -352,7 +406,7 @@ incspec/
352
406
 
353
407
  ```
354
408
  ┌────────────────────┐
355
- │ 6 步工作流完成
409
+ 步骤 1-6 完成
356
410
  │ 新基线已生成 │
357
411
  └────────┬───────────┘
358
412
 
@@ -441,8 +495,9 @@ incspec help <command> # 显示特定命令帮助
441
495
 
442
496
  ```bash
443
497
  # 步骤 1:分析代码流程
444
- incspec analyze <source-path> [--module=name] # 别名:a
498
+ incspec analyze <source-path> [--module=name] [--quick] # 别名:a
445
499
  incspec a src/views/Home --module=home
500
+ incspec analyze src/views/Home --quick # 启动快速模式
446
501
  incspec analyze src/views/Home --complete -o baselines/home-baseline-v1.md
447
502
  incspec analyze --baseline=home-baseline-v1.md # 使用现有基准(自动从归档恢复)
448
503
 
@@ -450,21 +505,23 @@ incspec analyze --baseline=home-baseline-v1.md # 使用现有基准(自动从
450
505
  incspec collect-req # 别名:cr
451
506
  incspec cr --complete
452
507
 
453
- # 步骤 3:收集 UI 依赖
508
+ # 步骤 3:收集 UI 依赖(快速模式跳过)
454
509
  incspec collect-dep # 别名:cd
455
510
  incspec cd --complete
456
511
 
457
- # 步骤 4:生成增量设计
512
+ # 步骤 4:生成增量设计(快速模式跳过)
458
513
  incspec design [--feature=name] # 别名:d
459
514
  incspec d --feature=user-auth --complete -o increments/auth-increment-v1.md
460
515
 
461
516
  # 步骤 5:应用代码变更
462
517
  incspec apply [increment-path] # 别名:ap
463
518
  incspec ap --source-dir=src/ --complete
519
+ # 快速模式下自动使用 requirements/structured-requirements.md 作为输入
464
520
 
465
521
  # 步骤 6:合并到基线
466
522
  incspec merge [increment-path] # 别名:m
467
523
  incspec m --complete -o baselines/home-baseline-v2.md
524
+ # 快速模式下重新分析代码生成新基线
468
525
  ```
469
526
 
470
527
  </details>
@@ -517,7 +574,7 @@ incspec archive -y # 跳过确认提示
517
574
 
518
575
  | 特性 | incspec | OpenSpec |
519
576
  |------|---------|----------|
520
- | 工作流 | 6+1 步增量循环(含归档) | 3 阶段(proposal → apply → archive) |
577
+ | 工作流 | 7 步增量循环 | 3 阶段(proposal → apply → archive) |
521
578
  | 侧重点 | 前端 API 流程分析 | 通用功能规范 |
522
579
  | 编号系统 | S/D/N/C/R 多层编号 | 单一编号 |
523
580
  | 代码生成 | 集成应用步骤 | 需手动编码 |
@@ -14,6 +14,7 @@ import {
14
14
  startWorkflow,
15
15
  updateStep,
16
16
  STATUS,
17
+ MODE,
17
18
  getStepInfo,
18
19
  isWorkflowIncomplete,
19
20
  getWorkflowProgress,
@@ -123,10 +124,12 @@ export async function analyzeCommand(ctx) {
123
124
 
124
125
  // Handle workflow state
125
126
  let workflow = readWorkflow(projectRoot);
127
+ const isQuick = options.quick || options.q;
126
128
  if (!workflow?.currentWorkflow) {
127
129
  const workflowName = typeof options.workflow === 'string' ? options.workflow : `analyze-${moduleName}`;
128
- workflow = startWorkflow(projectRoot, workflowName);
129
- printSuccess(`已创建新工作流: ${workflowName}`);
130
+ workflow = startWorkflow(projectRoot, workflowName, { mode: isQuick ? MODE.QUICK : MODE.FULL });
131
+ const modeLabel = isQuick ? '(快速模式: 5步)' : '';
132
+ printSuccess(`已创建新工作流: ${workflowName} ${modeLabel}`);
130
133
  }
131
134
 
132
135
  // Mark step as completed
@@ -151,15 +154,18 @@ export async function analyzeCommand(ctx) {
151
154
 
152
155
  // Get workflow state
153
156
  let workflow = readWorkflow(projectRoot);
157
+ const isQuick = options.quick || options.q;
154
158
 
155
159
  // Check if starting new workflow
156
160
  if (!workflow?.currentWorkflow) {
157
161
  let workflowName = typeof options.workflow === 'string' ? options.workflow : '';
158
162
  if (!workflowName) {
159
- workflowName = await prompt('请输入工作流名称', `analyze-${moduleName}`);
163
+ const modeHint = isQuick ? '(快速模式)' : '';
164
+ workflowName = await prompt(`请输入工作流名称 ${modeHint}`, `analyze-${moduleName}`);
160
165
  }
161
- workflow = startWorkflow(projectRoot, workflowName);
162
- printSuccess(`已创建新工作流: ${workflowName}`);
166
+ workflow = startWorkflow(projectRoot, workflowName, { mode: isQuick ? MODE.QUICK : MODE.FULL });
167
+ const modeLabel = isQuick ? '(快速模式: 5步)' : '';
168
+ printSuccess(`已创建新工作流: ${workflowName} ${modeLabel}`);
163
169
  } else if (isWorkflowIncomplete(workflow)) {
164
170
  // Current workflow is incomplete, ask for confirmation
165
171
  const progress = getWorkflowProgress(workflow);
@@ -167,19 +173,21 @@ export async function analyzeCommand(ctx) {
167
173
  printWarning(`当前工作流 "${workflow.currentWorkflow}" 未完成 (${progress.completed}/${progress.total})`);
168
174
  print(colorize(` 最后完成步骤: ${progress.lastCompletedStep || '无'}`, colors.dim));
169
175
  print('');
170
-
176
+
171
177
  const shouldArchive = await confirm('是否归档当前工作流并开始新工作流?');
172
-
178
+
173
179
  if (!shouldArchive) {
174
180
  printInfo('已取消。继续当前工作流。');
175
181
  print('');
176
182
  } else {
177
183
  let workflowName = typeof options.workflow === 'string' ? options.workflow : '';
178
184
  if (!workflowName) {
179
- workflowName = await prompt('请输入新工作流名称', `analyze-${moduleName}`);
185
+ const modeHint = isQuick ? '(快速模式)' : '';
186
+ workflowName = await prompt(`请输入新工作流名称 ${modeHint}`, `analyze-${moduleName}`);
180
187
  }
181
- workflow = startWorkflow(projectRoot, workflowName);
182
- printSuccess(`已归档旧工作流,创建新工作流: ${workflowName}`);
188
+ workflow = startWorkflow(projectRoot, workflowName, { mode: isQuick ? MODE.QUICK : MODE.FULL });
189
+ const modeLabel = isQuick ? '(快速模式: 5步)' : '';
190
+ printSuccess(`已归档旧工作流,创建新工作流: ${workflowName} ${modeLabel}`);
183
191
  }
184
192
  }
185
193
 
@@ -192,6 +200,14 @@ export async function analyzeCommand(ctx) {
192
200
  print(colorize('步骤 1: 代码流程分析', colors.bold, colors.cyan));
193
201
  print(colorize('─────────────────────', colors.dim));
194
202
  print('');
203
+
204
+ // Show quick mode info
205
+ if (isQuick) {
206
+ print(colorize('快速模式流程: 分析 -> 需求收集 -> 应用代码 -> 合并基线', colors.yellow));
207
+ print(colorize('(跳过 UI依赖采集 和 增量设计)', colors.dim));
208
+ print('');
209
+ }
210
+
195
211
  print(colorize('配置:', colors.bold));
196
212
  print(colorize(` 源代码路径: ${sourcePath}`, colors.dim));
197
213
  print(colorize(` 模块名称: ${moduleName}`, colors.dim));
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import * as path from 'path';
6
+ import * as fs from 'fs';
6
7
  import {
7
8
  ensureInitialized,
8
9
  INCSPEC_DIR,
@@ -13,6 +14,7 @@ import {
13
14
  readWorkflow,
14
15
  updateStep,
15
16
  STATUS,
17
+ isQuickMode,
16
18
  } from '../lib/workflow.mjs';
17
19
  import { listSpecs } from '../lib/spec.mjs';
18
20
  import {
@@ -45,24 +47,7 @@ export async function applyCommand(ctx) {
45
47
  return;
46
48
  }
47
49
 
48
- // Get increment file
49
- let incrementPath = args[0];
50
- if (!incrementPath) {
51
- const increments = listSpecs(projectRoot, 'increments');
52
- if (increments.length > 0) {
53
- const featureName = workflow.currentWorkflow.replace(/^analyze-/, '');
54
- const matched = increments.find(spec => spec.name.startsWith(`${featureName}-increment-`));
55
- if (matched) {
56
- incrementPath = matched.path;
57
- } else {
58
- incrementPath = increments[0].path;
59
- printWarning(`未找到与当前工作流匹配的增量文件,已使用最近文件: ${increments[0].name}`);
60
- }
61
- } else {
62
- printWarning('未找到增量设计文件。请先运行步骤 4 (design)。');
63
- return;
64
- }
65
- }
50
+ const quickMode = isQuickMode(workflow);
66
51
 
67
52
  // Get source directory
68
53
  const config = readProjectConfig(projectRoot);
@@ -70,12 +55,52 @@ export async function applyCommand(ctx) {
70
55
  ? options['source-dir']
71
56
  : (config?.source_dir || 'src');
72
57
 
58
+ // Determine input based on mode
59
+ let inputPath;
60
+ let inputType;
61
+
62
+ if (quickMode) {
63
+ // Quick mode: use requirements document
64
+ const reqFile = path.join(projectRoot, INCSPEC_DIR, DIRS.requirements, 'structured-requirements.md');
65
+ if (!fs.existsSync(reqFile)) {
66
+ printWarning('未找到需求文件。请先运行步骤 2 (collect-req)。');
67
+ return;
68
+ }
69
+ inputPath = path.join(INCSPEC_DIR, DIRS.requirements, 'structured-requirements.md');
70
+ inputType = 'requirements';
71
+ } else {
72
+ // Full mode: use increment design file
73
+ let incrementPath = args[0];
74
+ if (!incrementPath) {
75
+ const increments = listSpecs(projectRoot, 'increments');
76
+ if (increments.length > 0) {
77
+ const featureName = workflow.currentWorkflow.replace(/^analyze-/, '');
78
+ const matched = increments.find(spec => spec.name.startsWith(`${featureName}-increment-`));
79
+ if (matched) {
80
+ incrementPath = matched.path;
81
+ } else {
82
+ incrementPath = increments[0].path;
83
+ printWarning(`未找到与当前工作流匹配的增量文件,已使用最近文件: ${increments[0].name}`);
84
+ }
85
+ } else {
86
+ printWarning('未找到增量设计文件。请先运行步骤 4 (design)。');
87
+ return;
88
+ }
89
+ }
90
+ inputPath = incrementPath;
91
+ inputType = 'increment';
92
+ }
93
+
73
94
  print('');
74
95
  print(colorize('步骤 5: 应用代码变更', colors.bold, colors.cyan));
96
+ if (quickMode) {
97
+ print(colorize('(快速模式 - 基于需求文档)', colors.yellow));
98
+ }
75
99
  print(colorize('────────────────────', colors.dim));
76
100
  print('');
77
101
  print(colorize(`当前工作流: ${workflow.currentWorkflow}`, colors.dim));
78
- print(colorize(`增量设计文件: ${incrementPath}`, colors.dim));
102
+ print(colorize(`输入文件: ${inputPath}`, colors.dim));
103
+ print(colorize(`输入类型: ${inputType === 'requirements' ? '结构化需求' : '增量设计'}`, colors.dim));
79
104
  print(colorize(`源代码目录: ${sourceDir}`, colors.dim));
80
105
  print('');
81
106
 
@@ -84,21 +109,41 @@ export async function applyCommand(ctx) {
84
109
 
85
110
  print(colorize('使用说明:', colors.bold));
86
111
  print('');
87
- print(colorize('请在 Cursor 中运行以下命令:', colors.cyan));
88
- print('');
89
- print(colorize(` /incspec/inc-apply ${incrementPath}`, colors.bold, colors.white));
90
- print('');
91
- print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
92
- print('');
93
- print(colorize(` 请按照 ${incrementPath} 的增量设计,应用代码变更到 ${path.join(projectRoot, sourceDir)}`, colors.dim));
94
- print('');
95
- print(colorize('该命令将:', colors.dim));
96
- print(colorize(' 1. 解析增量设计文件中的变更计划', colors.dim));
97
- print(colorize(' 2. 按依赖顺序排序变更', colors.dim));
98
- print(colorize(' 3. 执行代码新建/修改/删除', colors.dim));
99
- print(colorize(' 4. 输出变更摘要', colors.dim));
112
+
113
+ if (quickMode) {
114
+ // Quick mode instructions
115
+ print(colorize('快速模式下,请直接根据需求文档实现代码变更:', colors.cyan));
116
+ print('');
117
+ print(colorize('在 Cursor 中:', colors.dim));
118
+ print(colorize(` /incspec/inc-apply ${inputPath}`, colors.bold, colors.white));
119
+ print('');
120
+ print(colorize('在 Claude Code 中:', colors.dim));
121
+ print(colorize(` 请根据 ${inputPath} 中的需求描述,直接实现代码变更`, colors.dim));
122
+ print('');
123
+ print(colorize('该命令将:', colors.dim));
124
+ print(colorize(' 1. 解析需求文档中的功能描述', colors.dim));
125
+ print(colorize(' 2. 基于现有基线分析影响范围', colors.dim));
126
+ print(colorize(' 3. 直接执行代码新建/修改/删除', colors.dim));
127
+ print(colorize(' 4. 输出变更摘要', colors.dim));
128
+ } else {
129
+ // Full mode instructions
130
+ print(colorize('请在 Cursor 中运行以下命令:', colors.cyan));
131
+ print('');
132
+ print(colorize(` /incspec/inc-apply ${inputPath}`, colors.bold, colors.white));
133
+ print('');
134
+ print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
135
+ print('');
136
+ print(colorize(` 请按照 ${inputPath} 的增量设计,应用代码变更到 ${path.join(projectRoot, sourceDir)}`, colors.dim));
137
+ print('');
138
+ print(colorize('该命令将:', colors.dim));
139
+ print(colorize(' 1. 解析增量设计文件中的变更计划', colors.dim));
140
+ print(colorize(' 2. 按依赖顺序排序变更', colors.dim));
141
+ print(colorize(' 3. 执行代码新建/修改/删除', colors.dim));
142
+ print(colorize(' 4. 输出变更摘要', colors.dim));
143
+ }
144
+
100
145
  print('');
101
- printWarning('请在执行前仔细审查增量设计文件!');
146
+ printWarning('请在执行前仔细审查输入文件!');
102
147
  print('');
103
148
  printInfo(`完成后运行 'incspec status' 查看进度`);
104
149
  print('');
@@ -10,7 +10,7 @@ import {
10
10
  DIRS,
11
11
  } from '../lib/config.mjs';
12
12
  import { archiveSpec, getSpecInfo } from '../lib/spec.mjs';
13
- import { archiveWorkflow, readWorkflow, STATUS } from '../lib/workflow.mjs';
13
+ import { archiveWorkflow, readWorkflow, updateStep, STATUS, isQuickMode, MODE } from '../lib/workflow.mjs';
14
14
  import {
15
15
  colors,
16
16
  colorize,
@@ -21,7 +21,24 @@ import {
21
21
  confirm,
22
22
  } from '../lib/terminal.mjs';
23
23
 
24
- const ARCHIVABLE_STEP_INDEXES = [0, 1, 2, 3, 5];
24
+ // Full mode: archivable steps are 1, 2, 3, 4, 6 (0-based: 0, 1, 2, 3, 5)
25
+ // Note: Step 5 (apply) has no file output, Step 7 (archive) is this command itself
26
+ const FULL_MODE_ARCHIVABLE_INDEXES = [0, 1, 2, 3, 5];
27
+ // Quick mode: archivable steps are 1, 2, 6 (0-based: 0, 1, 5)
28
+ // Note: Steps 3, 4 are skipped in quick mode
29
+ const QUICK_MODE_ARCHIVABLE_INDEXES = [0, 1, 5];
30
+
31
+ /**
32
+ * Get archivable step indexes based on workflow mode
33
+ * @param {Object} workflow
34
+ * @returns {number[]}
35
+ */
36
+ function getArchivableStepIndexes(workflow) {
37
+ if (isQuickMode(workflow)) {
38
+ return QUICK_MODE_ARCHIVABLE_INDEXES;
39
+ }
40
+ return FULL_MODE_ARCHIVABLE_INDEXES;
41
+ }
25
42
 
26
43
  function escapeRegExp(value) {
27
44
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
@@ -114,8 +131,10 @@ function getArchivableOutputs(workflow) {
114
131
  return null;
115
132
  }
116
133
 
134
+ const archivableIndexes = getArchivableStepIndexes(workflow);
117
135
  const outputs = [];
118
- for (const index of ARCHIVABLE_STEP_INDEXES) {
136
+
137
+ for (const index of archivableIndexes) {
119
138
  const step = workflow.steps[index];
120
139
  if (!step || step.status !== STATUS.COMPLETED || !step.output || step.output === '-') {
121
140
  return null;
@@ -260,6 +279,9 @@ export async function archiveCommand(ctx) {
260
279
  printSuccess(`文件已${keepOriginal ? '复制' : '移动'}到: ${archivePath}`);
261
280
  }
262
281
 
282
+ // Mark step 7 as completed
283
+ updateStep(projectRoot, 7, STATUS.COMPLETED);
284
+
263
285
  const refreshed = readWorkflow(projectRoot);
264
286
  if (refreshed?.currentWorkflow && shouldArchiveWorkflow(projectRoot, refreshed)) {
265
287
  const workflowName = refreshed.currentWorkflow;
@@ -12,6 +12,7 @@ import {
12
12
  readWorkflow,
13
13
  updateStep,
14
14
  STATUS,
15
+ isQuickMode,
15
16
  } from '../lib/workflow.mjs';
16
17
  import {
17
18
  colors,
@@ -76,5 +77,12 @@ export async function collectReqCommand(ctx) {
76
77
  if (options.complete) {
77
78
  updateStep(projectRoot, STEP_NUMBER, STATUS.COMPLETED, OUTPUT_FILE);
78
79
  printSuccess(`步骤 2 已标记为完成: ${OUTPUT_FILE}`);
80
+
81
+ // Quick mode hint
82
+ if (isQuickMode(workflow)) {
83
+ print('');
84
+ printInfo('快速模式: 跳过步骤 3、4,直接进入步骤 5');
85
+ print(colorize(" 运行 'incspec apply' 继续", colors.cyan));
86
+ }
79
87
  }
80
88
  }
package/commands/help.mjs CHANGED
@@ -34,12 +34,13 @@ const COMMANDS = {
34
34
  description: '显示当前工作流状态',
35
35
  },
36
36
  analyze: {
37
- usage: 'incspec analyze <source-path> [--module=name] [--baseline=file]',
37
+ usage: 'incspec analyze <source-path> [--module=name] [--quick] [--baseline=file]',
38
38
  aliases: ['a'],
39
39
  description: '步骤1: 分析代码流程,生成基线快照',
40
40
  options: [
41
41
  ['-m, --module=<name>', '指定模块名称'],
42
42
  ['-w, --workflow=<name>', '指定工作流名称(避免交互提示)'],
43
+ ['-q, --quick', '启动快速模式(5步流程: 分析->需求->应用->合并->归档)'],
43
44
  ['-b, --baseline=<file>', '使用现有基准报告(自动从归档恢复)'],
44
45
  ['--complete', '标记步骤完成'],
45
46
  ['-o, --output=<file>', '完成时指定输出文件'],
@@ -110,13 +111,18 @@ const COMMANDS = {
110
111
  archive: {
111
112
  usage: 'incspec archive [file-path] [--workflow] [-k|--keep] [-y|--yes]',
112
113
  aliases: ['ar'],
113
- description: '归档规范文件 (默认归档当前工作流产出)',
114
+ description: '步骤7: 归档工作流产出 (或指定文件)',
114
115
  options: [
115
116
  ['--workflow', '归档当前工作流全部产出文件'],
116
117
  ['-k, --keep', '复制而非移动'],
117
118
  ['-y, --yes', '跳过确认提示'],
118
119
  ],
119
120
  },
121
+ reset: {
122
+ usage: 'incspec reset',
123
+ aliases: ['rs'],
124
+ description: '重置当前工作流,归档已有产出',
125
+ },
120
126
  sync: {
121
127
  usage: 'incspec sync [--cursor] [--claude] [--all] [--project|--global]',
122
128
  aliases: ['s'],
@@ -183,7 +189,7 @@ function showGeneralHelp() {
183
189
  print(colorize('管理命令:', colors.bold));
184
190
  print('');
185
191
 
186
- const mgmtCommands = ['init', 'update', 'status', 'list', 'validate', 'archive', 'sync', 'help'];
192
+ const mgmtCommands = ['init', 'update', 'status', 'list', 'validate', 'archive', 'reset', 'sync', 'help'];
187
193
  mgmtCommands.forEach(cmd => {
188
194
  const def = COMMANDS[cmd];
189
195
  const aliases = def.aliases ? colorize(` (${def.aliases.join(', ')})`, colors.dim) : '';
@@ -12,6 +12,7 @@ import {
12
12
  readWorkflow,
13
13
  updateStep,
14
14
  STATUS,
15
+ isQuickMode,
15
16
  } from '../lib/workflow.mjs';
16
17
  import { listSpecs, getNextVersion } from '../lib/spec.mjs';
17
18
  import {
@@ -43,24 +44,7 @@ export async function mergeCommand(ctx) {
43
44
  return;
44
45
  }
45
46
 
46
- // Get increment file
47
- let incrementPath = args[0];
48
- if (!incrementPath) {
49
- const increments = listSpecs(projectRoot, 'increments');
50
- if (increments.length > 0) {
51
- const featureName = workflow.currentWorkflow.replace(/^analyze-/, '');
52
- const matched = increments.find(spec => spec.name.startsWith(`${featureName}-increment-`));
53
- if (matched) {
54
- incrementPath = matched.path;
55
- } else {
56
- incrementPath = increments[0].path;
57
- printWarning(`未找到与当前工作流匹配的增量文件,已使用最近文件: ${increments[0].name}`);
58
- }
59
- } else {
60
- printWarning('未找到增量设计文件。请先运行步骤 4 (design)。');
61
- return;
62
- }
63
- }
47
+ const quickMode = isQuickMode(workflow);
64
48
 
65
49
  // Calculate output file
66
50
  const moduleName = workflow.currentWorkflow.replace(/^analyze-/, '');
@@ -70,12 +54,39 @@ export async function mergeCommand(ctx) {
70
54
  const outputFile = outputOverride || defaultOutputFile;
71
55
  const outputPath = path.join(INCSPEC_DIR, DIRS.baselines, outputFile);
72
56
 
57
+ // Get increment file (only needed for full mode)
58
+ let incrementPath = null;
59
+ if (!quickMode) {
60
+ incrementPath = args[0];
61
+ if (!incrementPath) {
62
+ const increments = listSpecs(projectRoot, 'increments');
63
+ if (increments.length > 0) {
64
+ const featureName = workflow.currentWorkflow.replace(/^analyze-/, '');
65
+ const matched = increments.find(spec => spec.name.startsWith(`${featureName}-increment-`));
66
+ if (matched) {
67
+ incrementPath = matched.path;
68
+ } else {
69
+ incrementPath = increments[0].path;
70
+ printWarning(`未找到与当前工作流匹配的增量文件,已使用最近文件: ${increments[0].name}`);
71
+ }
72
+ } else {
73
+ printWarning('未找到增量设计文件。请先运行步骤 4 (design)。');
74
+ return;
75
+ }
76
+ }
77
+ }
78
+
73
79
  print('');
74
80
  print(colorize('步骤 6: 合并到基线', colors.bold, colors.cyan));
81
+ if (quickMode) {
82
+ print(colorize('(快速模式 - 重新分析生成新基线)', colors.yellow));
83
+ }
75
84
  print(colorize('─────────────────', colors.dim));
76
85
  print('');
77
86
  print(colorize(`当前工作流: ${workflow.currentWorkflow}`, colors.dim));
78
- print(colorize(`增量设计文件: ${incrementPath}`, colors.dim));
87
+ if (!quickMode) {
88
+ print(colorize(`增量设计文件: ${incrementPath}`, colors.dim));
89
+ }
79
90
  print(colorize(`输出基线文件: ${outputPath}`, colors.dim));
80
91
  print('');
81
92
 
@@ -84,20 +95,40 @@ export async function mergeCommand(ctx) {
84
95
 
85
96
  print(colorize('使用说明:', colors.bold));
86
97
  print('');
87
- print(colorize('请在 Cursor 中运行以下命令:', colors.cyan));
88
- print('');
89
- print(colorize(` /incspec/inc-merge ${incrementPath}`, colors.bold, colors.white));
90
- print('');
91
- print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
92
- print('');
93
- const outDir = path.join(projectRoot, INCSPEC_DIR, DIRS.baselines);
94
- print(colorize(` 请将 ${incrementPath} 的增量合并到基线 ${outDir}`, colors.dim));
95
- print('');
96
- print(colorize('该命令将:', colors.dim));
97
- print(colorize(' 1. 解析增量设计文件中的时序图和依赖图', colors.dim));
98
- print(colorize(' 2. 清理增量标记 (🆕/✏️/❌)', colors.dim));
99
- print(colorize(' 3. 重新编号为 S1-Sxx, D1-Dxx', colors.dim));
100
- print(colorize(' 4. 生成新的基线快照', colors.dim));
98
+
99
+ if (quickMode) {
100
+ // Quick mode instructions
101
+ print(colorize('快速模式下,将重新分析当前代码生成新基线:', colors.cyan));
102
+ print('');
103
+ print(colorize('在 Cursor 中:', colors.dim));
104
+ print(colorize(` /incspec/inc-merge --output=${outputFile}`, colors.bold, colors.white));
105
+ print('');
106
+ print(colorize('在 Claude Code 中:', colors.dim));
107
+ print(colorize(` 请分析当前代码状态,生成新的基线报告到 ${outputPath}`, colors.dim));
108
+ print('');
109
+ print(colorize('该命令将:', colors.dim));
110
+ print(colorize(' 1. 分析当前代码的完整流程', colors.dim));
111
+ print(colorize(' 2. 生成 API 调用时序图', colors.dim));
112
+ print(colorize(' 3. 生成依赖关系图', colors.dim));
113
+ print(colorize(' 4. 保存为新版本基线快照', colors.dim));
114
+ } else {
115
+ // Full mode instructions
116
+ print(colorize('请在 Cursor 中运行以下命令:', colors.cyan));
117
+ print('');
118
+ print(colorize(` /incspec/inc-merge ${incrementPath}`, colors.bold, colors.white));
119
+ print('');
120
+ print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
121
+ print('');
122
+ const outDir = path.join(projectRoot, INCSPEC_DIR, DIRS.baselines);
123
+ print(colorize(` 请将 ${incrementPath} 的增量合并到基线 ${outDir}`, colors.dim));
124
+ print('');
125
+ print(colorize('该命令将:', colors.dim));
126
+ print(colorize(' 1. 解析增量设计文件中的时序图和依赖图', colors.dim));
127
+ print(colorize(' 2. 清理增量标记', colors.dim));
128
+ print(colorize(' 3. 重新编号为 S1-Sxx, D1-Dxx', colors.dim));
129
+ print(colorize(' 4. 生成新的基线快照', colors.dim));
130
+ }
131
+
101
132
  print('');
102
133
  print(colorize('新基线将作为下一轮增量开发的起点。', colors.dim));
103
134
  print('');