@namewta/speculo 0.7.2 → 0.7.4

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 (55) hide show
  1. package/dist/src/migrations.js +755 -23
  2. package/dist/src/migrations.js.map +1 -1
  3. package/package.json +1 -1
  4. package/template/canonical/canonical-specdev-engineering-cognitive-mentor.md +200 -448
  5. package/template/canonical/canonical-specdev-goal-plan.md +744 -1108
  6. package/template/canonical/canonical-specdev-grill-with-docs.md +201 -449
  7. package/template/canonical/canonical-specdev-spec.md +232 -486
  8. package/template/canonical/canonical-specdev-tickets.md +411 -590
  9. package/template/canonical/canonical-specdev-wayfinder.md +199 -447
  10. package/template/skills/migrate-runtime-state/SKILL.md +6 -6
  11. package/template/skills/migrate-runtime-state/references/migration-contract.md +9 -3
  12. package/template/skills/migrate-runtime-state/scripts/migrate-runtime-state.mjs +404 -33
  13. package/template/workflows/specdev/I-implement/I-implement.md +98 -143
  14. package/template/workflows/specdev/I-implement/evidence-template.md +66 -48
  15. package/template/workflows/specdev/I-implement/execution-preflight.md +31 -21
  16. package/template/workflows/specdev/I-implement/merge-conflict-protocol.md +12 -12
  17. package/template/workflows/specdev/I-init-setup/I-init-setup.md +4 -5
  18. package/template/workflows/specdev/I-init-setup/change-status-template.json +14 -1
  19. package/template/workflows/specdev/I-init-setup/config-template.json +7 -6
  20. package/template/workflows/specdev/I-init-setup/status-template.json +1 -1
  21. package/template/workflows/specdev/INDEX.md +11 -8
  22. package/template/workflows/specdev/P-goal-plan/P-goal-plan.md +76 -102
  23. package/template/workflows/specdev/P-goal-plan/completion-control.md +26 -44
  24. package/template/workflows/specdev/P-goal-plan/goal-plan-template.md +46 -37
  25. package/template/workflows/specdev/P-goal-plan/lead-orchestration.md +34 -0
  26. package/template/workflows/specdev/P-goal-plan/orchestration-protocol.md +31 -46
  27. package/template/workflows/specdev/P-goal-plan/planning-modes.md +67 -89
  28. package/template/workflows/specdev/P-prototype/ui-prototype.md +1 -1
  29. package/template/workflows/specdev/T-tickets/T-tickets.md +6 -3
  30. package/template/workflows/specdev/T-tickets/ticket-readiness.md +5 -3
  31. package/template/workflows/specdev/T-tickets/ticket-template.md +8 -1
  32. package/template/workflows/specdev/T-tickets/tickets-map-template.md +5 -4
  33. package/template/workflows/specdev/_state/status.json +1 -1
  34. package/template/workflows/specdev/common/README.md +2 -2
  35. package/template/workflows/specdev/common/rules/change-completion.md +17 -20
  36. package/template/workflows/specdev/common/rules/deviation-control.md +1 -1
  37. package/template/workflows/specdev/common/rules/evidence-and-verification.md +31 -37
  38. package/template/workflows/specdev/common/rules/path-ownership.md +21 -23
  39. package/template/workflows/specdev/common/rules/readiness-and-depth.md +1 -1
  40. package/template/workflows/specdev/common/schemas/change-status.schema.json +153 -363
  41. package/template/workflows/specdev/common/schemas/config.schema.json +17 -13
  42. package/template/workflows/specdev/common/schemas/goal-plan.schema.json +33 -16
  43. package/template/workflows/specdev/common/schemas/status.schema.json +7 -63
  44. package/template/workflows/specdev/common/skills/dev-worktree/SKILL.md +42 -21
  45. package/template/workflows/specdev/common/skills/dev-worktree/references/create.md +36 -21
  46. package/template/workflows/specdev/common/skills/dev-worktree/references/finalize.md +46 -18
  47. package/template/workflows/specdev/common/skills/subagent-delivery/SKILL.md +34 -31
  48. package/template/workflows/specdev/common/skills/subagent-delivery/references/external-web-subagent.md +10 -23
  49. package/template/workflows/specdev/common/skills/subagent-delivery/references/native-subagent.md +15 -25
  50. package/template/workflows/specdev/common/tools/README.md +2 -1
  51. package/template/workflows/specdev/common/tools/validate-specdev.mjs +591 -219
  52. package/template/workflows/specdev/I-implement/delegated-evidence-template.md +0 -12
  53. package/template/workflows/specdev/P-goal-plan/delegated-execution-template.md +0 -35
  54. package/template/workflows/specdev/P-goal-plan/delegated-execution.md +0 -59
  55. package/template/workflows/specdev/P-goal-plan/workspace-execution-template.md +0 -24
@@ -98,7 +98,7 @@ Ticket 是**决策完备的微型执行计划**:它消除执行者在目标、
98
98
 
99
99
  - `lite`:局部、可逆、沿用既有模式、无公共契约或迁移影响;
100
100
  - `standard`:大多数多文件或跨层垂直切片;
101
- - `deep`:公共 API/schema、数据迁移、安全/隐私/资金、不可逆操作、expand-contract、共享核心路径、多 Agent 或高事故半径。
101
+ - `deep`:公共 API/schema、数据迁移、安全/隐私/资金、不可逆操作、expand-contract、共享核心路径、多个 implementation owner 的跨 Ticket 写入协调或高事故半径。
102
102
 
103
103
  规划深度不是优先级,也不是 Gate。每个 Ticket 必须记录触发该深度的原因。
104
104
 
@@ -115,7 +115,8 @@ Ticket 是**决策完备的微型执行计划**:它消除执行者在目标、
115
115
  - 有序执行路线和安全落点;
116
116
  - expected、writable、read-only、shared 路径;
117
117
  - 正常、失败和回归验证矩阵;
118
- - 用户界面交互受影响时的 E2E Gate 与执行 owner;后续委派 Goal Plan 可以显式把该 Gate 转交 Lead
118
+ - 每个 Ticket Goal Plan workspace 策略定义 current-workspace/direct-parent 或 source-worktree/parent-candidate 检查,以及按实际跨边界风险判定的 E2E disposition
119
+ - 每个实现 Ticket 的 implementation commit 与对应父分支完成条件;仅 required 模式创建独立 worktree;
119
120
  - Deep 的迁移、兼容窗口、监控、回滚和不可逆批准点;
120
121
  - 可判定验收标准。
121
122
 
@@ -143,6 +144,8 @@ Ticket 是**决策完备的微型执行计划**:它消除执行者在目标、
143
144
  - 依赖缺失或 DAG 有环;
144
145
  - 可写路径不明确或并行所有权冲突;
145
146
  - 验证方法不能执行且没有批准的替代证据;
147
+ - Ticket 未声明 E2E required/not-required 及理由,或在 required 模式把 E2E 安排到 source worktree;
148
+ - 无法形成实现 commit 与 Goal Plan 所选 direct-parent/candidate-merge 父分支出口;
146
149
  - 单个新上下文无法完成;
147
150
  - Standard/Deep 缺少有序执行路线;
148
151
  - Deep 缺少迁移、兼容、监控、回滚或批准点。
@@ -223,7 +226,7 @@ node Speculo Node 校验器 \
223
226
 
224
227
  ## 下一步
225
228
 
226
- 满足任一情况时建议运行 “目标规划阶段”:Ticket 数量达到或超过 10、存在多 Agent 并行、Deep Ticket、迁移、共享契约、多个 Gate 或高风险发布。少量线性 Ready Ticket 可直接进入 “实现阶段”。
229
+ 满足任一情况时建议运行 “目标规划阶段”:Ticket 数量达到或超过 10、存在多个 implementation owner 的并行写入协调、Deep Ticket、迁移、共享契约、多个 Gate 或高风险发布。只读 review/research 并行本身不触发 Goal Plan;少量线性 Ready Ticket 可直接进入 “实现阶段”。
227
230
 
228
231
  ---
229
232
 
@@ -307,10 +310,12 @@ node Speculo Node 校验器 \
307
310
  - [ ] 高影响未决问题为零。
308
311
  - [ ] `blocked_by` 指向存在的 Ticket,DAG 无环。
309
312
  - [ ] `expected_changes`、`writable_paths`、`read_only_paths` 和 `shared_paths` 中的项目路径都使用项目根相对路径。
310
- - [ ] `writable_paths` 非空,或明确为仅文档、调查或无代码变更。
313
+ - [ ] `writable_paths` 非空;纯 review/research 不伪装成 I-implement Ticket。
311
314
  - [ ] 每个 shared path 在 `shared_path_owners` 中有唯一 owner。
312
315
  - [ ] 正常、失败和回归至少各有一条验证,或有可信的不适用原因。
313
- - [ ] 仅当用户界面交互受影响时定义 E2E 与当前执行 owner;Ticket 不预设 Lead/Worker,委派 Goal Plan 可以显式改由 Lead 集成。
316
+ - [ ] 明确 `E2E disposition: required | not-required: reason`;required 场景、预期和接缝可执行。
317
+ - [ ] 按 Goal Plan 策略定义 current-workspace 或 source-worktree 的非 E2E 检查;E2E owner 固定为 Lead,运行环境分别为 current-workspace 或 parent-candidate。
318
+ - [ ] Ticket 完成合同包含 implementation commit、direct-parent 或 candidate-merge、父分支 result SHA 和 Lead Evidence;仅 required 模式需要独立 worktree。
314
319
  - [ ] Evidence 位置明确为 `specdev/changes/{change}/evidence/T-NN.md`。
315
320
  - [ ] 单个全新上下文能够完成;否则已拆分。
316
321
  - [ ] 所有内部文件与目录引用使用本文约定的逻辑路径。
@@ -326,7 +331,7 @@ node Speculo Node 校验器 \
326
331
 
327
332
  - [ ] 迁移顺序、兼容窗口、监控、回滚或前向恢复、收缩条件和批准点完整。
328
333
  - [ ] 安全、隐私、资金或数据完整性风险有缓解与验证。
329
- - [ ] 跨 Agent 路径所有权和集成 Gate 明确。
334
+ - [ ] 跨 implementation owner 的路径所有权和所选 direct-parent/parent-candidate 集成 Gate 明确。
330
335
  - [ ] expand-contract 的收缩条件可通过扫描、指标、查询或测试证明。
331
336
 
332
337
  ## Ready 状态
@@ -452,7 +457,12 @@ shared_path_owners: []
452
457
 
453
458
  不适用的关键风险类别必须写“不适用:原因”。
454
459
 
