ai-spec-dev 0.14.1 → 0.24.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.
@@ -6,12 +6,7 @@
6
6
  "Bash(grep -E \"^./\\\\w+/|^./\\\\w+\\\\.ts$\")",
7
7
  "Bash(wc -l core/*.ts prompts/*.ts)",
8
8
  "Bash(ls:*)",
9
- "Bash(ls \"D:\\\\Document\\\\xwechat_files\\\\wxid_01h824wams3o22_fdb0\\\\msg\\\\file\\\\2026-03\\\\ai-spec-dev-poc\\(1\\)\\(1\\)\\\\ai-spec-dev-poc\\\\dist\")",
10
- "Bash(npm view:*)",
11
- "Bash(ls \"D:\\\\Document\\\\xwechat_files\\\\wxid_01h824wams3o22_fdb0\\\\msg\\\\file\\\\2026-03\\\\ai-spec-dev-poc\\(1\\)\\(1\\)\\\\ai-spec-dev-poc\\\\dist/cli\")",
12
- "Bash(npx tsup:*)",
13
- "Bash(node node_modules/tsup/dist/cli-main.js)",
14
- "Bash(npm publish:*)",
9
+ "Bash(ls \"D:/Document/xwechat_files/wxid_01h824wams3o22_fdb0/msg/file/2026-03/ai-spec-dev-poc\\(2\\)/ai-spec-dev-poc/dist\")",
15
10
  "Bash(npm whoami:*)"
16
11
  ]
17
12
  }
