@zhuan-ai/zhuanspec 2.15.7 → 2.16.2

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.
Files changed (43) hide show
  1. package/dist/cli/hooks.d.ts +13 -1
  2. package/dist/cli/hooks.js +75 -2
  3. package/dist/cli/index.js +111 -4
  4. package/dist/commands/accuracy.js +5 -1
  5. package/dist/commands/knowledge.d.ts +21 -0
  6. package/dist/commands/knowledge.js +80 -0
  7. package/dist/commands/progress.d.ts +78 -0
  8. package/dist/commands/progress.js +349 -3
  9. package/dist/core/archive.js +28 -0
  10. package/dist/core/configurators/codex.d.ts +55 -1
  11. package/dist/core/configurators/codex.js +234 -2
  12. package/dist/core/corrections/select-candidates.d.ts +58 -0
  13. package/dist/core/corrections/select-candidates.js +357 -0
  14. package/dist/core/hooks/collect-knowledge.js +80 -5
  15. package/dist/core/hooks/deviation-check.d.ts +26 -1
  16. package/dist/core/hooks/deviation-check.js +32 -184
  17. package/dist/core/hooks/knowledge-index.d.ts +84 -0
  18. package/dist/core/hooks/knowledge-index.js +270 -0
  19. package/dist/core/hooks/post-archive.js +25 -13
  20. package/dist/core/hooks/record-progress.d.ts +64 -1
  21. package/dist/core/hooks/record-progress.js +224 -54
  22. package/dist/core/hooks/summarize.js +107 -20
  23. package/dist/core/hooks/user-input-hook.d.ts +38 -2
  24. package/dist/core/hooks/user-input-hook.js +346 -21
  25. package/dist/core/init.d.ts +16 -0
  26. package/dist/core/init.js +208 -11
  27. package/dist/core/metrics/code-accuracy.d.ts +152 -3
  28. package/dist/core/metrics/code-accuracy.js +323 -19
  29. package/dist/core/templates/agents-root-stub.d.ts +1 -1
  30. package/dist/core/templates/agents-root-stub.js +1 -0
  31. package/dist/core/templates/agents-template.d.ts +1 -1
  32. package/dist/core/templates/agents-template.js +27 -25
  33. package/dist/core/templates/codex-hooks-template.d.ts +37 -0
  34. package/dist/core/templates/codex-hooks-template.js +33 -2
  35. package/dist/core/templates/slash-command-templates.js +208 -66
  36. package/dist/core/templates/tasks-template.js +66 -14
  37. package/dist/core/update.js +17 -0
  38. package/dist/core/validation/strict-rules.d.ts +28 -0
  39. package/dist/core/validation/strict-rules.js +284 -0
  40. package/dist/utils/hook-merge.d.ts +6 -0
  41. package/dist/utils/hook-merge.js +33 -2
  42. package/dist/utils/phase-utils.js +5 -0
  43. package/package.json +22 -20
@@ -2,9 +2,9 @@ const baseGuardrails = `**约束条件**
2
2
  - **语言要求**:必须使用中文回答所有问题和输出所有内容(All responses MUST be in Chinese)。
3
3
  - 优先采用简单、最小化的实现,仅在请求或明确需要时添加复杂性。
4
4
  - 将更改严格限制在请求的结果范围内。
5
- - **工作区边界(强制)**:查找文档、检索工程代码、读取 \`.llm-wiki\`、执行 grep/glob/ls 时,范围必须限定在当前 ZhuanSpec 工作区内。禁止使用 \`../**\`、上级目录绝对路径或手动拼接到工作区外路径。Glob 返回相对路径时,必须以本次工具调用的 \`path\` 参数作为基准拼接绝对路径,不得误解为当前目录或上级目录。
5
+ - **工作区边界(强制)**:查找文档、检索工程代码、执行 grep/glob/ls 时,范围必须限定在当前 ZhuanSpec 工作区内。禁止使用 \`../**\`、上级目录绝对路径或手动拼接到工作区外路径。Glob 返回相对路径时,必须以本次工具调用的 \`path\` 参数作为基准拼接绝对路径,不得误解为当前目录或上级目录。
6
6
  - **知识库参考**:开始任何阶段前,先检查 \`zhuanspec/knowledge/\` 目录。使用 \`rg "[关键词]" zhuanspec/knowledge/\` 搜索相关陷阱和最佳实践,避免重复踩坑。阅读 \`zhuanspec/knowledge/index.md\` 了解项目级知识摘要。
7
- - **工程代码检索顺序**:凡是需要检索工程代码、配置类、数据模型类或关键实现位置时,优先读取已定位服务目录下的 \`[service]/.llm-wiki/index.md\`。\`llmwiki query -e --token <token> "[关键词]"\` 中的 \`<token>\` 必须来自对应服务的 \`[service]/.llm-wiki/index.md\`;每次执行 \`llmwiki query\` 后,必须判断查询结果是否与当前请求诉求匹配,并将关键词、服务、匹配/不匹配结论、简要原因记录到对应服务的 \`[service]/.llm-wiki/result.log\`;查配置类、数据模型类、配置项归属时优先使用 \`llmwiki knowledge points "[关键词]"\`。仅当对应服务的 \`.llm-wiki/\` 不存在、llmwiki 无结果、结果与当前请求诉求不匹配、或结果明显偏差时,才回退到 \`grep/glob/ls\`。
7
+ - **工程代码检索顺序**:凡是需要检索工程代码、配置类、数据模型类或关键实现位置时,必须先调用 \`@skill:load-project-knowledge\` 进行渐进式加载,使用返回的 search_priority 限定检索范围,按优先路径定位代码。仅当 Skill 无匹配结果时,才回退到 \`grep/glob/ls\`。
8
8
  - 如果需要额外的 ZhuanSpec 约定或澄清,请参考 \`zhuanspec/AGENTS.md\`(位于 \`zhuanspec/\` 目录内 - 如果看不到,请运行 \`ls zhuanspec\` 或 \`zhuanspec update\`)。`;
9
9
  const proposalGuardrails = `${baseGuardrails}\n- **强制澄清要求**:在创建任何提案文件之前,必须首先分析用户请求,识别所有不确定或模糊的方面(范围、技术选择、优先级、验收标准等)。如果发现任何模糊之处,必须停止并使用**选项式交互**(如 \`AskQuestion\` 工具)提问,获得明确答复后才能继续。严禁在不确定的情况下自行推测、假设或创建提案。严禁要求用户手动输入大段文字来回答澄清问题。
10
10
  - 识别任何模糊或歧义的细节,使用带预设选项的选择题在编辑文件之前询问必要的后续问题。
@@ -66,13 +66,7 @@ const proposalSteps = `**步骤**
66
66
  * 获取:matched_services(涉及的服务列表)、search_priority(检索优先路径)、architecture_constraints(架构约束)
67
67
  * 使用:后续代码定位使用 search_priority 限定范围,方案设计检查 architecture_constraints
