@zhuan-ai/zhuanspec 2.16.0 → 2.16.3

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.
@@ -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 字段
@@ -428,7 +422,7 @@ const proposalSteps = `**步骤**
428
422
  const proposalReferences = `**参考**
429
423
  - 当验证失败时,使用 \`zhuanspec show <id> --json --deltas-only\` 或 \`zhuanspec show <spec> --type spec\` 检查详细信息。
430
424
  - 在编写新要求之前,使用 \`rg -n "Requirement:|Scenario:" zhuanspec/specs\` 搜索现有要求。
431
- - 探索代码库时,先检查已定位服务目录下是否存在 \`[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\` 或直接文件读取。`;
432
426
  const applySteps = `**步骤**
433
427
  将这些步骤作为待办事项跟踪,逐一完成。
434
428
  1. **检查知识库并确认 Phase**:
@@ -438,6 +432,9 @@ const applySteps = `**步骤**
438
432
  - 阅读 \`changes/<id>/proposal.md\`、\`design.md\`(如果存在)和 \`tasks.md\` 以确认范围和验收标准。
439
433
  2. **Wave 并行执行(默认且唯一执行模式)**
440
434
  - **执行模型**:按 Wave 编号串行,Wave 内任务并行启动 subagent。
435
+ - **⚠️ 每个 Wave 启动前 MUST 重读核心机制(防长任务指令衰减)**:在为新 Wave 启动 subagent 前,编排 Agent **必须**在自己的输出里**逐字复述**以下两句话,作为执行前置自检(缺失即流程故障):
436
+ 1. "本 Wave 的每个任务 MUST 通过 Agent tool / spawn_agent 启动 subagent,禁止主线程串行手写代码或手写报告。"
437
+ 2. "任务报告必须由 subagent 生成,且必须符合 .claude/agents/tdd-apply-agent.md 或 apply-agent.md 的模板章节。"
441
438
  - **并行度限制**:每个 Wave 内最多同时启动 3 个 subagent。超过 3 个任务时,按批次(batch)执行,每批最多 3 个并行 subagent,批次间串行等待。
442
439
  - **Subagent 调用 @skill 后的行为**(任务标注 \`@skill:<skill-name>\` 时):
443
440
  1. 执行 @skill 标注的 Skill
@@ -518,6 +515,15 @@ const applySteps = `**步骤**
518
515
  - 同 Wave 所有任务(含阻塞任务)全部处理完成后 → 进入集成测试阶段
519
516
 
520
517
  **B. 集成测试阶段(MANDATORY,同 Wave 所有任务处理完成后)**:
518
+ B0. **任务报告 schema 校验(MANDATORY GATE,最先执行,不得跳过)**:
519
+ - 运行 \`zhuanspec validate-reports <change-id> --json\` 校验本 Wave 所有 \`reports/task-*.md\`
520
+ - 检查内容(基于 \`.claude/agents/tdd-apply-agent.md\` / \`apply-agent.md\` 模板):
521
+ * 公共字段:\`## 状态报告\` / Status / Task ID / Report File / \`### Agent 选择决策\` / Agent 类型
522
+ * tddApplyAgent 报告必须有:TDD Phase / \`### 上下文就绪摘要\` / \`### 验收点映射表\` / \`#### Verify RED\` / \`#### Verify GREEN\` / \`#### Mock Gate\` / \`### 测试运行结果\` / \`### Self-Review 发现\` / \`### Issues/Concerns\`
523
+ * applyAgent 报告必须有:\`### 实施内容\` / \`### 修改文件\` / \`### Self-Review 发现\` / \`### Issues/Concerns\`
524
+ * 交叉对账:tasks.md 中带 \`@test-case:TC-XXX\` 的任务,报告必须为 tddApplyAgent,否则必须显式声明 "TDD 适用性: 不适合(降级原因:...)"
525
+ - 任意报告校验失败 → **该任务强制视为 BLOCKED**,按 B5 流程以 Execution Mode = RETRY 重新 spawn subagent 产出合规报告;禁止跳过本步直接进入 B1
526
+ - 校验失败的根因通常是:编排 Agent 在主线程手写代码 + 手写偷工报告,没有真的 spawn subagent。修复方式:通过 Agent tool / spawn_agent 重新下发任务
521
527
  B1. **编译检查**:运行项目编译命令,确保无编译错误
522
528
  - Java: \`mvn compile -q\` / \`gradle compileJava\`
523
529
  - TypeScript: \`tsc --noEmit\`
@@ -594,6 +600,7 @@ const applySteps = `**步骤**
594
600
  B6. **生成集成测试报告(MANDATORY,不得跳过)**:
595
601
  - 报告路径:\`changes/<change-id>/reports/wave-{N}-integration-report.md\`
596
602
  - 记录所有任务执行结果、编译检查结果、阻塞任务重试结果
603
+ - **MUST 记录 B0 报告 schema 校验结果**(通过/失败任务列表,失败时附 \`validate-reports --json\` 输出)
597
604
  - **MUST 包含 Concerns 追踪章节**,列出所有 DONE_WITH_CONCERNS 和 BLOCKED 任务及其疑虑
598
605
  - **MUST 包含 \`## 🔁 待重试任务清单\` 段**(即使为空也要写 \`— 无需重跑\`),与 B4.1 第五步、B5 重试结果汇总一致
599
606
  - 整体状态:所有检查通过且无未解决的阻塞任务 → PASS
@@ -699,12 +706,15 @@ const archiveSteps = `**前置检查**:
699
706
  - \`progress.phaseDurations\` 必须关闭 review 段并开启 archive 段
700
707
  2. 通过运行 \`zhuanspec list\`(或 \`zhuanspec show <id>\`)验证变更 ID,如果变更缺失、已归档或尚未准备好归档,则停止。
701
708
  3. **验证 Review 门禁**:确认上述五个结果文件存在且全部通过(含轨道 4 的 \`closure-check-result.json\`)。
702
- 4. 运行 \`zhuanspec archive <id> --yes\`,以便 CLI 移动变更并应用规范更新,无需提示(仅对仅工具类工作使用 \`--skip-specs\`)。
703
- 5. 审查命令输出以确认目标规范已更新,并且变更已进入 \`changes/archive/\`。
704
- 6. 使用 \`zhuanspec validate --strict\` 进行验证,如果看起来有问题,使用 \`zhuanspec show <id>\` 进行检查。
705
- 7. **知识沉淀(手动补充)**:调用 \`@skill:zhuanspec:knowledge\` skill 从本次会话记忆中补充知识。
709
+ 4. **知识沉淀(手动补充,必须前置)**:调用 \`@skill:zhuanspec:knowledge\` skill(模式 A)从本次会话记忆中补充知识。
710
+ - 🔴 **红线(顺序不可调整)**:本步骤**必须**在执行 \`zhuanspec archive <id>\` 之前完成。\`zhuanspec archive\` 命令内部会按顺序执行 \`postArchiveHook\`(自动结构化提取) → \`pushArchiveResultToRemote\`(一次性同步 specs / archive / knowledge 三目录到远端);如果把手动沉淀放在 archive 命令之后,新写入的 knowledge 文件**仅落本地**,不会被推送到远端模板仓库,团队其他成员将看不到。
711
+ - 🔴 **禁止 AI 自行决定沉淀内容**:必须严格按 zhuanspec:knowledge skill 模式 A 步骤 4 执行——先列候选清单,再调用 \`askUserQuestion\` 让用户多选确认,再写入。禁止默认全沉淀,禁止跳过询问。
706
712
  - CLI 已自动从变更目录提取结构化知识(design.md/proposal.md/tasks.md 中的决策、注意事项等)
707
713
  - AI 需从会话记忆补充无法自动提取的内容(如对话中发现的隐式约定、调试陷阱等)
714
+ - 用户选择「跳过本次沉淀」时,本步骤可不写入任何文件,但仍需经过显式确认环节,禁止默认跳过。
715
+ 5. 运行 \`zhuanspec archive <id> --yes\`,以便 CLI 移动变更并应用规范更新,无需提示(仅对仅工具类工作使用 \`--skip-specs\`)。**该命令将自动 push specs / archive / knowledge 三目录到远端**,因此必须在步骤 4 完成知识沉淀后才执行。
716
+ 6. 审查命令输出以确认目标规范已更新,并且变更已进入 \`changes/archive/\`,且 "推送到远端" 段输出 \`✅ 已推送归档结果到远端\`(如使用 \`--skip-specs\` 则跳过推送)。
717
+ 7. 使用 \`zhuanspec validate --strict\` 进行验证,如果看起来有问题,使用 \`zhuanspec show <id>\` 进行检查。
708
718
  8. **会话分析**:调用 \`@skill:session-analytics\` skill 分析本次会话的指标数据(工具调用、Token消耗、时长等)。
709
719
  9. **输出反馈链接**:告知用户填写使用反馈:
710
720
  📋 https://doc.weixin.qq.com/forms/AJ4AfQfgAAwACwAAwaVABsCNqDXIKn8sf`;
