@hunter-harness/workflow-harness 0.2.21 → 0.2.23

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 (214) hide show
  1. package/harness/bundles/general/claude-code/.harness-build.json +1 -1
  2. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +12 -3
  3. package/harness/bundles/general/claude-code/harness-archive/checklist.md +14 -0
  4. package/harness/bundles/general/claude-code/harness-archive/templates/render-summary.mjs +24 -3
  5. package/harness/bundles/general/claude-code/harness-archive/templates/summary-data-template.json +11 -0
  6. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
  7. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  9. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +2 -1
  10. package/harness/bundles/general/claude-code/harness-plan/checklist.md +1 -0
  11. package/harness/bundles/general/claude-code/harness-plan/reference.md +17 -15
  12. package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  14. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +3 -1
  15. package/harness/bundles/general/claude-code/harness-submit/checklist.md +7 -1
  16. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  17. package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
  18. package/harness/bundles/general/claude-code/harness-test/checklist.md +6 -0
  19. package/harness/bundles/general/claude-code/scripts/harness_archive.py +1168 -28
  20. package/harness/bundles/general/claude-code/scripts/harness_environment.py +459 -0
  21. package/harness/bundles/general/claude-code/scripts/harness_events.py +93 -14
  22. package/harness/bundles/general/claude-code/scripts/harness_integration.py +126 -14
  23. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +30 -6
  24. package/harness/bundles/general/claude-code/scripts/harness_profile.py +33 -0
  25. package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +30 -8
  26. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  27. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +12 -3
  28. package/harness/bundles/general/codebuddy/harness-archive/checklist.md +14 -0
  29. package/harness/bundles/general/codebuddy/harness-archive/templates/render-summary.mjs +24 -3
  30. package/harness/bundles/general/codebuddy/harness-archive/templates/summary-data-template.json +11 -0
  31. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  32. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  33. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  34. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +2 -1
  35. package/harness/bundles/general/codebuddy/harness-plan/checklist.md +1 -0
  36. package/harness/bundles/general/codebuddy/harness-plan/reference.md +17 -15
  37. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
  38. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  39. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +3 -1
  40. package/harness/bundles/general/codebuddy/harness-submit/checklist.md +7 -1
  41. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  42. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
  43. package/harness/bundles/general/codebuddy/harness-test/checklist.md +6 -0
  44. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +1168 -28
  45. package/harness/bundles/general/codebuddy/scripts/harness_environment.py +459 -0
  46. package/harness/bundles/general/codebuddy/scripts/harness_events.py +93 -14
  47. package/harness/bundles/general/codebuddy/scripts/harness_integration.py +126 -14
  48. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +30 -6
  49. package/harness/bundles/general/codebuddy/scripts/harness_profile.py +33 -0
  50. package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +30 -8
  51. package/harness/bundles/general/codex/.harness-build.json +1 -1
  52. package/harness/bundles/general/codex/harness-archive/SKILL.md +12 -3
  53. package/harness/bundles/general/codex/harness-archive/checklist.md +14 -0
  54. package/harness/bundles/general/codex/harness-archive/templates/render-summary.mjs +24 -3
  55. package/harness/bundles/general/codex/harness-archive/templates/summary-data-template.json +11 -0
  56. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  57. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  58. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  59. package/harness/bundles/general/codex/harness-plan/SKILL.md +2 -1
  60. package/harness/bundles/general/codex/harness-plan/checklist.md +1 -0
  61. package/harness/bundles/general/codex/harness-plan/reference.md +17 -15
  62. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  63. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  64. package/harness/bundles/general/codex/harness-submit/SKILL.md +3 -1
  65. package/harness/bundles/general/codex/harness-submit/checklist.md +7 -1
  66. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  67. package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
  68. package/harness/bundles/general/codex/harness-test/checklist.md +6 -0
  69. package/harness/bundles/general/codex/scripts/harness_archive.py +1168 -28
  70. package/harness/bundles/general/codex/scripts/harness_environment.py +459 -0
  71. package/harness/bundles/general/codex/scripts/harness_events.py +93 -14
  72. package/harness/bundles/general/codex/scripts/harness_integration.py +126 -14
  73. package/harness/bundles/general/codex/scripts/harness_ledger.py +30 -6
  74. package/harness/bundles/general/codex/scripts/harness_profile.py +33 -0
  75. package/harness/bundles/general/codex/scripts/harness_test_guard.py +30 -8
  76. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  77. package/harness/bundles/general/cursor/harness-archive/SKILL.md +12 -3
  78. package/harness/bundles/general/cursor/harness-archive/checklist.md +14 -0
  79. package/harness/bundles/general/cursor/harness-archive/templates/render-summary.mjs +24 -3
  80. package/harness/bundles/general/cursor/harness-archive/templates/summary-data-template.json +11 -0
  81. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  82. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  83. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  84. package/harness/bundles/general/cursor/harness-plan/SKILL.md +2 -1
  85. package/harness/bundles/general/cursor/harness-plan/checklist.md +1 -0
  86. package/harness/bundles/general/cursor/harness-plan/reference.md +17 -15
  87. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  88. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  89. package/harness/bundles/general/cursor/harness-submit/SKILL.md +3 -1
  90. package/harness/bundles/general/cursor/harness-submit/checklist.md +7 -1
  91. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  92. package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
  93. package/harness/bundles/general/cursor/harness-test/checklist.md +6 -0
  94. package/harness/bundles/general/cursor/scripts/harness_archive.py +1168 -28
  95. package/harness/bundles/general/cursor/scripts/harness_environment.py +459 -0
  96. package/harness/bundles/general/cursor/scripts/harness_events.py +93 -14
  97. package/harness/bundles/general/cursor/scripts/harness_integration.py +126 -14
  98. package/harness/bundles/general/cursor/scripts/harness_ledger.py +30 -6
  99. package/harness/bundles/general/cursor/scripts/harness_profile.py +33 -0
  100. package/harness/bundles/general/cursor/scripts/harness_test_guard.py +30 -8
  101. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  102. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  103. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +12 -3
  104. package/harness/bundles/java/claude-code/harness-archive/checklist.md +14 -0
  105. package/harness/bundles/java/claude-code/harness-archive/templates/render-summary.mjs +24 -3
  106. package/harness/bundles/java/claude-code/harness-archive/templates/summary-data-template.json +11 -0
  107. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  108. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  109. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  110. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  111. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +2 -1
  112. package/harness/bundles/java/claude-code/harness-plan/checklist.md +1 -0
  113. package/harness/bundles/java/claude-code/harness-plan/reference.md +17 -15
  114. package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
  115. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  116. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +3 -1
  117. package/harness/bundles/java/claude-code/harness-submit/checklist.md +7 -1
  118. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  119. package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
  120. package/harness/bundles/java/claude-code/scripts/harness_archive.py +1168 -28
  121. package/harness/bundles/java/claude-code/scripts/harness_environment.py +459 -0
  122. package/harness/bundles/java/claude-code/scripts/harness_events.py +93 -14
  123. package/harness/bundles/java/claude-code/scripts/harness_integration.py +126 -14
  124. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +30 -6
  125. package/harness/bundles/java/claude-code/scripts/harness_profile.py +33 -0
  126. package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +30 -8
  127. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  128. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  129. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +12 -3
  130. package/harness/bundles/java/codebuddy/harness-archive/checklist.md +14 -0
  131. package/harness/bundles/java/codebuddy/harness-archive/templates/render-summary.mjs +24 -3
  132. package/harness/bundles/java/codebuddy/harness-archive/templates/summary-data-template.json +11 -0
  133. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  134. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  135. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  136. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  137. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +2 -1
  138. package/harness/bundles/java/codebuddy/harness-plan/checklist.md +1 -0
  139. package/harness/bundles/java/codebuddy/harness-plan/reference.md +17 -15
  140. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
  141. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  142. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +3 -1
  143. package/harness/bundles/java/codebuddy/harness-submit/checklist.md +7 -1
  144. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  145. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
  146. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +1168 -28
  147. package/harness/bundles/java/codebuddy/scripts/harness_environment.py +459 -0
  148. package/harness/bundles/java/codebuddy/scripts/harness_events.py +93 -14
  149. package/harness/bundles/java/codebuddy/scripts/harness_integration.py +126 -14
  150. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +30 -6
  151. package/harness/bundles/java/codebuddy/scripts/harness_profile.py +33 -0
  152. package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +30 -8
  153. package/harness/bundles/java/codex/.harness-build.json +1 -1
  154. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  155. package/harness/bundles/java/codex/harness-archive/SKILL.md +12 -3
  156. package/harness/bundles/java/codex/harness-archive/checklist.md +14 -0
  157. package/harness/bundles/java/codex/harness-archive/templates/render-summary.mjs +24 -3
  158. package/harness/bundles/java/codex/harness-archive/templates/summary-data-template.json +11 -0
  159. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  160. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  161. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  162. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  163. package/harness/bundles/java/codex/harness-plan/SKILL.md +2 -1
  164. package/harness/bundles/java/codex/harness-plan/checklist.md +1 -0
  165. package/harness/bundles/java/codex/harness-plan/reference.md +17 -15
  166. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  167. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  168. package/harness/bundles/java/codex/harness-submit/SKILL.md +3 -1
  169. package/harness/bundles/java/codex/harness-submit/checklist.md +7 -1
  170. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  171. package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
  172. package/harness/bundles/java/codex/scripts/harness_archive.py +1168 -28
  173. package/harness/bundles/java/codex/scripts/harness_environment.py +459 -0
  174. package/harness/bundles/java/codex/scripts/harness_events.py +93 -14
  175. package/harness/bundles/java/codex/scripts/harness_integration.py +126 -14
  176. package/harness/bundles/java/codex/scripts/harness_ledger.py +30 -6
  177. package/harness/bundles/java/codex/scripts/harness_profile.py +33 -0
  178. package/harness/bundles/java/codex/scripts/harness_test_guard.py +30 -8
  179. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  180. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  181. package/harness/bundles/java/cursor/harness-archive/SKILL.md +12 -3
  182. package/harness/bundles/java/cursor/harness-archive/checklist.md +14 -0
  183. package/harness/bundles/java/cursor/harness-archive/templates/render-summary.mjs +24 -3
  184. package/harness/bundles/java/cursor/harness-archive/templates/summary-data-template.json +11 -0
  185. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  186. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  187. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  188. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  189. package/harness/bundles/java/cursor/harness-plan/SKILL.md +2 -1
  190. package/harness/bundles/java/cursor/harness-plan/checklist.md +1 -0
  191. package/harness/bundles/java/cursor/harness-plan/reference.md +17 -15
  192. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  193. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  194. package/harness/bundles/java/cursor/harness-submit/SKILL.md +3 -1
  195. package/harness/bundles/java/cursor/harness-submit/checklist.md +7 -1
  196. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  197. package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
  198. package/harness/bundles/java/cursor/scripts/harness_archive.py +1168 -28
  199. package/harness/bundles/java/cursor/scripts/harness_environment.py +459 -0
  200. package/harness/bundles/java/cursor/scripts/harness_events.py +93 -14
  201. package/harness/bundles/java/cursor/scripts/harness_integration.py +126 -14
  202. package/harness/bundles/java/cursor/scripts/harness_ledger.py +30 -6
  203. package/harness/bundles/java/cursor/scripts/harness_profile.py +33 -0
  204. package/harness/bundles/java/cursor/scripts/harness_test_guard.py +30 -8
  205. package/harness/manifests/general/claude-code.json +29 -25
  206. package/harness/manifests/general/codebuddy.json +29 -25
  207. package/harness/manifests/general/codex.json +29 -25
  208. package/harness/manifests/general/cursor.json +29 -25
  209. package/harness/manifests/java/claude-code.json +30 -26
  210. package/harness/manifests/java/codebuddy.json +30 -26
  211. package/harness/manifests/java/codex.json +30 -26
  212. package/harness/manifests/java/cursor.json +30 -26
  213. package/hunter-workflow-family.json +2 -2
  214. package/package.json +1 -1
