@hunter-harness/workflow-harness 0.2.5 → 0.2.7

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 (270) hide show
  1. package/harness/bundles/general/claude-code/.harness-build.json +1 -1
  2. package/harness/bundles/general/claude-code/contracts/workflow-policy.json +169 -0
  3. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +7 -2
  4. package/harness/bundles/general/claude-code/harness-archive/reference.md +1 -1
  5. package/harness/bundles/general/claude-code/harness-archive/templates/render-summary.mjs +78 -155
  6. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +4 -2
  7. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +5 -3
  8. package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  9. package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  10. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +6 -2
  11. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +8 -3
  12. package/harness/bundles/general/claude-code/harness-review/SKILL.md +8 -3
  13. package/harness/bundles/general/claude-code/harness-run/SKILL.md +13 -7
  14. package/harness/bundles/general/claude-code/harness-run/checklist.md +2 -2
  15. package/harness/bundles/general/claude-code/harness-run/reference.md +6 -3
  16. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +11 -6
  17. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +5 -3
  18. package/harness/bundles/general/claude-code/harness-test/SKILL.md +12 -3
  19. package/harness/bundles/general/claude-code/harness-test/reference.md +1 -1
  20. package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +1 -1
  21. package/harness/bundles/general/claude-code/protocols/report-pipeline-protocol.md +11 -4
  22. package/harness/bundles/general/claude-code/scripts/harness_apidoc.py +53 -0
  23. package/harness/bundles/general/claude-code/scripts/harness_archive.py +231 -48
  24. package/harness/bundles/general/claude-code/scripts/harness_change.py +854 -0
  25. package/harness/bundles/general/claude-code/scripts/harness_events.py +134 -40
  26. package/harness/bundles/general/claude-code/scripts/harness_gate.py +1038 -0
  27. package/harness/bundles/general/claude-code/scripts/harness_preflight.py +46 -3
  28. package/harness/bundles/general/claude-code/scripts/harness_profile.py +2 -2
  29. package/harness/bundles/general/claude-code/scripts/harness_service.py +34 -1
  30. package/harness/bundles/general/claude-code/scripts/harness_state.py +148 -0
  31. package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +210 -14
  32. package/harness/bundles/general/claude-code/scripts/harness_workflow_policy.py +160 -0
  33. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  34. package/harness/bundles/general/codebuddy/contracts/workflow-policy.json +169 -0
  35. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +7 -2
  36. package/harness/bundles/general/codebuddy/harness-archive/reference.md +1 -1
  37. package/harness/bundles/general/codebuddy/harness-archive/templates/render-summary.mjs +78 -155
  38. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +4 -2
  39. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +5 -3
  40. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  41. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  42. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +6 -2
  43. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +8 -3
  44. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +8 -3
  45. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +13 -7
  46. package/harness/bundles/general/codebuddy/harness-run/checklist.md +2 -2
  47. package/harness/bundles/general/codebuddy/harness-run/reference.md +6 -3
  48. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +11 -6
  49. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +5 -3
  50. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +12 -3
  51. package/harness/bundles/general/codebuddy/harness-test/reference.md +1 -1
  52. package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +1 -1
  53. package/harness/bundles/general/codebuddy/protocols/report-pipeline-protocol.md +11 -4
  54. package/harness/bundles/general/codebuddy/scripts/harness_apidoc.py +53 -0
  55. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +231 -48
  56. package/harness/bundles/general/codebuddy/scripts/harness_change.py +854 -0
  57. package/harness/bundles/general/codebuddy/scripts/harness_events.py +134 -40
  58. package/harness/bundles/general/codebuddy/scripts/harness_gate.py +1038 -0
  59. package/harness/bundles/general/codebuddy/scripts/harness_preflight.py +46 -3
  60. package/harness/bundles/general/codebuddy/scripts/harness_profile.py +2 -2
  61. package/harness/bundles/general/codebuddy/scripts/harness_service.py +34 -1
  62. package/harness/bundles/general/codebuddy/scripts/harness_state.py +148 -0
  63. package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +210 -14
  64. package/harness/bundles/general/codebuddy/scripts/harness_workflow_policy.py +160 -0
  65. package/harness/bundles/general/codex/.harness-build.json +1 -1
  66. package/harness/bundles/general/codex/contracts/workflow-policy.json +169 -0
  67. package/harness/bundles/general/codex/harness-archive/SKILL.md +7 -2
  68. package/harness/bundles/general/codex/harness-archive/reference.md +1 -1
  69. package/harness/bundles/general/codex/harness-archive/templates/render-summary.mjs +78 -155
  70. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +4 -2
  71. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +5 -3
  72. package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  73. package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  74. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +6 -2
  75. package/harness/bundles/general/codex/harness-plan/SKILL.md +8 -3
  76. package/harness/bundles/general/codex/harness-review/SKILL.md +7 -2
  77. package/harness/bundles/general/codex/harness-run/SKILL.md +13 -7
  78. package/harness/bundles/general/codex/harness-run/checklist.md +2 -2
  79. package/harness/bundles/general/codex/harness-run/reference.md +6 -3
  80. package/harness/bundles/general/codex/harness-submit/SKILL.md +11 -6
  81. package/harness/bundles/general/codex/harness-sync/SKILL.md +5 -3
  82. package/harness/bundles/general/codex/harness-test/SKILL.md +12 -3
  83. package/harness/bundles/general/codex/harness-test/reference.md +1 -1
  84. package/harness/bundles/general/codex/protocols/ledger-protocol.md +1 -1
  85. package/harness/bundles/general/codex/protocols/report-pipeline-protocol.md +11 -4
  86. package/harness/bundles/general/codex/scripts/harness_apidoc.py +53 -0
  87. package/harness/bundles/general/codex/scripts/harness_archive.py +231 -48
  88. package/harness/bundles/general/codex/scripts/harness_change.py +854 -0
  89. package/harness/bundles/general/codex/scripts/harness_events.py +134 -40
  90. package/harness/bundles/general/codex/scripts/harness_gate.py +1038 -0
  91. package/harness/bundles/general/codex/scripts/harness_preflight.py +46 -3
  92. package/harness/bundles/general/codex/scripts/harness_profile.py +2 -2
  93. package/harness/bundles/general/codex/scripts/harness_service.py +34 -1
  94. package/harness/bundles/general/codex/scripts/harness_state.py +148 -0
  95. package/harness/bundles/general/codex/scripts/harness_test_guard.py +210 -14
  96. package/harness/bundles/general/codex/scripts/harness_workflow_policy.py +160 -0
  97. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  98. package/harness/bundles/general/cursor/contracts/workflow-policy.json +169 -0
  99. package/harness/bundles/general/cursor/harness-archive/SKILL.md +7 -2
  100. package/harness/bundles/general/cursor/harness-archive/reference.md +1 -1
  101. package/harness/bundles/general/cursor/harness-archive/templates/render-summary.mjs +78 -155
  102. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +4 -2
  103. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +5 -3
  104. package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  105. package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  106. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +6 -2
  107. package/harness/bundles/general/cursor/harness-plan/SKILL.md +8 -3
  108. package/harness/bundles/general/cursor/harness-review/SKILL.md +7 -2
  109. package/harness/bundles/general/cursor/harness-run/SKILL.md +13 -7
  110. package/harness/bundles/general/cursor/harness-run/checklist.md +2 -2
  111. package/harness/bundles/general/cursor/harness-run/reference.md +6 -3
  112. package/harness/bundles/general/cursor/harness-submit/SKILL.md +11 -6
  113. package/harness/bundles/general/cursor/harness-sync/SKILL.md +5 -3
  114. package/harness/bundles/general/cursor/harness-test/SKILL.md +12 -3
  115. package/harness/bundles/general/cursor/harness-test/reference.md +1 -1
  116. package/harness/bundles/general/cursor/protocols/ledger-protocol.md +1 -1
  117. package/harness/bundles/general/cursor/protocols/report-pipeline-protocol.md +11 -4
  118. package/harness/bundles/general/cursor/scripts/harness_apidoc.py +53 -0
  119. package/harness/bundles/general/cursor/scripts/harness_archive.py +231 -48
  120. package/harness/bundles/general/cursor/scripts/harness_change.py +854 -0
  121. package/harness/bundles/general/cursor/scripts/harness_events.py +134 -40
  122. package/harness/bundles/general/cursor/scripts/harness_gate.py +1038 -0
  123. package/harness/bundles/general/cursor/scripts/harness_preflight.py +46 -3
  124. package/harness/bundles/general/cursor/scripts/harness_profile.py +2 -2
  125. package/harness/bundles/general/cursor/scripts/harness_service.py +34 -1
  126. package/harness/bundles/general/cursor/scripts/harness_state.py +148 -0
  127. package/harness/bundles/general/cursor/scripts/harness_test_guard.py +210 -14
  128. package/harness/bundles/general/cursor/scripts/harness_workflow_policy.py +160 -0
  129. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  130. package/harness/bundles/java/claude-code/contracts/workflow-policy.json +169 -0
  131. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +11 -2
  132. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +7 -2
  133. package/harness/bundles/java/claude-code/harness-archive/reference.md +1 -1
  134. package/harness/bundles/java/claude-code/harness-archive/templates/render-summary.mjs +78 -155
  135. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +4 -2
  136. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +5 -3
  137. package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  138. package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  139. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +6 -2
  140. package/harness/bundles/java/claude-code/harness-package/SKILL.md +10 -4
  141. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +8 -3
  142. package/harness/bundles/java/claude-code/harness-review/SKILL.md +8 -3
  143. package/harness/bundles/java/claude-code/harness-run/SKILL.md +13 -7
  144. package/harness/bundles/java/claude-code/harness-run/reference.md +1 -1
  145. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +11 -6
  146. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +5 -3
  147. package/harness/bundles/java/claude-code/harness-test/SKILL.md +12 -3
  148. package/harness/bundles/java/claude-code/harness-test/reference.md +1 -1
  149. package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +1 -1
  150. package/harness/bundles/java/claude-code/protocols/report-pipeline-protocol.md +11 -4
  151. package/harness/bundles/java/claude-code/scripts/harness_apidoc.py +53 -0
  152. package/harness/bundles/java/claude-code/scripts/harness_archive.py +231 -48
  153. package/harness/bundles/java/claude-code/scripts/harness_change.py +854 -0
  154. package/harness/bundles/java/claude-code/scripts/harness_events.py +134 -40
  155. package/harness/bundles/java/claude-code/scripts/harness_gate.py +1038 -0
  156. package/harness/bundles/java/claude-code/scripts/harness_preflight.py +46 -3
  157. package/harness/bundles/java/claude-code/scripts/harness_profile.py +2 -2
  158. package/harness/bundles/java/claude-code/scripts/harness_service.py +34 -1
  159. package/harness/bundles/java/claude-code/scripts/harness_state.py +148 -0
  160. package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +210 -14
  161. package/harness/bundles/java/claude-code/scripts/harness_workflow_policy.py +160 -0
  162. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  163. package/harness/bundles/java/codebuddy/contracts/workflow-policy.json +169 -0
  164. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +11 -2
  165. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +7 -2
  166. package/harness/bundles/java/codebuddy/harness-archive/reference.md +1 -1
  167. package/harness/bundles/java/codebuddy/harness-archive/templates/render-summary.mjs +78 -155
  168. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +4 -2
  169. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +5 -3
  170. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  171. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  172. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +6 -2
  173. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +10 -4
  174. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +8 -3
  175. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +8 -3
  176. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +13 -7
  177. package/harness/bundles/java/codebuddy/harness-run/reference.md +1 -1
  178. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +11 -6
  179. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +5 -3
  180. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +12 -3
  181. package/harness/bundles/java/codebuddy/harness-test/reference.md +1 -1
  182. package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +1 -1
  183. package/harness/bundles/java/codebuddy/protocols/report-pipeline-protocol.md +11 -4
  184. package/harness/bundles/java/codebuddy/scripts/harness_apidoc.py +53 -0
  185. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +231 -48
  186. package/harness/bundles/java/codebuddy/scripts/harness_change.py +854 -0
  187. package/harness/bundles/java/codebuddy/scripts/harness_events.py +134 -40
  188. package/harness/bundles/java/codebuddy/scripts/harness_gate.py +1038 -0
  189. package/harness/bundles/java/codebuddy/scripts/harness_preflight.py +46 -3
  190. package/harness/bundles/java/codebuddy/scripts/harness_profile.py +2 -2
  191. package/harness/bundles/java/codebuddy/scripts/harness_service.py +34 -1
  192. package/harness/bundles/java/codebuddy/scripts/harness_state.py +148 -0
  193. package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +210 -14
  194. package/harness/bundles/java/codebuddy/scripts/harness_workflow_policy.py +160 -0
  195. package/harness/bundles/java/codex/.harness-build.json +1 -1
  196. package/harness/bundles/java/codex/contracts/workflow-policy.json +169 -0
  197. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +11 -2
  198. package/harness/bundles/java/codex/harness-archive/SKILL.md +7 -2
  199. package/harness/bundles/java/codex/harness-archive/reference.md +1 -1
  200. package/harness/bundles/java/codex/harness-archive/templates/render-summary.mjs +78 -155
  201. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +4 -2
  202. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +5 -3
  203. package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  204. package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  205. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +6 -2
  206. package/harness/bundles/java/codex/harness-package/SKILL.md +10 -4
  207. package/harness/bundles/java/codex/harness-plan/SKILL.md +8 -3
  208. package/harness/bundles/java/codex/harness-review/SKILL.md +7 -2
  209. package/harness/bundles/java/codex/harness-run/SKILL.md +13 -7
  210. package/harness/bundles/java/codex/harness-run/reference.md +1 -1
  211. package/harness/bundles/java/codex/harness-submit/SKILL.md +11 -6
  212. package/harness/bundles/java/codex/harness-sync/SKILL.md +5 -3
  213. package/harness/bundles/java/codex/harness-test/SKILL.md +12 -3
  214. package/harness/bundles/java/codex/harness-test/reference.md +1 -1
  215. package/harness/bundles/java/codex/protocols/ledger-protocol.md +1 -1
  216. package/harness/bundles/java/codex/protocols/report-pipeline-protocol.md +11 -4
  217. package/harness/bundles/java/codex/scripts/harness_apidoc.py +53 -0
  218. package/harness/bundles/java/codex/scripts/harness_archive.py +231 -48
  219. package/harness/bundles/java/codex/scripts/harness_change.py +854 -0
  220. package/harness/bundles/java/codex/scripts/harness_events.py +134 -40
  221. package/harness/bundles/java/codex/scripts/harness_gate.py +1038 -0
  222. package/harness/bundles/java/codex/scripts/harness_preflight.py +46 -3
  223. package/harness/bundles/java/codex/scripts/harness_profile.py +2 -2
  224. package/harness/bundles/java/codex/scripts/harness_service.py +34 -1
  225. package/harness/bundles/java/codex/scripts/harness_state.py +148 -0
  226. package/harness/bundles/java/codex/scripts/harness_test_guard.py +210 -14
  227. package/harness/bundles/java/codex/scripts/harness_workflow_policy.py +160 -0
  228. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  229. package/harness/bundles/java/cursor/contracts/workflow-policy.json +169 -0
  230. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +11 -2
  231. package/harness/bundles/java/cursor/harness-archive/SKILL.md +7 -2
  232. package/harness/bundles/java/cursor/harness-archive/reference.md +1 -1
  233. package/harness/bundles/java/cursor/harness-archive/templates/render-summary.mjs +78 -155
  234. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +4 -2
  235. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +5 -3
  236. package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +109 -7
  237. package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge_mcp.py +2 -0
  238. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +6 -2
  239. package/harness/bundles/java/cursor/harness-package/SKILL.md +10 -4
  240. package/harness/bundles/java/cursor/harness-plan/SKILL.md +8 -3
  241. package/harness/bundles/java/cursor/harness-review/SKILL.md +7 -2
  242. package/harness/bundles/java/cursor/harness-run/SKILL.md +13 -7
  243. package/harness/bundles/java/cursor/harness-run/reference.md +1 -1
  244. package/harness/bundles/java/cursor/harness-submit/SKILL.md +11 -6
  245. package/harness/bundles/java/cursor/harness-sync/SKILL.md +5 -3
  246. package/harness/bundles/java/cursor/harness-test/SKILL.md +12 -3
  247. package/harness/bundles/java/cursor/harness-test/reference.md +1 -1
  248. package/harness/bundles/java/cursor/protocols/ledger-protocol.md +1 -1
  249. package/harness/bundles/java/cursor/protocols/report-pipeline-protocol.md +11 -4
  250. package/harness/bundles/java/cursor/scripts/harness_apidoc.py +53 -0
  251. package/harness/bundles/java/cursor/scripts/harness_archive.py +231 -48
  252. package/harness/bundles/java/cursor/scripts/harness_change.py +854 -0
  253. package/harness/bundles/java/cursor/scripts/harness_events.py +134 -40
  254. package/harness/bundles/java/cursor/scripts/harness_gate.py +1038 -0
  255. package/harness/bundles/java/cursor/scripts/harness_preflight.py +46 -3
  256. package/harness/bundles/java/cursor/scripts/harness_profile.py +2 -2
  257. package/harness/bundles/java/cursor/scripts/harness_service.py +34 -1
  258. package/harness/bundles/java/cursor/scripts/harness_state.py +148 -0
  259. package/harness/bundles/java/cursor/scripts/harness_test_guard.py +210 -14
  260. package/harness/bundles/java/cursor/scripts/harness_workflow_policy.py +160 -0
  261. package/harness/manifests/general/claude-code.json +48 -28
  262. package/harness/manifests/general/codebuddy.json +48 -28
  263. package/harness/manifests/general/codex.json +48 -28
  264. package/harness/manifests/general/cursor.json +48 -28
  265. package/harness/manifests/java/claude-code.json +49 -29
  266. package/harness/manifests/java/codebuddy.json +49 -29
  267. package/harness/manifests/java/codex.json +49 -29
  268. package/harness/manifests/java/cursor.json +49 -29
  269. package/hunter-workflow-family.json +2 -2
  270. package/package.json +1 -1
