@hunter-harness/workflow-harness 0.4.2 → 0.4.8

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 (242) 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 +4 -3
  3. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
  4. package/harness/bundles/general/claude-code/harness-execute/SKILL.md +4 -2
  5. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  6. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  7. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +2 -2
  8. package/harness/bundles/general/claude-code/harness-plan/reference.md +30 -3
  9. package/harness/bundles/general/claude-code/harness-pull/SKILL.md +1 -1
  10. package/harness/bundles/general/claude-code/harness-push/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-review/SKILL.md +3 -3
  12. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +2 -2
  14. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +2 -2
  15. package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
  16. package/harness/bundles/general/claude-code/scripts/harness_archive.py +28 -1
  17. package/harness/bundles/general/claude-code/scripts/harness_change.py +74 -0
  18. package/harness/bundles/general/claude-code/scripts/harness_context.py +271 -10
  19. package/harness/bundles/general/claude-code/scripts/harness_events.py +4 -1
  20. package/harness/bundles/general/claude-code/scripts/harness_gate.py +280 -76
  21. package/harness/bundles/general/claude-code/scripts/harness_review.py +120 -0
  22. package/harness/bundles/general/claude-code/scripts/harness_runtime.py +14 -0
  23. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  24. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +4 -3
  25. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  26. package/harness/bundles/general/codebuddy/harness-execute/SKILL.md +4 -2
  27. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  28. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  29. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +2 -2
  30. package/harness/bundles/general/codebuddy/harness-plan/reference.md +30 -3
  31. package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +1 -1
  32. package/harness/bundles/general/codebuddy/harness-push/SKILL.md +1 -1
  33. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +3 -3
  34. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  35. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +2 -2
  36. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +2 -2
  37. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
  38. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +28 -1
  39. package/harness/bundles/general/codebuddy/scripts/harness_change.py +74 -0
  40. package/harness/bundles/general/codebuddy/scripts/harness_context.py +271 -10
  41. package/harness/bundles/general/codebuddy/scripts/harness_events.py +4 -1
  42. package/harness/bundles/general/codebuddy/scripts/harness_gate.py +280 -76
  43. package/harness/bundles/general/codebuddy/scripts/harness_review.py +120 -0
  44. package/harness/bundles/general/codebuddy/scripts/harness_runtime.py +14 -0
  45. package/harness/bundles/general/codex/.harness-build.json +1 -1
  46. package/harness/bundles/general/codex/harness-archive/SKILL.md +4 -3
  47. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  48. package/harness/bundles/general/codex/harness-execute/SKILL.md +4 -2
  49. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  50. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  51. package/harness/bundles/general/codex/harness-plan/SKILL.md +2 -2
  52. package/harness/bundles/general/codex/harness-plan/reference.md +30 -3
  53. package/harness/bundles/general/codex/harness-pull/SKILL.md +1 -1
  54. package/harness/bundles/general/codex/harness-push/SKILL.md +1 -1
  55. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  56. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  57. package/harness/bundles/general/codex/harness-submit/SKILL.md +2 -2
  58. package/harness/bundles/general/codex/harness-sync/SKILL.md +2 -2
  59. package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
  60. package/harness/bundles/general/codex/scripts/harness_archive.py +28 -1
  61. package/harness/bundles/general/codex/scripts/harness_change.py +74 -0
  62. package/harness/bundles/general/codex/scripts/harness_context.py +271 -10
  63. package/harness/bundles/general/codex/scripts/harness_events.py +4 -1
  64. package/harness/bundles/general/codex/scripts/harness_gate.py +280 -76
  65. package/harness/bundles/general/codex/scripts/harness_review.py +120 -0
  66. package/harness/bundles/general/codex/scripts/harness_runtime.py +14 -0
  67. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  68. package/harness/bundles/general/cursor/harness-archive/SKILL.md +4 -3
  69. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  70. package/harness/bundles/general/cursor/harness-execute/SKILL.md +4 -2
  71. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  72. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  73. package/harness/bundles/general/cursor/harness-plan/SKILL.md +2 -2
  74. package/harness/bundles/general/cursor/harness-plan/reference.md +30 -3
  75. package/harness/bundles/general/cursor/harness-pull/SKILL.md +1 -1
  76. package/harness/bundles/general/cursor/harness-push/SKILL.md +1 -1
  77. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  78. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  79. package/harness/bundles/general/cursor/harness-submit/SKILL.md +2 -2
  80. package/harness/bundles/general/cursor/harness-sync/SKILL.md +2 -2
  81. package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
  82. package/harness/bundles/general/cursor/scripts/harness_archive.py +28 -1
  83. package/harness/bundles/general/cursor/scripts/harness_change.py +74 -0
  84. package/harness/bundles/general/cursor/scripts/harness_context.py +271 -10
  85. package/harness/bundles/general/cursor/scripts/harness_events.py +4 -1
  86. package/harness/bundles/general/cursor/scripts/harness_gate.py +280 -76
  87. package/harness/bundles/general/cursor/scripts/harness_review.py +120 -0
  88. package/harness/bundles/general/cursor/scripts/harness_runtime.py +14 -0
  89. package/harness/bundles/general/pi/.harness-build.json +1 -1
  90. package/harness/bundles/general/pi/harness-archive/SKILL.md +4 -3
  91. package/harness/bundles/general/pi/harness-codebase-map/SKILL.md +1 -1
  92. package/harness/bundles/general/pi/harness-execute/SKILL.md +4 -2
  93. package/harness/bundles/general/pi/harness-knowledge-ingest/SKILL.md +1 -1
  94. package/harness/bundles/general/pi/harness-knowledge-query/SKILL.md +1 -1
  95. package/harness/bundles/general/pi/harness-plan/SKILL.md +2 -2
  96. package/harness/bundles/general/pi/harness-plan/reference.md +30 -3
  97. package/harness/bundles/general/pi/harness-pull/SKILL.md +1 -1
  98. package/harness/bundles/general/pi/harness-push/SKILL.md +1 -1
  99. package/harness/bundles/general/pi/harness-review/SKILL.md +1 -1
  100. package/harness/bundles/general/pi/harness-run/SKILL.md +1 -1
  101. package/harness/bundles/general/pi/harness-submit/SKILL.md +2 -2
  102. package/harness/bundles/general/pi/harness-sync/SKILL.md +2 -2
  103. package/harness/bundles/general/pi/harness-test/SKILL.md +1 -1
  104. package/harness/bundles/general/pi/scripts/harness_archive.py +28 -1
  105. package/harness/bundles/general/pi/scripts/harness_change.py +74 -0
  106. package/harness/bundles/general/pi/scripts/harness_context.py +271 -10
  107. package/harness/bundles/general/pi/scripts/harness_events.py +4 -1
  108. package/harness/bundles/general/pi/scripts/harness_gate.py +280 -76
  109. package/harness/bundles/general/pi/scripts/harness_review.py +120 -0
  110. package/harness/bundles/general/pi/scripts/harness_runtime.py +14 -0
  111. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  112. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  113. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +4 -3
  114. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  115. package/harness/bundles/java/claude-code/harness-execute/SKILL.md +4 -2
  116. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  117. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  118. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  119. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +2 -2
  120. package/harness/bundles/java/claude-code/harness-plan/reference.md +30 -3
  121. package/harness/bundles/java/claude-code/harness-pull/SKILL.md +1 -1
  122. package/harness/bundles/java/claude-code/harness-push/SKILL.md +1 -1
  123. package/harness/bundles/java/claude-code/harness-review/SKILL.md +3 -3
  124. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  125. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +2 -2
  126. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +2 -2
  127. package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
  128. package/harness/bundles/java/claude-code/scripts/harness_archive.py +28 -1
  129. package/harness/bundles/java/claude-code/scripts/harness_change.py +74 -0
  130. package/harness/bundles/java/claude-code/scripts/harness_context.py +271 -10
  131. package/harness/bundles/java/claude-code/scripts/harness_events.py +4 -1
  132. package/harness/bundles/java/claude-code/scripts/harness_gate.py +280 -76
  133. package/harness/bundles/java/claude-code/scripts/harness_review.py +120 -0
  134. package/harness/bundles/java/claude-code/scripts/harness_runtime.py +14 -0
  135. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  136. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  137. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +4 -3
  138. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  139. package/harness/bundles/java/codebuddy/harness-execute/SKILL.md +4 -2
  140. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  141. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  142. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  143. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +2 -2
  144. package/harness/bundles/java/codebuddy/harness-plan/reference.md +30 -3
  145. package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +1 -1
  146. package/harness/bundles/java/codebuddy/harness-push/SKILL.md +1 -1
  147. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +3 -3
  148. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  149. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +2 -2
  150. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +2 -2
  151. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
  152. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +28 -1
  153. package/harness/bundles/java/codebuddy/scripts/harness_change.py +74 -0
  154. package/harness/bundles/java/codebuddy/scripts/harness_context.py +271 -10
  155. package/harness/bundles/java/codebuddy/scripts/harness_events.py +4 -1
  156. package/harness/bundles/java/codebuddy/scripts/harness_gate.py +280 -76
  157. package/harness/bundles/java/codebuddy/scripts/harness_review.py +120 -0
  158. package/harness/bundles/java/codebuddy/scripts/harness_runtime.py +14 -0
  159. package/harness/bundles/java/codex/.harness-build.json +1 -1
  160. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  161. package/harness/bundles/java/codex/harness-archive/SKILL.md +4 -3
  162. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  163. package/harness/bundles/java/codex/harness-execute/SKILL.md +4 -2
  164. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  165. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  166. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  167. package/harness/bundles/java/codex/harness-plan/SKILL.md +2 -2
  168. package/harness/bundles/java/codex/harness-plan/reference.md +30 -3
  169. package/harness/bundles/java/codex/harness-pull/SKILL.md +1 -1
  170. package/harness/bundles/java/codex/harness-push/SKILL.md +1 -1
  171. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  172. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  173. package/harness/bundles/java/codex/harness-submit/SKILL.md +2 -2
  174. package/harness/bundles/java/codex/harness-sync/SKILL.md +2 -2
  175. package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
  176. package/harness/bundles/java/codex/scripts/harness_archive.py +28 -1
  177. package/harness/bundles/java/codex/scripts/harness_change.py +74 -0
  178. package/harness/bundles/java/codex/scripts/harness_context.py +271 -10
  179. package/harness/bundles/java/codex/scripts/harness_events.py +4 -1
  180. package/harness/bundles/java/codex/scripts/harness_gate.py +280 -76
  181. package/harness/bundles/java/codex/scripts/harness_review.py +120 -0
  182. package/harness/bundles/java/codex/scripts/harness_runtime.py +14 -0
  183. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  184. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  185. package/harness/bundles/java/cursor/harness-archive/SKILL.md +4 -3
  186. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  187. package/harness/bundles/java/cursor/harness-execute/SKILL.md +4 -2
  188. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  189. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  190. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  191. package/harness/bundles/java/cursor/harness-plan/SKILL.md +2 -2
  192. package/harness/bundles/java/cursor/harness-plan/reference.md +30 -3
  193. package/harness/bundles/java/cursor/harness-pull/SKILL.md +1 -1
  194. package/harness/bundles/java/cursor/harness-push/SKILL.md +1 -1
  195. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  196. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  197. package/harness/bundles/java/cursor/harness-submit/SKILL.md +2 -2
  198. package/harness/bundles/java/cursor/harness-sync/SKILL.md +2 -2
  199. package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
  200. package/harness/bundles/java/cursor/scripts/harness_archive.py +28 -1
  201. package/harness/bundles/java/cursor/scripts/harness_change.py +74 -0
  202. package/harness/bundles/java/cursor/scripts/harness_context.py +271 -10
  203. package/harness/bundles/java/cursor/scripts/harness_events.py +4 -1
  204. package/harness/bundles/java/cursor/scripts/harness_gate.py +280 -76
  205. package/harness/bundles/java/cursor/scripts/harness_review.py +120 -0
  206. package/harness/bundles/java/cursor/scripts/harness_runtime.py +14 -0
  207. package/harness/bundles/java/pi/.harness-build.json +1 -1
  208. package/harness/bundles/java/pi/harness-apidoc/SKILL.md +1 -1
  209. package/harness/bundles/java/pi/harness-archive/SKILL.md +4 -3
  210. package/harness/bundles/java/pi/harness-codebase-map/SKILL.md +1 -1
  211. package/harness/bundles/java/pi/harness-execute/SKILL.md +4 -2
  212. package/harness/bundles/java/pi/harness-knowledge-ingest/SKILL.md +1 -1
  213. package/harness/bundles/java/pi/harness-knowledge-query/SKILL.md +1 -1
  214. package/harness/bundles/java/pi/harness-package/SKILL.md +1 -1
  215. package/harness/bundles/java/pi/harness-plan/SKILL.md +2 -2
  216. package/harness/bundles/java/pi/harness-plan/reference.md +30 -3
  217. package/harness/bundles/java/pi/harness-pull/SKILL.md +1 -1
  218. package/harness/bundles/java/pi/harness-push/SKILL.md +1 -1
  219. package/harness/bundles/java/pi/harness-review/SKILL.md +1 -1
  220. package/harness/bundles/java/pi/harness-run/SKILL.md +1 -1
  221. package/harness/bundles/java/pi/harness-submit/SKILL.md +2 -2
  222. package/harness/bundles/java/pi/harness-sync/SKILL.md +2 -2
  223. package/harness/bundles/java/pi/harness-test/SKILL.md +1 -1
  224. package/harness/bundles/java/pi/scripts/harness_archive.py +28 -1
  225. package/harness/bundles/java/pi/scripts/harness_change.py +74 -0
  226. package/harness/bundles/java/pi/scripts/harness_context.py +271 -10
  227. package/harness/bundles/java/pi/scripts/harness_events.py +4 -1
  228. package/harness/bundles/java/pi/scripts/harness_gate.py +280 -76
  229. package/harness/bundles/java/pi/scripts/harness_review.py +120 -0
  230. package/harness/bundles/java/pi/scripts/harness_runtime.py +14 -0
  231. package/harness/manifests/general/claude-code.json +22 -22
  232. package/harness/manifests/general/codebuddy.json +22 -22
  233. package/harness/manifests/general/codex.json +22 -22
  234. package/harness/manifests/general/cursor.json +22 -22
  235. package/harness/manifests/general/pi.json +22 -22
  236. package/harness/manifests/java/claude-code.json +24 -24
  237. package/harness/manifests/java/codebuddy.json +24 -24
  238. package/harness/manifests/java/codex.json +24 -24
  239. package/harness/manifests/java/cursor.json +24 -24
  240. package/harness/manifests/java/pi.json +24 -24
  241. package/hunter-workflow-family.json +2 -2
  242. package/package.json +15 -15
