@hunter-harness/workflow-harness 0.4.0 → 0.4.1

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 (386) 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-codebase-map/SKILL.md +1 -1
  4. package/harness/bundles/general/claude-code/harness-execute/SKILL.md +1 -1
  5. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  6. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  7. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
  8. package/harness/bundles/general/claude-code/harness-pull/SKILL.md +1 -1
  9. package/harness/bundles/general/claude-code/harness-push/SKILL.md +1 -1
  10. package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  12. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  14. package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
  15. package/harness/bundles/general/claude-code/scripts/harness_archive.py +29 -6
  16. package/harness/bundles/general/claude-code/scripts/harness_deploy.py +1 -1
  17. package/harness/bundles/general/claude-code/scripts/harness_knowledge_candidates.py +398 -0
  18. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  19. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  20. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  21. package/harness/bundles/general/codebuddy/harness-execute/SKILL.md +1 -1
  22. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  23. package/harness/bundles/general/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  24. package/harness/bundles/general/codebuddy/harness-plan/SKILL.md +1 -1
  25. package/harness/bundles/general/codebuddy/harness-pull/SKILL.md +1 -1
  26. package/harness/bundles/general/codebuddy/harness-push/SKILL.md +1 -1
  27. package/harness/bundles/general/codebuddy/harness-review/SKILL.md +1 -1
  28. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  29. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
  30. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  31. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
  32. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +29 -6
  33. package/harness/bundles/general/codebuddy/scripts/harness_deploy.py +1 -1
  34. package/harness/bundles/general/codebuddy/scripts/harness_knowledge_candidates.py +398 -0
  35. package/harness/bundles/general/codex/.harness-build.json +1 -1
  36. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  37. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  38. package/harness/bundles/general/codex/harness-execute/SKILL.md +1 -1
  39. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  40. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  41. package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
  42. package/harness/bundles/general/codex/harness-pull/SKILL.md +1 -1
  43. package/harness/bundles/general/codex/harness-push/SKILL.md +1 -1
  44. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  45. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  46. package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
  47. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  48. package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
  49. package/harness/bundles/general/codex/scripts/harness_archive.py +29 -6
  50. package/harness/bundles/general/codex/scripts/harness_deploy.py +1 -1
  51. package/harness/bundles/general/codex/scripts/harness_knowledge_candidates.py +398 -0
  52. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  53. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  54. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  55. package/harness/bundles/general/cursor/harness-execute/SKILL.md +1 -1
  56. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  57. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  58. package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
  59. package/harness/bundles/general/cursor/harness-pull/SKILL.md +1 -1
  60. package/harness/bundles/general/cursor/harness-push/SKILL.md +1 -1
  61. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  62. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  63. package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
  64. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  65. package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
  66. package/harness/bundles/general/cursor/scripts/harness_archive.py +29 -6
  67. package/harness/bundles/general/cursor/scripts/harness_deploy.py +1 -1
  68. package/harness/bundles/general/cursor/scripts/harness_knowledge_candidates.py +398 -0
  69. package/harness/bundles/general/pi/.harness-build.json +6 -0
  70. package/harness/bundles/general/pi/CONTEXT.md +98 -0
  71. package/harness/bundles/general/pi/README.md +478 -0
  72. package/harness/bundles/general/pi/contracts/build-profile-v3.schema.json +302 -0
  73. package/harness/bundles/general/pi/contracts/ci-metrics.schema.json +36 -0
  74. package/harness/bundles/general/pi/contracts/doctor-capability.schema.json +43 -0
  75. package/harness/bundles/general/pi/contracts/external-platform-observation.schema.json +62 -0
  76. package/harness/bundles/general/pi/contracts/fixtures/managed-execution.json +341 -0
  77. package/harness/bundles/general/pi/contracts/process-identity.schema.json +132 -0
  78. package/harness/bundles/general/pi/contracts/run-session.schema.json +142 -0
  79. package/harness/bundles/general/pi/contracts/service-retirement-receipt.schema.json +85 -0
  80. package/harness/bundles/general/pi/contracts/service-session.schema.json +147 -0
  81. package/harness/bundles/general/pi/contracts/workflow-policy.json +574 -0
  82. package/harness/bundles/general/pi/harness-archive/SKILL.md +322 -0
  83. package/harness/bundles/general/pi/harness-archive/checklist.md +71 -0
  84. package/harness/bundles/general/pi/harness-archive/reference.md +150 -0
  85. package/harness/bundles/general/pi/harness-archive/scripts/gen-manifest.ps1 +31 -0
  86. package/harness/bundles/general/pi/harness-archive/templates/summary-data-template.json +218 -0
  87. package/harness/bundles/general/pi/harness-codebase-map/SKILL.md +116 -0
  88. package/harness/bundles/general/pi/harness-codebase-map/checklist.md +126 -0
  89. package/harness/bundles/general/pi/harness-codebase-map/reference.md +364 -0
  90. package/harness/bundles/general/pi/harness-codebase-map/templates/ARCHITECTURE.md +57 -0
  91. package/harness/bundles/general/pi/harness-codebase-map/templates/CONCERNS.md +49 -0
  92. package/harness/bundles/general/pi/harness-codebase-map/templates/CONVENTIONS.md +57 -0
  93. package/harness/bundles/general/pi/harness-codebase-map/templates/INTEGRATIONS.md +52 -0
  94. package/harness/bundles/general/pi/harness-codebase-map/templates/STACK.md +55 -0
  95. package/harness/bundles/general/pi/harness-codebase-map/templates/STRUCTURE.md +69 -0
  96. package/harness/bundles/general/pi/harness-codebase-map/templates/TESTING.md +64 -0
  97. package/harness/bundles/general/pi/harness-codebase-map/templates/map-manifest.schema.json +73 -0
  98. package/harness/bundles/general/pi/harness-codebase-map/templates/map-summary.md +64 -0
  99. package/harness/bundles/general/pi/harness-execute/SKILL.md +170 -0
  100. package/harness/bundles/general/pi/harness-knowledge-ingest/SKILL.md +103 -0
  101. package/harness/bundles/general/pi/harness-knowledge-query/SKILL.md +97 -0
  102. package/harness/bundles/general/pi/harness-plan/SKILL.md +158 -0
  103. package/harness/bundles/general/pi/harness-plan/checklist.md +243 -0
  104. package/harness/bundles/general/pi/harness-plan/protocols.md +133 -0
  105. package/harness/bundles/general/pi/harness-plan/reference.md +468 -0
  106. package/harness/bundles/general/pi/harness-pull/SKILL.md +55 -0
  107. package/harness/bundles/general/pi/harness-push/SKILL.md +83 -0
  108. package/harness/bundles/general/pi/harness-review/SKILL.md +175 -0
  109. package/harness/bundles/general/pi/harness-review/checklist.md +124 -0
  110. package/harness/bundles/general/pi/harness-review/protocols.md +69 -0
  111. package/harness/bundles/general/pi/harness-review/reference.md +114 -0
  112. package/harness/bundles/general/pi/harness-run/SKILL.md +188 -0
  113. package/harness/bundles/general/pi/harness-run/checklist.md +279 -0
  114. package/harness/bundles/general/pi/harness-run/protocols.md +141 -0
  115. package/harness/bundles/general/pi/harness-run/reference.md +886 -0
  116. package/harness/bundles/general/pi/harness-submit/SKILL.md +182 -0
  117. package/harness/bundles/general/pi/harness-submit/checklist.md +452 -0
  118. package/harness/bundles/general/pi/harness-submit/reference.md +152 -0
  119. package/harness/bundles/general/pi/harness-sync/SKILL.md +72 -0
  120. package/harness/bundles/general/pi/harness-sync/reference.md +176 -0
  121. package/harness/bundles/general/pi/harness-test/SKILL.md +250 -0
  122. package/harness/bundles/general/pi/harness-test/checklist.md +359 -0
  123. package/harness/bundles/general/pi/harness-test/pitfalls-java.md +14 -0
  124. package/harness/bundles/general/pi/harness-test/pitfalls.md +307 -0
  125. package/harness/bundles/general/pi/harness-test/reference.md +880 -0
  126. package/harness/bundles/general/pi/harness-test/scripts/runtime-helpers.mjs +216 -0
  127. package/harness/bundles/general/pi/protocols/archive-report-protocol.md +196 -0
  128. package/harness/bundles/general/pi/protocols/ci-layering-protocol.md +22 -0
  129. package/harness/bundles/general/pi/protocols/evidence-based-reporting-protocol.md +134 -0
  130. package/harness/bundles/general/pi/protocols/execution-session-protocol.md +52 -0
  131. package/harness/bundles/general/pi/protocols/external-platform-protocol.md +27 -0
  132. package/harness/bundles/general/pi/protocols/ledger-protocol.md +365 -0
  133. package/harness/bundles/general/pi/protocols/memory-closeout-protocol.md +21 -0
  134. package/harness/bundles/general/pi/protocols/model-routing-protocol.md +22 -0
  135. package/harness/bundles/general/pi/protocols/powershell-protocol.md +238 -0
  136. package/harness/bundles/general/pi/protocols/registry-governance-protocol.md +31 -0
  137. package/harness/bundles/general/pi/protocols/report-pipeline-protocol.md +172 -0
  138. package/harness/bundles/general/pi/protocols/sensitive-info-protocol.md +110 -0
  139. package/harness/bundles/general/pi/protocols/state-layout-protocol.md +209 -0
  140. package/harness/bundles/general/pi/protocols/submit-protocol.md +78 -0
  141. package/harness/bundles/general/pi/protocols/verification-graph-protocol.md +32 -0
  142. package/harness/bundles/general/pi/scripts/harness_adoption_metrics.py +391 -0
  143. package/harness/bundles/general/pi/scripts/harness_apidoc.py +53 -0
  144. package/harness/bundles/general/pi/scripts/harness_archive.py +11345 -0
  145. package/harness/bundles/general/pi/scripts/harness_change.py +1626 -0
  146. package/harness/bundles/general/pi/scripts/harness_check_gate.py +113 -0
  147. package/harness/bundles/general/pi/scripts/harness_context.py +1774 -0
  148. package/harness/bundles/general/pi/scripts/harness_deploy.py +968 -0
  149. package/harness/bundles/general/pi/scripts/harness_efficiency.py +443 -0
  150. package/harness/bundles/general/pi/scripts/harness_environment.py +1690 -0
  151. package/harness/bundles/general/pi/scripts/harness_events.py +2234 -0
  152. package/harness/bundles/general/pi/scripts/harness_events_sync.py +1425 -0
  153. package/harness/bundles/general/pi/scripts/harness_execution_contracts.py +596 -0
  154. package/harness/bundles/general/pi/scripts/harness_fixback.py +1975 -0
  155. package/harness/bundles/general/pi/scripts/harness_gate.py +3816 -0
  156. package/harness/bundles/general/pi/scripts/harness_headless.py +37 -0
  157. package/harness/bundles/general/pi/scripts/harness_integration.py +2564 -0
  158. package/harness/bundles/general/pi/scripts/harness_knowledge_candidates.py +796 -0
  159. package/harness/bundles/general/pi/scripts/harness_ledger.py +3556 -0
  160. package/harness/bundles/general/pi/scripts/harness_migration_head.py +220 -0
  161. package/harness/bundles/general/pi/scripts/harness_orchestration.py +344 -0
  162. package/harness/bundles/general/pi/scripts/harness_paths.py +676 -0
  163. package/harness/bundles/general/pi/scripts/harness_phase.py +1726 -0
  164. package/harness/bundles/general/pi/scripts/harness_plan_aggregate.py +249 -0
  165. package/harness/bundles/general/pi/scripts/harness_plan_finalize.py +1016 -0
  166. package/harness/bundles/general/pi/scripts/harness_preflight.py +650 -0
  167. package/harness/bundles/general/pi/scripts/harness_process.py +1065 -0
  168. package/harness/bundles/general/pi/scripts/harness_profile.py +1817 -0
  169. package/harness/bundles/general/pi/scripts/harness_report_model.py +442 -0
  170. package/harness/bundles/general/pi/scripts/harness_retry.py +175 -0
  171. package/harness/bundles/general/pi/scripts/harness_review.py +631 -0
  172. package/harness/bundles/general/pi/scripts/harness_runtime.py +2243 -0
  173. package/harness/bundles/general/pi/scripts/harness_service.py +3355 -0
  174. package/harness/bundles/general/pi/scripts/harness_state.py +365 -0
  175. package/harness/bundles/general/pi/scripts/harness_sync.py +407 -0
  176. package/harness/bundles/general/pi/scripts/harness_test_cleanup.py +175 -0
  177. package/harness/bundles/general/pi/scripts/harness_test_guard.py +1899 -0
  178. package/harness/bundles/general/pi/scripts/harness_test_runner.py +1586 -0
  179. package/harness/bundles/general/pi/scripts/harness_verification.py +593 -0
  180. package/harness/bundles/general/pi/scripts/harness_workflow_policy.py +266 -0
  181. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  182. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  183. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  184. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  185. package/harness/bundles/java/claude-code/harness-execute/SKILL.md +1 -1
  186. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  187. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  188. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  189. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
  190. package/harness/bundles/java/claude-code/harness-pull/SKILL.md +1 -1
  191. package/harness/bundles/java/claude-code/harness-push/SKILL.md +1 -1
  192. package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
  193. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  194. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
  195. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  196. package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
  197. package/harness/bundles/java/claude-code/scripts/harness_archive.py +29 -6
  198. package/harness/bundles/java/claude-code/scripts/harness_deploy.py +1 -1
  199. package/harness/bundles/java/claude-code/scripts/harness_knowledge_candidates.py +398 -0
  200. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  201. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  202. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  203. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  204. package/harness/bundles/java/codebuddy/harness-execute/SKILL.md +1 -1
  205. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  206. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  207. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  208. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
  209. package/harness/bundles/java/codebuddy/harness-pull/SKILL.md +1 -1
  210. package/harness/bundles/java/codebuddy/harness-push/SKILL.md +1 -1
  211. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
  212. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  213. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
  214. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  215. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
  216. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +29 -6
  217. package/harness/bundles/java/codebuddy/scripts/harness_deploy.py +1 -1
  218. package/harness/bundles/java/codebuddy/scripts/harness_knowledge_candidates.py +398 -0
  219. package/harness/bundles/java/codex/.harness-build.json +1 -1
  220. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  221. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  222. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  223. package/harness/bundles/java/codex/harness-execute/SKILL.md +1 -1
  224. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  225. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  226. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  227. package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
  228. package/harness/bundles/java/codex/harness-pull/SKILL.md +1 -1
  229. package/harness/bundles/java/codex/harness-push/SKILL.md +1 -1
  230. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  231. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  232. package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
  233. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  234. package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
  235. package/harness/bundles/java/codex/scripts/harness_archive.py +29 -6
  236. package/harness/bundles/java/codex/scripts/harness_deploy.py +1 -1
  237. package/harness/bundles/java/codex/scripts/harness_knowledge_candidates.py +398 -0
  238. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  239. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  240. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  241. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  242. package/harness/bundles/java/cursor/harness-execute/SKILL.md +1 -1
  243. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  244. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  245. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  246. package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
  247. package/harness/bundles/java/cursor/harness-pull/SKILL.md +1 -1
  248. package/harness/bundles/java/cursor/harness-push/SKILL.md +1 -1
  249. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  250. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  251. package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
  252. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  253. package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
  254. package/harness/bundles/java/cursor/scripts/harness_archive.py +29 -6
  255. package/harness/bundles/java/cursor/scripts/harness_deploy.py +1 -1
  256. package/harness/bundles/java/cursor/scripts/harness_knowledge_candidates.py +398 -0
  257. package/harness/bundles/java/pi/.harness-build.json +6 -0
  258. package/harness/bundles/java/pi/CONTEXT.md +98 -0
  259. package/harness/bundles/java/pi/README.md +478 -0
  260. package/harness/bundles/java/pi/contracts/build-profile-v3.schema.json +302 -0
  261. package/harness/bundles/java/pi/contracts/ci-metrics.schema.json +36 -0
  262. package/harness/bundles/java/pi/contracts/doctor-capability.schema.json +43 -0
  263. package/harness/bundles/java/pi/contracts/external-platform-observation.schema.json +62 -0
  264. package/harness/bundles/java/pi/contracts/fixtures/managed-execution.json +341 -0
  265. package/harness/bundles/java/pi/contracts/process-identity.schema.json +132 -0
  266. package/harness/bundles/java/pi/contracts/run-session.schema.json +142 -0
  267. package/harness/bundles/java/pi/contracts/service-retirement-receipt.schema.json +85 -0
  268. package/harness/bundles/java/pi/contracts/service-session.schema.json +147 -0
  269. package/harness/bundles/java/pi/contracts/workflow-policy.json +574 -0
  270. package/harness/bundles/java/pi/harness-apidoc/SKILL.md +97 -0
  271. package/harness/bundles/java/pi/harness-apidoc/checklist.md +142 -0
  272. package/harness/bundles/java/pi/harness-apidoc/reference.md +233 -0
  273. package/harness/bundles/java/pi/harness-archive/SKILL.md +322 -0
  274. package/harness/bundles/java/pi/harness-archive/checklist.md +71 -0
  275. package/harness/bundles/java/pi/harness-archive/reference.md +150 -0
  276. package/harness/bundles/java/pi/harness-archive/scripts/gen-manifest.ps1 +31 -0
  277. package/harness/bundles/java/pi/harness-archive/templates/summary-data-template.json +218 -0
  278. package/harness/bundles/java/pi/harness-codebase-map/SKILL.md +116 -0
  279. package/harness/bundles/java/pi/harness-codebase-map/checklist.md +126 -0
  280. package/harness/bundles/java/pi/harness-codebase-map/reference.md +364 -0
  281. package/harness/bundles/java/pi/harness-codebase-map/templates/ARCHITECTURE.md +57 -0
  282. package/harness/bundles/java/pi/harness-codebase-map/templates/CONCERNS.md +49 -0
  283. package/harness/bundles/java/pi/harness-codebase-map/templates/CONVENTIONS.md +57 -0
  284. package/harness/bundles/java/pi/harness-codebase-map/templates/INTEGRATIONS.md +52 -0
  285. package/harness/bundles/java/pi/harness-codebase-map/templates/STACK.md +55 -0
  286. package/harness/bundles/java/pi/harness-codebase-map/templates/STRUCTURE.md +69 -0
  287. package/harness/bundles/java/pi/harness-codebase-map/templates/TESTING.md +64 -0
  288. package/harness/bundles/java/pi/harness-codebase-map/templates/map-manifest.schema.json +73 -0
  289. package/harness/bundles/java/pi/harness-codebase-map/templates/map-summary.md +64 -0
  290. package/harness/bundles/java/pi/harness-execute/SKILL.md +170 -0
  291. package/harness/bundles/java/pi/harness-knowledge-ingest/SKILL.md +103 -0
  292. package/harness/bundles/java/pi/harness-knowledge-query/SKILL.md +97 -0
  293. package/harness/bundles/java/pi/harness-package/SKILL.md +94 -0
  294. package/harness/bundles/java/pi/harness-package/checklist.md +322 -0
  295. package/harness/bundles/java/pi/harness-package/reference.md +210 -0
  296. package/harness/bundles/java/pi/harness-plan/SKILL.md +158 -0
  297. package/harness/bundles/java/pi/harness-plan/checklist.md +243 -0
  298. package/harness/bundles/java/pi/harness-plan/protocols.md +133 -0
  299. package/harness/bundles/java/pi/harness-plan/reference.md +468 -0
  300. package/harness/bundles/java/pi/harness-pull/SKILL.md +55 -0
  301. package/harness/bundles/java/pi/harness-push/SKILL.md +83 -0
  302. package/harness/bundles/java/pi/harness-review/SKILL.md +175 -0
  303. package/harness/bundles/java/pi/harness-review/checklist.md +124 -0
  304. package/harness/bundles/java/pi/harness-review/protocols.md +69 -0
  305. package/harness/bundles/java/pi/harness-review/reference.md +114 -0
  306. package/harness/bundles/java/pi/harness-run/SKILL.md +206 -0
  307. package/harness/bundles/java/pi/harness-run/checklist.md +252 -0
  308. package/harness/bundles/java/pi/harness-run/protocols.md +141 -0
  309. package/harness/bundles/java/pi/harness-run/reference.md +820 -0
  310. package/harness/bundles/java/pi/harness-submit/SKILL.md +189 -0
  311. package/harness/bundles/java/pi/harness-submit/checklist.md +452 -0
  312. package/harness/bundles/java/pi/harness-submit/reference.md +152 -0
  313. package/harness/bundles/java/pi/harness-sync/SKILL.md +72 -0
  314. package/harness/bundles/java/pi/harness-sync/reference.md +176 -0
  315. package/harness/bundles/java/pi/harness-test/SKILL.md +264 -0
  316. package/harness/bundles/java/pi/harness-test/checklist.md +320 -0
  317. package/harness/bundles/java/pi/harness-test/pitfalls-java.md +16 -0
  318. package/harness/bundles/java/pi/harness-test/pitfalls.md +307 -0
  319. package/harness/bundles/java/pi/harness-test/reference.md +792 -0
  320. package/harness/bundles/java/pi/harness-test/scripts/runtime-helpers.mjs +216 -0
  321. package/harness/bundles/java/pi/protocols/archive-report-protocol.md +196 -0
  322. package/harness/bundles/java/pi/protocols/ci-layering-protocol.md +22 -0
  323. package/harness/bundles/java/pi/protocols/evidence-based-reporting-protocol.md +134 -0
  324. package/harness/bundles/java/pi/protocols/execution-session-protocol.md +52 -0
  325. package/harness/bundles/java/pi/protocols/external-platform-protocol.md +27 -0
  326. package/harness/bundles/java/pi/protocols/ledger-protocol.md +365 -0
  327. package/harness/bundles/java/pi/protocols/memory-closeout-protocol.md +21 -0
  328. package/harness/bundles/java/pi/protocols/model-routing-protocol.md +22 -0
  329. package/harness/bundles/java/pi/protocols/powershell-protocol.md +238 -0
  330. package/harness/bundles/java/pi/protocols/registry-governance-protocol.md +31 -0
  331. package/harness/bundles/java/pi/protocols/report-pipeline-protocol.md +172 -0
  332. package/harness/bundles/java/pi/protocols/sensitive-info-protocol.md +110 -0
  333. package/harness/bundles/java/pi/protocols/state-layout-protocol.md +209 -0
  334. package/harness/bundles/java/pi/protocols/submit-protocol.md +78 -0
  335. package/harness/bundles/java/pi/protocols/verification-graph-protocol.md +32 -0
  336. package/harness/bundles/java/pi/scripts/harness_adoption_metrics.py +391 -0
  337. package/harness/bundles/java/pi/scripts/harness_apidoc.py +53 -0
  338. package/harness/bundles/java/pi/scripts/harness_archive.py +11345 -0
  339. package/harness/bundles/java/pi/scripts/harness_change.py +1626 -0
  340. package/harness/bundles/java/pi/scripts/harness_check_gate.py +113 -0
  341. package/harness/bundles/java/pi/scripts/harness_context.py +1774 -0
  342. package/harness/bundles/java/pi/scripts/harness_deploy.py +968 -0
  343. package/harness/bundles/java/pi/scripts/harness_efficiency.py +443 -0
  344. package/harness/bundles/java/pi/scripts/harness_environment.py +1690 -0
  345. package/harness/bundles/java/pi/scripts/harness_events.py +2234 -0
  346. package/harness/bundles/java/pi/scripts/harness_events_sync.py +1425 -0
  347. package/harness/bundles/java/pi/scripts/harness_execution_contracts.py +596 -0
  348. package/harness/bundles/java/pi/scripts/harness_fixback.py +1975 -0
  349. package/harness/bundles/java/pi/scripts/harness_gate.py +3816 -0
  350. package/harness/bundles/java/pi/scripts/harness_headless.py +37 -0
  351. package/harness/bundles/java/pi/scripts/harness_integration.py +2564 -0
  352. package/harness/bundles/java/pi/scripts/harness_knowledge_candidates.py +796 -0
  353. package/harness/bundles/java/pi/scripts/harness_ledger.py +3556 -0
  354. package/harness/bundles/java/pi/scripts/harness_migration_head.py +220 -0
  355. package/harness/bundles/java/pi/scripts/harness_orchestration.py +344 -0
  356. package/harness/bundles/java/pi/scripts/harness_paths.py +676 -0
  357. package/harness/bundles/java/pi/scripts/harness_phase.py +1726 -0
  358. package/harness/bundles/java/pi/scripts/harness_plan_aggregate.py +249 -0
  359. package/harness/bundles/java/pi/scripts/harness_plan_finalize.py +1016 -0
  360. package/harness/bundles/java/pi/scripts/harness_preflight.py +650 -0
  361. package/harness/bundles/java/pi/scripts/harness_process.py +1065 -0
  362. package/harness/bundles/java/pi/scripts/harness_profile.py +1817 -0
  363. package/harness/bundles/java/pi/scripts/harness_report_model.py +442 -0
  364. package/harness/bundles/java/pi/scripts/harness_retry.py +175 -0
  365. package/harness/bundles/java/pi/scripts/harness_review.py +631 -0
  366. package/harness/bundles/java/pi/scripts/harness_runtime.py +2243 -0
  367. package/harness/bundles/java/pi/scripts/harness_service.py +3355 -0
  368. package/harness/bundles/java/pi/scripts/harness_state.py +365 -0
  369. package/harness/bundles/java/pi/scripts/harness_sync.py +407 -0
  370. package/harness/bundles/java/pi/scripts/harness_test_cleanup.py +175 -0
  371. package/harness/bundles/java/pi/scripts/harness_test_guard.py +1899 -0
  372. package/harness/bundles/java/pi/scripts/harness_test_runner.py +1586 -0
  373. package/harness/bundles/java/pi/scripts/harness_verification.py +593 -0
  374. package/harness/bundles/java/pi/scripts/harness_workflow_policy.py +266 -0
  375. package/harness/manifests/general/claude-code.json +17 -17
  376. package/harness/manifests/general/codebuddy.json +17 -17
  377. package/harness/manifests/general/codex.json +17 -17
  378. package/harness/manifests/general/cursor.json +17 -17
  379. package/harness/manifests/general/pi.json +475 -0
  380. package/harness/manifests/java/claude-code.json +19 -19
  381. package/harness/manifests/java/codebuddy.json +19 -19
  382. package/harness/manifests/java/codex.json +19 -19
  383. package/harness/manifests/java/cursor.json +19 -19
  384. package/harness/manifests/java/pi.json +499 -0
  385. package/hunter-workflow-family.json +2 -2
  386. package/package.json +1 -1