@@ -2,5 +2,5 @@
2
2
  "schemaVersion": 1,
3
3
  "overlay": "none",
4
4
  "agent": "claude-code",
5
- "coreHash": "7996938abca24d16"
5
+ "coreHash": "15e7aa9003de59d7"
6
6
  }
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-archive — 变更归档
25
25
 
26
26
  ## Purpose
@@ -56,6 +56,11 @@ disallowed-tools:
56
56
  - `evidence/verification-ledger.json`
57
57
  - 至少一个 test 或 review 报告/证据
58
58
  - 缺失任一项 → `archivable=false`;可从 `.harness/cache/change-snapshots/<change>/` 恢复正式层后再重试
59
+ - **产品候选验证**:
60
+ - 有远端 CI:保留 `product-candidate-ci.json` 兼容证据;归档会把有效的 legacy schema v1 证据迁移为 `remote-claimed` 的 schema v2 `product-candidate-verification.json`,不会冒充 `remote-attested`。
61
+ - `remote-attested` 必须同时带远端运行 URL 与 `verification.attestationDigest`;只有 URL、旧 JSON 哈希或 ledger 哈希只能达到 `remote-claimed`。
62
+ - 无 CI:先运行 `harness_archive.py certify-local --change-dir ... --project . --json`,只复用身份一致且完整的 `unitTestFull` ledger 证据,不重复执行测试。
63
+ - `release-candidate` 默认要求候选验证通过;仅封存未完成事实时显式使用 `--intent record-only`,归档结果必须为 `releaseEligible=false`,不得用于发布。
59
64
 