68
68
  - 审查 \`zhuanspec/project.md\`,运行 \`zhuanspec list\` 和 \`zhuanspec list --specs\`
69
- - 检查已定位服务是否存在 \`[service]/.llm-wiki/\`:
70
- * 若存在,先阅读对应服务目录下的 \`[service]/.llm-wiki/index.md\`
71
- * \`llmwiki query -e --token <token> "[关键词]"\` 中的 \`<token>\` 必须来自对应服务的 \`[service]/.llm-wiki/index.md\`
72
- * 功能/实现定位优先使用 \`llmwiki query -e --token <token> "[关键词]"\`
73
- * 每次执行 \`llmwiki query\` 后,必须判断查询结果是否与当前请求诉求匹配,并将关键词、服务、匹配/不匹配结论、简要原因记录到对应服务的 \`[service]/.llm-wiki/result.log\`
74
- * 配置类、数据模型类、配置项归属优先使用 \`llmwiki knowledge points "[关键词]"\`
75
- - 检查相关代码或文档时,优先使用 llmwiki 的结果缩小范围;仅当对应服务的 \`.llm-wiki/\` 不存在、llmwiki 无结果、结果与当前请求诉求不匹配、或结果明显偏差时,才通过 \`rg\`/\`ls\`/\`glob\` 兜底;注意任何需要澄清的空白。
69
+ - **工程代码检索**:使用 \`@skill:load-project-knowledge\` 返回的 search_priority 限定检索范围,按优先路径定位代码;仅当 Skill 无匹配结果时,才通过 \`rg\`/\`ls\`/\`glob\` 兆底。
76
70
  - **TechDesign 目录识别**:
77
71
  * 扫描 changes/ 目录下的所有变更
78
72
  * 检查每个变更的 metrics/progress.json 的 phase 字段
@@ -177,6 +171,36 @@ const proposalSteps = `**步骤**
177
171
  * 分层实现说明、关键逻辑 → 写入 \`## 实现细节\`
178
172
  * 参数校验、错误码、异常处理 → 写入 \`## 边界条件 / 异常处理\`
179
173
  - **摄取原则**:保留原始章节标题和结构,便于 apply 阶段按章节定位;不要压缩或省略具体字段定义
174
+
175
+ ⚠️ **CHECKPOINT [DESIGN-EXTERNAL-DEPENDENCY-GATE]**(提案阶段前置闭环,必须在创建 design.md 后立即执行):
176
+ 依据 techDesign 阶段产出的外部依赖清单(如不存在则从用户提供的技术方案 / specs 中提取),对每一项依赖执行“有疑问就 AskQuestion”原则:
177
+ 1. **依赖识别**:全量罗列 ES 索引 / MQ Topic / Redis key / SCF-RPC 接口 / HTTP API / OSS / Apollo 配置 / 定时任务 共 8 类外部依赖,按类型分桶
178
+ 2. **硬规则使用 AskQuestion**:只要某项依赖的状态、版本、负责方、兜底策略任一字段不明确,**必须** 调用 \`AskQuestion\` 工具一次性展示;严禁默认写 ✅ 或 “待确认”跳过
179
+ 3. **矩阵数据落地**:根据用户回答将结果写入 design.md 的「外部依赖可用性矩阵」段(**6 列**,格式见下),作为后续 propose / apply / 集成验证阶段的唯一事实源
180
+ 4. **闭环完结**:本步骤结束前对账——所有 techDesign 阶段标记为 ⚠️/❓ 的条目必须沉淀为 ✅ / ❌ / ✅+兜底,不允许留白
181
+
182
+ 外部依赖可用性矩阵(6 列标准格式,必须出现在 design.md):
183
+ \`\`\`markdown
184
+ ## 外部依赖可用性矩阵
185
+
186
+ | 依赖名称 | 类型 | 状态 | 版本/环境 | 兜底/阻塞策略 | 负责方 |
187
+ |----------|------|------|-----------|------------------|--------|
188
+ | t_customer_ext ES 索引 | ES | ✅ 可用 | prod v7.10 | 必须真实接入 | DBA @zhangsan |
189
+ | 员工组织树 API | SCF-RPC | ❌ 不可用 | — | 标记 BLOCKED,不生成占位代码 | HR @lisi |
190
+ | zzmq:customer-sync | MQ | ⚠️ 待确认 | pre 环境未建 | 未解除前用 DB 轮询兜底 | infra @wangwu |
191
+ | \`dh:customer:merge:*\` Redisson 键 | Redis | ✅ 可用 | prod v4.x | 统一键前缀 + 30s TTL | 本域 |
192
+ | OSS 导出桶 | OSS | ⚠️ 待确认 | bucket 未申请 | 先用本地文件兜底 | ops @zhaoliu |
193
+ | Apollo 配置空间 customer.limit | Config | ✅ 可用 | prod | 新增 key 默认值 100 | 本域 |
194
+ \`\`\`
195
+
196
+ 列含义:
197
+ - **依赖名称**:具体到索引/Topic/键/接口类名,禁止写“ES”/“MQ”等类型占位
198
+ - **类型**:枚举 \`ES|MQ|Redis|SCF-RPC|HTTP|OSS|Config|Job\` 八桶之一
199
+ - **状态**:枚举 \`✅ 可用\` / \`⚠️ 待确认\` / \`❌ 不可用\`
200
+ - **版本/环境**:写出确认的版本号或部署环境,未确认则与“状态=⚠️”保持一致
201
+ - **兜底/阻塞策略**:状态=❌ 必须写 “标记 BLOCKED...”;状态=⚠️ 必须写出兜底方案
202
+ - **负责方**:确认人或模块负责人(可写 “本域” 表示无需外部确认)
203
+
180
204
  6. 在 \`changes/<id>/specs/<capability>/spec.md\` 中起草规范增量(每个功能一个文件夹),使用 \`## ADDED|MODIFIED|REMOVED Requirements\`,每个要求至少包含一个 \`#### Scenario:\`,并在相关时交叉引用相关功能。
181
205
 
182
206
  ⚠️ **CHECKPOINT [SPEC-REQUIREMENT-FORMAT]**:
@@ -304,19 +328,21 @@ const proposalSteps = `**步骤**
304
328
  - [ ] 每个任务的「内容」字段自包含:AI 执行时不需要再回溯技术方案猜测实现细节
305
329
 
306
330
  **D. 外部依赖可用性**(必须在 design.md 中列出):
307
- - [ ] design.md 包含"外部依赖可用性矩阵"段
331
+ - [ ] design.md 包含"外部依赖可用性矩阵"段(**6 列**:依赖名称 / 类型 / 状态 / 版本环境 / 兜底阻塞策略 / 负责方)
332
+ - [ ] 矩阵条目按 8 类分桶完整罗列:ES / MQ / Redis / SCF-RPC / HTTP / OSS / Config / Job
308
333
  - [ ] 每个外部依赖标注状态:✅ 可用 / ⚠️ 待确认 / ❌ 不可用
309
334
  - [ ] 状态为 ❌ 的依赖,对应功能在 tasks.md 中标注"不生成占位实现,标记 BLOCKED"
310
335
  - [ ] 状态为 ⚠️ 的依赖,说明兜底方案(如 ES 不可用时用 DB 查询兜底)
311
-
312
- 依赖矩阵格式(必须出现在 design.md 中):
336
+ - [ ] 条目不得留空或写 TBD,疑问必须在步骤 5 的 DESIGN-EXTERNAL-DEPENDENCY-GATE 中通过 AskQuestion 解决
337
+
338
+ 依赖矩阵格式(必须出现在 design.md 中,6 列):
313
339
  \`\`\`
314
- | 依赖 | 状态 | 阻塞策略 |
315
- |------|------|---------|
316
- | ES 集群 | ✅ 可用 | 必须真实接入 |
317
- | 员工组织树 API | ❌ 不可用 | 标记 BLOCKED,不生成占位代码 |
318
- | MQ Topic | ✅ 可用 | 必须真实消费 |
319
- | OSS 导出 | ⚠️ 待确认 | 先用本地文件兜底 |
340
+ | 依赖名称 | 类型 | 状态 | 版本/环境 | 兜底/阻塞策略 | 负责方 |
341
+ |----------|------|------|-----------|------------------|--------|
342
+ | t_customer_ext ES 索引 | ES | ✅ 可用 | prod v7.10 | 必须真实接入 | DBA @zhangsan |
343
+ | 员工组织树 API | SCF-RPC | ❌ 不可用 | — | 标记 BLOCKED,不生成占位代码 | HR @lisi |
344
+ | zzmq:customer-sync | MQ | ✅ 可用 | prod | 必须真实消费 | infra @wangwu |
345
+ | OSS 导出桶 | OSS | ⚠️ 待确认 | bucket 未申请 | 先用本地文件兜底 | ops @zhaoliu |
320
346
  \`\`\`
321
347
 
322
348
  **E. 测试与验收标准**(若为 TDD 模式或已提供测试 case):
@@ -396,7 +422,7 @@ const proposalSteps = `**步骤**
396
422
  const proposalReferences = `**参考**
397
423
  - 当验证失败时,使用 \`zhuanspec show <id> --json --deltas-only\` 或 \`zhuanspec show <spec> --type spec\` 检查详细信息。
398
424
  - 在编写新要求之前,使用 \`rg -n "Requirement:|Scenario:" zhuanspec/specs\` 搜索现有要求。
399
- - 探索代码库时,先检查已定位服务目录下是否存在 \`[service]/.llm-wiki/\`;若存在,先阅读 \`[service]/.llm-wiki/index.md\`,并使用其中提供的 token 执行 \`llmwiki query -e --token <token> <keyword>\`,随后判断查询结果是否与当前请求诉求匹配,并将关键词、服务、匹配/不匹配结论、简要原因记录到对应服务的 \`[service]/.llm-wiki/result.log\`;也可使用 \`llmwiki knowledge points <keyword>\` 缩小范围。仅在 llmwiki 不可用、未命中、或结果与当前请求诉求不匹配时,再使用 \`rg <keyword>\`、\`ls\` 或直接文件读取。`;
425
+ - 探索代码库时,先调用 \`@skill:load-project-knowledge\` 进行渐进式加载,使用返回的 search_priority 限定检索范围,按优先路径定位代码。仅当 Skill 无匹配结果时,再使用 \`rg <keyword>\`、\`ls\` 或直接文件读取。`;
400
426
  const applySteps = `**步骤**
401
427
  将这些步骤作为待办事项跟踪,逐一完成。
402
428
  1. **检查知识库并确认 Phase**:
@@ -503,15 +529,67 @@ const applySteps = `**步骤**
503
529
  - 提取状态为 DONE_WITH_CONCERNS 或 BLOCKED 的任务及其 concerns/blocker 原因
