@localsummer/incspec 0.0.5 → 0.0.7

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/lib/terminal.mjs CHANGED
@@ -241,6 +241,88 @@ export async function select({ message, choices }) {
241
241
  });
242
242
  }
243
243
 
244
+ /**
245
+ * Interactive checkbox (multi-select) prompt
246
+ * @param {Object} options
247
+ * @param {string} options.message
248
+ * @param {Array<{name: string, value: any, checked?: boolean}>} options.choices
249
+ * @returns {Promise<any[]>}
250
+ */
251
+ export async function checkbox({ message, choices }) {
252
+ return new Promise((resolve) => {
253
+ let cursor = 0;
254
+ const selected = choices.map(c => c.checked || false);
255
+
256
+ const rl = readline.createInterface({
257
+ input: process.stdin,
258
+ output: process.stdout,
259
+ });
260
+
261
+ if (process.stdin.isTTY) {
262
+ process.stdin.setRawMode(true);
263
+ }
264
+ readline.emitKeypressEvents(process.stdin, rl);
265
+
266
+ const render = () => {
267
+ process.stdout.write('\x1b[2J\x1b[H');
268
+
269
+ console.log(colorize(message, colors.bold, colors.cyan));
270
+ console.log(colorize('(space: toggle, a: toggle all, enter: confirm)', colors.dim));
271
+ console.log();
272
+
273
+ choices.forEach((choice, index) => {
274
+ const isCursor = cursor === index;
275
+ const isSelected = selected[index];
276
+ const pointer = isCursor ? colorize('>', colors.cyan) : ' ';
277
+ const check = isSelected ? colorize('[x]', colors.green) : '[ ]';
278
+ const name = isCursor ? colorize(choice.name, colors.bold) : choice.name;
279
+
280
+ console.log(`${pointer} ${check} ${name}`);
281
+ });
282
+ };
283
+
284
+ const cleanup = () => {
285
+ if (process.stdin.isTTY) {
286
+ process.stdin.setRawMode(false);
287
+ }
288
+ rl.close();
289
+ };
290
+
291
+ const handleKeypress = (str, key) => {
292
+ if (!key) return;
293
+
294
+ if (key.name === 'up' || key.name === 'k') {
295
+ cursor = cursor > 0 ? cursor - 1 : choices.length - 1;
296
+ render();
297
+ } else if (key.name === 'down' || key.name === 'j') {
298
+ cursor = cursor < choices.length - 1 ? cursor + 1 : 0;
299
+ render();
300
+ } else if (key.name === 'space') {
301
+ selected[cursor] = !selected[cursor];
302
+ render();
303
+ } else if (str === 'a') {
304
+ const allSelected = selected.every(s => s);
305
+ selected.fill(!allSelected);
306
+ render();
307
+ } else if (key.name === 'return') {
308
+ cleanup();
309
+ process.stdin.removeListener('keypress', handleKeypress);
310
+ process.stdout.write('\x1b[2J\x1b[H');
311
+ const result = choices.filter((_, i) => selected[i]).map(c => c.value);
312
+ resolve(result);
313
+ } else if (key.name === 'escape' || (key.ctrl && key.name === 'c')) {
314
+ cleanup();
315
+ process.stdin.removeListener('keypress', handleKeypress);
316
+ process.stdout.write('\x1b[2J\x1b[H');
317
+ process.exit(0);
318
+ }
319
+ };
320
+
321
+ process.stdin.on('keypress', handleKeypress);
322
+ render();
323
+ });
324
+ }
325
+
244
326
  /**
245
327
  * Format a table for terminal output
246
328
  * @param {string[]} headers
@@ -290,3 +372,29 @@ export function spinner(message) {
290
372
  }
291
373
  };
292
374
  }
375
+
376
+ /**
377
+ * Format date to local datetime string
378
+ * @param {Date} date - Date object
379
+ * @returns {string} Format: YYYY-MM-DD HH:mm
380
+ */
381
+ export function formatLocalDateTime(date) {
382
+ const year = date.getFullYear();
383
+ const month = String(date.getMonth() + 1).padStart(2, '0');
384
+ const day = String(date.getDate()).padStart(2, '0');
385
+ const hours = String(date.getHours()).padStart(2, '0');
386
+ const minutes = String(date.getMinutes()).padStart(2, '0');
387
+ return `${year}-${month}-${day} ${hours}:${minutes}`;
388
+ }
389
+
390
+ /**
391
+ * Format date to local date string
392
+ * @param {Date} date - Date object
393
+ * @returns {string} Format: YYYY-MM-DD
394
+ */
395
+ export function formatLocalDate(date) {
396
+ const year = date.getFullYear();
397
+ const month = String(date.getMonth() + 1).padStart(2, '0');
398
+ const day = String(date.getDate()).padStart(2, '0');
399
+ return `${year}-${month}-${day}`;
400
+ }
package/lib/workflow.mjs CHANGED
@@ -8,6 +8,7 @@
8
8
  import * as fs from 'fs';
