@hunter-harness/workflow-harness 0.2.85 → 0.3.0

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 (282) 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 +46 -17
  3. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +2 -2
  4. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +2 -2
  5. package/harness/bundles/general/claude-code/harness-execute/SKILL.md +189 -0
  6. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +2 -2
  7. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +2 -2
  8. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +10 -9
  9. package/harness/bundles/general/claude-code/harness-plan/checklist.md +19 -91
  10. package/harness/bundles/general/claude-code/harness-plan/protocols.md +3 -1
  11. package/harness/bundles/general/claude-code/harness-plan/reference.md +74 -83
  12. package/harness/bundles/general/claude-code/harness-pull/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-push/SKILL.md +1 -1
  14. package/harness/bundles/general/claude-code/harness-review/SKILL.md +3 -3
  15. package/harness/bundles/general/claude-code/harness-review/protocols.md +1 -1
  16. package/harness/bundles/general/claude-code/harness-run/SKILL.md +13 -5
  17. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +2 -2
  18. package/harness/bundles/general/claude-code/harness-submit/checklist.md +1 -1
  19. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  20. package/harness/bundles/general/claude-code/harness-test/SKILL.md +11 -2
  21. package/harness/bundles/general/claude-code/scripts/harness_adoption_metrics.py +391 -0
  22. package/harness/bundles/general/claude-code/scripts/harness_archive.py +23 -14
  23. package/harness/bundles/general/claude-code/scripts/harness_change.py +25 -7
  24. package/harness/bundles/general/claude-code/scripts/harness_context.py +154 -60
  25. package/harness/bundles/general/claude-code/scripts/harness_events.py +1 -1
  26. package/harness/bundles/general/claude-code/scripts/harness_events_sync.py +1 -0
  27. package/harness/bundles/general/claude-code/scripts/harness_fixback.py +14 -10
  28. package/harness/bundles/general/claude-code/scripts/harness_gate.py +293 -90
  29. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +47 -2
  30. package/harness/bundles/general/claude-code/scripts/harness_paths.py +175 -0
  31. package/harness/bundles/general/claude-code/scripts/harness_phase.py +65 -23
  32. package/harness/bundles/general/claude-code/scripts/harness_plan_finalize.py +140 -874
  33. package/harness/bundles/general/claude-code/scripts/harness_review.py +25 -4
  34. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  35. package/harness/bundles/general/codebuddy/contracts/workflow-policy.json +46 -17
  36. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +2 -2
  37. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +2 -2
  38. package/harness/bundles/general/codebuddy/harness-execute/SKILL.md +170 -0
  39. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +2 -2
  40. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +2 -2
  41. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +10 -9
  42. package/harness/bundles/general/codebuddy/harness-plan/checklist.md +19 -91
  43. package/harness/bundles/general/codebuddy/harness-plan/protocols.md +3 -1
  44. package/harness/bundles/general/codebuddy/harness-plan/reference.md +74 -83
  45. package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +1 -1
  46. package/harness/bundles/general/codebuddy/harness-push/SKILL.md +1 -1
  47. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +3 -3
  48. package/harness/bundles/general/codebuddy/harness-review/protocols.md +1 -1
  49. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +13 -5
  50. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +2 -2
  51. package/harness/bundles/general/codebuddy/harness-submit/checklist.md +1 -1
  52. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  53. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +11 -2
  54. package/harness/bundles/general/codebuddy/scripts/harness_adoption_metrics.py +391 -0
  55. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +23 -14
  56. package/harness/bundles/general/codebuddy/scripts/harness_change.py +25 -7
  57. package/harness/bundles/general/codebuddy/scripts/harness_context.py +154 -60
  58. package/harness/bundles/general/codebuddy/scripts/harness_events.py +1 -1
  59. package/harness/bundles/general/codebuddy/scripts/harness_events_sync.py +1 -0
  60. package/harness/bundles/general/codebuddy/scripts/harness_fixback.py +14 -10
  61. package/harness/bundles/general/codebuddy/scripts/harness_gate.py +293 -90
  62. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +47 -2
  63. package/harness/bundles/general/codebuddy/scripts/harness_paths.py +175 -0
  64. package/harness/bundles/general/codebuddy/scripts/harness_phase.py +65 -23
  65. package/harness/bundles/general/codebuddy/scripts/harness_plan_finalize.py +140 -874
  66. package/harness/bundles/general/codebuddy/scripts/harness_review.py +25 -4
  67. package/harness/bundles/general/codex/.harness-build.json +1 -1
  68. package/harness/bundles/general/codex/contracts/workflow-policy.json +46 -17
  69. package/harness/bundles/general/codex/harness-archive/SKILL.md +2 -2
  70. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +2 -2
  71. package/harness/bundles/general/codex/harness-execute/SKILL.md +170 -0
  72. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +2 -2
  73. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +2 -2
  74. package/harness/bundles/general/codex/harness-plan/SKILL.md +10 -9
  75. package/harness/bundles/general/codex/harness-plan/checklist.md +19 -91
  76. package/harness/bundles/general/codex/harness-plan/protocols.md +3 -1
  77. package/harness/bundles/general/codex/harness-plan/reference.md +74 -83
  78. package/harness/bundles/general/codex/harness-pull/SKILL.md +1 -1
  79. package/harness/bundles/general/codex/harness-push/SKILL.md +1 -1
  80. package/harness/bundles/general/codex/harness-review/SKILL.md +3 -3
  81. package/harness/bundles/general/codex/harness-review/protocols.md +1 -1
  82. package/harness/bundles/general/codex/harness-run/SKILL.md +13 -5
  83. package/harness/bundles/general/codex/harness-submit/SKILL.md +2 -2
  84. package/harness/bundles/general/codex/harness-submit/checklist.md +1 -1
  85. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  86. package/harness/bundles/general/codex/harness-test/SKILL.md +11 -2
  87. package/harness/bundles/general/codex/scripts/harness_adoption_metrics.py +391 -0
  88. package/harness/bundles/general/codex/scripts/harness_archive.py +23 -14
  89. package/harness/bundles/general/codex/scripts/harness_change.py +25 -7
  90. package/harness/bundles/general/codex/scripts/harness_context.py +154 -60
  91. package/harness/bundles/general/codex/scripts/harness_events.py +1 -1
  92. package/harness/bundles/general/codex/scripts/harness_events_sync.py +1 -0
  93. package/harness/bundles/general/codex/scripts/harness_fixback.py +14 -10
  94. package/harness/bundles/general/codex/scripts/harness_gate.py +293 -90
  95. package/harness/bundles/general/codex/scripts/harness_ledger.py +47 -2
  96. package/harness/bundles/general/codex/scripts/harness_paths.py +175 -0
  97. package/harness/bundles/general/codex/scripts/harness_phase.py +65 -23
  98. package/harness/bundles/general/codex/scripts/harness_plan_finalize.py +140 -874
  99. package/harness/bundles/general/codex/scripts/harness_review.py +25 -4
  100. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  101. package/harness/bundles/general/cursor/contracts/workflow-policy.json +46 -17
  102. package/harness/bundles/general/cursor/harness-archive/SKILL.md +2 -2
  103. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +2 -2
  104. package/harness/bundles/general/cursor/harness-execute/SKILL.md +170 -0
  105. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +2 -2
  106. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +2 -2
  107. package/harness/bundles/general/cursor/harness-plan/SKILL.md +10 -9
  108. package/harness/bundles/general/cursor/harness-plan/checklist.md +19 -91
  109. package/harness/bundles/general/cursor/harness-plan/protocols.md +3 -1
  110. package/harness/bundles/general/cursor/harness-plan/reference.md +74 -83
  111. package/harness/bundles/general/cursor/harness-pull/SKILL.md +1 -1
  112. package/harness/bundles/general/cursor/harness-push/SKILL.md +1 -1
  113. package/harness/bundles/general/cursor/harness-review/SKILL.md +3 -3
  114. package/harness/bundles/general/cursor/harness-review/protocols.md +1 -1
  115. package/harness/bundles/general/cursor/harness-run/SKILL.md +13 -5
  116. package/harness/bundles/general/cursor/harness-submit/SKILL.md +2 -2
  117. package/harness/bundles/general/cursor/harness-submit/checklist.md +1 -1
  118. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  119. package/harness/bundles/general/cursor/harness-test/SKILL.md +11 -2
  120. package/harness/bundles/general/cursor/scripts/harness_adoption_metrics.py +391 -0
  121. package/harness/bundles/general/cursor/scripts/harness_archive.py +23 -14
  122. package/harness/bundles/general/cursor/scripts/harness_change.py +25 -7
  123. package/harness/bundles/general/cursor/scripts/harness_context.py +154 -60
  124. package/harness/bundles/general/cursor/scripts/harness_events.py +1 -1
  125. package/harness/bundles/general/cursor/scripts/harness_events_sync.py +1 -0
  126. package/harness/bundles/general/cursor/scripts/harness_fixback.py +14 -10
  127. package/harness/bundles/general/cursor/scripts/harness_gate.py +293 -90
  128. package/harness/bundles/general/cursor/scripts/harness_ledger.py +47 -2
  129. package/harness/bundles/general/cursor/scripts/harness_paths.py +175 -0
  130. package/harness/bundles/general/cursor/scripts/harness_phase.py +65 -23
  131. package/harness/bundles/general/cursor/scripts/harness_plan_finalize.py +140 -874
  132. package/harness/bundles/general/cursor/scripts/harness_review.py +25 -4
  133. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  134. package/harness/bundles/java/claude-code/contracts/workflow-policy.json +46 -17
  135. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +2 -2
  136. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +2 -2
  137. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +2 -2
  138. package/harness/bundles/java/claude-code/harness-execute/SKILL.md +189 -0
  139. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +2 -2
  140. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +2 -2
  141. package/harness/bundles/java/claude-code/harness-package/SKILL.md +2 -2
  142. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +10 -9
  143. package/harness/bundles/java/claude-code/harness-plan/checklist.md +19 -91
  144. package/harness/bundles/java/claude-code/harness-plan/protocols.md +3 -1
  145. package/harness/bundles/java/claude-code/harness-plan/reference.md +74 -83
  146. package/harness/bundles/java/claude-code/harness-pull/SKILL.md +1 -1
  147. package/harness/bundles/java/claude-code/harness-push/SKILL.md +1 -1
  148. package/harness/bundles/java/claude-code/harness-review/SKILL.md +3 -3
  149. package/harness/bundles/java/claude-code/harness-review/protocols.md +1 -1
  150. package/harness/bundles/java/claude-code/harness-run/SKILL.md +13 -5
  151. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +2 -2
  152. package/harness/bundles/java/claude-code/harness-submit/checklist.md +1 -1
  153. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  154. package/harness/bundles/java/claude-code/harness-test/SKILL.md +11 -2
  155. package/harness/bundles/java/claude-code/scripts/harness_adoption_metrics.py +391 -0
  156. package/harness/bundles/java/claude-code/scripts/harness_archive.py +23 -14
  157. package/harness/bundles/java/claude-code/scripts/harness_change.py +25 -7
  158. package/harness/bundles/java/claude-code/scripts/harness_context.py +154 -60
  159. package/harness/bundles/java/claude-code/scripts/harness_events.py +1 -1
  160. package/harness/bundles/java/claude-code/scripts/harness_events_sync.py +1 -0
  161. package/harness/bundles/java/claude-code/scripts/harness_fixback.py +14 -10
  162. package/harness/bundles/java/claude-code/scripts/harness_gate.py +293 -90
  163. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +47 -2
  164. package/harness/bundles/java/claude-code/scripts/harness_paths.py +175 -0
  165. package/harness/bundles/java/claude-code/scripts/harness_phase.py +65 -23
  166. package/harness/bundles/java/claude-code/scripts/harness_plan_finalize.py +140 -874
  167. package/harness/bundles/java/claude-code/scripts/harness_review.py +25 -4
  168. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  169. package/harness/bundles/java/codebuddy/contracts/workflow-policy.json +46 -17
  170. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +2 -2
  171. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +2 -2
  172. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +2 -2
  173. package/harness/bundles/java/codebuddy/harness-execute/SKILL.md +170 -0
  174. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +2 -2
  175. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +2 -2
  176. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +2 -2
  177. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +10 -9
  178. package/harness/bundles/java/codebuddy/harness-plan/checklist.md +19 -91
  179. package/harness/bundles/java/codebuddy/harness-plan/protocols.md +3 -1
  180. package/harness/bundles/java/codebuddy/harness-plan/reference.md +74 -83
  181. package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +1 -1
  182. package/harness/bundles/java/codebuddy/harness-push/SKILL.md +1 -1
  183. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +3 -3
  184. package/harness/bundles/java/codebuddy/harness-review/protocols.md +1 -1
  185. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +13 -5
  186. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +2 -2
  187. package/harness/bundles/java/codebuddy/harness-submit/checklist.md +1 -1
  188. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  189. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +11 -2
  190. package/harness/bundles/java/codebuddy/scripts/harness_adoption_metrics.py +391 -0
  191. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +23 -14
  192. package/harness/bundles/java/codebuddy/scripts/harness_change.py +25 -7
  193. package/harness/bundles/java/codebuddy/scripts/harness_context.py +154 -60
  194. package/harness/bundles/java/codebuddy/scripts/harness_events.py +1 -1
  195. package/harness/bundles/java/codebuddy/scripts/harness_events_sync.py +1 -0
  196. package/harness/bundles/java/codebuddy/scripts/harness_fixback.py +14 -10
  197. package/harness/bundles/java/codebuddy/scripts/harness_gate.py +293 -90
  198. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +47 -2
  199. package/harness/bundles/java/codebuddy/scripts/harness_paths.py +175 -0
  200. package/harness/bundles/java/codebuddy/scripts/harness_phase.py +65 -23
  201. package/harness/bundles/java/codebuddy/scripts/harness_plan_finalize.py +140 -874
  202. package/harness/bundles/java/codebuddy/scripts/harness_review.py +25 -4
  203. package/harness/bundles/java/codex/.harness-build.json +1 -1
  204. package/harness/bundles/java/codex/contracts/workflow-policy.json +46 -17
  205. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +2 -2
  206. package/harness/bundles/java/codex/harness-archive/SKILL.md +2 -2
  207. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +2 -2
  208. package/harness/bundles/java/codex/harness-execute/SKILL.md +170 -0
  209. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +2 -2
  210. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +2 -2
  211. package/harness/bundles/java/codex/harness-package/SKILL.md +2 -2
  212. package/harness/bundles/java/codex/harness-plan/SKILL.md +10 -9
  213. package/harness/bundles/java/codex/harness-plan/checklist.md +19 -91
  214. package/harness/bundles/java/codex/harness-plan/protocols.md +3 -1
  215. package/harness/bundles/java/codex/harness-plan/reference.md +74 -83
  216. package/harness/bundles/java/codex/harness-pull/SKILL.md +1 -1
  217. package/harness/bundles/java/codex/harness-push/SKILL.md +1 -1
  218. package/harness/bundles/java/codex/harness-review/SKILL.md +3 -3
  219. package/harness/bundles/java/codex/harness-review/protocols.md +1 -1
  220. package/harness/bundles/java/codex/harness-run/SKILL.md +13 -5
  221. package/harness/bundles/java/codex/harness-submit/SKILL.md +2 -2
  222. package/harness/bundles/java/codex/harness-submit/checklist.md +1 -1
  223. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  224. package/harness/bundles/java/codex/harness-test/SKILL.md +11 -2
  225. package/harness/bundles/java/codex/scripts/harness_adoption_metrics.py +391 -0
  226. package/harness/bundles/java/codex/scripts/harness_archive.py +23 -14
  227. package/harness/bundles/java/codex/scripts/harness_change.py +25 -7
  228. package/harness/bundles/java/codex/scripts/harness_context.py +154 -60
  229. package/harness/bundles/java/codex/scripts/harness_events.py +1 -1
  230. package/harness/bundles/java/codex/scripts/harness_events_sync.py +1 -0
  231. package/harness/bundles/java/codex/scripts/harness_fixback.py +14 -10
  232. package/harness/bundles/java/codex/scripts/harness_gate.py +293 -90
  233. package/harness/bundles/java/codex/scripts/harness_ledger.py +47 -2
  234. package/harness/bundles/java/codex/scripts/harness_paths.py +175 -0
  235. package/harness/bundles/java/codex/scripts/harness_phase.py +65 -23
  236. package/harness/bundles/java/codex/scripts/harness_plan_finalize.py +140 -874
  237. package/harness/bundles/java/codex/scripts/harness_review.py +25 -4
  238. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  239. package/harness/bundles/java/cursor/contracts/workflow-policy.json +46 -17
  240. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +2 -2
  241. package/harness/bundles/java/cursor/harness-archive/SKILL.md +2 -2
  242. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +2 -2
  243. package/harness/bundles/java/cursor/harness-execute/SKILL.md +170 -0
  244. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +2 -2
  245. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +2 -2
  246. package/harness/bundles/java/cursor/harness-package/SKILL.md +2 -2
  247. package/harness/bundles/java/cursor/harness-plan/SKILL.md +10 -9
  248. package/harness/bundles/java/cursor/harness-plan/checklist.md +19 -91
  249. package/harness/bundles/java/cursor/harness-plan/protocols.md +3 -1
  250. package/harness/bundles/java/cursor/harness-plan/reference.md +74 -83
  251. package/harness/bundles/java/cursor/harness-pull/SKILL.md +1 -1
  252. package/harness/bundles/java/cursor/harness-push/SKILL.md +1 -1
  253. package/harness/bundles/java/cursor/harness-review/SKILL.md +3 -3
  254. package/harness/bundles/java/cursor/harness-review/protocols.md +1 -1
  255. package/harness/bundles/java/cursor/harness-run/SKILL.md +13 -5
  256. package/harness/bundles/java/cursor/harness-submit/SKILL.md +2 -2
  257. package/harness/bundles/java/cursor/harness-submit/checklist.md +1 -1
  258. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  259. package/harness/bundles/java/cursor/harness-test/SKILL.md +11 -2
  260. package/harness/bundles/java/cursor/scripts/harness_adoption_metrics.py +391 -0
  261. package/harness/bundles/java/cursor/scripts/harness_archive.py +23 -14
  262. package/harness/bundles/java/cursor/scripts/harness_change.py +25 -7
  263. package/harness/bundles/java/cursor/scripts/harness_context.py +154 -60
  264. package/harness/bundles/java/cursor/scripts/harness_events.py +1 -1
  265. package/harness/bundles/java/cursor/scripts/harness_events_sync.py +1 -0
  266. package/harness/bundles/java/cursor/scripts/harness_fixback.py +14 -10
  267. package/harness/bundles/java/cursor/scripts/harness_gate.py +293 -90
  268. package/harness/bundles/java/cursor/scripts/harness_ledger.py +47 -2
  269. package/harness/bundles/java/cursor/scripts/harness_paths.py +175 -0
  270. package/harness/bundles/java/cursor/scripts/harness_phase.py +65 -23
  271. package/harness/bundles/java/cursor/scripts/harness_plan_finalize.py +140 -874
  272. package/harness/bundles/java/cursor/scripts/harness_review.py +25 -4
  273. package/harness/manifests/general/claude-code.json +40 -32
  274. package/harness/manifests/general/codebuddy.json +40 -32
  275. package/harness/manifests/general/codex.json +40 -32
  276. package/harness/manifests/general/cursor.json +40 -32
  277. package/harness/manifests/java/claude-code.json +42 -34
  278. package/harness/manifests/java/codebuddy.json +42 -34
  279. package/harness/manifests/java/codex.json +42 -34
  280. package/harness/manifests/java/cursor.json +42 -34
  281. package/hunter-workflow-family.json +4 -4
  282. package/package.json +1 -1
