@hunter-harness/workflow-harness 0.2.11 → 0.2.12

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/contracts/ci-metrics.schema.json +36 -0
  3. package/harness/bundles/general/claude-code/contracts/workflow-policy.json +30 -0
  4. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
  5. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
  6. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  7. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +4 -4
  9. package/harness/bundles/general/claude-code/harness-plan/checklist.md +6 -0
  10. package/harness/bundles/general/claude-code/harness-plan/reference.md +7 -2
  11. package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
  12. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-run/checklist.md +3 -2
  14. package/harness/bundles/general/claude-code/harness-run/reference.md +6 -4
  15. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
  16. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  17. package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
  18. package/harness/bundles/general/claude-code/scripts/harness_archive.py +282 -120
  19. package/harness/bundles/general/claude-code/scripts/harness_events.py +400 -24
  20. package/harness/bundles/general/claude-code/scripts/harness_gate.py +585 -21
  21. package/harness/bundles/general/claude-code/scripts/harness_integration.py +403 -18
  22. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +225 -29
  23. package/harness/bundles/general/claude-code/scripts/harness_phase.py +926 -0
  24. package/harness/bundles/general/claude-code/scripts/harness_plan_finalize.py +361 -0
  25. package/harness/bundles/general/claude-code/scripts/harness_profile.py +50 -0
  26. package/harness/bundles/general/claude-code/scripts/harness_runtime.py +248 -0
  27. package/harness/bundles/general/claude-code/scripts/harness_state.py +15 -2
  28. package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +188 -0
  29. package/harness/bundles/general/claude-code/scripts/harness_workflow_policy.py +19 -0
  30. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  31. package/harness/bundles/general/codebuddy/contracts/ci-metrics.schema.json +36 -0
  32. package/harness/bundles/general/codebuddy/contracts/workflow-policy.json +30 -0
  33. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  34. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  35. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  36. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  37. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +4 -4
  38. package/harness/bundles/general/codebuddy/harness-plan/checklist.md +6 -0
  39. package/harness/bundles/general/codebuddy/harness-plan/reference.md +7 -2
  40. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
  41. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  42. package/harness/bundles/general/codebuddy/harness-run/checklist.md +3 -2
  43. package/harness/bundles/general/codebuddy/harness-run/reference.md +6 -4
  44. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
  45. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  46. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
  47. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +282 -120
  48. package/harness/bundles/general/codebuddy/scripts/harness_events.py +400 -24
  49. package/harness/bundles/general/codebuddy/scripts/harness_gate.py +585 -21
  50. package/harness/bundles/general/codebuddy/scripts/harness_integration.py +403 -18
  51. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +225 -29
  52. package/harness/bundles/general/codebuddy/scripts/harness_phase.py +926 -0
  53. package/harness/bundles/general/codebuddy/scripts/harness_plan_finalize.py +361 -0
  54. package/harness/bundles/general/codebuddy/scripts/harness_profile.py +50 -0
  55. package/harness/bundles/general/codebuddy/scripts/harness_runtime.py +248 -0
  56. package/harness/bundles/general/codebuddy/scripts/harness_state.py +15 -2
  57. package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +188 -0
  58. package/harness/bundles/general/codebuddy/scripts/harness_workflow_policy.py +19 -0
  59. package/harness/bundles/general/codex/.harness-build.json +1 -1
  60. package/harness/bundles/general/codex/contracts/ci-metrics.schema.json +36 -0
  61. package/harness/bundles/general/codex/contracts/workflow-policy.json +30 -0
  62. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  63. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  64. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  65. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  66. package/harness/bundles/general/codex/harness-plan/SKILL.md +4 -4
  67. package/harness/bundles/general/codex/harness-plan/checklist.md +6 -0
  68. package/harness/bundles/general/codex/harness-plan/reference.md +7 -2
  69. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  70. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  71. package/harness/bundles/general/codex/harness-run/checklist.md +3 -2
  72. package/harness/bundles/general/codex/harness-run/reference.md +6 -4
  73. package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
  74. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  75. package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
  76. package/harness/bundles/general/codex/scripts/harness_archive.py +282 -120
  77. package/harness/bundles/general/codex/scripts/harness_events.py +400 -24
  78. package/harness/bundles/general/codex/scripts/harness_gate.py +585 -21
  79. package/harness/bundles/general/codex/scripts/harness_integration.py +403 -18
  80. package/harness/bundles/general/codex/scripts/harness_ledger.py +225 -29
  81. package/harness/bundles/general/codex/scripts/harness_phase.py +926 -0
  82. package/harness/bundles/general/codex/scripts/harness_plan_finalize.py +361 -0
  83. package/harness/bundles/general/codex/scripts/harness_profile.py +50 -0
  84. package/harness/bundles/general/codex/scripts/harness_runtime.py +248 -0
  85. package/harness/bundles/general/codex/scripts/harness_state.py +15 -2
  86. package/harness/bundles/general/codex/scripts/harness_test_guard.py +188 -0
  87. package/harness/bundles/general/codex/scripts/harness_workflow_policy.py +19 -0
  88. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  89. package/harness/bundles/general/cursor/contracts/ci-metrics.schema.json +36 -0
  90. package/harness/bundles/general/cursor/contracts/workflow-policy.json +30 -0
  91. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  92. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  93. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  94. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  95. package/harness/bundles/general/cursor/harness-plan/SKILL.md +4 -4
  96. package/harness/bundles/general/cursor/harness-plan/checklist.md +6 -0
  97. package/harness/bundles/general/cursor/harness-plan/reference.md +7 -2
  98. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  99. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  100. package/harness/bundles/general/cursor/harness-run/checklist.md +3 -2
  101. package/harness/bundles/general/cursor/harness-run/reference.md +6 -4
  102. package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
  103. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  104. package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
  105. package/harness/bundles/general/cursor/scripts/harness_archive.py +282 -120
  106. package/harness/bundles/general/cursor/scripts/harness_events.py +400 -24
  107. package/harness/bundles/general/cursor/scripts/harness_gate.py +585 -21
  108. package/harness/bundles/general/cursor/scripts/harness_integration.py +403 -18
  109. package/harness/bundles/general/cursor/scripts/harness_ledger.py +225 -29
  110. package/harness/bundles/general/cursor/scripts/harness_phase.py +926 -0
  111. package/harness/bundles/general/cursor/scripts/harness_plan_finalize.py +361 -0
  112. package/harness/bundles/general/cursor/scripts/harness_profile.py +50 -0
  113. package/harness/bundles/general/cursor/scripts/harness_runtime.py +248 -0
  114. package/harness/bundles/general/cursor/scripts/harness_state.py +15 -2
  115. package/harness/bundles/general/cursor/scripts/harness_test_guard.py +188 -0
  116. package/harness/bundles/general/cursor/scripts/harness_workflow_policy.py +19 -0
  117. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  118. package/harness/bundles/java/claude-code/contracts/ci-metrics.schema.json +36 -0
  119. package/harness/bundles/java/claude-code/contracts/workflow-policy.json +30 -0
  120. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  121. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  122. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  123. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  124. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  125. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  126. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +4 -4
  127. package/harness/bundles/java/claude-code/harness-plan/checklist.md +6 -0
  128. package/harness/bundles/java/claude-code/harness-plan/reference.md +7 -2
  129. package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
  130. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  131. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
  132. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  133. package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
  134. package/harness/bundles/java/claude-code/scripts/harness_archive.py +282 -120
  135. package/harness/bundles/java/claude-code/scripts/harness_events.py +400 -24
  136. package/harness/bundles/java/claude-code/scripts/harness_gate.py +585 -21
  137. package/harness/bundles/java/claude-code/scripts/harness_integration.py +403 -18
  138. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +225 -29
  139. package/harness/bundles/java/claude-code/scripts/harness_phase.py +926 -0
  140. package/harness/bundles/java/claude-code/scripts/harness_plan_finalize.py +361 -0
  141. package/harness/bundles/java/claude-code/scripts/harness_profile.py +50 -0
  142. package/harness/bundles/java/claude-code/scripts/harness_runtime.py +248 -0
  143. package/harness/bundles/java/claude-code/scripts/harness_state.py +15 -2
  144. package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +188 -0
  145. package/harness/bundles/java/claude-code/scripts/harness_workflow_policy.py +19 -0
  146. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  147. package/harness/bundles/java/codebuddy/contracts/ci-metrics.schema.json +36 -0
  148. package/harness/bundles/java/codebuddy/contracts/workflow-policy.json +30 -0
  149. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  150. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  151. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  152. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  153. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  154. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  155. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +4 -4
  156. package/harness/bundles/java/codebuddy/harness-plan/checklist.md +6 -0
  157. package/harness/bundles/java/codebuddy/harness-plan/reference.md +7 -2
  158. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
  159. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  160. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
  161. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  162. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
  163. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +282 -120
  164. package/harness/bundles/java/codebuddy/scripts/harness_events.py +400 -24
  165. package/harness/bundles/java/codebuddy/scripts/harness_gate.py +585 -21
  166. package/harness/bundles/java/codebuddy/scripts/harness_integration.py +403 -18
  167. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +225 -29
  168. package/harness/bundles/java/codebuddy/scripts/harness_phase.py +926 -0
  169. package/harness/bundles/java/codebuddy/scripts/harness_plan_finalize.py +361 -0
  170. package/harness/bundles/java/codebuddy/scripts/harness_profile.py +50 -0
  171. package/harness/bundles/java/codebuddy/scripts/harness_runtime.py +248 -0
  172. package/harness/bundles/java/codebuddy/scripts/harness_state.py +15 -2
  173. package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +188 -0
  174. package/harness/bundles/java/codebuddy/scripts/harness_workflow_policy.py +19 -0
  175. package/harness/bundles/java/codex/.harness-build.json +1 -1
  176. package/harness/bundles/java/codex/contracts/ci-metrics.schema.json +36 -0
  177. package/harness/bundles/java/codex/contracts/workflow-policy.json +30 -0
  178. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  179. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  180. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  181. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  182. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  183. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  184. package/harness/bundles/java/codex/harness-plan/SKILL.md +4 -4
  185. package/harness/bundles/java/codex/harness-plan/checklist.md +6 -0
  186. package/harness/bundles/java/codex/harness-plan/reference.md +7 -2
  187. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  188. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  189. package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
  190. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  191. package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
  192. package/harness/bundles/java/codex/scripts/harness_archive.py +282 -120
  193. package/harness/bundles/java/codex/scripts/harness_events.py +400 -24
  194. package/harness/bundles/java/codex/scripts/harness_gate.py +585 -21
  195. package/harness/bundles/java/codex/scripts/harness_integration.py +403 -18
  196. package/harness/bundles/java/codex/scripts/harness_ledger.py +225 -29
  197. package/harness/bundles/java/codex/scripts/harness_phase.py +926 -0
  198. package/harness/bundles/java/codex/scripts/harness_plan_finalize.py +361 -0
  199. package/harness/bundles/java/codex/scripts/harness_profile.py +50 -0
  200. package/harness/bundles/java/codex/scripts/harness_runtime.py +248 -0
  201. package/harness/bundles/java/codex/scripts/harness_state.py +15 -2
  202. package/harness/bundles/java/codex/scripts/harness_test_guard.py +188 -0
  203. package/harness/bundles/java/codex/scripts/harness_workflow_policy.py +19 -0
  204. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  205. package/harness/bundles/java/cursor/contracts/ci-metrics.schema.json +36 -0
  206. package/harness/bundles/java/cursor/contracts/workflow-policy.json +30 -0
  207. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  208. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  209. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  210. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  211. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  212. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  213. package/harness/bundles/java/cursor/harness-plan/SKILL.md +4 -4
  214. package/harness/bundles/java/cursor/harness-plan/checklist.md +6 -0
  215. package/harness/bundles/java/cursor/harness-plan/reference.md +7 -2
  216. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  217. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  218. package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
  219. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  220. package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
  221. package/harness/bundles/java/cursor/scripts/harness_archive.py +282 -120
  222. package/harness/bundles/java/cursor/scripts/harness_events.py +400 -24
  223. package/harness/bundles/java/cursor/scripts/harness_gate.py +585 -21
  224. package/harness/bundles/java/cursor/scripts/harness_integration.py +403 -18
  225. package/harness/bundles/java/cursor/scripts/harness_ledger.py +225 -29
  226. package/harness/bundles/java/cursor/scripts/harness_phase.py +926 -0
  227. package/harness/bundles/java/cursor/scripts/harness_plan_finalize.py +361 -0
  228. package/harness/bundles/java/cursor/scripts/harness_profile.py +50 -0
  229. package/harness/bundles/java/cursor/scripts/harness_runtime.py +248 -0
  230. package/harness/bundles/java/cursor/scripts/harness_state.py +15 -2
  231. package/harness/bundles/java/cursor/scripts/harness_test_guard.py +188 -0
  232. package/harness/bundles/java/cursor/scripts/harness_workflow_policy.py +19 -0
  233. package/harness/manifests/general/claude-code.json +42 -26
  234. package/harness/manifests/general/codebuddy.json +42 -26
  235. package/harness/manifests/general/codex.json +42 -26
  236. package/harness/manifests/general/cursor.json +42 -26
  237. package/harness/manifests/java/claude-code.json +42 -26
  238. package/harness/manifests/java/codebuddy.json +42 -26
  239. package/harness/manifests/java/codex.json +42 -26
  240. package/harness/manifests/java/cursor.json +42 -26
  241. package/hunter-workflow-family.json +2 -2
  242. package/package.json +1 -1