455
- 仅当用户界面交互受影响时增加 E2E 行并指定当前执行 owner。若后续 Goal Plan 含委派附录,再由该计划显式转交 Lead;Ticket 不预设 Lead/Worker 角色。
460
+ - **Workspace checks:** Goal Plan current workspace 或 source worktree 运行单元、组件、静态、类型、lint/build 等适用非 E2E 检查。
461
+ - **E2E disposition:** required / not-required:原因。
462
+ - **E2E owner/environment:** Lead / current-workspace 或 parent-candidate;required 时写明场景、接缝与预期。
463
+ - **Integration evidence:** implementation/source commit、parent before、适用 candidate/result SHA 和父分支包含关系。
464
+
465
+ E2E 由实际跨边界行为与风险决定,不限于 UI;required 模式不得在 Ticket source worktree 运行或声明通过。
456
466
 
457
467
  ## 9. 发布、迁移与恢复
458
468
 
@@ -470,6 +480,8 @@ shared_path_owners: []
470
480
  - [ ] `AC-001`:<可判定结果>。
471
481
  - [ ] 验证矩阵全部执行并记录到 `specdev/changes/{change}/evidence/T-01.md`。
472
482
  - [ ] 实际项目修改未超出 `writable_paths`,shared path 由指定 owner 修改。
483
+ - [ ] Ticket 已按 Goal Plan 策略形成非空 implementation/source commit,direct-parent 或 candidate 验证通过且父分支 result 已记录。
484
+ - [ ] E2E disposition 已执行;required 模式 E2E 在 parent-candidate、current 模式在 current workspace 由 Lead 完成。
473
485
  - [ ] 未发生未批准的范围、契约或发布偏差。
474
486
  - [ ] Ticket、Tickets Map 和 Evidence 状态一致。
475
487
 
@@ -529,10 +541,11 @@ T-01 [READY]
529
541
 
530
542
  ## 5. 并行与路径所有权
531
543
 
532
- - 最大并发来自 `specdev/config.json`。
533
- - shared owner 为专用 Ticket 或明确的集成 owner;只有委派 Goal Plan 才使用 Lead 角色。
544
+ - implementation subagent 上限来自 `specdev/config.json`,Goal Plan 可进一步降低且不含 Lead。
545
+ - review/research/test-observation agent 不设 SpecDev 数字上限,但保持只读。
546
+ - shared owner 为专用 Ticket;Lead 是 SpecDev 状态与父分支 integration owner。
534
547
  - 项目路径契约以 Ticket frontmatter 为准。
535
- - 并行写代码的 Ticket 使用独立 worktree;只读调查不需要。
548
+ - 每个实现 Ticket workspace 由 Goal Plan 选择;current 模式串行使用当前 workspace,required 模式使用独立 worktree;只读调查不进入 I-implement Ticket。
536
549
 
537
550
  | Ticket A | Ticket B | Writable 交集 | 真实依赖 | 处理 |
538
551
  |---|---|---|---|---|
@@ -540,7 +553,7 @@ T-01 [READY]
540
553
 
541
554
  ## 6. Gate、Wave 与集成点
542
555
 
543
- T-tickets 可以标注候选 Wave 和行为里程碑。需要正式跨 Ticket 编排时,由 “目标规划阶段” 完成 Gate、Wave、owner、发布与恢复,并把结果投影回本 Map。
556
+ T-tickets 可以标注候选 Wave、E2E disposition 和行为里程碑。需要正式跨 Ticket 编排时,由 “目标规划阶段” 完成 Gate、Wave、Lead、动态派单边界、candidate 集成顺序、发布与恢复,并把结果投影回本 Map。
544
557
 
545
558
  ## 7. 横切契约与风险
546
559
 
@@ -716,7 +729,7 @@ Change CONTEXT/ADR 是 active change 内的执行权威,不是 workflow 级永
716
729
 
717
730
  ### Deep
718
731
 
719
- 任一条件触发:公共 API、schema、wire format、数据迁移、认证授权、隐私、资金、不可逆操作、expand-contract、共享核心路径、多 Agent 复杂协作、多个实质架构方案或高事故半径。
732
+ 任一条件触发:公共 API、schema、wire format、数据迁移、认证授权、隐私、资金、不可逆操作、expand-contract、共享核心路径、多个 implementation owner 的跨 Ticket 写入协调、多个实质架构方案或高事故半径。
720
733
 
721
734
  额外要求:数据流或状态转换、兼容窗口、迁移顺序、可观测性、回滚、风险缓解、收缩条件和人工批准点。
722
735
 
@@ -756,39 +769,37 @@ Ticket 只有同时满足以下适用条件才可设置 `ready: true`:
756
769
 
757
770
  # 路径所有权与并发规则
758
771
 
759
- 路径所有权是并行执行的硬边界,不是文件预测清单。
772
+ 路径所有权是逻辑写入边界;worktree 是物理隔离边界,两者不能互相替代。
760
773
 
761
774
  ## 1. 四类路径
762
775
 
763
- - `expected_changes`:预计修改的项目路径,仅用于导航;每项写成项目根相对路径。
764
- - `writable_paths`:实现者获准修改的项目路径或 glob,是硬约束。
765
- - `read_only_paths`:建立上下文但不得修改的项目路径。
766
- - `shared_paths`:多个 Ticket 可能需要修改的项目路径,必须指定唯一 owner
767
-
768
- 示例:
776
+ - `expected_changes`:导航预测;
777
+ - `writable_paths`:当前 Ticket implementation owner 可写的硬边界;
778
+ - `read_only_paths`:只读上下文;
779
+ - `shared_paths`:多个 Ticket 可能触达且必须有唯一 owner 的项目路径。
769
780
 
770
- ```yaml
771
- expected_changes: ["src/auth/session.ts"]
772
- writable_paths: ["src/auth/**"]
773
- read_only_paths: ["src/users/**"]
774
- shared_paths: ["package.json"]
775
- ```
781
+ 所有项目路径使用项目根相对路径。根依赖清单、锁文件、根导出、共享 schema、迁移索引、全局路由和跨 Ticket 合同默认视为 shared。
776
782
 
777
783
  ## 2. 所有权规则
778
784
 
779
- 1. 可能并行的 Ticket,其 `writable_paths` 不得相交。
780
- 2. glob 与具体路径按覆盖关系判断,不得只比较字符串。
781
- 3. 根依赖清单、锁文件、根导出、共享 schema、迁移索引、全局路由和跨 Ticket 合同文件默认视为 shared。
782
- 4. shared path 只能由专用 owner Ticket 或 Goal Plan 明确指定的唯一集成 owner 修改;消费者 Ticket 只读。委派 Goal Plan 可以把该 owner 指定为 Lead,但普通计划不预设角色。
783
- 5. 需要越界时先停止,按 下方 `<deviation-control>` 标签 提出 ownership change;不得先改后报。
784
- 6. 前置 Ticket 改变目录结构后,后续 Ticket 开始前重新解析项目路径;若授权范围语义未改变,可只更新导航路径。
785
- 7. 不得把“最后解决合并冲突”当作所有权方案。
785
+ 1. 可能并行的 Ticket,其 writable paths 不得相交;glob 按覆盖关系判断。
786
+ 2. shared path 只由专用 owner Ticket 修改;消费者 Ticket 只读。Lead 负责集成,不以冲突解决替代 shared owner。
787
+ 3. implementation subagent 只写其 Packet 与 Ticket 授权路径;Lead 自行实现也受同一边界约束。
788
+ 4. review/research/test-observation agent 只读项目与 SpecDev 工件。
789
+ 5. 越界前停止并按 deviation control 提出 ownership change;不得先改后报。
790
+ 6. 上游 Ticket 改变目录/合同后,下游基于已集成父分支重新解析路径和 preflight。
791
+
792
+ ## 3. Ticket workspace strategy
793
+
794
+ Goal Plan 创建时选择 Ticket workspace strategy,默认 `current`。`current` 模式的 Ticket 使用当前分支、当前 workspace 和严格串行执行;允许一个 implementation subagent 写入当前 workspace,但前一 Ticket 必须完成 commit、Lead 验收和 direct-parent 验证后才能开始下一个。`required` 模式每个 Ticket 使用唯一来源 worktree `specdev-worktree/<ticket-id>`,并通过 candidate-merge 集成。没有 Ticket 的获批 Direct Spec 继续由 current workspace 唯一 owner 执行;只读调查不创建实现 worktree。
786
795
 
787
- ## 3. Worktree 与分支
796
+ workspace/implementation owner 可以是 Lead 或动态 implementation subagent;integration owner 固定为 Lead。current 模式 Lead 在父分支直接验收和推进,required 模式 Lead 建立 parent-candidate、运行适用 E2E 并推进父分支。required 生命周期由 下方 `<dev-worktree>` 标签 管理,current 生命周期由 I-implement 的 direct-parent 规则管理。
788
797
 
789
- Worktree 只在存在可观察隔离需求时使用:并行写入、保护当前本地状态、一次性实验、后台恢复、provider 要求或用户明确要求。只读调查和没有其他隔离事实的顺序写入默认共用当前工作区。Agent Team、Ticket 数量和泛化的“更安全”都不构成隔离理由。Worktree 防止工作区污染,路径所有权防止逻辑冲突,两者不能互相替代。
798
+ ## 4. 并发
790
799
 
791
- 生命周期由调用方明确的 workspace owner integration owner 下方 `<dev-worktree>` 标签 管理。`single-session` 通常把两者映射为主会话;`lead-team` 可以把 integration owner 映射为 Lead,但角色选择不决定是否使用 worktree。同一 current workspace 只允许一个项目与 SpecDev 状态写入 owner;Worker 要写项目文件时必须拥有独立 workspace。编排规则位于 “目标规划阶段的核心编排规则”。
800
+ required 模式 implementation subagent 上限取 Goal Plan、config 和平台能力共同约束,Lead 不计入。current 模式保持单 writer 串行安全不变量,Ticket 严格串行。review/research/test-observation agent 不设置 SpecDev 数字上限,但 Lead 必须避免重复工作与可变环境争用。
801
+
802
+ **完成标准**:每个项目写入映射到唯一 Ticket、owner 和来源 worktree;shared 与父分支写入 owner 唯一。
792
803
 
793
804
  </path-ownership>
794
805
 
@@ -796,61 +807,55 @@ Worktree 只在存在可观察隔离需求时使用:并行写入、保护当
796
807
 
797
808
  # 证据与验证规范
798
809
 
799
- 验证回答“怎样证明行为已经正确发生”,Evidence 回答“实际运行了什么、结果是什么、仍有什么风险”。
810
+ 验证回答“怎样证明”,Evidence 记录“实际运行了什么、在哪个状态运行、结果和残余风险是什么”。
800
811
 
801
812
  ## 1. 验证矩阵
802
813
 
803
- 每一行绑定一个行为、合同或风险:
814
+ 每行绑定行为、合同或风险,并标记环境:
804
815
 