@@ -21,27 +21,18 @@ if str(SCRIPTS_DIR) not in sys.path:
21
21
  sys.path.insert(0, str(SCRIPTS_DIR))
22
22
 
23
23
  import harness_ledger as hl # noqa: E402
24
+ import harness_paths as hpaths # noqa: E402
24
25
 
25
26
 
26
27
  PHASE_GRAPH = {
27
- "plan": ("run",),
28
- "run": ("test",),
29
- "test": ("review", "run"),
30
- "review": ("submit", "run"),
28
+ "plan": ("execute",),
29
+ "execute": ("review", "execute"),
30
+ "review": ("submit", "execute"),
31
31
  "submit": (),
32
32
  }
33
33
 
34
- WORKFLOW_PHASES = (
35
- "plan",
36
- "run",
37
- "test",
38
- "review",
39
- "package",
40
- "apidoc",
41
- "submit",
42
- "merge",
43
- "archive",
44
- )
34
+ # 唯一权威清单在 harness_paths(叶子模块,harness_phase 引的是同一个对象)。
35
+ WORKFLOW_PHASES = hpaths.WORKFLOW_PHASES
45
36
 
46
37
  DISPLAY_TITLE_MAX_LENGTH = 80
47
38
 
@@ -270,13 +261,26 @@ def _contract(project: Path, change: str) -> tuple[Path, dict[str, Any], Path]:
270
261
 