@@ -776,13 +776,14 @@ def write_cached_archive_entries(
776
776
 
777
777
  def load_preserved_entries(knowledge: Path) -> list[dict[str, Any]]:
778
778
  active_entries = load_entries_from_dir(knowledge / "entries" / "active")
779
- demoted_entries = [
779
+ manually_decided_entries = [
780
780
  entry
781
- for status in ["candidate", "stale"]
781
+ for status in ["candidate", "stale", "superseded", "conflicted"]
782
782
  for entry in load_entries_from_dir(knowledge / "entries" / status)
783
783
  if entry.get("lifecycle", {}).get("demotedAt")
784
+ or entry.get("lifecycle", {}).get("judgeAction")
784
785
  ]
785
- return active_entries + demoted_entries
786
+ return active_entries + manually_decided_entries
786
787
 
787
788
 
788
789
  def combine_generated_with_preserved(knowledge: Path, generated: list[dict[str, Any]]) -> list[dict[str, Any]]:
@@ -2981,6 +2982,7 @@ def query_index(
2981
2982
  file_filters: list[str] | None = None,
2982
2983
  statuses: list[str] | None = None,
2983
2984
  types: list[str] | None = None,
2985
+ change_id: str | None = None,
2984
2986
  ) -> dict[str, Any]:
2985
2987
  project = project.resolve()
2986
2988
  knowledge = project / ".harness" / "knowledge"
@@ -2993,6 +2995,26 @@ def query_index(
2993
2995
  build_index(project, snapshot=snapshot)
2994
2996
  entries = search_entries(sqlite_path, query, limit, file_filters, statuses, types)
2995
2997
  context_path = write_context_pack(project, knowledge, query, entries)
2998
+ if change_id:
2999
+ changes_root = (project / ".harness" / "changes").resolve()
3000
+ change_dir = (changes_root / change_id).resolve()
3001
+ try:
3002
+ change_dir.relative_to(changes_root)
3003
+ except ValueError as exc:
3004
+ raise ValueError("change id escapes .harness/changes") from exc
3005
+ if not change_dir.is_dir():
3006
+ raise ValueError(f"change does not exist: {change_id}")
3007
+ write_json(
3008
+ change_dir / "meta" / "knowledge-context.json",
3009
+ {
3010
+ "schemaVersion": 1,
3011
+ "changeId": change_id,
3012
+ "generatedAt": now_iso(),
3013
+ "query": query,
3014
+ "contextPack": str(context_path),
3015
+ "matchIds": [entry["id"] for entry in entries],
3016
+ },
3017
+ )
2996
3018
  filters = {
2997
3019
  "files": file_filters or [],
2998
3020
  "statuses": statuses or [],
@@ -3367,7 +3389,7 @@ def render_entry_for_context(entry: dict[str, Any], include_stale: bool = False)
3367
3389
  NEAR_DUPLICATE_THRESHOLD = 0.88
3368
3390
  AUTO_SUPERSEDE_SIMILARITY = 0.75
3369
3391
  AUTO_SUPERSEDE_WEAK_SIMILARITY = 0.55
3370
- JUDGE_ACTIONS = {"promote", "drop", "supersede", "keep-conflict"}
3392
+ JUDGE_ACTIONS = {"promote", "drop", "supersede", "keep-conflict", "defer"}
3371
3393
  ENTRY_STATUSES = {"candidate", "active", "stale", "superseded", "conflicted"}
3372
3394
 
3373
3395
 
@@ -3829,6 +3851,8 @@ def judge_export(project: Path) -> dict[str, Any]:
3829
3851
  for entry in entries:
3830
3852
  if entry.get("status") != "conflicted":
3831
3853
  continue
3854
+ if entry.get("lifecycle", {}).get("judgeAction") in {"keep-conflict", "defer"}:
3855
+ continue
3832
3856
  for other_id in entry.get("lifecycle", {}).get("conflictsWith") or []:
3833
3857
  pair = tuple(sorted([entry["id"], str(other_id)]))
3834
3858
  if pair in seen_pairs:
@@ -3878,6 +3902,10 @@ def judge_export(project: Path) -> dict[str, Any]:
3878
3902
  for entry in entries:
3879
3903
  if entry.get("status") != "candidate":
3880
3904
  continue
3905
+ if entry.get("lifecycle", {}).get("judgeAction") == "defer":
3906
+ review_after = str(entry.get("lifecycle", {}).get("reviewAfter") or "")
3907
+ if not review_after or review_after > dt.date.today().isoformat():
3908
+ continue
3881
3909
  promote_candidates.append(
3882
3910
  {
3883
3911
  "kind": "promote-candidate",
@@ -3984,6 +4012,18 @@ def apply_judge_decision(
3984
4012
  relocate_entry_file(knowledge, entry, source_path)
3985
4013
  path_by_id[entry["id"]] = knowledge / "entries" / "conflicted" / entry_filename(entry)
3986
4014
  after_status = "conflicted"
4015
+ elif action == "defer":
4016
+ lifecycle = entry.setdefault("lifecycle", {})
4017
+ lifecycle["judgeAction"] = action
4018
+ lifecycle["judgeReason"] = reason
4019
+ lifecycle["deferredAt"] = now_iso()
4020
+ lifecycle["reviewAfter"] = decision.get("reviewAfter")
4021
+ lifecycle["lastCheckedAt"] = now_iso()
4022
+ relocate_entry_file(knowledge, entry, source_path)
4023
+ path_by_id[entry["id"]] = (
4024
+ knowledge / "entries" / str(entry.get("status") or "candidate") / entry_filename(entry)
4025
+ )
4026
+ after_status = str(entry.get("status") or "candidate")
3987
4027
  else:
3988
4028
  raise ValueError(f"unsupported judge action: {action}")
3989
4029
 
@@ -3997,6 +4037,35 @@ def apply_judge_decision(
3997
4037
  }
3998
4038
 
3999
4039
 
4040
+ def persist_judge_decisions(knowledge: Path, applied: list[dict[str, Any]]) -> Path:
4041
+ """Keep one durable latest decision per entry independently of generated reports."""
4042
+ path = knowledge / "judgements" / "decisions.json"
4043
+ current: dict[str, Any] = {"schemaVersion": 1, "decisions": {}}
4044
+ if path.exists():
4045
+ try:
4046
+ loaded = read_json(path)
4047
+ if isinstance(loaded, dict) and isinstance(loaded.get("decisions"), dict):
4048
+ current = loaded
4049
+ except (OSError, json.JSONDecodeError):
4050
+ pass
4051
+ decisions = dict(current.get("decisions") or {})
4052
+ for record in applied:
4053
+ decisions[str(record["id"])] = {
4054
+ "id": record["id"],
4055
+ "action": record["action"],
4056
+ "reason": record.get("reason") or "",
4057
+ "supersededBy": record.get("supersededBy"),
4058
+ "status": record.get("after", {}).get("status"),
4059
+ "decidedAt": now_iso(),
4060
+ }
4061
+ write_json(path, {
4062
+ "schemaVersion": 1,
4063
+ "updatedAt": now_iso(),
4064
+ "decisions": dict(sorted(decisions.items())),
4065
+ })
4066
+ return path
4067
+
4068
+
4000
4069
  def judge_apply(project: Path, decisions_path: Path, force: bool = False) -> dict[str, Any]:
4001
4070
  project = project.resolve()
4002
4071
  knowledge = project / ".harness" / "knowledge"
@@ -4051,11 +4120,13 @@ def judge_apply(project: Path, decisions_path: Path, force: bool = False) -> dic
4051
4120
  }
4052
4121
  judgement_path = knowledge / "reports" / f"judgements-{timestamp()}.json"
4053
4122
  write_json(judgement_path, judgement)
4123
+ decisions_ledger = persist_judge_decisions(knowledge, applied)
4054
4124
  index = refresh_outputs_from_entry_files(project, knowledge)
4055
4125
  return {
4056
4126
  "project": str(project),
4057
4127
  "generatedAt": judgement["generatedAt"],
4058
4128
  "judgement": str(judgement_path),
4129
+ "decisionsLedger": str(decisions_ledger),
4059
4130
  "applied": len(applied),
4060
4131
  "errors": errors,
4061
4132
  "stats": index.get("stats", {}),
@@ -4262,6 +4333,26 @@ def maintain_knowledge(project: Path, archive_id: str) -> dict[str, Any]:
4262
4333
  }
4263
4334
 
4264
4335
 
4336
+ def drain_maintenance_outbox(project: Path, limit: int = 50) -> dict[str, Any]:
4337
+ """Advance all retryable maintenance items in one bounded invocation."""
4338
+ project = project.resolve()
4339
+ root = _outbox_root(project)
4340
+ all_archive_ids = sorted({
4341
+ path.stem
4342
+ for status in ("pending", "failed")
4343
+ for path in (root / status).glob("*.json")
4344
+ })
4345
+ archive_ids = all_archive_ids[:max(0, limit)]
4346
+ results = [maintain_knowledge(project, archive_id) for archive_id in archive_ids]
4347
+ return {
4348
+ "ok": all(result.get("ok") for result in results),
4349
+ "project": str(project),
4350
+ "processed": len(results),
4351
+ "remaining": max(0, len(all_archive_ids) - len(results)),
4352
+ "results": results,
4353
+ }
4354
+
4355
+
4265
4356
  def main(argv: list[str] | None = None) -> int:
4266
4357
  parser = argparse.ArgumentParser(description="Build and query Harness knowledge indexes.")
4267
4358
  sub = parser.add_subparsers(dest="command", required=True)
@@ -4321,6 +4412,7 @@ def main(argv: list[str] | None = None) -> int:
4321
4412
  query.add_argument("--file", action="append", dest="files", default=[], help="Only return entries linked to this source file")
4322
4413
  query.add_argument("--status", action="append", dest="statuses", default=[], help="Only return entries with this lifecycle status")
4323
4414
  query.add_argument("--type", action="append", dest="types", default=[], help="Only return entries of this knowledge type")
4415
+ query.add_argument("--change", default=None, help="Write a change-scoped knowledge-context pointer")
4324
4416
 
4325
4417
  promote = sub.add_parser("promote", help="Promote a candidate knowledge entry to active")
4326
4418
  promote.add_argument("--project", default=".", help="Project root containing .harness/knowledge")
@@ -4378,7 +4470,10 @@ def main(argv: list[str] | None = None) -> int:
4378
4470
  help="Single-process maintenance: claim outbox, ingest+dedupe, supersede, reverify, judge-export",
4379
4471
  )
4380
4472
  maintain.add_argument("--project", default=".", help="Project root containing .harness/knowledge")
4381
- maintain.add_argument("--archive-id", required=True, help="Archive id of the outbox item to maintain")
4473
+ maintain_target = maintain.add_mutually_exclusive_group(required=True)
4474
+ maintain_target.add_argument("--archive-id", help="Archive id of the outbox item to maintain")
4475
+ maintain_target.add_argument("--drain", action="store_true", help="Process all pending/failed items once")
4476
+ maintain.add_argument("--limit", type=int, default=50, help="Maximum items processed by --drain")
4382
4477
  maintain.add_argument("--json", action="store_true", help="Emit machine-readable JSON (default behavior)")
4383
4478
 
4384
4479
  args = parser.parse_args(argv)
@@ -4414,7 +4509,10 @@ def main(argv: list[str] | None = None) -> int:
4414
4509
  print(json.dumps(result, ensure_ascii=False, indent=2))
4415
4510
  return 0
4416
4511
  if args.command == "query":
4417
- result = query_index(Path(args.project), args.query, args.limit, args.files, args.statuses, args.types)
4512
+ result = query_index(
4513
+ Path(args.project), args.query, args.limit, args.files, args.statuses,
4514
+ args.types, args.change,
4515
+ )
4418
4516
  print(json.dumps(result, ensure_ascii=False, indent=2))
4419
4517
  return 0
4420
4518
  if args.command == "promote":
@@ -4468,7 +4566,11 @@ def main(argv: list[str] | None = None) -> int:
4468
4566
  print(json.dumps(result, ensure_ascii=False, indent=2))
4469
4567
  return 0
4470
4568
  if args.command == "maintain":
4471
- result = maintain_knowledge(Path(args.project), args.archive_id)
4569
+ result = (
4570
+ drain_maintenance_outbox(Path(args.project), args.limit)
4571
+ if args.drain
4572
+ else maintain_knowledge(Path(args.project), args.archive_id)
4573
+ )
4472
4574
  print(json.dumps(result, ensure_ascii=False, indent=2))
4473
4575
  return 0 if result.get("ok") else 1
4474
4576
  return 2
@@ -219,6 +219,7 @@ def create_server() -> Any:
219
219
  files: list[str] | None = None,
220
220
  statuses: list[str] | None = None,
221
221
  types: list[str] | None = None,
222
+ change_id: str | None = None,
222
223
  ) -> dict[str, Any]:
223
224
  return hk.query_index(
224
225
  Path(project),
@@ -227,6 +228,7 @@ def create_server() -> Any:
227
228
  file_filters=files or [],
228
229
  statuses=statuses or [],
229
230
  types=types or [],
231
+ change_id=change_id,
230
232
  )
231
233
 
232
234
  @server.tool(description=TOOL_DESCRIPTIONS[7]["description"])
@@ -20,9 +20,11 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=5cadfa54663ecdbf; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=89e664933ed69572; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-knowledge-query
25
25
 
26
+ 并行 change 中查询必须传 `--change <change-id>`;成功后以该 change 的 `meta/knowledge-context.json` 为稳定指针。全局 `context-packs/latest.json` 仅向后兼容,不得用于判断多个 active change 的上下文归属。
27
+
26
28
  根据用户的新需求或排查问题,从项目本地 `.harness/knowledge` 中检索历史需求、决策、实现、风险和测试证据,并生成 AI 可读的 context pack。
27
29
 
28
30
  此 skill 只负责查询和使用知识。整理、同步和 promote 条目由 `harness-knowledge-ingest` 负责。
@@ -147,7 +149,7 @@ powershell.exe -Command "python '<ingest-skill-dir>\scripts\harness_knowledge.py
147
149
 
148
150
  ## 执行日志
149
151
 
150
- `events.ndjson` 为唯一事实源(schema_version 2,`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
152
+ `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
151
153
 
152
154
  ```powershell
153
155
  python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --note "<触发指令>"
@@ -156,3 +158,5 @@ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/cha
156
158
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
157
159
 
158
160
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
161
+
162
+ 每次阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`;重试同一阶段时增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
@@ -20,11 +20,13 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=5cadfa54663ecdbf; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=89e664933ed69572; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-plan — 需求规划
25
25
 
26
26
  ## Purpose
27
27
 
28
+ 确定 change 后必须运行 `python <skills-root>/scripts/harness_gate.py classify --change <id> --stage plan --json`,并把脚本返回的 risk tier、默认阶段、条件阶段和必需验证写入计划;不得凭模型印象另建风险分级。
29
+
28
30
  需求 → 设计文档 → 任务拆分 → 测试场景表(编码/测试唯一真相源)。存在 `.harness/archive/` 或 `.harness/knowledge/` 时须先 `harness-knowledge-query`。
29
31
 
30
32
  ## When to Use
@@ -41,6 +43,7 @@ disallowed-tools:
41
43
  6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
42
44
  7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
43
45
  8. **禁止读取 `docs/superpowers/` 作为正式输入** — 旧草稿仅人工线索
46
+ 9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --base <baseCommit> --json`;`changedSegments=[]` 时复用已有 profile/rules/map/knowledge/change/code 指纹,不再重复跑全量 `harness-sync`、知识重建或代码库扫描。只有对应 segment 变化或缺失时才定向刷新;快照不能替代源码读取和验证门禁。
44
47
 
45
48
  状态目录分层:新路径优先,旧路径兼容 → [[../protocols/state-layout-protocol.md|state-layout-protocol]]
46
49
 
@@ -66,7 +69,7 @@ disallowed-tools:
66
69
 
67
70
  ## Subagent 委派
68
71
 
69
- - **阶段 3 探索**:先运行 `python <skills-root>/scripts/harness_preflight.py check-agents --skills-root <skills-root> --agent harness-explorer --json`;可用则委派,否则主会话探索;无效返回不 retry
72
+ - **阶段 3 探索**:先运行 `python <skills-root>/scripts/harness_preflight.py check-agents --skills-root <skills-root> --agent harness-explorer --json`;可用则委派,否则主会话探索且不 retry。`reasonCode=CUSTOM_AGENTS_UNSUPPORTED` 表示当前工具本身没有自定义 agent 能力,是正常的 inline 路径,控制台不得显示“harness-explorer subagent 不可用”类告警。
70
73
  - **阶段 7.5**:仅 `--adversarial`;先运行 `python <skills-root>/scripts/harness_preflight.py check-agents --skills-root <skills-root> --agent harness-evaluator --json`;可用才委派到 `reports/plan-review/`
71
74
 
72
75
  ## Workflow 概要
@@ -121,7 +124,7 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
121
124
 
122
125
  ## 执行日志
123
126
 
124
- `events.ndjson` 为唯一事实源(schema_version 2,`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
127
+ `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
125
128
 
126
129
  ```powershell
127
130
  python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --note "<触发指令>"
@@ -130,3 +133,5 @@ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/cha
130
133
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
131
134
 
132
135
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
136
+
137
+ 每次阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`;重试同一阶段时增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(curl *)
22
22
  - Bash(codegraph *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=5cadfa54663ecdbf; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=89e664933ed69572; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-review — 代码审查
26
26
 
27
27
  ## Purpose
@@ -57,17 +57,20 @@ disallowed-tools:
57
57
  6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
58
58
  7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
59
59
  8. **禁止读取 `docs/superpowers/` 作为正式输入** — 旧草稿仅人工线索
60
+ 9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --base <baseCommit> --json`;`changedSegments=[]` 时复用已有 profile/rules/map/knowledge/change/code 指纹,不再重复跑全量 `harness-sync`、知识重建或代码库扫描。只有对应 segment 变化或缺失时才定向刷新;快照不能替代源码读取和验证门禁。
60
61
 
61
62
  状态目录分层:新路径优先,旧路径兼容 → [[../protocols/state-layout-protocol.md|state-layout-protocol]]
62
63
 
63
64
  ## Workflow
64
65
 
66
+ 先用 `harness_change.py resolve [--change] --json` 解析 change;多个 active change 未显式选择时返回 `CHANGE_SELECTION_REQUIRED`,禁止再按 Glob/mtime 猜测。阶段边界固定使用 `harness_gate.py begin --phase review --change <id> --task <n> --skills-root <skills-root> --executor-tool <tool> --json` 和 `harness_gate.py close --phase review --change <id> --status <OK|WARN|FAIL> --run-id <begin-run-id> --json`。不得手工追加 `phase.start/phase.end`;close 失败不得宣称审查完成。
67
+
65
68
  0. **启动准备** — 确定变更名(Glob `.harness/changes/*/plans/*-plan.md`,排除 `.harness/archive/*/`,读 frontmatter 提取 change-name);**append `phase.start` 事件**(不得等审查完成才补)
66
69
  1. **读取 worktree 状态(门禁检查)** — 读 `.harness/changes/<change-name>/meta/worktree.json`:`requested=true` 但 worktree 不存在 → 停止并提示先修复 `harness-run`,不得静默回主目录(否则 git diff 为空);`requested=true` 且 worktree 已创建 → spawned agent 用该 worktree 路径执行 `git diff`(确保审查 worktree 变更而非主目录);`requested=false` → 审查主目录变更
67
70
  <!-- @section-id review.delegate -->
68
71
  ### 2. 委派 harness-reviewer
69
72
 
70
- 先运行 `python <skills-root>/scripts/harness_preflight.py check-agents --skills-root <skills-root> --agent harness-reviewer --json`。`usable=false` → **直接主会话审查**,记 `decision` 事件,**不委派**。`usable=true` 时用 Agent spawn `harness-reviewer`(只读, 6 维度)。返回空 / 无报告正文 → **不 retry**,降级主会话审查。
73
+ 先运行 `python <skills-root>/scripts/harness_preflight.py check-agents --skills-root <skills-root> --agent harness-reviewer --json`。`usable=false` → **直接主会话审查**,记 `decision` 事件,**不委派**。`reasonCode=CUSTOM_AGENTS_UNSUPPORTED` 是当前工具没有自定义 agent 能力的正常 inline 路径,不显示缺失告警。`usable=true` 时用 Agent spawn `harness-reviewer`(只读, 6 维度)。返回空 / 无报告正文 → **不 retry**,降级主会话审查。
71
74
 
72
75
  3. **持久化报告(强制,主会话)** — Agent 返回后主会话 Write 到 `reports/review/review-report-*.md`。未 Write → 🟡WARN,不得宣称 review 完成。
73
76
  4. **生成修复反馈(原生协议)** — 若报告存在 RED/YELLOW 问题,执行 `protocols.md` 的 `review-fixback-protocol`,将问题转化为结构化 fixback 清单并落盘到 `.harness/changes/<change-name>/reports/review/fixback-YYYYMMDD-HHmm.md`。若无 RED/YELLOW,记录 `review-fixback-protocol: skipped(no findings)`。不调用 Superpowers `receiving-code-review`,也不记录外部 skill 降级。
@@ -153,7 +156,7 @@ review 读取 `state-snapshot.json`(`harness_state.py` / state-layout-protocol
153
156
 
154
157
  ## 执行日志
155
158
 
156
- `events.ndjson` 为唯一事实源(schema_version 2,`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
159
+ `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
157
160
 
158
161
  ```powershell
159
162
  python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --note "<触发指令>"
@@ -162,3 +165,5 @@ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/cha
162
165
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
163
166
 
164
167
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
168
+
169
+ 每次阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`;重试同一阶段时增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
@@ -21,7 +21,7 @@ disallowed-tools:
21
21
  - Bash(curl *)
22
22
  - Bash(codegraph *)
23
23
  ---
24
- <!-- generated by harness_deploy.py; core=5cadfa54663ecdbf; overlay=none; agent=claude-code; do not edit -->
24
+ <!-- generated by harness_deploy.py; core=89e664933ed69572; overlay=none; agent=claude-code; do not edit -->
25
25
  # harness-run — 需求编码
26
26
 
27
27
  ## Purpose
@@ -63,6 +63,7 @@ disallowed-tools:
63
63
  6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
64
64
  7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
65
65
  8. **禁止读取 `docs/superpowers/` 作为正式输入** — 旧草稿仅人工线索
66
+ 9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --base <baseCommit> --json`;`changedSegments=[]` 时复用已有 profile/rules/map/knowledge/change/code 指纹,不再重复跑全量 `harness-sync`、知识重建或代码库扫描。只有对应 segment 变化或缺失时才定向刷新;快照不能替代源码读取和验证门禁。
66
67
 
67
68
  状态目录分层:新路径优先,旧路径兼容 → [[../protocols/state-layout-protocol.md|state-layout-protocol]]
68
69
 
@@ -72,15 +73,17 @@ disallowed-tools:
72
73
 
73
74
  ## Workflow 概要
74
75
 
75
- 0. 加载上下文(change-name、spec/plan/detail/scenarios/ledger/run-task-status/worktree;`--fixback` 读 fixback)→ append `phase.start`
76
- 0.5. **测试基础设施探测**(先写 `CHECKING`,四项证据齐备后再结论)→ `reference.md` Step 0.5
76
+ 0. 加载上下文:先 `harness_change.py resolve [--change] --json`(多 active 缺参 → `CHANGE_SELECTION_REQUIRED`,禁止按 mtime 猜测);读 spec/plan/detail/scenarios/ledger/run-task-status/worktree;`--fixback` 读 fixback **`harness_gate.py begin --phase run --change <id>`**(内部 claim + phase.start + identity;禁止手工 Write `events.ndjson` / 手工 `phase.end`)
77
+ 0.5. **测试基础设施探测**(先写 `CHECKING`,四项证据齐备后再结论)→ `reference.md` Step 0.5;进入 TDD 前执行 `harness_test_guard.py begin --project . --change-dir ".harness/changes/<cn>" --json`
77
78
  1. **变更簇 TDD** — `protocols.md` `run-tdd-protocol`;批量 RED/GREEN;按需 `change-cluster-review-protocol`(高风险 + reviewer 预检可用)
78
- 2. 构建验证 + ledger(`harness_ledger.py diff-hash --change-dir` 纳入 ignored tests,`reference.md` Step 2c
79
+ 2. 构建验证 + **仅**通过 `harness_ledger.py record` 写 ledger(禁止 Write/Edit `verification-ledger.json`);`diff-hash --change-dir` 纳入 ignored tests → `reference.md` Step 2c
79
80
  3. **场景覆盖检查**(场景表映射,禁止用用例数冒充场景数)
80
- 4. **关门检查**(10 项)+ 计划状态持久化
81
+ 4. **关门检查**(10 项)→ `harness_test_guard.py close` → **`harness_gate.py close --phase run --change <id> --status <OK|WARN|FAIL>`**(内部 phase.end + 释放租约;close 失败不得用自然语言宣称成功)
81
82
 
82
83
  **Fixback**:`--fixback` 或用户要求时读 `reports/review/fixback-*.md`;RED 优先;未选用则记 `fixback: advisory-not-applied`。
83
84
 
85
+ **Foundation Gate**:若 `meta/implementation-checkpoints.json` 中 `foundation-gate` 为 pending,不得开始 plan 中任务 6+;由 `harness_gate.py` 硬阻断。
86
+
84
87
  ## P0 执行可信度规则
85
88
 
86
89
  - 命令结果不得靠猜测;普通 Bash 被拒 → 立即改用等价 PowerShell 重试一次
@@ -97,7 +100,8 @@ disallowed-tools:
97
100
  | **变更簇 TDD** | 一簇一次 RED/GREEN;低价值项豁免;新分支必须 RED |
98
101
  | **RED/GREEN** | RED 须有效;静态验证 ≠ 测试通过;greenfield 大重写豁免见 reference |
99
102
  | **Mapper/DB** | 纯 Mock 不得宣称 DB 验证通过;迁移脚本**永不自动执行** |
100
- | **探测/ledger** | 基础设施先探测;每次构建/测试写 ledger;用 canonical `diff-hash --change-dir` |
103
+ | **探测/ledger** | 基础设施先探测;每次构建/测试经 `harness_ledger.py record`;禁止手写 ledger JSON;用 canonical `diff-hash --change-dir` |
104
+ | **Gate/Guard** | 阶段边界只用 `harness_gate.py begin/close`;测试跟踪用 `harness_test_guard.py begin/close/record/stage` |
101
105
  | **预存变更** | 保留 → baseline 隔离;存在则最终 ≥ 🟡WARN |
102
106
  | **关门/状态** | 10 项关门检查;持久化 run-task-status;P0 静态-only 不得建议 submit |
103
107
  | **Worktree** | `requested=true` 时代码只写 worktree |
@@ -133,7 +137,7 @@ python <skills-root>/scripts/harness_test_guard.py record --project . --change-d
133
137
 
134
138
  ## 执行日志
135
139
 
136
- `events.ndjson` 为唯一事实源(schema_version 2,`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
140
+ `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
137
141
 
138
142
  ```powershell
139
143
  python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --note "<触发指令>"
@@ -142,3 +146,5 @@ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/cha
142
146
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
143
147
 
144
148
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
149
+
150
+ 每次阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`;重试同一阶段时增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
@@ -149,7 +149,7 @@ description: harness-run 的执行检查清单。仅在编码执行时读取。
149
149
  - [ ] 最终构建只执行一次,如果前面已有构建成功证据,可复用 verification-ledger
150
150
  - [ ] 判断是否需要全量测试:改了公共模块/数据访问层/数据库迁移/权限认证/接口层/数据契约,或用户要求 full-run-validation → 执行测试命令(按技术栈,如 Java 的 `mvn test -pl <module> -o`);否则跳过全量测试
151
151
  - [ ] 构建失败 → 先分析错误类型(见 reference.md 构建失败策略表)
152
- - [ ] **写入 verification-ledger.json**:`compile` 项必写(status/command/scope/evidence/时间戳/durationMs);若执行了测试命令则 `unitTest` 项必写(testsRun/failures/errors/skipped/evidence);未执行时标记 `NOT_RUN_BY_RUN`
152
+ - [ ] **经 `harness_ledger.py record` 写入 ledger**(禁止 Write/Edit `verification-ledger.json`):`compile` 项必写;若执行了测试则 `unitTest` 项必写;未执行时标记 `NOT_RUN_BY_RUN`
153
153
  - [ ] 顶层写入 `diffHash` / `currentHead` / `module` / `profile`;`diffHash` 必须执行 `harness_ledger.py diff-hash --repo . --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json`,纳入 test-tracking manifest 中的 ignored tests;`currentHead`=`git rev-parse HEAD`
154
154
  - [ ] test/submit/package 阶段如果 diffHash 一致,可复用 run 的 compile/unitTest 结果
155
155
 
@@ -231,7 +231,7 @@ description: harness-run 的执行检查清单。仅在编码执行时读取。
231
231
 
232
232
  ## 事件收尾记录
233
233
 
234
- - [ ] append `phase.end` 事件(`note` 含结束时间、耗时、结果、摘要、checkpoint commit 状态)
234
+ - [ ] append `phase.end` **仅**通过 `harness_gate.py close`(禁止手工 Edit `events.ndjson` / 直接 append phase.end 绕过 close 校验)
235
235
  - [ ] 如果存在 🟡静态验证 P0 场景 → 下一步必须写 `必须先运行 /harness-test`,不得并列"提交代码"
236
236
  - [ ] 如果存在数据库迁移/DB 验证未完成 → 最终不得输出纯 ✅OK
237
237
 
@@ -509,9 +509,9 @@ powershell.exe -Command "<测试命令> <模块定位参数>"
509
509
  - 如果 exit code 非 0 或无有效 stdout,标记为 ❌ 构建失败 / 状态未知
510
510
  - 如果是 TDD 降级(无测试基础设施),测试命令步骤跳过,标记 🟡 静态验证
511
511
 
512
- ### 2c. 写入 verification-ledger
512
+ ### 2c. 写入 verification-ledger(仅经 `harness_ledger.py record`)
513
513
 
514
- 步骤 2 完成后**必须**写入/更新 `.harness/changes/<change-name>/evidence/verification-ledger.json`:
514
+ 步骤 2 完成后**必须**通过 `harness_ledger.py record` 写入/更新 ledger(**禁止** Write/Edit `verification-ledger.json`):
515
515
 
516
516
  - `compile` 项:始终写入(status / command / scope / evidence / 时间戳 / durationMs)
517
517
  - `unitTest` 项:仅当 2b 执行了全量测试命令时写入(testsRun / failures / errors / skipped / evidence);未执行时标记 `{"status": "NOT_RUN_BY_RUN", "note": "轻量验证,全量单元测试由 harness-test 执行"}`
@@ -522,12 +522,15 @@ powershell.exe -Command "<测试命令> <模块定位参数>"
522
522
 
523
523
  ```powershell
524
524
  python <skills-root>/scripts/harness_ledger.py diff-hash --repo . --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json
525
+ python <skills-root>/scripts/harness_ledger.py record --change-dir ".harness/changes/<change-name>" --verification compile --status PASS --command "<cmd>" --exit-code 0 --json
525
526
  ```
526
527
 
527
528
  > `content-changeset-2` 同时读取 tracked diff、标准 untracked 文件和 manifest 的精确测试路径。manifest 缺失时保持普通行为;manifest 存在但路径越界、内容 hash 漂移或结构非法时命令失败,ledger 不可复用。checkpoint commit 不改变各路径的工作树内容,因此提交前后 hash 保持一致。
528
529
 
529
530
  > 这样 harness-test 的 Phase 1 可读取 ledger 判断是否复用 run 的 unitTest(diffHash commit-invariant + reuse 规则 #2 允许 HEAD 前移 → run 的 checkpoint commit 不破坏复用),submit 也可复用 compile 结果。详见 `../protocols/ledger-protocol.md`。
530
531
 
532
+ 阶段边界:`harness_gate.py begin/close`;测试跟踪:`harness_test_guard.py begin/close`。close 失败不得用自然语言覆盖。
533
+
531
534
  ## 步骤 3:场景覆盖检查
532
535
 
533
536
  对照场景表,逐条确认代码逻辑已覆盖,**并将覆盖结果展示给用户**。**状态必须三类标注**:
@@ -799,7 +802,7 @@ powershell.exe -Command "git -C '<project-path>' diff --check"
799
802
 
800
803
  ## 执行日志记录
801
804
 
802
- `/harness-run` 只向 `events.ndjson` 追加事件(schema_version 2);`logs/execution-log.md` 由 `harness_events.py append` 自动渲染。步骤 0 之前 append `phase.start`;各阶段写入 `command` / `verification` / `decision` / `issue`,人类可读摘要放 `note`。事件类型与脚本用法见 [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]] 与 SKILL.md `## 执行日志`。
805
+ `/harness-run` 只向 `events.ndjson` 追加事件(schema_version 3,兼容读取 v1/v2);`logs/execution-log.md` 由 `harness_events.py append` 自动渲染。步骤 0 之前 append `phase.start`;各阶段写入 `command` / `verification` / `decision` / `issue`,人类可读摘要放 `note`。事件类型与脚本用法见 [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]] 与 SKILL.md `## 执行日志`。
803
806
 
804
807
  关键 `note` / `decision` 须覆盖:测试基础设施探测(CHECKING→结论)、预存变更、run-tdd-protocol RED 类型、变更簇 RED/GREEN、批量构建 exit code、关门检查 10 项、计划状态持久化路径。
805
808
 
@@ -20,7 +20,7 @@ disallowed-tools:
20
20
  - Bash(awk *)
21
21
  - Bash(curl *)
22
22
  ---
23
- <!-- generated by harness_deploy.py; core=5cadfa54663ecdbf; overlay=none; agent=claude-code; do not edit -->
23
+ <!-- generated by harness_deploy.py; core=89e664933ed69572; overlay=none; agent=claude-code; do not edit -->
24
24
  # harness-submit — 最终提交(含 worktree 合并)
25
25
 
26
26
  ## Purpose
@@ -57,6 +57,7 @@ disallowed-tools:
57
57
  6. **implementation-detail** — 自适应执行参考;legacy 缺失 🟡WARN,不阻断
58
58
  7. **test-scenarios** — 测试真相源:`plans/<change>-test-scenarios.md`
59
59
  8. **禁止读取 `docs/superpowers/` 作为正式输入** — 旧草稿仅人工线索
60
+ 9. **每个 skill 边界只刷新一次状态快照** — 先运行 `python <skills-root>/scripts/harness_state.py capture --project . --change-dir ".harness/changes/<change-name>" --base <baseCommit> --json`;`changedSegments=[]` 时复用已有 profile/rules/map/knowledge/change/code 指纹,不再重复跑全量 `harness-sync`、知识重建或代码库扫描。只有对应 segment 变化或缺失时才定向刷新;快照不能替代源码读取和验证门禁。
60
61
 
61
62
  状态目录分层:新路径优先,旧路径兼容 → [[../protocols/state-layout-protocol.md|state-layout-protocol]]
62
63
 
@@ -66,18 +67,20 @@ disallowed-tools:
66
67
 
67
68
  ## Workflow
68
69
 
70
+ worktree 合并前必须运行 `harness_change.py integration-lock acquire --run-id <run-id> --json`;获取失败即停止。无论成功、冲突或异常,都在 `finally` 运行 `harness_change.py integration-lock release --run-id <run-id> --json`。持有 integration lock 后不得反向申请 change lease。
71
+
69
72
  **模式判定**:读 `meta/worktree.json`。`requested=false` → 步骤 0–7(主目录);`requested=true` → 步骤 0–6 在 worktree 执行,成功后**不结束**,接续「worktree 合并流程」。用户仅调用 `/harness-merge` 且 worktree 已有本地 commit 时,从合并流程步骤 M0 重入。
70
73
 
71
74
  ### 提交流程(步骤 0–7)
72
75
 
73
- 0. **启动准备** — 确定变更名;读 ledger,以 `harness_ledger.py diff-hash --repo . --base <baseCommit> --change-dir ".harness/changes/<change-name>" --json` 计算 diffHash + post-test 7 类分类;append `phase.start`
76
+ 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)
74
77
  1. **合并最新代码** — 主目录:`stash` → `pull --rebase` → `stash pop`;**worktree:N/A**(远端同步在合并段主分支完成)
75
- 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` 写回 ledger `unitTestFull` 项。增量 `unitTest` 永远不能冒充 `unitTestFull` 门禁。
78
+ 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` 门禁。
76
79
  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**。
77
80
  4. **提交方式** — 主目录:AskUserQuestion 三选项(commit+push / 仅本地 / 取消);**worktree:固定仅本地 commit**
78
81
  5. **commit-message.txt** ⚠️ — 展示 staged、diff stat、完整中文 message;用户确认
79
82
  6. **commit / push** — `git commit -F`;主目录按选项 push(push 前 fetch 检查远端);**worktree:只 commit,记录 local hash**
80
- 7. **收尾引导**主目录:可选 worktree 清理 + 提示 `/harness-archive`;**worktree:接续下方合并流程**
83
+ 7. **收尾****`harness_gate.py close --phase submit --status ...`**;主目录:可选 worktree 清理 + 提示 `/harness-archive`;**worktree:接续下方合并流程**
81
84
 
82
85
  详细步骤见 `checklist.md`。
83
86
 
@@ -91,7 +94,7 @@ M4. **冲突处理** — 若 `CONFLICT` → **停下**,列出冲突文件,
91
94
  M5. **合并后验证** — 他人提交引入 → 必须重跑构建+测试;否则 ledger 复用 🔁REUSED
92
95
  M6. **push 主分支** — fetch 后 `log HEAD..@{u}` 非空则回 M2;否则 push,记录 `mergeFinalHash`
93
96
  M7. **清理 worktree** — `worktree remove` + `branch -D`(Windows 兜底见 `reference.md`);更新 `worktree.json`(`created=false` + removedAt 等)
94
- M8. **ledger + 收尾** — 写入 `mergeFinalHash`;append `phase.end`;提示 `/harness-archive`
97
+ M8. **ledger + 收尾** — 经 `harness_ledger.py record` 写入 `mergeFinalHash`;**`harness_gate.py close --phase merge`**(禁止手工 phase.end);提示 `/harness-archive`
95
98
 
96
99
  ## P0 执行可信度规则
97
100
 
@@ -150,7 +153,7 @@ git 经 PowerShell;commit/报告不得含明文密钥。遵循 `../protocols/s
150
153
 
151
154
  ## 执行日志
152
155
 
153
- `events.ndjson` 为唯一事实源(schema_version 2,`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
156
+ `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
154
157
 
155
158
  ```powershell
156
159
  python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --note "<触发指令>"
@@ -159,3 +162,5 @@ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/cha
159
162
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
160
163
 
161
164
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
165
+
166
+ 每次阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`;重试同一阶段时增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。
@@ -19,7 +19,7 @@ disallowed-tools:
19
19
  - Bash(awk *)
20
20
  - Bash(curl *)
21
21
  ---
22
- <!-- generated by harness_deploy.py; core=5cadfa54663ecdbf; overlay=none; agent=claude-code; do not edit -->
22
+ <!-- generated by harness_deploy.py; core=89e664933ed69572; overlay=none; agent=claude-code; do not edit -->
23
23
  # harness-sync — 元数据同步
24
24
 
25
25
  ## Purpose
@@ -39,7 +39,7 @@ disallowed-tools:
39
39
  | 2 | CodeGraph 索引是否需重建 |
40
40
  | 3 | `.harness/codebase/map/` 是否过期 → 报告建议 `/harness-codebase-map` |
41
41
  | 3.5 | `harness_knowledge.py sync`;可 `sync --update`;失败不得假装可用。**知识闭环主入口**是 `/harness-knowledge-ingest auto`(含 Agent judge),sync 不重复列人工知识待办 |
42
- | 3.6 | 扫描 `.harness/knowledge/maintenance-outbox/{pending,failed}`;对每项运行 `harness_knowledge.py maintain --project . --archive-id <id> --json`(§8.2:archive close 只 enqueue,sync 异步推进 outbox 到 completed/completed_rules_pending_judge) |
42
+ | 3.6 | 单次运行 `harness_knowledge.py maintain --project . --drain --json`,有界推进全部 `.harness/knowledge/maintenance-outbox/{pending,failed}`;不得为每个条目重复启动 Python/重建索引(§8.2:archive close 只 enqueue,sync 异步推进 outbox 到 completed/pending-judge) |
43
43
  | 4 | CLAUDE.md 完整性/行数 → 超限 AskUserQuestion 瘦身 |
44
44
  | 5 | AGENTS.md 与 CLAUDE.md 一致 |
45
45
  | 6 | `.harness/` 结构(init 规程 → `reference.md` 第 6 步);可选 `harness_deploy.py diff` 检查已装 skill 是否过期 |
@@ -71,7 +71,7 @@ disallowed-tools:
71
71
 
72
72
  ## 执行日志
73
73
 
74
- `events.ndjson` 为唯一事实源(schema_version 2,`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
74
+ `events.ndjson` 为唯一事实源(schema_version 3,兼容读取 v1/v2;`note` 承载人类可读摘要);`logs/execution-log.md` 由 `harness_events.py` 渲染,**禁止用 Write/Edit 直接维护**。直接修改的内容会在 `phase.end` 或 finalize 时被完整重建覆盖,属于数据丢失;需要保留的详情必须进入事件 `note`。结构 → [[../protocols/report-pipeline-protocol.md|report-pipeline-protocol]]
75
75
 
76
76
  ```powershell
77
77
  python <skills-root>/scripts/harness_events.py append --change-dir ".harness/changes/<change-name>" --phase <phase> --type phase.start --note "<触发指令>"
@@ -80,3 +80,5 @@ python <skills-root>/scripts/harness_events.py append --change-dir ".harness/cha
80
80
  > **脚本接线**:`harness_events.py append`;`harness_archive.py finalize`;`harness_preflight.py check`;`harness_ledger.py can-reuse`;`harness_service.py ensure/stop`(须 `--files`/`serviceStart.inputFiles`)。JSON 输出按 D13 护栏解读。
81
81
 
82
82
  > **Task 4 §6.1 写入契约**:普通 `append` = 加锁 -> 追加一行 -> fsync -> 解锁,**不 load 历史、不渲染**(O(1),跨进程锁 `events.ndjson.lock`,UUID 用完整 `uuid4().hex` 无需去重扫描)。仅 `--type phase.end` append 在追加成功后渲染一次 `execution-log.md`;显式 `harness_events.py render` 随时从完整 events 重建;`harness_archive.py finalize` 在 collect 前强制 render 一次。高频 command append 期间 log 可能滞后,phase 边界保持最新。
83
+
84
+ 每次阶段结束必须写 `--status OK|WARN|FAIL|BLOCKED`;重试同一阶段时增加 `--attempt <n>`,不得覆盖或伪装成一次执行。跨工具继续执行时写 `--executor-tool <codex|claude-code|codebuddy|cursor>`,并在接棒事件写 `--handoff-from-tool` / `--handoff-reason`;也可由 `HUNTER_HARNESS_TOOL/AGENT/MODEL/RUN_ID` 环境变量统一注入。