@localsummer/incspec 0.0.4 → 0.0.6
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 +19 -0
- package/commands/analyze.mjs +95 -0
- package/commands/help.mjs +2 -1
- package/package.json +1 -1
- package/templates/AGENTS.md +5 -2
- package/templates/cursor-commands/analyze-codeflow.md +29 -13
- package/templates/cursor-commands/analyze-increment-codeflow.md +4 -4
- package/templates/cursor-commands/merge-to-baseline.md +4 -4
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
# IncSpec
|
|
12
12
|
|
|
13
|
+

|
|
14
|
+
|
|
13
15
|
IncSpec 通过**增量规范驱动开发**让人类与 AI 编程助手保持一致 - 这是一个 6+1 步工作流(6 步开发 + 归档),在修改代码前先捕获代码流程基线。**无需 API 密钥。**
|
|
14
16
|
|
|
15
17
|
## 为什么选择 IncSpec?
|
|
@@ -89,6 +91,8 @@ AI 编程助手在处理复杂前端代码库时常常力不从心,因为 API
|
|
|
89
91
|
└───────────┘
|
|
90
92
|
```
|
|
91
93
|
|
|
94
|
+
> **提示**: 如果已有基准报告,可使用 `incspec analyze --baseline=<file>` 直接跳过分析步骤,快速进入后续工作流。
|
|
95
|
+
|
|
92
96
|
## 快速开始
|
|
93
97
|
|
|
94
98
|
### 支持的 AI 工具
|
|
@@ -124,6 +128,9 @@ AI 编程助手在处理复杂前端代码库时常常力不从心,因为 API
|
|
|
124
128
|
#### 步骤 1:安装 CLI
|
|
125
129
|
|
|
126
130
|
```bash
|
|
131
|
+
# 从 Npm 安装(推荐)
|
|
132
|
+
npm install -g @localsummer/incspec
|
|
133
|
+
|
|
127
134
|
# 从 GitHub 克隆并安装
|
|
128
135
|
git clone https://github.com/localSummer/IncSpec.git
|
|
129
136
|
cd IncSpec
|
|
@@ -186,6 +193,17 @@ $ incspec status # 检查当前工作流状态
|
|
|
186
193
|
$ incspec analyze src/views/Home --complete # 标记步骤 1 完成
|
|
187
194
|
```
|
|
188
195
|
|
|
196
|
+
**使用现有基准报告** (跳过分析):
|
|
197
|
+
|
|
198
|
+
如果已有基准报告文件,可直接使用,跳过分析步骤:
|
|
199
|
+
```bash
|
|
200
|
+
$ incspec analyze --baseline=home-baseline-v1.md # 直接使用现有基准报告
|
|
201
|
+
```
|
|
202
|
+
- 自动搜索 `baselines/` 和 `archives/` 目录
|
|
203
|
+
- 若文件在归档目录,自动移动到 `baselines/` 目录
|
|
204
|
+
- 模块名自动从文件名推断 (`xxx-baseline-vN.md` -> `xxx`)
|
|
205
|
+
- 可通过 `--module` 覆盖模块名
|
|
206
|
+
|
|
189
207
|
#### 2. 收集结构化需求
|
|
190
208
|
|
|
191
209
|
定义你想要的变更:
|
|
@@ -422,6 +440,7 @@ incspec help <command> # 显示特定命令帮助
|
|
|
422
440
|
incspec analyze <source-path> [--module=name] # 别名:a
|
|
423
441
|
incspec a src/views/Home --module=home
|
|
424
442
|
incspec analyze src/views/Home --complete -o baselines/home-baseline-v1.md
|
|
443
|
+
incspec analyze --baseline=home-baseline-v1.md # 使用现有基准(自动从归档恢复)
|
|
425
444
|
|
|
426
445
|
# 步骤 2:收集结构化需求
|
|
427
446
|
incspec collect-req # 别名:cr
|
package/commands/analyze.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,
|
|
@@ -32,6 +33,49 @@ import {
|
|
|
32
33
|
|
|
33
34
|
const STEP_NUMBER = 1;
|
|
34
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Search for a file in the archives directory
|
|
38
|
+
* @param {string} projectRoot - Project root path
|
|
39
|
+
* @param {string} fileName - File name to search
|
|
40
|
+
* @returns {string|null} - Full path if found, null otherwise
|
|
41
|
+
*/
|
|
42
|
+
function findInArchives(projectRoot, fileName) {
|
|
43
|
+
const archivesDir = path.join(projectRoot, INCSPEC_DIR, DIRS.archives);
|
|
44
|
+
if (!fs.existsSync(archivesDir)) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Recursive search: archives/ -> YYYY-MM/ -> [module/] -> files
|
|
49
|
+
const monthDirs = fs.readdirSync(archivesDir, { withFileTypes: true })
|
|
50
|
+
.filter(d => d.isDirectory())
|
|
51
|
+
.map(d => d.name)
|
|
52
|
+
.sort()
|
|
53
|
+
.reverse(); // Prioritize recent months
|
|
54
|
+
|
|
55
|
+
for (const month of monthDirs) {
|
|
56
|
+
const monthPath = path.join(archivesDir, month);
|
|
57
|
+
|
|
58
|
+
// Check files directly in month directory
|
|
59
|
+
const directPath = path.join(monthPath, fileName);
|
|
60
|
+
if (fs.existsSync(directPath)) {
|
|
61
|
+
return directPath;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Check module subdirectories
|
|
65
|
+
const subDirs = fs.readdirSync(monthPath, { withFileTypes: true })
|
|
66
|
+
.filter(d => d.isDirectory());
|
|
67
|
+
|
|
68
|
+
for (const subDir of subDirs) {
|
|
69
|
+
const subPath = path.join(monthPath, subDir.name, fileName);
|
|
70
|
+
if (fs.existsSync(subPath)) {
|
|
71
|
+
return subPath;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
35
79
|
/**
|
|
36
80
|
* Execute analyze command
|
|
37
81
|
* @param {Object} ctx - Command context
|
|
@@ -42,6 +86,57 @@ export async function analyzeCommand(ctx) {
|
|
|
42
86
|
// Ensure initialized
|
|
43
87
|
const projectRoot = ensureInitialized(cwd);
|
|
44
88
|
|
|
89
|
+
// Handle --baseline option: use existing baseline report
|
|
90
|
+
if (options.baseline) {
|
|
91
|
+
const baselineFile = typeof options.baseline === 'string' ? options.baseline : '';
|
|
92
|
+
if (!baselineFile) {
|
|
93
|
+
printError('请指定基准报告文件名');
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const baselinesDir = path.join(projectRoot, INCSPEC_DIR, DIRS.baselines);
|
|
98
|
+
const baselinePath = path.join(baselinesDir, baselineFile);
|
|
99
|
+
let fromArchive = false;
|
|
100
|
+
|
|
101
|
+
// 1. First check baselines directory
|
|
102
|
+
if (!fs.existsSync(baselinePath)) {
|
|
103
|
+
// 2. Search in archives directory
|
|
104
|
+
const archivePath = findInArchives(projectRoot, baselineFile);
|
|
105
|
+
if (!archivePath) {
|
|
106
|
+
printError(`基准文件不存在: ${baselineFile}`);
|
|
107
|
+
printInfo('已搜索 baselines/ 和 archives/ 目录');
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// 3. Move to baselines directory
|
|
112
|
+
fs.renameSync(archivePath, baselinePath);
|
|
113
|
+
fromArchive = true;
|
|
114
|
+
printInfo(`已从归档恢复: ${path.relative(projectRoot, archivePath)}`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Infer module name from filename (xxx-baseline-vN.md -> xxx)
|
|
118
|
+
let moduleName = typeof options.module === 'string' ? options.module : '';
|
|
119
|
+
if (!moduleName) {
|
|
120
|
+
const match = baselineFile.match(/^(.+)-baseline-v\d+\.md$/);
|
|
121
|
+
moduleName = match ? match[1] : path.basename(baselineFile, '.md');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Handle workflow state
|
|
125
|
+
let workflow = readWorkflow(projectRoot);
|
|
126
|
+
if (!workflow?.currentWorkflow) {
|
|
127
|
+
const workflowName = typeof options.workflow === 'string' ? options.workflow : `analyze-${moduleName}`;
|
|
128
|
+
workflow = startWorkflow(projectRoot, workflowName);
|
|
129
|
+
printSuccess(`已创建新工作流: ${workflowName}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Mark step as completed
|
|
133
|
+
updateStep(projectRoot, STEP_NUMBER, STATUS.COMPLETED, baselineFile);
|
|
134
|
+
print('');
|
|
135
|
+
printSuccess(`已使用现有基准报告: ${baselineFile}`);
|
|
136
|
+
printInfo(`运行 'incspec status' 查看进度`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
45
140
|
// Get source path
|
|
46
141
|
let sourcePath = args[0];
|
|
47
142
|
if (!sourcePath) {
|
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]',
|
|
37
|
+
usage: 'incspec analyze <source-path> [--module=name] [--baseline=file]',
|
|
38
38
|
aliases: ['a'],
|
|
39
39
|
description: '步骤1: 分析代码流程,生成基线快照',
|
|
40
40
|
options: [
|
|
41
41
|
['-m, --module=<name>', '指定模块名称'],
|
|
42
42
|
['-w, --workflow=<name>', '指定工作流名称(避免交互提示)'],
|
|
43
|
+
['-b, --baseline=<file>', '使用现有基准报告(自动从归档恢复)'],
|
|
43
44
|
['--complete', '标记步骤完成'],
|
|
44
45
|
['-o, --output=<file>', '完成时指定输出文件'],
|
|
45
46
|
],
|
package/package.json
CHANGED
package/templates/AGENTS.md
CHANGED
|
@@ -41,10 +41,13 @@ AI 编码助手使用 IncSpec 进行增量规格驱动开发的操作指南。
|
|
|
41
41
|
|
|
42
42
|
### 步骤 1: 分析代码工作流
|
|
43
43
|
|
|
44
|
-
**命令**: `incspec analyze <source-path> [--module=name]`
|
|
44
|
+
**命令**: `incspec analyze <source-path> [--module=name] [--baseline=file]`
|
|
45
45
|
|
|
46
46
|
**目的**: 生成包含 API 调用时序图和依赖关系图的基线快照。
|
|
47
47
|
|
|
48
|
+
**选项**:
|
|
49
|
+
- `--baseline=<file>`: 使用现有基准报告,自动从 baselines/ 或 archives/ 目录恢复
|
|
50
|
+
|
|
48
51
|
**输出**: `incspec/baselines/{module}-baseline-v{n}.md`
|
|
49
52
|
|
|
50
53
|
**关键交付物**:
|
|
@@ -215,7 +218,7 @@ incspec list -l # 长格式(含时间戳)
|
|
|
215
218
|
incspec list -a # 包含归档
|
|
216
219
|
|
|
217
220
|
# 6步工作流
|
|
218
|
-
incspec analyze <path> [--module=name]
|
|
221
|
+
incspec analyze <path> [--module=name] [--baseline=file] # 步骤1: 基线分析
|
|
219
222
|
incspec collect-req / cr # 步骤2: 需求收集
|
|
220
223
|
incspec collect-dep / cd # 步骤3: 依赖收集
|
|
221
224
|
incspec design [--feature=name] / d # 步骤4: 增量设计
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 分析代码工作流,生成带编号的API调用时序图、依赖关系图和依赖总结
|
|
3
|
-
argument-hint: <
|
|
3
|
+
argument-hint: <source-path> [target-dir]
|
|
4
4
|
allowed-tools: Glob, Grep, Read, Write, Bash
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -9,17 +9,33 @@ allowed-tools: Glob, Grep, Read, Write, Bash
|
|
|
9
9
|
在开始分析前,先用 Bash 执行:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
incspec analyze <
|
|
12
|
+
incspec analyze <source-path> --module=<module> --workflow=analyze-<module>
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
完成报告写入后,再用 Bash 执行:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
incspec analyze <
|
|
18
|
+
incspec analyze <source-path> --module=<module> --workflow=analyze-<module> --complete --output=<output-file>
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
**使用现有基准报告** (跳过分析):
|
|
22
|
+
|
|
23
|
+
若已有基准报告文件,可直接使用:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
incspec analyze --baseline=<baseline-file> [--module=<module>] [--workflow=<workflow>]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
说明:
|
|
30
|
+
- `<baseline-file>` 文件名,自动搜索 baselines/ 和 archives/ 目录
|
|
31
|
+
- 若文件在归档目录,自动移动到 baselines/ 目录
|
|
32
|
+
- `<module>` 默认从文件名推断 (xxx-baseline-vN.md -> xxx)
|
|
33
|
+
- `<workflow>` 默认为 analyze-<module>
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
21
37
|
说明:
|
|
22
|
-
- `<module>` 默认为
|
|
38
|
+
- `<module>` 默认为 source-path 最后一级目录名,若用户显式指定模块名则使用该值
|
|
23
39
|
- `<output-file>` 必须与最终写入的文件名一致
|
|
24
40
|
- 若 incspec 提示未初始化,请先运行 `incspec init`
|
|
25
41
|
|
|
@@ -29,19 +45,19 @@ incspec analyze <source_path> --module=<module> --workflow=analyze-<module> --co
|
|
|
29
45
|
|
|
30
46
|
你需要完成以下任务:
|
|
31
47
|
|
|
32
|
-
1. **代码分析**:检查
|
|
48
|
+
1. **代码分析**:检查 source-path 目录下的所有组件和Store文件,识别初始化阶段的API调用
|
|
33
49
|
2. **时序图绘制**:构建带编号的API调用时序图,展示调用顺序
|
|
34
50
|
3. **依赖图绘制**:构建带编号的API依赖关系图,展示依赖关系
|
|
35
51
|
4. **依赖总结**:生成带编号的依赖关系文字总结
|
|
36
|
-
5. **Markdown输出**:将分析结果输出到
|
|
52
|
+
5. **Markdown输出**:将分析结果输出到 target-dir 目录
|
|
37
53
|
|
|
38
54
|
**重要提示**:默认情况下,只输出上述核心分析内容。只有在用户明确要求提供"潜在问题与优化建议"时,才在文档末尾添加该部分内容。
|
|
39
55
|
|
|
40
56
|
## 输出配置
|
|
41
57
|
|
|
42
|
-
- **
|
|
58
|
+
- **target-dir**: 报告输出目录,默认 `incspec/baselines`
|
|
43
59
|
- **文件命名**: `{module}-baseline-v{n}.md`
|
|
44
|
-
- `{module}`: 模块名称,从
|
|
60
|
+
- `{module}`: 模块名称,从 source-path 的最后一级目录名推断,或由用户指定
|
|
45
61
|
- `{n}`: 版本号,扫描目标目录中同名前缀的文件,取最大版本号+1,若无则为 1
|
|
46
62
|
- **示例**: 分析 `src/views/resume` 目录,输出 `incspec/baselines/resume-baseline-v1.md`
|
|
47
63
|
|
|
@@ -69,7 +85,7 @@ incspec analyze <source_path> --module=<module> --workflow=analyze-<module> --co
|
|
|
69
85
|
|
|
70
86
|
### 第一步:代码扫描
|
|
71
87
|
|
|
72
|
-
- 使用 Glob 工具扫描
|
|
88
|
+
- 使用 Glob 工具扫描 source-path 目录下的所有文件
|
|
73
89
|
- 关注文件类型:
|
|
74
90
|
- 组件文件(.jsx, .tsx, .js, .ts)
|
|
75
91
|
- Store文件(Zustand, MobX等)
|
|
@@ -116,7 +132,7 @@ incspec analyze <source_path> --module=<module> --workflow=analyze-<module> --co
|
|
|
116
132
|
# [模块名称] API工作流分析
|
|
117
133
|
|
|
118
134
|
**分析时间**: [自动生成的时间戳]
|
|
119
|
-
**分析范围**: [
|
|
135
|
+
**分析范围**: [source-path的相对路径或绝对路径]
|
|
120
136
|
|
|
121
137
|
## 概述
|
|
122
138
|
|
|
@@ -271,8 +287,8 @@ graph TD
|
|
|
271
287
|
|
|
272
288
|
## 工作流程
|
|
273
289
|
|
|
274
|
-
1. **确认路径**:验证
|
|
275
|
-
2. **生成元信息**:记录分析时间(使用当前时间戳)和分析范围(
|
|
290
|
+
1. **确认路径**:验证 source-path 和 target-dir 的有效性
|
|
291
|
+
2. **生成元信息**:记录分析时间(使用当前时间戳)和分析范围(source-path)
|
|
276
292
|
3. **扫描目录**:使用 Glob 工具获取所有相关文件
|
|
277
293
|
4. **分析文件**:使用 Read 工具逐个分析文件中的API调用
|
|
278
294
|
5. **构建模型**:在内存中构建完整的API调用关系模型
|
|
@@ -280,7 +296,7 @@ graph TD
|
|
|
280
296
|
7. **生成图表**:使用Mermaid语法创建带编号的可视化图表
|
|
281
297
|
8. **编写文档**:按照规范格式生成Markdown文档(包含元信息和三个核心部分)
|
|
282
298
|
9. **可选增强**:仅当用户明确要求时,在文档末尾添加"潜在问题与优化建议"部分
|
|
283
|
-
10. **保存输出**:使用 Write 工具保存到
|
|
299
|
+
10. **保存输出**:使用 Write 工具保存到 target-dir
|
|
284
300
|
|
|
285
301
|
## 质量标准
|
|
286
302
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 基于现状、需求和依赖,生成增量需求的设计蓝图(时序、依赖、文件变更),指导代码生成
|
|
3
|
-
argument-hint: [
|
|
3
|
+
argument-hint: [baseline-snapshot-path] [structured-requirements-path] [ui-dependencies-path] [report-output-dir]
|
|
4
4
|
allowed-tools: Glob, Grep, Read, Write, Bash
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -31,9 +31,9 @@ incspec design --feature=<feature> --complete --output=<output-file>
|
|
|
31
31
|
|
|
32
32
|
接收以下三份材料(由用户提供或从指定文件读取):
|
|
33
33
|
|
|
34
|
-
1.
|
|
35
|
-
2.
|
|
36
|
-
3. **
|
|
34
|
+
1. **baseline-snapshot-path** (来自 `analyze-codeflow`): 包含 S1~Sxx 时序编号、Dxx 依赖节点、Rxx 关系总结
|
|
35
|
+
2. **structured-requirements-path** (来自 `structured-requirements-collection`): 包含新增/修改功能、触发条件、核心状态、数据流向的 5 列表格
|
|
36
|
+
3. **ui-dependencies-path** (来自 `ui-dependency-collection`): 包含依赖类型、来源路径、变更类型的依赖详情表
|
|
37
37
|
|
|
38
38
|
# 执行流程
|
|
39
39
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: 将增量需求报告融合为新的代码流基线快照
|
|
3
|
-
argument-hint: <increment-report-path> [baseline-output-
|
|
3
|
+
argument-hint: <increment-report-path> [baseline-output-dir]
|
|
4
4
|
allowed-tools: Read, Write, Bash
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -38,7 +38,7 @@ incspec merge <increment-report-path> --complete --output=<output-file>
|
|
|
38
38
|
# 输入参数
|
|
39
39
|
|
|
40
40
|
1. **increment-report-path** (必填): 增量需求融合快照报告的完整路径(如 increment-codeflow-v2.md)
|
|
41
|
-
2. **baseline-output-
|
|
41
|
+
2. **baseline-output-dir** (可选): 新基线报告的输出路径,默认为 `<原文件名>-baseline.md`
|
|
42
42
|
|
|
43
43
|
# 执行流程
|
|
44
44
|
|
|
@@ -202,7 +202,7 @@ D3_DEL (删除) -> 已移除
|
|
|
202
202
|
- 新基线总节点: N 个
|
|
203
203
|
|
|
204
204
|
📁 输出文件:
|
|
205
|
-
✓ <baseline-output-
|
|
205
|
+
✓ <baseline-output-dir>
|
|
206
206
|
|
|
207
207
|
🔄 下一步操作:
|
|
208
208
|
1. 检查新基线报告的完整性
|
|
@@ -268,7 +268,7 @@ D3_DEL (删除) -> 已移除
|
|
|
268
268
|
|
|
269
269
|
## 输出目录
|
|
270
270
|
|
|
271
|
-
- **baseline-output-
|
|
271
|
+
- **baseline-output-dir**: 默认为 `incspec/baselines`
|
|
272
272
|
- 如目录不存在,需主动创建
|
|
273
273
|
|
|
274
274
|
## 文件命名
|