@@ -712,10 +722,11 @@ const archiveReferences = `**参考**
712
722
  - 在归档之前使用 \`zhuanspec list\` 确认变更 ID。
713
723
  - 使用 \`zhuanspec list --specs\` 检查刷新的规范,并在移交之前解决任何验证问题。
714
724
  - 知识提取分工:
715
- - **CLI 自动**:归档时从变更目录(proposal.md/tasks.md/design.md/specs/*.md)正则提取结构化知识
716
- - **AI 手动**:调用 \`zhuanspec:knowledge\` skill 从会话记忆补充隐式约定、调试发现等
725
+ - **CLI 自动**(archive 命令内):归档时从变更目录(proposal.md/tasks.md/design.md/specs/*.md)正则提取结构化知识,写入本地 \`zhuanspec/knowledge/\`,随后由同一条 archive 命令一并 push 到远端
726
+ - **AI 手动**(archive 命令前):调用 \`zhuanspec:knowledge\` skill 从会话记忆补充隐式约定、调试发现等。**必须在 \`zhuanspec archive\` 命令之前**调用,否则补充内容仅落本地、不会进入远端推送
717
727
  - 会话分析 (\`session-analytics\`):记录本次会话的效率指标,用于改进工作流。`;
718
728
  const designGuardrails = `${baseGuardrails}\n- **独立设计阶段**:techDesign 命令用于在 proposal 之前生成技术设计请求文档,不依赖变更提案。设计文档可作为后续提案的输入。
729
+ - **Skill 调用连续性(红线)**:在 techDesign 流程中调用任何辅助类 Skill(如 \`@skill:load-project-knowledge\`)后,**必须立即推进到下一编号步骤**,禁止把 Skill 的输出当作流程终态,禁止停顿等待用户输入“继续/下一步”等确认词。只有在显式标注的 AskUserQuestion 步骤(如开发范围确认、需求来源确认、外部依赖确认)才允许暂停等待用户。
719
730
  - **需求澄清优先**:在生成设计请求前,必须确认需求来源(大神页面、需求描述文本等)。
720
731
  - **开发范围前置确认(硬约束)**:在调用技术方案 Skill 前,**必须**先通过 AskUserQuestion 确认开发范围是“仅后端开发”还是“全栈开发”,根据答复选择对应 Skill(仅后端=\`generate-tech-spec-md-skill\`,全栈=\`generate-fullstack-tech-spec-skill\`),禁止默认或跳过此确认环节。
721
732
  - **Skill 可用性前置检查(硬约束)**:在实际调用技术方案 Skill 前,**必须**先校验目标 Skill 是否已安装且可用;**若不可用,立即中断流程**并提示用户到 Skill 市场安装对应 Skill,禁止以人工编写/其他 Skill 代替。
@@ -725,8 +736,13 @@ const designGuardrails = `${baseGuardrails}\n- **独立设计阶段**:techDesi
725
736
  - **禁止创建提案文件**:禁止创建 .tech-design、design.md、proposal.md、tasks.md、specs/ 等。
726
737
  - **Proposal 复用**:proposal 阶段通过 progress.json 的 phase 字段识别 techDesign 目录。`;
727
738
  const designSteps = `**步骤**