504
530
  - 将结果记录到集成测试报告的 **Concerns 追踪章节**
505
531
 
506
- B5. **阻塞任务重试**:
507
- - 将当前 Wave 中编译失败被标记为 BLOCKED 的任务重新执行
508
- - 重新启动 subagent 执行阻塞任务(此时可利用同 Wave 已完成任务的上下文)
509
- - 重试后仍失败 → 记录到集成测试报告
532
+ B4.1. **外部依赖全量扫描与兜底闭环(MANDATORY,不允许遗漏)**:
533
+ 此环节是提案阶段 DESIGN-EXTERNAL-DEPENDENCY-GATE 的**集成验证兑现验收点**,用于兜底“新产生的未知外部依赖 / 原矩阵漏网项”,严禁遗漏。步骤必须完整依序执行:
534
+
535
+ **第一步:三类来源全量采集**
536
+ 1. 从 \`design.md\` 的「外部依赖可用性矩阵」6 列表格提取原始清单(包含状态 ✅ / ⚠️ / ❌ 和负责方)
537
+ 2. 从本 Wave 所有任务报告的 concerns / blocker 文本中提取涉及外部依赖的条目(关键词:ES / 索引 / MQ / Topic / Consumer / Redis / RPC / SCF / HTTP / OSS / Apollo / xxl-job / 定时任务 ...)
538
+ 3. 对本 Wave 新增 / 修改的源码做静态扫描,抓取上述关键词所对应的注解 / API 调用 / Bean 注入(例:\`@MessageConsumer\` / \`RedisTemplate\` / \`@ApolloJsonValue\` / \`@XxlJob\` / \`@ServiceContract\`)
539
+
540
+ **第二步:按下述 8 桶分类**,将第一步的汇总项映射到桶中,**每一桶都必须给出结论**(没有项 → 显式写 \`—\` 并注明已确认无依赖,禁止跳过桶):
541
+ \`\`\`
542
+ 桶 1:ES(索引 / 查询 / 异构同步)
543
+ 桶 2:MQ(zzmq / RocketMQ Producer / Consumer / Topic)
544
+ 桶 3:Redis(缓存 key / Redisson 分布式锁 / ZZLock)
545
+ 桶 4:SCF-RPC(@ServiceContract 下游接口 / contract、client pom 依赖是否已引入 / 版本是否需要升级)
546
+ 桶 5:HTTP(第三方 REST API / 网关 / Webhook)
547
+ 桶 6:OSS(导入 / 导出 / 附件存储 bucket)
548
+ 桶 7:Config(Apollo namespace / 环境变量 / 配置项)
549
+ 桶 8:Job(xxl-job 注册 / cron / 分片任务)
550
+ \`\`\`
551
+
552
+ **第三步:状态不明确的桶强制 AskQuestion**
553
+ - 对任一桶中出现下列情形 → **必须** 调用 \`AskQuestion\` 一次性批量向用户澄清:
554
+ * design.md 矩阵中状态=❌ 或 ⚠️ ,且任务报告仍在涉及该依赖
555
+ * 第一步代码扫描发现新的 / 未录入矩阵的依赖项
556
+ * 任务报告的 concern 文本明确说明“给了占位 / 默认兜底 / 待核实”
557
+ * 桶内无任何条目 但 Wave 新增代码涉及该类型关键词(依赖声明遗漏)
558
+ - 严禁以“任务状态为 DONE_WITH_CONCERNS 且有报告就算闭环”为由跳过 AskQuestion;必须拿到用户选项式答复
559
+
560
+ **第四步:对账表写回集成报告**
561
+ - 将本步骤结果写入集成测试报告的 **外部依赖兜底对账表**(5 列):
562
+ \`\`\`
563
+ | 桶 | 依赖条目 | 来源(矩阵/报告/代码) | 解决状态(✅ 真实实现 / ❌ BLOCKED / ✅+兜底) | 后续动作 |
564
+ \`\`\`
565
+ - 所有 ✅+兜底 条目必须同步回写 design.md 矩阵(结束时两份数据保持一致)
566
+ - 存在任一桶结论缺失 → B6 报告整体状态强制标记 FAIL,阻断进入下一 Wave
567
+
568
+ **第五步:依赖补齐后即刻列出重跑清单(MANDATORY,澄清 ≠ 闭环)**
569
+ - 扫描本 Wave 所有状态为 \`NEEDS_CONTEXT\` 或 \`BLOCKED\` 的任务报告,识别「阻断原因涉及本次 AskQuestion 已澄清依赖 / 兜底对账表中解决状态变为 ✅ 的条目」的任务
570
+ - 在集成测试报告中新增 \`## 🔁 待重试任务清单\` 段(5 列):
571
+ \`\`\`
572
+ | 任务ID | 原状态 | 阻断原因(concern 摘要) | 已澄清/补齐的依赖条目 | 重跑执行方 |
573
+ \`\`\`
574
+ - **立刻移交 B5 统一执行重跑**(不得拖到全局 Concerns 汇总;不得将 NEEDS_CONTEXT 当 DONE_WITH_CONCERNS 混过)
575
+ - 若清单为空(本 Wave 无需重跑)→ 显式写 \`— 无需重跑\`,禁止省略该段
576
+
577
+ B5. **阻塞任务重试(BLOCKED ∪ NEEDS_CONTEXT 合并处理)**:
578
+ - 重试对象覆盖两类:
579
+ a. 编译失败 / 测试失败被标记为 \`BLOCKED\` 的任务(原有范围)
580
+ b. B4.1 第五步「待重试任务清单」中因外部依赖已澄清而解锁的 \`NEEDS_CONTEXT\` / \`BLOCKED\` 任务
581
+ - 重跑前确认:design.md 矩阵已写回澄清结果(与兜底对账表一致),否则 subagent 仍会读到旧状态再次报 NEEDS_CONTEXT
582
+ - 重新启动 subagent(\`applyAgent\` / \`tddApplyAgent\`),**在下发 prompt 中显式标注 \`Execution Mode = RETRY\`** 并附带:
583
+ * 上次报告中的 concerns / blocker 摘要
584
+ * 本次澄清补齐的依赖条目(来自兜底对账表)
585
+ * 最新 design.md 矩阵片段
586
+ - 重试后仍失败 → 保留 BLOCKED 状态并记录到集成测试报告;B6 整体状态强制 FAIL
510
587
 
511
588
  B6. **生成集成测试报告(MANDATORY,不得跳过)**:
512
589
  - 报告路径:\`changes/<change-id>/reports/wave-{N}-integration-report.md\`
513
590
  - 记录所有任务执行结果、编译检查结果、阻塞任务重试结果
514
591
  - **MUST 包含 Concerns 追踪章节**,列出所有 DONE_WITH_CONCERNS 和 BLOCKED 任务及其疑虑
592
+ - **MUST 包含 \`## 🔁 待重试任务清单\` 段**(即使为空也要写 \`— 无需重跑\`),与 B4.1 第五步、B5 重试结果汇总一致
515
593
  - 整体状态:所有检查通过且无未解决的阻塞任务 → PASS
516
594
  - **未生成报告文件 → 阻断,不得进入下一 Wave**
517
595
 
@@ -551,9 +629,10 @@ const applySteps = `**步骤**
551
629
  - 如果存在未解决的 Concerns:
552
630
  * 输出汇总列表(任务ID、状态、疑虑内容、建议后续处理)
553
631
  * **选项式提问用户**:
554
- a. “全部修复” → 逐个处理未解决的 concerns
555
- b. “忽略并继续” → 记录用户决策后进入 TC 验证
556
- c. “部分修复” → 让用户选择哪些需要修复
632
+ a. “全部修复” → 对每个未解决 concern 对应任务,**以 \`Execution Mode = RETRY\` 重新下发 subagent**(applyAgent / tddApplyAgent),重跑产出新报告后回到本步骤再次扫描,直至 Concerns 清零或用户改选 b/c
633
+ b. “忽略并继续” → 记录用户决策(含忽略原因)后进入 TC 验证
634
+ c. “部分修复” → 让用户勾选待修复任务,**仅对勾选任务按 RETRY 模式重新下发**,其余记录决策后进入 TC 验证
635
+ * **「修复」选项的执行契约(MANDATORY)**:选 a 或 c 后,对所选任务以 \`Execution Mode = RETRY\` 重新 spawn subagent(applyAgent / tddApplyAgent);prompt 中须附带:上次报告 concerns 摘要 + 本次已澄清的依赖条目 + 最新 design.md 矩阵片段。重跑产出新报告后回到本步骤再次扫描,直至 Concerns 清零或用户改选 b。禁止在主线程串行“修复”或在没有重新产出报告的前提下手动改成 DONE
557
636
  - 如果无未解决的 Concerns:直接进入 TC 验证
558
637
  9. **TC 实现验证** - 所有任务完成后、进入审查门禁前:
559
638
  - 检查提案目录中是否存在 \`test-cases.md\`
@@ -614,12 +693,15 @@ const archiveSteps = `**前置检查**:
614
693
  - \`progress.phaseDurations\` 必须关闭 review 段并开启 archive 段
615
694
  2. 通过运行 \`zhuanspec list\`(或 \`zhuanspec show <id>\`)验证变更 ID,如果变更缺失、已归档或尚未准备好归档,则停止。
616
695
  3. **验证 Review 门禁**:确认上述五个结果文件存在且全部通过(含轨道 4 的 \`closure-check-result.json\`)。
617
- 4. 运行 \`zhuanspec archive <id> --yes\`,以便 CLI 移动变更并应用规范更新,无需提示(仅对仅工具类工作使用 \`--skip-specs\`)。
618
- 5. 审查命令输出以确认目标规范已更新,并且变更已进入 \`changes/archive/\`。
619
- 6. 使用 \`zhuanspec validate --strict\` 进行验证,如果看起来有问题,使用 \`zhuanspec show <id>\` 进行检查。
620
- 7. **知识沉淀(手动补充)**:调用 \`@skill:zhuanspec:knowledge\` skill 从本次会话记忆中补充知识。
696
+ 4. **知识沉淀(手动补充,必须前置)**:调用 \`@skill:zhuanspec:knowledge\` skill(模式 A)从本次会话记忆中补充知识。
697
+ - 🔴 **红线(顺序不可调整)**:本步骤**必须**在执行 \`zhuanspec archive <id>\` 之前完成。\`zhuanspec archive\` 命令内部会按顺序执行 \`postArchiveHook\`(自动结构化提取) → \`pushArchiveResultToRemote\`(一次性同步 specs / archive / knowledge 三目录到远端);如果把手动沉淀放在 archive 命令之后,新写入的 knowledge 文件**仅落本地**,不会被推送到远端模板仓库,团队其他成员将看不到。
698
+ - 🔴 **禁止 AI 自行决定沉淀内容**:必须严格按 zhuanspec:knowledge skill 模式 A 步骤 4 执行——先列候选清单,再调用 \`askUserQuestion\` 让用户多选确认,再写入。禁止默认全沉淀,禁止跳过询问。
621
699
  - CLI 已自动从变更目录提取结构化知识(design.md/proposal.md/tasks.md 中的决策、注意事项等)
622
700
  - AI 需从会话记忆补充无法自动提取的内容(如对话中发现的隐式约定、调试陷阱等)
701
+ - 用户选择「跳过本次沉淀」时,本步骤可不写入任何文件,但仍需经过显式确认环节,禁止默认跳过。
702
+ 5. 运行 \`zhuanspec archive <id> --yes\`,以便 CLI 移动变更并应用规范更新,无需提示(仅对仅工具类工作使用 \`--skip-specs\`)。**该命令将自动 push specs / archive / knowledge 三目录到远端**,因此必须在步骤 4 完成知识沉淀后才执行。
703
+ 6. 审查命令输出以确认目标规范已更新,并且变更已进入 \`changes/archive/\`,且 "推送到远端" 段输出 \`✅ 已推送归档结果到远端\`(如使用 \`--skip-specs\` 则跳过推送)。
704
+ 7. 使用 \`zhuanspec validate --strict\` 进行验证,如果看起来有问题,使用 \`zhuanspec show <id>\` 进行检查。
623
705
  8. **会话分析**:调用 \`@skill:session-analytics\` skill 分析本次会话的指标数据(工具调用、Token消耗、时长等)。
624
706
  9. **输出反馈链接**:告知用户填写使用反馈:
625
707
  📋 https://doc.weixin.qq.com/forms/AJ4AfQfgAAwACwAAwaVABsCNqDXIKn8sf`;
@@ -627,8 +709,8 @@ const archiveReferences = `**参考**
627
709
  - 在归档之前使用 \`zhuanspec list\` 确认变更 ID。
628
710
  - 使用 \`zhuanspec list --specs\` 检查刷新的规范,并在移交之前解决任何验证问题。
629
711
  - 知识提取分工:
630
- - **CLI 自动**:归档时从变更目录(proposal.md/tasks.md/design.md/specs/*.md)正则提取结构化知识
631
- - **AI 手动**:调用 \`zhuanspec:knowledge\` skill 从会话记忆补充隐式约定、调试发现等
712
+ - **CLI 自动**(archive 命令内):归档时从变更目录(proposal.md/tasks.md/design.md/specs/*.md)正则提取结构化知识,写入本地 \`zhuanspec/knowledge/\`,随后由同一条 archive 命令一并 push 到远端
713
+ - **AI 手动**(archive 命令前):调用 \`zhuanspec:knowledge\` skill 从会话记忆补充隐式约定、调试发现等。**必须在 \`zhuanspec archive\` 命令之前**调用,否则补充内容仅落本地、不会进入远端推送
632
714
  - 会话分析 (\`session-analytics\`):记录本次会话的效率指标,用于改进工作流。`;
633
715
  const designGuardrails = `${baseGuardrails}\n- **独立设计阶段**:techDesign 命令用于在 proposal 之前生成技术设计请求文档,不依赖变更提案。设计文档可作为后续提案的输入。
634
716
  - **需求澄清优先**:在生成设计请求前,必须确认需求来源(大神页面、需求描述文本等)。
@@ -709,6 +791,31 @@ const designSteps = `**步骤**
709
791
  - Skill 会自动获取大神页面内容并生成完整技术方案文档
710
792
  - **禁止**:在未完成步骤 4 的开发范围确认和步骤 5 的 Skill 可用性校验前调用任何 Skill;禁止两个 Skill 同时调用。
711
793
 