805
- | 行为或风险 | 验证接缝 | 方法或命令 | 预期结果 | Evidence |
806
- |---|---|---|---|---|
807
- | 正常路径 | 公共接口 | 项目定向测试 | 指定外部行为成立 | `specdev/changes/{change}/evidence/T-NN.md` |
808
- | 无效输入 | schema 或公共接口 | 定向失败测试 | 稳定错误行为成立 | `specdev/changes/{change}/evidence/T-NN.md` |
809
- | 回归 | 现有测试套件 | 项目回归命令 | 相关既有行为保持 | `specdev/changes/{change}/evidence/T-NN.md` |
816
+ | 行为或风险 | 接缝 | 命令/方法 | 环境 | 预期 | Evidence |
817
+ |---|---|---|---|---|---|
818
+ | 正常/失败路径 | 公共接口或稳定接缝 | 定向测试 | current-workspace source-worktree | 合同成立 | Ticket Evidence |
819
+ | 跨模块回归 | 集成接缝 | 回归命令 | current-workspace 或 parent-candidate | 组合状态成立 | Ticket Evidence |
820
+ | E2E required | 真实端到端边界 | 场景步骤 | current-workspace parent-candidate | 外部行为成立 | Ticket Evidence |
821
+
822
+ ## 2. 两层验证
823
+
824
+ ### Current workspace
825
+
826
+ current 模式的 implementation owner 在当前父分支和当前 workspace 工作。Ticket 必须严格串行,workspace clean 后形成非空 implementation commit;Lead 在同一 workspace 执行适用集成/回归和 E2E,并在父 HEAD 未漂移时将 Ticket commit 记录为 result SHA。
827
+
828
+ ### Source-worktree
810
829
 
811
- 命令引用项目脚本时,项目文件路径使用项目根相对路径,例如 `package.json` `Makefile`。
830
+ implementation owner 运行最接近目标行为的单元/组件测试、静态分析、类型、lint/build 等适用非 E2E 检查。来源实现必须在 clean worktree 形成 commit。任何 source-worktree E2E pass 声明无效。
812
831
 
813
- ## 2. 最小充分验证
832
+ ### Parent-candidate
814
833
 
815
- 选择最接近目标行为的稳定接缝:
834
+ required 模式下,Lead 在最新父分支与 source commit 的 candidate 状态运行受影响集成/回归、项目父状态检查和适用 E2E。E2E 由实际跨边界风险决定,不限于 UI;not-required 必须写理由。required E2E 未运行或失败时不得推进父分支。
816
835
 
817
- 1. 公共接口或契约集成测试;
818
- 2. 稳定接缝上的单元测试;
819
- 3. 类型检查、静态分析、lint 和构建;
820
- 4. 可重复手动步骤、截图或查询结果;
821
- 5. 代码阅读推断。
836
+ ### Direct Spec
822
837
 
823
- E2E 仅在变更影响用户界面交互时加入验证矩阵。普通执行由当前实现或集成 owner 运行;委派执行中 Worker 只记录场景、预期结果和待执行状态,由 Lead 在集成阶段运行。APICLI、后端、库或数据变更默认使用其稳定接缝,不追加 E2E
838
+ 获批 Direct Spec 不创建 Ticket worktree 或 candidate。Lead 在 current workspace 记录实施前基线,运行轻量合同要求的定向检查、适用回归与 E2E,并记录最终 checkpointdirty 状态、运行环境、命令、退出状态和未运行原因。E2E 仍只由 Lead 执行;不得为套用两层验证而伪造 Ticket、source/candidate/result 或父分支推进证据。
824
839
 
825
- 低层证据不能替代明确要求的用户行为证据。高风险迁移还需要 dry-run、调用点扫描、数据核对、监控信号或回滚演练。
840
+ 低层证据不能替代明确要求的外部行为证据。高风险迁移还需要 dry-run、调用点扫描、数据核对、监控或恢复演练。
826
841
 
827
- ## 3. 失败分类
842
+ ## 3. Agent 声明
828
843
 
829
- 每个失败必须分类为:
844
+ subagent 只返回候选命令与结果,不写 Evidence。Lead 重读 workspace/Git、必要时复跑或核对输出后落盘;外部 provider 自报、截图、模拟和推断在此之前标记 `unverified`。review/research/test-observation agent 不拥有 E2E Gate。
830
845
 
831
- - Ticket 引入的新失败;
832
- - 基线已存在的失败;
833
- - 环境、权限或基础设施失败;
834
- - 验证本身无效或无法观察目标行为。
846
+ ## 4. 失败分类与完整性
835
847
 
836
- 不得通过跳过测试、放宽断言、吞错、删除用例或把命令移出验证矩阵来制造绿色。
848
+ 失败分类为本 Ticket 新失败、基线既有失败、环境/权限/基础设施失败、无效验证或 candidate stale。不得通过跳过、放宽断言、吞错、删除用例或迁移验证位置制造绿色。
837
849
 
838
- ## 4. Evidence 最低内容
850
+ 受控反向验证只用于可能静默通过的关键门禁:证明检查能在目标风险出现时失败,再恢复并重跑。普通测试不为形式执行破坏性操作。
839
851
 
840
- 每个完成 Ticket `specdev/changes/{change}/evidence/T-NN.md` 记录:
852
+ ## 5. Evidence 最低内容
841
853
 
842
- - 基线、分支或 worktree;
843
- - 实际修改的项目路径;
844
- - 每条命令、退出状态和结果摘要;
845
- - 每条验收合同的证据映射;
846
- - 未运行项与原因;
847
- - 新失败、既有失败和环境失败;
848
- - 偏差及批准;
849
- - 残余风险;
850
- - worktree、提交或 PR 引用;
851
- - 最终结论。
854
+ 每个 Ticket Evidence 至少包含:Lead、Dispatch/返回(若有)、workspace 策略、base/source/result SHA、candidate 字段(required 模式适用,current 模式明确不适用)、实际路径、每条命令/环境/退出状态、合同映射、双轴审查、E2E disposition、未运行项、失败分类、偏差、残余风险和父分支重读结果。
852
855
 
853
- 无法运行关键验证、存在未批准偏差或 Evidence 不完整时,Ticket 不得标为 `done`。
856
+ required Ticket Done 必须有 source commit、通过 candidate、父分支 result 与 Lead Evidence;current Ticket Done 必须有 implementation commit、通过 direct-parent 验证、父分支 result 与 Lead Evidence。无法运行 required 验证、存在未批准偏差、父分支未包含 Ticket commit 或 Evidence 不完整时不得 Done。
857
+
858
+ Direct Spec Evidence 至少包含:用户批准与轻量合同、Lead、实施前/最终 checkpoint、实际路径、定向/回归/E2E 命令及环境、验收映射、未运行项、偏差、残余风险和提交授权状态。
854
859
 
855
860
  </evidence-and-verification>
856
861
 
@@ -898,7 +903,7 @@ E2E 仅在变更影响用户界面交互时加入验证矩阵。普通执行由
898
903
 
899
904
  - 未批准的 ticket、spec、architecture 或 release 偏差不得继续实现。
900
905
  - 不得通过扩大 `writable_paths`、删除测试、降低断言或把风险改写成“已知限制”来绕过停止。
901
- - 偏差影响普通并行执行时,当前集成 owner 必须暂停受影响 Wave,重新计算路径所有权、依赖和 Gate;委派执行由 Lead 承担同一责任。
906
+ - 偏差影响并行执行、source checkpoint 或 candidate 集成时,Lead 必须暂停受影响 Wave,重新计算路径所有权、依赖、Gate 与父分支顺序;任何 subagent 都不能自行改写上层合同。
902
907
 
903
908
  </deviation-control>
904
909
 
@@ -959,77 +964,107 @@ E2E 仅在变更影响用户界面交互时加入验证矩阵。普通执行由
959
964
 
960
965
  <dev-worktree>
961
966
 
962
- # SpecDev Dev Worktree
967
+ # Dev Worktree
968
+
969
+ 本 Skill 由 T-tickets/P-goal-plan/I-implement 和 P-prototype 复用。`purpose=ticket` 仅在 Goal Plan 选择 `required` 时使用完整 source → candidate → parent 状态机;`current` Ticket 不调用本 Skill。`purpose=prototype` 只使用调用方批准的临时生命周期。
970
+
971
+ ## 输入
972
+
973
+ - `operation=create | restore | finalize | remove`;
974
+ - `purpose=ticket | prototype`;
975
+ - repository、父分支、`base_sha`、branch、portable workspace locator;
976
+ - workspace、implementation 和 integration owner;
977
+ - 允许动作、路径合同、验证合同、调用方状态记录位置。
978
+
979
+ required Ticket 还必须提供 Ready Ticket、Goal Plan(若存在)、Evidence 路径、implementation commit 与本地 candidate integration/父分支更新授权。缺失时返回 blocked;current Ticket 应按 I-implement 的 direct-parent 规则执行。
980
+
981
+ ## 1. 创建或恢复
982
+
983
+ `operation=create` 时加载 下方 `<dev-worktree-create>` 标签。Ticket 使用 `specdev-worktree/<ticket-id>`;同一 Ticket 只存在一个来源 worktree。`operation=restore` 时重读实际 Git worktree/branch/tip/dirty 状态并与调用方记录核对,漂移时停止。
984
+
985
+ **完成标准**:来源基线、branch、locator、owners 和实际 Git 状态一致;现有用户改动未被覆盖。
986
+
987
+ ## 2. 来源实现门
988
+
989
+ implementation owner 只在来源 worktree 修改授权项目路径,运行 Ticket 要求的单元、组件、静态、类型、lint/build 等非 E2E 检查。进入 `review` 前,worktree 必须 clean,branch tip 必须是已授权的 `source_checkpoint` commit,实际 diff 必须符合路径合同。
990
+
991
+ **完成标准**:source checkpoint 不可变且可达;来源 worktree 没有 E2E pass 声明。
963
992
 
964
- ## 适用范围
993
+ ## 3. 候选合并与父分支推进
965
994
 
966
- - 只用于具备 `parallel-write`、`protect-local-state`、`disposable-experiment`、`background-resume`、`provider-requirement` `user-requested` 触发事实的 Ready Ticket/原型。
967
- - 只读调查、Agent Team 本身和没有其他隔离事实的顺序执行默认共用当前工作区。
968
- - 调用方必须明确 trigger、workspace owner、implementation owner、integration owner、固定基线、父分支、工作项 ID、持久化 owner 和允许的结束动作。
969
- - Coordination 与 workspace 正交:`single-session` 可以使用本 Skill;`lead-team` 不自动使用。Current workspace 下 Worker 只读;Worker 写入必须绑定本 Skill 创建的独立 workspace。
970
- - 平台原生 worktree 优先;不可用时使用 Git worktree。
995
+ `operation=finalize` 仅由 Lead/integration owner 调用,并加载 下方 `<dev-worktree-finalize>` 标签。Lead 在独立 parent-candidate checkout 组合最新父分支与 source checkpoint,运行集成检查和适用 E2E,通过后才推进父分支。
971
996
 