60
65
  ## Inputs
61
66
 
@@ -109,9 +114,9 @@ blocking user confirmation 让用户确认归档操作。**用户拒绝 → 终
109
114
 
110
115
  ### Phase 3:执行归档
111
116
 
112
- 1. 运行 `python <skills-root>/scripts/harness_archive.py status --change-dir ".harness/changes/<change-name>" --json` 前置检查。
117
+ 1. 运行 `python <skills-root>/scripts/harness_archive.py status --change-dir ".harness/changes/<change-name>" --intent release-candidate --json` 前置检查。无 CI 项目若已有完整全量 ledger,先运行 `certify-local`;若用户明确只封存事实,则 status/finalize 均使用 `--intent record-only`。
113
118
  2. `meta/archive-meta.md` **由 `harness_archive.py finalize` 自动生成**(与 summary-data `finalStatus` 同源);**禁止 agent 手写**该文件,手写视为数据丢失。维护者结论写入 events(decision/issue)即可,finalize 会汇总到 summary / archive-meta。
114
- 3. 运行 `python <skills-root>/scripts/harness_archive.py finalize --change-dir ".harness/changes/<change-name>" --archive-root ".harness/archive" --json`;读 JSON(cleanup、事件、移动、collect、render、validate、manifest 比对、archive-meta)。finalize 内部负责且仅负责一次 `phase.start` / `phase.end`,调用者不得重复追加。**finalize 不再同步执行知识维护**(§8.2):它写一个 `pending` maintenance-outbox 项即返回,`knowledgeMaintenance=QUEUED`;写 outbox 失败时 `NOT_QUEUED`(warning,不回滚 archive,总状态 CONDITIONAL)。后续由 `harness-sync` / `harness_knowledge.py maintain` 异步推进 outbox。**finalize 失败或 validate 报错时不删除原目录**。
119
+ 3. 运行 `python <skills-root>/scripts/harness_archive.py finalize --change-dir ".harness/changes/<change-name>" --archive-root ".harness/archive" --intent <release-candidate|record-only> --json`;读 JSON(cleanup、事件、移动、collect、render、validate、manifest 比对、archive-meta)。finalize 内部负责且仅负责一次 `phase.start` / `phase.end`,调用者不得重复追加。**finalize 不再同步执行知识维护**(§8.2):它写一个 `pending` maintenance-outbox 项即返回,`knowledgeMaintenance=QUEUED`;写 outbox 失败时 `NOT_QUEUED`(warning,不回滚 archive,总状态 CONDITIONAL)。后续由 `harness-sync` / `harness_knowledge.py maintain` 异步推进 outbox。**finalize 失败或 validate 报错时不删除原目录**。
115
120
 
