ai-spec-dev 0.17.0 → 0.25.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,6 +2,9 @@
2
2
 
3
3
  > AI 驱动的功能开发编排工具 — 从一句话需求到可运行代码的完整流水线,支持单 Repo 及多 Repo 跨端联动
4
4
 
5
+ [![Version](https://img.shields.io/badge/version-0.25.0-blue)](https://github.com/hzhongzhong/ai-spec)
6
+ [![Author](https://img.shields.io/badge/author-hzhongzhong-green)](https://github.com/hzhongzhong)
7
+
5
8
  **单 Repo 模式:**
6
9
  ```
7
10
  需求描述 → 项目宪法 → 项目感知 → Spec+Tasks → 交互式润色(Diff预览) → Spec质量预评估 → Approval Gate → DSL提取+校验 → Git 隔离 → 代码生成(同层并行) → TDD测试(--tdd) / 测试骨架 → 错误反馈自动修复 → 2-pass 代码审查 → 经验积累(宪法§9)
@@ -147,6 +150,7 @@ ai-spec init 分析代码库,生成项目宪法(.ai-spec-cons
147
150
  ai-spec init --consolidate 整合宪法:将 §9 积累教训提炼归并到 §1–§8,清理冗余(Constitution Rebase)
148
151
  ai-spec create [idea] 完整工作流:宪法 → context → spec → tasks → refine → worktree → codegen → 测试生成 → 错误修复 → review → 经验积累
149
152
  ai-spec update [change] 增量更新:修改现有 Spec → 重提取 DSL → 识别受影响文件 → 可选重新生成代码
153
+ ai-spec learn [lesson] 零摩擦知识注入:直接将工程决策或教训写入宪法 §9(无需运行 review)
150
154
  ai-spec export DSL → OpenAPI 3.1.0 YAML/JSON(可导入 Postman / Swagger UI / openapi-generator)
151
155
  ai-spec mock 从 DSL 生成 Mock Server / 前端 Proxy 配置 / MSW Handlers(联调利器)
152
156
  ai-spec review [file] 对当前 git diff 运行 2-pass AI 代码审查(架构层 + 实现层),并打印评分趋势
@@ -204,6 +208,7 @@ ai-spec create # 省略 idea 时交互式询问
204
208
  --skip-error-feedback # 跳过错误反馈自动修复
205
209
  --skip-review # 跳过代码审查(同时跳过经验积累)
206
210
  --skip-assessment # 跳过 Spec 质量预评估(省一次 AI 调用)
211
+ --force # 强制绕过 minSpecScore 质量门槛(score 不足时继续执行)
207
212
 
208
213
  # 模式增强
209
214
  --tdd # TDD 模式:在代码生成前写入真实断言测试,由 error feedback loop 驱动实现通过测试
@@ -240,9 +245,25 @@ ai-spec config --model <name> # 设置默认 spec model
240
245
  ai-spec config --codegen <mode> # 设置默认 codegen 模式
241
246
  ai-spec config --codegen-provider <name> # 设置默认 codegen provider
242
247
  ai-spec config --codegen-model <name> # 设置默认 codegen model
248
+ ai-spec config --min-spec-score <n> # 设置 Spec 质量门槛(1-10,0 = 禁用)
243
249
  ai-spec config --reset # 清空配置文件
244
250
  ```
245
251
 
252
+ > **Spec 质量门槛(minSpecScore)**
253
+ > - 设置后,`create` 在 Approval Gate 前会运行质量评估,`overallScore` 低于阈值时阻断流程
254
+ > - **`--auto` 模式同样生效**:CI 环境中配置了门槛则强制执行,避免低质量 Spec 静默通过
255
+ > - `--force` 可临时绕过(输出黄色警告)
256
+ > - 未配置(默认 0)时评估仅为建议性,不阻断
257
+
258
+ #### `ai-spec learn`
259
+
260
+ ```
261
+ ai-spec learn "教训或决策描述" # 直接写入宪法 §9
262
+ ai-spec learn # 省略时交互式输入
263
+ ```
264
+
265
+ > 适合混用其他 AI 工具(Cursor / Copilot)的团队:在任何场景发现问题或做出架构决策时,无需经过完整 review 流程,直接将知识写入宪法,下次 `create` 即生效。
266
+
246
267
  #### `ai-spec workspace`
247
268
 
248
269
  ```
@@ -277,12 +298,14 @@ ai-spec export --dsl <path> # 指定 DSL 文件
277
298
  #### `ai-spec mock`
278
299
 
279
300
  ```
280
- ai-spec mock # 读取最新 DSL,生成 mock/server.js(Express 独立 Mock 服务器)
281
- ai-spec mock --port 3002 # 指定端口(默认 3001)
282
- ai-spec mock --proxy # 同时生成前端框架 Proxy 配置片段(Vite/Next.js/webpack 自动识别)
283
- ai-spec mock --msw # 同时生成 MSW Handlers(src/mocks/handlers.ts + browser.ts)
284
- ai-spec mock --dsl <path> # 指定 DSL 文件路径(默认自动寻找最新)
285
- ai-spec mock --workspace # 为工作区内所有后端 repo 批量生成 Mock
301
+ ai-spec mock # 读取最新 DSL,生成 mock/server.js(Express 独立 Mock 服务器)
302
+ ai-spec mock --port 3002 # 指定端口(默认 3001)
303
+ ai-spec mock --proxy # 同时生成前端框架 Proxy 配置片段(Vite/Next.js/webpack 自动识别)
304
+ ai-spec mock --msw # 同时生成 MSW Handlers(src/mocks/handlers.ts + browser.ts)
305
+ ai-spec mock --dsl <path> # 指定 DSL 文件路径(默认自动寻找最新)
306
+ ai-spec mock --workspace # 为工作区内所有后端 repo 批量生成 Mock
307
+ ai-spec mock --serve --frontend <path> # 生成后直接启动 Mock 服务器 + 自动 patch 前端 Proxy
308
+ ai-spec mock --restore --frontend <path> # 撤销 Proxy patch,停止 Mock 服务器
286
309
  ```
287
310
 
288
311
  ---
@@ -338,13 +361,9 @@ ai-spec init --force
338
361
 
339
362
  #### Constitution Rebase — 为什么需要定期整合
340
363
 
341
- `ai-spec review` 每次运行后会把审查 issue 追加到宪法 §9。长期运行后 §9 会积累大量条目(重复措辞、已修复问题、不再适用的早期教训)。宪法全文注入每次 AI 调用——内容越长,AI 对中间章节的注意力越分散,效果反而下降。当宪法超过 6,000 字符时,CLI 会自动显示警告提示整合。
364
+ `ai-spec review` 每次运行后会把审查 issue 追加到宪法 §9。长期运行后 §9 会积累大量条目(重复措辞、已修复问题、不再适用的早期教训)。宪法被注入每次 AI 调用,超过 2000 字符后会被硬截断,越积越多反而降低效果。
342
365
 
343
- **建议频率**:§9 达到 8 条以上时(系统会自动提示),或出现以下警告时,运行一次整合:
344
-
345
- ```
346
- ⚠ Constitution is long (8,432 chars). Consider running: ai-spec init --consolidate
347
- ```
366
+ **建议频率**:§9 达到 8 条以上时(系统会自动提示),运行一次整合。
348
367
 
349
368
  ```bash
350
369
  # 预览效果(不写入)
@@ -644,8 +663,27 @@ ai-spec mock --port 3002 --proxy --msw
644
663
 
645
664
  # 为工作区所有后端 repo 批量生成
646
665
  ai-spec mock --workspace
666
+
667
+ # ── 一键联调(推荐)──────────────────────────────────────────
668
+ # 生成 + 启动 Mock 服务器(后台) + 自动 patch 前端 Proxy
669
+ ai-spec mock --serve --frontend ../my-frontend
670
+
671
+ # 联调结束后恢复(撤销 Proxy patch,停止 Mock 服务器)
672
+ ai-spec mock --restore --frontend ../my-frontend
647
673
  ```
648
674
 
675
+ **`--serve` 详解:**
676
+
677
+ `--serve` 做以下三件事:
678
+ 1. 在后台启动 `node mock/server.js`(PID 记录在 `.ai-spec-mock.lock.json`)
679
+ 2. 根据前端框架自动 patch Proxy 配置:
680
+ - **Vite**:生成 `vite.config.ai-spec-mock.ts`(mergeConfig 方式,非破坏性),在 `package.json` 添加 `dev:mock` 脚本
681
+ - **CRA**:临时修改 `package.json` 的 `"proxy"` 字段(原值备份在 lock 文件)
682
+ - **Next.js / webpack**:打印手动配置说明
683
+ 3. 打印前端启动命令(`npm run dev:mock` 或 `npm start`)
684
+
685
+ `--restore` 的逆操作:删除 `vite.config.ai-spec-mock.ts`、还原 `package.json`、发送 SIGTERM 到 Mock 服务器进程。
686
+
649
687
  **生成的文件:**
650
688
 
651
689
  | 文件 | 说明 |
@@ -657,6 +695,8 @@ ai-spec mock --workspace
657
695
  | `mock/proxy.webpack.comment.txt` | webpack devServer.proxy 配置片段(默认 fallback) |
658
696
  | `src/mocks/handlers.ts` | MSW 请求拦截 handlers(`--msw`) |
659
697
  | `src/mocks/browser.ts` | MSW browser worker 初始化(`--msw`) |
698
+ | `vite.config.ai-spec-mock.ts` | 前端临时 Vite 配置(`--serve`,非破坏性,`--restore` 后删除) |
699
+ | `.ai-spec-mock.lock.json` | Proxy patch 记录 + Mock 服务器 PID(`--restore` 后删除) |
660
700
 
661
701
  **Mock Server 特性:**
662
702
 
@@ -665,18 +705,43 @@ ai-spec mock --workspace
665
705
  - Fixture 数据从 DSL 数据模型的字段类型推断(String → `"example_xxx"`,DateTime → ISO 8601 字符串,etc.)
666
706
  - GET List 端点(描述含 "list"/"all")自动返回分页结构 `{ data: [...], total, page, pageSize }`
667
707
 
668
- **联调工作流:**
708
+ **联调工作流(手动):**
669
709
 
670
710
  ```
671
711
  后端 repo:
672
712
  ai-spec create "用户登录功能" # → 生成 DSL + 代码框架
673
- ai-spec mock --proxy # → 生成 mock/server.js
713
+ ai-spec mock # → 生成 mock/server.js
674
714
  node mock/server.js # → Mock 服务器运行在 localhost:3001
675
715
 
676
716
  前端 repo:
677
717
  配置 Proxy: 将 /api 代理到 localhost:3001 (参见 mock/proxy.*.txt)
678
- # 或者:
679
- ai-spec mock --msw # → 生成 MSW handlers,前端完全脱离后端运行
718
+ ```
719
+
720
+ **联调工作流(一键,推荐):**
721
+
722
+ ```bash
723
+ # 后端 repo 执行(一条命令完成全部)
724
+ cd backend-repo
725
+ ai-spec mock --serve --frontend ../frontend-repo
726
+ # → 自动生成 server.js,启动 Mock 服务器(后台),patch 前端 Proxy
727
+
728
+ # 按提示在前端 repo 启动 Dev Server
729
+ cd ../frontend-repo
730
+ npm run dev:mock
731
+ # → 打开浏览器,直接看到 Mock 数据
732
+
733
+ # 联调结束
734
+ cd ../backend-repo
735
+ ai-spec mock --restore --frontend ../frontend-repo
736
+ ```
737
+
738
+ **工作区一键联调(`ai-spec create --serve`):**
739
+
740
+ 在多 Repo 工作区模式下,加 `--serve` 标志,Pipeline 完成后自动执行上述流程:
741
+
742
+ ```bash
743
+ ai-spec create "用户登录功能" --serve
744
+ # 完成后自动:生成 Mock → 启动服务器 → patch 前端 Proxy → 打印 dev 命令
680
745
  ```
681
746
 
682
747
  ---
@@ -1000,7 +1065,7 @@ specs/
1000
1065
  ~ src/routes/client/index.ts... ✔
1001
1066
  ```
1002
1067
 
1003
- **跨 Task 一致性保障**:每个 task 完成后,写入的 `src/api*` / `src/service*` / `src/store*` / `src/composable*` 文件会被读回并缓存;后续 task prompt 中注入这些文件的**所有 export 声明行**(而非前 N 字符的截断),确保路由/组件层 import 使用的函数名与 API 层完全一致(不再出现 `getTasks` vs `getTaskList` 的跨 task 幻觉)。当前 task 创建新路由模块文件时,也会自动携带对应 `routes/index.ts` 的精确注册指令。
1068
+ **跨 Task 一致性保障**:每个 task 完成后,写入的 `src/api*` / `src/service*` / `src/store*` / `src/composable*` 文件会被读回并缓存;后续 task prompt 中可以看到这些文件的实际导出内容,确保路由/组件层 import 使用的函数名与 API 层一致(不再出现 `getTasks` vs `getTaskList` 的跨 task 幻觉)。当前 task 创建新路由模块文件时,也会自动携带对应 `routes/index.ts` 的精确注册指令。
1004
1069
 
1005
1070
  **分页参数 ground-truth 注入**:`frontend-context-loader` 自动扫描 `src/apis/`(及 `src/api/`、`src/services/` 等)中现有的 API 文件,找到包含分页字段(`pageIndex`/`pageSize`/`pageNum`/`current` 等)的 interface 及对应导出函数,作为 `paginationExample` 注入 prompt,并标注 "COPY THIS EXACTLY"。生成的列表接口将与项目现有接口使用完全相同的分页参数名称和 HTTP 方法(POST body 或 GET query)。
1006
1071
 
package/RELEASE_LOG.md CHANGED
@@ -2,6 +2,432 @@
2
2
 
3
3
  ---
4
4
 
5
+ ## [0.24.0] 2026-03-25 — 四项质量修复(lesson 计数、export default、impliesRegistration、依赖拓扑排序)
6
+
7
+ ### 修复内容
8
+
9
+ **Fix #1 — Lesson count 误计**
10
+ - 文件:`prompts/consolidate.prompt.ts`
11
+ - 问题:`parseConstitutionStats` 中用 `line.startsWith("-")` 统计 §9 教训条数,会将多行教训的子列表项、普通破折号行都计入,导致计数虚高、过早触发 consolidate 警告。
12
+ - 修复:改为正则 `/^-\s+.*\*\*\[\d{4}-\d{2}-\d{2}\]\*\*/` 只匹配带日期徽章的真实教训行。
13
+
14
+ **Fix #2 — `export default function/class` 未捕获**
15
+ - 文件:`core/code-generator.ts` → `extractBehavioralContract`
16
+ - 问题:React 函数组件 (`export default function Foo()`) 和 class 组件只被当作单行 export 处理,消费者看不到函数体内的 return 结构与 props 形状。
17
+ - 修复:在单行 export 分支之前新增完整块捕获逻辑(大括号深度计数),与 `defineStore` 捕获逻辑对称。
18
+
19
+ **Fix #3 — `impliesRegistration` 对 `route`/`view`/`api` 层失效**
20
+ - 文件:`core/code-generator.ts` → `runApiModeWithTasks`
21
+ - 问题:`impliesRegistration` 仅依赖任务文本关键词,若 `route` 层任务描述不含 "route"/"router" 等词,则跳过路由索引更新,新路由永远不注册。
22
+ - 修复:增加 `task.layer === "route" || "view" || "api"` 的层级直接判断,文本关键词作为额外补充。
23
+
24
+ **Fix #4 — `dependencies` 字段从未使用**
25
+ - 文件:`core/code-generator.ts` + `core/task-generator.ts`
26
+ - 问题:同层任务始终全量并行,任务 JSON 中声明的 `dependencies` 字段完全被忽略,层内顺序依赖无法保证。
27
+ - 修复:
28
+ - 新增 `topoSortLayerTasks(tasks)` 函数,将同层任务按依赖关系分拆为多个批次(batch);同批次内仍并行,批次间顺序执行。
29
+ - 每批完成后立即更新 `generatedFileCache`,确保后续批次能看到前驱批次的导出。
30
+ - `task-generator.ts` 同步更新 `TaskLayer` 类型、`LAYER_ORDER`、`layerColors`,补齐 `view` 和 `route` 层。
31
+
32
+ ---
33
+
34
+ ## [0.23.0] 2026-03-25 — 文件名幻觉修复(`index.vue` → `TaskManagement.vue`)
35
+
36
+ ### 根本原因
37
+
38
+ 路由文件引用的是 `@/views/task-management/index.vue`,但实际文件是 `TaskManagement.vue`。
39
+
40
+ **两个叠加 bug:**
41
+
42
+ **Bug 1:`generatedFileCache` 不缓存 `views/` 文件**
43
+
44
+ cache 的 regex 只覆盖 `src/api*/service*/stores*/composables*/`,视图组件从未被缓存。路由文件生成时,cache 里根本看不到 `TaskManagement.vue` 的存在,只能靠「约定」猜文件名。
45
+
46
+ `index.vue` 是全球最常见的视图组件命名(Next.js、Nuxt、Vite 项目大量使用),模型先验概率极高 → 幻觉必然发生。
47
+
48
+ **Bug 2:路由文件和视图组件在同一层(`view`)或路由在更早的层**
49
+
50
+ 即使扩展了 cache regex,如果路由文件和视图组件并行执行,视图的 cache 条目还是不存在。
51
+
52
+ ### 修复
53
+
54
+ **1. 新增 `route` 层(`core/code-generator.ts`)**
55
+
56
+ 完整的前端六层链:
57
+ ```
58
+ data → infra → service → api → view → route → test
59
+ ```
60
+
61
+ | 层 | 前端含义 |
62
+ |---|---|
63
+ | `service` | `src/api/` HTTP 函数 |
64
+ | `api` | `src/stores/` stores |
65
+ | `view` | `src/views/` 页面组件 |
66
+ | `route` | `src/router/routes/` 路由文件 ← 新增 |
67
+ | `test` | 测试 |
68
+
69
+ **2. `view` 文件加入 cache(路径 sentinel,`core/code-generator.ts`)**
70
+
71
+ 扩展 cache regex:加入 `views?/pages?/`。但不读取文件内容(SFC 300+ 行太大),而是写入固定 sentinel:
72
+ ```
73
+ // view component — use this exact path for router imports
74
+ ```
75
+
76
+ **3. `buildGeneratedFilesSection` 对 view 文件只展示路径标记**
77
+
78
+ ```
79
+ // exists: src/views/task-management/TaskManagement.vue
80
+ ```
81
+
82
+ 路由生成 AI 看到的不是猜测,而是已知事实。
83
+
84
+ **4. `tasks.prompt.ts` 四层分离规则**
85
+
86
+ 含具体 EXAMPLE:
87
+ ```
88
+ TASK-003 layer:"view" src/views/task-management/TaskManagement.vue
89
+ TASK-004 layer:"route" src/router/routes/taskManagement.ts ← 此时 cache 有 TaskManagement.vue ✓
90
+ ```
91
+
92
+ **5. `codegen.prompt.ts` Rule 17 补充路径规则**
93
+
94
+ "// exists:" 条目中的路径是权威来源,不得替换为 `index.vue` 或其他猜测值。
95
+
96
+ ---
97
+
98
+ ## [0.22.0] 2026-03-25 — 前端三层分离(`view` 层)彻底根治 API→Store 命名幻觉
99
+
100
+ ### 根本原因
101
+
102
+ v0.21.0 修复了「store → 页面」的命名幻觉,但遗漏了「**api 文件 → store**」这条更上游的依赖链。
103
+
104
+ v0.21.0 的 `tasks.prompt.ts` 写的是:
105
+ ```
106
+ "service" — API call files (src/api/) AND stores (src/stores/)
107
+ ```
108
+
109
+ 两者被分配到**同一层**(`service`),并行执行。生成 `taskStore.ts` 时,`taskManagement.ts`(exports `getTaskList`)还没写完,不在 cache 里。Store AI 只能猜 `getTasks`。
110
+
111
+ **完整的前端命名幻觉依赖链:**
112
+ ```
113
+ src/apis/taskManagement.ts (layer: service)
114
+ ↓ store 需要知道这里有哪些函数
115
+ src/stores/taskStore.ts (layer: ???) ← 必须在 service 之后
116
+ ↓ 页面需要知道这里有哪些 actions
117
+ src/views/TaskManagement.vue (layer: ???) ← 必须在 store 之后
118
+ ```
119
+
120
+ 如果三者在同一层或 store 与 api 同层,幻觉必然发生。
121
+
122
+ ### 修复
123
+
124
+ **1. 新增 `view` 层(`core/code-generator.ts`)**
125
+
126
+ `LAYER_ORDER` 从 5 层扩展到 6 层:
127
+ ```
128
+ ["data", "infra", "service", "api", "view", "test"]
129
+ ```
130
+
131
+ 映射关系:
132
+ | 层 | 后端含义 | 前端含义 |
133
+ |---|---|---|
134
+ | `service` | 业务逻辑 | API call 函数(`src/api/` 或 `src/apis/`) |
135
+ | `api` | 路由/控制器 | Pinia/Vuex stores(`src/stores/`) |
136
+ | `view` | (后端不用) | 页面/视图组件(`src/views/`, `src/pages/`) |
137
+ | `test` | 测试 | 测试 |
138
+
139
+ **2. `tasks.prompt.ts` 三层分离规则**
140
+
141
+ 明确的层级分配规则,含错误原因解释:
142
+ ```
143
+ service → src/apis/*.ts (HTTP 函数,如 getTaskList)
144
+ api → src/stores/*.ts (store 调用 service 层函数 — service 层已在 cache 里)
145
+ view → src/views/*.vue (页面调用 store — api 层已在 cache 里)
146
+ ```
147
+
148
+ 附带具体 EXAMPLE 展示正确的三 task 写法。
149
+
150
+ ### 效果
151
+
152
+ 完整的三级 cache 保障:
153
+ ```
154
+ service 层完成 → cache 有 getTaskList ← store 生成时看得到 ✓
155
+ api 层完成 → cache 有 fetchTasks ← 页面生成时看得到 ✓
156
+ ```
157
+
158
+ ---
159
+
160
+ ## [0.21.0] 2026-03-25 — Store 行为契约提取修复(`fetchTasks` → `fetchTaskList` 幻觉根治)
161
+
162
+ ### 根本原因分析
163
+
164
+ 触发条件:**Pinia / Vuex / Zustand store 文件被生成后,消费该 store 的页面/组件在同一轮继续生成时,函数名出现幻觉**(如 `fetchTasks` 被猜成 `fetchTaskList`、`loadTasks`、`fetchTaskData`)。
165
+
166
+ **两个叠加 bug:**
167
+
168
+ **Bug 1:`extractBehavioralContract` 对 store 文件是空壳**
169
+
170
+ Pinia composition API store 的典型结构:
171
+ ```typescript
172
+ export const useTaskStore = defineStore('task', () => {
173
+ const tasks = ref<Task[]>([])
174
+ async function fetchTasks() { ... }
175
+ return { tasks, fetchTasks } // ← 这里是真正的公开 API
176
+ })
177
+ ```
178
+
179
+ `extractBehavioralContract` 的 `export const ...` 规则只捕获**第一行**:
180
+ ```
181
+ export const useTaskStore = defineStore('task', () => {
182
+ ```
183
+ `return { tasks, fetchTasks }` 完全丢失。消费方 AI 看到的是空壳,只能靠直觉猜函数名——而 GPT/Claude 类模型的直觉会把 `fetchTasks` 猜成 `fetchTaskList`("更完整的命名风格")。
184
+
185
+ **Bug 2:store 和页面在同一 task layer 并行执行时,cache 快照里没有 store**
186
+
187
+ cache 更新逻辑是在**整层完成后**统一写入,确保下一层看到完整结果。但如果 task generator AI 把 store 和消费 store 的页面分配到同一层(如都是 `service` 层),它们并行执行,页面生成时 cache 里根本没有 store 内容。
188
+
189
+ ---
190
+
191
+ ### 修复方案
192
+
193
+ **1. `extractBehavioralContract` 新增两个捕获模式(`core/code-generator.ts`)**
194
+
195
+ - `export const X = defineStore(` / `createStore(` / `createSlice(` — 使用**括号深度计数器**完整捕获整个 `defineStore(...)` 调用(含 state/actions/getters 定义体)
196
+ - `return { ... }` — 使用**大括号深度计数器**完整捕获 return 对象(Pinia composition API 的公开 API 列表),并添加注释行 `// public API (return object):` 提示 AI 这是权威命名来源
197
+
198
+ **2. `buildGeneratedFilesSection` 对 store/composable 文件传全文内容(`core/code-generator.ts`)**
199
+
200
+ 对路径匹配 `src/stores?/` 或 `src/composables?/` 的文件,不再调用 `extractBehavioralContract`,直接传入完整文件内容。Store 文件通常 50-200 行,context 成本可接受,且整个文件就是 API 合约。
201
+
202
+ ```typescript
203
+ const isStoreOrComposable = /src[\\/](stores?|composables?)[\\/]/i.test(filePath);
204
+ lines.push(isStoreOrComposable ? content : extractBehavioralContract(content));
205
+ ```
206
+
207
+ **3. 强化 Rule 17(`prompts/codegen.prompt.ts`)**
208
+
209
+ 补充常见幻觉模式的负例:
210
+ ```
211
+ fetchTasks → fetchTaskList ✗ fetchTaskData ✗ fetchTaskAll ✗
212
+ fetchTasks → getTasks ✗ loadTasks ✗ queryTasks ✗
213
+ createTask → createTasks ✗
214
+ ```
215
+ 以及 Pinia 专项说明:"// public API (return object):" 区段展示的是 EVERY available action name。
216
+
217
+ **4. 前端层级顺序规则(`prompts/tasks.prompt.ts`)**
218
+
219
+ 新增 CRITICAL 规则:在同一功能中,**store 必须在 `service` 层,消费该 store 的页面/组件必须在 `api` 层**。打破同层并行依赖,确保页面生成时 cache 已有 store 的完整内容。
220
+
221
+ ---
222
+
223
+ ### 效果
224
+
225
+ 修复后 cache 区段对 Pinia composition API store 的展示从:
226
+ ```
227
+ export const useTaskStore = defineStore('task', () => {
228
+ ```
229
+ 变为:
230
+ ```
231
+ export const useTaskStore = defineStore('task', () => {
232
+ const tasks = ref([])
233
+ ...
234
+ // public API (return object):
235
+ return {
236
+ tasks,
237
+ loading,
238
+ fetchTasks,
239
+ createTask,
240
+ updateTaskStatus,
241
+ }
242
+ ```
243
+ 消费方 AI 能看到 `fetchTasks` 的精确名字,无需猜测。
244
+
245
+ ---
246
+
247
+ ## [0.20.0] 2026-03-25 — 一键 Mock 联调(`--serve` / `--restore`)
248
+
249
+ ### 功能:Mock Server 自动启动 + 前端 Proxy 自动 patch
250
+
251
+ **背景**:代码生成完成后,前端要联调需要手动三步:① 启动 Mock 服务器、② 在前端框架配置 Proxy、③ 启动前端 Dev Server。每次都要做一遍,且 Proxy 修改要记得恢复。
252
+
253
+ **方案**:新增 `--serve` / `--restore` 工作流,做到一条命令完成所有操作,联调结束一条命令还原。
254
+
255
+ ---
256
+
257
+ #### `ai-spec mock --serve --frontend <path>`
258
+
259
+ 在后台启动 Mock 服务器,并自动 patch 前端 Proxy:
260
+
261
+ - **Vite 项目**:生成 `vite.config.ai-spec-mock.ts`(使用 `mergeConfig` 动态合并基础配置,非破坏性),在 `package.json` 添加 `"dev:mock"` 脚本 → 执行 `npm run dev:mock`
262
+ - **CRA 项目**:临时修改 `package.json` 的 `"proxy"` 字段(原值存入 lock 文件),执行 `npm start`
263
+ - **Next.js / webpack**:自动 patch 不适用,打印手动配置说明
264
+
265
+ 所有操作记录在 `<frontend-dir>/.ai-spec-mock.lock.json`(含 Mock 服务器 PID),供 `--restore` 使用。
266
+
267
+ #### `ai-spec mock --restore --frontend <path>`
268
+
269
+ 逐一撤销 lock 文件中记录的所有操作,并向 Mock 服务器进程发送 SIGTERM。
270
+
271
+ #### `ai-spec create --serve`(工作区模式)
272
+
273
+ 多 Repo Pipeline 完成后,自动触发:
274
+ 1. 为后端 repo 生成 Mock Assets
275
+ 2. 后台启动 Mock 服务器
276
+ 3. 为前端 repo patch Proxy
277
+ 4. 打印前端 Dev Server 启动命令
278
+
279
+ ```bash
280
+ ai-spec create "用户登录" --serve
281
+ # → [W1..W4] 后端 + 前端 Pipeline
282
+ # → ✔ Mock 服务器启动 (PID 12345) → http://localhost:3001
283
+ # → ✔ 前端 Proxy patched (vite)
284
+ # → Ready! cd ../frontend && npm run dev:mock
285
+ ```
286
+
287
+ ---
288
+
289
+ #### 实现细节
290
+
291
+ **新增文件/函数(`core/mock-server-generator.ts`):**
292
+
293
+ | 函数 | 说明 |
294
+ |---|---|
295
+ | `applyMockProxy(frontendDir, mockPort, endpoints?)` | 检测前端框架,执行对应 patch 操作,写入 lock 文件 |
296
+ | `restoreMockProxy(frontendDir)` | 读取 lock 文件,逐一撤销,删除 lock 文件 |
297
+ | `startMockServerBackground(serverJsPath, port)` | `spawn` 后台 detached 进程,返回 PID |
298
+ | `saveMockServerPid(frontendDir, pid)` | 将 PID 写入已有 lock 文件 |
299
+
300
+ **`generateViteMockConfigTs`** 生成的 `vite.config.ai-spec-mock.ts` 通过动态 `import()` 加载基础配置,支持 object / function 两种导出形式:
301
+
302
+ ```typescript
303
+ export default defineConfig(async (env) => {
304
+ const mod = await import('./vite.config');
305
+ const baseConfigOrFn = mod.default;
306
+ const baseConfig = typeof baseConfigOrFn === 'function'
307
+ ? await baseConfigOrFn(env)
308
+ : baseConfigOrFn;
309
+ return mergeConfig(baseConfig ?? {}, { server: { proxy: { ... } } });
310
+ });
311
+ ```
312
+
313
+ ---
314
+
315
+ ## [0.19.0] 2026-03-25 — 错误解析重写 · 行为契约完整提取 · Auto Gate 修复
316
+
317
+ ### 1. 错误解析重写(`core/error-feedback.ts`)
318
+
319
+ **问题**:`parseErrors` 取输出最后 80 行。TypeScript / Jest 错误的结构是"具体 file:line 错误在前,摘要在后",`slice(-80)` 恰好丢掉了最前面真正有文件路径的错误行,只留下摘要——AI 修的是摘要里说的东西,不是实际的错误位置。2 轮结束后 branch 仍有编译错误。
320
+
321
+ **修复**:扫全文,**只保留含 `file:line` 模式的行**,过滤掉所有摘要行、noise 行。遇到 20 条即停(break),确保取到的是最早出现的 20 个可操作错误,message 截断从 300 → 400 字符避免切掉关键类型信息。
322
+
323
+ ```
324
+ // Before: slice(-80) — 取末尾,丢掉最前面的具体报错
325
+ src/services/auth.ts:15:3 - error TS2345... ← 丢失
326
+ ...
327
+ Found 12 errors. ← 被"修复"的是这里
328
+
329
+ // After: scan full, filter by file:line — 取有路径的行
330
+ src/services/auth.ts:15:3 - error TS2345... ← ✔ 捕获
331
+ src/controllers/user.ts:42:1 - error TS2304 ← ✔ 捕获
332
+ ```
333
+
334
+ ### 2. 行为契约完整提取(`core/code-generator.ts`)
335
+
336
+ **问题**:`extractBehavioralContract` 对 `interface` / `type` 只捕获开头一行(`export interface UserService {`),body 里的所有方法签名、字段定义全部丢失。Task B 看到的是空壳,照样幻觉方法名和参数类型。
337
+
338
+ **修复**:`interface` / `type X = {` / `class` / `enum` 使用大括号深度计数器,**完整捕获多行块**直到对应的 `}`。单行的 `export function` / `export const` 保持原有行为。
339
+
340
+ ```typescript
341
+ // Before: 只有一行
342
+ export interface UserService {
343
+
344
+ // After: 完整 interface body
345
+ export interface UserService {
346
+ getUser(id: string): Promise<User | null>;
347
+ createUser(dto: CreateUserDto): Promise<User>;
348
+ deleteUser(id: string): Promise<void>;
349
+ }
350
+ export type CreateUserDto = {
351
+ name: string;
352
+ email: string;
353
+ role: 'admin' | 'user';
354
+ }
355
+ ```
356
+
357
+ ### 3. Auto 模式 Gate 修复(`cli/index.ts`)
358
+
359
+ **问题**:`if (!opts.auto && !opts.skipAssessment)` 让 `minSpecScore` 在 `--auto` 模式下完全失效。团队配置了 `minSpecScore: 7`,CI 跑 `--auto` 照样通过,没有任何警告。
360
+
361
+ **修复**:`--auto` 模式下,如果 `minSpecScore > 0`,**仍然运行 assessment 并强制执行 Gate**(只跳过交互式展示 scorecard)。`--force` 仍可绕过。
362
+
363
+ ```
364
+ # 配置了 minSpecScore: 7 的项目
365
+ ai-spec create --auto → 运行 assessment,score=5 → exit(1),打印原因
366
+ ai-spec create --auto --force → 运行 assessment,score=5 → 黄色警告,继续
367
+ ai-spec create --auto(未配置 minSpecScore) → 跳过 assessment,行为不变
368
+ ```
369
+
370
+ ---
371
+
372
+ ## [0.18.0] 2026-03-25 — ai-spec learn · 行为契约注入 · Approval Gate 硬门槛
373
+
374
+ ### 1. `ai-spec learn` — 零摩擦知识注入
375
+
376
+ **背景**:宪法 §9 只收录通过 `ai-spec review` 触发的教训,依赖工具覆盖率(100% 使用 ai-spec review 在实际团队几乎不可能)。混用 Cursor / Copilot 的决策和踩坑永远不会回流。
377
+
378
+ **新增命令**:`ai-spec learn "<lesson>"`
379
+
380
+ ```bash
381
+ ai-spec learn "所有新接口必须走 validateRequest 中间件,上次某 PR 遗漏导致生产 bug"
382
+ ai-spec learn # 无参数时进入交互式输入
383
+ ```
384
+
385
+ - 直接 append 到 `.ai-spec-constitution.md` §9,无需 AI 调用,无需完整 review 流程
386
+ - 自动去重(检查前 60 字符是否已存在相似条目)
387
+ - §9 超过 8 条时提示 `--consolidate`
388
+
389
+ **新增函数**(`core/knowledge-memory.ts`):`appendDirectLesson(projectRoot, lessonText)`
390
+
391
+ ### 2. Generated File Cache — 行为契约注入
392
+
393
+ **背景**:0.17.0 解决了函数名幻觉(名称层)。但 Task A 的 service 校验了某字段,Task B 的 API 层完全不知道这个校验存在,命名正确但逻辑前后矛盾,lint/test 不一定能抓住。
394
+
395
+ **升级**(`core/code-generator.ts`):将 `extractExportSignatures()` 替换为 `extractBehavioralContract()`:
396
+
397
+ ```typescript
398
+ // Before: 只提取 export 行(名称层)
399
+ export function createTask(dto: CreateTaskDto): Promise<Task>
400
+
401
+ // After: 同时提取 throw/validation 模式(契约层)
402
+ export function createTask(dto: CreateTaskDto): Promise<Task>
403
+ export function updateTask(id: string, dto: UpdateTaskDto): Promise<Task>
404
+
405
+ // Error contracts (throws / validation):
406
+ // throw new AppError('TASK_TITLE_REQUIRED', 400)
407
+ // throw new AppError('PROJECT_NOT_FOUND', 404)
408
+ ```
409
+
410
+ 后续 task 注入的 context 不仅知道"叫什么",还知道"校验什么、会抛什么错",有效防止跨 task 的行为契约幻觉。
411
+
412
+ ### 3. Approval Gate 可配置硬门槛
413
+
414
+ **背景**:spec-assessor 是建议性的、不阻断的——赶时间的工程师直接 Proceed,错误检测时机太晚。
415
+
416
+ **新增配置项**(`.ai-spec.json`):`minSpecScore`(默认 0 = 禁用)
417
+
418
+ ```bash
419
+ ai-spec config --min-spec-score 7 # 设置最低分 7/10
420
+ ```
421
+
422
+ 当 `overallScore < minSpecScore` 时:
423
+ - 打印红色错误信息,列出失败原因和当前阈值
424
+ - `process.exit(1)` 阻断流程
425
+ - `--force` flag 可强制绕过(同时输出黄色警告)
426
+
427
+ **设计原则**:默认关闭,不破坏现有用户工作流;团队可按需在 `.ai-spec.json` 开启,阈值完全可配置。
428
+
429
+ ---
430
+
5
431
  ## [0.17.0] 2026-03-24 — 宪法全文注入 · Export 精准缓存 · 宪法长度警告
6
432
 
7
433
  ### 1. 宪法全文注入(移除硬截断)