@@ -2,5 +2,5 @@
2
2
  "schemaVersion": 1,
3
3
  "overlay": "none",
4
4
  "agent": "claude-code",
5
- "coreHash": "ec59ac2389d9dce9"
5
+ "coreHash": "3c6eec08da6f5a5c"
6
6
  }
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(awk *)
22
22
  - Bash(curl *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-archive — 变更归档
26
26
 
27
27
  ## Purpose
@@ -144,11 +144,12 @@ disallowed-tools:
144
144
 
145
145
  `execute` 内部运行自动门禁。实际计划最后阶段已终态、边界快照存在且 `status.archivable=true` 时直接执行;未满足时返回阻断且不移动原目录。用户取消后不得重跑。
146
146
 
147
- ### 二·A、两个常见阻断的正规出路(不要自己拼 python -c)
147
+ ### 二·A、常见阻断的正规出路(不要自己拼 python -c)
148
148
 
149
149
  | 阻断 | 出路 |
150
150
  |------|------|
151
- | `SENSITIVE_EVIDENCE_UNQUARANTINED`(默认只告警,`HUNTER_HARNESS_SENSITIVE_SCAN=block` 时才阻断) | `python <skills-root>/scripts/harness_runtime.py quarantine-evidence --project . --change-dir ".harness/changes/<cn>" --file "<相对 change-dir 的路径>" --reason "<为什么是敏感证据>" --json`(`--file` 可重复)。私有根默认已与项目同盘、且在项目根之外——**不要**手工指定项目内的路径,归档的密钥扫描会以 `SECRET_SCAN_PRIVATE_PATH_IN_COPY_ROOT` 拒绝 |
151
+ | `PROJECT_RELEASE_POLICY_BLOCKED` / `LOCAL_RELEASE_NOT_AUTHORIZED`(本地可复现证据未获发布授权) | `python <skills-root>/scripts/harness_change.py allow-local-release --change <cn> --json`(在 `meta/gate-policy.json` 写入 `candidateVerification.allowLocalRelease=true`,幂等,保留既有策略内容)。**不要**手改 `gate-policy.json` |
152
+ | `SENSITIVE_EVIDENCE_UNQUARANTINED`(默认只告警,`HUNTER_HARNESS_SENSITIVE_SCAN=block` 时才阻断) | 报错的 `nextAction` 自带含全部 `--file` 的完整命令;等价于 `python <skills-root>/scripts/harness_runtime.py quarantine-evidence --project . --change-dir ".harness/changes/<cn>" --file "<相对 change-dir 的路径>" --reason "<为什么是敏感证据>" --json`(`--file` 可重复)。私有根默认已与项目同盘、且在项目根之外——**不要**手工指定项目内的路径,归档的密钥扫描会以 `SECRET_SCAN_PRIVATE_PATH_IN_COPY_ROOT` 拒绝。harness 自生成发布日志里的 `recovery_token` 是系统字段,0.4.7(workflow-harness)起扫描器已豁免,无需隔离 |
152
153
  | `DIFF_ZERO_WITH_NONEMPTY_COMMIT`(提交范围非空但 filesChanged=0) | 契约缺 `ownership.productPaths`,全部改动被判为 `foreignPaths`。用 `python <skills-root>/scripts/harness_change.py declare-ownership --change <cn> --product-path "<目录前缀或精确文件>" --json` 按计划的实际改动范围声明(可重复;只收精确路径,不支持通配)。**不要**手改 `change-context.json` |
153
154
 
154
155
  ### 二·A·1、发布内容预检与服务端 422
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-codebase-map — 代码库地图
25
25
 
26
26
  ## Purpose
@@ -23,7 +23,7 @@ disallowed-tools:
23
23
  - Bash(node *)
24
24
  - Bash(codegraph *)
25
25
  ---
26
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
26
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
27
27
  # harness-execute — 执行(编码 + 验证)
28
28
 
29
29
  > 2026-08 阶段合并:原 `run`(编码)与 `test`(验证)合并为单一 `execute` 阶段。
@@ -86,7 +86,7 @@ disallowed-tools:
86
86
  2. 构建验证 + **仅**通过 `harness_ledger.py record` 写 ledger(禁止 Write/Edit `verification-ledger.json`);profile 缺失或陈旧时先 `harness_preflight.py detect --project . --json`;`record --project . --profile-input <key>` 从同一 target 推导 scope、coverage、规范命令与输入闭包
87
87
  3. **验证执行**:单元测试可复用则跳过(`harness_ledger.py can-reuse`);接口测试**强制批量执行器**一次跑完全部场景;数据兼容验证按场景表执行 → `harness-test/reference.md`
88
88
  4. **场景覆盖检查**(场景表映射,禁止用用例数冒充场景数)
89
- 5. **关门检查**(10 项)→ 只执行一次 `harness_gate.py close`;`--to-phase` 必须取返回的 `nextPhases` `plannedPhases` execute 的真实后继(fixback 时为 execute 自身)。该命令内部关闭 test guard、写 `phase.end`、释放租约、写 handoff 并补传事件;不得再单独调用 test-guard/context close。失败时按结构化 `recoveryAction` 原样重试,已完成步骤幂等复用。
89
+ 5. **关门检查**(10 项)→ 只执行一次 `harness_gate.py close`;`--to-phase` 可省略——计划后继唯一(排除 fixback 自环)时自动派生并交接(输出含 `derivedToPhase`)。仅 fixback 回环时显式传 `--to-phase execute`。该命令内部关闭 test guard、写 `phase.end`、释放租约、写 handoff 并补传事件;不得再单独调用 test-guard/context close。失败时按结构化 `recoveryAction` 原样重试,已完成步骤幂等复用。
90
90
 
91
91
  **阶段归属规则**:只用 `ownerPhase=execute` 的任务和场景判定本阶段结果。`ownerPhase=review`/`submit` 的场景按计划留给后续阶段属于正常移交,出现在关门返回值的 `deferred` 里,不阻断 execute。合并前 `ownerPhase=run`/`test` 的旧清单经别名表归一为 execute,在 execute 关门时一并到期。
92
92
 
@@ -102,6 +102,8 @@ python <skills-root>/scripts/harness_test_runner.py exec --project . --timeout-s
102
102
 
103
103
  **长阶段租约**:`gate begin` 的租约默认 TTL 3600 秒,execute 阶段常常跑得更久。租约过期不会中断执行,**也不再阻断收尾**:`gate close` 发现租约过期而 run-id 仍是本阶段的,会自动用原 run-id 重取并照常关门,只在返回体的 `leaseLapsed` 里记录。不需要定期续租;报 `LEASE_ABSENT`/`LEASE_INVALID` 时先确认 begin 真的跑过,**不要**重跑 `gate begin`。
104
104
 
105
+ **关门重试是幂等续跑**(0.4.5 workflow 起):租约释放是 close 的最后一个可失败步骤,handoff/monitor/清草稿任一失败时租约仍持有,原样重跑同一命令即可(已完成步骤由 closeTransaction journal 幂等跳过)。万一处于「phase.end 已写 + 租约已放 + 交接未完成」的历史中间态,重跑 close 会自动识别并补跑剩余步骤(`PHASE_CLOSE_RESUMED`):未带 `--to-phase` 时从 plannedPhases 派生唯一后继,后继不唯一才报 `PHASE_HANDOFF_PENDING` 并列出候选。**都不需要手工 `harness_change.py claim`**——LEASE_ABSENT 只在 begin 从未跑过时才该出现。
106
+
105
107
  **接口测试执行器优先级**:接口测试执行器(默认首选)> PowerShell batch `.ps1` > Playwright MCP `browser_evaluate`(仅前两者不可用或用户明确选择)> curl + UTF-8 JSON body file(兜底)。执行器在 PowerShell 可用时**禁止**用 Playwright MCP 逐条执行。→ `harness-test/reference.md`「接口测试工具优先级」
106
108
 
107
109
  **陈旧测试安全修复**:只有当前生产代码、已批准计划或可验证历史能唯一确定新契约时,才允许仅修改测试并立即重跑,然后记录:
@@ -8,7 +8,7 @@ disallowed-tools:
8
8
  - Bash(git *)
9
9
  - Bash(curl *)
10
10
  ---
11
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
11
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
12
12
  # harness-knowledge-ingest
13
13
 
14
14
  知识 ingest 完全由 Hunter Platform 负责。归档完成时,客户端生成一个确定性 ZIP;
@@ -8,7 +8,7 @@ disallowed-tools:
8
8
  - Bash(git *)
9
9
  - Bash(curl *)
10
10
  ---
11
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
11
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
12
12
  # harness-knowledge-query
13
13
 
14
14
  项目知识以 Hunter Platform 的服务端索引为唯一真源。客户端只提交查询并消费结果:
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(awk *)
22
22
  - Bash(curl *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-plan — 需求规划
26
26
 
27
27
  ## Purpose
@@ -123,7 +123,7 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
123
123
  | 空目录 | 不得为“预留目录”生成 `.gitkeep`;只有产品明确需要跟踪空目录时才能创建,并在计划中说明业务原因 |
124
124
  | 设计审批包 | 一次 blocking user confirmation 含 worktree(读 `harness.json` `defaultWorktree`)。必须同时展示 **in_scope 与 out_of_scope 两个列表**——只展示"做什么"会让范围误判活到发布之后,代价是整份计划 republish |
125
125
  | 引用即追问 | 需求引用了外部设计文档章节(贴段落、指 `### Bn`、说"之前设计的时候如…")时,阶段 2 必须确认该章节是否纳入本次范围,落到 in_scope 或 out_of_scope;引用 ≠ 纳入,也 ≠ 排除 |
126
- | 阶段 8 | 唯一入口:`hunter-harness plan finalize`(证据包 → 八 target + journal committed + plan-events.ndjson)。失败不得手工补终态;历史 legacy 收据只读(`harness_plan_finalize.py verify`) |
126
+ | 阶段 8 | 唯一入口:`hunter-harness plan finalize`(证据包 → 八 target + journal committed + plan-events.ndjson)。assurance/高风险计划先跑 `plan review-record` 把对抗评审收据写回证据包(`PLAN_REVIEW_REQUIRED` 报错里的 `expected_review.input_hash` 是公开契约),不得手拼哈希。失败不得手工补终态;历史 legacy 收据只读(`harness_plan_finalize.py verify`) |
127
127
  | 发布路径 | **只有 v2**(`plan evidence-pack` → `plan finalize`);legacy staging/finalize/republish 已于 0.3.0 移除,历史 legacy 收据保持可读(`harness_plan_finalize.py verify`)。v2 的场景契约已补齐 `priority`/`owner_phase` 与可执行测试三元,派生的 `meta/scenario-manifest.json` 能被 execute 门禁与 `harness_ledger.py record` 解包消费,证据闭环走得通。P0/P1 场景必须给全可执行三元(要么整组给全、要么整组省略;省略则 manifest 降为 schemaVersion 1,关门绑不上结构化执行收据) |
128
128
  | 发布后改产物 | 改 `meta/plan-evidence-input.json` 后重跑 `plan evidence-pack`(`context.attempt` 递增、`expected_baseline` 置 present 并带上次 manifest 哈希/generation),再 `plan finalize`——新 attempt + 重新派生 manifest 一次完成。**绝不手改 `meta/scenario-manifest.json`**(派生物,手改必致 `ARTIFACT_HASH_DRIFT`)→ `reference.md`「发布后修订计划」 |
129
129
  | v2 输入骨架 | 不要猜 `plan-evidence-input.json` 结构:`npx hunter-harness plan evidence-pack --print-template` 给出**一个字不改就能通过 evidence-pack** 的骨架(结构合法;`change_key`/`run_id` 仍须换成真实身份才能 finalize),逐项替换即可。结构不符时命令返回 `PLAN_EVIDENCE_INPUT_INVALID`,带 `field_path` 与 `problems[]`(缺失/多余键、枚举取值)——按 problems 改完重跑;**不得**为找契约去反编译 `dist/bin.js` 或翻 npx 缓存。带不了 `<>` 的占位字段与硬约束清单 → `reference.md` 阶段 8 v2 路径 |
@@ -360,10 +360,34 @@ status: approved
360
360
  # 1) 规划自然产出 → 证据包(结构化身份/哈希全由冻结模块推导)
361
361
  npx hunter-harness plan evidence-pack --input .harness/changes/<cn>/meta/plan-evidence-input.json \
362
362
  --output .harness/changes/<cn>/meta/plan-evidence.json
363
- # 2) 证据包 质量门 + 原子发布 + 事件 outbox
363
+ # 2) assurance / 高风险计划:记录对抗评审收据(0.4.8+;非 assurance 可跳过)
364
+ npx hunter-harness plan review-record --input .harness/changes/<cn>/meta/plan-evidence.json \
365
+ --receipt .harness/changes/<cn>/meta/plan-review-draft.json
366
+ # 3) 证据包 → 质量门 + 原子发布 + 事件 outbox
364
367
  npx hunter-harness plan finalize --input .harness/changes/<cn>/meta/plan-evidence.json
365
368
  ```
366
369
 
370
+ **对抗评审收据(assurance 必做,0.4.8 起有正式链路)**:profile.mode 被推到 `assurance`
371
+ (auth/concurrency/migration 等风险信号自动推断)或任一场景 `risk_level: "high"` 时,
372
+ finalize 硬性要求证据包顶层 `adversarial_review` 收据,缺失即 `PLAN_REVIEW_REQUIRED` fail closed。
373
+ 收据的 `input_hash` 绑定产物 + 语义投影 + capabilities + 高风险发现 + 透镜(全在 CLI 内部管线,
374
+ 外部不可预计算),所以**不要手拼收据**:
375
+
376
+ 1. 先完成阶段 7.5 对抗评审,把结论写成草稿 `meta/plan-review-draft.json`:
377
+ `{ "reviewer_identity": "inline:<标识>", "findings": [] }`
378
+ (`review_mode` 缺省 `inline`;`completed_at` 缺省取当前时间;`findings` 为空数组表示无发现)
379
+ 2. 跑 `plan review-record`:CLI 内部重跑 layer1/layer2/layer3 算出权威 `input_hash`,
380
+ 代算 `findings_hash`,把完整收据写回证据包顶层 `adversarial_review`(缺省覆盖 `--input`,
381
+ 可用 `--output` 写到别处)。stdout 的 `review_required: false` 表示该包未触发评审、收据不会被消费。
382
+ 3. 再跑 `plan finalize`。
383
+
384
+ 两条公开契约(不再需要从 dist 里翻):
385
+
386
+ - `PLAN_REVIEW_REQUIRED` 报错的 `expected_review.input_hash` 就是绑定期望值——校验器自曝期望,
387
+ 手工构造收据时用它;`findings_hash` 是你端 `findings` 数组 canonical JSON 的 sha256。
388
+ - 收据绑定**证据包内容**:`review-record` 写回后任何对 pack 的修改(包括重跑 evidence-pack)
389
+ 都使收据失效,必须重跑 `review-record`。墙钟时间不进 `input_hash`,不必担心时间戳漂移。
390
+
367
391
  **自然输入文件**(`meta/plan-evidence-input.json`,权威定义 `packages/cli/src/commands/plan-evidence-pack.ts` 的 `EvidencePackInputFile`)由规划阶段逐步沉淀,各字段定稿时点不得倒置。
368
392
 
369
393
  > 📋 **先取骨架,别猜结构**:CLI 自带模板输出,不需要去找 TS 接口或翻 npx 缓存——
@@ -388,10 +412,13 @@ npx hunter-harness plan finalize --input .harness/changes/<cn>/meta/plan-evidenc
388
412
  - `structured_input.scenarios` **至少 3 条**——八维度缺项由命令补 `not_applicable`,但场景总数不能少于 3
389
413
  - `intent.acceptance_examples` 2~5 条,`approval.content.acceptance_examples` 3~7 条 → 取 3 条同时满足
390
414
  - `key_alternatives` / `invariants` / `failure_behaviors` / `compatibility_boundaries` 各至少 1 条
391
- - `intent.in_scope`/`out_of_scope` 与 `approval.content` 同名字段必须**集合相等**
415
+ - `intent.in_scope`/`out_of_scope` 与 `approval.content` 同名字段必须**集合相等**;0.4.8 起 approval 侧可以**整项省略**(从 intent 继承,成功输出的 `warnings` 会标 `approval_scope_inherited`),写了就必须相等
416
+ - `intent.uncertainties` 非空时,每一项都会生成未决决策 `intent_uncertainty:<sha256(文本)>`,必须在 `decision_nodes` 提供**同 id** 的节点(通常是一条 `product_decision`,`status: "resolved"` + `resolution`/`resolved_by: "user"`/`resolved_at` 三元);不想走决策图就留空数组。缺节点时边界报错会直接列出期望的决策 id
417
+ - `tasks[].affected_paths` 必须是**文件形态**的相对路径:正斜杠分隔、不能以 `/` 结尾、不含 `.`/`..` 段、不接受盘符/绝对路径。目录路径会被拒——改为列出其中的具体文件
392
418
  - tasks 只写 `task_id/objective/affected_paths/owner_phase`,六个 refs 数组由命令接线;多写 `cluster`/`title` 这类键会因精确键集被拒
393
419
  - scenarios 只写 `scenario_id/title/acceptance/coverage_dimension/execution_level/evidence_requirements/risk_level`(+可选 `verification_command`);`priority`/`test_file` 这类计划表列不属于本输入
394
420
  - `machine.worktree_policy` ∈ `project_default | required | forbidden`(没有 `none`)
421
+ - `decision_nodes[]` 的 `type` ∈ `fact | engineering_default | product_decision | risk_decision`,`status` ∈ `pending | resolved | blocked | superseded`;`status: "resolved"` 必须带 `resolution`/`resolved_by`/`resolved_at` 三元,且 `resolved_by` 与类型推导的解决者一致(fact→evidence、engineering_default→engineering_default、产品/风险决策→user)
395
422
 
396
423
  > **结构错了怎么读报错**:命令在边界返回 `code:"PLAN_EVIDENCE_INPUT_INVALID"`(`stage:"boundary"`),
397
424
  > `field_path` 指向第一处问题,`problems[]` 逐条给 `missing_keys`/`unexpected_keys`/`message`。
@@ -428,7 +455,7 @@ npx hunter-harness plan finalize --input .harness/changes/<cn>/meta/plan-evidenc
428
455
  > 可执行三元是**可选**的,但要么整组给全、要么整组省略。ledger 场景全部带齐 → manifest 声明
429
456
  > `schemaVersion 2`,关门可绑结构化执行收据;否则降为 1。
430
457
 
431
- - **证据包**(`plan-evidence.json`)是命令推导的产物(trusted/publication/context/baseline),不得手改;任何字段变化必须改自然输入后重跑 evidence-pack
458
+ - **证据包**(`plan-evidence.json`)是命令推导的产物(trusted/publication/context/baseline),不得手改;任何字段变化必须改自然输入后重跑 evidence-pack。唯一的例外是 `adversarial_review` 顶层字段——它由 `plan review-record`(或手工构造的合规收据)写入,evidence-pack 构建时也会透传自然输入里已有的该字段。
432
459
  - **成功语义**:finalize exit 0 且 `code:"PLAN_FINALIZED"`。落盘事实 = 八 target(plans/*.md ×4 + meta/*.json ×4)+ `meta/publication-journals/<op>.json`(状态 committed)+ `meta/plan-events.ndjson`(artifact_published/phase_ended)。确定性门失败 exit 1 且 `code:"PLAN_FINALIZE_DETERMINISTIC_FAILED"` 附 findings——此时必须回到对应阶段修正规划内容,**不得**手改证据包或 staged 内容绕过。
433
460
  - **验证**:journal `state==="committed"` + 八 target 存在 + plan-events.ndjson 含两类终态事件;不得手工补写任何一项。
434
461
  - **legacy 收据**:v2 路径不写 `plan-finalization.json`;消费方若读历史 legacy receipt,`harness_plan_finalize.py verify` 保持可读。0.3.0 起 v2 无 legacy 回退——自然输入不完整先补齐(例如补真实审批记录),不得走已删除的 Python finalizer。
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(awk *)
22
22
  - Bash(curl *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-pull — 从 Hunter Platform 下拉与恢复
26
26
 
27
27
  ## Purpose
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(awk *)
22
22
  - Bash(curl *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-push — 上传到 Hunter Platform
26
26
 
27
27
  ## Purpose
@@ -22,7 +22,7 @@ disallowed-tools:
22
22
  - Bash(curl *)
23
23
  - Bash(codegraph *)
24
24
  ---
25
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
25
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
26
26
  # harness-review — 代码审查
27
27
 
28
28
  ## Purpose
@@ -77,8 +77,8 @@ review 默认优先在独立上下文执行,避免主会话已形成的实现
77
77
 
78
78
  项目规模小、风险低或没有 CodeGraph 都不是跳过独立评审的理由。原因码是稳定机器字段,仅用于协议与技术详情;面向用户的事件摘要必须写成「已使用独立评审」或「当前环境没有可用的隔离评审能力,已由主会话完成评审」等中文说明。
79
79
 
80
- 3. **持久化报告与事实 sidecar(强制,主会话)** — Agent 返回后主会话 Write 到 `reports/review/review-report-*.md`,并把同一批发现写成临时 JSON 后调用 `python <skills-root>/scripts/harness_review.py write-findings --change-dir <change-dir> --input <findings.json>`。每条发现必须填写 `fixbackAction=code|manual|workflow`:只有确实需要修改产品代码的项使用 `code`;人工验收用 `manual`;流程、暂存或工具使用建议用 `workflow`。权威计数来自 `reports/review/review-findings.json`,不是 Markdown。任一写入缺失 → 评审未完整结束,不得关门。
81
- 4. **生成修复反馈(原生协议)** — 若报告存在 RED/YELLOW 问题,执行 `protocols.md` 的 `review-fixback-protocol`,将问题转化为结构化 fixback 清单并落盘到 `.harness/changes/<change-name>/reports/review/fixback-YYYYMMDD-HHmm.md`;随后把 disposition 临时 JSON 交给 `python <skills-root>/scripts/harness_review.py write-dispositions --change-dir <change-dir> --input <dispositions.json>`,权威状态写入 `reports/review/fixback-dispositions.json`。若无 RED/YELLOW,也必须写空 findings sidecar,并记录 `review-fixback-protocol: skipped(no findings)`。不调用 Superpowers `receiving-code-review`,也不记录外部 skill 降级。
80
+ 3. **持久化报告与事实 sidecar(强制,主会话)** — Agent 返回后主会话 Write 到 `reports/review/review-report-*.md`,并调用 `python <skills-root>/scripts/harness_review.py scaffold --change-dir <change-dir> [--run-id <id>]` 生成 findings 写入骨架(runId 缺省从 events.ndjson 最新 review phase.start 推断),补齐每一条发现后经 `harness_review.py write-findings --change-dir <change-dir> --stdin` 落地。每条发现必须填写 `fixbackAction=code|manual|workflow`:只有确实需要修改产品代码的项使用 `code`;人工验收用 `manual`;流程、暂存或工具使用建议用 `workflow`。权威计数来自 `reports/review/review-findings.json`,不是 Markdown。任一写入缺失 → 评审未完整结束,不得关门。
81
+ 4. **生成修复反馈(原生协议)** — 若报告存在 RED/YELLOW 问题,执行 `protocols.md` 的 `review-fixback-protocol`,将问题转化为结构化 fixback 清单并落盘到 `.harness/changes/<change-name>/reports/review/fixback-YYYYMMDD-HHmm.md`;随后重跑 `harness_review.py scaffold --change-dir <change-dir>`(已有 findings 时输出每条的 OPEN 处置骨架,runId 自动与 findings 同轮),逐条改判后交给 `harness_review.py write-dispositions --change-dir <change-dir> --stdin` 落地,权威状态写入 `reports/review/fixback-dispositions.json`。若无 RED/YELLOW,也必须写空 findings sidecar,并记录 `review-fixback-protocol: skipped(no findings)`。不调用 Superpowers `receiving-code-review`,也不记录外部 skill 降级。
82
82
  5. **收尾** — 先写完 `review-findings.json` 与 `fixback-dispositions.json`,且两者 `runId` 必须等于本轮 Review;每个 finding 必须有 disposition。随后只调用一次 gate close,由门禁校验 sidecar、写 `phase.end` 与交接;缺失或不一致时保持 Review 未结束并按恢复提示补齐。控制台输出摘要。
83
83
 
84
84
  ## Review 定位(重要)
@@ -22,7 +22,7 @@ disallowed-tools:
22
22
  - Bash(curl *)
23
23
  - Bash(codegraph *)
24
24
  ---
25
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
25
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
26
26
  # harness-run — 需求编码
27
27
 
28
28
  > **2026-08 阶段合并**:原 `run`(编码)与 `test`(验证)合并为单一 `execute` 阶段,
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(awk *)
22
22
  - Bash(curl *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-submit — 最终提交(含 worktree 合并)
26
26
 
27
27
  ## Purpose
@@ -73,7 +73,7 @@ worktree 合并前必须运行 `harness_change.py integration-lock acquire --run
73
73
 
74
74
  ### 提交流程(步骤 0–7)
75
75
 
76
- 0. **启动准备** — `harness_context.py prepare --project . --change <id> --phase submit --executor <tool> --json`(`--project` 必填)确定唯一变更与 executionRoot;`harness_context.py begin --project . --change <id> --phase submit --executor <tool> --json` 校验 review→submit receipt;**`harness_gate.py begin --phase submit --change <id>`**;读 ledger,以 `harness_ledger.py diff-hash --repo <executionRoot> --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json` 计算 diffHash + post-test 7 类分类(`executionRoot` 必须直接取准备回执;禁止手写 ledger / 手工 phase.end
76
+ 0. **启动准备** — `harness_context.py prepare --project . --change <id> --phase submit --executor <tool> --json`(`--project` 必填)确定唯一变更与 executionRoot;`harness_context.py begin --project . --change <id> --phase submit --executor <tool> --json` 校验 review→submit receipt;**`harness_gate.py begin --phase submit --change <id>`**;读 ledger,以 `harness_ledger.py diff-hash --repo <executionRoot> --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json` 计算 diffHash + post-test 7 类分类(`executionRoot` 必须直接取准备回执;禁止手写 ledger / 手工 phase.end)。若 gate begin 报 `CONTEXT_HANDOFF_REQUIRED` / `CONTEXT_BEGIN_REQUIRED`(上一阶段关门时未写交接的历史断链),**一条命令修复**:`harness_context.py handoff --project . --change <id> --to-phase submit --executor <tool> --json`(自动补租约→写收据→begin 确认;**不要**再 `harness_change.py claim` 阶段租约,也不要手工拼 context close/prepare/begin 序列)
77
77
  1. **合并最新代码** — 主目录与 worktree 均**不在业务工作区 stash/pull**;远端同步由合并段 integration transaction 在隔离 integration worktree 内完成(见「worktree 合并流程」);**正常路径禁止 `git stash` / `stash pop`**
78
78
  2. **最终验证** — ledger 复用优先;提交前只调用 `can-reuse --project . --profile-input unitTestFull --command <profile 规范命令>`。不得传入另一套 `--files`,不得把 runner 包装说明写进 `command`。`reuse=true` 时禁止重跑;只有真实输入、依赖、工具链或环境身份变化时才执行一次同一 profile 验证,并只登记一条结果。不要读取 ledger/archive 实现源码或临时编写散列脚本排查参数。
79
79
  - 无远端 CI 且 gate-policy 未强制 remote provider 时,验证通过/复用后运行 `harness_archive.py certify-local --change-dir ... --project . --json`,从同一 ledger 生成 `local-reproducible` 产品候选收据;该命令不执行测试。
@@ -19,7 +19,7 @@ disallowed-tools:
19
19
  - Bash(awk *)
20
20
  - Bash(curl *)
21
21
  ---
22
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
22
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
23
23
  # harness-sync
24
24
 
25
25
  ## Purpose
@@ -51,7 +51,7 @@ CLI 负责 Python runtime 解析、Adapter 事务、远端知识职责、文档
51
51
  ## Interpret
52
52
 
53
53
  - `OK`:所有可验证组件通过。
54
- - `ADVISORY`:例如需要运行中文指令审计提案;退出码仍为 0,且 `sync` 本身没有改写文档。
54
+ - `ADVISORY`:例如需要运行中文指令审计提案;退出码仍为 0,且 `sync` 本身没有改写文档。`CODEGRAPH_SERVICE_UNREACHABLE` 也属此级:daemon 未运行时索引仍可正常查询(CLI/MCP 直读数据库),仅增量自动同步暂停,不需要按 WARN 修复。
55
55
  - `WARN`:存在过期、冲突、待评审或 `UNKNOWN` 证据;按组件的中文 `nextAction` 处理。
56
56
  - `FAIL`:组件执行失败;不得宣称同步完成。
57
57
  - `BLOCKED`:runtime、项目状态或能力契约阻塞;先修复阻塞条件。
@@ -23,7 +23,7 @@ disallowed-tools:
23
23
  - Bash(node *)
24
24
  - Bash(codegraph *)
25
25
  ---
26
- <!-- generated by harness_deploy.py; core=ec59ac2389d9dce9; overlay=none; agent=claude-code; do not edit -->
26
+ <!-- generated by harness_deploy.py; core=3c6eec08da6f5a5c; overlay=none; agent=claude-code; do not edit -->
27
27
  # harness-test — 测试执行
28
28
 
29
29
  > **2026-08 阶段合并**:原 `run`(编码)与 `test`(验证)合并为单一 `execute` 阶段,
@@ -819,6 +819,10 @@ def evaluate_product_ci_gate(change_dir: Path) -> dict[str, Any]:
819
819
  "evidenceValid": True,
820
820
  "capabilities": sorted(capabilities),
821
821
  "evidence": evidence,
822
+ "nextAction": (
823
+ "项目策略要求远端认证证据:先跑远端 CI 验证,或调整 "
824
+ "meta/gate-policy.json 的 candidateVerification.remoteRequired"
825
+ ),
822
826
  }
823
827
  if not allow_local_release:
824
828
  return {
@@ -833,6 +837,12 @@ def evaluate_product_ci_gate(change_dir: Path) -> dict[str, Any]:
833
837
  "evidenceValid": True,
834
838
  "capabilities": sorted(capabilities),
835
839
  "evidence": evidence,
840
+ "nextAction": (
841
+ "本地可复现证据需要显式授权:harness_change.py "
842
+ f"allow-local-release --change {change_dir.name}"
843
+ "(写入 candidateVerification.allowLocalRelease=true),"
844
+ "然后重跑 archive"
845
+ ),
836
846
  }
837
847
  return {
838
848
  "ok": True,
@@ -2469,6 +2479,13 @@ def validate_sensitive_evidence_publication_gate(
2469
2479
  change_dir, exclude_dirs=hruntime.PUBLICATION_EXCLUDED_DIRS
2470
2480
  )
2471
2481
  if candidates:
2482
+ quarantine_cmd = (
2483
+ "harness_runtime.py quarantine-evidence --project . "
2484
+ f"--change-dir {change_dir} "
2485
+ + " ".join(
2486
+ f"--file {item['path']}" for item in candidates
2487
+ )
2488
+ )
2472
2489
  return _advisory_sensitive_gate(
2473
2490
  {
2474
2491
  "ok": False,
@@ -2476,7 +2493,8 @@ def validate_sensitive_evidence_publication_gate(
2476
2493
  "receiptPath": str(receipt_path),
2477
2494
  "unresolvedFailures": candidates,
2478
2495
  "nextAction": (
2479
- "Quarantine the original bytes before archive publication."
2496
+ "把明文证据逐条隔离出可发布树(原字节移入私有隔离区,"
2497
+ "一轮命令可带全部 --file):" + quarantine_cmd
2480
2498
  ),
2481
2499
  },
2482
2500
  policy,
@@ -6366,6 +6384,11 @@ def validate_report_adequacy(summary: dict[str, Any]) -> dict[str, Any]:
6366
6384
  "code": "DIFF_ZERO_WITH_NONEMPTY_COMMIT",
6367
6385
  "severity": "error",
6368
6386
  "message": f"final commit {final} differs from base {base} but filesChanged=0",
6387
+ "nextAction": (
6388
+ "产品代码路径未声明会导致 diff 归到 foreignPaths。声明后重跑 archive:"
6389
+ "harness_change.py declare-ownership --change <change> "
6390
+ "--product-path <产品代码目录>(精确路径,可重复传)"
6391
+ ),
6369
6392
  })
6370
6393
 
6371
6394
  # HH-ARCHIVE-20260730-001: refuse internally-consistent but truncated boundaries.
@@ -7160,6 +7183,10 @@ def _project_release_policy_gate(
7160
7183
  "candidateVerification.allowLocalRelease=true"
7161
7184
  ),
7162
7185
  "remoteRequired": remote_required,
7186
+ "nextAction": (
7187
+ "本地发布需要显式授权:harness_change.py allow-local-release "
7188
+ f"--change {change_dir.name},然后重跑 archive"
7189
+ ),
7163
7190
  }
7164
7191
  evidence = candidate_gate.get("evidence")
7165
7192
  evidence = evidence if isinstance(evidence, dict) else {}
@@ -1099,6 +1099,59 @@ def cmd_resolve(args: argparse.Namespace) -> int:
1099
1099
  )
1100
1100
 
1101
1101
 
1102
+ def allow_local_release(project_root: Path, change_id: str) -> dict[str, Any]:
1103
+ """在 gate-policy.json 写入 candidateVerification.allowLocalRelease=true。
1104
+
1105
+ archive 的 PROJECT_RELEASE_POLICY_BLOCKED 要求这个策略位,此前只能手工
1106
+ 编辑 meta/gate-policy.json(2026-08-30 sales-insight-agent archive 实测)。
1107
+ 这里给出正规入口:保留既有策略内容,只翻转一个布尔位;幂等。
1108
+ """
1109
+ resolved = resolve_change(project_root, change_id)
1110
+ if not resolved.get("ok"):
1111
+ return resolved
1112
+ change_dir = Path(resolved["changeDir"])
1113
+ policy_path = change_dir / "meta" / "gate-policy.json"
1114
+ policy: dict[str, Any] = {"schemaVersion": 1}
1115
+ if policy_path.is_file():
1116
+ try:
1117
+ data = _read_json(policy_path)
1118
+ except (OSError, json.JSONDecodeError) as exc:
1119
+ return {
1120
+ "ok": False,
1121
+ "code": "GATE_POLICY_INVALID",
1122
+ "message": str(exc),
1123
+ "path": str(policy_path),
1124
+ }
1125
+ if not isinstance(data, dict) or data.get("schemaVersion") != 1:
1126
+ return {
1127
+ "ok": False,
1128
+ "code": "GATE_POLICY_INVALID",
1129
+ "message": "gate-policy.json 必须是 schemaVersion=1 的对象",
1130
+ "path": str(policy_path),
1131
+ }
1132
+ policy = data
1133
+ candidate = policy.get("candidateVerification")
1134
+ candidate = dict(candidate) if isinstance(candidate, dict) else {}
1135
+ if candidate.get("allowLocalRelease") is True:
1136
+ return {
1137
+ "ok": True,
1138
+ "code": "LOCAL_RELEASE_ALREADY_ALLOWED",
1139
+ "changeId": resolved["changeId"],
1140
+ "path": str(policy_path),
1141
+ "candidateVerification": candidate,
1142
+ }
1143
+ candidate["allowLocalRelease"] = True
1144
+ policy["candidateVerification"] = candidate
1145
+ _write_json(policy_path, policy)
1146
+ return {
1147
+ "ok": True,
1148
+ "code": "LOCAL_RELEASE_ALLOWED",
1149
+ "changeId": resolved["changeId"],
1150
+ "path": str(policy_path),
1151
+ "candidateVerification": candidate,
1152
+ }
1153
+
1154
+
1102
1155
  def declare_product_ownership(
1103
1156
  project_root: Path, change_id: str, *, product_paths: list[str]
1104
1157
  ) -> dict[str, Any]:
@@ -1167,6 +1220,20 @@ def declare_product_ownership(
1167
1220
  }
1168
1221
 
1169
1222
 
1223
+ def cmd_allow_local_release(args: argparse.Namespace) -> int:
1224
+ project = resolve_main_project_root()
1225
+ payload = allow_local_release(project, args.change)
1226
+ if payload.get("ok"):
1227
+ emit(payload, as_json=bool(args.json))
1228
+ return 0
1229
+ return emit_error(
1230
+ str(payload.get("code", "ALLOW_LOCAL_RELEASE_FAILED")),
1231
+ str(payload.get("message", "allow local release failed")),
1232
+ as_json=bool(args.json),
1233
+ extra={k: v for k, v in payload.items() if k not in {"ok", "message"}},
1234
+ )
1235
+
1236
+
1170
1237
  def cmd_declare_ownership(args: argparse.Namespace) -> int:
1171
1238
  project = resolve_main_project_root()
1172
1239
  payload = declare_product_ownership(
@@ -1564,6 +1631,13 @@ def build_parser() -> argparse.ArgumentParser:
1564
1631
  )
1565
1632
  p_ownership.set_defaults(func=cmd_declare_ownership)
1566
1633
 
1634
+ p_local_release = sub.add_parser(
1635
+ "allow-local-release", parents=[shared],
1636
+ help="set candidateVerification.allowLocalRelease=true in gate-policy.json",
1637
+ )
1638
+ p_local_release.add_argument("--change", required=True)
1639
+ p_local_release.set_defaults(func=cmd_allow_local_release)
1640
+
1567
1641
  p_claim = sub.add_parser("claim", parents=[shared])
1568
1642
  p_claim.add_argument("--change", required=True)
1569
1643
  p_claim.add_argument("--phase", required=True)