116
121
  - **Read `reference.md`** — finalize 输出字段、archive-meta 格式、CONDITIONAL_OK 规则
117
122
  - **Read `templates/summary-data-template.json`** — summary-data 数据结构
@@ -187,6 +192,10 @@ finalize 内部负责且仅负责一次 `phase.start` / `phase.end`,并在移
187
192
 
188
193
  git 命令通过 `powershell.exe -Command "..."` 执行;archive-meta.md 和 final-summary.html 不得含明文 token/密码/密钥;归档报告必须区分 ✅真实成功 / 🟡跳过·静态验证 / ❌失败。
189
194
 
195
+ ### 十三、归档完整性与发布资格分离
196
+
197
+ `archiveIntegrity` 表示归档内容是否完整;`candidateVerification` 表示候选验证证据及保证级别;`releaseEligible` 只有两者均满足发布策略时才为 true。`record-only` 允许保留证据不足的历史事实,但绝不等价于 CI 绿灯或可发布。
198
+
190
199
  ## Output Format
191
200
 
192
201
  > 归档元数据格式见 `reference.md` 的 archive-meta 模板;最终报告由 `templates/summary-data-template.json` 数据结构 + `templates/render-summary.mjs` 固定脚本渲染。
@@ -14,6 +14,20 @@ description: harness-archive 的归档前检查项和归档后验证项。仅在
14
14
  - before/after checksum 不一致时,不得删除原目录。
15
15
  - 默认渲染器 `templates/render-summary.mjs`(finalize 内嵌调用)。
16
16
 
17
+ ### Wave-A 状态机与身份(IA-1 / IA-4)
18
+
19
+ 硬顺序:feature frozen → local gates → product candidate CI → **CI green** → merge → authoritative CI → archive product candidate → archive-only governance → release。
20
+
21
+ - [ ] `evidence/product-candidate-ci.json`(或等价 ledger 字段)`conclusion=success`,含 `runUrl` + `commit`;否则 `PRODUCT_CI_NOT_GREEN` 阻断
22
+ - [ ] summary/identity 含 `productCommit` / `productTreeHash` / `archiveCommit`;`productTreeHash` 排除 `.harness/**`
23
+ - [ ] 产品输入在 archive 后变化 → `ARCHIVE_EVIDENCE_REOPEN_REQUIRED`,旧 archive 不可作发布证据
24
+ - [ ] Manifest:coverage 字节在最终 snapshot 后不得静默漂移;后写报告必须 `exclusionReasons`,禁止假绿 `checksumStatus=OK`
25
+
26
+ ### Environment 合同(IA-3)
27
+
28
+ - [ ] 使用可写环境栈前:`harness_environment.py fingerprint` → `acquire` lease → run → `release`
29
+ - [ ] 租约落在主仓 `.harness/runtime/env-leases/`;跨 change 默认不得共享可写 volume
30
+
17
31
  ## 归档前检查(Phase 1)
18
32
 
19
33
  > ⚠️ **单一所有权**:finalize 内部负责且仅负责一次 `phase.start` / `phase.end`。归档前检查不得自行追加 archive 阶段边界。
@@ -42,6 +42,16 @@ const duration = (minutes) => {
42
42
  if (value < 60) return `${Math.round(value * 10) / 10} 分钟`;
43
43
  return `${Math.floor(value / 60)} 小时 ${Math.round(value % 60)} 分钟`;
44
44
  };
45
+ const durationMs = (ms) => {
46
+ const value = number(ms);
47
+ if (value <= 0) return "0 秒";
48
+ if (value < 1000) return `${value}ms`;
49
+ const seconds = value / 1000;
50
+ if (seconds < 60) return `${Math.round(seconds * 10) / 10} 秒`;
51
+ const minutes = seconds / 60;
52
+ if (minutes < 60) return `${Math.round(minutes * 10) / 10} 分钟`;
53
+ return `${Math.floor(minutes / 60)} 小时 ${Math.round(minutes % 60)} 分钟`;
54
+ };
45
55
 
46
56
  const stages = Object.entries(record(data.stageStatus));
47
57
  const verification = record(data.verification);
@@ -49,6 +59,17 @@ const unit = record(verification.unitTests);
49
59
  const api = record(verification.apiTests);
50
60
  const durations = record(data.durations);
51
61
  const durationStages = list(durations.stages);