972
- ## 生命周期
997
+ 本地 candidate checkout/branch 的创建、重建和回收属于已授权 local candidate integration;来源 branch/worktree 的删除仍需要独立 cleanup 授权。push、PR、remote merge、deploy、migration 和生产动作不从本 Skill 继承。
973
998
 
974
- 1. 创建或恢复时加载 下方 `<dev-worktree-create>` 标签。
975
- 2. implementation owner 完成后返回工作项状态、Evidence/record 路径、`workspace_ref`、不可变 source checkpoint、commit 或 PR 引用和未验证项;Ticket worktree 从 `active` 更新为 `review`。
976
- 3. `terminal_action=integrate` 时 integration owner 自动加载 下方 `<dev-worktree-finalize>` 标签;`retain` 保持 review。一次性原型只评估和清理,不合入生产分支。
999
+ **完成标准**:Ticket `integrated` 时父 HEAD 精确等于记录的 result SHA,并包含 source checkpoint;失败或 stale 时父分支未变化。后续 `removed` 只表示来源 branch/worktree 已清理,不撤销该集成事实。
977
1000
 
978
- Ticket worktree 状态依次为 `planned → active → review → integrating → integrated → removed`;失败进入 `blocked`,记录写入 `specdev/changes/{change}/.status.json` 的 `worktrees`。`integrating` 是带完整授权、来源和尝试证据的可恢复锁:同一父分支一次只允许一个 integration owner;fast-forward 与 merge-commit 都必须落到可复核的 `integrated/passed` 终态。原型的 branch、`workspace_ref` 和清理结果只写入 `specdev/changes/{change}/prototypes/{prototype-id}/record.md`,不伪造 Ticket worktree 记录。
1001
+ ## 4. 移除
979
1002
 
980
- ## 边界
1003
+ `operation=remove` 先验证 Ticket 已 `integrated` 或 prototype 已结束、目标 worktree clean、checkpoint 可恢复且删除目标精确。只有明确 cleanup 授权时删除来源 branch/worktree;强制删除需要单独确认。删除后重读 `git worktree list` 与 refs,并只把调用方生命周期状态更新为 `removed`;`base_sha`、source checkpoint、candidate/result、验证、E2E 与 Evidence 字段必须原样保留。
981
1004
 
982
- - 每个隔离 Ticket 使用独立 worktree 和分支;同一并行 Wave 固定相同 `base_sha`。每个原型使用独立 worktree 和分支。
983
- - Git provider 固定使用 `<project-root>/specdev-worktree/<work-item-id>/`,持久化 `workspace_ref: specdev-worktree/<work-item-id>`;`<project-root>` 由 `workspace.json#path_base: project-root` 解析。
984
- - native/external provider 保留其可迁移 opaque locator;所有 provider 都不保存机器绝对路径、认证秘密或真实用户数据。
985
- - 项目根 `.gitignore` 的 `specdev-worktree/` 条目由 `speculo init` 单一维护;缺失时创建流程阻塞并提示重新运行 init。
986
- - E2E 仅适用于用户界面交互受影响的变更,由 integration owner 在集成阶段运行。
987
- - `terminal_action=integrate` 授权本地 fast-forward,以及分叉集成所需的暂存、merge continue 和一次集成专用 merge commit;不授权普通实现提交、push、PR、远端 merge、部署、迁移或删除分支/worktree。
1005
+ **完成标准**:只删除精确授权目标;失败保留现场与恢复命令。
1006
+
1007
+ ## 固定规则
1008
+
1009
+ - Agent Team 不决定 worktree;Ticket 切片本身决定来源 worktree;
1010
+ - Ticket E2E 只在 Lead-owned parent-candidate checkout 运行;
1011
+ - 每个 Done Ticket 必须有 source commit 与父分支 result,worktree 状态为 `integrated` 或其清理后终态 `removed`;
1012
+ - candidate 失败保留来源 worktree 修正,父分支不动;
1013
+ - 成功集成不自动清理来源 branch/worktree。
988
1014
 
989
1015
  </dev-worktree>
990
1016
 
991
1017
  <dev-worktree-create>
992
1018
 
993
- # 创建或恢复工作项 Worktree
1019
+ # Create Or Restore Worktree
1020
+
1021
+ ## Ticket 前置条件
994
1022
 
995
- ## 前置
1023
+ - Ticket Ready,项目根是有效 Git repository,父分支和 `base_sha` 可解析;
1024
+ - implementation commit 与 local candidate integration/父分支更新已授权;
1025
+ - workspace、implementation、integration owner 唯一;integration owner 必须为 Lead;
1026
+ - `specdev-worktree/` 已由 Speculo init 加入项目 `.gitignore`;
1027
+ - 目标 branch/worktree 不覆盖现有用户 workspace,路径合同无冲突。
996
1028
 
997
- - Ticket `ready: true` 且依赖完成,或原型问题与临时写入范围已锁定;项目写路径无冲突。
998
- - 调用方已记录允许的 trigger 及其事实。`parallel-write` 还要求 `specdev/config.json` 中 `git.worktree_for_parallel: true`;一次性原型要求 P-prototype 已取得本次临时 worktree 授权。
999
- - 调用方已指定 workspace owner、implementation owner、integration owner、父分支、工作项 ID、持久化 owner、`integrate | retain`,并固定 `base_sha`;并行 Ticket 共用同一基线。
1029
+ Prototype 只要求调用方已记录本次临时 branch/worktree 授权、问题、owner、locator 和清理策略;它不写 Ticket worktree 状态。
1000
1030
 
1001
- ## 创建
1031
+ ## 创建 Ticket 来源 worktree
1002
1032
 
1003
- 1. Speculo 工作区声明的 `path_base: project-root` 解析 `<project-root>`。若记录的 provider `git`,要求 `workspace_ref` 精确为 `specdev-worktree/<work-item-id>`,拼接后仍位于 project root,且 `specdev-worktree/` 不是逃逸到外部的符号链接。
1004
- 2. 读取调用方拥有的持久化记录:Ticket 使用 `specdev/changes/{change}/.status.json` `worktrees`;原型使用 `specdev/changes/{change}/prototypes/{prototype-id}/record.md`。若已有可恢复记录,Git provider 必须在 `git worktree list --porcelain` 中匹配固定路径、分支与 `base_sha`;native/external 由对应 provider 解析 opaque locator。一致则恢复,任一不一致停止。
1005
- 3. 否则优先调用平台原生 worktree 能力。使用 native/external 时保存 provider 返回的可迁移 locator;不可用时进入 Git fallback。
1006
- 4. Git fallback 前确认项目根 `.gitignore` 已包含 `specdev-worktree/` 或等价根模式。缺失时停止并提示重新运行当前版本 `speculo init`,不在本 Skill 内修改 `.gitignore`。
1007
- 5. Git fallback 固定 `physical_path = <project-root>/specdev-worktree/<work-item-id>`、`workspace_ref = specdev-worktree/<work-item-id>`,从 `base_sha` 执行 `git worktree add -b <work-item-branch> <physical-path> <base-sha>`。已存在但未与同一记录和 Git 注册匹配的目标路径一律阻塞。
1008
- 6. 分支使用 `speculo/<change>/<work-item-id>`;现有分支未能匹配记录时停止。
1009
- 7. 安装项目所需依赖,运行最小基线检查。E2E 不属于 implementation owner 的创建基线。
1010
- 8. Ticket 将记录写入 `worktrees`;`owner` 保持 implementation owner 的兼容含义:
1033
+ 1. 重读父分支 HEAD、工作树、现有 worktrees refs;父 HEAD 与计划基线不一致时由 Lead决定更新 `base_sha` 或阻塞;
1034
+ 2. 固定 branch `speculo/<change>/<ticket-id>` locator `specdev-worktree/<ticket-id>`;
1035
+ 3. 确认目标 branch/path 不存在,或其实际记录精确匹配当前 Ticket;
1036
+ 4. `base_sha` 创建 Git worktree,不复用其他 Ticket/原型目录;
1037
+ 5. 在来源 worktree 读取项目 Agent 指令、依赖、构建与路径合同;
1038
+ 6. 安装实际需要的依赖,运行最小非 E2E 基线;
1039
+ 7. Lead 写入 `specdev/changes/{change}/.status.json`,状态为 `active`。
1040
+
1041
+ 初始记录:
1011
1042
 
1012
1043
  ```json
1013
1044
  {
1014
1045
  "ticket_id": "T-01",
1015
- "owner": "<implementation-owner>",
1016
- "integration_owner": "<integration-owner>",
1046
+ "owner": "lead",
1047
+ "implementation_owner": "lead-or-dynamic-agent",
1048
+ "integration_owner": "lead",
1017
1049
  "provider": "git",
1018
- "base_sha": "<sha>",
1050
+ "base_sha": "<immutable-sha>",
1019
1051
  "parent_branch": "<parent-branch>",
1020
1052
  "branch": "speculo/<change>/T-01",
1021
1053
  "workspace_ref": "specdev-worktree/T-01",
1022
- "terminal_action": "integrate",
1023
1054
  "source_checkpoint": null,
1024
1055
  "integration": {
1025
1056
  "status": "pending",
1026
1057
  "parent_before_sha": null,
1027
1058
  "source_sha": null,
1059
+ "candidate_sha": null,
1060
+ "candidate_branch": null,
1061
+ "candidate_workspace_ref": null,
1028
1062
  "result_sha": null,
1029
1063
  "method": null,
1030
1064
  "conflict_paths": [],
1031
1065
  "verification": "pending",
1032
- "evidence": "specdev/changes/{change}/evidence/T-01.md",
1066
+ "e2e": {"required": false, "status": "not-required", "evidence": null},
1067
+ "evidence": "specdev/changes/<change>/evidence/T-01.md",
1033
1068
  "attempts": 0
1034
1069
  },
1035
1070
  "status": "active",
@@ -1037,39 +1072,73 @@ Ticket worktree 状态依次为 `planned → active → review → integrating
1037
1072
  }
