@localsummer/incspec 0.0.6 → 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 +76 -15
- package/commands/analyze.mjs +28 -12
- package/commands/apply.mjs +78 -33
- package/commands/archive.mjs +25 -3
- package/commands/collect-dep.mjs +2 -2
- package/commands/collect-req.mjs +10 -2
- package/commands/design.mjs +2 -2
- package/commands/help.mjs +20 -11
- package/commands/list.mjs +2 -1
- package/commands/merge.mjs +64 -33
- package/commands/reset.mjs +166 -0
- package/commands/status.mjs +30 -7
- package/commands/sync.mjs +210 -0
- package/commands/update.mjs +2 -1
- package/index.mjs +13 -6
- package/lib/agents.mjs +1 -1
- package/lib/claude.mjs +144 -0
- package/lib/config.mjs +13 -10
- package/lib/cursor.mjs +20 -5
- package/lib/terminal.mjs +108 -0
- package/lib/workflow.mjs +123 -29
- package/package.json +1 -1
- package/templates/AGENTS.md +89 -36
- package/templates/INCSPEC_BLOCK.md +1 -1
- package/templates/WORKFLOW.md +1 -0
- package/templates/cursor-commands/analyze-codeflow.md +12 -1
- package/templates/cursor-commands/apply-increment-code.md +129 -1
- package/templates/cursor-commands/merge-to-baseline.md +87 -1
- package/templates/cursor-commands/structured-requirements-collection.md +6 -0
- package/templates/inc-spec-skill/SKILL.md +286 -0
- package/templates/inc-spec-skill/references/analyze-codeflow.md +368 -0
- package/templates/inc-spec-skill/references/analyze-increment-codeflow.md +246 -0
- package/templates/inc-spec-skill/references/apply-increment-code.md +520 -0
- package/templates/inc-spec-skill/references/inc-archive.md +278 -0
- package/templates/inc-spec-skill/references/merge-to-baseline.md +415 -0
- package/templates/inc-spec-skill/references/structured-requirements-collection.md +129 -0
- package/templates/inc-spec-skill/references/ui-dependency-collection.md +143 -0
- package/commands/cursor-sync.mjs +0 -116
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
15
|
-
IncSpec 通过**增量规范驱动开发**让人类与 AI 编程助手保持一致 - 这是一个
|
|
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
|
-
- **
|
|
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
|
## 快速开始
|
|
@@ -100,12 +146,12 @@ AI 编程助手在处理复杂前端代码库时常常力不从心,因为 API
|
|
|
100
146
|
<details>
|
|
101
147
|
<summary><strong>原生斜杠命令</strong>(点击展开)</summary>
|
|
102
148
|
|
|
103
|
-
运行 `incspec
|
|
149
|
+
运行 `incspec sync` 后,这些工具可使用内置的 incspec 命令。
|
|
104
150
|
|
|
105
151
|
| 工具 | 命令 |
|
|
106
152
|
|------|------|
|
|
107
153
|
| **Cursor** | `/incspec/inc-analyze`、`/incspec/inc-collect-req`、`/incspec/inc-collect-dep`、`/incspec/inc-design`、`/incspec/inc-apply`、`/incspec/inc-merge`、`/incspec/inc-archive` |
|
|
108
|
-
| **Claude Code** | 使用
|
|
154
|
+
| **Claude Code** | 使用 `inc-spec-skill` Skill |
|
|
109
155
|
|
|
110
156
|
</details>
|
|
111
157
|
|
|
@@ -159,16 +205,20 @@ incspec init
|
|
|
159
205
|
- 生成包含工作流指令的 `AGENTS.md`
|
|
160
206
|
- 在 `incspec/project.md` 中设置项目配置
|
|
161
207
|
|
|
162
|
-
#### 步骤 3:同步
|
|
208
|
+
#### 步骤 3:同步 IDE 集成(可选)
|
|
163
209
|
|
|
164
|
-
|
|
210
|
+
同步到 Cursor 或 Claude Code:
|
|
165
211
|
```bash
|
|
166
|
-
incspec
|
|
212
|
+
incspec sync # 交互式选择
|
|
213
|
+
incspec sync --cursor # 仅 Cursor
|
|
214
|
+
incspec sync --claude # 仅 Claude Code
|
|
215
|
+
incspec sync --all # 全部
|
|
167
216
|
```
|
|
168
217
|
|
|
169
218
|
**设置完成后:**
|
|
170
219
|
- 运行 `incspec status` 验证设置
|
|
171
220
|
- Cursor 用户可直接触发 `/incspec/inc-*` 命令
|
|
221
|
+
- Claude Code 用户可使用 `inc-spec-skill` Skill
|
|
172
222
|
|
|
173
223
|
### 创建你的第一个增量
|
|
174
224
|
|
|
@@ -193,6 +243,14 @@ $ incspec status # 检查当前工作流状态
|
|
|
193
243
|
$ incspec analyze src/views/Home --complete # 标记步骤 1 完成
|
|
194
244
|
```
|
|
195
245
|
|
|
246
|
+
**启动快速模式** (5步流程):
|
|
247
|
+
|
|
248
|
+
适用于 Bug 修复或简单功能变更:
|
|
249
|
+
```bash
|
|
250
|
+
$ incspec analyze src/views/Home --quick # 启动快速模式工作流
|
|
251
|
+
```
|
|
252
|
+
快速模式跳过步骤 3 (UI依赖采集) 和步骤 4 (增量设计),直接从需求进入代码应用。
|
|
253
|
+
|
|
196
254
|
**使用现有基准报告** (跳过分析):
|
|
197
255
|
|
|
198
256
|
如果已有基准报告文件,可直接使用,跳过分析步骤:
|
|
@@ -271,7 +329,7 @@ AI:我将增量合并到新基线。
|
|
|
271
329
|
|
|
272
330
|
### 7. 归档已完成的工作
|
|
273
331
|
|
|
274
|
-
|
|
332
|
+
完成步骤 1-6 后,使用归档命令保存本轮产出:
|
|
275
333
|
|
|
276
334
|
```text
|
|
277
335
|
你:归档本轮工作流产出
|
|
@@ -300,7 +358,7 @@ $ incspec archive -y # 归档所有工作流产出,跳过确认
|
|
|
300
358
|
|
|
301
359
|
在以下情况下执行归档:
|
|
302
360
|
|
|
303
|
-
1.
|
|
361
|
+
1. **步骤 1-6 全部完成** - 代码已应用,新基线已生成
|
|
304
362
|
2. **功能已验证通过** - 确认变更符合预期
|
|
305
363
|
3. **准备开始下一轮迭代** - 需要清空当前工作区
|
|
306
364
|
|
|
@@ -348,7 +406,7 @@ incspec/
|
|
|
348
406
|
|
|
349
407
|
```
|
|
350
408
|
┌────────────────────┐
|
|
351
|
-
│ 6
|
|
409
|
+
│ 步骤 1-6 完成 │
|
|
352
410
|
│ 新基线已生成 │
|
|
353
411
|
└────────┬───────────┘
|
|
354
412
|
│
|
|
@@ -437,8 +495,9 @@ incspec help <command> # 显示特定命令帮助
|
|
|
437
495
|
|
|
438
496
|
```bash
|
|
439
497
|
# 步骤 1:分析代码流程
|
|
440
|
-
incspec analyze <source-path> [--module=name]
|
|
498
|
+
incspec analyze <source-path> [--module=name] [--quick] # 别名:a
|
|
441
499
|
incspec a src/views/Home --module=home
|
|
500
|
+
incspec analyze src/views/Home --quick # 启动快速模式
|
|
442
501
|
incspec analyze src/views/Home --complete -o baselines/home-baseline-v1.md
|
|
443
502
|
incspec analyze --baseline=home-baseline-v1.md # 使用现有基准(自动从归档恢复)
|
|
444
503
|
|
|
@@ -446,21 +505,23 @@ incspec analyze --baseline=home-baseline-v1.md # 使用现有基准(自动从
|
|
|
446
505
|
incspec collect-req # 别名:cr
|
|
447
506
|
incspec cr --complete
|
|
448
507
|
|
|
449
|
-
# 步骤 3:收集 UI
|
|
508
|
+
# 步骤 3:收集 UI 依赖(快速模式跳过)
|
|
450
509
|
incspec collect-dep # 别名:cd
|
|
451
510
|
incspec cd --complete
|
|
452
511
|
|
|
453
|
-
# 步骤 4
|
|
512
|
+
# 步骤 4:生成增量设计(快速模式跳过)
|
|
454
513
|
incspec design [--feature=name] # 别名:d
|
|
455
514
|
incspec d --feature=user-auth --complete -o increments/auth-increment-v1.md
|
|
456
515
|
|
|
457
516
|
# 步骤 5:应用代码变更
|
|
458
517
|
incspec apply [increment-path] # 别名:ap
|
|
459
518
|
incspec ap --source-dir=src/ --complete
|
|
519
|
+
# 快速模式下自动使用 requirements/structured-requirements.md 作为输入
|
|
460
520
|
|
|
461
521
|
# 步骤 6:合并到基线
|
|
462
522
|
incspec merge [increment-path] # 别名:m
|
|
463
523
|
incspec m --complete -o baselines/home-baseline-v2.md
|
|
524
|
+
# 快速模式下重新分析代码生成新基线
|
|
464
525
|
```
|
|
465
526
|
|
|
466
527
|
</details>
|
|
@@ -501,7 +562,7 @@ incspec archive -y # 跳过确认提示
|
|
|
501
562
|
| `status` | `st` | 状态 |
|
|
502
563
|
| `list` | `ls` | 列表 |
|
|
503
564
|
| `validate` | `v` | 验证 |
|
|
504
|
-
| `
|
|
565
|
+
| `sync` | `s` | 同步 |
|
|
505
566
|
| `update` | `up` | 更新 |
|
|
506
567
|
| `help` | `h` | 帮助 |
|
|
507
568
|
|
|
@@ -513,7 +574,7 @@ incspec archive -y # 跳过确认提示
|
|
|
513
574
|
|
|
514
575
|
| 特性 | incspec | OpenSpec |
|
|
515
576
|
|------|---------|----------|
|
|
516
|
-
| 工作流 |
|
|
577
|
+
| 工作流 | 7 步增量循环 | 3 阶段(proposal → apply → archive) |
|
|
517
578
|
| 侧重点 | 前端 API 流程分析 | 通用功能规范 |
|
|
518
579
|
| 编号系统 | S/D/N/C/R 多层编号 | 单一编号 |
|
|
519
580
|
| 代码生成 | 集成应用步骤 | 需手动编码 |
|
package/commands/analyze.mjs
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
163
|
+
const modeHint = isQuick ? '(快速模式)' : '';
|
|
164
|
+
workflowName = await prompt(`请输入工作流名称 ${modeHint}`, `analyze-${moduleName}`);
|
|
160
165
|
}
|
|
161
|
-
workflow = startWorkflow(projectRoot, workflowName);
|
|
162
|
-
|
|
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
|
-
|
|
185
|
+
const modeHint = isQuick ? '(快速模式)' : '';
|
|
186
|
+
workflowName = await prompt(`请输入新工作流名称 ${modeHint}`, `analyze-${moduleName}`);
|
|
180
187
|
}
|
|
181
|
-
workflow = startWorkflow(projectRoot, workflowName);
|
|
182
|
-
|
|
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));
|
|
@@ -207,9 +223,9 @@ export async function analyzeCommand(ctx) {
|
|
|
207
223
|
print('');
|
|
208
224
|
print(colorize(` /incspec/inc-analyze ${sourcePath} --module=${moduleName}`, colors.bold, colors.white));
|
|
209
225
|
print('');
|
|
210
|
-
print(colorize('
|
|
226
|
+
print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
|
|
211
227
|
print('');
|
|
212
|
-
print(colorize(`
|
|
228
|
+
print(colorize(` 请分析 ${sourcePath} 的代码流程,生成基线报告到 ${path.join(projectRoot, INCSPEC_DIR, DIRS.baselines)}`, colors.dim));
|
|
213
229
|
print('');
|
|
214
230
|
printInfo(`完成后运行 'incspec status' 查看进度`);
|
|
215
231
|
print('');
|
package/commands/apply.mjs
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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('');
|
package/commands/archive.mjs
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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;
|
package/commands/collect-dep.mjs
CHANGED
|
@@ -62,9 +62,9 @@ export async function collectDepCommand(ctx) {
|
|
|
62
62
|
print('');
|
|
63
63
|
print(colorize(` /incspec/inc-collect-dep`, colors.bold, colors.white));
|
|
64
64
|
print('');
|
|
65
|
-
print(colorize('
|
|
65
|
+
print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
|
|
66
66
|
print('');
|
|
67
|
-
print(colorize(`
|
|
67
|
+
print(colorize(` 请收集 UI 依赖,生成依赖报告到 ${path.join(projectRoot, INCSPEC_DIR, DIRS.requirements)}`, colors.dim));
|
|
68
68
|
print('');
|
|
69
69
|
print(colorize('该命令将交互式采集 6 维度 UI 依赖:', colors.dim));
|
|
70
70
|
print(colorize(' - UI组件库 (Arco/Antd)', colors.dim));
|
package/commands/collect-req.mjs
CHANGED
|
@@ -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,
|
|
@@ -62,9 +63,9 @@ export async function collectReqCommand(ctx) {
|
|
|
62
63
|
print('');
|
|
63
64
|
print(colorize(` /incspec/inc-collect-req`, colors.bold, colors.white));
|
|
64
65
|
print('');
|
|
65
|
-
print(colorize('
|
|
66
|
+
print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
|
|
66
67
|
print('');
|
|
67
|
-
print(colorize(`
|
|
68
|
+
print(colorize(` 请收集需求,生成结构化需求表格到 ${path.join(projectRoot, INCSPEC_DIR, DIRS.requirements)}`, colors.dim));
|
|
68
69
|
print('');
|
|
69
70
|
print(colorize('该命令将交互式收集需求,生成 5 列结构化表格:', colors.dim));
|
|
70
71
|
print(colorize(' | 新增/修改功能 | 涉及UI组件 | 触发条件 | 影响的核心状态 | 预期数据流向 |', colors.dim));
|
|
@@ -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/design.mjs
CHANGED
|
@@ -102,13 +102,13 @@ export async function designCommand(ctx) {
|
|
|
102
102
|
print('');
|
|
103
103
|
print(colorize(` /incspec/inc-design --feature=${featureName}`, colors.bold, colors.white));
|
|
104
104
|
print('');
|
|
105
|
-
print(colorize('
|
|
105
|
+
print(colorize('或在 Claude Code 中使用 inc-spec-skill 技能:', colors.cyan));
|
|
106
106
|
print('');
|
|
107
107
|
const baselinePath = path.join(projectRoot, INCSPEC_DIR, DIRS.baselines, latestBaseline);
|
|
108
108
|
const reqPath = path.join(projectRoot, INCSPEC_DIR, DIRS.requirements, 'structured-requirements.md');
|
|
109
109
|
const depPath = path.join(projectRoot, INCSPEC_DIR, DIRS.requirements, 'ui-dependencies.md');
|
|
110
110
|
const outDir = path.join(projectRoot, INCSPEC_DIR, DIRS.increments);
|
|
111
|
-
print(colorize(`
|
|
111
|
+
print(colorize(` 请基于基线 ${latestBaseline} 和需求/依赖文件,设计增量方案到 ${outDir}`, colors.dim));
|
|
112
112
|
print('');
|
|
113
113
|
print(colorize('该命令将生成包含 7 大模块的增量设计蓝图:', colors.dim));
|
|
114
114
|
print(colorize(' 1. 一句话摘要', colors.dim));
|
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,19 +111,27 @@ 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
|
},
|
|
120
|
-
|
|
121
|
-
usage: 'incspec
|
|
122
|
-
aliases: ['
|
|
123
|
-
description: '
|
|
121
|
+
reset: {
|
|
122
|
+
usage: 'incspec reset',
|
|
123
|
+
aliases: ['rs'],
|
|
124
|
+
description: '重置当前工作流,归档已有产出',
|
|
125
|
+
},
|
|
126
|
+
sync: {
|
|
127
|
+
usage: 'incspec sync [--cursor] [--claude] [--all] [--project|--global]',
|
|
128
|
+
aliases: ['s'],
|
|
129
|
+
description: '同步集成到 IDE/AI 工具 (Cursor, Claude Code)',
|
|
124
130
|
options: [
|
|
125
|
-
['--
|
|
131
|
+
['--cursor', '仅同步 Cursor 命令'],
|
|
132
|
+
['--claude', '仅同步 Claude Code Skill'],
|
|
133
|
+
['--all', '同步所有目标'],
|
|
134
|
+
['--project', '同步到当前目录'],
|
|
126
135
|
['--global', '同步到全局目录'],
|
|
127
136
|
],
|
|
128
137
|
},
|
|
@@ -158,7 +167,7 @@ export async function helpCommand(ctx = {}) {
|
|
|
158
167
|
* Show general help
|
|
159
168
|
*/
|
|
160
169
|
function showGeneralHelp() {
|
|
161
|
-
print(colorize('
|
|
170
|
+
print(colorize(' IncSpec - 增量规范驱动开发工具', colors.bold, colors.cyan));
|
|
162
171
|
print(colorize(' ────────────────────────────', colors.dim));
|
|
163
172
|
print('');
|
|
164
173
|
print(colorize('用法:', colors.bold));
|
|
@@ -167,7 +176,7 @@ function showGeneralHelp() {
|
|
|
167
176
|
|
|
168
177
|
print(colorize('工作流命令:', colors.bold));
|
|
169
178
|
print('');
|
|
170
|
-
|
|
179
|
+
|
|
171
180
|
const workflowCommands = ['analyze', 'collect-req', 'collect-dep', 'design', 'apply', 'merge'];
|
|
172
181
|
workflowCommands.forEach((cmd, index) => {
|
|
173
182
|
const def = COMMANDS[cmd];
|
|
@@ -180,7 +189,7 @@ function showGeneralHelp() {
|
|
|
180
189
|
print(colorize('管理命令:', colors.bold));
|
|
181
190
|
print('');
|
|
182
191
|
|
|
183
|
-
const mgmtCommands = ['init', 'update', 'status', 'list', 'validate', 'archive', '
|
|
192
|
+
const mgmtCommands = ['init', 'update', 'status', 'list', 'validate', 'archive', 'reset', 'sync', 'help'];
|
|
184
193
|
mgmtCommands.forEach(cmd => {
|
|
185
194
|
const def = COMMANDS[cmd];
|
|
186
195
|
const aliases = def.aliases ? colorize(` (${def.aliases.join(', ')})`, colors.dim) : '';
|
|
@@ -198,7 +207,7 @@ function showGeneralHelp() {
|
|
|
198
207
|
print(colorize(' incspec update # 更新模板文件', colors.dim));
|
|
199
208
|
print(colorize(' incspec analyze src/views/Home # 分析代码流程', colors.dim));
|
|
200
209
|
print(colorize(' incspec status # 查看工作流状态', colors.dim));
|
|
201
|
-
print(colorize(' incspec
|
|
210
|
+
print(colorize(' incspec sync # 同步 IDE 集成', colors.dim));
|
|
202
211
|
print('');
|
|
203
212
|
print(colorize(`运行 'incspec help <command>' 查看命令详情。`, colors.dim));
|
|
204
213
|
print('');
|