62
+ const timing = record(data.timing);
63
+ const wallLabel = timing.workflowWallClockMs != null
64
+ ? durationMs(timing.workflowWallClockMs)
65
+ : (durations.totalLabel || duration(durations.totalMinutes));
66
+ const timingColumnsHtml = `
67
+ <article class="card" id="timingColumns"><h2>时长(三列)</h2>
68
+ <div class="row"><div><strong>活动执行</strong><small>stageActiveExecution</small></div><span>${esc(durationMs(timing.stageActiveExecutionMs))}</span></div>
69
+ <div class="row"><div><strong>阶段墙钟</strong><small>stageWallClockSpan</small></div><span>${esc(durationMs(timing.stageWallClockSpanMs))}</span></div>
70
+ <div class="row"><div><strong>全流程墙钟</strong><small>workflowWallClock</small></div><span>${esc(durationMs(timing.workflowWallClockMs))}</span></div>
71
+ <p><small>reportCutoffAt=<code id="reportCutoffAt">${esc(timing.reportCutoffAt || "N/A")}</code> · durations.totalMinutes 仅为活动执行,不冒充墙钟</small></p>
72
+ </article>`;
52
73
  const maxMinutes = Math.max(1, ...durationStages.map((item) => number(item.minutes)));
53
74
  const diff = record(data.diffStat);
54
75
  const risks = list(data.knownRisks);
@@ -86,12 +107,12 @@ const html = `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><met
86
107
  @media(max-width:800px){.metrics{grid-template-columns:1fr 1fr}.grid,.risk{grid-template-columns:1fr}}@media(max-width:480px){main{width:calc(100% - 18px);margin-top:9px}.metrics{grid-template-columns:1fr}.hero{padding:19px}h1{font-size:23px}dl{grid-template-columns:1fr}}
87
108
  </style></head><body><main>
88
109
  <section class="hero"><div class="eyebrow">HARNESS EXECUTION REPORT</div><h1>${esc(data.changeName || "未命名变更")}</h1><p class="goal">${esc(data.businessGoal || "未记录业务目标")}</p><div class="status">${pill(data.finalStatus)}<span>基于事件、验证账本与 Git 证据生成${data.riskTier ? ` · riskTier=${esc(data.riskTier)}` : ""}</span></div>${reasonHtml ? `<div class="status">${reasonHtml}</div>` : ""}</section>
89
- <section class="metrics"><article class="metric"><small>任务提交</small><strong><code title="${esc(data.finalCommit)}">${esc(shortHash(data.finalCommit))}</code></strong><small>${esc(data.finalCommitBranch || "未记录分支")}</small></article><article class="metric"><small>代码范围</small><strong>${number(diff.filesChanged)} 个文件</strong><small><span class="plus">+${number(diff.insertions)}</span> · <span class="minus">-${number(diff.deletions)}</span></small></article><article class="metric"><small>总耗时</small><strong>${esc(durations.totalLabel || duration(durations.totalMinutes))}</strong><small>${durationStages.length} 个阶段</small></article><article class="metric"><small>归档完整性</small><strong>${esc(record(data.archiveManifest).checksumStatus || "UNKNOWN")}</strong><small>${number(record(data.archiveManifest).totalArchiveFiles)} 个归档文件</small></article></section>
90
- <section class="grid"><div><article class="card"><h2>验证结论</h2>${verificationHtml}</article><article class="card"><h2>阶段耗时</h2>${durationHtml}</article></div><div><article class="card"><h2>阶段状态</h2>${stageHtml}</article><article class="card"><h2>风险与后续</h2><div class="risk"><div><h3>已知风险</h3><ul>${riskHtml}</ul></div><div><h3>人工动作</h3><ul>${actionHtml}</ul></div></div></article></div></section>
110
+ <section class="metrics"><article class="metric"><small>产品提交</small><strong><code title="${esc(data.productCommit || data.finalCommit)}">${esc(shortHash(data.productCommit || data.finalCommit))}</code></strong><small>archive=${esc(shortHash(data.archiveCommit || data.finalCommit))}</small></article><article class="metric"><small>代码范围</small><strong>${number(diff.filesChanged)} 个文件</strong><small><span class="plus">+${number(diff.insertions)}</span> · <span class="minus">-${number(diff.deletions)}</span></small></article><article class="metric"><small>全流程墙钟</small><strong>${esc(wallLabel)}</strong><small>活动=${esc(durationMs(timing.stageActiveExecutionMs))} · ${durationStages.length} 阶段</small></article><article class="metric"><small>归档完整性</small><strong>${esc(record(data.archiveManifest).checksumStatus || "UNKNOWN")}</strong><small>${number(record(data.archiveManifest).totalArchiveFiles)} 个归档文件</small></article></section>
111
+ <section class="grid"><div><article class="card"><h2>验证结论</h2>${verificationHtml}</article><article class="card"><h2>阶段耗时(活动)</h2>${durationHtml}</article>${timingColumnsHtml}</div><div><article class="card"><h2>阶段状态</h2>${stageHtml}</article><article class="card"><h2>风险与后续</h2><div class="risk"><div><h3>已知风险</h3><ul>${riskHtml}</ul></div><div><h3>人工动作</h3><ul>${actionHtml}</ul></div></div></article></div></section>
91
112
  <details><summary>变更文件(${files.length})</summary><div><table><thead><tr><th>文件</th><th>新增</th><th>删除</th></tr></thead><tbody>${fileRows}</tbody></table></div></details>
92
113
  <details><summary>执行时间线与工具交接(${timeline.length})</summary><div><table><thead><tr><th>阶段</th><th>尝试</th><th>状态</th><th>来源 / 摘要</th></tr></thead><tbody>${timelineRows}</tbody></table></div></details>
93
114
  <details><summary>命令证据(${commands.length})</summary><div><table><thead><tr><th>阶段</th><th>命令</th><th>结果</th></tr></thead><tbody>${commandRows}</tbody></table></div></details>
94
- <details><summary>技术元数据</summary><div><dl><dt>完整提交</dt><dd><code>${esc(data.finalCommit || "N/A")}</code></dd><dt>基线提交</dt><dd><code>${esc(data.baseCommit || "N/A")}</code></dd><dt>Git 范围</dt><dd><code>${esc(diff.range || "N/A")}</code></dd><dt>报告数据版本</dt><dd>${esc(data.schemaVersion || "N/A")}</dd><dt>事实来源</dt><dd>${esc(list(record(data.reportPipeline).sources).join(" · ") || "N/A")}</dd></dl></div></details>
115
+ <details><summary>技术元数据</summary><div><dl><dt>产品提交</dt><dd><code>${esc(data.productCommit || data.finalCommit || "N/A")}</code></dd><dt>产品树哈希</dt><dd><code>${esc(data.productTreeHash || "N/A")}</code></dd><dt>归档提交</dt><dd><code>${esc(data.archiveCommit || data.finalCommit || "N/A")}</code></dd><dt>基线提交</dt><dd><code>${esc(data.baseCommit || "N/A")}</code></dd><dt>Git 范围</dt><dd><code>${esc(diff.range || "N/A")}</code></dd><dt>报告数据版本</dt><dd>${esc(data.schemaVersion || "N/A")}</dd><dt>事实来源</dt><dd>${esc(list(record(data.reportPipeline).sources).join(" · ") || "N/A")}</dd></dl></div></details>
95
116
  </main></body></html>`;