728
- 0. **检查知识库并生成 change-id**:
739
+ 0. **检查知识库、加载项目知识并生成 change-id**:
729
740
  - 运行 \`rg "[需求关键词]" zhuanspec/knowledge/\` 搜索相关陷阱和最佳实践,避免重复踩坑。阅读 \`zhuanspec/knowledge/index.md\` 了解项目级知识摘要。
741
+ - **加载项目知识(必选)**:调用 \`@skill:load-project-knowledge\` 进行渐进式加载:
742
+ * 输入:domain(当前项目)、keywords(从需求描述提取的核心关键词)
743
+ * 获取:matched_services(涉及的服务列表)、search_priority(检索优先路径)、architecture_constraints(架构约束)
744
+ * 使用:后续技术方案设计需引用 matched_services 作为服务定位,方案设计需检查 architecture_constraints
745
+ * ⚠️ **连续性约束(红线)**:\`load-project-knowledge\` 完成并输出 matched_services 表后,**必须立即继续执行下面的“生成 change-id”子步骤以及步骤 1(Phase 初始化)**,禁止停顿等待用户输入“继续”。该 Skill 只是辅助加载,不是流程门禁。
730
746
  - **生成 change-id**(与 proposal 阶段命名规则一致):
731
747
  * 从用户需求描述中提取核心动词和关键词
732
748
  * 格式:动词开头 + kebab-case 关词组合
@@ -868,26 +884,33 @@ const reviewGuardrails = `${baseGuardrails}\n- **门禁审查阶段**:review
868
884
  const reviewSteps = `**步骤**
869
885
  0. **⚠️ 纠偏沉淀优先检查(Phase 切换前强制执行)**:
870
886
  - **计数源(两级 fallback,新→旧)**:
871
- - Level 1:读 \`zhuanspec/changes/<change-id>/metrics/user_inputs.json\`,筛选 \`correctionSignal.kind === 'hard' && postBaseline === true && resolution.triggeredFourOption === true\` 的条目作为纠偏明细
887
+ - Level 1:读 \`zhuanspec/changes/<change-id>/metrics/user_inputs.json\`,筛选 \`correctionSignal.kind === 'hard' && postBaseline === true\` 的条目作为纠偏明细
872
888
  - Level 2:\`user_inputs.json\` 存在但条目缺 \`correctionSignal\` → 按 \`inputs[*].summary\` 关键词扫描推断
873
889
  - **同时读** \`zhuanspec/changes/<change-id>/metrics/progress.json\`,检查:
874
890
  - 上述任一 Level 得到的纠偏条目数 N 是否 > 0
875
891
  - \`askedPitfallSaved\` 字段是否为 \`true\`
876
892
  - **如果满足条件(N > 0 且 askedPitfallSaved !== true)**:
877
- - **立即调用 \`AskUserQuestion\` 工具**,以二选一方式询问用户:
878
- \`\`\`
879
- header: "踩坑沉淀"
880
- question: "本轮 Apply 阶段发生过 N 次用户纠偏(N 为上述来源的实际长度,请列出最近 3 条摘要 —— Level 1 用 fullPrompt.slice(0,200)、Level 2 用 summary),是否沉淀为项目知识?"
881
- 选项 1: "是,沉淀"
882
- 选项 2: "否,跳过"
883
- \`\`\`
884
- - **用户选择"是"时**:
885
- 1. **必须调用 \`@skill:zhuanspec:knowledge --mode=correction --correction <change-id>\`**(或等价的 \`/zhuanspec:knowledge\` slash command 并在交互中选择模式 B)来完成沉淀
886
- 2. 本 skill 将自动完成:读取 \`user_inputs.json\`(Level 1)或 summary 关键词扫描(Level 2)→ 分类决策树归入 \`troubleshooting/\` / \`best-practices/\` / \`implicit-conventions/\` → 去重扫描 → 套用统一 Front Matter → 写入知识文件 → 更新 \`knowledge/index.md\` → 运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\`
887
- 3. **红线**:**禁止主 agent 自行使用 Write/Edit 创建 \`zhuanspec/knowledge/\` 下的任何文件**,禁止自行判定分类或文件名格式;禁止新建 \`decisions/\` 或三类目录以外的分类。
888
- - **用户选择"否"时**:
889
- - 运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\` 标记已处理,不写入任何知识文件
890
- - **如果不满足条件(无纠偏或已沉淀)**:直接进入下一步
893
+ 1. **先生成决策清单(必须)**:运行
894
+ \`\`\`bash
895
+ zhuanspec progress list-corrections <change-id>
896
+ \`\`\`
897
+ CLI 会完成:读 user_inputs.json → 过滤 trivial 确认词(如“是的/好的/ok”)→ 去重(完全重复 + 子串包含)→ 启发式分类 → 写到 \`zhuanspec/changes/<change-id>/review/pending-corrections.md\`。并在 stdout 输出 **合计 / 有效 / 过滤** 三个计数。
898
+ 2. **调用 \`AskUserQuestion\`(三选项,禁止默认)**:
899
+ \`\`\`
900
+ header: "踩坑沉淀"
901
+ question: "本轮有 M 条有效纠偏候选(已过滤 trivial / 去重,详见 review/pending-corrections.md),请选择沉淀范围:"
902
+ 选项 1:"全部沉淀"
903
+ 选项 2:"选择性沉淀(请回复编号清单,例如 1,3,5)"
904
+ 选项 3:"跳过"
905
+ \`\`\`
906
+ 🔴 **红线**:禁止跳过本次询问;禁止仅根据最近 N 条摘要就起心动念、绕过清单文件。
907
+ 3. **用户选择 "全部沉淀" 或 "选择性沉淀"**:
908
+ - 必须调用 \`@skill:zhuanspec:knowledge --mode=correction --correction <change-id>\`(或 \`/zhuanspec:knowledge\` 交互模式 B)来完成沉淀。
909
+ - 选择性沉淀时,把用户回复的编号清单以 \`--include <编号串>\` 形式透传给 skill(例:\`--include 1,3,5\`),或在 skill 交互中照实转述编号。skill 必须以 \`pending-corrections.md\` 作为商定范围的单一源,禁止从会话记忆里“发挥”额外条目。
910
+ - skill 完成后会自动运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\`。
911
+ 🔴 **红线**:禁止主 agent 自行使用 Write/Edit 创建 \`zhuanspec/knowledge/\` 下的任何文件;禁止自行判定分类或文件名格式;禁止新建 \`decisions/\` 或三类目录以外的分类。
912
+ 4. **用户选择 "跳过"**:运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\` 标记已处理,不写入任何知识文件。
913
+ - **如果不满足条件(无纠偏或已沉淀)**:直接进入下一步。
891
914
 
892
915
  1. **切换 Phase 到 review(第一步,必须立即执行)**:
893
916
  - 如果此提示已包含特定的变更 ID,请使用该值;否则运行 \`zhuanspec list\` 显示活跃变更并询问用户要审查哪个
@@ -1061,12 +1084,34 @@ const knowledgeSteps = `**步骤**
1061
1084
  3. **搜索**:
1062
1085
  - \`rg "<关键词>" zhuanspec/knowledge/\`
1063
1086
  - 结合 \`index.md\` 关键词段快速锁定
1064
- 4. **从会话添加**:
1065
- - 先按**分类决策树**判定归属目录;**禁止**凭习惯写到 decisions/
1066
- - 先 \`rg "<主关键词>" zhuanspec/knowledge/<category>/\` 做去重扫描:若命中高度相似条目 → 在已有文件追加 \`## 追加:<日期>\` 章节,不新建文件
1067
- - 否则新建 \`zhuanspec/knowledge/<category>/<YYYYMMDD>-<kebab-slug>.md\`,严格套用上面的 Front Matter 模板
1087
+ 4. **从会话添加(强制:先列候选 → 用户确认 → 再写入)**:
1088
+
1089
+ 🔴 **红线**:禁止 AI 自行判断 "哪些内容值得沉淀" 后直接 Write/Edit。必须严格走完 4.1 → 4.2 → 4.3 → 4.4 四个子步骤,缺一不可。
1090
+
1091
+ **4.1 列候选清单(不写入任何文件)**:
1092
+ 基于本次会话记忆,按【分类决策树】先列出所有 "待沉淀候选条目",每条必须包含:
1093
+ - 序号(1、 2、 3 …)
1094
+ - 候选标题(≤ 30 字)
1095
+ - 命中分类(\`troubleshooting\` / \`best-practices\` / \`implicit-conventions\`)
1096
+ - 一句话理由(来自会话哪段对话 / 哪个修复 / 哪条纠偏)
1097
+ - 拟用文件名(\`<YYYYMMDD>-<kebab-slug>.md\`)
1098
+ - 重复检查结果:先对主关键词执行 \`rg "<主关键词>" zhuanspec/knowledge/<category>/\`,命中需展示对应文件路径与拟采取动作(追加章节 vs 新建文件)
1099
+
1100
+ **4.2 调用 \`askUserQuestion\` 让用户决策(必须多选,禁止默认)**:
1101
+ - 选项 A:全部沉淀
1102
+ - 选项 B:选择性沉淀(用户回复编号清单,例如 \`1,3,5\`)
1103
+ - 选项 C:跳过本次沉淀
1104
+ - 🔴 **红线**:禁止「默认全沉淀」,禁止「跳过此询问」,禁止「合并多条后一次性写入」。askUserQuestion 未调用前不得启动任何 Write/Edit/MultiEdit 操作。
1105
+
1106
+ **4.3 按用户决策写入**:
1107
+ - 用户未选中的条目一律不写入,不生成任何文件
1108
+ - 命中重复的:在已有文件追加 \`## 追加:<日期>\` 章节,不新建文件
1109
+ - 新条目:新建 \`zhuanspec/knowledge/<category>/<YYYYMMDD>-<kebab-slug>.md\`,严格套用上面的 Front Matter 模板
1068
1110
  - **同步更新** \`zhuanspec/knowledge/index.md\`:在对应分区(\`## Troubleshooting\` / \`## Best Practices\` / \`## Implicit Conventions\`)追加一行 \`- [<标题>](<category>/<文件名>) — <关键词摘要>\`
1069
1111
 
1112
+ **4.4 输出摘要**:
1113
+ 列出本轮新建 / 追加 / 被跳过的候选编号与路径,供用户复核。
1114
+
1070
1115
  ---
1071
1116
 
1072
1117
  ## 模式 B:纠偏沉淀(Apply 阶段收尾 / Review 步骤 0 / PostToolUse 触发)
@@ -1075,15 +1120,14 @@ const knowledgeSteps = `**步骤**
1075
1120
  - 优先使用入参 \`--correction <change-id>\`
1076
1121
  - 否则读取 \`zhuanspec/changes/*/metrics/progress.json\`,定位 \`corrections.length > 0 && askedPitfallSaved !== true\` 的 change-id
1077
1122
  - 同时存在多个时,调用 \`askUserQuestion\` 让用户二选一,严禁随意选择
1078
- 2. **读取原始纠偏记录(两级 fallback,新→旧)**:
1079
- - **Level 1(优先,v2.15.15+)**:\`zhuanspec/changes/<change-id>/metrics/user_inputs.json\` 的 \`inputs\` 数组,筛选条件 \`correctionSignal.kind === 'hard' && postBaseline === true\`;每条取 \`fullPrompt\`(最长 2000 字)、\`correctionSignal.matchedKeywords\`、\`correctionSignal.isRequirementChange\`、\`resolution.path\`、\`timestamp\`
1080
- - **Level 2(中间版本兼容,v2.15.5~v2.15.14)**:\`user_inputs.json\` 存在但条目缺 \`correctionSignal\` 字段 → 对 \`inputs[*].summary\` 执行关键词扫描(参考 \`src/core/hooks/deviation-check.ts\` 的 \`USER_CORRECTION_KEYWORDS\` / \`REQUIREMENT_CHANGE_KEYWORDS\`)推断纠偏条目;无 \`fullPrompt\` 时用 \`summary\` 兜底
1081
- - 同时读 \`zhuanspec/changes/<change-id>/metrics/progress.json\` 的 \`corrections\` 数组作为纠偏计数交叉校验
1082
- 3. **用户二次确认(强制)**:
1083
- - 打印最近 3 条摘要:Level 1 用 \`fullPrompt.slice(0, 300)\`、Level 2 用 \`summary\`
1084
- - 调 \`askUserQuestion\`:\`是,沉淀 / 否,跳过\`
1085
- - 用户选"否"时,直接跳到步骤 7 只做 resolve-correction --mark-pitfall-saved,不写入任何文件
1086
- 4. **逐条分类**:对每条 correction 走上面的「分类决策树」,得到 \`<category>\`。
1123
+ 2. **以 pending-corrections.md 为起点(商定范围的唯一源)**:
1124
+ - 检查文件是否存在:\`zhuanspec/changes/<change-id>/review/pending-corrections.md\`。不存在则运行 \`zhuanspec progress list-corrections <change-id>\` 生成(CLI 已含 trivial 过滤 + 去重)。
1125
+ - 清单已明确标出:有效候选编号 / 拟分类 / 拟用文件名 / 已过滤明细(trivial / 过短 / 重复 / 子串包含)。**模式 B 只从这份清单里取候选**,禁止从会话记忆里“发挥”额外条目。
1126
+ 3. **范围决策(跟随 review 步骤 0 的三选项)**:
1127
+ - 接收入参 \`--include <编号串>\`(如 \`--include 1,3,5\`)表示选择性沉淀;未传则默认 = 全部有效候选。
1128
+ - 若未提供且不是从 review 步骤 0 / Stop hook 走进来,调 \`askUserQuestion\` 让用户三选一:\`全部沉淀 / 选择性沉淀(回复编号串) / 跳过\`。
1129
+ - 选择“跳过”时,直接跳到步骤 7 只做 resolve-correction --mark-pitfall-saved,不写入任何文件。
1130
+ 4. **逐条分类**:对选中的每条候选走上面的「分类决策树」,可参考清单里的「拟分类」作为起点,但决策树优先级更高。
1087
1131
  5. **去重扫描**:对每条(含其关键词)先执行 \`rg "<主关键词>" zhuanspec/knowledge/<category>/\`:
1088
1132
  - 命中相似条目 → 在已有文件追加 \`## 追加:<日期> — <change-id>\` 章节
1089
1133
  - 未命中 → 新建 \`zhuanspec/knowledge/<category>/<YYYYMMDD>-<kebab-slug>.md\`
@@ -1092,10 +1136,10 @@ const knowledgeSteps = `**步骤**
1092
1136
  - \`**来源变更**\` 字段固定写 \`<change-id>\`
1093
1137
  - \`## 背景\` / \`## 问题 / 经验\` / \`## 解决方案 / 建议\` 必须基于 user_inputs.json 的 fullPrompt / summary 与当次会话上下文还原,**禁止编造**
1094
1138
  - 同步更新 \`zhuanspec/knowledge/index.md\` 对应分区
1095
- 7. **标记已处理(强制收尾,无论步骤 3 用户选是/否)**:
1139
+ 7. **标记已处理(强制收尾,无论步骤 3 用户选什么)**:
1096
1140
  - 运行 \`zhuanspec progress resolve-correction <change-id> --mark-pitfall-saved\`
1097
1141
  - 确认 \`progress.json.askedPitfallSaved === true\`,避免下次 Stop hook 重复询问
1098
- 8. **输出摘要**:列出本轮新建 / 追加的知识文件路径 + index.md 更新行;报告 \`<change-id>\` 的纠偏沉淀已完成。
1142
+ 8. **输出摘要**:列出本轮新建 / 追加 / 被跳过的知识文件路径 + index.md 更新行;报告 \`<change-id>\` 的纠偏沉淀已完成。
1099
1143
 
1100
1144
  ---
1101
1145
 
@@ -1103,6 +1147,7 @@ const knowledgeSteps = `**步骤**
1103
1147
  - 所有写入 knowledge 目录的动作只能经本 skill 完成;禁止主 agent 或其他流程自行 Write。