271
262
 
272
263
  def _phase_plan(contract_root: Path) -> tuple[list[str] | None, str]:
273
- policy_path = contract_root / "meta" / "gate-policy.json"
274
- if not policy_path.is_file():
275
- return None, "legacy"
276
- try:
277
- policy = _read_json(policy_path)
278
- except (OSError, ValueError, json.JSONDecodeError):
264
+ """读出阶段计划;无法采信时说明原因,而不是悄悄退成 legacy。
265
+
266
+ 以前这里遇到未知阶段名一律返回 (None, "legacy"):阶段计划整个失效,
267
+ `_allowed_next_phases` 退回硬编码的 PHASE_GRAPH,而调用方看不出发生过这件事。
268
+ 未知阶段名不是假想问题——阶段清单少一个 merge 时,worktree 变更的
269
+ plannedPhases 就会带着 merge 走到这里。
270
+
271
+ 未知名先过 LEGACY_PHASE_ALIASES 读时映射(阶段改名后历史 change 靠它继续可读),
272
+ 仍然解析不了才降级,并把原因与具体阶段名带在 source 里。
273
+
274
+ 权威切换(2026-08):v2 发布快照(plan-profile.json)优先,classify 工作
275
+ 副本回退——发布后的阶段计划以已审批快照为准。
276
+ """
277
+ loaded = hpaths.load_change_gate_policy(contract_root)
278
+ policy = loaded.get("policy")
279
+ if policy is None:
280
+ if loaded.get("working_error"):
281
+ return None, "legacy:policy-unreadable"
279
282
  return None, "legacy"