1038
1073
  ```
1039
1074
 
1040
- native/external provider 将示例中的 provider 与 `workspace_ref` 换为对应可迁移 locator,不套用 Git 物理路径。原型不使用本 JSON 结构,只在 record Run and Assets 中记录源码 branch/commit,并在 frontmatter 写入 `workspace_ref` 与清理状态。
1075
+ `e2e.required` Ticket/Goal Plan disposition 一致;required 时初始 status `pending`。
1076
+
1077
+ ## 恢复
1078
+
1079
+ 恢复时核对 repository、branch、locator、`base_sha`、实际 HEAD、dirty 状态和 owner。状态记录与 Git 不一致、branch 被其他 worktree 占用或出现越界修改时停止;Lead 写 blocker,不重建覆盖。
1041
1080
 
1042
- `terminal_action=integrate` 不替代来源实现提交授权;进入 `review` 前必须把已获授权的最终 commit 写为 `source_checkpoint`。完成条件:工作区可定位、基线可用、调用方记录与实际 provider、分支和 checkpoint 一致;Git provider 的引用与工作项 ID 完全一致。失败时在调用方拥有的记录中设为 `blocked` 并保留现场。
1081
+ 进入 `review` 前必须由 implementation owner 创建最终 commit;Lead 重读 branch tip、diff `git status`,把精确 SHA 写入 `source_checkpoint`。
1082
+
1083
+ **完成标准**:来源 worktree 可定位且唯一;基线、记录与 Git 一致;source 检查不含 E2E;失败时保留现场。
1043
1084
 
1044
1085
  </dev-worktree-create>
1045
1086
 
1046
1087
  <dev-worktree-finalize>
1047
1088
 
1048
- # 集成与清理工作项 Worktree
1089
+ # Candidate Merge And Parent Integration
1090
+
1091
+ 仅由 Lead/integration owner 对状态为 `review` 的 Ticket 调用。
1092
+
1093
+ ## 1. 接收 source checkpoint
1094
+
1095
+ 1. 核对 Ticket、Goal Plan、Evidence 目标、owner 与本地 integration 授权;
1096
+ 2. 验证来源 worktree clean,branch tip 精确等于 `source_checkpoint`,commit 从 `base_sha` 可达;
1097
+ 3. 审计实际 diff 未越过 writable/shared owner 合同;
1098
+ 4. 确认 source-worktree 必跑非 E2E 检查已执行,且没有把 E2E 自报为通过;
1099
+ 5. 重读父分支 checkout clean、HEAD 与 remote/本地约定,记录 `parent_before_sha`。
1100
+
1101
+ 失败时保持 `review`/`blocked`,不开始候选合并。
1102
+
1103
+ ## 2. 建立 parent-candidate checkout
1049
1104
 
1050
- ## 集成
1105
+ 1. 使用 branch `speculo/integration/<change>/<ticket-id>` 和 locator `specdev-worktree/.integration/<ticket-id>`,从最新 `parent_before_sha` 建立 Lead-owned integration worktree;
1106
+ 2. 如果父 SHA 是 source checkpoint 的祖先,在 candidate checkout 执行 `git merge --ff-only <source_checkpoint>`,`method=fast-forward`;
1107
+ 3. 否则执行 `git merge --no-ff --no-commit <source_checkpoint>`;
1108
+ 4. 冲突按 下方 `<merge-conflict-protocol>` 标签 处理。需要新产品决定时执行 `git merge --abort`,记录 blocker 并返回来源 worktree;
1109
+ 5. 对分叉结果创建一次 Lead-owned candidate merge commit,`method=merge-commit`;
1110
+ 6. 记录 candidate branch/locator、`candidate_sha`、`source_sha`、冲突路径与 attempts,worktree 状态改为 `integrating`、integration 状态改为 `candidate`。
1051
1111
 
1052
- 仅生产 Ticket 进入本段;一次性原型不得合入生产分支。
1112
+ 重试前从最新父分支重建 candidate branch/worktree;旧 candidate SHA 保存在 Evidence。候选生命周期的重建/回收包含在 local candidate integration 授权中。
1053
1113
 
1054
- 1. integration owner 确认记录为 `review`、`terminal_action=integrate`,读取 implementation owner 的 Evidence,并验证实际修改未越过 writable/shared owner 合同。`source_checkpoint` 必须是不可变 commit,且与记录 branch 当前 tip 一致、从 `base_sha` 可达。
1055
- 2. 确认目标 checkout 正位于 `parent_branch`、index 与项目 working tree 干净,并把当前 HEAD 固定为 `parent_before_sha`。目标不干净、父分支不匹配、其他记录已在同一父分支 `integrating` 或 HEAD 在集成期间变化时停止,不覆盖用户工作。
1056
- 3. 将记录原子更新为 `integrating`,设置 `integration.status=running`、`parent_before_sha`、`source_sha` 并递增 `attempts`。中断恢复时先核对记录、Git `MERGE_HEAD` 和当前 HEAD,不重复开始第二次集成。
1057
- 4. 恢复已有 `integrating` 记录时只进入一个分支:HEAD 仍等于 `parent_before_sha` 且没有 `MERGE_HEAD` 时恢复同一次尝试;HEAD 已等于 `source_checkpoint`、没有 `MERGE_HEAD` 且 `parent_before_sha` 可达来源时,将其视为已完成但尚未落状态的 fast-forward;`MERGE_HEAD` 等于 `source_checkpoint` 时恢复未完成 merge。其他 HEAD、来源或 merge 状态漂移一律设为 `blocked`,不修改 Git 现场。
1058
- 5. 若 `parent_before_sha` 是 `source_checkpoint` 的祖先,先在来源 workspace 运行 Ticket 定向验证、受影响回归、项目 typecheck/lint/build 和适用最小 E2E,再从目标 checkout 执行 `git merge --ff-only <source_checkpoint>`。重读目标 HEAD、tree 和 Evidence,确认 HEAD 精确等于 `source_checkpoint` 后,记录 `method=fast-forward`、`result_sha=source_checkpoint`、空 `conflict_paths`、验证命令与结果、`verification=passed`、Evidence 和 `integration.status=passed`,再把 worktree 状态更新为 `integrated`。这是 fast-forward 的终态,不继续执行 merge-commit 步骤。
1059
- 6. 若双方已分叉,从干净目标 checkout 执行 `git merge --no-ff --no-commit <source_checkpoint>`。出现冲突时加载 下方 `<merge-conflict-protocol>` 标签,并将本记录作为持久授权来源;不为 `git add`、继续 merge 或集成提交重复请求确认。
1060
- 7. 在未提交的合并结果上运行 Ticket 定向验证、受影响回归、项目 typecheck/lint/build 和适用最小 E2E。可由既有意图机械修正的失败最多处理 3 轮;不得放宽断言、删除检查或引入未批准行为。
1061
- 8. 验证通过后完成一次集成专用 merge commit,重读 HEAD、parents、tree、diff 和 Evidence,确认父分支为第一 parent、`source_checkpoint` 为第二 parent,记录 `method=merge-commit`、`result_sha`、conflict paths、`verification=passed`、Evidence 与 `integration.status=passed`,再把 worktree 状态更新为 `integrated`。
1062
- 9. 冲突需要新产品/架构/安全/迁移决定、修改越过授权路径、验证无法通过、目标状态漂移或提交 hook 无法安全完成时,执行 `git merge --abort`(仅限本流程从干净目标开始的 merge),设置 worktree 与 integration 为 `blocked`,记录最小失败、已通过行为和恢复条件,并保留来源 worktree。
1114
+ ## 3. 在候选父状态验证
1063
1115
 
1064
- Fast-forward 路径的 `result_sha` 等于 `source_checkpoint`;merge-commit 路径必须保持父分支为第一 parent、来源 checkpoint 为第二 parent。任何成功结果都必须能从记录和 Evidence 复核。
1116
+ candidate checkout 运行:
1065
1117
 
1066
- ## 清理
1118
+ - Ticket 受影响集成与回归;
1119
+ - 项目要求的 typecheck/lint/build 或其他父状态检查;
1120
+ - 仅当 Ticket/Goal Plan `e2e.required=true` 时运行对应 E2E。
1067
1121
 
1068
- 1. 取得用户对删除 worktree 和分支的授权。
1069
- 2. Git provider 从 project root 解析 `specdev-worktree/<work-item-id>`,重验无路径逃逸且与 `git worktree list --porcelain` 的记录一致,再从主工作树移除;native/external 通过对应 provider 管理入口移除。
1070
- 3. 确认 worktree 不再注册且工作项目录不存在后删除对应分支。Ticket 将状态更新为 `removed`;原型把 `cleanup_status` 更新为 `clean`。保留项目根 `specdev-worktree/` 统一目录及 `.gitignore` 条目。
1122
+ 每条命令记录运行环境 `parent-candidate`、退出码与摘要。E2E required 未运行或失败时 integration `verification=failed`、`status=failed`;父分支保持 `parent_before_sha`。机械修正次数不得超过 Goal Plan 快照的 `integration_attempt_limit`;不得放宽断言、删除检查或发明行为。
1071
1123
 
1072
- PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成也不自动清理。清理失败时停止;仅在用户明确要求时使用强制删除。
1124
+ ## 4. 推进父分支
1125
+
1126
+ 全部 required 检查通过后:
1127
+
1128
+ 1. 重读父分支 HEAD;不等于 `parent_before_sha` 时将 candidate 标记 `stale`,不推进父分支并从步骤 2 重建;
1129
+ 2. 在父分支 checkout 执行 `git merge --ff-only <candidate_sha>`;候选 merge commit 本身已以父 SHA 为第一祖先,因此不再创建第二个 merge commit;
1130
+ 3. 重读父 HEAD、tree 与 ancestor 关系,确认 HEAD 精确等于 candidate SHA 且包含 source checkpoint;
1131
+ 4. 写入 `result_sha=candidate_sha`、`verification=passed`、E2E 最终状态和 Evidence;
1132
+ 5. integration/status 改为 `passed`/`integrated`,再由 Lead 标记 Ticket Done。
1133
+
1134
+ ## 5. 失败、清理与恢复
1135
+
1136
+ - candidate 检查失败:父分支不动,Ticket 回 `in_progress` 或 `blocked`,来源 worktree 保留;
1137
+ - 父 HEAD 漂移:旧 candidate 记 `stale`,完整重建并重跑;
1138
+ - 成功后可按 candidate integration 授权回收 transient integration worktree/branch;来源 branch/worktree 不自动清理。获得独立 cleanup 授权并清理后,只将生命周期状态改为 `removed`,完整保留已经通过的集成与 E2E 证据;
1139
+ - push、PR、remote merge、deploy、migration 和生产动作仍需各自授权。
1140
+
1141
+ **完成标准**:passed 时父 HEAD=result/candidate SHA 且包含 source commit;failed/stale 时父 HEAD 仍为开始该轮记录的父状态或更新后的外部事实,没有本轮候选污染。
1073
1142
 
1074
1143
  </dev-worktree-finalize>
1075
1144
 
@@ -1077,25 +1146,25 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1077
1146
 
1078
1147
  # Merge / Rebase Conflict Protocol
1079
1148
 
1080
- 只在 `git status` 证明仓库正处于 mergerebase 冲突时加载。普通集成设计冲突继续按 deviation/upstream owner 处理。
1149
+ 只在 `git status` 证明仓库正处于 merge/rebase 冲突时加载。
1081
1150
 
1082
1151
  ## 流程
1083
1152
 
1084
- 1. 读取 Git 状态、操作类型、冲突文件、base/ours/theirs commit、当前 Ticket/Evidence,以及是否存在匹配的 `terminal_action=integrate` worktree 记录。
1085
- 2. 追溯双方意图:commit message、冻结的 source、Spec、Ticket、ADR、测试和调用者。二者缺失时不凭代码表面猜测产品行为。
1086
- 3. conflict hunk 写出双方意图、共同约束和建议结果。只合并既有意图;需要发明新行为或改变上层合同则停止并登记 deviation。
1087
- 4. 在获授权可写范围内解决文本,运行受影响测试、typecheck、lint 和项目要求的验证。能从既有权威唯一推导的冲突直接处理,不把“发生冲突”本身升级为人工确认。
1088
- 5. 若当前 merge 来自匹配记录的本地集成,`terminal_action=integrate` 已授权 `git add`、继续 merge 和一次集成专用 commit;验证通过后直接完成,不逐动作请求确认。其他 merge/rebase 仍分别取得 Git 副作用授权;没有授权时保存分析、剩余文件和精确恢复命令。
1089
- 6. 需要发明新产品行为、改变 Spec/ADR、安全/迁移决定、越过路径 owner 或无法保持双方既有意图时停止;由从干净目标开始的自动集成执行 `git merge --abort`,记录 blocker 并保留来源 worktree。普通冲突现场不擅自 abort。
1090
- 7. 重读 Git 状态、parents diff,确认无 marker、无未声明路径、双方要求及测试仍成立。
1153
+ 1. 读取 Git 状态、操作类型、冲突路径、base/ours/theirs SHA、Ticket/Evidence 与匹配的 candidate integration 记录。
1154
+ 2. commitsource、Spec、Ticket、ADR、测试和调用者追溯双方意图;信息不足时不猜产品行为。
1155
+ 3. 对每个 hunk 写出双方意图、共同约束和唯一可推导结果;需要新行为或上层决定时停止并登记 deviation。
1156
+ 4. 在授权路径内解决文本,运行受影响的非 E2E 检查;candidate checkout 中按 finalize 合同运行父状态检查/E2E。
1157
+ 5. 匹配的 local candidate integration 授权包含 `git add`、candidate merge commit、必要的 `git merge --abort` 和 transient candidate checkout/branch 生命周期;不扩展到来源 branch/worktree cleanup 或远端动作。
1158
+ 6. 需要改变 Spec/ADR、安全/迁移决定、越过 owner 或无法同时保持既有意图时,在 Lead-created candidate 中执行 `git merge --abort`,记录 blocker 并保留来源 worktree;未知普通冲突现场不擅自 abort。
1159
+ 7. 重读 Git 状态、parents diff,确认无 marker、无未声明路径、双方合同及验证仍成立。
1091
1160
 
1092
1161
  ## 完成标准
1093
1162
 
1094
- - 每个 hunk 的结果可追溯到双方意图;
1163
+ - 每个 hunk 可追溯到既有意图;
1095
1164
  - 新产品决定没有藏在冲突解决中;
1096
- - 项目验证有命令、退出码和关键输出;
1097
- - Git 副作用来自逐动作授权,或来自可核对 worktree 记录中的持久本地集成授权;
1098
- - 完成或暂停状态可以从 EvidenceGit 状态恢复。
1165
+ - 验证记录命令、运行环境、退出码和摘要;
1166
+ - Git 副作用来自明确的 candidate integration 或其他逐动作授权;
1167
+ - 完成/暂停可以从 Git、change status Evidence 恢复。
1099
1168
 
1100
1169
  </merge-conflict-protocol>
1101
1170
 
@@ -1103,16 +1172,15 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1103
1172
 
1104
1173
  ```json
