@hunter-harness/workflow-harness 0.2.9 → 0.2.11

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/harness-archive/SKILL.md +1 -1
  3. package/harness/bundles/general/claude-code/harness-archive/reference.md +12 -2
  4. package/harness/bundles/general/claude-code/harness-archive/templates/summary-data-template.json +6 -2
  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 +3 -1
  7. package/harness/bundles/general/claude-code/harness-knowledge-ingest/reference.md +7 -0
  8. package/harness/bundles/general/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  9. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  10. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-review/SKILL.md +3 -3
  12. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-run/reference.md +2 -0
  14. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +15 -10
  15. package/harness/bundles/general/claude-code/harness-submit/checklist.md +40 -76
  16. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +17 -2
  17. package/harness/bundles/general/claude-code/harness-sync/reference.md +2 -2
  18. package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
  19. package/harness/bundles/general/claude-code/harness-test/reference.md +2 -0
  20. package/harness/bundles/general/claude-code/protocols/archive-report-protocol.md +24 -4
  21. package/harness/bundles/general/claude-code/protocols/ledger-protocol.md +36 -0
  22. package/harness/bundles/general/claude-code/protocols/state-layout-protocol.md +15 -0
  23. package/harness/bundles/general/claude-code/scripts/harness_archive.py +803 -274
  24. package/harness/bundles/general/claude-code/scripts/harness_change.py +18 -0
  25. package/harness/bundles/general/claude-code/scripts/harness_deploy.py +1 -44
  26. package/harness/bundles/general/claude-code/scripts/harness_events.py +104 -6
  27. package/harness/bundles/general/claude-code/scripts/harness_gate.py +25 -4
  28. package/harness/bundles/general/claude-code/scripts/harness_integration.py +878 -0
  29. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +440 -10
  30. package/harness/bundles/general/claude-code/scripts/harness_paths.py +315 -0
  31. package/harness/bundles/general/claude-code/scripts/harness_profile.py +45 -0
  32. package/harness/bundles/general/claude-code/scripts/harness_review.py +326 -0
  33. package/harness/bundles/general/claude-code/scripts/harness_sync.py +407 -0
  34. package/harness/bundles/general/claude-code/scripts/harness_test_guard.py +244 -49
  35. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  36. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  37. package/harness/bundles/general/codebuddy/harness-archive/reference.md +12 -2
  38. package/harness/bundles/general/codebuddy/harness-archive/templates/summary-data-template.json +6 -2
  39. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  40. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +3 -1
  41. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/reference.md +7 -0
  42. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  43. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  44. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
  45. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +3 -3
  46. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  47. package/harness/bundles/general/codebuddy/harness-run/reference.md +2 -0
  48. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +15 -10
  49. package/harness/bundles/general/codebuddy/harness-submit/checklist.md +40 -76
  50. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +17 -2
  51. package/harness/bundles/general/codebuddy/harness-sync/reference.md +2 -2
  52. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
  53. package/harness/bundles/general/codebuddy/harness-test/reference.md +2 -0
  54. package/harness/bundles/general/codebuddy/protocols/archive-report-protocol.md +24 -4
  55. package/harness/bundles/general/codebuddy/protocols/ledger-protocol.md +36 -0
  56. package/harness/bundles/general/codebuddy/protocols/state-layout-protocol.md +15 -0
  57. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +803 -274
  58. package/harness/bundles/general/codebuddy/scripts/harness_change.py +18 -0
  59. package/harness/bundles/general/codebuddy/scripts/harness_deploy.py +1 -44
  60. package/harness/bundles/general/codebuddy/scripts/harness_events.py +104 -6
  61. package/harness/bundles/general/codebuddy/scripts/harness_gate.py +25 -4
  62. package/harness/bundles/general/codebuddy/scripts/harness_integration.py +878 -0
  63. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +440 -10
  64. package/harness/bundles/general/codebuddy/scripts/harness_paths.py +315 -0
  65. package/harness/bundles/general/codebuddy/scripts/harness_profile.py +45 -0
  66. package/harness/bundles/general/codebuddy/scripts/harness_review.py +326 -0
  67. package/harness/bundles/general/codebuddy/scripts/harness_sync.py +407 -0
  68. package/harness/bundles/general/codebuddy/scripts/harness_test_guard.py +244 -49
  69. package/harness/bundles/general/codex/.harness-build.json +1 -1
  70. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  71. package/harness/bundles/general/codex/harness-archive/reference.md +12 -2
  72. package/harness/bundles/general/codex/harness-archive/templates/summary-data-template.json +6 -2
  73. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  74. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +3 -1
  75. package/harness/bundles/general/codex/harness-knowledge-ingest/reference.md +7 -0
  76. package/harness/bundles/general/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  77. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  78. package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
  79. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  80. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  81. package/harness/bundles/general/codex/harness-run/reference.md +2 -0
  82. package/harness/bundles/general/codex/harness-submit/SKILL.md +15 -10
  83. package/harness/bundles/general/codex/harness-submit/checklist.md +40 -76
  84. package/harness/bundles/general/codex/harness-sync/SKILL.md +17 -2
  85. package/harness/bundles/general/codex/harness-sync/reference.md +2 -2
  86. package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
  87. package/harness/bundles/general/codex/harness-test/reference.md +2 -0
  88. package/harness/bundles/general/codex/protocols/archive-report-protocol.md +24 -4
  89. package/harness/bundles/general/codex/protocols/ledger-protocol.md +36 -0
  90. package/harness/bundles/general/codex/protocols/state-layout-protocol.md +15 -0
  91. package/harness/bundles/general/codex/scripts/harness_archive.py +803 -274
  92. package/harness/bundles/general/codex/scripts/harness_change.py +18 -0
  93. package/harness/bundles/general/codex/scripts/harness_deploy.py +1 -44
  94. package/harness/bundles/general/codex/scripts/harness_events.py +104 -6
  95. package/harness/bundles/general/codex/scripts/harness_gate.py +25 -4
  96. package/harness/bundles/general/codex/scripts/harness_integration.py +878 -0
  97. package/harness/bundles/general/codex/scripts/harness_ledger.py +440 -10
  98. package/harness/bundles/general/codex/scripts/harness_paths.py +315 -0
  99. package/harness/bundles/general/codex/scripts/harness_profile.py +45 -0
  100. package/harness/bundles/general/codex/scripts/harness_review.py +326 -0
  101. package/harness/bundles/general/codex/scripts/harness_sync.py +407 -0
  102. package/harness/bundles/general/codex/scripts/harness_test_guard.py +244 -49
  103. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  104. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  105. package/harness/bundles/general/cursor/harness-archive/reference.md +12 -2
  106. package/harness/bundles/general/cursor/harness-archive/templates/summary-data-template.json +6 -2
  107. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  108. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +3 -1
  109. package/harness/bundles/general/cursor/harness-knowledge-ingest/reference.md +7 -0
  110. package/harness/bundles/general/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  111. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  112. package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
  113. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  114. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  115. package/harness/bundles/general/cursor/harness-run/reference.md +2 -0
  116. package/harness/bundles/general/cursor/harness-submit/SKILL.md +15 -10
  117. package/harness/bundles/general/cursor/harness-submit/checklist.md +40 -76
  118. package/harness/bundles/general/cursor/harness-sync/SKILL.md +17 -2
  119. package/harness/bundles/general/cursor/harness-sync/reference.md +2 -2
  120. package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
  121. package/harness/bundles/general/cursor/harness-test/reference.md +2 -0
  122. package/harness/bundles/general/cursor/protocols/archive-report-protocol.md +24 -4
  123. package/harness/bundles/general/cursor/protocols/ledger-protocol.md +36 -0
  124. package/harness/bundles/general/cursor/protocols/state-layout-protocol.md +15 -0
  125. package/harness/bundles/general/cursor/scripts/harness_archive.py +803 -274
  126. package/harness/bundles/general/cursor/scripts/harness_change.py +18 -0
  127. package/harness/bundles/general/cursor/scripts/harness_deploy.py +1 -44
  128. package/harness/bundles/general/cursor/scripts/harness_events.py +104 -6
  129. package/harness/bundles/general/cursor/scripts/harness_gate.py +25 -4
  130. package/harness/bundles/general/cursor/scripts/harness_integration.py +878 -0
  131. package/harness/bundles/general/cursor/scripts/harness_ledger.py +440 -10
  132. package/harness/bundles/general/cursor/scripts/harness_paths.py +315 -0
  133. package/harness/bundles/general/cursor/scripts/harness_profile.py +45 -0
  134. package/harness/bundles/general/cursor/scripts/harness_review.py +326 -0
  135. package/harness/bundles/general/cursor/scripts/harness_sync.py +407 -0
  136. package/harness/bundles/general/cursor/scripts/harness_test_guard.py +244 -49
  137. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  138. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  139. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  140. package/harness/bundles/java/claude-code/harness-archive/reference.md +12 -2
  141. package/harness/bundles/java/claude-code/harness-archive/templates/summary-data-template.json +6 -2
  142. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  143. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +3 -1
  144. package/harness/bundles/java/claude-code/harness-knowledge-ingest/reference.md +7 -0
  145. package/harness/bundles/java/claude-code/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  146. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  147. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  148. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
  149. package/harness/bundles/java/claude-code/harness-review/SKILL.md +3 -3
  150. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  151. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +15 -10
  152. package/harness/bundles/java/claude-code/harness-submit/checklist.md +40 -76
  153. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +17 -2
  154. package/harness/bundles/java/claude-code/harness-sync/reference.md +2 -2
  155. package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
  156. package/harness/bundles/java/claude-code/protocols/archive-report-protocol.md +24 -4
  157. package/harness/bundles/java/claude-code/protocols/ledger-protocol.md +36 -0
  158. package/harness/bundles/java/claude-code/protocols/state-layout-protocol.md +15 -0
  159. package/harness/bundles/java/claude-code/scripts/harness_archive.py +803 -274
  160. package/harness/bundles/java/claude-code/scripts/harness_change.py +18 -0
  161. package/harness/bundles/java/claude-code/scripts/harness_deploy.py +1 -44
  162. package/harness/bundles/java/claude-code/scripts/harness_events.py +104 -6
  163. package/harness/bundles/java/claude-code/scripts/harness_gate.py +25 -4
  164. package/harness/bundles/java/claude-code/scripts/harness_integration.py +878 -0
  165. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +440 -10
  166. package/harness/bundles/java/claude-code/scripts/harness_paths.py +315 -0
  167. package/harness/bundles/java/claude-code/scripts/harness_profile.py +45 -0
  168. package/harness/bundles/java/claude-code/scripts/harness_review.py +326 -0
  169. package/harness/bundles/java/claude-code/scripts/harness_sync.py +407 -0
  170. package/harness/bundles/java/claude-code/scripts/harness_test_guard.py +244 -49
  171. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  172. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  173. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  174. package/harness/bundles/java/codebuddy/harness-archive/reference.md +12 -2
  175. package/harness/bundles/java/codebuddy/harness-archive/templates/summary-data-template.json +6 -2
  176. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  177. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +3 -1
  178. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/reference.md +7 -0
  179. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  180. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  181. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  182. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
  183. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +3 -3
  184. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  185. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +15 -10
  186. package/harness/bundles/java/codebuddy/harness-submit/checklist.md +40 -76
  187. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +17 -2
  188. package/harness/bundles/java/codebuddy/harness-sync/reference.md +2 -2
  189. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
  190. package/harness/bundles/java/codebuddy/protocols/archive-report-protocol.md +24 -4
  191. package/harness/bundles/java/codebuddy/protocols/ledger-protocol.md +36 -0
  192. package/harness/bundles/java/codebuddy/protocols/state-layout-protocol.md +15 -0
  193. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +803 -274
  194. package/harness/bundles/java/codebuddy/scripts/harness_change.py +18 -0
  195. package/harness/bundles/java/codebuddy/scripts/harness_deploy.py +1 -44
  196. package/harness/bundles/java/codebuddy/scripts/harness_events.py +104 -6
  197. package/harness/bundles/java/codebuddy/scripts/harness_gate.py +25 -4
  198. package/harness/bundles/java/codebuddy/scripts/harness_integration.py +878 -0
  199. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +440 -10
  200. package/harness/bundles/java/codebuddy/scripts/harness_paths.py +315 -0
  201. package/harness/bundles/java/codebuddy/scripts/harness_profile.py +45 -0
  202. package/harness/bundles/java/codebuddy/scripts/harness_review.py +326 -0
  203. package/harness/bundles/java/codebuddy/scripts/harness_sync.py +407 -0
  204. package/harness/bundles/java/codebuddy/scripts/harness_test_guard.py +244 -49
  205. package/harness/bundles/java/codex/.harness-build.json +1 -1
  206. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  207. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  208. package/harness/bundles/java/codex/harness-archive/reference.md +12 -2
  209. package/harness/bundles/java/codex/harness-archive/templates/summary-data-template.json +6 -2
  210. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  211. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +3 -1
  212. package/harness/bundles/java/codex/harness-knowledge-ingest/reference.md +7 -0
  213. package/harness/bundles/java/codex/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  214. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  215. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  216. package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
  217. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  218. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  219. package/harness/bundles/java/codex/harness-submit/SKILL.md +15 -10
  220. package/harness/bundles/java/codex/harness-submit/checklist.md +40 -76
  221. package/harness/bundles/java/codex/harness-sync/SKILL.md +17 -2
  222. package/harness/bundles/java/codex/harness-sync/reference.md +2 -2
  223. package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
  224. package/harness/bundles/java/codex/protocols/archive-report-protocol.md +24 -4
  225. package/harness/bundles/java/codex/protocols/ledger-protocol.md +36 -0
  226. package/harness/bundles/java/codex/protocols/state-layout-protocol.md +15 -0
  227. package/harness/bundles/java/codex/scripts/harness_archive.py +803 -274
  228. package/harness/bundles/java/codex/scripts/harness_change.py +18 -0
  229. package/harness/bundles/java/codex/scripts/harness_deploy.py +1 -44
  230. package/harness/bundles/java/codex/scripts/harness_events.py +104 -6
  231. package/harness/bundles/java/codex/scripts/harness_gate.py +25 -4
  232. package/harness/bundles/java/codex/scripts/harness_integration.py +878 -0
  233. package/harness/bundles/java/codex/scripts/harness_ledger.py +440 -10
  234. package/harness/bundles/java/codex/scripts/harness_paths.py +315 -0
  235. package/harness/bundles/java/codex/scripts/harness_profile.py +45 -0
  236. package/harness/bundles/java/codex/scripts/harness_review.py +326 -0
  237. package/harness/bundles/java/codex/scripts/harness_sync.py +407 -0
  238. package/harness/bundles/java/codex/scripts/harness_test_guard.py +244 -49
  239. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  240. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  241. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  242. package/harness/bundles/java/cursor/harness-archive/reference.md +12 -2
  243. package/harness/bundles/java/cursor/harness-archive/templates/summary-data-template.json +6 -2
  244. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  245. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +3 -1
  246. package/harness/bundles/java/cursor/harness-knowledge-ingest/reference.md +7 -0
  247. package/harness/bundles/java/cursor/harness-knowledge-ingest/scripts/harness_knowledge.py +141 -2
  248. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  249. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  250. package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
  251. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  252. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  253. package/harness/bundles/java/cursor/harness-submit/SKILL.md +15 -10
  254. package/harness/bundles/java/cursor/harness-submit/checklist.md +40 -76
  255. package/harness/bundles/java/cursor/harness-sync/SKILL.md +17 -2
  256. package/harness/bundles/java/cursor/harness-sync/reference.md +2 -2
  257. package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
  258. package/harness/bundles/java/cursor/protocols/archive-report-protocol.md +24 -4
  259. package/harness/bundles/java/cursor/protocols/ledger-protocol.md +36 -0
  260. package/harness/bundles/java/cursor/protocols/state-layout-protocol.md +15 -0
  261. package/harness/bundles/java/cursor/scripts/harness_archive.py +803 -274
  262. package/harness/bundles/java/cursor/scripts/harness_change.py +18 -0
  263. package/harness/bundles/java/cursor/scripts/harness_deploy.py +1 -44
  264. package/harness/bundles/java/cursor/scripts/harness_events.py +104 -6
  265. package/harness/bundles/java/cursor/scripts/harness_gate.py +25 -4
  266. package/harness/bundles/java/cursor/scripts/harness_integration.py +878 -0
  267. package/harness/bundles/java/cursor/scripts/harness_ledger.py +440 -10
  268. package/harness/bundles/java/cursor/scripts/harness_paths.py +315 -0
  269. package/harness/bundles/java/cursor/scripts/harness_profile.py +45 -0
  270. package/harness/bundles/java/cursor/scripts/harness_review.py +326 -0
  271. package/harness/bundles/java/cursor/scripts/harness_sync.py +407 -0
  272. package/harness/bundles/java/cursor/scripts/harness_test_guard.py +244 -49
  273. package/harness/manifests/general/claude-code.json +47 -31
  274. package/harness/manifests/general/codebuddy.json +47 -31
  275. package/harness/manifests/general/codex.json +47 -31
  276. package/harness/manifests/general/cursor.json +47 -31
  277. package/harness/manifests/java/claude-code.json +47 -31
  278. package/harness/manifests/java/codebuddy.json +47 -31
  279. package/harness/manifests/java/codex.json +47 -31
  280. package/harness/manifests/java/cursor.json +47 -31
  281. package/hunter-workflow-family.json +2 -2
  282. package/package.json +1 -1