package/README.md CHANGED
@@ -147,6 +147,7 @@ ai-spec init 分析代码库,生成项目宪法(.ai-spec-cons
147
147
  ai-spec init --consolidate 整合宪法:将 §9 积累教训提炼归并到 §1–§8,清理冗余(Constitution Rebase)
148
148
  ai-spec create [idea] 完整工作流:宪法 → context → spec → tasks → refine → worktree → codegen → 测试生成 → 错误修复 → review → 经验积累
149
149
  ai-spec update [change] 增量更新:修改现有 Spec → 重提取 DSL → 识别受影响文件 → 可选重新生成代码
150
+ ai-spec learn [lesson] 零摩擦知识注入:直接将工程决策或教训写入宪法 §9(无需运行 review)
150
151
  ai-spec export DSL → OpenAPI 3.1.0 YAML/JSON(可导入 Postman / Swagger UI / openapi-generator)
151
152
  ai-spec mock 从 DSL 生成 Mock Server / 前端 Proxy 配置 / MSW Handlers(联调利器)
152
153
  ai-spec review [file] 对当前 git diff 运行 2-pass AI 代码审查(架构层 + 实现层),并打印评分趋势
@@ -204,6 +205,7 @@ ai-spec create # 省略 idea 时交互式询问
204
205
  --skip-error-feedback # 跳过错误反馈自动修复
205
206
  --skip-review # 跳过代码审查(同时跳过经验积累)
206
207
  --skip-assessment # 跳过 Spec 质量预评估(省一次 AI 调用)
208
+ --force # 强制绕过 minSpecScore 质量门槛(score 不足时继续执行)
207
209
 
208
210
  # 模式增强
209
211
  --tdd # TDD 模式:在代码生成前写入真实断言测试,由 error feedback loop 驱动实现通过测试
@@ -240,9 +242,25 @@ ai-spec config --model <name> # 设置默认 spec model
240
242
  ai-spec config --codegen <mode> # 设置默认 codegen 模式
241
243
  ai-spec config --codegen-provider <name> # 设置默认 codegen provider
242
244
  ai-spec config --codegen-model <name> # 设置默认 codegen model
245
+ ai-spec config --min-spec-score <n> # 设置 Spec 质量门槛(1-10,0 = 禁用)
243
246
  ai-spec config --reset # 清空配置文件
244
247
  ```
245
248
 
249
+ > **Spec 质量门槛(minSpecScore)**
250
+ > - 设置后,`create` 在 Approval Gate 前会运行质量评估,`overallScore` 低于阈值时阻断流程
251
+ > - **`--auto` 模式同样生效**:CI 环境中配置了门槛则强制执行,避免低质量 Spec 静默通过
252
+ > - `--force` 可临时绕过(输出黄色警告)
253
+ > - 未配置(默认 0)时评估仅为建议性,不阻断
254
+
255
+ #### `ai-spec learn`
256
+
257
+ ```
258
+ ai-spec learn "教训或决策描述" # 直接写入宪法 §9
259
+ ai-spec learn # 省略时交互式输入
260
+ ```
261
+
262
+ > 适合混用其他 AI 工具(Cursor / Copilot)的团队:在任何场景发现问题或做出架构决策时,无需经过完整 review 流程,直接将知识写入宪法,下次 `create` 即生效。
263
+
246
264
  #### `ai-spec workspace`
247
265
 
248
266
  ```
@@ -277,12 +295,14 @@ ai-spec export --dsl <path> # 指定 DSL 文件
277
295
  #### `ai-spec mock`
278
296
 
279
297
  ```
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
298
+ ai-spec mock # 读取最新 DSL,生成 mock/server.js(Express 独立 Mock 服务器)
299
+ ai-spec mock --port 3002 # 指定端口(默认 3001)
300
+ ai-spec mock --proxy # 同时生成前端框架 Proxy 配置片段(Vite/Next.js/webpack 自动识别)
301
+ ai-spec mock --msw # 同时生成 MSW Handlers(src/mocks/handlers.ts + browser.ts)
302
+ ai-spec mock --dsl <path> # 指定 DSL 文件路径(默认自动寻找最新)
303
+ ai-spec mock --workspace # 为工作区内所有后端 repo 批量生成 Mock
304
+ ai-spec mock --serve --frontend <path> # 生成后直接启动 Mock 服务器 + 自动 patch 前端 Proxy
305
+ ai-spec mock --restore --frontend <path> # 撤销 Proxy patch,停止 Mock 服务器
286
306
  ```
287
307
 
288
308
  ---
@@ -640,8 +660,27 @@ ai-spec mock --port 3002 --proxy --msw
640
660
 
641
661
  # 为工作区所有后端 repo 批量生成
642
662
  ai-spec mock --workspace
663
+
664
+ # ── 一键联调(推荐)──────────────────────────────────────────
665
+ # 生成 + 启动 Mock 服务器(后台) + 自动 patch 前端 Proxy
666
+ ai-spec mock --serve --frontend ../my-frontend
667
+
668
+ # 联调结束后恢复(撤销 Proxy patch,停止 Mock 服务器)
669
+ ai-spec mock --restore --frontend ../my-frontend
643
670
  ```
644
671
 
672
+ **`--serve` 详解:**
673
+
674
+ `--serve` 做以下三件事:
675
+ 1. 在后台启动 `node mock/server.js`(PID 记录在 `.ai-spec-mock.lock.json`)
676
+ 2. 根据前端框架自动 patch Proxy 配置:
677
+ - **Vite**:生成 `vite.config.ai-spec-mock.ts`(mergeConfig 方式,非破坏性),在 `package.json` 添加 `dev:mock` 脚本
678
+ - **CRA**:临时修改 `package.json` 的 `"proxy"` 字段(原值备份在 lock 文件)
679
+ - **Next.js / webpack**:打印手动配置说明
680
+ 3. 打印前端启动命令(`npm run dev:mock` 或 `npm start`)
681
+
682
+ `--restore` 的逆操作:删除 `vite.config.ai-spec-mock.ts`、还原 `package.json`、发送 SIGTERM 到 Mock 服务器进程。
683
+
645
684
  **生成的文件:**
646
685
 
647
686
  | 文件 | 说明 |
@@ -653,6 +692,8 @@ ai-spec mock --workspace
653
692
  | `mock/proxy.webpack.comment.txt` | webpack devServer.proxy 配置片段(默认 fallback) |
654
693
  | `src/mocks/handlers.ts` | MSW 请求拦截 handlers(`--msw`) |
655
694
  | `src/mocks/browser.ts` | MSW browser worker 初始化(`--msw`) |
695
+ | `vite.config.ai-spec-mock.ts` | 前端临时 Vite 配置(`--serve`,非破坏性,`--restore` 后删除) |
696
+ | `.ai-spec-mock.lock.json` | Proxy patch 记录 + Mock 服务器 PID(`--restore` 后删除) |
656
697
 
657
698
  **Mock Server 特性:**
658
699
 
@@ -661,18 +702,43 @@ ai-spec mock --workspace
661
702
  - Fixture 数据从 DSL 数据模型的字段类型推断(String → `"example_xxx"`,DateTime → ISO 8601 字符串,etc.)
662
703
  - GET List 端点(描述含 "list"/"all")自动返回分页结构 `{ data: [...], total, page, pageSize }`
663
704
 
664
- **联调工作流:**
705
+ **联调工作流(手动):**
665
706
 
666
707
  ```
667
708
  后端 repo:
668
709
  ai-spec create "用户登录功能" # → 生成 DSL + 代码框架
669
- ai-spec mock --proxy # → 生成 mock/server.js
710
+ ai-spec mock # → 生成 mock/server.js
670
711
  node mock/server.js # → Mock 服务器运行在 localhost:3001
671
712
 
672
713
  前端 repo:
673
714
  配置 Proxy: 将 /api 代理到 localhost:3001 (参见 mock/proxy.*.txt)
674
- # 或者:
675
- ai-spec mock --msw # → 生成 MSW handlers,前端完全脱离后端运行
715
+ ```
716
+
717
+ **联调工作流(一键,推荐):**
718
+
719
+ ```bash
720
+ # 后端 repo 执行(一条命令完成全部)
721
+ cd backend-repo
722
+ ai-spec mock --serve --frontend ../frontend-repo
723
+ # → 自动生成 server.js,启动 Mock 服务器(后台),patch 前端 Proxy
724
+
725
+ # 按提示在前端 repo 启动 Dev Server
726
+ cd ../frontend-repo
727
+ npm run dev:mock
728
+ # → 打开浏览器,直接看到 Mock 数据
729
+
730
+ # 联调结束
731
+ cd ../backend-repo
732
+ ai-spec mock --restore --frontend ../frontend-repo
733
+ ```
734
+
735
+ **工作区一键联调(`ai-spec create --serve`):**
736
+
737
+ 在多 Repo 工作区模式下,加 `--serve` 标志,Pipeline 完成后自动执行上述流程:
738
+
739
+ ```bash
740
+ ai-spec create "用户登录功能" --serve
741
+ # 完成后自动:生成 Mock → 启动服务器 → patch 前端 Proxy → 打印 dev 命令
676
742
  ```
677
743
 
678
744
  ---
package/RELEASE_LOG.md CHANGED
@@ -2,6 +2,477 @@
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
+
431
+ ## [0.17.0] 2026-03-24 — 宪法全文注入 · Export 精准缓存 · 宪法长度警告
432
+
433
+ ### 1. 宪法全文注入(移除硬截断)
434
+
435
+ **问题**:宪法在所有 prompt 中存在硬截断(`codegen`/`task-generator`/`spec-assessor`/`update` 各处分别为 1500–2000 字符),§9 最新教训恰好位于宪法末尾,最容易被截掉——工具越用越长的宪法反而越来越被忽视。
436
+
437
+ **修复**(涉及 6 处):
438
+ - `core/code-generator.ts` — 代码生成 prompt 中的宪法注入
439
+ - `cli/index.ts` — update 命令中的宪法注入
440
+ - `prompts/update.prompt.ts` — update prompt 构建函数
441
+ - `core/task-generator.ts` — task 生成 prompt
442
+ - `core/spec-assessor.ts` — Spec 质量评估 prompt
443
+ - `core/context-loader.ts` — 项目文件预览从 800 → 2000 字符
444
+
445
+ 现代模型(Claude/Gemini/Qwen3)上下文窗口充足,宪法通常 3000–8000 字符,全文注入不会造成负担,但能确保 §9 始终被 AI 读到。
446
+
447
+ ### 2. Generated File Cache — Export 精准提取
448
+
449
+ **问题**:跨 task 一致性保障依赖 `generatedFileCache`,原实现截取每个缓存文件的前 800 字符注入后续 task prompt。对于超过 30 行的 service/api 文件,大量 export 函数名落在 800 字符之外,跨 task 函数名幻觉问题依然存在于大文件场景。
450
+
451
+ **修复**(`core/code-generator.ts`):新增 `extractExportSignatures()` 函数,从文件全文中提取**所有以 `export` 开头的声明行**,注入后续 task prompt。无论文件长度,所有导出名称完整可见;对无显式 export 的文件(CommonJS)回退到前 3000 字符。
452
+
453
+ ```typescript
454
+ // Before: 取前 800 字符,大文件的 export 被截掉
455
+ content.slice(0, 800)
456
+
457
+ // After: 提取所有 export 声明行,精准且不浪费 token
458
+ export function getUserList(...): Promise<...>
459
+ export function createUser(...): Promise<...>
460
+ export const updateUser = ...
461
+ // ...全部导出,不含实现细节
462
+ ```
463
+
464
+ ### 3. 宪法长度警告
465
+
466
+ **新增**:当宪法超过 **6,000 字符**时,`create` / `update` / workspace 各命令加载上下文后自动输出提示:
467
+
468
+ ```
469
+ ⚠ Constitution is long (8,432 chars). Consider running: ai-spec init --consolidate
470
+ ```
471
+
472
+ 设计原则:不阻断流程,纯提示性;帮助用户在宪法真正影响 AI 注意力之前主动整合,而不是等到效果已经变差才发现。
473
+
474
+ ---
475
+
5
476
  ## [0.16.0] 2026-03-24 — Spec 质量预评估 · 分层代码审查 · TDD 模式
6
477
 
7
478
  ### 1. Spec 质量预评估(`core/spec-assessor.ts`, `prompts/spec-assess.prompt.ts`)