96
117
 
97
118
  fs.mkdirSync(path.dirname(outPath), { recursive: true });
@@ -3,6 +3,17 @@
3
3
  "changeName": "<change-name>",
4
4
  "businessGoal": "本次变更为了做什么",
5
5
  "finalStatus": "OK | WARN | CONDITIONAL_OK | FAIL",
6
+ "archiveIntent": "release-candidate | record-only",
7
+ "archiveIntegrity": {
8
+ "ok": true
9
+ },
10
+ "candidateVerification": {
11
+ "ok": false,
12
+ "code": "PRODUCT_CANDIDATE_VERIFIED | PRODUCT_CANDIDATE_NOT_VERIFIED | PRODUCT_CI_GREEN | PRODUCT_CI_NOT_GREEN",
13
+ "assurance": "local-reproducible | remote-claimed | remote-attested",
14
+ "message": ""
15
+ },
16
+ "releaseEligible": false,
6
17
  "finalCommit": "<commit-hash>",
7
18
  "finalCommitBranch": "<origin/branch>",
8
19
  "baseCommit": "<base-commit-hash>",
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-codebase-map — 代码库地图
25
25
 
26
26
  ## Purpose
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-knowledge-ingest
25
25
 
26
26
  从 `.harness/archive/**/reports/final/summary-data.json` 抽取项目知识,生成并维护本地 `.harness/knowledge/` 索引。
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-knowledge-query
25
25
 
26
26
  并行 change 中查询必须传 `--change <change-id>`;成功后以该 change 的 `meta/knowledge-context.json` 为稳定指针。全局 `context-packs/latest.json` 仅向后兼容,不得用于判断多个 active change 的上下文归属。
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-plan — 需求规划
25
25
 
26
26
  ## Purpose
@@ -109,6 +109,7 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
109
109
  | 歧义优先检查 | 否定、对比、动作对象或范围存在多种合理解释时,最小取证后先给推荐理解并一次一问;确认前不深挖错误方向 |
110
110
  | 简单修复探索预算 | 预计不超过 2 个代码文件、且不涉及认证/安全/迁移/并发/API 契约重设时,最多 1 次合并 CodeGraph 查询 + 1 次定向补查、1 个用户澄清问题;无关发现只记非阻断说明 |
111
111
  | 精简产物 | 简单修复只保留实现所需的设计、任务、边界和测试;禁止在 spec/plan/detail/scenarios 中重复同一背景和结论 |
112
+ | 测试执行成本 | 场景表必须设计快速反馈层级、预计时长、资源预算、超时和可复用证据;默认先跑受影响测试,再跑模块门禁,候选验证只复用身份一致的全量证据 |
112
113
  | state snapshot | 读取 `state-snapshot.json`(`harness_state.py` / state-layout-protocol §state-snapshot.json)了解 project/worktree root、HEAD/base、profile/rules/map/knowledge 指纹;失效由脚本刷新,**不得仅凭缓存跳过代码探索或验证门禁**(design §3.6) |
113
114
  | 协议 | sensitive-info / evidence-based-reporting / state-layout |
114
115
 
@@ -198,6 +198,7 @@ source: harness-plan
198
198
  □ 已生成基础任务列表,并用 artifact 事件 note 记录任务拆分摘要
199
199
  □ 已叠加项目层序依赖(数据/契约→业务层→接口层)
200
200
  □ 已生成 4 维度场景表(单元/接口/数据兼容/集成)
201
+ □ 每个自动化场景均标注执行层级、预计时长、资源预算、超时、可复用证据;快速反馈不默认扫描全仓库
201
202
  □ 已确定变更名(kebab-case)