1105
1174
  {
1106
- "schema_version": 3,
1175
+ "schema_version": 5,
1107
1176
  "interaction_language": "zh-CN",
1108
1177
  "artifact_language": "zh-CN",
1109
1178
  "git": {
1110
- "auto_commit": false,
1111
- "default_branch": null,
1112
- "worktree_for_parallel": true
1179
+ "default_branch": null
1113
1180
  },
1114
1181
  "execution": {
1115
- "max_parallel": 3,
1182
+ "max_implementation_agents": 3,
1183
+ "max_integration_attempts": 3,
1116
1184
  "deep_ticket_human_approval": true,
1117
1185
  "shared_path_owner": "explicit"
1118
1186
  },
@@ -1125,7 +1193,9 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1125
1193
  "planning": {
1126
1194
  "default_depth": "standard",
1127
1195
  "require_ready_gate": true,
1128
- "require_evidence": true
1196
+ "require_evidence": true,
1197
+ "ui_prototype_default_variants": 3,
1198
+ "ui_prototype_max_variants": 5
1129
1199
  }
1130
1200
  }
1131
1201
  ```
@@ -1137,33 +1207,32 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1137
1207
  ```json
1138
1208
  {
1139
1209
  "$schema": "https://json-schema.org/draft/2020-12/schema",
1140
- "$id": "urn:speculo:specdev:config:v3",
1210
+ "$id": "urn:speculo:specdev:config:v5",
1141
1211
  "title": "SpecDev Configuration",
1142
1212
  "type": "object",
1143
1213
  "required": ["schema_version", "interaction_language", "artifact_language", "git", "execution", "verification", "planning"],
1144
1214
  "properties": {
1145
- "schema_version": {"const": 3},
1215
+ "schema_version": {"const": 5},
1146
1216
  "interaction_language": {"type": "string", "minLength": 1},
1147
1217
  "artifact_language": {"type": "string", "minLength": 1},
1148
1218
  "git": {
1149
1219
  "type": "object",
1150
- "required": ["auto_commit", "default_branch", "worktree_for_parallel"],
1220
+ "required": ["default_branch"],
1151
1221
  "properties": {
1152
- "auto_commit": {"type": "boolean"},
1153
- "default_branch": {"type": ["string", "null"]},
1154
- "worktree_for_parallel": {"type": "boolean"}
1222
+ "default_branch": {"type": ["string", "null"]}
1155
1223
  },
1156
- "additionalProperties": true
1224
+ "additionalProperties": false
1157
1225
  },
1158
1226
  "execution": {
1159
1227
  "type": "object",
1160
- "required": ["max_parallel", "deep_ticket_human_approval", "shared_path_owner"],
1228
+ "required": ["max_implementation_agents", "max_integration_attempts", "deep_ticket_human_approval", "shared_path_owner"],
1161
1229
  "properties": {
1162
- "max_parallel": {"type": "integer", "minimum": 1},
1230
+ "max_implementation_agents": {"type": "integer", "minimum": 1},
1231
+ "max_integration_attempts": {"type": "integer", "minimum": 1},
1163
1232
  "deep_ticket_human_approval": {"type": "boolean"},
1164
1233
  "shared_path_owner": {"type": "string", "minLength": 1}
1165
1234
  },
1166
- "additionalProperties": true
1235
+ "additionalProperties": false
1167
1236
  },
1168
1237
  "verification": {
1169
1238
  "type": "object",
@@ -1178,16 +1247,21 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1178
1247
  },
1179
1248
  "planning": {
1180
1249
  "type": "object",
1181
- "required": ["default_depth", "require_ready_gate", "require_evidence"],
1250
+ "required": ["default_depth", "require_ready_gate", "require_evidence", "ui_prototype_default_variants", "ui_prototype_max_variants"],
1182
1251
  "properties": {
1183
1252
  "default_depth": {"enum": ["lite", "standard", "deep"]},
1184
1253
  "require_ready_gate": {"type": "boolean"},
1185
- "require_evidence": {"type": "boolean"}
1254
+ "require_evidence": {"type": "boolean"},
1255
+ "ui_prototype_default_variants": {"type": "integer", "minimum": 1},
1256
+ "ui_prototype_max_variants": {"type": "integer", "minimum": 1}
1186
1257
  },
1187
1258
  "additionalProperties": true
1188
1259
  }
1189
1260
  },
1190
- "additionalProperties": true
1261
+ "allOf": [{
1262
+ "$comment": "ui_prototype_default_variants <= ui_prototype_max_variants is enforced by validate-specdev.mjs because JSON Schema cannot compare sibling numeric values."
1263
+ }],
1264
+ "additionalProperties": false
1191
1265
  }
1192
1266
  ```
1193
1267
 
@@ -1197,7 +1271,7 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1197
1271
 
1198
1272
  ```json