794
+ 6.5. **新增表澄清与数据存储策略(硬约束,存在新增表时必须执行)**:
795
+ - 从步骤 6 产出的 tech-spec.md 中提取所有 **新增/重构 DB 表**(关键词:CREATE TABLE / 新增表 / t_* / 新建业务表),形成候选表清单。若无新增表 → 跳过本步并在技术方案写明“无新增表,无需数据存储策略评估”
796
+ - 对每张新增表,**必须** 调用 \`AskQuestion\` 向用户批量澄清下列字段(可多表合并一次问答),严禁默认和代书填入:
797
+ 1. **预估数量级**:枚举 \`< 10w\` / \`10w~100w\` / \`100w~1000w\` / \`> 1000w\`
798
+ 2. **查询场景**:枚举 \`单表查询\` / \`连表查询\` / \`跨库查询\` / \`复杂聚合/全文搜索\`
799
+ 3. **QPS 量级**:枚举 \`读 < 50\` / \`读 50~500\` / \`读 > 500\`;写入同样枚举
800
+ 4. **数据时效性**:枚举 \`强一致\` / \`最终一致(分钟级)\` / \`T+1 离线\`
801
+ 5. **一致性要求**:枚举 \`强一致\` / \`最终一致\` / \`弱一致\`;并追问 **是否跨表事务**(是 / 否)
802
+ - 根据用户回答自动推荐 **存储策略**(用 Skill 或启发式规则均可):
803
+ * 数量级 ≥ 100w 且写 QPS 不高 → 建议 **分库分表**(或 OLAP 异构),在技术方案补充分片键 / 路由策略
804
+ * 读 QPS ≥ 500 或 表 ≥ 1000w → 建议 **引入 Redis 缓存**,给出缓存 key / TTL / 失效策略
805
+ * 查询场景为“复杂聚合/全文搜索”或表 ≥ 1000w 且需多维度筛选 → 建议 **引入 ES 异构索引**,描述写入时机与同步方案
806
+ * 一致性要求为“强一致”且跨表事务为“是” → 不使用 最终一致方案(Redis/ES 异构 仅做旁路),主链路用 MySQL 事务,必要时补 TCC / 补偿
807
+ * 其余情形 → 保留仅 MySQL,补充必要索引设计
808
+ - 将澄清结果和存储决策写入技术方案的「## 数据存储策略」段(固定模板):
809
+ \`\`\`markdown
810
+ ## 数据存储策略
811
+
812
+ | 表名 | 预估数量级 | 查询场景 | 读/写 QPS | 时效性 | 一致性(含跨表事务) | 存储策略 | 备注 |
813
+ |------|-----------|---------|------------|--------|-------------------|---------|------|
814
+ | t_customer_ext | 100w~1000w | 多维度筛选 | 800 / 100 | 最终一致 | 最终一致 / 否 | MySQL + ES 异构 | 写入后异步同步 ES |
815
+ | t_customer_tag_link | < 10w | 单表 | 50 / 5 | 强一致 | 强一致 / 是 | 仅 MySQL + 联合索引(tenant_id,customer_id) | — |
816
+ \`\`\`
817
+ - ⚠️ **CHECKPOINT [DATA-STORAGE-STRATEGY]**:表行任一列写 \`TBD\` / 空 / \`待评估\` → 本步骤未通过,禁止进入步骤 7
818
+
712
819
  7. **外部依赖可用性确认(必须在技术方案定稿前执行)**:
713
820
  - 从 Skill 生成的技术方案中提取所有外部依赖(ES、MQ、Redis、OSS、权限服务、员工组织树 API、下游 RPC 等)
714
821
  - 使用 AskQuestion 工具逐项确认可用状态:
@@ -757,24 +864,34 @@ const reviewGuardrails = `${baseGuardrails}\n- **门禁审查阶段**:review
757
864
  - **Schema 版本**:新生成的 \`code-review-result.json\` / \`unit-test-result.json\` / \`closure-check-result.json\` 必须包含 \`"schemaVersion": 2\` 字段以启用 Skill 真实性硬校验;缺失或 < 2 时 CLI 会按历史数据豁免并打 ⚠️ 警告,禁止借 legacy 通道规避校验。`;
758
865
  const reviewSteps = `**步骤**
759
866
  0. **⚠️ 纠偏沉淀优先检查(Phase 切换前强制执行)**:
760
- - 读取 \`zhuanspec/changes/<change-id>/metrics/progress.json\`,检查以下两个字段:
761
- - \`corrections\` 数组是否存在且有元素(\`length > 0\`)
867
+ - **计数源(两级 fallback,新→旧)**:
868
+ - Level 1:读 \`zhuanspec/changes/<change-id>/metrics/user_inputs.json\`,筛选 \`correctionSignal.kind === 'hard' && postBaseline === true\` 的条目作为纠偏明细
869
+ - Level 2:\`user_inputs.json\` 存在但条目缺 \`correctionSignal\` → 按 \`inputs[*].summary\` 关键词扫描推断
870
+ - **同时读** \`zhuanspec/changes/<change-id>/metrics/progress.json\`,检查:
871
+ - 上述任一 Level 得到的纠偏条目数 N 是否 > 0
762
872
  - \`askedPitfallSaved\` 字段是否为 \`true\`
763
- - **如果满足条件(corrections 非空 且 askedPitfallSaved !== true)**:
764
- - **立即调用 \`AskUserQuestion\` 工具**,以二选一方式询问用户:
765
- \`\`\`
766
- header: "踩坑沉淀"
767
- question: "本轮 Apply 阶段发生过 N 次用户纠偏(N 为 corrections 数组的实际长度,请列出最近 3 条 promptPreview 摘要),是否沉淀为项目知识?"
768
- 选项 1: "是,沉淀"
769
- 选项 2: "否,跳过"
770
- \`\`\`
771
- - **用户选择"是"时**:
772
- 1. **必须调用 \`@skill:zhuanspec:knowledge --mode=correction --correction <change-id>\`**(或等价的 \`/zhuanspec:knowledge\` slash command 并在交互中选择模式 B)来完成沉淀
773
- 2. 本 skill 将自动完成:读取 \`.correction-log\` → 分类决策树归入 \`troubleshooting/\` / \`best-practices/\` / \`implicit-conventions/\` → 去重扫描 → 套用统一 Front Matter → 写入知识文件 → 更新 \`knowledge/index.md\` → 运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\`
774
- 3. **红线**:**禁止主 agent 自行使用 Write/Edit 创建 \`zhuanspec/knowledge/\` 下的任何文件**,禁止自行判定分类或文件名格式;禁止新建 \`decisions/\` 或三类目录以外的分类。
775
- - **用户选择"否"时**:
776
- - 运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\` 标记已处理,不写入任何知识文件
777
- - **如果不满足条件(无纠偏或已沉淀)**:直接进入下一步
873
+ - **如果满足条件(N > 0 且 askedPitfallSaved !== true)**:
874
+ 1. **先生成决策清单(必须)**:运行
875
+ \`\`\`bash
876
+ zhuanspec progress list-corrections <change-id>
877
+ \`\`\`
878
+ CLI 会完成:读 user_inputs.json → 过滤 trivial 确认词(如“是的/好的/ok”)→ 去重(完全重复 + 子串包含)→ 启发式分类 → 写到 \`zhuanspec/changes/<change-id>/review/pending-corrections.md\`。并在 stdout 输出 **合计 / 有效 / 过滤** 三个计数。
879
+ 2. **调用 \`AskUserQuestion\`(三选项,禁止默认)**:
880
+ \`\`\`
881
+ header: "踩坑沉淀"
882
+ question: "本轮有 M 条有效纠偏候选(已过滤 trivial / 去重,详见 review/pending-corrections.md),请选择沉淀范围:"
883
+ 选项 1:"全部沉淀"
884
+ 选项 2:"选择性沉淀(请回复编号清单,例如 1,3,5)"
885
+ 选项 3:"跳过"
886
+ \`\`\`
887
+ 🔴 **红线**:禁止跳过本次询问;禁止仅根据最近 N 条摘要就起心动念、绕过清单文件。
888
+ 3. **用户选择 "全部沉淀" 或 "选择性沉淀"**:
889
+ - 必须调用 \`@skill:zhuanspec:knowledge --mode=correction --correction <change-id>\`(或 \`/zhuanspec:knowledge\` 交互模式 B)来完成沉淀。
890
+ - 选择性沉淀时,把用户回复的编号清单以 \`--include <编号串>\` 形式透传给 skill(例:\`--include 1,3,5\`),或在 skill 交互中照实转述编号。skill 必须以 \`pending-corrections.md\` 作为商定范围的单一源,禁止从会话记忆里“发挥”额外条目。
891
+ - skill 完成后会自动运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\`。
892
+ 🔴 **红线**:禁止主 agent 自行使用 Write/Edit 创建 \`zhuanspec/knowledge/\` 下的任何文件;禁止自行判定分类或文件名格式;禁止新建 \`decisions/\` 或三类目录以外的分类。
893
+ 4. **用户选择 "跳过"**:运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\` 标记已处理,不写入任何知识文件。
894
+ - **如果不满足条件(无纠偏或已沉淀)**:直接进入下一步。
778
895
 
779
896
  1. **切换 Phase 到 review(第一步,必须立即执行)**:
780
897
  - 如果此提示已包含特定的变更 ID,请使用该值;否则运行 \`zhuanspec list\` 显示活跃变更并询问用户要审查哪个
@@ -891,7 +1008,7 @@ const knowledgeGuardrails = `${baseGuardrails}
891
1008
  - **职责分离**:
892
1009
  - **CLI 自动提取**(归档阶段 post-archive):从变更目录 design.md/proposal.md/tasks.md/specs 抽取结构化知识。CLI 的"决策类"输出归并到 \`best-practices/\`,不再写入 \`decisions/\`。
893
1010
  - **AI 手动补充**(本 skill 模式 A):从会话记忆中补充无法自动提取的知识。
894
- - **纠偏沉淀**(本 skill 模式 B):对接 apply 阶段 \`.correction-log\` 的纠偏记录。`;
1011
+ - **纠偏沉淀**(本 skill 模式 B):对接 apply 阶段 \`user_inputs.json\` 的纠偏记录。`;
895
1012
  const knowledgeSteps = `**步骤**
896
1013
 
897
1014
  本 skill 支持两种模式,触发方式不同、流程不同:
@@ -948,12 +1065,34 @@ const knowledgeSteps = `**步骤**
948
1065
  3. **搜索**:
949
1066
  - \`rg "<关键词>" zhuanspec/knowledge/\`
950
1067
  - 结合 \`index.md\` 关键词段快速锁定
951
- 4. **从会话添加**:
952
- - 先按**分类决策树**判定归属目录;**禁止**凭习惯写到 decisions/
953
- - 先 \`rg "<主关键词>" zhuanspec/knowledge/<category>/\` 做去重扫描:若命中高度相似条目 → 在已有文件追加 \`## 追加:<日期>\` 章节,不新建文件
954
- - 否则新建 \`zhuanspec/knowledge/<category>/<YYYYMMDD>-<kebab-slug>.md\`,严格套用上面的 Front Matter 模板
1068
+ 4. **从会话添加(强制:先列候选 → 用户确认 → 再写入)**:
1069
+
1070
+ 🔴 **红线**:禁止 AI 自行判断 "哪些内容值得沉淀" 后直接 Write/Edit。必须严格走完 4.1 → 4.2 → 4.3 → 4.4 四个子步骤,缺一不可。
1071
+
1072
+ **4.1 列候选清单(不写入任何文件)**:
1073
+ 基于本次会话记忆,按【分类决策树】先列出所有 "待沉淀候选条目",每条必须包含:
1074
+ - 序号(1、 2、 3 …)
1075
+ - 候选标题(≤ 30 字)
1076
+ - 命中分类(\`troubleshooting\` / \`best-practices\` / \`implicit-conventions\`)
1077
+ - 一句话理由(来自会话哪段对话 / 哪个修复 / 哪条纠偏)
1078
+ - 拟用文件名(\`<YYYYMMDD>-<kebab-slug>.md\`)
1079
+ - 重复检查结果:先对主关键词执行 \`rg "<主关键词>" zhuanspec/knowledge/<category>/\`,命中需展示对应文件路径与拟采取动作(追加章节 vs 新建文件)
1080
+
1081
+ **4.2 调用 \`askUserQuestion\` 让用户决策(必须多选,禁止默认)**:
1082
+ - 选项 A:全部沉淀
1083
+ - 选项 B:选择性沉淀(用户回复编号清单,例如 \`1,3,5\`)
1084
+ - 选项 C:跳过本次沉淀
1085
+ - 🔴 **红线**:禁止「默认全沉淀」,禁止「跳过此询问」,禁止「合并多条后一次性写入」。askUserQuestion 未调用前不得启动任何 Write/Edit/MultiEdit 操作。
1086
+
1087
+ **4.3 按用户决策写入**:
1088
+ - 用户未选中的条目一律不写入,不生成任何文件
1089
+ - 命中重复的:在已有文件追加 \`## 追加:<日期>\` 章节,不新建文件
1090
+ - 新条目:新建 \`zhuanspec/knowledge/<category>/<YYYYMMDD>-<kebab-slug>.md\`,严格套用上面的 Front Matter 模板
955
1091
  - **同步更新** \`zhuanspec/knowledge/index.md\`:在对应分区(\`## Troubleshooting\` / \`## Best Practices\` / \`## Implicit Conventions\`)追加一行 \`- [<标题>](<category>/<文件名>) — <关键词摘要>\`
956
1092
 
1093
+ **4.4 输出摘要**:
1094
+ 列出本轮新建 / 追加 / 被跳过的候选编号与路径,供用户复核。
1095
+
957
1096
  ---
958
1097
 
959
1098
  ## 模式 B:纠偏沉淀(Apply 阶段收尾 / Review 步骤 0 / PostToolUse 触发)
@@ -962,26 +1101,26 @@ const knowledgeSteps = `**步骤**
962
1101
  - 优先使用入参 \`--correction <change-id>\`
963
1102
  - 否则读取 \`zhuanspec/changes/*/metrics/progress.json\`,定位 \`corrections.length > 0 && askedPitfallSaved !== true\` 的 change-id
964
1103
  - 同时存在多个时,调用 \`askUserQuestion\` 让用户二选一,严禁随意选择
965
- 2. **读取原始纠偏记录**(两份必须都读):
966
- - \`zhuanspec/changes/<change-id>/.correction-log\`(JSONL,每行含 \`ts\` / \`event\` / \`promptPreview\` / \`reason?\`)
967
- - \`zhuanspec/changes/<change-id>/metrics/progress.json\` 的 \`corrections\` 数组
968
- 3. **用户二次确认(强制)**:
969
- - 将最近 3 条 promptPreview 摘要打印给用户
970
- - 调 \`askUserQuestion\`:\`是,沉淀 / 否,跳过\`
971
- - 用户选"否"时,直接跳到步骤 7 只做 resolve-correction --mark-pitfall-saved,不写入任何文件
972
- 4. **逐条分类**:对每条 correction 走上面的「分类决策树」,得到 \`<category>\`。
1104
+ 2. **以 pending-corrections.md 为起点(商定范围的唯一源)**:
1105
+ - 检查文件是否存在:\`zhuanspec/changes/<change-id>/review/pending-corrections.md\`。不存在则运行 \`zhuanspec progress list-corrections <change-id>\` 生成(CLI 已含 trivial 过滤 + 去重)。
1106
+ - 清单已明确标出:有效候选编号 / 拟分类 / 拟用文件名 / 已过滤明细(trivial / 过短 / 重复 / 子串包含)。**模式 B 只从这份清单里取候选**,禁止从会话记忆里“发挥”额外条目。
1107
+ 3. **范围决策(跟随 review 步骤 0 的三选项)**:
1108
+ - 接收入参 \`--include <编号串>\`(如 \`--include 1,3,5\`)表示选择性沉淀;未传则默认 = 全部有效候选。
1109
+ - 若未提供且不是从 review 步骤 0 / Stop hook 走进来,调 \`askUserQuestion\` 让用户三选一:\`全部沉淀 / 选择性沉淀(回复编号串) / 跳过\`。
1110
+ - 选择“跳过”时,直接跳到步骤 7 只做 resolve-correction --mark-pitfall-saved,不写入任何文件。
1111
+ 4. **逐条分类**:对选中的每条候选走上面的「分类决策树」,可参考清单里的「拟分类」作为起点,但决策树优先级更高。
973
1112
  5. **去重扫描**:对每条(含其关键词)先执行 \`rg "<主关键词>" zhuanspec/knowledge/<category>/\`:
974
1113
  - 命中相似条目 → 在已有文件追加 \`## 追加:<日期> — <change-id>\` 章节
975
1114
  - 未命中 → 新建 \`zhuanspec/knowledge/<category>/<YYYYMMDD>-<kebab-slug>.md\`
976
1115
  6. **写入文件**(严格使用统一 Front Matter 模板):
977
1116
  - \`**来源**\` 字段固定写 \`用户纠偏(change: <change-id>)\`
978
1117
  - \`**来源变更**\` 字段固定写 \`<change-id>\`
979
- - \`## 背景\` / \`## 问题 / 经验\` / \`## 解决方案 / 建议\` 必须基于 \`.correction-log\` 原始 promptPreview 与当次会话上下文还原,**禁止编造**
1118
+ - \`## 背景\` / \`## 问题 / 经验\` / \`## 解决方案 / 建议\` 必须基于 user_inputs.json 的 fullPrompt / summary 与当次会话上下文还原,**禁止编造**
980
1119
  - 同步更新 \`zhuanspec/knowledge/index.md\` 对应分区
981
- 7. **标记已处理(强制收尾,无论步骤 3 用户选是/否)**:
1120
+ 7. **标记已处理(强制收尾,无论步骤 3 用户选什么)**:
982
1121
  - 运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\`
983
1122
  - 确认 \`progress.json.askedPitfallSaved === true\`,避免下次 Stop hook 重复询问
984
- 8. **输出摘要**:列出本轮新建 / 追加的知识文件路径 + index.md 更新行;报告 \`<change-id>\` 的纠偏沉淀已完成。
1123
+ 8. **输出摘要**:列出本轮新建 / 追加 / 被跳过的知识文件路径 + index.md 更新行;报告 \`<change-id>\` 的纠偏沉淀已完成。
985
1124
 
986
1125
  ---
987
1126
 
@@ -989,6 +1128,7 @@ const knowledgeSteps = `**步骤**
989
1128
  - 所有写入 knowledge 目录的动作只能经本 skill 完成;禁止主 agent 或其他流程自行 Write。