@@ -0,0 +1,407 @@
1
+ """harness_sync — 受管 sync runtime 清理器(变更簇 D / task 13,RET-36/37/38/39)。
2
+
3
+ 每次 sync 使用 `.harness/runtime/sync/<run-id>/deploy/<agent>/` 并写
4
+ `owner.json`(runId/pid/processStart/startedAt/agent/purpose/expiresAt)。
5
+ 正常、失败与异常退出均在 finally 清理本 run(`SyncRun` 上下文管理器 /
6
+ `finalize_run`)。启动时 `reap_stale_runs` 只回收同时满足以下条件的目录:
7
+
8
+ 1. owner 进程已死亡(pid liveness + create-time 匹配,可注入);
9
+ 2. 已超过 TTL(expiresAt < now);
10
+ 3. 删除目标 resolved 后仍位于精确 sync runtime root 内;
11
+ 4. 不是当前活跃 run。
12
+
13
+ owner 缺失的 legacy 目录默认只报告 `unverifiable`,不删除;显式
14
+ `--diagnose` 模式才处理。删除失败只产生带精确路径的 warning。
15
+
16
+ 本模块不做任何 `.gitignore` / `git check-ignore` 判断(RET-34/COM-004),
17
+ 不修改也不建议修改项目 Git 策略。
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import argparse
23
+ import json
24
+ import os
25
+ import re
26
+ import shutil
27
+ import sys
28
+ import uuid
29
+ from dataclasses import dataclass, field
30
+ from datetime import datetime, timedelta, timezone
31
+ from pathlib import Path
32
+ from typing import Any, Callable
33
+
34
+ SYNC_RUNTIME_REL = Path(".harness") / "runtime" / "sync"
35
+ OWNER_FILE = "owner.json"
36
+ OWNER_SCHEMA_VERSION = 1
37
+ DEFAULT_TTL_SECONDS = 3600
38
+
39
+ _RUN_ID_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$")
40
+
41
+
42
+ def _now() -> datetime:
43
+ return datetime.now(timezone.utc)
44
+
45
+
46
+ def _iso(value: datetime) -> str:
47
+ return value.astimezone(timezone.utc).isoformat()
48
+
49
+
50
+ def _parse_iso(raw: Any) -> datetime | None:
51
+ if not isinstance(raw, str) or not raw.strip():
52
+ return None
53
+ text = raw.strip()
54
+ if text.endswith("Z"):
55
+ text = text[:-1] + "+00:00"
56
+ try:
57
+ parsed = datetime.fromisoformat(text)
58
+ except ValueError:
59
+ return None
60
+ if parsed.tzinfo is None:
61
+ parsed = parsed.replace(tzinfo=timezone.utc)
62
+ return parsed.astimezone(timezone.utc)
63
+
64
+
65
+ def sync_runtime_root(project_root: Path | str) -> Path:
66
+ return Path(project_root) / SYNC_RUNTIME_REL
67
+
68
+
69
+ def _validate_run_id(run_id: str) -> str:
70
+ if not isinstance(run_id, str) or not _RUN_ID_RE.match(run_id):
71
+ raise ValueError(f"invalid run id: {run_id!r}")
72
+ if run_id in {".", ".."} or "/" in run_id or "\\" in run_id:
73
+ raise ValueError(f"run id must not escape sync root: {run_id!r}")
74
+ return run_id
75
+
76
+
77
+ def _process_start_marker() -> str:
78
+ """Best-effort process create-time marker for owner liveness matching.
79
+
80
+ 跨平台保守实现:boot 时间 + pid 足以区分同 pid 的不同世代进程。
81
+ """
82
+ try:
83
+ with open("/proc/stat", "r", encoding="utf-8") as handle:
84
+ for line in handle:
85
+ if line.startswith("btime"):
86
+ return f"boot:{line.split()[1]}"
87
+ except OSError:
88
+ pass
89
+ return f"pid:{os.getpid()} boot:unknown"
90
+
91
+
92
+ def _default_pid_alive(pid: int, process_start: str | None) -> bool:
93
+ if pid <= 0:
94
+ return False
95
+ try:
96
+ os.kill(pid, 0)
97
+ except ProcessLookupError:
98
+ return False
99
+ except PermissionError:
100
+ return True
101
+ except OSError:
102
+ return False
103
+ return True
104
+
105
+
106
+ @dataclass
107
+ class SyncRun:
108
+ """Handle for one sync run; use as context manager for finally cleanup."""
109
+
110
+ project_root: Path
111
+ run_id: str
112
+ purpose: str
113
+ ttl_seconds: int = DEFAULT_TTL_SECONDS
114
+ keep_temp: bool = False
115
+ agents: list[str] = field(default_factory=list)
116
+ _finalized: bool = False
117
+
118
+ @property
119
+ def run_dir(self) -> Path:
120
+ return sync_runtime_root(self.project_root) / self.run_id
121
+
122
+ def workspace(self, agent: str) -> Path:
123
+ return self.run_dir / "deploy" / agent
124
+
125
+ def __enter__(self) -> "SyncRun":
126
+ return self
127
+
128
+ def __exit__(self, exc_type, exc, tb) -> bool:
129
+ finalize_run(self)
130
+ return False
131
+
132
+
133
+ def _write_json(path: Path, payload: dict[str, Any]) -> None:
134
+ path.parent.mkdir(parents=True, exist_ok=True)
135
+ path.write_text(
136
+ json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
137
+ )
138
+
139
+
140
+ def _read_json(path: Path) -> dict[str, Any] | None:
141
+ try:
142
+ data = json.loads(path.read_text(encoding="utf-8"))
143
+ except (OSError, json.JSONDecodeError):
144
+ return None
145
+ return data if isinstance(data, dict) else None
146
+
147
+
148
+ def begin_run(
149
+ project_root: Path | str,
150
+ *,
151
+ run_id: str | None = None,
152
+ agent: str,
153
+ purpose: str,
154
+ ttl_seconds: int = DEFAULT_TTL_SECONDS,
155
+ keep_temp: bool = False,
156
+ ) -> SyncRun:
157
+ """Create `.harness/runtime/sync/<run-id>/deploy/<agent>/` + owner.json."""
158
+ root = Path(project_root)
159
+ run_id = _validate_run_id(run_id or f"sync-{uuid.uuid4().hex[:12]}")
160
+ run = SyncRun(
161
+ project_root=root,
162
+ run_id=run_id,
163
+ purpose=purpose,
164
+ ttl_seconds=ttl_seconds,
165
+ keep_temp=keep_temp,
166
+ agents=[agent],
167
+ )
168
+ workspace = run.workspace(agent)
169
+ workspace.mkdir(parents=True, exist_ok=True)
170
+ started = _now()
171
+ owner = {
172
+ "schemaVersion": OWNER_SCHEMA_VERSION,
173
+ "runId": run_id,
174
+ "pid": os.getpid(),
175
+ "processStart": _process_start_marker(),
176
+ "startedAt": _iso(started),
177
+ "agent": agent,
178
+ "agents": [agent],
179
+ "purpose": purpose,
180
+ "expiresAt": _iso(started + timedelta(seconds=ttl_seconds)),
181
+ }
182
+ _write_json(run.run_dir / OWNER_FILE, owner)
183
+ return run
184
+
185
+
186
+ def register_agent_workspace(run: SyncRun, agent: str) -> Path:
187
+ """Add another agent workspace under the same run-id (INT-008)."""
188
+ workspace = run.workspace(agent)
189
+ workspace.mkdir(parents=True, exist_ok=True)
190
+ if agent not in run.agents:
191
+ run.agents.append(agent)
192
+ owner_path = run.run_dir / OWNER_FILE
193
+ owner = _read_json(owner_path)
194
+ if owner is not None:
195
+ agents = owner.get("agents")
196
+ if not isinstance(agents, list):
197
+ agents = [owner.get("agent")]
198
+ if agent not in agents:
199
+ agents.append(agent)
200
+ owner["agents"] = agents
201
+ _write_json(owner_path, owner)
202
+ return workspace
203
+
204
+
205
+ def finalize_run(run: SyncRun) -> None:
206
+ """Remove this run's workspace unless keep_temp diagnostics requested it."""
207
+ if run._finalized:
208
+ return
209
+ run._finalized = True
210
+ if run.keep_temp:
211
+ return
212
+ run_dir = run.run_dir
213
+ if run_dir.exists():
214
+ shutil.rmtree(run_dir, ignore_errors=True)
215
+
216
+
217
+ def finalize_run_id(
218
+ project_root: Path | str, run_id: str, *, keep_temp: bool = False
219
+ ) -> dict[str, Any]:
220
+ """Finalize one exact CLI-managed run with the same boundary checks."""
221
+ run_id = _validate_run_id(run_id)
222
+ root = sync_runtime_root(project_root).resolve()
223
+ run_dir = (root / run_id).resolve()
224
+ if not _inside_resolved(run_dir, root) or run_dir == root:
225
+ raise ValueError(f"run path escapes sync root: {run_dir}")
226
+ existed = run_dir.is_dir()
227
+ if existed and not keep_temp:
228
+ shutil.rmtree(run_dir)
229
+ return {
230
+ "ok": True,
231
+ "action": "finalize",
232
+ "runId": run_id,
233
+ "deleted": existed and not keep_temp,
234
+ "kept": bool(existed and keep_temp),
235
+ }
236
+
237
+
238
+ def _inside_resolved(child: Path, parent: Path) -> bool:
239
+ try:
240
+ resolved_child = child.resolve()
241
+ resolved_parent = parent.resolve()
242
+ except OSError:
243
+ return False
244
+ return resolved_child == resolved_parent or resolved_parent in resolved_child.parents
245
+
246
+
247
+ def reap_stale_runs(
248
+ project_root: Path | str,
249
+ *,
250
+ now: datetime | None = None,
251
+ pid_alive: Callable[[int, str | None], bool] | None = None,
252
+ active_run_ids: set[str] | None = None,
253
+ diagnose: bool = False,
254
+ ) -> dict[str, Any]:
255
+ """Reap only dead-owner + past-TTL dirs inside the exact sync root.
256
+
257
+ Ownerless legacy dirs are reported as ``unverifiable`` and left alone
258
+ unless ``diagnose=True`` explicitly handles them.
259
+ """
260
+ now = now or _now()
261
+ alive = pid_alive or _default_pid_alive
262
+ active = active_run_ids or set()
263
+ result: dict[str, Any] = {
264
+ "ok": True,
265
+ "reaped": [],
266
+ "skipped": [],
267
+ "unverifiable": [],
268
+ "warnings": [],
269
+ }
270
+ root = sync_runtime_root(project_root)
271
+ if not root.is_dir():
272
+ return result
273
+
274
+ for entry in sorted(root.iterdir()):
275
+ if not entry.is_dir():
276
+ continue
277
+ run_id = entry.name
278
+ # 删除目标必须 resolved 后仍位于精确 sync root 内(RET-39)。
279
+ if not _inside_resolved(entry, root):
280
+ result["warnings"].append(f"path escapes sync root, untouched: {entry}")
281
+ continue
282
+ if run_id in active:
283
+ result["skipped"].append(run_id)
284
+ continue
285
+ owner_path = entry / OWNER_FILE
286
+ owner = _read_json(owner_path) if owner_path.is_file() else None
287
+ if owner is None:
288
+ # owner 缺失的 legacy 目录:默认只报告 UNVERIFIABLE,不删除。
289
+ result["unverifiable"].append(run_id)
290
+ if diagnose:
291
+ try:
292
+ shutil.rmtree(entry)
293
+ result["reaped"].append(run_id)
294
+ except OSError as exc:
295
+ result["warnings"].append(f"failed to remove {entry}: {exc}")
296
+ continue
297
+ pid = owner.get("pid")
298
+ process_start = owner.get("processStart")
299
+ expires = _parse_iso(owner.get("expiresAt"))
300
+ owner_dead = not alive(int(pid) if isinstance(pid, int) else -1, process_start)
301
+ past_ttl = expires is not None and expires < now
302
+ if owner_dead and past_ttl:
303
+ try:
304
+ shutil.rmtree(entry)
305
+ result["reaped"].append(run_id)
306
+ except OSError as exc:
307
+ result["warnings"].append(f"failed to remove {entry}: {exc}")
308
+ else:
309
+ result["skipped"].append(run_id)
310
+ return result
311
+
312
+
313
+ def cmd_reap(args: argparse.Namespace) -> int:
314
+ result = reap_stale_runs(
315
+ Path(args.project),
316
+ active_run_ids=set(args.active_run or []),
317
+ diagnose=bool(args.diagnose),
318
+ )
319
+ payload = {"action": "reap", **result}
320
+ if args.json:
321
+ print(json.dumps(payload, ensure_ascii=False))
322
+ else:
323
+ reaped = ", ".join(result["reaped"]) or "-"
324
+ skipped = ", ".join(result["skipped"]) or "-"
325
+ unverifiable = ", ".join(result["unverifiable"]) or "-"
326
+ print(f"reaped: {reaped}")
327
+ print(f"skipped: {skipped}")
328
+ print(f"unverifiable: {unverifiable}")
329
+ for warning in result["warnings"]:
330
+ print(f"warning: {warning}", file=sys.stderr)
331
+ return 0
332
+
333
+
334
+ def cmd_begin(args: argparse.Namespace) -> int:
335
+ run = begin_run(
336
+ Path(args.project),
337
+ run_id=args.run_id,
338
+ agent=args.agent,
339
+ purpose=args.purpose,
340
+ ttl_seconds=args.ttl_seconds,
341
+ keep_temp=bool(args.keep_temp),
342
+ )
343
+ payload = {
344
+ "ok": True,
345
+ "action": "begin",
346
+ "runId": run.run_id,
347
+ "runDir": str(run.run_dir.resolve()),
348
+ "workspace": str(run.workspace(args.agent).resolve()),
349
+ }
350
+ print(json.dumps(payload, ensure_ascii=False) if args.json else payload["workspace"])
351
+ return 0
352
+
353
+
354
+ def cmd_finalize(args: argparse.Namespace) -> int:
355
+ payload = finalize_run_id(
356
+ Path(args.project), args.run_id, keep_temp=bool(args.keep_temp)
357
+ )
358
+ print(json.dumps(payload, ensure_ascii=False) if args.json else payload["runId"])
359
+ return 0
360
+
361
+
362
+ def build_parser() -> argparse.ArgumentParser:
363
+ parser = argparse.ArgumentParser(
364
+ prog="harness_sync",
365
+ description="managed sync runtime owner/TTL/finally cleaner",
366
+ )
367
+ sub = parser.add_subparsers(dest="command", required=True)
368
+ p_begin = sub.add_parser("begin", help="create one owned sync runtime")
369
+ p_begin.add_argument("--project", required=True)
370
+ p_begin.add_argument("--run-id")
371
+ p_begin.add_argument("--agent", required=True)
372
+ p_begin.add_argument("--purpose", required=True)
373
+ p_begin.add_argument("--ttl-seconds", type=int, default=DEFAULT_TTL_SECONDS)
374
+ p_begin.add_argument("--keep-temp", action="store_true")
375
+ p_begin.add_argument("--json", action="store_true")
376
+ p_begin.set_defaults(func=cmd_begin)
377
+ p_finalize = sub.add_parser("finalize", help="remove one exact owned sync runtime")
378
+ p_finalize.add_argument("--project", required=True)
379
+ p_finalize.add_argument("--run-id", required=True)
380
+ p_finalize.add_argument("--keep-temp", action="store_true")
381
+ p_finalize.add_argument("--json", action="store_true")
382
+ p_finalize.set_defaults(func=cmd_finalize)
383
+ p_reap = sub.add_parser("reap", help="reap dead-owner past-TTL sync run dirs")
384
+ p_reap.add_argument("--project", required=True, help="project root path")
385
+ p_reap.add_argument("--json", action="store_true", help="emit JSON payload")
386
+ p_reap.add_argument(
387
+ "--diagnose",
388
+ action="store_true",
389
+ help="explicit diagnostics mode: also remove ownerless legacy dirs",
390
+ )
391
+ p_reap.add_argument(
392
+ "--active-run",
393
+ action="append",
394
+ default=[],
395
+ help="run id still active (never reaped); repeatable",
396
+ )
397
+ p_reap.set_defaults(func=cmd_reap)
398
+ return parser
399
+
400
+
401
+ def main(argv: list[str] | None = None) -> int:
402
+ args = build_parser().parse_args(argv)
403
+ return int(args.func(args))
404
+
405
+
406
+ if __name__ == "__main__":
407
+ sys.exit(main())