1199
1273
  {
1200
- "schema_version": 4,
1274
+ "schema_version": 5,
1201
1275
  "workflow": "specdev",
1202
1276
  "active": [],
1203
1277
  "archived": []
@@ -1211,83 +1285,27 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1211
1285
  ```json
1212
1286
  {
1213
1287
  "$schema": "https://json-schema.org/draft/2020-12/schema",
1214
- "$id": "urn:speculo:specdev:status:v4",
1288
+ "$id": "urn:speculo:specdev:status:v5",
1215
1289
  "title": "SpecDev Global Status",
1216
1290
  "type": "object",
1217
- "required": [
1218
- "schema_version",
1219
- "workflow",
1220
- "active",
1221
- "archived"
1222
- ],
1291
+ "required": ["schema_version", "workflow", "active", "archived"],
1223
1292
  "properties": {
1224
- "schema_version": {
1225
- "const": 4
1226
- },
1227
- "workflow": {
1228
- "const": "specdev"
1229
- },
1293
+ "schema_version": {"const": 5},
1294
+ "workflow": {"const": "specdev"},
1230
1295
  "active": {
1231
1296
  "type": "array",
1232
1297
  "items": {
1233
1298
  "type": "object",
1234
- "required": [
1235
- "change",
1236
- "current_work",
1237
- "works_run"
1238
- ],
1299
+ "required": ["change"],
1239
1300
  "properties": {
1240
1301
  "change": {
1241
1302
  "type": "string",
1242
1303
  "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]+(?:-[a-z0-9]+)*$"
1243
- },
1244
- "current_work": {
1245
- "type": [
1246
- "string",
1247
- "null"
1248
- ],
1249
- "pattern": "^specdev/"
1250
- },
1251
- "works_run": {
1252
- "type": "array",
1253
- "items": {
1254
- "type": "string",
1255
- "pattern": "^specdev/"
1256
- },
1257
- "uniqueItems": true
1258
- },
1259
- "claimed_investigations": {
1260
- "type": "array",
1261
- "items": {
1262
- "type": "object",
1263
- "required": [
1264
- "id",
1265
- "owner",
1266
- "claimed_at"
1267
- ],
1268
- "properties": {
1269
- "id": {
1270
- "type": "string"
1271
- },
1272
- "owner": {
1273
- "type": "string"
1274
- },
1275
- "session": {
1276
- "type": [
1277
- "string",
1278
- "null"
1279
- ]
1280
- },
1281
- "claimed_at": {
1282
- "type": "string"
1283
- }
1284
- },
1285
- "additionalProperties": false
1286
- }
1287
1304
  }
1288
1305
  },
1289
1306
  "additionalProperties": false
1290
- }
1307
+ },
1308
+ "uniqueItems": true
1291
1309
  },
1292
1310
  "archived": {
1293
1311
  "type": "array",
@@ -1308,11 +1326,24 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1308
1326
 
1309
1327
  ```json
1310
1328
  {
1311
- "schema_version": 3,
1329
+ "schema_version": 6,
1312
1330
  "artifact": "change-status",
1313
1331
  "change": "<YYYY-MM-DD-topic>",
1314
1332
  "change_status": "active",
1315
1333
  "current_work": null,
1334
+ "works_run": [],
1335
+ "claimed_investigations": [],
1336
+ "execution_authorization": {
1337
+ "implementation_commit": {"status": "not-authorized", "source": null, "granted_at": null, "scope": "Ticket implementation commits"},
1338
+ "local_candidate_integration": {"status": "not-authorized", "source": null, "granted_at": null, "scope": "Lead-owned local direct-parent or candidate integration and parent update"},
1339
+ "source_cleanup": {"status": "not-authorized", "source": null, "granted_at": null, "scope": "Source worktree and branch cleanup"}
1340
+ },
1341
+ "leadership": {
1342
+ "current": "<owner-or-session-locator>",
1343
+ "epoch": 1,
1344
+ "assigned_at": "<ISO-8601>",
1345
+ "history": []
1346
+ },
1316
1347
  "created_at": "<ISO-8601>",
1317
1348
  "updated_at": "<ISO-8601>",
1318
1349
  "completed_at": null,
@@ -1331,394 +1362,184 @@ PR、`terminal_action=retain` 或暂缓集成时保留 worktree。成功集成
1331
1362
  ```json
1332
1363
  {
1333
1364
  "$schema": "https://json-schema.org/draft/2020-12/schema",
1334
- "$id": "urn:speculo:specdev:change-status:v3",
1365
+ "$id": "urn:speculo:specdev:change-status:v6",
1335
1366
  "title": "SpecDev Change Status",
1336
1367
  "type": "object",
1337
1368
  "required": [
1338
- "schema_version",
1339
- "artifact",
1340
- "change",
1341
- "change_status",
1342
- "current_work",
1343
- "created_at",
1344
- "updated_at",
1345
- "completed_at",
1346
- "archived",
1347
- "archive_path",
1348
- "blockers",
1349
- "deviations"
1369
+ "schema_version", "artifact", "change", "change_status", "current_work", "works_run",
1370
+ "claimed_investigations", "execution_authorization", "leadership", "created_at", "updated_at",
1371
+ "completed_at", "archived", "archive_path", "blockers", "deviations", "worktrees"
1350
1372
  ],
1351
1373
  "properties": {
1352
- "schema_version": {
1353
- "const": 3
1354
- },
1355
- "artifact": {
1356
- "const": "change-status"
1357
- },
1358
- "change": {
1359
- "type": "string",
1360
- "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]+(?:-[a-z0-9]+)*$"
1361
- },
1362
- "change_status": {
1363
- "enum": [
1364
- "active",
1365
- "blocked",
1366
- "completed",
1367
- "archived"
1368
- ]
1374
+ "schema_version": {"const": 6},
1375
+ "artifact": {"const": "change-status"},
1376
+ "change": {"type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]+(?:-[a-z0-9]+)*$"},
1377
+ "change_status": {"enum": ["active", "blocked", "completed", "archived"]},
1378
+ "current_work": {"type": ["string", "null"], "pattern": "^specdev/"},
1379
+ "works_run": {"type": "array", "items": {"type": "string", "pattern": "^specdev/"}, "uniqueItems": true},
1380
+ "claimed_investigations": {"type": "array", "items": {"$ref": "#/$defs/claim"}},
1381
+ "execution_authorization": {"$ref": "#/$defs/authorization"},
1382
+ "leadership": {"$ref": "#/$defs/leadership"},
1383
+ "created_at": {"type": "string", "minLength": 1},
1384
+ "updated_at": {"type": "string", "minLength": 1},
1385
+ "completed_at": {"type": ["string", "null"]},
1386
+ "archived": {"type": "boolean"},
1387
+ "archive_path": {"anyOf": [{"type": "null"}, {"type": "string", "pattern": "^specdev/archive/[0-9]{4}-[0-9]{2}/.+/$"}]},
1388
+ "blockers": {"type": "array", "items": {"type": "string"}},
1389
+ "deviations": {"type": "array", "items": {"type": "string"}},
1390
+ "worktrees": {"type": "array", "items": {"$ref": "#/$defs/worktree"}}
1391
+ },
1392
+ "$defs": {
1393
+ "claim": {
1394
+ "type": "object",
1395
+ "required": ["id", "owner", "session", "claimed_at"],
1396
+ "properties": {
1397
+ "id": {"type": "string", "minLength": 1},
1398
+ "owner": {"type": "string", "minLength": 1},
1399
+ "session": {"type": ["string", "null"]},
1400
+ "claimed_at": {"type": "string", "minLength": 1}
1401
+ },
1402
+ "additionalProperties": false
1369
1403
  },
1370
- "current_work": {
1371
- "type": [
1372
- "string",
1373
- "null"
1374
- ]
1404
+ "authorization-entry": {
1405
+ "type": "object",
1406
+ "required": ["status", "source", "granted_at", "scope"],
1407
+ "properties": {
1408
+ "status": {"enum": ["authorized", "not-authorized", "revoked"]},
1409
+ "source": {"type": ["string", "null"]},
1410
+ "granted_at": {"type": ["string", "null"]},
1411
+ "scope": {"type": "string", "minLength": 1}
1412
+ },
1413
+ "allOf": [{
1414
+ "if": {"properties": {"status": {"const": "authorized"}}, "required": ["status"]},
1415
+ "then": {"properties": {"source": {"type": "string", "minLength": 1}, "granted_at": {"type": "string", "minLength": 1}}}
1416
+ }],
1417
+ "additionalProperties": false
1375
1418
  },
1376
- "created_at": {
1377
- "type": "string",
1378
- "minLength": 1
1419
+ "authorization": {
1420
+ "type": "object",
1421
+ "required": ["implementation_commit", "local_candidate_integration", "source_cleanup"],
1422
+ "properties": {
1423
+ "implementation_commit": {"$ref": "#/$defs/authorization-entry"},
1424
+ "local_candidate_integration": {"$ref": "#/$defs/authorization-entry"},
1425
+ "source_cleanup": {"$ref": "#/$defs/authorization-entry"}
1426
+ },
1427
+ "additionalProperties": false
1379
1428
  },
1380
- "updated_at": {
1381
- "type": "string",
1382
- "minLength": 1
1429
+ "leadership-history": {
1430
+ "type": "object",
1431
+ "required": ["owner", "epoch", "assigned_at", "ended_at"],
1432
+ "properties": {
1433
+ "owner": {"type": "string", "minLength": 1},
1434
+ "epoch": {"type": "integer", "minimum": 1},
1435
+ "assigned_at": {"type": "string", "minLength": 1},
1436
+ "ended_at": {"type": "string", "minLength": 1}
1437
+ },
1438
+ "additionalProperties": false
1383
1439
  },
1384
- "completed_at": {
1385
- "type": [
1386
- "string",
1387
- "null"
1388
- ]
1440
+ "leadership": {
1441
+ "type": "object",
1442
+ "required": ["current", "epoch", "assigned_at", "history"],
1443
+ "properties": {
1444
+ "current": {"type": "string", "minLength": 1},
1445
+ "epoch": {"type": "integer", "minimum": 1},
1446
+ "assigned_at": {"type": "string", "minLength": 1},
1447
+ "history": {"type": "array", "items": {"$ref": "#/$defs/leadership-history"}}
1448
+ },
1449
+ "additionalProperties": false
1389
1450
  },
1390
- "archived": {
1391
- "type": "boolean"
1451
+ "full-suite": {
1452
+ "type": "object",
1453
+ "required": ["required", "status", "reason", "evidence"],
1454
+ "properties": {
1455
+ "required": {"type": "boolean"},
1456
+ "status": {"enum": ["not-required", "pending", "passed", "failed"]},
1457
+ "reason": {"type": ["string", "null"]},
1458
+ "evidence": {"type": ["string", "null"]}
1459
+ },
1460
+ "allOf": [{
1461
+ "if": {"properties": {"required": {"const": false}}, "required": ["required"]},
1462
+ "then": {"properties": {"status": {"const": "not-required"}, "reason": {"type": "string", "minLength": 1}}}
1463
+ }],
1464
+ "additionalProperties": false
1392
1465
  },
1393
- "archive_path": {
1394
- "anyOf": [
1395
- {
1396
- "type": "null"
1397
- },
1466
+ "worktree": {
1467
+ "type": "object",
1468
+ "required": ["ticket_id", "owner", "implementation_owner", "integration_owner", "provider", "base_sha", "parent_branch", "branch", "workspace_ref", "source_checkpoint", "integration", "status", "updated_at"],
1469
+ "properties": {
1470
+ "ticket_id": {"type": "string", "pattern": "^T-[0-9]{2,}$"},
1471
+ "owner": {"type": "string", "minLength": 1},
1472
+ "implementation_owner": {"type": "string", "minLength": 1},
1473
+ "integration_owner": {"type": "string", "minLength": 1},
1474
+ "provider": {"const": "git"},
1475
+ "base_sha": {"type": "string", "minLength": 1},
1476
+ "parent_branch": {"type": "string", "minLength": 1},
1477
+ "branch": {"type": "string", "minLength": 1},
1478
+ "workspace_ref": {"type": "string", "pattern": "^(?:current|specdev-worktree/[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]+(?:-[a-z0-9]+)*/T-[0-9]{2,})$"},
1479
+ "source_checkpoint": {"type": ["string", "null"]},
1480
+ "integration": {"$ref": "#/$defs/integration"},
1481
+ "status": {"enum": ["planned", "active", "review", "integrating", "integrated", "removed", "blocked"]},
1482
+ "updated_at": {"type": "string", "minLength": 1}
1483
+ },
1484
+ "allOf": [
1398
1485
  {
1399
- "type": "string",
1400
- "pattern": "^specdev/archive/[0-9]{4}-[0-9]{2}/.+/$"
1401
- }
1402
- ]
1403
- },
1404
- "blockers": {
1405
- "type": "array",
1406
- "items": {
1407
- "type": "string"
1408
- }
1409
- },
1410
- "deviations": {
1411
- "type": "array",
1412
- "items": {
1413
- "type": "string"
1414
- }
1415
- },
1416
- "worktrees": {
1417
- "type": "array",
1418
- "items": {
1419
- "type": "object",
1420
- "required": [
1421
- "ticket_id",
1422
- "owner",
1423
- "provider",
1424
- "base_sha",
1425
- "branch",
1426
- "workspace_ref",
1427
- "status",
1428
- "updated_at"
1429
- ],
1430
- "properties": {
1431
- "ticket_id": {
1432
- "type": "string",
1433
- "pattern": "^T-[0-9]{2,}$"
1434
- },
1435
- "owner": {
1436
- "type": "string",
1437
- "minLength": 1
1438
- },
1439
- "integration_owner": {
1440
- "type": "string",
1441
- "minLength": 1
1442
- },
1443
- "provider": {
1444
- "enum": [
1445
- "native",
1446
- "git",
1447
- "external"
1448
- ]
1449
- },
1450
- "base_sha": {
1451
- "type": "string",
1452
- "minLength": 1
1453
- },
1454
- "parent_branch": {
1455
- "type": "string",
1456
- "minLength": 1
1457
- },
1458
- "branch": {
1459
- "type": "string",
1460
- "minLength": 1
1461
- },
1462
- "workspace_ref": {
1463
- "type": "string",
1464
- "minLength": 1,
1465
- "pattern": "^(?!/)(?![A-Za-z]:[\\\\/]).+"
1466
- },
1467
- "terminal_action": {
1468
- "enum": [
1469
- "integrate",
1470
- "retain"
1471
- ]
1472
- },
1473
- "source_checkpoint": {
1474
- "type": [
1475
- "string",
1476
- "null"
1477
- ]
1478
- },
1479
- "integration": {
1480
- "type": "object",
1481
- "required": [
1482
- "status",
1483
- "parent_before_sha",
1484
- "source_sha",
1485
- "result_sha",
1486
- "method",
1487
- "conflict_paths",
1488
- "verification",
1489
- "evidence",
1490
- "attempts"
1491
- ],
1486
+ "if": {"properties": {"workspace_ref": {"const": "current"}}, "required": ["workspace_ref"]},
1487
+ "then": {
1492
1488
  "properties": {
1493
- "status": {
1494
- "enum": [
1495
- "pending",
1496
- "running",
1497
- "passed",
1498
- "blocked"
1499
- ]
1500
- },
1501
- "parent_before_sha": {
1502
- "type": ["string", "null"]
1503
- },
1504
- "source_sha": {
1505
- "type": ["string", "null"]
1506
- },
1507
- "result_sha": {
1508
- "type": ["string", "null"]
1509
- },
1510
- "method": {
1511
- "enum": [null, "fast-forward", "merge-commit"]
1512
- },
1513
- "conflict_paths": {
1514
- "type": "array",
1515
- "items": {"type": "string"}
1516
- },
1517
- "verification": {
1518
- "enum": ["pending", "passed", "failed"]
1519
- },
1520
- "evidence": {
1521
- "type": "string",
1522
- "pattern": "^\\{roots\\.state\\}/specdev/changes/[^<]+/evidence/T-[0-9]{2,}\\.md$"
1523
- },
1524
- "attempts": {
1525
- "type": "integer",
1526
- "minimum": 0
1527
- }
1528
- },
1529
- "additionalProperties": true
1530
- },
1531
- "status": {
1532
- "enum": [
1533
- "planned",
1534
- "active",
1535
- "review",
1536
- "integrating",
1537
- "integrated",
1538
- "removed",
1539
- "blocked"
1540
- ]
1541
- },
1542
- "updated_at": {
1543
- "type": "string",
1544
- "minLength": 1
1545
- }
1546
- },
1547
- "dependentRequired": {
1548
- "terminal_action": [
1549
- "integration_owner",
1550
- "parent_branch",
1551
- "source_checkpoint",
1552
- "integration"
1553
- ]
1554
- },
1555
- "allOf": [
1556
- {
1557
- "if": {
1558
- "properties": {
1559
- "status": {"const": "integrating"}
1560
- },
1561
- "required": ["status"]
1562
- },
1563
- "then": {
1564
- "required": [
1565
- "terminal_action",
1566
- "integration_owner",
1567
- "parent_branch",
1568
- "source_checkpoint",
1569
- "integration"
1570
- ],
1571
- "properties": {
1572
- "terminal_action": {"const": "integrate"}
1573
- }
1574
- }
1575
- },
1576
- {
1577
- "if": {
1578
- "properties": {
1579
- "status": {"enum": ["integrating", "integrated"]},
1580
- "terminal_action": {"const": "integrate"}
1581
- },
1582
- "required": ["status", "terminal_action"]
1583
- },
1584
- "then": {
1585
- "properties": {
1586
- "source_checkpoint": {"type": "string", "minLength": 1},
1587
- "integration": {
1489
+ "integration": {
1490
+ "allOf": [{
1588
1491
  "properties": {
1589
- "parent_before_sha": {"type": "string", "minLength": 1},
1590
- "source_sha": {"type": "string", "minLength": 1},
1591
- "attempts": {"type": "integer", "minimum": 1}
1492
+ "candidate_sha": {"const": null},
1493
+ "candidate_tree_sha": {"const": null},
1494
+ "candidate_branch": {"const": null},
1495
+ "candidate_workspace_ref": {"const": null},
1496
+ "method": {"enum": [null, "direct-parent"]}
1592
1497
  }
1593
- }
1498
+ }]
1594
1499
  }
1595
1500
  }
1596
1501
  },
1597
- {
1598
- "if": {
1599
- "properties": {
1600
- "status": {"const": "integrating"},
1601
- "terminal_action": {"const": "integrate"}
1602
- },
1603
- "required": ["status", "terminal_action"]
1604
- },
1605
- "then": {
1606
- "properties": {
1607
- "integration": {
1608
- "properties": {
1609
- "status": {"const": "running"}
1610
- }
1611
- }
1612
- }
1613
- }
1614
- },
1615
- {
1616
- "if": {
1617
- "properties": {
1618
- "status": {"const": "integrated"},
1619
- "terminal_action": {"const": "integrate"}
1620
- },
1621
- "required": ["status", "terminal_action"]
1622
- },
1623
- "then": {
1624
- "properties": {
1625
- "integration": {
1626
- "properties": {
1627
- "status": {"const": "passed"},
1628
- "result_sha": {"type": "string", "minLength": 1},
1629
- "method": {"enum": ["fast-forward", "merge-commit"]},
1630
- "verification": {"const": "passed"}
1631
- }
1632
- }
1633
- }
1634
- }
1635
- },
1636
- {
1637
- "if": {
1638
- "properties": {
1639
- "terminal_action": {"const": "retain"}
1640
- },
1641
- "required": ["terminal_action"]
1642
- },
1643
- "then": {
1644
- "properties": {
1645
- "status": {
1646
- "not": {"enum": ["integrating", "integrated"]}
1647
- }
1648
- }
1649
- }
1650
- }
1651
- ],
1652
- "additionalProperties": true
1653
- }
1654
- }
1655
- },
1656
- "allOf": [
1657
- {
1658
- "if": {
1659
- "properties": {
1660
- "worktrees": {
1661
- "contains": {
1662
- "properties": {
1663
- "provider": {
1664
- "const": "git"
1665
- }
1666
- },
1667
- "required": [
1668
- "provider"
1669
- ]
1670
- }
1671
- }
1672
- }
1673
- },
1674
- "then": {
1675
- "properties": {
1676
- "worktrees": {
1677
- "items": {
1678
- "if": {
1679
- "properties": {
1680
- "provider": {
1681
- "const": "git"
1682
- }
1683
- },
1684
- "required": [
1685
- "provider"
1686
- ]
1687
- },
1688
- "then": {
1689
- "properties": {
1690
- "workspace_ref": {
1691
- "pattern": "^specdev-worktree/T-[0-9]{2,}$"
1692
- }
1693
- }
1502
+ "else": {
1503
+ "properties": {
1504
+ "integration": {
1505
+ "allOf": [{"properties": {"method": {"enum": [null, "fast-forward", "merge-commit"]}}}]
1694
1506
  }
1695
1507
  }
1696
1508
  }
1697
1509
  }
1698
- }
1510
+ ],
1511
+ "additionalProperties": false
1699
1512
  },
1700
- {
1701
- "if": {
1702
- "properties": {
1703
- "change_status": {
1704
- "const": "archived"
1705
- }
1706
- }
1513
+ "integration": {
1514
+ "type": "object",
1515
+ "required": ["status", "parent_ref", "parent_before_sha", "source_sha", "candidate_sha", "candidate_tree_sha", "candidate_branch", "candidate_workspace_ref", "result_sha", "method", "conflict_paths", "verification", "full_suite", "e2e", "evidence", "attempts", "promotion_status"],
1516
+ "properties": {
1517
+ "status": {"enum": ["pending", "candidate", "passed", "failed", "stale"]},
1518
+ "parent_ref": {"type": ["string", "null"]},
1519
+ "parent_before_sha": {"type": ["string", "null"]},
1520
+ "source_sha": {"type": ["string", "null"]},
1521
+ "candidate_sha": {"type": ["string", "null"]},
1522
+ "candidate_tree_sha": {"type": ["string", "null"]},
1523
+ "candidate_branch": {"type": ["string", "null"]},
1524
+ "candidate_workspace_ref": {"anyOf": [{"type": "null"}, {"type": "string", "pattern": "^specdev-worktree/\\.integration/[0-9]{4}-[0-9]{2}-[0-9]{2}-[a-z0-9]+(?:-[a-z0-9]+)*/T-[0-9]{2,}$"}]},
1525
+ "result_sha": {"type": ["string", "null"]},
1526
+ "method": {"enum": [null, "direct-parent", "fast-forward", "merge-commit"]},
1527
+ "conflict_paths": {"type": "array", "items": {"type": "string"}},
1528
+ "verification": {"enum": ["pending", "passed", "failed"]},
1529
+ "full_suite": {"$ref": "#/$defs/full-suite"},
1530
+ "e2e": {"$ref": "#/$defs/full-suite"},
1531
+ "evidence": {"type": "string", "pattern": "^\\{roots\\.state\\}/specdev/changes/[^<]+/evidence/T-[0-9]{2,}\\.md$"},
1532
+ "attempts": {"type": "integer", "minimum": 0},
1533
+ "promotion_status": {"enum": ["pending", "applying", "applied", "failed", "stale"]}
1707
1534
  },
1708
- "then": {
1709
- "properties": {
1710
- "archived": {
1711
- "const": true
1712
- },
1713
- "archive_path": {
1714
- "type": "string",
1715
- "pattern": "^specdev/archive/[0-9]{4}-[0-9]{2}/.+/$"
1716
- }
1717
- }
1718
- }
1535
+ "additionalProperties": false
1719
1536
  }
1720
- ],
1721
- "additionalProperties": true
1537
+ },
1538
+ "allOf": [{
1539
+ "if": {"properties": {"change_status": {"const": "archived"}}, "required": ["change_status"]},
1540
+ "then": {"properties": {"archived": {"const": true}, "archive_path": {"type": "string", "pattern": "^specdev/archive/[0-9]{4}-[0-9]{2}/.+/$"}}}
1541
+ }],
1542
+ "additionalProperties": false
1722
1543
  }
1723
1544
  ```
1724
1545