202
203
  □ 产物已写入 .harness/changes/<change-name>/plans/:
203
204
  - <change-name>-plan.md(简洁任务表)
@@ -228,34 +228,36 @@ status: approved
228
228
 
229
229
  #### 1.1 <类名.方法名>
230
230
 
231
- | # | 分类 | 场景描述 | 输入 | 预期 |
232
- |:--:|:----:|----------|------|------|
233
- | UT-001 | 正常 | ... | ... | ... |
234
- | UT-002 | 异常 | ... | ... | 抛 xxxException |
235
- | UT-003 | 边界 | ... | ... | ... |
231
+ | # | 分类 | 场景描述 | 输入 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
232
+ |:--:|:----:|----------|------|------|----------|----------|----------|------|------------|
233
+ | UT-001 | 正常 | ... | ... | ... | affected | ≤10s | 1 worker / ≤512MB | 30s | inputsHash + command |
234
+ | UT-002 | 异常 | ... | ... | 抛 xxxException | affected | ≤10s | 1 worker / ≤512MB | 30s | inputsHash + command |
235
+ | UT-003 | 边界 | ... | ... | ... | module | ≤60s | ≤50% CPU / ≤1GB | 120s | ledger identity |
236
236
 
237
237
  ### 二、接口测试场景
238
238
 
239
239
  #### 2.1 POST /xxx
240
240
 
241
- | # | 分类 | 场景描述 | 关键字段 | HTTP | code | message |
242
- |:--:|:----:|----------|----------|:----:|:----:|--------|
243
- | API-001 | 正常 | ... | ... | 200 | 0 | 成功 |
244
- | API-002 | 校验 | ... | ... | 200 | xxx | ... |
241
+ | # | 分类 | 场景描述 | 关键字段 | HTTP | code | message | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
242
+ |:--:|:----:|----------|----------|:----:|:----:|--------|----------|----------|----------|------|------------|
243
+ | API-001 | 正常 | ... | ... | 200 | 0 | 成功 | module | ≤60s | 1 service / ≤1GB | 120s | environmentHash + ledger |
244
+ | API-002 | 校验 | ... | ... | 200 | xxx | ... | affected | ≤20s | 1 service / ≤1GB | 60s | environmentHash + ledger |
245
245
 
246
246
  ### 三、数据兼容场景
247
247
 
248
- | # | 分类 | 场景描述 | 操作 | 数据特征 | 预期 |
249
- |:--:|:----:|----------|:----:|----------|------|
250
- | COM-001 | 旧数据 | ... | ... | ... | ... |
248
+ | # | 分类 | 场景描述 | 操作 | 数据特征 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
249
+ |:--:|:----:|----------|:----:|----------|------|----------|----------|----------|------|------------|
250
+ | COM-001 | 旧数据 | ... | ... | ... | ... | module | ≤60s | isolated DB / ≤1GB | 120s | dbSchemaHash + ledger |
251
251
 
252
252
  ### 四、集成场景
253
253
 
254
- | # | 分类 | 场景描述 | 前置条件 | 步骤 | 预期 |
255
- |:--:|:----:|----------|----------|------|------|
256
- | INT-001 | 端到端 | ... | ... | N 步操作 | ... |
254
+ | # | 分类 | 场景描述 | 前置条件 | 步骤 | 预期 | 执行层级 | 预计时长 | 资源预算 | 超时 | 可复用证据 |
255
+ |:--:|:----:|----------|----------|------|------|----------|----------|----------|------|------------|
256
+ | INT-001 | 端到端 | ... | ... | N 步操作 | ... | candidate | ≤10m | ≤50% CPU / ≤2GB | 15m | verification identity |
257
257
  ```
258
258
 
259
+ 执行层级固定为 `affected`(快速反馈)、`module`(变更模块门禁)、`candidate`(产品候选)。禁止所有场景默认跑全仓库;无法给出预算或超时时必须说明原因,并拆分或隔离高成本场景。只有 command、inputs/toolchain/environment 身份一致的成功 ledger 证据可以复用。
260
+
259
261
  ## 产物保存规则(跨阶段:阶段0.5/4/6/8)
260
262
 
261
263
  1. **自动确定变更名**:基于需求描述自动生成变更名(kebab-case),无需用户确认
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(curl *)
22
22
  - Bash(codegraph *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-review — 代码审查
26
26
 
27
27
  ## Purpose
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(curl *)
22
22
  - Bash(codegraph *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-run — 需求编码
26
26
 
27
27
  ## Purpose
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-submit — 最终提交(含 worktree 合并)
25
25
 
26
26
  ## Purpose
@@ -77,6 +77,8 @@ worktree 合并前必须运行 `harness_change.py integration-lock acquire --run
77
77
  0. **启动准备** — `harness_change.py resolve` 确定变更名;**`harness_gate.py begin --phase submit --change <id>`**;读 ledger,以 `harness_ledger.py diff-hash --repo . --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json` 计算 diffHash + post-test 7 类分类(禁止手写 ledger / 手工 phase.end)
78
78
  1. **合并最新代码** — 主目录与 worktree 均**不在业务工作区 stash/pull**;远端同步由合并段 integration transaction 在隔离 integration worktree 内完成(见「worktree 合并流程」);**正常路径禁止 `git stash` / `stash pop`**