@@ -266,6 +266,8 @@ def capture_current_state(
266
266
  segment_files=files,
267
267
  )
268
268
  changed: list[str] = []
269
+ baseline_created = previous is None
270
+ unresolved: list[str] = []
269
271
  if previous:
270
272
  old_segments = previous.get("segments") or {}
271
273
  for name, segment in fresh["segments"].items():
@@ -275,7 +277,12 @@ def capture_current_state(
275
277
  else:
276
278
  changed.append(name)
277
279
  else:
278
- changed = list(fresh["segments"])
280
+ # A first observation establishes the baseline; it is not evidence
281
+ # that every segment changed during the current phase.
282
+ unresolved = sorted(fresh["segments"])
283
+ fresh["baselineCreated"] = baseline_created
284
+ fresh["changedSegments"] = sorted(changed)
285
+ fresh["unresolvedSegments"] = unresolved
279
286
  write_snapshot(change_dir, fresh)
280
287
  return fresh, changed
281
288
 
@@ -312,7 +319,13 @@ def main(argv: list[str] | None = None) -> int:
312
319
  "ok": True,
313
320
  "path": str(snapshot_path(change_dir)),
314
321
  "changedSegments": changed,
315
- "reusedSegments": sorted(set(snapshot["segments"]) - set(changed)),
322
+ "reusedSegments": sorted(
323
+ set(snapshot["segments"])
324
+ - set(changed)
325
+ - set(snapshot.get("unresolvedSegments") or [])
326
+ ),
327
+ "baselineCreated": bool(snapshot.get("baselineCreated")),
328
+ "unresolvedSegments": list(snapshot.get("unresolvedSegments") or []),
316
329
  "git": snapshot["git"],
317
330
  }