990
1129
  - 只能写入三类目录之一,禁止新建 decisions/。
991
1130
  - 文件名、Front Matter、index.md 更新三者缺一不可。
1131
+ - **模式 A 写入前必须走完「列候选(4.1) + askUserQuestion 多选确认(4.2)」双步骤**;禁止 AI 自行判断「哪些内容值得沉淀」后直接写入,禁止默认全沉淀,禁止跳过询问环节。
992
1132
  - 模式 B 必须以 \`resolve-correction --mark-pitfall-saved\` 收尾。`;
993
1133
  const knowledgeReferences = `**参考**
994
1134
  - 参考样例(格式基准):项目 \`zhuanspec/knowledge/best-practices/oms-call-pattern.md\`、\`zhuanspec/knowledge/troubleshooting/20260506-apply-pitfalls.md\`、\`zhuanspec/knowledge/implicit-conventions/outbound-cis-inventory-lock.md\`
@@ -997,7 +1137,9 @@ const knowledgeReferences = `**参考**
997
1137
  - \`best-practices/\` — 可复用的最佳实践、设计决策落地
998
1138
  - \`implicit-conventions/\` — 隐式约定、默认行为、团队惯例
999
1139
  - CLI 归档时自动从变更目录提取知识(post-archive hook);所有"决策类"输出归入 \`best-practices/\`
1000
- - 模式 B 依赖文件:\`zhuanspec/changes/<change-id>/.correction-log\`(JSONL)、\`metrics/progress.json.corrections\`
1140
+ - 模式 B 依赖文件(两级 fallback,按优先级):
1141
+ 1. \`zhuanspec/changes/<change-id>/metrics/user_inputs.json\`(v2.15.15+ 主数据源,含 \`fullPrompt\` / \`correctionSignal\` / \`postBaseline\` / \`resolution\`)
1142
+ 2. \`zhuanspec/changes/<change-id>/metrics/progress.json\` 的 \`corrections\` 数组(计数交叉校验)
1001
1143
  - 模式 B 收尾命令:\`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\``;