79
79
  2. **最终验证** — ledger 复用优先;**提交前最终门禁只调 `can-reuse`**(删除与 coverage 冲突的二次全量门禁):`harness_ledger.py can-reuse --verification unitTestFull --scope module --project . --profile-input unitTestFull --command <resolved commands.unitTestFull.command>`。`--command` **按 profile key resolve**:读 `build-profile.json` 的 `commands.unitTestFull.command`(v2),或 `harness_profile.py resolve --project . --key unitTestFull --json` 取 resolved command,**不复制示例模块名**(文档示例只展示 key)。`--profile-input unitTestFull` 从 `verificationInputs.unitTestFull`(v2 由 `commands.unitTestFull.inputs` 派生)展开依赖闭包,**禁止用仅含 staged 文件的 `--files` 快捷方式**冒充全量闭包。`reuse=true` → 不再执行二次全量测试;仅 `reuse=false` 时执行**同一 resolved verification**(profile `unitTestFull` 命令),成功后用同一文件集、command、`scope=module` 经 **`harness_ledger.py record`** 写回 ledger `unitTestFull` 项。增量 `unitTest` 永远不能冒充 `unitTestFull` 门禁。
80
+ - 无远端 CI 且 gate-policy 未强制 remote provider 时,验证通过/复用后运行 `harness_archive.py certify-local --change-dir ... --project . --json`,从同一 ledger 生成 `local-reproducible` 产品候选收据;该命令不执行测试。
81
+ - gate-policy 要求 `remote-attested` 时不得降级成本地收据,等待远端 attestation。
80
82
  3. **.gitignore + 精确暂存** ⚠️ — 检查 `.harness/` 在 `.gitignore`;**禁止 `git add -A`**。若存在 `evidence/test-tracking.json`,先执行 `python <skills-root>/scripts/harness_test_guard.py stage --project . --change-dir ".harness/changes/<change-name>" --json`;失败即硬停止。无 manifest 时不使用 `-f`。manifest 之外的文件按精确业务路径正常暂存,**禁止全局 force-add**。
81
83
  4. **提交方式** — 主目录:blocking user confirmation 三选项(commit+push / 仅本地 / 取消);**worktree:固定仅本地 commit**
82
84
  5. **commit-message.txt** ⚠️ — 展示 staged、diff stat、完整中文 message;用户确认
@@ -15,6 +15,12 @@ description: harness-submit 的8 步工作流详细步骤和执行日志记录
15
15
  - blocking user confirmation 参数错误时不得自行绕过,必须改用固定模板重问。
16
16
  - staged diff 是唯一提交依据。
17
17
 
18
+ ### Wave-A 发布身份与环境边界
19
+
20
+ - [ ] 产品候选身份与归档治理身份分离:`productCommit`/`productTreeHash` 绑产品验证;`archiveCommit` 可晚于产品
21
+ - [ ] 进入 candidate CI / archive 前确认 product candidate CI 证据可被 `harness_archive status` 读取为 green
22
+ - [ ] 需要可写 DB/栈时走 `harness_environment` lease;禁止跨 change 默认可写共享
23
+
18
24
 
19
25
  ## 步骤 0:启动准备
20
26
 
@@ -364,7 +370,7 @@ python harness/scripts/harness_integration.py verify --change <change-name> --ru
364
370
  **写 check-ok marker**(npm run check exit 0 后强制):
365
371
 
366
372
  ```powershell
367
- powershell.exe -Command "python harness/scripts/harness_check_gate.py --write"
373
+ node scripts/check-gate.mjs --write
368
374
  ```
369
375
 
370
376
  ### 步骤 M5:push
@@ -19,7 +19,7 @@ disallowed-tools:
19
19
  - Bash(awk *)
20
20
  - Bash(curl *)
21
21
  ---
22
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
22
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
23
23
  # harness-sync — 元数据同步
24
24
 
25
25
  ## Purpose
@@ -22,7 +22,7 @@ disallowed-tools:
22
22
  - Bash(node *)
23
23
  - Bash(codegraph *)
24
24
  ---
25
- <!-- generated by harness_deploy.py; core=7996938abca24d16; overlay=none; agent=claude-code; do not edit -->
25
+ <!-- generated by harness_deploy.py; core=15e7aa9003de59d7; overlay=none; agent=claude-code; do not edit -->
26
26
  # harness-test — 测试执行
27
27
 
28
28
  ## Purpose
@@ -6,6 +6,12 @@ description: harness-test 的 Phase 0 环境准备 + Playwright 探测 + 关门
6
6
 
7
7
  以下检查项确认完了再开始测试。每一项背后都有踩坑经历。
8
8
 
9
+ ### Wave-A 环境合同(IA-3)
10
+
11
+ - [ ] 需要可写 DB/栈时:先 `harness_environment.py fingerprint` → `acquire` lease → 再跑测试 → `release`
12
+ - [ ] 无 lease 不得占用可写栈(`ENVIRONMENT_LEASE_REQUIRED`);跨 change 默认可写共享拒绝(`ENVIRONMENT_LEASE_CROSS_CHANGE`)
13
+ - [ ] 租约目录:主仓 `.harness/runtime/env-leases/`(与 change 状态目录分离)
14
+
9
15
  #### 0.0 加载项目配置(如存在)与确定变更名
10
16
 
11
17
  先检查当前项目的测试配置文件(按优先级查找):