318
331
  if args.json:
@@ -564,6 +564,159 @@ def record(
564
564
  return _result(True, action, "RECORDED", [rel for _, rel in validated], manifestPath=str(manifest_path))
565
565
 
566
566
 
567
+ def rehome(
568
+ from_project: Path | str,
569
+ to_project: Path | str,
570
+ change_dir: Path | str,
571
+ expected_head: str,
572
+ ) -> dict[str, Any]:
573
+ """Atomically hand test ownership from a merged feature worktree to target."""
574
+ action = "rehome"
575
+ from_root = Path(from_project).resolve()
576
+ to_root = Path(to_project).resolve()
577
+ if not from_root.is_dir() or not to_root.is_dir():
578
+ return _result(False, action, "PROJECT_ROOT_MISSING", [])
579
+ if harness_paths.repository_identity(from_root) != harness_paths.repository_identity(to_root):
580
+ return _result(False, action, "REPOSITORY_MISMATCH", [])
581
+ to_head_result = _git(to_root, "rev-parse", "--verify", "HEAD")
582
+ to_head = to_head_result.stdout.strip() if to_head_result.returncode == 0 else ""
583
+ if not expected_head or to_head != expected_head:
584
+ return _result(
585
+ False, action, "EXPECTED_HEAD_MISMATCH", [],
586
+ expectedHead=expected_head, actualHead=to_head,
587
+ )
588
+ from_head_result = _git(from_root, "rev-parse", "--verify", "HEAD")
589
+ from_head = from_head_result.stdout.strip() if from_head_result.returncode == 0 else ""
590
+ from_tree_result = _git(from_root, "rev-parse", "HEAD^{tree}")
591
+ to_tree_result = _git(to_root, "rev-parse", f"{expected_head}^{{tree}}")
592
+ from_tree = from_tree_result.stdout.strip() if from_tree_result.returncode == 0 else ""
593
+ to_tree = to_tree_result.stdout.strip() if to_tree_result.returncode == 0 else ""
594
+ if not from_tree or from_tree != to_tree:
595
+ return _result(
596
+ False, action, "TREE_MISMATCH", [],
597
+ fromHead=from_head, toHead=to_head, fromTree=from_tree, toTree=to_tree,
598
+ )
599
+
600
+ change_root = _change_dir(from_root, change_dir)
601
+ if change_root is None:
602
+ return _result(False, action, "CHANGE_DIR_OUTSIDE_PROJECT", [])
603
+ manifest_path = _manifest_path(change_root)
604
+ if manifest_path is None:
605
+ return _result(False, action, "MANIFEST_PATH_OUTSIDE_PROJECT", [])
606
+ lock_path = manifest_path.with_name(manifest_path.name + ".lock")
607
+ try:
608
+ with _exclusive_lock(lock_path, wait_seconds=5.0):
609
+ try:
610
+ manifest = _read_json(manifest_path)
611
+ except FileNotFoundError:
612
+ return _result(False, action, "MANIFEST_MISSING", [])
613
+ except (OSError, json.JSONDecodeError) as exc:
614
+ return _result(False, action, "MANIFEST_INVALID", [], error=str(exc))
615
+ is_v2 = isinstance(manifest, dict) and manifest.get("schemaVersion") == 2
616
+ entries = manifest.get("files") if isinstance(manifest, dict) else None
617
+ if not isinstance(entries, list):
618
+ return _result(False, action, "MANIFEST_INVALID", [])
619
+ if not is_v2 and (
620
+ manifest.get("schemaVersion") != SCHEMA_VERSION
621
+ or manifest.get("mode") != MODE
622
+ or manifest.get("projectRoot") != str(from_root)
623
+ ):
624
+ return _result(False, action, "MANIFEST_PROJECT_MISMATCH", [])
625
+ if is_v2:
626
+ error, validated = _validate_existing_manifest_v2(
627
+ from_root, manifest, require_files=False
628
+ )
629
+ if error:
630
+ return _result(False, action, error, [])
631
+ else:
632
+ validated: dict[str, dict[str, Any]] = {}
633
+ for item in entries:
634
+ if not _entry_shape_valid(item):
635
+ return _result(False, action, "MANIFEST_INVALID", [])
636
+ rel = item["path"]
637
+ source, normalized, error = _validate_file(from_root, rel)
638
+ if error or normalized != rel or source is None:
639
+ return _result(False, action, error or "MANIFEST_INVALID", [rel])
640
+ if item["sha256"] != _sha256(source):
641
+ return _result(False, action, "HASH_DRIFT", [rel])
642
+ validated[rel] = dict(item)
643
+
644
+ updated = json.loads(json.dumps(manifest))
645
+ updated_entries: list[dict[str, Any]] = []
646
+ for rel, item in sorted(validated.items()):
647
+ target, normalized, error = _validate_file(to_root, rel)
648
+ if error or normalized != rel or target is None:
649
+ return _result(False, action, "TARGET_CONTENT_MISMATCH", [rel])
650
+ replacement = dict(item)
651
+ if is_v2:
652
+ digest = logical_file_hash(to_root, rel)
653
+ source_digest = item.get("logicalHash") or item.get("binaryHash")
654
+ if digest != source_digest:
655
+ return _result(False, action, "TARGET_CONTENT_MISMATCH", [rel])
656
+ replacement["logicalHash"] = digest
657
+ replacement["binaryHash"] = (
658
+ None if digest.startswith("gitblob:") else digest
659
+ )
660
+ replacement["ignored"] = _is_ignored(to_root, rel)
661
+ else:
662
+ digest = _sha256(target)
663
+ if digest != item["sha256"]:
664
+ return _result(False, action, "TARGET_CONTENT_MISMATCH", [rel])
665
+ replacement["sha256"] = digest
666
+ replacement["ignored"] = _is_ignored(to_root, rel)
667
+ replacement["trackedBefore"] = (
668
+ _git(to_root, "ls-files", "--error-unmatch", "--", rel).returncode == 0
669
+ )
670
+ updated_entries.append(replacement)
671
+
672
+ before_hash = _sha256(manifest_path)
673
+ handoff_at = time.strftime("%Y-%m-%dT%H:%M:%S")
674
+ handoff_id = "handoff-" + hashlib.sha256(
675
+ f"{from_root}\0{to_root}\0{from_head}\0{to_head}".encode("utf-8")
676
+ ).hexdigest()[:20]
677
+ handoffs = updated.get("handoffs")
678
+ if handoffs is None:
679
+ handoffs = []
680
+ if not isinstance(handoffs, list):
681
+ return _result(False, action, "MANIFEST_INVALID", [])
682
+ handoff = {
683
+ "id": handoff_id,
684
+ "fromRoot": str(from_root),
685
+ "toRoot": str(to_root),
686
+ "fromHead": from_head,
687
+ "toHead": to_head,
688
+ "expectedHead": expected_head,
689
+ "treeHash": to_tree,
690
+ "at": handoff_at,
691
+ "manifestHashBefore": before_hash,
692
+ }
693
+ if not any(isinstance(item, dict) and item.get("id") == handoff_id for item in handoffs):
694
+ handoffs.append(handoff)
695
+ updated["files"] = updated_entries
696
+ updated["projectRoot"] = str(to_root)
697
+ updated["head"] = to_head
698
+ updated["handoffs"] = handoffs
699
+ _write_json(manifest_path, updated)
700
+ after_hash = _sha256(manifest_path)
701
+ except LockUnavailable:
702
+ return _result(False, action, "MANIFEST_LOCKED", [])
703
+ return _result(
704
+ True,
705
+ action,
706
+ "REHOMED",
707
+ sorted(validated),
708
+ fromRoot=str(from_root),
709
+ toRoot=str(to_root),
710
+ fromHead=from_head,
711
+ toHead=to_head,
712
+ treeHash=to_tree,
713
+ handoffId=handoff_id,
714
+ manifestHashBefore=before_hash,
715
+ manifestHashAfter=after_hash,
716
+ manifestPath=str(manifest_path),
717
+ )
718
+
719
+
567
720
  def _stage_locked(
568
721
  project_root: Path, change_root: Path, manifest_path: Path, index_path: Path
569
722
  ) -> dict[str, Any]:
@@ -709,6 +862,31 @@ def begin(project: Path | str, change_dir: Path | str) -> dict[str, Any]:
709
862
  if not _manifest_target_inside(change_root, snapshot_path):
710
863
  return _result(False, action, "SNAPSHOT_PATH_OUTSIDE_PROJECT", [])
711
864
 
865
+ if snapshot_path.is_file():
866
+ try:
867
+ snapshot = _read_json(snapshot_path)
868
+ except (OSError, json.JSONDecodeError) as exc:
869
+ return _result(False, action, "SNAPSHOT_INVALID", [], error=str(exc))
870
+ entries = snapshot.get("files") if isinstance(snapshot, dict) else None
871
+ if (
872
+ not isinstance(snapshot, dict)
873
+ or snapshot.get("schemaVersion") != SCHEMA_VERSION
874
+ or snapshot.get("mode") != MODE
875
+ or snapshot.get("projectRoot") != str(project_root)
876
+ or not isinstance(entries, list)
877
+ or any(not isinstance(item, dict) or not isinstance(item.get("path"), str)
878
+ for item in entries)
879
+ ):
880
+ return _result(False, action, "SNAPSHOT_INVALID", [])
881
+ return _result(
882
+ True,
883
+ action,
884
+ "SNAPSHOT_REUSED",
885
+ [item["path"] for item in entries],
886
+ snapshotPath=str(snapshot_path),
887
+ fileCount=len(entries),
888
+ )
889
+
712
890
  files = _enumerate_allowed_test_files(project_root)
713
891
  snapshot = {
714
892
  "schemaVersion": SCHEMA_VERSION,
@@ -867,6 +1045,12 @@ def main(argv: list[str] | None = None) -> int:
867
1045
  close_parser.add_argument("--project", required=True)
868
1046
  close_parser.add_argument("--change-dir", required=True)
869
1047
  close_parser.add_argument("--json", action="store_true")
1048
+ rehome_parser = sub.add_parser("rehome")
1049
+ rehome_parser.add_argument("--from", dest="from_project", required=True)
1050
+ rehome_parser.add_argument("--to", dest="to_project", required=True)
1051
+ rehome_parser.add_argument("--change-dir", required=True)
1052
+ rehome_parser.add_argument("--expected-head", required=True)
1053
+ rehome_parser.add_argument("--json", action="store_true")
870
1054
  mark_parser = sub.add_parser("mark")
871
1055
  mark_parser.add_argument("--project", required=True)
872
1056
  mark_parser.add_argument("--change-dir", required=True)
@@ -883,6 +1067,10 @@ def main(argv: list[str] | None = None) -> int:
883
1067
  elif args.action == "mark":
884
1068
  files = [item.strip() for item in args.files.split(",") if item.strip()]
885
1069
  result = mark(args.project, args.change_dir, files)
1070
+ elif args.action == "rehome":
1071
+ result = rehome(
1072
+ args.from_project, args.to_project, args.change_dir, args.expected_head
1073
+ )
886
1074
  else:
887
1075
  result = stage(args.project, args.change_dir)
888
1076
  print(json.dumps(result, ensure_ascii=False, indent=2 if args.json else None))
@@ -19,6 +19,8 @@ TOP_LEVEL_KEYS = frozenset(
19
19
  "skills",
20
20
  "requiredArtifacts",
21
21
  "requiredValidations",
22
+ "validationPhases",
23
+ "capabilityGates",
22
24
  "conditionalStages",
23
25
  "interactionWhitelist",
24
26
  "checkpointRules",
@@ -48,6 +50,9 @@ SKILL_KEYS = frozenset(
48
50
  )
49
51
 
50
52
  CONDITIONAL_STAGE_KEYS = frozenset({"tiers", "signals"})
53
+ CAPABILITY_GATE_KEYS = frozenset(
54
+ {"signals", "requiredStages", "requiredValidations"}
55
+ )
51
56
  CHECKPOINT_RULE_KEYS = frozenset(
52
57
  {
53
58
  "afterTasks",
@@ -121,6 +126,20 @@ def validate_policy(data: Any) -> dict[str, Any]:
121
126
  for phase, items in section_data.items():
122
127
  _require_type(items, list, f"{section}.{phase}")
123
128
 
129
+ validation_phases = data["validationPhases"]
130
+ _require_type(validation_phases, dict, "validationPhases")
131
+ for verification, phase in validation_phases.items():
132
+ _require_type(phase, str, f"validationPhases.{verification}")
133
+
134
+ capability_gates = data["capabilityGates"]
135
+ _require_type(capability_gates, dict, "capabilityGates")
136
+ for capability, gate in capability_gates.items():
137
+ path = f"capabilityGates.{capability}"
138
+ _require_type(gate, dict, path)
139
+ _reject_unknown(gate, CAPABILITY_GATE_KEYS, path)
140
+ for key in CAPABILITY_GATE_KEYS:
141
+ _require_type(gate[key], list, f"{path}.{key}")
142
+
124
143
  conditional = data["conditionalStages"]
125
144
  _require_type(conditional, dict, "conditionalStages")
126
145
  for stage_name, stage in conditional.items():
@@ -2,5 +2,5 @@
2
2
  "schemaVersion": 1,
3
3
  "overlay": "java",
4
4
  "agent": "cursor",
5
- "coreHash": "0bc98072234275dd"
5
+ "coreHash": "2adf80c5975eb711"
6
6
  }
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://hunter-harness.dev/contracts/ci-metrics.schema.json",
4
+ "title": "Hunter Harness CI Metrics",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "schemaVersion",
9
+ "runner",
10
+ "source",
11
+ "suites",
12
+ "passed",
13
+ "failed",
14
+ "skipped",
15
+ "setupErrors",
16
+ "durationMs",
17
+ "headSha"
18
+ ],
19
+ "properties": {
20
+ "schemaVersion": { "const": 1 },
21
+ "runner": { "enum": ["junit", "vitest", "playwright"] },
22
+ "source": { "type": ["string", "null"] },
23
+ "suites": { "type": ["integer", "null"], "minimum": 0 },
24
+ "passed": { "type": ["integer", "null"], "minimum": 0 },
25
+ "failed": { "type": ["integer", "null"], "minimum": 0 },
26
+ "skipped": { "type": ["integer", "null"], "minimum": 0 },
27
+ "setupErrors": { "type": ["integer", "null"], "minimum": 0 },
28
+ "durationMs": { "type": ["integer", "null"], "minimum": 0 },
29
+ "headSha": {
30
+ "anyOf": [
31
+ { "type": "null" },
32
+ { "type": "string", "pattern": "^[0-9a-f]{40}([0-9a-f]{24})?$" }
33
+ ]
34
+ }
35
+ }
36
+ }
@@ -138,6 +138,36 @@
138
138
  "submit": [],
139
139
  "package": ["package"]
140
140
  },
141
+ "validationPhases": {
142
+ "compile": "run",
143
+ "unitTest": "run",
144
+ "unitTestFull": "test",
145
+ "apiTest": "test",
146
+ "dbCompatibility": "test",
147
+ "package": "package"
148
+ },
149
+ "capabilityGates": {
150
+ "deployment": {
151
+ "signals": ["deploy-required"],
152
+ "requiredStages": ["package"],
153
+ "requiredValidations": ["package"]
154
+ },
155
+ "container": {
156
+ "signals": ["install-verification"],
157
+ "requiredStages": ["package"],
158
+ "requiredValidations": ["package"]
159
+ },
160
+ "api": {
161
+ "signals": ["api-diff-present"],
162
+ "requiredStages": ["apidoc"],
163
+ "requiredValidations": ["apiTest"]
164
+ },
165
+ "database": {
166
+ "signals": ["migration"],
167
+ "requiredStages": [],
168
+ "requiredValidations": ["dbCompatibility"]
169
+ }
170
+ },
141
171
  "conditionalStages": {
142
172
  "review": {
143
173
  "tiers": ["standard", "full"],
@@ -2,7 +2,7 @@
2
2
  name: harness-apidoc
3
3
  description: 从 Java 后端代码生成结构化前端 API 文档(Controller/VO/ErrorCode)。使用场景:接口文档、前端接口文档、API 文档生成
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-apidoc — 前端接口文档(Java overlay)
7
7
 
8
8
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-archive
3
3
  description: 归档所有变更产出(计划/测试报告/审查/SQL/API文档)到
4
4
  .harness/archive/,含归档元数据和可视化最终总结。使用场景:归档、完成归档、收尾、打包产出物
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-archive — 变更归档
8
8
 
9
9
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-codebase-map
3
3
  description: 分析现有代码库并生成 .harness/codebase/map/
4
4
  下的结构化代码库地图。用于陌生项目理解、重大改造前梳理、harness-sync 提示 map 过期后的人工刷新。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-codebase-map — 代码库地图
8
8
 
9
9
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-knowledge-ingest
3
3
  description: 从 .harness/archive 归档整理、同步和维护项目知识索引。适用场景:ingest knowledge、sync
4
4
  knowledge、rebuild knowledge index、promote knowledge、确认知识条目、检查知识库是否过期。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-knowledge-ingest
8
8
 
9
9
  从 `.harness/archive/**/reports/final/summary-data.json` 抽取项目知识,生成并维护本地 `.harness/knowledge/` 索引。
@@ -3,7 +3,7 @@ name: harness-knowledge-query
3
3
  description: 根据新需求、设计任务、代码修改请求或问题排查,在规划和编码前查询 .harness/knowledge
4
4
  历史上下文。适用场景:query knowledge、查找历史需求、根据归档理解需求、继续之前类似开发、生成需求上下文包。
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-knowledge-query
8
8
 
9
9
  并行 change 中查询必须传 `--change <change-id>`;成功后以该 change 的 `meta/knowledge-context.json` 为稳定指针。全局 `context-packs/latest.json` 仅向后兼容,不得用于判断多个 active change 的上下文归属。
@@ -2,7 +2,7 @@
2
2
  name: harness-package
3
3
  description: 增量模块打包:拉取最新→编译验证→mvn package→汇总 jar/war。使用场景:打包、package、发版准备
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-package — 增量模块打包(Java overlay)
7
7
 
8
8
  ## Purpose
@@ -2,7 +2,7 @@
2
2
  name: harness-plan
3
3
  description: 将需求转化为设计文档+实施计划+完整测试场景表,必须在编码前完成。使用场景:需求分析、feature plan、技术方案设计、实现方案规划
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-plan — 需求规划
7
7
 
8
8
  ## Purpose
@@ -58,7 +58,7 @@ description: 将需求转化为设计文档+实施计划+完整测试场景表
58
58
 
59
59
  | 阶段 | 动作 |
60
60
  |------|------|
61
- | 0 | git status;脏工作区 → baseline 隔离 + `decision`,不询问 |
61
+ | 0 | 用当前解释器运行 `harness_runtime.py doctor`,后续消费绝对 argv;git status;脏工作区 → baseline 隔离 + `decision`,不询问 |
62
62
  | 0.5 | 先初始化 change-name + `phase.start`,从第一条知识查询起保留事件证据 |
63
63
  | 1 | `harness-knowledge-query` 单次 query(内部 ensure-current;失败记 `issue`) |
64
64
  | 2 | 歧义优先检查 + 复杂度分级;先确认会改变实现方向的语义歧义 |
@@ -66,7 +66,7 @@ description: 将需求转化为设计文档+实施计划+完整测试场景表
66
66
  | 4 | **设计审批包** AskUserQuestion;确认事件早于 approved 设计文档和 `meta/worktree.json` |
67
67
  | 5–6 | plan + implementation-detail + test-scenarios → `plans/` |
68
68
  | 7.5 | 仅 `--adversarial` 对抗评审 |
69
- | 8 | 产物完整性必检 → `checklist.md` |
69
+ | 8 | 在临时产物集上运行 `harness_plan_finalize.py finalize`;原子发布、唯一 `phase.end`、render → `checklist.md` |
70
70
 
71
71
  change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`)
72
72
 
@@ -82,7 +82,7 @@ change-name 范围变更 → 提示重命名或记 🟡WARN(→ `reference.md`
82
82
  |------|------|
83
83
  | 产物路径 | 只写 `.harness/changes/<cn>/`;禁止 superpowers 输入 |
84
84
  | 设计审批包 | 一次 AskUserQuestion 含 worktree(读 `harness.json` `defaultWorktree`) |
85
- | 阶段 8 | spec/plan/detail/scenarios/worktree.json/logs/events 缺一不可 ❌FAIL |
85
+ | 阶段 8 | spec/plan/detail/scenarios/worktree.json 先进入 staging;仅 finalizer 校验成功后发布并写唯一 `phase.end`/log,失败不得手工补终态 |
86
86
  | Plan 结束 | **禁止**询问执行模式;只提示 `/harness-run` |
87
87
  | 知识查询 | 0.5 失败不得假装已读历史 |
88
88
  | 歧义优先检查 | 否定、对比、动作对象或范围存在多种合理解释时,最小取证后先给推荐理解并一次一问;确认前不深挖错误方向 |
@@ -213,6 +213,12 @@ source: harness-plan
213
213
 
214
214
  > **缺任一文件 → ❌FAIL,不得宣称 plan 完成。**
215
215
 
216
+ - [ ] 所有待发布产物先写入 staging,不直接覆盖正式 change 目录
217
+ - [ ] 执行 `harness_plan_finalize.py finalize --change-dir ... --staging-dir ... --change ... --run-id ... --attempt ... --json`
218
+ - [ ] finalizer 返回 `ok=true` 与 `artifactsHash`;重复执行返回 `idempotent=true`
219
+ - [ ] finalizer 失败时正式目录无半发布产物、无成功 `phase.end`、无伪造 execution log
220
+ - [ ] 禁止在 finalizer 之前手工追加成功 `phase.end`
221
+
216
222
  | 文件 | 必须存在 | 检查结果 |
217
223
  |------|:---:|:---:|
218
224
  | `.harness/changes/<change>/spec/<change>-design.md` | ✅ | □ |
@@ -14,8 +14,11 @@ description: harness-plan 的需求提取模板、任务拆分规则、测试场
14
14
  {
15
15
  "requested": true,
16
16
  "created": false,
17
- "path": ".claude/worktrees/<change-name>",
18
- "branch": "worktree/<change-name>",
17
+ "agent": "<active-adapter>",
18
+ "worktreeRoot": "<adapter-worktree-root>",
19
+ "branchPrefix": "<adapter-branch-prefix>",
20
+ "path": "<adapter-worktree-root>/<change-name>",
21
+ "branch": "<adapter-branch-prefix><change-name>",
19
22
  "decisionBy": "user",
20
23
  "decisionAt": "YYYY-MM-DD HH:mm",
21
24
  "ownerSkill": "harness-run"
@@ -38,6 +41,8 @@ description: harness-plan 的需求提取模板、任务拆分规则、测试场
38
41
 
39
42
  ### 决策事件 note 示例
40
43
 
44
+ `path` 与 `branch` 必须来自 `harness_runtime.py adapter`/`meta/runtime.json`,不得复制其他 agent 的历史路径。Codex 的合同固定为 `.codex/worktrees/<change-name>` 与 `codex/<change-name>`。
45
+
41
46
  `用户选择使用 Worktree;决策文件为 meta/worktree.json;requested=true, created=false;创建责任为 harness-run。`
42
47
 
43
48
  ## 参考 — 详细格式
@@ -3,7 +3,7 @@ name: harness-review
3
3
  description: 6维度代码审查(架构/安全/规范/兼容/测试/性能),对照项目规则(见
4
4
  .harness/context-index.json)和测试场景表,在隔离上下文运行。使用场景:代码审查、提交前检查、合并评审
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-review — 代码审查
8
8
 
9
9
  ## Purpose
@@ -2,7 +2,7 @@
2
2
  name: harness-run
3
3
  description: 按变更簇执行 TDD 编码循环(RED→GREEN→REFACTOR→编译验证),逐变更簇实现计划中的任务。使用场景:开始编码、实现功能、写代码、TDD 编码
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-run — 需求编码
7
7
 
8
8
  ## Purpose
@@ -3,7 +3,7 @@ name: harness-submit
3
3
  description: 最终提交封装:验证→中文 commit→提交/推送;worktree 模式含 --no-ff
4
4
  合并回主分支。使用场景:提交代码、commit、push、合并分支、merge to main、完成开发
5
5
  ---
6
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
6
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
7
7
  # harness-submit — 最终提交(含 worktree 合并)
8
8
 
9
9
  ## Purpose
@@ -2,7 +2,7 @@
2
2
  name: harness-sync
3
3
  description: 检查并更新项目AI元数据(CodeGraph索引、harness-codebase-map分析、CLAUDE.md、AGENTS.md、.harness/完整性),确保Claude对代码库的理解与最新代码一致。当用户说'同步/更新索引/刷新元数据/检查一致性'时使用
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-sync — 元数据同步
7
7
 
8
8
  ## Purpose
@@ -2,7 +2,7 @@
2
2
  name: harness-test
3
3
  description: 测试执行:读取场景表,执行单元测试+API接口测试+数据兼容验证,输出测试报告。当用户说'跑测试/验证/跑用例/接口测试/单元测试'时使用
4
4
  ---
5
- <!-- generated by harness_deploy.py; core=0bc98072234275dd; overlay=java; agent=cursor; do not edit -->
5
+ <!-- generated by harness_deploy.py; core=2adf80c5975eb711; overlay=java; agent=cursor; do not edit -->
6
6
  # harness-test — 测试执行
7
7
 
8
8
  ## Purpose