1002
1144
  export const slashCommandBodies = {
1003
1145
  proposal: [proposalGuardrails, proposalOutputFormat, proposalSteps, proposalReferences].join('\n\n'),
@@ -40,6 +40,25 @@ Answer: <!-- user answer -->
40
40
  <!-- If @skill:none, MUST provide justification in description -->
41
41
  <!-- @skill names MUST match exactly the names returned by \`zhuanspec skills list\` -->
42
42
 
43
+ ### 中间件/基础能力 → 必选 Skill 映射(强制项)
44
+
45
+ 任务描述出现下表任一关键词时,@skill 字段 **MUST** 引用对应 Skill(多个用逗号分隔):
46
+
47
+ | 任务涉及中间件/能力 | 关键词识别 | 必选 @skill |
48
+ |--------------------|-----------|-------------|
49
+ | MQ Producer/Consumer | zzmq / RocketMQ / Topic: / @MessageConsumer / @MessageProducer | java-middleware-usage-skill |
50
+ | 定时任务 | xxl-job / @JobHandler / @XxlJob / cron | java-middleware-usage-skill |
51
+ | 分布式锁 | Redisson / @RedissonLock / ZZLock | java-middleware-usage-skill |
52
+ | Apollo 配置 | @ApolloJsonValue / apollo / 配置中心 | java-middleware-usage-skill |
53
+ | Redis 缓存 | @Cacheable / RedisTemplate / Lettuce / 缓存 | java-middleware-usage-skill |
54
+ | SCF RPC | @ServiceContract / @SCFInterface / scf-client / SCF 接口 | java-scf-rpc-usage-skill |
55
+ | DAO / Mapper | Mapper.xml / MyBatis / selectByXxx / @MyBatis | java-db-schema-standards |
56
+ | Elasticsearch | Elasticsearch / ES 索引 / ES 异构索引 | es-integration(若已注册) |
57
+
58
+ 未来扩展:新增中间件参考文件时,同步追加本表及 \`src/core/validation/strict-rules.ts\` 的中间件关键词白名单。
59
+
60
+ ### 实现区域 Skill 关联
61
+
43
62
  | 实现区域 | 实际功能 | 关联 Skill | 匹配理由 |
44
63
  |---------|---------|-----------|---------|
45
64
  | <!-- module/file --> | <!-- actual function --> | <!-- skill name --> | <!-- why it matches --> |
@@ -72,6 +91,31 @@ Answer: <!-- user answer -->
72
91
  4. 确保引用的章节在技术方案文档中存在
73
92
  -->
74
93
 
94
+ ## 分层拆分原则(强制)
95
+
96
+ ⚠️ **大型需求拆分时 MUST 遵循以下分层约束**,每个任务只实现"一个功能模块的一层代码",禁止跨层混合:
97
+
98
+ | Wave | 允许层 | 代表任务 |
99
+ |------|--------|---------|
100
+ | Wave 1(底层) | \`dao\` + 外部 \`assemble\` + \`ddl\` + \`config\` | Mapper/DAO/Entity/Mapper.xml、对外 SCF/HTTP 封装类 |
101
+ | Wave 2(中间层) | \`domain\` + \`application\` | DomainService(单聚合)、ApplicationService(跨聚合编排) |
102
+ | Wave 3(顶层) | \`entry-*\` + \`fe\` | SCF 实现/Controller、MQ Producer/Consumer、xxl-job Handler、前端页面 |
103
+
104
+ **任务 @layer 标签白名单**(必填项,与 \`@skill\`/\`@depends\`/\`@ref\` 并列):
105
+ - \`@layer:dao\` / \`@layer:assemble\` / \`@layer:domain\` / \`@layer:application\`
106
+ - 入口层细分:\`@layer:entry-scf\` / \`@layer:entry-mq-producer\` / \`@layer:entry-mq-consumer\` / \`@layer:entry-job\`
107
+ - 纯前端/配置/DDL 可用:\`@layer:fe\` / \`@layer:config\` / \`@layer:ddl\`
108
+
109
+ **拆分步骤**(由 Propose Agent 在任务分解前执行):
110
+ 1. 先按上表把所有要新增/修改的文件归入分层桶;
111
+ 2. 同一层允许多个任务,**但单任务禁止横跨两层**;
112
+ 3. 按 Wave 顺序编号,Wave 数量可扩展(例如 ES 索引初始化可放 Wave 0)。
113
+
114
+ **按 \`@layer\` 自动归 Wave(先分层后填 Wave 编号,禁止混层)**:
115
+ - Wave 1 (底层) = \`@layer:dao\` / \`@layer:assemble\` / \`@layer:ddl\` / \`@layer:config\`
116
+ - Wave 2 (中间层) = \`@layer:domain\` / \`@layer:application\`
117
+ - Wave 3 (顶层) = \`@layer:entry-scf\` / \`@layer:entry-mq-producer\` / \`@layer:entry-mq-consumer\` / \`@layer:entry-job\` / \`@layer:fe\`
118
+
75
119
  ## 任务格式说明
76
120
 
77
121
  ⚠️ **所有任务项必须使用 GitHub Flavored Markdown 复选框格式**:
@@ -80,11 +124,11 @@ Answer: <!-- user answer -->
80
124
  - **严禁使用** \`#### Task N.M:\` 或 \`#### T1:\` 标题格式
81
125
  - **严禁使用** ✅ emoji 标记完成,必须用 \`[x]\`
82
126
 
83
- 每个任务按类型使用对应的固定模板,必须填满所有字段:
127
+ 每个任务按类型使用对应的固定模板,必须填满所有字段,**@layer 为强制字段**:
84
128
 
85
129
  ### 类型 A:新增文件
86
130
 
87
- - [ ] N.M [描述] @skill:xxx @ref:xxx
131
+ - [ ] N.M [描述] @layer:xxx @skill:xxx @ref:xxx
88
132
  - **文件**: \`完整相对路径\`(新增)
89
133
  - **内容**:
90
134
  - 类定义: [类名、继承/实现关系]
@@ -95,7 +139,7 @@ Answer: <!-- user answer -->
95
139
  - **验证**: [具体的输入输出断言,含正常和异常场景]
96
140
 
97
141
  示例:
98
- - [ ] 5.1 创建 CustomerDomainService @skill:java-scf-rpc-usage-skill
142
+ - [ ] 5.1 创建 CustomerDomainService @layer:domain @skill:java-scf-rpc-usage-skill
99
143
  @ref:techDesign/tech-spec.md#3.1-新建客户
100
144
  - **文件**: \`domain_hub_server/src/main/java/com/zz/domain/hub/domain/CustomerDomainService.java\`(新增)
101
145
  - **内容**:
@@ -108,14 +152,14 @@ Answer: <!-- user answer -->
108
152
 
109
153
  ### 类型 B:修改文件
110
154
 
111
- - [ ] N.M [描述] @skill:xxx @ref:xxx
155
+ - [ ] N.M [描述] @layer:xxx @skill:xxx @ref:xxx
112
156
  - **文件**: \`完整相对路径\`(总行数)
113
157
  - **修改位置**: L行号范围 \`函数名/类名\` 之后/之内
114
158
  - **内容**: [具体改什么:新增代码逻辑/修改现有逻辑/删除代码,描述修改方式]
115
159
  - **验证**: [修改后的预期行为,含回归验证]
116
160
 
117
161
  示例:
118
- - [ ] 1.1 在 review 命令中增加任务完成度硬门禁 @skill:none
162
+ - [ ] 1.1 在 review 命令中增加任务完成度硬门禁 @layer:config @skill:none
119
163
  @ref:techDesign/tech-spec.md#7.1-任务完成度检查
120
164
  - **文件**: \`src/commands/review.ts\`(138行)
121
165
  - **修改位置**: L32-38 \`runReview()\` 函数内,现有校验逻辑之后
@@ -127,6 +171,7 @@ Answer: <!-- user answer -->
127
171
  - 单个任务 AI 执行时间不超过 30 分钟
128
172
  - 超过则需拆分为多个子任务
129
173
  - **禁止模糊描述**:不允许"创建XXX类"不带文件路径、"实现YYY方法"不带方法签名和关键逻辑
174
+ - **禁止跨层合并**:单任务不得同时修改 dao/domain/entry 等多层代码
130
175
 
131
176
  ## Coverage Checklist
132
177
 
@@ -144,23 +189,30 @@ Answer: <!-- user answer -->
144
189
  | 配置项 | <!-- N个 --> | <!-- T编号范围 --> | <!-- 100% --> |
145
190
  | 前端组件 | <!-- N个 --> | <!-- T编号范围 --> | <!-- 100% --> |
146
191
 
147
- ### Wave 1
192
+ ### Wave 1(底层:DAO / 外部 Assemble)
193
+
194
+ <!-- Wave 1: Tasks with no dependencies, 层归属限定 dao/assemble/ddl/config -->
195
+
196
+ - [ ] 1.1 <!-- Task description --> @layer:dao @skill:none <!-- 纯配置变更或手动操作 -->
148
197
 
149
- <!-- Wave 1: Tasks with no dependencies -->
198
+ ### Wave 2(中间层:Domain / Application)
150
199
 
151
- - [ ] 1.1 <!-- Task description --> @skill:none <!-- 纯配置变更或手动操作 -->
200
+ <!-- Wave 2: Tasks depending on Wave 1, 层归属限定 domain/application -->
152
201
 
153
- ### Wave 2
202
+ - [ ] 2.1 <!-- Task description --> @depends:1.1 @layer:domain @skill:none <!-- 无需特定 skill -->
154
203
 
155
- <!-- Wave 2: Tasks depending on Wave 1 -->
204
+ ### Wave 3(顶层:SCF / MQ / 定时任务 / 前端)
156
205
 
157
- - [ ] 2.1 <!-- Task description --> @depends:1.1 @skill:none <!-- 无需特定 skill -->
206
+ <!-- Wave 3: Tasks depending on Wave 2, 层归属限定 entry-scf/entry-mq-*/entry-job/fe -->
158
207
 
159
- ### Wave 3
208
+ - [ ] 3.1 <!-- Task description --> @depends:2.1 @layer:entry-scf @skill:none <!-- 无需特定 skill -->
160
209
 
161
- <!-- Wave 3: Tasks depending on Wave 2 -->
210
+ #### Layered Task Splitting Self-Check(填写 tasks.md 前自检)
162
211
 
163
- - [ ] 3.1 <!-- Task description --> @depends:2.1 @skill:none <!-- 无需特定 skill -->
212
+ - [ ] 每个 task 只包含一层的修改(不跨 dao/service/entry)
213
+ - [ ] 每个 task 都带了合法的 \`@layer:xxx\`(白名单 11 种:dao/assemble/domain/application/entry-scf/entry-mq-producer/entry-mq-consumer/entry-job/fe/config/ddl)
214
+ - [ ] Wave 编号与 \`@layer\` 一致(Wave 1 底层 / Wave 2 中间 / Wave 3 顶层)
215
+ - [ ] 含 CREATE TABLE / MQ / 定时任务 / Redis 等关键词的 task 均已关联对应 \`@skill\`
164
216
 
165
217
  ## Dependency Analysis
166
218
 
@@ -5,6 +5,7 @@ import { ZHUANSPEC_DIR_NAME } from './config.js';
5
5
  import { ToolRegistry } from './configurators/registry.js';
6
6
  import { SlashCommandRegistry } from './configurators/slash/registry.js';
7
7
  import { agentsTemplate } from './templates/agents-template.js';
8
+ import { InitCommand } from './init.js';
8
9
  import { cloneArchRepoToTemp, readBusinessDirection, fetchArchitectureFile, syncBusinessSpecTemplate, syncBusinessClaudeAssets, syncCommonDotClaude, } from './business-assets-sync.js';
9
10
  export class UpdateCommand {
10
11
  async execute(projectPath) {
@@ -65,6 +66,19 @@ export class UpdateCommand {
65
66
  // and .claude/ from the architecture repo. A single git clone is
66
67
  // shared across all sync calls to avoid repeated network IO.
67
68
  const businessSync = await this.runBusinessAssetSync(resolvedProjectPath, zhuanspecPath);
69
+ // 5. v2.15.16:同步 .claude/settings.json。
70
+ // 早期的 update 流程仅刷 CLAUDE.md,不管 settings.json,
71
+ // 导致老版 settings.json 里已下线的 hook entry
72
+ // (如 deviation-check --trigger post-prompt)无法被清理。
73
+ // 这里复用 InitCommand.syncClaudeSettings,内部会先剔除纯 ZhuanSpec 管辖
74
+ // 的老 group(所有 command 以 zhuanspec-hook 开头),再 append 新模板。
75
+ let settingsHookSummary = null;
76
+ try {
77
+ settingsHookSummary = await new InitCommand().syncClaudeSettings(resolvedProjectPath);
78
+ }
79
+ catch (error) {
80
+ console.error(`同步 .claude/settings.json 失败:${error instanceof Error ? error.message : String(error)}`);
81
+ }
68
82
  const summaryParts = [];
69
83
  const instructionFiles = ['zhuanspec/AGENTS.md'];
70
84
  if (updatedFiles.includes('AGENTS.md')) {
@@ -81,6 +95,9 @@ export class UpdateCommand {
81
95
  }
82
96
  // Business-sync summary lines
83
97
  this.appendBusinessSyncSummary(summaryParts, businessSync);
98
+ if (settingsHookSummary) {
99
+ summaryParts.push(`.claude/settings.json 已同步(新增 ${settingsHookSummary.totalAddedHooks} 条、跳过重复 ${settingsHookSummary.duplicateHooksSkipped} 条)`);
100
+ }
84
101
  const failedItems = [
85
102
  ...failedFiles,
86
103
  ...failedSlashTools.map((toolId) => `斜杠命令刷新(${toolId})`),