@@ -0,0 +1,593 @@
1
+ #!/usr/bin/env python3
2
+ """Select verification targets from a diff and dependency graph."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import fnmatch
8
+ import json
9
+ import time
10
+ from collections import Counter
11
+ from pathlib import Path
12
+ from typing import Any
13
+
14
+
15
+ _COVERAGE_RANK = {"incremental": 0, "module": 1, "module-am": 2, "full": 3}
16
+
17
+ _REASON_EXPLANATIONS = {
18
+ "PRODUCT_IDENTITY_REQUIRED": "A product identity is required before a verification can run.",
19
+ "CAPABILITY_MISSING": "A required execution capability is not available.",
20
+ "REQUIRED_COVERAGE_INVALID": "The required coverage declaration is invalid.",
21
+ "COVERAGE_DECLARATION_REQUIRED": "The target does not declare the coverage level needed for this gate.",
22
+ "COVERAGE_INSUFFICIENT": "The target coverage is below the required gate level.",
23
+ "NOT_APPLICABLE": "The target is explicitly not applicable to this change.",
24
+ "FROZEN_IDENTITY_REQUIRED": "The target requires a frozen product identity.",
25
+ "FROZEN_IDENTITY_DRIFT": "The current product identity differs from the frozen identity.",
26
+ "REUSE_POLICY_NEVER": "The target policy explicitly requires a fresh execution.",
27
+ "REUSE_EVIDENCE_INVALID": "Ledger evidence does not match the target and product identity exactly.",
28
+ "REUSE_ELIGIBLE": "Identity-matched ledger evidence permits reuse.",
29
+ "SELECTED_FOR_EXECUTION": "The target was selected for execution and passed its gate checks.",
30
+ "COMMAND_NOT_DECLARED": "The target command key is absent from the authoritative command declaration map.",
31
+ "COMMAND_DECLARATION_INVALID": "The authoritative command declaration is empty or malformed.",
32
+ "DEPENDENCY_UNKNOWN": "The target depends on a node that is not in the verification graph.",
33
+ "DEPENDENCY_BLOCKED": "A dependency was skipped or blocked, so this target cannot run.",
34
+ "DEPENDENCY_CYCLE": "The verification graph contains a dependency cycle.",
35
+ "VERIFICATION_REUSED": "The target reused an identity-matched verification receipt.",
36
+ "VERIFICATION_ARGV_NOT_CONCRETE": "The target command arguments are not concrete and executable.",
37
+ }
38
+
39
+
40
+ def _reason_explanation(reason_codes: list[str], decision: str) -> str:
41
+ explanations: list[str] = []
42
+ for raw in reason_codes:
43
+ code = str(raw).split(":", 1)[0]
44
+ explanation = _REASON_EXPLANATIONS.get(code)
45
+ if explanation is None:
46
+ if raw.startswith("depends-on:"):
47
+ explanation = f"The target waits for dependency {raw.split(':', 1)[1]} to complete."
48
+ elif raw.startswith("consumer-of:"):
49
+ explanation = f"The target is included because it consumes {raw.split(':', 1)[1]}."
50
+ elif raw.startswith("input-match:"):
51
+ explanation = f"A changed input matched {raw.split(':', 1)[1]}."
52
+ elif raw.startswith("CAPABILITY_MISSING:"):
53
+ explanation = f"Capability {raw.split(':', 1)[1]} is unavailable."
54
+ else:
55
+ explanation = f"Verification decision reason: {raw}."
56
+ if explanation not in explanations:
57
+ explanations.append(explanation)
58
+ if explanations:
59
+ return " ".join(explanations)
60
+ return {
61
+ "EXECUTE": "The target passed all declared gate checks and is ready to execute.",
62
+ "REUSE": "The target has valid identity-matched reusable evidence.",
63
+ "SKIP": "The target is not applicable to this change.",
64
+ "BLOCKED": "The target cannot execute until its blocking conditions are resolved.",
65
+ }.get(decision, "The target has no executable decision.")
66
+
67
+
68
+ def _normalize_targets(raw_targets: Any) -> list[dict[str, Any]]:
69
+ if isinstance(raw_targets, dict):
70
+ return [
71
+ {**dict(target), "id": str(target.get("id") or target_id)}
72
+ for target_id, target in raw_targets.items()
73
+ if isinstance(target_id, str) and isinstance(target, dict)
74
+ ]
75
+ if isinstance(raw_targets, list):
76
+ return [
77
+ dict(target)
78
+ for target in raw_targets
79
+ if isinstance(target, dict) and str(target.get("id") or "").strip()
80
+ ]
81
+ return []
82
+
83
+
84
+ def select_verifications(payload: dict[str, Any]) -> dict[str, Any]:
85
+ changed = sorted(
86
+ {
87
+ str(path).replace("\\", "/")
88
+ for path in payload.get("changedFiles", [])
89
+ if str(path).strip()
90
+ }
91
+ )
92
+ targets = _normalize_targets(payload.get("targets", []))
93
+ selected_ids: set[str] = set()
94
+ reasons: dict[str, list[str]] = {}
95
+ for target in targets:
96
+ target_id = str(target.get("id") or "")
97
+ patterns = [str(pattern) for pattern in target.get("inputs", [])]
98
+ matched = sorted(
99
+ path
100
+ for path in changed
101
+ if any(fnmatch.fnmatch(path, pattern) for pattern in patterns)
102
+ )
103
+ if matched:
104
+ selected_ids.add(target_id)
105
+ reasons[target_id] = ["input-match:" + path for path in matched]
106
+
107
+ changed_closure = True
108
+ while changed_closure:
109
+ changed_closure = False
110
+ for target in targets:
111
+ target_id = str(target.get("id") or "")
112
+ dependencies = {str(item) for item in target.get("dependsOn", [])}
113
+ if target_id not in selected_ids and dependencies & selected_ids:
114
+ selected_ids.add(target_id)
115
+ reasons[target_id] = [
116
+ "consumer-of:" + dependency
117
+ for dependency in sorted(dependencies & selected_ids)
118
+ ]
119
+ changed_closure = True
120
+
121
+ escalation_reasons: list[str] = []
122
+ lockfiles = {
123
+ "package-lock.json",
124
+ "npm-shrinkwrap.json",
125
+ "pnpm-lock.yaml",
126
+ "yarn.lock",
127
+ "pom.xml",
128
+ "Cargo.lock",
129
+ "go.sum",
130
+ }
131
+ if any(path in lockfiles or Path(path).name in lockfiles for path in changed):
132
+ escalation_reasons.append("lockfile-changed")
133
+ if any(
134
+ path.startswith(("packages/contracts/", "contracts/"))
135
+ or "/schema/" in path
136
+ or path.endswith((".schema.json", ".proto"))
137
+ for path in changed
138
+ ):
139
+ escalation_reasons.append("public-contract-changed")
140
+ selected = [
141
+ {**target, "selectionReasons": reasons[str(target.get("id") or "")]}
142
+ for target in targets
143
+ if str(target.get("id") or "") in selected_ids
144
+ ]
145
+ omitted = [
146
+ {**target, "omissionReason": "no impacted input or dependency"}
147
+ for target in targets
148
+ if str(target.get("id") or "") not in selected_ids
149
+ ]
150
+ return {
151
+ "ok": True,
152
+ "code": "VERIFICATION_TARGETS_SELECTED",
153
+ "changedFiles": changed,
154
+ "selected": selected,
155
+ "omitted": omitted,
156
+ "dependencyClosure": [str(item.get("id")) for item in selected],
157
+ "candidateRequired": bool(escalation_reasons),
158
+ "escalationReasons": escalation_reasons,
159
+ }
160
+
161
+
162
+ def _resource_locks(target: dict[str, Any]) -> list[str]:
163
+ locks = sorted(
164
+ {
165
+ str(item).strip()
166
+ for item in target.get("resourceLocks", [])
167
+ if str(item).strip()
168
+ }
169
+ )
170
+ estimated = float(
171
+ target.get("estimatedDurationSeconds")
172
+ or target.get("expectedDurationSeconds")
173
+ or 0
174
+ )
175
+ if estimated >= 60 and not locks:
176
+ locks.append("harness:unclassified-heavy")
177
+ return locks
178
+
179
+
180
+ def _target_decision(
181
+ target: dict[str, Any],
182
+ *,
183
+ product_identity: str,
184
+ frozen_identity: str,
185
+ available_capabilities: set[str],
186
+ verification_ledger: list[dict[str, Any]],
187
+ command_declarations: dict[str, Any] | None = None,
188
+ ) -> tuple[str, list[str]]:
189
+ blockers: list[str] = []
190
+ if not product_identity:
191
+ return "BLOCKED", ["PRODUCT_IDENTITY_REQUIRED"]
192
+ if command_declarations is not None:
193
+ command_key = str(target.get("commandKey") or "").strip()
194
+ declaration = command_declarations.get(command_key) if command_key else None
195
+ if declaration is None:
196
+ blockers.append("COMMAND_NOT_DECLARED")
197
+ elif isinstance(declaration, dict):
198
+ argv = declaration.get("argv") or declaration.get("argvTemplate")
199
+ if not isinstance(argv, list) or not argv or not all(
200
+ isinstance(item, str) and item for item in argv
201
+ ):
202
+ blockers.append("COMMAND_DECLARATION_INVALID")
203
+ elif not isinstance(declaration, list) or not declaration or not all(
204
+ isinstance(item, str) and item for item in declaration
205
+ ):
206
+ blockers.append("COMMAND_DECLARATION_INVALID")
207
+ required_capabilities = {
208
+ str(item).strip()
209
+ for item in target.get("requiredCapabilities", [])
210
+ if str(item).strip()
211
+ }
212
+ blockers.extend(
213
+ "CAPABILITY_MISSING:" + item
214
+ for item in sorted(required_capabilities - available_capabilities)
215
+ )
216
+ required_coverage = str(target.get("requiredCoverage") or "").strip()
217
+ coverage_level = str(
218
+ target.get("coverageLevel") or target.get("scope") or ""
219
+ ).strip()
220
+ if required_coverage:
221
+ if required_coverage not in _COVERAGE_RANK:
222
+ blockers.append("REQUIRED_COVERAGE_INVALID")
223
+ elif coverage_level not in _COVERAGE_RANK:
224
+ blockers.append("COVERAGE_DECLARATION_REQUIRED")
225
+ elif _COVERAGE_RANK[coverage_level] < _COVERAGE_RANK[required_coverage]:
226
+ blockers.append(
227
+ f"COVERAGE_INSUFFICIENT:{coverage_level}<{required_coverage}"
228
+ )
229
+ applicability = target.get("applicability")
230
+ if isinstance(applicability, dict) and applicability.get("applicable") is False:
231
+ return "SKIP", [
232
+ str(applicability.get("reasonCode") or "NOT_APPLICABLE")
233
+ ]
234
+ if (
235
+ target.get("requiresFrozenIdentity") is True
236
+ and not frozen_identity
237
+ ):
238
+ blockers.append("FROZEN_IDENTITY_REQUIRED")
239
+ if (
240
+ target.get("requiresFrozenIdentity") is True
241
+ and frozen_identity
242
+ and product_identity != frozen_identity
243
+ ):
244
+ blockers.append("FROZEN_IDENTITY_DRIFT")
245
+ if blockers:
246
+ return "BLOCKED", blockers
247
+ reuse = target.get("reuse")
248
+ if isinstance(reuse, dict) and reuse.get("eligible") is True:
249
+ if target.get("reusePolicy") == "never":
250
+ return "EXECUTE", ["REUSE_POLICY_NEVER"]
251
+ evidence_id = str(reuse.get("evidenceId") or "").strip()
252
+ evidence_product = str(reuse.get("productIdentity") or "").strip()
253
+ target_id = str(target.get("id") or "")
254
+ ledger_match = next(
255
+ (
256
+ item
257
+ for item in verification_ledger
258
+ if str(item.get("evidenceId") or "") == evidence_id
259
+ and str(item.get("targetId") or item.get("verification") or "")
260
+ == target_id
261
+ and str(item.get("productIdentity") or "") == product_identity
262
+ and item.get("status") == "OK"
263
+ ),
264
+ None,
265
+ )
266
+ if (
267
+ str(target.get("reusePolicy") or "") != "ledger-exact"
268
+ or not evidence_id
269
+ or evidence_product != product_identity
270
+ or ledger_match is None
271
+ ):
272
+ return "BLOCKED", ["REUSE_EVIDENCE_INVALID"]
273
+ return "REUSE", [str(reuse.get("reasonCode") or "REUSE_ELIGIBLE")]
274
+ return "EXECUTE", ["SELECTED_FOR_EXECUTION"]
275
+
276
+
277
+ def schedule_verifications(payload: dict[str, Any]) -> dict[str, Any]:
278
+ """Build an explainable, lock-aware verification execution plan.
279
+
280
+ Dependencies define the earliest wave. Nodes in the same wave may run in
281
+ parallel only when their declared resource locks are disjoint. Long tasks
282
+ without a lock declaration receive one shared conservative lock.
283
+ """
284
+ targets = _normalize_targets(payload.get("targets", []))
285
+ if not targets:
286
+ return {
287
+ "ok": False,
288
+ "code": "VERIFICATION_TARGETS_REQUIRED",
289
+ "productIdentity": str(payload.get("productIdentity") or ""),
290
+ "frozenIdentity": str(payload.get("frozenIdentity") or ""),
291
+ "plan": [],
292
+ "waves": [],
293
+ }
294
+ targets.sort(key=lambda item: str(item["id"]))
295
+ by_id = {str(item["id"]): item for item in targets}
296
+ product_identity = str(payload.get("productIdentity") or "")
297
+ frozen_identity = str(payload.get("frozenIdentity") or "")
298
+ available_capabilities = {
299
+ str(item).strip()
300
+ for item in payload.get("availableCapabilities", [])
301
+ if str(item).strip()
302
+ }
303
+ verification_ledger = [
304
+ dict(item)
305
+ for item in payload.get("verificationLedger", [])
306
+ if isinstance(item, dict)
307
+ ]
308
+ raw_commands = payload.get("commands")
309
+ command_declarations = (
310
+ {str(key): value for key, value in raw_commands.items()}
311
+ if isinstance(raw_commands, dict)
312
+ else None
313
+ )
314
+ decisions: dict[str, tuple[str, list[str]]] = {
315
+ target_id: _target_decision(
316
+ target,
317
+ product_identity=product_identity,
318
+ frozen_identity=frozen_identity,
319
+ available_capabilities=available_capabilities,
320
+ verification_ledger=verification_ledger,
321
+ command_declarations=command_declarations,
322
+ )
323
+ for target_id, target in by_id.items()
324
+ }
325
+ waves: list[list[str]] = []
326
+ placed: dict[str, int | None] = {}
327
+ pending = set(by_id)
328
+
329
+ while pending:
330
+ progressed = False
331
+ for target_id in sorted(pending):
332
+ target = by_id[target_id]
333
+ dependencies = [str(item) for item in target.get("dependsOn", [])]
334
+ unknown = sorted(set(dependencies) - set(by_id))
335
+ if unknown:
336
+ decisions[target_id] = (
337
+ "BLOCKED",
338
+ ["DEPENDENCY_UNKNOWN:" + item for item in unknown],
339
+ )
340
+ placed[target_id] = None
341
+ pending.remove(target_id)
342
+ progressed = True
343
+ break
344
+ if any(item not in placed for item in dependencies):
345
+ continue
346
+ failed_dependencies = [
347
+ item
348
+ for item in dependencies
349
+ if decisions[item][0] in {"SKIP", "BLOCKED"}
350
+ ]
351
+ if failed_dependencies:
352
+ decisions[target_id] = (
353
+ "BLOCKED",
354
+ [
355
+ "DEPENDENCY_BLOCKED:" + item
356
+ for item in sorted(failed_dependencies)
357
+ ],
358
+ )
359
+ placed[target_id] = None
360
+ pending.remove(target_id)
361
+ progressed = True
362
+ break
363
+ decision, _ = decisions[target_id]
364
+ if decision in {"SKIP", "BLOCKED"}:
365
+ placed[target_id] = None
366
+ pending.remove(target_id)
367
+ progressed = True
368
+ break
369
+ dependency_waves = [
370
+ placed[item]
371
+ for item in dependencies
372
+ if placed.get(item) is not None
373
+ ]
374
+ earliest = (
375
+ max(int(item) for item in dependency_waves) + 1
376
+ if dependency_waves
377
+ else 0
378
+ )
379
+ if decision == "REUSE":
380
+ placed[target_id] = max(0, earliest - 1)
381
+ pending.remove(target_id)
382
+ progressed = True
383
+ break
384
+ locks = set(_resource_locks(target))
385
+ wave = earliest
386
+ while True:
387
+ while wave >= len(waves):
388
+ waves.append([])
389
+ occupied = {
390
+ lock
391
+ for item_id in waves[wave]
392
+ for lock in _resource_locks(by_id[item_id])
393
+ }
394
+ if not locks & occupied:
395
+ waves[wave].append(target_id)
396
+ placed[target_id] = wave
397
+ break
398
+ wave += 1
399
+ pending.remove(target_id)
400
+ progressed = True
401
+ break
402
+ if not progressed:
403
+ for target_id in sorted(pending):
404
+ decisions[target_id] = ("BLOCKED", ["DEPENDENCY_CYCLE"])
405
+ placed[target_id] = None
406
+ pending.clear()
407
+
408
+ plan: list[dict[str, Any]] = []
409
+ for target_id, target in by_id.items():
410
+ decision, reasons = decisions[target_id]
411
+ dependencies = [str(item) for item in target.get("dependsOn", [])]
412
+ reason_codes = [
413
+ *reasons,
414
+ *["depends-on:" + item for item in dependencies],
415
+ ]
416
+ plan.append(
417
+ {
418
+ **target,
419
+ "id": target_id,
420
+ "decision": decision,
421
+ "reasonCodes": reason_codes,
422
+ "explanation": _reason_explanation(reason_codes, decision),
423
+ "resourceLocks": _resource_locks(target),
424
+ "wave": placed[target_id],
425
+ }
426
+ )
427
+ decision_counts = dict(
428
+ sorted(Counter(item["decision"] for item in plan).items())
429
+ )
430
+ return {
431
+ "ok": all(item["decision"] != "BLOCKED" for item in plan),
432
+ "code": (
433
+ "VERIFICATION_PLAN_READY"
434
+ if all(item["decision"] != "BLOCKED" for item in plan)
435
+ else "VERIFICATION_PLAN_BLOCKED"
436
+ ),
437
+ "productIdentity": product_identity,
438
+ "frozenIdentity": frozen_identity,
439
+ "plan": plan,
440
+ "decisionCounts": decision_counts,
441
+ "waves": [
442
+ {"wave": index, "targets": target_ids}
443
+ for index, target_ids in enumerate(waves)
444
+ if target_ids
445
+ ],
446
+ }
447
+
448
+
449
+ def execute_verifications(payload: dict[str, Any]) -> dict[str, Any]:
450
+ """Execute a scheduled graph wave-by-wave through managed run sessions."""
451
+ import harness_runtime
452
+
453
+ scheduled = schedule_verifications(payload)
454
+ if not scheduled["ok"]:
455
+ return {**scheduled, "execution": []}
456
+ state_root = Path(str(payload.get("stateRoot") or "")).expanduser().resolve()
457
+ working_directory = Path(
458
+ str(payload.get("workingDirectory") or "")
459
+ ).expanduser().resolve()
460
+ if not str(payload.get("stateRoot") or "").strip():
461
+ return {
462
+ **scheduled,
463
+ "ok": False,
464
+ "code": "VERIFICATION_STATE_ROOT_REQUIRED",
465
+ "execution": [],
466
+ }
467
+ if not working_directory.is_dir():
468
+ return {
469
+ **scheduled,
470
+ "ok": False,
471
+ "code": "VERIFICATION_WORKDIR_INVALID",
472
+ "execution": [],
473
+ }
474
+ by_id = {str(item["id"]): item for item in scheduled["plan"]}
475
+ outcomes: dict[str, dict[str, Any]] = {
476
+ target_id: {
477
+ "targetId": target_id,
478
+ "status": "OK",
479
+ "reasonCode": "VERIFICATION_REUSED",
480
+ }
481
+ for target_id, target in by_id.items()
482
+ if target.get("decision") == "REUSE"
483
+ }
484
+ execution: list[dict[str, Any]] = list(outcomes.values())
485
+ for wave in scheduled["waves"]:
486
+ running: list[tuple[str, str]] = []
487
+ for target_id in wave["targets"]:
488
+ target = by_id[target_id]
489
+ failed_dependencies = [
490
+ dependency
491
+ for dependency in target.get("dependsOn", [])
492
+ if outcomes.get(str(dependency), {}).get("status") != "OK"
493
+ ]
494
+ if failed_dependencies:
495
+ outcome = {
496
+ "targetId": target_id,
497
+ "status": "BLOCKED",
498
+ "reasonCode": "DEPENDENCY_EXECUTION_FAILED",
499
+ "blockedBy": failed_dependencies,
500
+ }
501
+ outcomes[target_id] = outcome
502
+ execution.append(outcome)
503
+ continue
504
+ argv = target.get("argvTemplate")
505
+ if (
506
+ not isinstance(argv, list)
507
+ or not argv
508
+ or not all(isinstance(item, str) and item for item in argv)
509
+ or any("{" in item or "}" in item for item in argv)
510
+ ):
511
+ outcome = {
512
+ "targetId": target_id,
513
+ "status": "BLOCKED",
514
+ "reasonCode": "VERIFICATION_ARGV_NOT_CONCRETE",
515
+ }
516
+ outcomes[target_id] = outcome
517
+ execution.append(outcome)
518
+ continue
519
+ receipt = harness_runtime.start_run_session(
520
+ state_root=state_root,
521
+ verification=target_id,
522
+ argv=argv,
523
+ working_directory=working_directory,
524
+ timeout_seconds=target.get("timeoutSeconds"),
525
+ expected_duration_seconds=target.get(
526
+ "estimatedDurationSeconds"
527
+ ),
528
+ product_identity=scheduled["productIdentity"],
529
+ resource_locks=list(target["resourceLocks"]),
530
+ )
531
+ if receipt.get("status") in harness_runtime.RUN_TERMINAL_STATUSES:
532
+ outcome = {"targetId": target_id, **receipt}
533
+ outcomes[target_id] = outcome
534
+ execution.append(outcome)
535
+ else:
536
+ running.append((target_id, str(receipt["sessionId"])))
537
+ while running:
538
+ remaining: list[tuple[str, str]] = []
539
+ for target_id, session_id in running:
540
+ receipt = harness_runtime.run_session_status(state_root, session_id)
541
+ if receipt.get("status") in harness_runtime.RUN_TERMINAL_STATUSES:
542
+ outcome = {"targetId": target_id, **receipt}
543
+ outcomes[target_id] = outcome
544
+ execution.append(outcome)
545
+ else:
546
+ remaining.append((target_id, session_id))
547
+ running = remaining
548
+ if running:
549
+ time.sleep(0.05)
550
+ execution_ok = all(item.get("status") == "OK" for item in execution)
551
+ return {
552
+ **scheduled,
553
+ "ok": execution_ok,
554
+ "code": (
555
+ "VERIFICATION_EXECUTION_OK"
556
+ if execution_ok
557
+ else "VERIFICATION_EXECUTION_FAILED"
558
+ ),
559
+ "execution": execution,
560
+ }
561
+
562
+
563
+ def main(argv: list[str] | None = None) -> int:
564
+ parser = argparse.ArgumentParser(prog="harness_verification.py")
565
+ parser.add_argument(
566
+ "command",
567
+ nargs="?",
568
+ choices=("select", "plan", "execute"),
569
+ default="select",
570
+ )
571
+ parser.add_argument("--input", required=True, type=Path)
572
+ parser.add_argument("--out", type=Path)
573
+ parser.add_argument("--json", action="store_true")
574
+ args = parser.parse_args(argv)
575
+ payload = json.loads(args.input.read_text(encoding="utf-8-sig"))
576
+ if args.command == "execute":
577
+ result = execute_verifications(payload)
578
+ elif args.command == "plan":
579
+ result = schedule_verifications(payload)
580
+ else:
581
+ result = select_verifications(payload)
582
+ if args.out:
583
+ args.out.parent.mkdir(parents=True, exist_ok=True)
584
+ args.out.write_text(
585
+ json.dumps(result, ensure_ascii=False, indent=2) + "\n",
586
+ encoding="utf-8",
587
+ )
588
+ print(json.dumps(result, ensure_ascii=False, indent=2))
589
+ return 0 if result.get("ok") else 1
590
+
591
+
592
+ if __name__ == "__main__":
593
+ raise SystemExit(main())