9
9
  import * as path from 'path';
10
10
  import { INCSPEC_DIR, FILES, getTemplatesDir } from './config.mjs';
11
+ import { formatLocalDateTime } from './terminal.mjs';
11
12
 
12
13
  /** Workflow steps definition */
13
14
  export const STEPS = [
@@ -211,7 +212,7 @@ export function readWorkflow(projectRoot) {
211
212
  * @returns {string}
212
213
  */
213
214
  export function generateWorkflowContent(workflow) {
214
- const now = new Date().toISOString().replace('T', ' ').slice(0, 16);
215
+ const now = formatLocalDateTime(new Date());
215
216
 
216
217
  const lines = [
217
218
  '# Workflow Status',
@@ -292,7 +293,7 @@ export function initWorkflow(projectRoot) {
292
293
  */
293
294
  function generateInitialWorkflowContent() {
294
295
  const templatePath = path.join(getTemplatesDir(), 'WORKFLOW.md');
295
- const now = new Date().toISOString().replace('T', ' ').slice(0, 16);
296
+ const now = formatLocalDateTime(new Date());
296
297
 
297
298
  if (fs.existsSync(templatePath)) {
298
299
  let content = fs.readFileSync(templatePath, 'utf-8');
@@ -324,7 +325,7 @@ function generateInitialWorkflowContent() {
324
325
  * @returns {Object}
325
326
  */
326
327
  export function startWorkflow(projectRoot, workflowName) {
327
- const now = new Date().toISOString().replace('T', ' ').slice(0, 16);
328
+ const now = formatLocalDateTime(new Date());
328
329
  let workflow = readWorkflow(projectRoot);
329
330
 
330
331
  if (!workflow) {
@@ -381,7 +382,7 @@ export function updateStep(projectRoot, stepNumber, status, outputFile = null) {
381
382
  throw new Error(`无效的步骤编号: ${stepNumber}`);
382
383
  }
383
384
 
384
- const now = new Date().toISOString().replace('T', ' ').slice(0, 16);
385
+ const now = formatLocalDateTime(new Date());
385
386
  const normalizedOutput = normalizeOutputName(outputFile);
386
387
 
387
388
  workflow.steps[index] = {
@@ -411,7 +412,7 @@ export function completeWorkflow(projectRoot) {
411
412
  throw new Error('工作流未初始化');
412
413
  }
413
414
 
414
- const now = new Date().toISOString().replace('T', ' ').slice(0, 16);
415
+ const now = formatLocalDateTime(new Date());
415
416
 
416
417
  // Add to history
417
418
  workflow.history.unshift({
@@ -440,7 +441,7 @@ export function archiveWorkflow(projectRoot) {
440
441
  throw new Error('工作流未初始化');
441
442
  }
442
443
 
443
- const now = new Date().toISOString().replace('T', ' ').slice(0, 16);
444
+ const now = formatLocalDateTime(new Date());
444
445
 
445
446
  workflow.history.unshift({
446
447
  name: workflow.currentWorkflow,
@@ -549,7 +550,7 @@ export function addToHistory(projectRoot, entry) {
549
550
  };
550
551
  }
551
552
 
552
- const now = new Date().toISOString().replace('T', ' ').slice(0, 16);
553
+ const now = formatLocalDateTime(new Date());
553
554
 
554
555
  workflow.history.unshift({
555
556
  name: entry.name,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@localsummer/incspec",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "面向 AI 编程助手的增量规范驱动开发工具",
5
5
  "bin": {
6
6
  "incspec": "index.mjs"
@@ -234,9 +234,12 @@ incspec archive <file> # 归档指定文件
234
234
  incspec archive <file> --keep # 复制而非移动
235
235
 
236
236
  # IDE 集成
237
- incspec cursor-sync # 同步 Cursor 斜杠命令
238
- incspec cursor-sync --project # 同步到项目目录
239
- incspec cursor-sync --global # 同步到全局目录
237
+ incspec sync # 交互式选择同步目标
238
+ incspec sync --cursor # 同步 Cursor 斜杠命令
239
+ incspec sync --claude # 同步 Claude Code Skill
240
+ incspec sync --all # 同步全部
241
+ incspec sync --global # 同步到全局目录
242
+ incspec sync --project # 同步到当前目录
240
243
 
241
244
  # 帮助
242
245
  incspec help [command] # 显示帮助
@@ -245,7 +248,7 @@ incspec --version / -v # 显示版本
245
248
 
246
249
  ### Cursor 斜杠命令
247
250
 
248
- 运行 `incspec cursor-sync` 后,以下命令可用:
251
+ 运行 `incspec sync --cursor` 后,以下命令可用:
249
252
 
250
253
  | 命令 | 步骤 | 描述 |
251
254
  |------|------|------|
@@ -585,7 +588,7 @@ incspec status
585
588
  incspec status # 我在哪里?
586
589
  incspec list # 有什么?
587
590
  incspec validate --strict # 是否正确?
588
- incspec cursor-sync # 设置IDE命令
591
+ incspec sync # 设置IDE命令
589
592
  ```
590
593
 
591
594
  ## 与AI助手集成
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: 分析代码工作流,生成带编号的API调用时序图、依赖关系图和依赖总结
3
- argument-hint: <source_path> [target_path]
3
+ argument-hint: <source-path> [target-dir]
4
4
  allowed-tools: Glob, Grep, Read, Write, Bash
5
5
  ---
6
6
 
@@ -9,13 +9,13 @@ allowed-tools: Glob, Grep, Read, Write, Bash
9
9
  在开始分析前,先用 Bash 执行:
10
10
 
11
11
  ```bash
12
- incspec analyze <source_path> --module=<module> --workflow=analyze-<module>
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 <source_path> --module=<module> --workflow=analyze-<module> --complete --output=<output-file>
18
+ incspec analyze <source-path> --module=<module> --workflow=analyze-<module> --complete --output=<output-file>
19
19
  ```
20
20
 
21
21
  **使用现有基准报告** (跳过分析):
@@ -35,7 +35,7 @@ incspec analyze --baseline=<baseline-file> [--module=<module>] [--workflow=<work
35
35
  ---
36
36
 
37
37
  说明:
38
- - `<module>` 默认为 source_path 最后一级目录名,若用户显式指定模块名则使用该值
38
+ - `<module>` 默认为 source-path 最后一级目录名,若用户显式指定模块名则使用该值
39
39
  - `<output-file>` 必须与最终写入的文件名一致
40
40
  - 若 incspec 提示未初始化,请先运行 `incspec init`
41
41
 
@@ -45,19 +45,19 @@ incspec analyze --baseline=<baseline-file> [--module=<module>] [--workflow=<work
45
45
 
46
46
  你需要完成以下任务:
47
47
 
48
- 1. **代码分析**:检查 source_path 目录下的所有组件和Store文件,识别初始化阶段的API调用
48
+ 1. **代码分析**:检查 source-path 目录下的所有组件和Store文件,识别初始化阶段的API调用
49
49
  2. **时序图绘制**:构建带编号的API调用时序图,展示调用顺序
50
50
  3. **依赖图绘制**:构建带编号的API依赖关系图,展示依赖关系
51
51
  4. **依赖总结**:生成带编号的依赖关系文字总结
52
- 5. **Markdown输出**:将分析结果输出到 target_path 目录
52
+ 5. **Markdown输出**:将分析结果输出到 target-dir 目录
53
53
 
54
54
  **重要提示**:默认情况下,只输出上述核心分析内容。只有在用户明确要求提供"潜在问题与优化建议"时,才在文档末尾添加该部分内容。
55
55
 
56
56
  ## 输出配置
57
57
 
58
- - **target_path**: 报告输出目录,默认 `incspec/baselines`
58
+ - **target-dir**: 报告输出目录,默认 `incspec/baselines`
59
59
  - **文件命名**: `{module}-baseline-v{n}.md`
60
- - `{module}`: 模块名称,从 source_path 的最后一级目录名推断,或由用户指定
60
+ - `{module}`: 模块名称,从 source-path 的最后一级目录名推断,或由用户指定
61
61
  - `{n}`: 版本号,扫描目标目录中同名前缀的文件,取最大版本号+1,若无则为 1
62
62
  - **示例**: 分析 `src/views/resume` 目录,输出 `incspec/baselines/resume-baseline-v1.md`
63
63
 
@@ -85,7 +85,7 @@ incspec analyze --baseline=<baseline-file> [--module=<module>] [--workflow=<work
85
85
 
86
86
  ### 第一步:代码扫描
87
87
 
88
- - 使用 Glob 工具扫描 source_path 目录下的所有文件
88
+ - 使用 Glob 工具扫描 source-path 目录下的所有文件
89
89
  - 关注文件类型:
90
90
  - 组件文件(.jsx, .tsx, .js, .ts)
91
91
  - Store文件(Zustand, MobX等)
@@ -132,7 +132,7 @@ incspec analyze --baseline=<baseline-file> [--module=<module>] [--workflow=<work
132
132
  # [模块名称] API工作流分析
133
133
 
134
134
  **分析时间**: [自动生成的时间戳]
135
- **分析范围**: [source_path的相对路径或绝对路径]
135
+ **分析范围**: [source-path的相对路径或绝对路径]
136
136
 
137
137
  ## 概述
138
138
 
@@ -287,8 +287,8 @@ graph TD
287
287
 
288
288
  ## 工作流程
289
289
 
290
- 1. **确认路径**:验证 source_pathtarget_path 的有效性
291
- 2. **生成元信息**:记录分析时间(使用当前时间戳)和分析范围(source_path
290
+ 1. **确认路径**:验证 source-pathtarget-dir 的有效性
291
+ 2. **生成元信息**:记录分析时间(使用当前时间戳)和分析范围(source-path
292
292
  3. **扫描目录**:使用 Glob 工具获取所有相关文件
293
293
  4. **分析文件**:使用 Read 工具逐个分析文件中的API调用
294
294
  5. **构建模型**:在内存中构建完整的API调用关系模型
@@ -296,7 +296,7 @@ graph TD
296
296
  7. **生成图表**:使用Mermaid语法创建带编号的可视化图表
297
297
  8. **编写文档**:按照规范格式生成Markdown文档(包含元信息和三个核心部分)
298
298
  9. **可选增强**:仅当用户明确要求时,在文档末尾添加"潜在问题与优化建议"部分
299
- 10. **保存输出**:使用 Write 工具保存到 target_path
299
+ 10. **保存输出**:使用 Write 工具保存到 target-dir
300
300
 
301
301
  ## 质量标准
302
302
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: 基于现状、需求和依赖,生成增量需求的设计蓝图(时序、依赖、文件变更),指导代码生成
3
- argument-hint: [旧需求快照] [结构化需求] [UI依赖报告] [report-output-dir]
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. **旧需求快照**(来自 `analyze-codeflow`): 包含 S1~Sxx 时序编号、Dxx 依赖节点、Rxx 关系总结
35
- 2. **结构化需求描述**(来自 `structured-requirements-collection`): 包含新增/修改功能、触发条件、核心状态、数据流向的 5 列表格
36
- 3. **UI依赖采集报告**(来自 `ui-dependency-collection`): 包含依赖类型、来源路径、变更类型的依赖详情表
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-path]
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-path** (可选): 新基线报告的输出路径,默认为 `<原文件名>-baseline.md`
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-path>
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-path**: 默认为 `incspec/baselines`
271
+ - **baseline-output-dir**: 默认为 `incspec/baselines`
272
272
  - 如目录不存在,需主动创建
273
273
 
274
274
  ## 文件命名
@@ -0,0 +1,4 @@
1
+ Security scan passed
2
+ Scanned at: 2025-11-20T14:20:58.168746
3
+ Tool: gitleaks + pattern-based validation
4
+ Content hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
@@ -0,0 +1,231 @@
1
+ ---
2
+ name: inc-spec-skill
3
+ description: 设计优先的前端功能增量编码工作流。适用于实现新UI组件、修改现有功能,或当用户提及"增量编码"、"代码流程分析"、"需求收集",以及需要带有API/Store依赖追踪的结构化功能开发时使用。
4
+ ---
5
+
6
+ # AI增量编码
7
+
8
+ ## 目录
9
+
10
+ - [快速开始](#快速开始)
11
+ - [工作流概览](#工作流概览)
12
+ - [CLI集成](#cli集成)
13
+ - [步骤详情](#步骤详情)
14
+ - [最佳实践](#最佳实践)
15
+ - [参考资源](#参考资源)
16
+
17
+ ## 快速开始
18
+
19
+ ```
20
+ 1. 分析现有代码 → incspec analyze <path>
21
+ 2. 收集需求 → incspec collect-req
22
+ 3. 收集依赖 → incspec collect-dep
23
+ 4. 设计增量 → incspec design
24
+ 5. 应用代码变更 → incspec apply <report>
25
+ 6. 合并到基线 → incspec merge <report>
26
+ 7. 归档工作流 → incspec archive --yes
27
+ ```
28
+
29
+ 首次使用前初始化: `incspec init`
30
+
31
+ ## 工作流概览
32
+
33
+ 7步设计优先工作流确保代码变更与现有架构无缝集成:
34
+
35
+ | 步骤 | 目的 | 产出 |
36
+ |------|------|------|
37
+ | 1. 代码流程分析 | 记录当前API/Store/组件交互 | 基线快照 |
38
+ | 2. 需求收集 | 将模糊需求转换为结构化5列表格 | 需求报告 |
39
+ | 3. 依赖收集 | 识别所有API/Store/类型依赖 | 依赖报告 |
40
+ | 4. 增量设计 | 生成实现蓝图 | 增量快照 |
41
+ | 5. 代码应用 | 按蓝图创建/修改文件 | 更新后的代码库 |
42
+ | 6. 基线合并 | 将增量转换为干净基线 | 新基线 |
43
+ | 7. 归档 | 归档工作流产出到 `archives/YYYY-MM/` | 干净的工作区 |
44
+
45
+ ## CLI集成
46
+
47
+ 每个步骤与 `incspec` CLI同步以跟踪工作流状态:
48
+
49
+ | 步骤 | 开始 | 完成 |
50
+ |------|------|------|
51
+ | 分析 | `incspec analyze <path> --module=<m>` 或 `--baseline=<file>` | `--complete --output=<file>` |
52
+ | 需求 | `incspec collect-req` | `--complete` |
53
+ | 依赖 | `incspec collect-dep` | `--complete` |
54
+ | 设计 | `incspec design --feature=<f>` | `--complete --output=<file>` |
55
+ | 应用 | `incspec apply <report>` | `--complete` |
56
+ | 合并 | `incspec merge <report>` | `--complete --output=<file>` |
57
+ | 归档 | `incspec archive --yes` | - |
58
+
59
+ 管理命令:
60
+ - `incspec status` - 查看工作流状态
61
+ - `incspec list` - 列出规范文件
62
+ - `incspec validate` - 验证项目健康状态
63
+
64
+ ## 步骤详情
65
+
66
+ ### 步骤1: 代码流程分析
67
+
68
+ 分析现有代码,创建API调用、依赖关系和组件交互的文档化基线。
69
+
70
+ **输入:** 源代码目录路径 (如 `src/pages/dashboard`) 或现有基线文件 (`--baseline=<file>`)
71
+
72
+ **输出:** 基线报告,包含:
73
+ - 编号的API调用序列图 (如 `[1]`、`[2]`)
74
+ - 组件/Store依赖关系图
75
+ - 数据流摘要
76
+
77
+ 详见 [references/analyze-codeflow.md](references/analyze-codeflow.md)。
78
+
79
+ ### 步骤2: 需求收集
80
+
81
+ 将模糊的用户需求转换为严格的5列结构化表格,消除所有歧义术语。
82
+
83
+ **输入:** 用户的非正式需求描述
84
+
85
+ **输出:** 结构化表格,包含以下列:
86
+ 1. 需求ID
87
+ 2. 详细描述 (不含"某些"、"相关"等模糊术语)
88
+ 3. 验收标准
89
+ 4. 依赖项
90
+ 5. 实现备注
91
+
92
+ 详见 [references/structured-requirements-collection.md](references/structured-requirements-collection.md)。
93
+
94
+ ### 步骤3: 依赖收集
95
+
96
+ 在代码生成前识别所有上下文依赖。
97
+
98
+ **输入:** 步骤2的结构化需求
99
+
100
+ **输出:** 完整的依赖清单:
101
+ - **API:** 端点、方法、请求/响应类型
102
+ - **Store:** 模块、状态属性、actions
103
+ - **类型:** 现有和新增的TypeScript接口
104
+ - **组件:** 共享组件、工具函数
105
+
106
+ 详见 [references/ui-dependency-collection.md](references/ui-dependency-collection.md)。
107
+
108
+ ### 步骤4: 增量设计
109
+
110
+ 基于当前状态、需求和依赖生成实现蓝图。**设计获批前不编写任何代码。**
111
+
112
+ **输入:** 基线(步骤1) + 需求(步骤2) + 依赖(步骤3)
113
+
114
+ **输出:** 增量快照,包含:
115
+ - 集成新调用的API序列图
116
+ - 文件修改计划 (新增/修改/删除)
117
+ - 分步实现指导
118
+
119
+ 详见 [references/analyze-increment-codeflow.md](references/analyze-increment-codeflow.md)。
120
+
121
+ ### 步骤5: 代码应用
122
+
123
+ 通过创建新文件和修改现有文件执行增量蓝图。
124
+
125
+ **输入:** 步骤4的增量快照 + 源代码目录
126
+
127
+ **输出:** 修改后的代码库:
128
+ - 按蓝图创建的新文件
129
+ - 更新的现有文件
130
+ - 正确的导入和类型定义
131
+
132
+ 详见 [references/apply-increment-code.md](references/apply-increment-code.md)。
133
+
134
+ ### 步骤6: 基线合并
135
+
136
+ 将增量快照(带有新增/修改/删除标记)转换为干净基线,为下次迭代做准备。
137
+
138
+ **输入:** 步骤4的增量快照
139
+
140
+ **输出:** 代表当前系统状态的干净基线(无增量标记)
141
+
142
+ 详见 [references/merge-to-baseline.md](references/merge-to-baseline.md)。
143
+
144
+ ### 步骤7: 归档
145
+
146
+ 将已完成的工作流产出归档到 `archives/YYYY-MM/{module}/` 目录。
147
+
148
+ **输入:** 要归档的文件(可选,默认为当前工作流)
149
+
150
+ **操作:**
151
+ ```bash
152
+ incspec archive --yes # 归档所有工作流产出
153
+ incspec archive <file> --yes # 归档指定文件
154
+ incspec archive <file> --keep # 复制而非移动
155
+ ```
156
+
157
+ 详见 [references/inc-archive.md](references/inc-archive.md)。
158
+
159
+ ## 最佳实践
160
+
161
+ **顺序执行:** 按步骤1-7顺序执行。跳过步骤会导致集成问题。
162
+
163
+ **设计先于编码:** 步骤4设计获批前不编写任何代码。
164
+
165
+ **不可跳过依赖:** 遗漏依赖(步骤3)是集成失败的首要原因。
166
+
167
+ **CLI同步:** 始终与 `incspec` CLI同步以保证工作流可追溯。
168
+
169
+ **验证节点:**
170
+ - 步骤2后: 需求中无模糊术语
171
+ - 步骤4后: 编码前审查蓝图
172
+ - 步骤5后: 验证所有文件已正确创建/修改
173
+ - 步骤7后: 确认工作区已清理
174
+
175
+ ## 常见陷阱
176
+
177
+ | 陷阱 | 后果 |
178
+ |------|------|
179
+ | 跳过代码流程分析 | 集成问题,返工 |
180
+ | 接受模糊需求 | 编码时发现歧义 |
181
+ | 遗漏依赖 | 导入错误,运行时失败 |
182
+ | 编码先于设计 | 在不符合架构的实现上浪费精力 |
183
+ | 跳过基线合并 | 对当前系统状态产生混淆 |
184
+ | 忽略归档 | 工作区杂乱,历史丢失 |
185
+
186
+ ## 参考资源
187
+
188
+ | 文件 | 用途 |
189
+ |------|------|
190
+ | [analyze-codeflow.md](references/analyze-codeflow.md) | 代码流程分析和API序列图 |
191
+ | [structured-requirements-collection.md](references/structured-requirements-collection.md) | 5列需求结构化 |
192
+ | [ui-dependency-collection.md](references/ui-dependency-collection.md) | API/Store/类型依赖收集 |
193
+ | [analyze-increment-codeflow.md](references/analyze-increment-codeflow.md) | 设计优先的增量蓝图 |
194
+ | [apply-increment-code.md](references/apply-increment-code.md) | 基于蓝图的代码应用 |
195
+ | [merge-to-baseline.md](references/merge-to-baseline.md) | 增量到基线转换 |
196
+ | [inc-archive.md](references/inc-archive.md) | 工作流产出归档 |
197
+
198
+ ## 使用示例
199
+
200
+ **任务:** 为产品仪表板添加筛选功能
201
+
202
+ ```
203
+ 步骤1: 分析产品仪表板代码流程
204
+ → 记录当前数据获取、store结构、API端点
205
+
206
+ 步骤2: 结构化筛选需求
207
+ → 将"添加一些筛选器"转换为具体筛选类型(类别、价格、评分)
208
+ → 定义确切行为和组合逻辑(AND/OR)
209
+
210
+ 步骤3: 收集依赖
211
+ → 识别筛选API端点、store扩展、共享筛选组件
212
+
213
+ 步骤4: 生成增量蓝图
214
+ → 规划FilterPanel集成、状态管理变更、文件修改
215
+
216
+ 步骤5: 应用增量
217
+ → 创建FilterPanel组件,修改ProductDashboard,更新store
218
+
219
+ 步骤6: 合并到基线
220
+ → 生成新仪表板状态的干净快照
221
+
222
+ 步骤7: 归档
223
+ → 归档工作流产出,为下次增量做准备(如添加排序功能)
224
+ ```
225
+
226
+ ## 开发工作流集成
227
+
228
+ - **版本控制:** 步骤7(完整周期)后提交
229
+ - **代码审查:** 在步骤4审查增量蓝图
230
+ - **测试:** 在步骤5添加测试
231
+ - **文档:** 在步骤6更新文档