283
+ unknown: list[str] = []
280
284
  for field, source in (
281
285
  ("plannedPhases", "change"),
282
286
  ("defaultPhases", "policy-default"),
@@ -285,25 +289,31 @@ def _phase_plan(contract_root: Path) -> tuple[list[str] | None, str]:
285
289
  if not isinstance(raw, list):
286
290
  continue
287
291
  phases = [str(item).strip() for item in raw if str(item).strip()]
288
- if (
289
- phases
290
- and len(phases) == len(set(phases))
291
- and all(item in WORKFLOW_PHASES for item in phases)
292
- ):
293
- return phases, source
292
+ if not phases or len(phases) != len(set(phases)):
293
+ continue
294
+ resolved = [hpaths.resolve_phase_name(item) for item in phases]
295
+ missing = [item for item, hit in zip(phases, resolved) if hit is None]
296
+ if missing:
297
+ unknown.extend(missing)
298
+ continue
299
+ # 映射后可能出现重复(两个旧名合并成同一个新阶段),保序去重。
300
+ return list(dict.fromkeys(str(item) for item in resolved)), source
301
+ if unknown:
302
+ return None, "legacy:unknown-phases=" + ",".join(dict.fromkeys(unknown))
294
303
  return None, "legacy"
295
304
 
296
305
 
297
306
  def _allowed_next_phases(contract_root: Path, from_phase: str) -> list[str]:
298
307
  planned, _source = _phase_plan(contract_root)
308
+ resolved_from = hpaths.resolve_phase_name(from_phase) or from_phase
299
309
  if planned is None:
300
- return list(PHASE_GRAPH.get(from_phase, ()))
301
- if from_phase not in planned:
310
+ return list(PHASE_GRAPH.get(resolved_from, ()))
311
+ if resolved_from not in planned:
302
312
  return []
303
- index = planned.index(from_phase)
313
+ index = planned.index(resolved_from)
304
314
  allowed = planned[index + 1 : index + 2]
305
- if from_phase in {"test", "review"} and "run" in planned:
306
- allowed = [*allowed, "run"]
315
+ if resolved_from in {"execute", "review"} and "execute" in planned:
316
+ allowed = [*allowed, "execute"]
307
317
  return list(dict.fromkeys(allowed))
308
318
 
309
319
 
@@ -322,12 +332,14 @@ def configure_phase_plan(
322
332
  except (OSError, ValueError, json.JSONDecodeError) as exc:
323
333
  return {"ok": False, "code": _contract_error_code(exc), "error": str(exc)}
324
334
  normalized = [str(item).strip() for item in phases if str(item).strip()]
335
+ resolved = [hpaths.resolve_phase_name(item) for item in normalized]
325
336
  if (
326
337
  not normalized
327
338
  or len(normalized) != len(set(normalized))
328
- or any(item not in WORKFLOW_PHASES for item in normalized)
329
- or normalized[0] != "plan"
330
- or normalized[-1] != "archive"
339
+ or any(item is None for item in resolved)
340
+ or len(set(resolved)) != len(resolved)
341
+ or resolved[0] != "plan"
342
+ or resolved[-1] != "archive"
331
343
  ):
332
344
  return {
333
345
  "ok": False,
@@ -340,6 +352,9 @@ def configure_phase_plan(
340
352
  "ok": False,
341
353
  "code": "PHASE_PLAN_JUSTIFICATION_REQUIRED",
342
354
  }
355
+ # 旧名入参(plan,run,test,review,archive)归一为现阶段名后落盘;
356
+ # 上面已校验 resolved 无 None 且保序唯一。
357
+ normalized = [str(item) for item in resolved]
343
358
  worktree_path = contract_root / "meta" / "worktree.json"
344
359
  if worktree_path.is_file():
345
360
  try:
@@ -405,6 +420,7 @@ def _paths(state_root: Path) -> dict[str, Path]:
405
420
  "begins": runtime / "transition-begins.ndjson",
406
421
  "current": runtime / "current-context.json",
407
422
  "lease": runtime / "context-lease.json",
423
+ "adoptions": runtime / "context-adoptions.ndjson",
408
424
  }
409
425
 
410
426
 
@@ -442,7 +458,7 @@ def _reselect_review_fixback(
442
458
  state_root: Path,
443
459
  executor: str,
444
460
  ) -> dict[str, Any]:
445
- """Supersede an unbegun review→submit choice with review→run."""
461
+ """Supersede an unbegun review→submit choice with review→execute."""
446
462
 
447
463
  paths = _paths(state_root)
448
464
  with _exclusive_state_lock(paths["runtime"] / "branch-selection.lock"):
@@ -450,8 +466,8 @@ def _reselect_review_fixback(
450
466
  latest = transitions[-1] if transitions else None
451
467
  if (
452
468
  isinstance(latest, dict)
453
- and latest.get("fromPhase") == "review"
454
- and latest.get("toPhase") == "run"
469
+ and hpaths.resolve_phase_name(latest.get("fromPhase")) == "review"
470
+ and hpaths.resolve_phase_name(latest.get("toPhase")) == "execute"
455
471
  and latest.get("trigger") == "review-fixback"
456
472
  ):
457
473
  return {
@@ -503,14 +519,14 @@ def _reselect_review_fixback(
503
519
  }
504
520
  paths["lease"].unlink(missing_ok=True)
505
521
  # Any submit context present here was only prepared, never begun. The
506
- # new run context is written by prepare_context after this atomic choice.
522
+ # new execute context is written by prepare_context after this atomic choice.
507
523
  paths["current"].unlink(missing_ok=True)
508
524
 
509
525
  receipt: dict[str, Any] = {
510
526
  "schemaVersion": 1,
511
527
  "changeName": change,
512
528
  "fromPhase": "review",
513
- "toPhase": "run",
529
+ "toPhase": "execute",
514
530
  "status": "OK",
515
531
  "executor": executor,
516
532
  "productCommit": _head(project),
@@ -519,8 +535,8 @@ def _reselect_review_fixback(
519
535
  + sum(
520
536
  1
521
537
  for item in transitions
522
- if item.get("fromPhase") == "review"
523
- and item.get("toPhase") == "run"
538
+ if hpaths.resolve_phase_name(item.get("fromPhase")) == "review"
539
+ and hpaths.resolve_phase_name(item.get("toPhase")) == "execute"
524
540
  ),
525
541
  "closedAt": _now().isoformat(),
526
542
  "previousReceiptHash": latest.get("receiptHash"),
@@ -534,7 +550,7 @@ def _reselect_review_fixback(
534
550
  state_root,
535
551
  transition_hash=receipt["receiptHash"],
536
552
  from_phase="review",
537
- to_phase="run",
553
+ to_phase="execute",
538
554
  )
539
555
  return {
540
556
  "ok": True,
@@ -604,13 +620,20 @@ def _claim_prepared_context(
604
620
  )
605
621
  except (OSError, ValueError, json.JSONDecodeError):
606
622
  return {"ok": False, "code": "CONTEXT_CURRENT_INVALID"}
623
+ # 跨阶段推进必须有 receipt 证明它合法;同一个阶段换执行者不需要。
624
+ # 以前两者都要 receipt,于是上一阶段崩溃没能正常 close 时,接手的工具
625
+ # 连"继续把这个阶段干完"都做不到。并发保护不受影响:租约未过期而
626
+ # owner 不同,上面 CONTEXT_LEASE_HELD 已经拦下了,能走到这里只剩
627
+ # 「租约已过期」和「租约已被上一阶段 close 删除」两种情况。
628
+ adoption: dict[str, Any] | None = None
607
629
  if recovery is None and isinstance(current, dict) and (
608
- current.get("executor") != executor or current.get("phase") != phase
630
+ hpaths.resolve_phase_name(current.get("phase")) != phase
609
631
  ):
610
632
  valid_receipt = (
611
633
  isinstance(latest, dict)
612
- and latest.get("toPhase") == phase
613
- and latest.get("fromPhase") == current.get("phase")
634
+ and hpaths.resolve_phase_name(latest.get("toPhase")) == phase
635
+ and hpaths.resolve_phase_name(latest.get("fromPhase"))
636
+ == hpaths.resolve_phase_name(current.get("phase"))
614
637
  )
615
638
  if not valid_receipt:
616
639
  return {
@@ -621,6 +644,19 @@ def _claim_prepared_context(
621
644
  "toExecutor": executor,
622
645
  "toPhase": phase,
623
646
  }
647
+ executor_changed = (
648
+ isinstance(current, dict) and current.get("executor") != executor
649
+ )
650
+ if recovery is not None or executor_changed:
651
+ adoption = {
652
+ "previousExecutor": (
653
+ current.get("executor") if isinstance(current, dict) else None
654
+ ),
655
+ "newExecutor": executor,
656
+ "reason": (
657
+ "lease_expired" if recovery is not None else "same_phase_handoff"
658
+ ),
659
+ }
624
660
 
625
661
  try:
626
662
  execution_root = _execution_root(project, contract_root, state_root)
@@ -657,6 +693,20 @@ def _claim_prepared_context(
657
693
  current_context["preparationId"] = preparation_id
658
694
  _write_json_atomic(paths["lease"], lease)
659
695
  _write_json_atomic(paths["current"], current_context)
696
+ if adoption is not None:
697
+ # 接管必须留痕。过期租约本来就允许任何执行者顶替,但以前只在返回体
698
+ # 里挂一个 recovery,退出进程就没了——事后查"这个阶段是谁接手的"
699
+ # 无据可依。收据形状照 harness_archive.adopt_existing_range。
700
+ adoption = {
701
+ "schemaVersion": 1,
702
+ "changeName": change,
703
+ "phase": phase,
704
+ **adoption,
705
+ "previousOwner": recovery.get("previousOwner") if recovery else None,
706
+ "expiredAt": recovery.get("expiredAt") if recovery else None,
707
+ "adoptedAt": now.isoformat(),
708
+ }
709
+ _append_ndjson(paths["adoptions"], adoption)
660
710
  return {
661
711
  "ok": True,
662
712
  "lease": lease,
@@ -664,10 +714,25 @@ def _claim_prepared_context(
664
714
  "transitions": transitions,
665
715
  "latestTransition": latest,
666
716
  "recovery": recovery,
717
+ "adoption": adoption,
667
718
  "executionRoot": str(execution_root),
668
719
  }
669
720
 
670
721
 
722
+ def _unknown_phase_error(phase: Any) -> dict[str, Any]:
723
+ return {
724
+ "ok": False,
725
+ "code": "PHASE_UNKNOWN",
726
+ "phase": str(phase),
727
+ "allowedPhases": list(WORKFLOW_PHASES),
728
+ "legacyAliases": dict(hpaths.LEGACY_PHASE_ALIASES),
729
+ "message": (
730
+ f"未知阶段名 {phase!r};合法阶段 {list(WORKFLOW_PHASES)},"
731
+ f"旧名别名 {hpaths.LEGACY_PHASE_ALIASES}。"
732
+ ),
733
+ }
734
+
735
+
671
736
  def prepare_context(
672
737
  project: Path,
673
738
  *,
@@ -680,6 +745,10 @@ def prepare_context(
680
745
  preparation_id: str | None = None,
681
746
  ) -> dict[str, Any]:
682
747
  project = Path(project).resolve()
748
+ canonical_phase = hpaths.resolve_phase_name(phase)
749
+ if canonical_phase is None:
750
+ return _unknown_phase_error(phase)
751
+ phase = canonical_phase
683
752
  candidates = _active_changes(project)
684
753
  if change is None:
685
754
  if not candidates:
@@ -726,7 +795,7 @@ def prepare_context(
726
795
  paths = _paths(state_root)
727
796
  paths["runtime"].mkdir(parents=True, exist_ok=True)
728
797
  reselection: dict[str, Any] | None = None
729
- if trigger == "review-fixback" and phase == "run":
798
+ if trigger == "review-fixback" and phase == "execute":
730
799
  reselection = _reselect_review_fixback(
731
800
  project,
732
801
  change,
@@ -768,9 +837,14 @@ def prepare_context(
768
837
  _allowed_next_phases(contract_root, phase)
769
838
  if planned_phases is not None
770
839
  else (
771
- list(PHASE_GRAPH.get(str(latest.get("toPhase")), ()))
840
+ list(
841
+ PHASE_GRAPH.get(
842
+ hpaths.resolve_phase_name(str(latest.get("toPhase"))) or "",
843
+ (),
844
+ )
845
+ )
772
846
  if latest
773
- else ["plan", "run"]
847
+ else ["plan", "execute"]
774
848
  )
775
849
  )
776
850
  return {
@@ -1014,7 +1088,7 @@ def _bootstrap_v2_plan_transition(
1014
1088
  """v2 发布已 committed 却没有交接凭证时,补录 plan → to_phase 凭证。
1015
1089
 
1016
1090
  v2 plan finalize 只写 plan-events.ndjson 与发布 journal,不碰 context 事务
1017
- 存储,于是 run 阶段 prepare 必报 HANDOFF_REQUIRED、begin 必报
1091
+ 存储,于是 execute 阶段 prepare 必报 HANDOFF_REQUIRED、begin 必报
1018
1092
  LEGACY_BOOTSTRAP_REQUIRED——两个错误都不给恢复路径,调用方只能读脚本源码
1019
1093
  自己拼出 classify + configure-plan + close,参数全靠现编,可审计性更差。
1020
1094
 
@@ -1061,6 +1135,14 @@ def close_transition(
1061
1135
  status: str = "OK",
1062
1136
  ) -> dict[str, Any]:
1063
1137
  project = Path(project).resolve()
1138
+ canonical_from = hpaths.resolve_phase_name(from_phase)
1139
+ canonical_to = hpaths.resolve_phase_name(to_phase)
1140
+ if canonical_from is None:
1141
+ return _unknown_phase_error(from_phase)
1142
+ if canonical_to is None:
1143
+ return _unknown_phase_error(to_phase)
1144
+ from_phase = canonical_from
1145
+ to_phase = canonical_to
1064
1146
  try:
1065
1147
  contract_root, _contract_data, state_root = _contract(project, change)
1066
1148
  except (OSError, ValueError, json.JSONDecodeError) as exc:
@@ -1136,8 +1218,8 @@ def close_transition(
1136
1218
  latest = transitions[-1] if transitions else None
1137
1219
  if (
1138
1220
  isinstance(latest, dict)
1139
- and latest.get("fromPhase") == from_phase
1140
- and latest.get("toPhase") == to_phase
1221
+ and hpaths.resolve_phase_name(latest.get("fromPhase")) == from_phase
1222
+ and hpaths.resolve_phase_name(latest.get("toPhase")) == to_phase
1141
1223
  and latest.get("status") == status
1142
1224
  and latest.get("artifacts") == artifact_entries
1143
1225
  and (executor is None or latest.get("executor") == executor)
@@ -1158,7 +1240,9 @@ def close_transition(
1158
1240
  effective_executor = executor or str(lease.get("owner") or "")
1159
1241
  if not effective_executor:
1160
1242
  return {"ok": False, "code": "CONTEXT_EXECUTOR_REQUIRED"}
1161
- if lease.get("owner") != effective_executor or lease.get("phase") != from_phase:
1243
+ if lease.get("owner") != effective_executor or (
1244
+ hpaths.resolve_phase_name(lease.get("phase")) != from_phase
1245
+ ):
1162
1246
  return {
1163
1247
  "ok": False,
1164
1248
  "code": "CONTEXT_LEASE_MISMATCH",
@@ -1177,8 +1261,8 @@ def close_transition(
1177
1261
  + sum(
1178
1262
  1
1179
1263
  for item in transitions
1180
- if item.get("fromPhase") == from_phase
1181
- and item.get("toPhase") == to_phase
1264
+ if hpaths.resolve_phase_name(item.get("fromPhase")) == from_phase
1265
+ and hpaths.resolve_phase_name(item.get("toPhase")) == to_phase
1182
1266
  )
1183
1267
  )
1184
1268
  receipt: dict[str, Any] = {
@@ -1204,7 +1288,7 @@ def close_transition(
1204
1288
  _append_ndjson(paths["transitions"], receipt)
1205
1289
  paths["lease"].unlink(missing_ok=True)
1206
1290
  invalidation = None
1207
- if to_phase == "run" and from_phase in {"test", "review"}:
1291
+ if to_phase == "execute" and from_phase in {"execute", "review"}:
1208
1292
  invalidation = _invalidate_for_fixback(
1209
1293
  state_root,
1210
1294
  transition_hash=receipt["receiptHash"],
@@ -1283,7 +1367,7 @@ def _begin_transition_unlocked(
1283
1367
  ),
1284
1368
  }
1285
1369
  receipt = transitions[-1]
1286
- if receipt.get("toPhase") != phase:
1370
+ if hpaths.resolve_phase_name(receipt.get("toPhase")) != phase:
1287
1371
  return {
1288
1372
  "ok": False,
1289
1373
  "code": "HANDOFF_REQUIRED",
@@ -1360,6 +1444,10 @@ def begin_transition(
1360
1444
  """Acknowledge a transition while serializing branch selection."""
1361
1445
 
1362
1446
  project = Path(project).resolve()
1447
+ canonical_phase = hpaths.resolve_phase_name(phase)
1448
+ if canonical_phase is None:
1449
+ return _unknown_phase_error(phase)
1450
+ phase = canonical_phase
1363
1451
  try:
1364
1452
  _contract_root, _contract_data, state_root = _contract(project, change)
1365
1453
  except (OSError, ValueError, json.JSONDecodeError) as exc:
@@ -1386,6 +1474,10 @@ def cancel_prepared_context(
1386
1474
  """Remove a target-phase preparation that never obtained its gate."""
1387
1475
 
1388
1476
  project = Path(project).resolve()
1477
+ canonical_phase = hpaths.resolve_phase_name(phase)
1478
+ if canonical_phase is None:
1479
+ return _unknown_phase_error(phase)
1480
+ phase = canonical_phase
1389
1481
  try:
1390
1482
  _contract_root, _contract_data, state_root = _contract(project, change)
1391
1483
  except (OSError, ValueError, json.JSONDecodeError) as exc:
@@ -1400,7 +1492,8 @@ def cancel_prepared_context(
1400
1492
  except (OSError, ValueError, json.JSONDecodeError):
1401
1493
  current = None
1402
1494
  if isinstance(current, dict) and (
1403
- current.get("phase") == phase and current.get("executor") == executor
1495
+ hpaths.resolve_phase_name(current.get("phase")) == phase
1496
+ and current.get("executor") == executor
1404
1497
  and (
1405
1498
  preparation_id is None
1406
1499
  or current.get("preparationId") == preparation_id
@@ -1415,7 +1508,8 @@ def cancel_prepared_context(
1415
1508
  except (OSError, ValueError, json.JSONDecodeError):
1416
1509
  lease = None
1417
1510
  if isinstance(lease, dict) and (
1418
- lease.get("phase") == phase and lease.get("owner") == executor
1511
+ hpaths.resolve_phase_name(lease.get("phase")) == phase
1512
+ and lease.get("owner") == executor
1419
1513
  and (
1420
1514
  preparation_id is None
1421
1515
  or lease.get("preparationId") == preparation_id
@@ -1429,7 +1523,7 @@ def cancel_prepared_context(
1429
1523
  for item in begins
1430
1524
  if not (
1431
1525
  receipt_hash is not None
1432
- and item.get("phase") == phase
1526
+ and hpaths.resolve_phase_name(item.get("phase")) == phase
1433
1527
  and item.get("executor") == executor
1434
1528
  and item.get("receiptHash") == receipt_hash
1435
1529
  and (
@@ -2014,7 +2014,7 @@ def cmd_append(args: argparse.Namespace) -> int:
2014
2014
  "PHASE_ALREADY_CLOSED: refusing a second phase.end for the same "
2015
2015
  "attempt. A retry needs a fresh run id AND the next attempt number "
2016
2016
  "(attempts are global per phase, not per run id). For a published "
2017
- "plan use harness_plan_finalize.py republish, which allocates both.",
2017
+ "plan rerun plan evidence-pack + plan finalize with the next attempt.",
2018
2018
  as_json=as_json,
2019
2019
  error_code="PHASE_ALREADY_CLOSED",
2020
2020
  )
@@ -76,6 +76,7 @@ EVENT_SUMMARY_MAX_LENGTH = 500
76
76
 
77
77
  PHASE_LABELS = {
78
78
  "plan": "计划",
79
+ "execute": "执行",
79
80
  "run": "编码",
80
81
  "test": "测试",
81
82
  "review": "评审",
@@ -333,7 +333,7 @@ def open_review_batch(
333
333
  _write_json(_session_path(change_dir), session)
334
334
  he.append_event(
335
335
  change_dir,
336
- phase="run",
336
+ phase="execute",
337
337
  type_="decision",
338
338
  note=f"已从评审结果创建修复批次,共 {len(issue_entries)} 个代码修复项。",
339
339
  run_id=run_id,
@@ -355,7 +355,7 @@ def _default_context_prepare(**kwargs: Any) -> dict[str, Any]:
355
355
 
356
356
  return hctx.prepare_context(
357
357
  kwargs["project"],
358
- phase="run",
358
+ phase="execute",
359
359
  executor=kwargs["executor"],
360
360
  change=kwargs["change"],
361
361
  trigger="review-fixback",
@@ -369,7 +369,7 @@ def _default_context_begin(**kwargs: Any) -> dict[str, Any]:
369
369
  return hctx.begin_transition(
370
370
  kwargs["project"],
371
371
  kwargs["change"],
372
- phase="run",
372
+ phase="execute",
373
373
  executor=kwargs["executor"],
374
374
  preparation_id=kwargs["preparation_id"],
375
375
  )
@@ -381,7 +381,7 @@ def _default_context_cancel(**kwargs: Any) -> dict[str, Any]:
381
381
  return hctx.cancel_prepared_context(
382
382
  kwargs["project"],
383
383
  kwargs["change"],
384
- phase="run",
384
+ phase="execute",
385
385
  executor=kwargs["executor"],
386
386
  preparation_id=kwargs["preparation_id"],
387
387
  )
@@ -394,7 +394,7 @@ def _default_gate_begin(**kwargs: Any) -> dict[str, Any]:
394
394
  "begin",
395
395
  "--json",
396
396
  "--phase",
397
- "run",
397
+ "execute",
398
398
  "--change",
399
399
  str(kwargs["change"]),
400
400
  "--project",
@@ -405,6 +405,10 @@ def _default_gate_begin(**kwargs: Any) -> dict[str, Any]:
405
405
  str(kwargs["run_id"]),
406
406
  "--note",
407
407
  "开始处理评审中确认需要修改的代码问题。",
408
+ # 显式标记这一轮是 review fixback。以前靠 gate 嗅探 note 里有没有
409
+ # "fixback" 字样——而上面这条 note 一个都没有,于是 fixback 的 run 事件
410
+ # 从来没被打上 trigger/from_phase。
411
+ "--fixback",
408
412
  ]
409
413
  for option, key in (
410
414
  ("--executor-tool", "executor_tool"),
@@ -483,7 +487,7 @@ def launch_review_fixback(
483
487
  started_at = time.monotonic()
484
488
  start_event = he.append_event(
485
489
  change_dir,
486
- phase="run",
490
+ phase="execute",
487
491
  type_="phase.prepare.start",
488
492
  note="正在检查评审修复的前置条件。",
489
493
  run_id=effective_run_id,
@@ -518,7 +522,7 @@ def launch_review_fixback(
518
522
  message = str(result.get("message") or result.get("error") or "前置条件未满足,修复未启动。")
519
523
  he.append_event(
520
524
  change_dir,
521
- phase="run",
525
+ phase="execute",
522
526
  type_="phase.prepare.end",
523
527
  status="BLOCKED",
524
528
  code=code,
@@ -537,7 +541,7 @@ def launch_review_fixback(
537
541
  "ok": False,
538
542
  "code": code,
539
543
  "message": message,
540
- "recoveryAction": "处理提示的前置条件后重新执行 /harness-run --fixback",
544
+ "recoveryAction": "处理提示的前置条件后重新执行 /harness-execute --fixback",
541
545
  "preparationDurationMs": duration,
542
546
  "contextCancellation": cancellation,
543
547
  }
@@ -562,7 +566,7 @@ def launch_review_fixback(
562
566
  duration = max(0, round((time.monotonic() - started_at) * 1000))
563
567
  he.append_event(
564
568
  change_dir,
565
- phase="run",
569
+ phase="execute",
566
570
  type_="phase.prepare.end",
567
571
  status="STARTED",
568
572
  message="前置条件已满足,修复编码已启动。",
@@ -661,7 +665,7 @@ def resume_batch(
661
665
  _write_json(session_path, session)
662
666
  he.append_event(
663
667
  change_dir,
664
- phase="run",
668
+ phase="execute",
665
669
  type_="decision",
666
670
  note=(
667
671
  "已恢复现有修复批次,将从未完成步骤继续。"