1104
1148
  - 只能写入三类目录之一,禁止新建 decisions/。
1105
1149
  - 文件名、Front Matter、index.md 更新三者缺一不可。
1150
+ - **模式 A 写入前必须走完「列候选(4.1) + askUserQuestion 多选确认(4.2)」双步骤**;禁止 AI 自行判断「哪些内容值得沉淀」后直接写入,禁止默认全沉淀,禁止跳过询问环节。
1106
1151
  - 模式 B 必须以 \`resolve-correction --mark-pitfall-saved\` 收尾。`;
1107
1152
  const knowledgeReferences = `**参考**
1108
1153
  - 参考样例(格式基准):项目 \`zhuanspec/knowledge/best-practices/oms-call-pattern.md\`、\`zhuanspec/knowledge/troubleshooting/20260506-apply-pitfalls.md\`、\`zhuanspec/knowledge/implicit-conventions/outbound-cis-inventory-lock.md\`
@@ -191,18 +191,24 @@ Answer: <!-- user answer -->
191
191
 
192
192
  ### Wave 1(底层:DAO / 外部 Assemble)
193
193
 
194
+ > ⚠️ **MUST (subagent gate)**: 本 Wave 每个任务必须通过 Agent tool / spawn_agent 启动 subagent 执行;主线程直接施工产生的报告会被 B0 schema 校验(\`zhuanspec validate-reports <change-id>\`)拦截并触发 RETRY。
195
+
194
196
  <!-- Wave 1: Tasks with no dependencies, 层归属限定 dao/assemble/ddl/config -->
195
197
 
196
198
  - [ ] 1.1 <!-- Task description --> @layer:dao @skill:none <!-- 纯配置变更或手动操作 -->
197
199
 
198
200
  ### Wave 2(中间层:Domain / Application)
199
201
 
202
+ > ⚠️ **MUST (subagent gate)**: 本 Wave 每个任务必须通过 Agent tool / spawn_agent 启动 subagent 执行;主线程直接施工产生的报告会被 B0 schema 校验(\`zhuanspec validate-reports <change-id>\`)拦截并触发 RETRY。
203
+
200
204
  <!-- Wave 2: Tasks depending on Wave 1, 层归属限定 domain/application -->
201
205
 
202
206
  - [ ] 2.1 <!-- Task description --> @depends:1.1 @layer:domain @skill:none <!-- 无需特定 skill -->
203
207
 
204
208
  ### Wave 3(顶层:SCF / MQ / 定时任务 / 前端)
205
209
 
210
+ > ⚠️ **MUST (subagent gate)**: 本 Wave 每个任务必须通过 Agent tool / spawn_agent 启动 subagent 执行;主线程直接施工产生的报告会被 B0 schema 校验(\`zhuanspec validate-reports <change-id>\`)拦截并触发 RETRY。
211
+
206
212
  <!-- Wave 3: Tasks depending on Wave 2, 层归属限定 entry-scf/entry-mq-*/entry-job/fe -->
207
213
 
208
214
  - [ ] 3.1 <!-- Task description --> @depends:2.1 @layer:entry-scf @skill:none <!-- 无需特定 skill -->
@@ -153,6 +153,8 @@ Answer: <!-- user answer -->
153
153
 
154
154
  ### Wave 2
155
155
 
156
+ > ⚠️ **MUST (subagent gate)**: 本 Wave 每个任务必须通过 Agent tool / spawn_agent 启动 subagent(优先 tddApplyAgent)执行;主线程直接施工产生的报告会被 B0 schema 校验(\`zhuanspec validate-reports <change-id>\`)拦截并触发 RETRY。
157
+
156
158
  <!-- Wave 2: Red Phase - Write failing tests that define expected behavior -->
157
159
  <!-- 先写测试,测试应当初始失败 — 证明测试确实在验证有意义的行为 -->
158
160
  <!-- 每个测试任务必须使用类型A/B模板,明确测试文件路径、测试方法签名、断言内容 -->
@@ -162,6 +164,8 @@ Answer: <!-- user answer -->
162
164
 
163
165
  ### Wave 3
164
166
 
167
+ > ⚠️ **MUST (subagent gate)**: 本 Wave 每个任务必须通过 Agent tool / spawn_agent 启动 subagent(优先 tddApplyAgent)执行;主线程直接施工产生的报告会被 B0 schema 校验(\`zhuanspec validate-reports <change-id>\`)拦截并触发 RETRY。
168
+
165
169
  <!-- Wave 3: Green Phase - Write minimal code to make tests pass -->
166
170
  <!-- 编写最少代码使测试通过,每个任务必须使用类型A(新增)或类型B(修改)模板 -->
167
171
 
@@ -170,6 +174,8 @@ Answer: <!-- user answer -->
170
174
 
171
175
  ### Wave 4
172
176
 
177
+ > ⚠️ **MUST (subagent gate)**: 本 Wave 每个任务必须通过 Agent tool / spawn_agent 启动 subagent(优先 tddApplyAgent)执行;主线程直接施工产生的报告会被 B0 schema 校验(\`zhuanspec validate-reports <change-id>\`)拦截并触发 RETRY。
178
+
173
179
  <!-- Wave 4: Refactor Phase - Clean up code while keeping tests green -->
174
180
  <!-- 在保持测试通过的前提下重构,每个任务使用类型B模板标明修改位置 -->
175
181
 
@@ -178,6 +184,8 @@ Answer: <!-- user answer -->
178
184
 
179
185
  ### Wave 5
180
186
 
187
+ > ⚠️ **MUST (subagent gate)**: 本 Wave 每个任务必须通过 Agent tool / spawn_agent 启动 subagent 执行;主线程直接施工产生的报告会被 B0 schema 校验(\`zhuanspec validate-reports <change-id>\`)拦截并触发 RETRY。
188
+
181
189
  <!-- Wave 5: Documentation - Document the implemented feature -->
182
190
 
183
191
  - [ ] 5.1 <!-- 更新 API 文档 --> @depends:4.2 @skill:none <!-- justification: documentation task -->
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Apply 阶段任务报告 schema 校验。
3
+ *
4
+ * 背景:编排 Agent 在长任务尾部容易"指令衰减",跳过 Agent tool / spawn_agent
5
+ * 的 subagent 调用,自己在主线程顺手把任务做掉再补一份偷工的报告。这种偷工
6
+ * 报告会缺失 tdd-apply-agent.md / apply-agent.md 模板里强制的章节
7
+ * (TDD Phase / Verify RED / Verify GREEN / Mock Gate / Skill 调用记录 ...)。
8
+ *
9
+ * 本模块对 `zhuanspec/changes/<id>/reports/task-*.md` 做轻量结构校验:
10
+ * - 必备公共字段:`## 状态报告` / Status / Task ID / Report File / Agent 选择决策 / Agent 类型
11
+ * - 当 Agent 类型 = `tddApplyAgent`:再校验 TDD Phase / 上下文就绪摘要 /
12
+ * 验收点映射表 / TDD 执行过程(Verify RED + Verify GREEN)/ 测试运行结果 /
13
+ * Self-Review 发现 / Issues
14
+ * - 当 Agent 类型 = `applyAgent`:校验实施内容 / 修改文件 / Self-Review 发现 / Issues
15
+ *
16
+ * 与 tasks.md 交叉对账:若任务在 tasks.md 里带 `@test-case:TC-XXX`,则该任务的
17
+ * 报告原则上必须由 `tddApplyAgent` 产出(除非报告里显式声明降级原因,对应
18
+ * apply-agent.md 中的"降级使用 applyAgent"路径)。
19
+ */
20
+ export type ReportAgentType = 'tddApplyAgent' | 'applyAgent' | 'unknown';
21
+ export interface ReportIssue {
22
+ level: 'ERROR' | 'WARNING';
23
+ taskId: string;
24
+ message: string;
25
+ }
26
+ export interface SingleReportResult {
27
+ /** Task id parsed from filename, e.g. "1.1". */
28
+ taskId: string;
29
+ /** Absolute path to the report file. */
30
+ filePath: string;
31
+ /** Agent type declared inside report, or 'unknown' when absent. */
32
+ declaredAgentType: ReportAgentType;
33
+ /** Agent type expected from tasks.md (`@test-case` ⇒ tddApplyAgent). */
34
+ expectedAgentType: ReportAgentType;
35
+ /** Whether the report has a downgrade justification (i.e. claims "降级"/"不适合 TDD"). */
36
+ hasDowngradeJustification: boolean;
37
+ /** Section / field names that were required but not found. */
38
+ missing: string[];
39
+ /** Issues collected for this report. */
40
+ issues: ReportIssue[];
41
+ /** Whether the report passes schema validation. */
42
+ valid: boolean;
43
+ }
44
+ export interface ReportSchemaSummary {
45
+ changeId: string;
46
+ reportsDir: string;
47
+ /** Total reports inspected. */
48
+ totalReports: number;
49
+ /** Reports passing all schema checks. */
50
+ passedReports: number;
51
+ /** Reports failing schema checks. */
52
+ failedReports: number;
53
+ /** Tasks in tasks.md that have no report file at all. */
54
+ missingReports: string[];
55
+ /** Per-report results. */
56
+ reports: SingleReportResult[];
57
+ /** Overall validity (no ERROR-level issues + no missing reports). */
58
+ valid: boolean;
59
+ }
60
+ /**
61
+ * Inspect a single report file. Pure string-level checks — no side effects.
62
+ *
63
+ * @param taskId The task id (derived from filename).
64
+ * @param content The raw markdown content of the report file.
65
+ * @param expected The agent type expected from tasks.md (default 'unknown').
66
+ */
67
+ export declare function checkReportContent(taskId: string, filePath: string, content: string, expected: ReportAgentType): SingleReportResult;
68
+ /**
69
+ * Validate all task reports under `<changeDir>/reports/`.
70
+ * Cross-checks against `<changeDir>/tasks.md` to detect missing reports and
71
+ * agent-type mismatches.
72
+ */
73
+ export declare function validateTaskReports(changeDir: string): Promise<ReportSchemaSummary>;
74
+ //# sourceMappingURL=report-schema.d.ts.map