@hunter-harness/workflow-harness 0.2.43 → 0.2.44

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 (274) hide show
  1. package/harness/bundles/general/claude-code/.harness-build.json +1 -1
  2. package/harness/bundles/general/claude-code/contracts/build-profile-v3.schema.json +100 -0
  3. package/harness/bundles/general/claude-code/contracts/fixtures/managed-execution.json +341 -0
  4. package/harness/bundles/general/claude-code/contracts/process-identity.schema.json +132 -0
  5. package/harness/bundles/general/claude-code/contracts/run-session.schema.json +142 -0
  6. package/harness/bundles/general/claude-code/contracts/service-retirement-receipt.schema.json +85 -0
  7. package/harness/bundles/general/claude-code/contracts/service-session.schema.json +147 -0
  8. package/harness/bundles/general/claude-code/harness-archive/SKILL.md +1 -1
  9. package/harness/bundles/general/claude-code/harness-codebase-map/SKILL.md +1 -1
  10. package/harness/bundles/general/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  11. package/harness/bundles/general/claude-code/harness-knowledge-query/SKILL.md +1 -1
  12. package/harness/bundles/general/claude-code/harness-plan/SKILL.md +1 -1
  13. package/harness/bundles/general/claude-code/harness-review/SKILL.md +1 -1
  14. package/harness/bundles/general/claude-code/harness-run/SKILL.md +1 -1
  15. package/harness/bundles/general/claude-code/harness-submit/SKILL.md +1 -1
  16. package/harness/bundles/general/claude-code/harness-submit/checklist.md +12 -0
  17. package/harness/bundles/general/claude-code/harness-sync/SKILL.md +1 -1
  18. package/harness/bundles/general/claude-code/harness-test/SKILL.md +1 -1
  19. package/harness/bundles/general/claude-code/scripts/harness_archive.py +267 -22
  20. package/harness/bundles/general/claude-code/scripts/harness_change.py +137 -2
  21. package/harness/bundles/general/claude-code/scripts/harness_efficiency.py +153 -0
  22. package/harness/bundles/general/claude-code/scripts/harness_environment.py +55 -25
  23. package/harness/bundles/general/claude-code/scripts/harness_execution_contracts.py +596 -0
  24. package/harness/bundles/general/claude-code/scripts/harness_integration.py +289 -52
  25. package/harness/bundles/general/claude-code/scripts/harness_ledger.py +5 -0
  26. package/harness/bundles/general/claude-code/scripts/harness_orchestration.py +344 -0
  27. package/harness/bundles/general/claude-code/scripts/harness_process.py +1065 -0
  28. package/harness/bundles/general/claude-code/scripts/harness_profile.py +244 -4
  29. package/harness/bundles/general/claude-code/scripts/harness_runtime.py +543 -132
  30. package/harness/bundles/general/claude-code/scripts/harness_service.py +1469 -194
  31. package/harness/bundles/general/claude-code/scripts/harness_test_runner.py +107 -117
  32. package/harness/bundles/general/claude-code/scripts/harness_verification.py +79 -0
  33. package/harness/bundles/general/codebuddy/.harness-build.json +1 -1
  34. package/harness/bundles/general/codebuddy/contracts/build-profile-v3.schema.json +100 -0
  35. package/harness/bundles/general/codebuddy/contracts/fixtures/managed-execution.json +341 -0
  36. package/harness/bundles/general/codebuddy/contracts/process-identity.schema.json +132 -0
  37. package/harness/bundles/general/codebuddy/contracts/run-session.schema.json +142 -0
  38. package/harness/bundles/general/codebuddy/contracts/service-retirement-receipt.schema.json +85 -0
  39. package/harness/bundles/general/codebuddy/contracts/service-session.schema.json +147 -0
  40. package/harness/bundles/general/codebuddy/harness-archive/SKILL.md +1 -1
  41. package/harness/bundles/general/codebuddy/harness-codebase-map/SKILL.md +1 -1
  42. package/harness/bundles/general/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  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 +1 -1
  46. package/harness/bundles/general/codebuddy/harness-run/SKILL.md +1 -1
  47. package/harness/bundles/general/codebuddy/harness-submit/SKILL.md +1 -1
  48. package/harness/bundles/general/codebuddy/harness-submit/checklist.md +12 -0
  49. package/harness/bundles/general/codebuddy/harness-sync/SKILL.md +1 -1
  50. package/harness/bundles/general/codebuddy/harness-test/SKILL.md +1 -1
  51. package/harness/bundles/general/codebuddy/scripts/harness_archive.py +267 -22
  52. package/harness/bundles/general/codebuddy/scripts/harness_change.py +137 -2
  53. package/harness/bundles/general/codebuddy/scripts/harness_efficiency.py +153 -0
  54. package/harness/bundles/general/codebuddy/scripts/harness_environment.py +55 -25
  55. package/harness/bundles/general/codebuddy/scripts/harness_execution_contracts.py +596 -0
  56. package/harness/bundles/general/codebuddy/scripts/harness_integration.py +289 -52
  57. package/harness/bundles/general/codebuddy/scripts/harness_ledger.py +5 -0
  58. package/harness/bundles/general/codebuddy/scripts/harness_orchestration.py +344 -0
  59. package/harness/bundles/general/codebuddy/scripts/harness_process.py +1065 -0
  60. package/harness/bundles/general/codebuddy/scripts/harness_profile.py +244 -4
  61. package/harness/bundles/general/codebuddy/scripts/harness_runtime.py +543 -132
  62. package/harness/bundles/general/codebuddy/scripts/harness_service.py +1469 -194
  63. package/harness/bundles/general/codebuddy/scripts/harness_test_runner.py +107 -117
  64. package/harness/bundles/general/codebuddy/scripts/harness_verification.py +79 -0
  65. package/harness/bundles/general/codex/.harness-build.json +1 -1
  66. package/harness/bundles/general/codex/contracts/build-profile-v3.schema.json +100 -0
  67. package/harness/bundles/general/codex/contracts/fixtures/managed-execution.json +341 -0
  68. package/harness/bundles/general/codex/contracts/process-identity.schema.json +132 -0
  69. package/harness/bundles/general/codex/contracts/run-session.schema.json +142 -0
  70. package/harness/bundles/general/codex/contracts/service-retirement-receipt.schema.json +85 -0
  71. package/harness/bundles/general/codex/contracts/service-session.schema.json +147 -0
  72. package/harness/bundles/general/codex/harness-archive/SKILL.md +1 -1
  73. package/harness/bundles/general/codex/harness-codebase-map/SKILL.md +1 -1
  74. package/harness/bundles/general/codex/harness-knowledge-ingest/SKILL.md +1 -1
  75. package/harness/bundles/general/codex/harness-knowledge-query/SKILL.md +1 -1
  76. package/harness/bundles/general/codex/harness-plan/SKILL.md +1 -1
  77. package/harness/bundles/general/codex/harness-review/SKILL.md +1 -1
  78. package/harness/bundles/general/codex/harness-run/SKILL.md +1 -1
  79. package/harness/bundles/general/codex/harness-submit/SKILL.md +1 -1
  80. package/harness/bundles/general/codex/harness-submit/checklist.md +12 -0
  81. package/harness/bundles/general/codex/harness-sync/SKILL.md +1 -1
  82. package/harness/bundles/general/codex/harness-test/SKILL.md +1 -1
  83. package/harness/bundles/general/codex/scripts/harness_archive.py +267 -22
  84. package/harness/bundles/general/codex/scripts/harness_change.py +137 -2
  85. package/harness/bundles/general/codex/scripts/harness_efficiency.py +153 -0
  86. package/harness/bundles/general/codex/scripts/harness_environment.py +55 -25
  87. package/harness/bundles/general/codex/scripts/harness_execution_contracts.py +596 -0
  88. package/harness/bundles/general/codex/scripts/harness_integration.py +289 -52
  89. package/harness/bundles/general/codex/scripts/harness_ledger.py +5 -0
  90. package/harness/bundles/general/codex/scripts/harness_orchestration.py +344 -0
  91. package/harness/bundles/general/codex/scripts/harness_process.py +1065 -0
  92. package/harness/bundles/general/codex/scripts/harness_profile.py +244 -4
  93. package/harness/bundles/general/codex/scripts/harness_runtime.py +543 -132
  94. package/harness/bundles/general/codex/scripts/harness_service.py +1469 -194
  95. package/harness/bundles/general/codex/scripts/harness_test_runner.py +107 -117
  96. package/harness/bundles/general/codex/scripts/harness_verification.py +79 -0
  97. package/harness/bundles/general/cursor/.harness-build.json +1 -1
  98. package/harness/bundles/general/cursor/contracts/build-profile-v3.schema.json +100 -0
  99. package/harness/bundles/general/cursor/contracts/fixtures/managed-execution.json +341 -0
  100. package/harness/bundles/general/cursor/contracts/process-identity.schema.json +132 -0
  101. package/harness/bundles/general/cursor/contracts/run-session.schema.json +142 -0
  102. package/harness/bundles/general/cursor/contracts/service-retirement-receipt.schema.json +85 -0
  103. package/harness/bundles/general/cursor/contracts/service-session.schema.json +147 -0
  104. package/harness/bundles/general/cursor/harness-archive/SKILL.md +1 -1
  105. package/harness/bundles/general/cursor/harness-codebase-map/SKILL.md +1 -1
  106. package/harness/bundles/general/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  107. package/harness/bundles/general/cursor/harness-knowledge-query/SKILL.md +1 -1
  108. package/harness/bundles/general/cursor/harness-plan/SKILL.md +1 -1
  109. package/harness/bundles/general/cursor/harness-review/SKILL.md +1 -1
  110. package/harness/bundles/general/cursor/harness-run/SKILL.md +1 -1
  111. package/harness/bundles/general/cursor/harness-submit/SKILL.md +1 -1
  112. package/harness/bundles/general/cursor/harness-submit/checklist.md +12 -0
  113. package/harness/bundles/general/cursor/harness-sync/SKILL.md +1 -1
  114. package/harness/bundles/general/cursor/harness-test/SKILL.md +1 -1
  115. package/harness/bundles/general/cursor/scripts/harness_archive.py +267 -22
  116. package/harness/bundles/general/cursor/scripts/harness_change.py +137 -2
  117. package/harness/bundles/general/cursor/scripts/harness_efficiency.py +153 -0
  118. package/harness/bundles/general/cursor/scripts/harness_environment.py +55 -25
  119. package/harness/bundles/general/cursor/scripts/harness_execution_contracts.py +596 -0
  120. package/harness/bundles/general/cursor/scripts/harness_integration.py +289 -52
  121. package/harness/bundles/general/cursor/scripts/harness_ledger.py +5 -0
  122. package/harness/bundles/general/cursor/scripts/harness_orchestration.py +344 -0
  123. package/harness/bundles/general/cursor/scripts/harness_process.py +1065 -0
  124. package/harness/bundles/general/cursor/scripts/harness_profile.py +244 -4
  125. package/harness/bundles/general/cursor/scripts/harness_runtime.py +543 -132
  126. package/harness/bundles/general/cursor/scripts/harness_service.py +1469 -194
  127. package/harness/bundles/general/cursor/scripts/harness_test_runner.py +107 -117
  128. package/harness/bundles/general/cursor/scripts/harness_verification.py +79 -0
  129. package/harness/bundles/java/claude-code/.harness-build.json +1 -1
  130. package/harness/bundles/java/claude-code/contracts/build-profile-v3.schema.json +100 -0
  131. package/harness/bundles/java/claude-code/contracts/fixtures/managed-execution.json +341 -0
  132. package/harness/bundles/java/claude-code/contracts/process-identity.schema.json +132 -0
  133. package/harness/bundles/java/claude-code/contracts/run-session.schema.json +142 -0
  134. package/harness/bundles/java/claude-code/contracts/service-retirement-receipt.schema.json +85 -0
  135. package/harness/bundles/java/claude-code/contracts/service-session.schema.json +147 -0
  136. package/harness/bundles/java/claude-code/harness-apidoc/SKILL.md +1 -1
  137. package/harness/bundles/java/claude-code/harness-archive/SKILL.md +1 -1
  138. package/harness/bundles/java/claude-code/harness-codebase-map/SKILL.md +1 -1
  139. package/harness/bundles/java/claude-code/harness-knowledge-ingest/SKILL.md +1 -1
  140. package/harness/bundles/java/claude-code/harness-knowledge-query/SKILL.md +1 -1
  141. package/harness/bundles/java/claude-code/harness-package/SKILL.md +1 -1
  142. package/harness/bundles/java/claude-code/harness-plan/SKILL.md +1 -1
  143. package/harness/bundles/java/claude-code/harness-review/SKILL.md +1 -1
  144. package/harness/bundles/java/claude-code/harness-run/SKILL.md +1 -1
  145. package/harness/bundles/java/claude-code/harness-submit/SKILL.md +1 -1
  146. package/harness/bundles/java/claude-code/harness-submit/checklist.md +12 -0
  147. package/harness/bundles/java/claude-code/harness-sync/SKILL.md +1 -1
  148. package/harness/bundles/java/claude-code/harness-test/SKILL.md +1 -1
  149. package/harness/bundles/java/claude-code/scripts/harness_archive.py +267 -22
  150. package/harness/bundles/java/claude-code/scripts/harness_change.py +137 -2
  151. package/harness/bundles/java/claude-code/scripts/harness_efficiency.py +153 -0
  152. package/harness/bundles/java/claude-code/scripts/harness_environment.py +55 -25
  153. package/harness/bundles/java/claude-code/scripts/harness_execution_contracts.py +596 -0
  154. package/harness/bundles/java/claude-code/scripts/harness_integration.py +289 -52
  155. package/harness/bundles/java/claude-code/scripts/harness_ledger.py +5 -0
  156. package/harness/bundles/java/claude-code/scripts/harness_orchestration.py +344 -0
  157. package/harness/bundles/java/claude-code/scripts/harness_process.py +1065 -0
  158. package/harness/bundles/java/claude-code/scripts/harness_profile.py +244 -4
  159. package/harness/bundles/java/claude-code/scripts/harness_runtime.py +543 -132
  160. package/harness/bundles/java/claude-code/scripts/harness_service.py +1469 -194
  161. package/harness/bundles/java/claude-code/scripts/harness_test_runner.py +107 -117
  162. package/harness/bundles/java/claude-code/scripts/harness_verification.py +79 -0
  163. package/harness/bundles/java/codebuddy/.harness-build.json +1 -1
  164. package/harness/bundles/java/codebuddy/contracts/build-profile-v3.schema.json +100 -0
  165. package/harness/bundles/java/codebuddy/contracts/fixtures/managed-execution.json +341 -0
  166. package/harness/bundles/java/codebuddy/contracts/process-identity.schema.json +132 -0
  167. package/harness/bundles/java/codebuddy/contracts/run-session.schema.json +142 -0
  168. package/harness/bundles/java/codebuddy/contracts/service-retirement-receipt.schema.json +85 -0
  169. package/harness/bundles/java/codebuddy/contracts/service-session.schema.json +147 -0
  170. package/harness/bundles/java/codebuddy/harness-apidoc/SKILL.md +1 -1
  171. package/harness/bundles/java/codebuddy/harness-archive/SKILL.md +1 -1
  172. package/harness/bundles/java/codebuddy/harness-codebase-map/SKILL.md +1 -1
  173. package/harness/bundles/java/codebuddy/harness-knowledge-ingest/SKILL.md +1 -1
  174. package/harness/bundles/java/codebuddy/harness-knowledge-query/SKILL.md +1 -1
  175. package/harness/bundles/java/codebuddy/harness-package/SKILL.md +1 -1
  176. package/harness/bundles/java/codebuddy/harness-plan/SKILL.md +1 -1
  177. package/harness/bundles/java/codebuddy/harness-review/SKILL.md +1 -1
  178. package/harness/bundles/java/codebuddy/harness-run/SKILL.md +1 -1
  179. package/harness/bundles/java/codebuddy/harness-submit/SKILL.md +1 -1
  180. package/harness/bundles/java/codebuddy/harness-submit/checklist.md +12 -0
  181. package/harness/bundles/java/codebuddy/harness-sync/SKILL.md +1 -1
  182. package/harness/bundles/java/codebuddy/harness-test/SKILL.md +1 -1
  183. package/harness/bundles/java/codebuddy/scripts/harness_archive.py +267 -22
  184. package/harness/bundles/java/codebuddy/scripts/harness_change.py +137 -2
  185. package/harness/bundles/java/codebuddy/scripts/harness_efficiency.py +153 -0
  186. package/harness/bundles/java/codebuddy/scripts/harness_environment.py +55 -25
  187. package/harness/bundles/java/codebuddy/scripts/harness_execution_contracts.py +596 -0
  188. package/harness/bundles/java/codebuddy/scripts/harness_integration.py +289 -52
  189. package/harness/bundles/java/codebuddy/scripts/harness_ledger.py +5 -0
  190. package/harness/bundles/java/codebuddy/scripts/harness_orchestration.py +344 -0
  191. package/harness/bundles/java/codebuddy/scripts/harness_process.py +1065 -0
  192. package/harness/bundles/java/codebuddy/scripts/harness_profile.py +244 -4
  193. package/harness/bundles/java/codebuddy/scripts/harness_runtime.py +543 -132
  194. package/harness/bundles/java/codebuddy/scripts/harness_service.py +1469 -194
  195. package/harness/bundles/java/codebuddy/scripts/harness_test_runner.py +107 -117
  196. package/harness/bundles/java/codebuddy/scripts/harness_verification.py +79 -0
  197. package/harness/bundles/java/codex/.harness-build.json +1 -1
  198. package/harness/bundles/java/codex/contracts/build-profile-v3.schema.json +100 -0
  199. package/harness/bundles/java/codex/contracts/fixtures/managed-execution.json +341 -0
  200. package/harness/bundles/java/codex/contracts/process-identity.schema.json +132 -0
  201. package/harness/bundles/java/codex/contracts/run-session.schema.json +142 -0
  202. package/harness/bundles/java/codex/contracts/service-retirement-receipt.schema.json +85 -0
  203. package/harness/bundles/java/codex/contracts/service-session.schema.json +147 -0
  204. package/harness/bundles/java/codex/harness-apidoc/SKILL.md +1 -1
  205. package/harness/bundles/java/codex/harness-archive/SKILL.md +1 -1
  206. package/harness/bundles/java/codex/harness-codebase-map/SKILL.md +1 -1
  207. package/harness/bundles/java/codex/harness-knowledge-ingest/SKILL.md +1 -1
  208. package/harness/bundles/java/codex/harness-knowledge-query/SKILL.md +1 -1
  209. package/harness/bundles/java/codex/harness-package/SKILL.md +1 -1
  210. package/harness/bundles/java/codex/harness-plan/SKILL.md +1 -1
  211. package/harness/bundles/java/codex/harness-review/SKILL.md +1 -1
  212. package/harness/bundles/java/codex/harness-run/SKILL.md +1 -1
  213. package/harness/bundles/java/codex/harness-submit/SKILL.md +1 -1
  214. package/harness/bundles/java/codex/harness-submit/checklist.md +12 -0
  215. package/harness/bundles/java/codex/harness-sync/SKILL.md +1 -1
  216. package/harness/bundles/java/codex/harness-test/SKILL.md +1 -1
  217. package/harness/bundles/java/codex/scripts/harness_archive.py +267 -22
  218. package/harness/bundles/java/codex/scripts/harness_change.py +137 -2
  219. package/harness/bundles/java/codex/scripts/harness_efficiency.py +153 -0
  220. package/harness/bundles/java/codex/scripts/harness_environment.py +55 -25
  221. package/harness/bundles/java/codex/scripts/harness_execution_contracts.py +596 -0
  222. package/harness/bundles/java/codex/scripts/harness_integration.py +289 -52
  223. package/harness/bundles/java/codex/scripts/harness_ledger.py +5 -0
  224. package/harness/bundles/java/codex/scripts/harness_orchestration.py +344 -0
  225. package/harness/bundles/java/codex/scripts/harness_process.py +1065 -0
  226. package/harness/bundles/java/codex/scripts/harness_profile.py +244 -4
  227. package/harness/bundles/java/codex/scripts/harness_runtime.py +543 -132
  228. package/harness/bundles/java/codex/scripts/harness_service.py +1469 -194
  229. package/harness/bundles/java/codex/scripts/harness_test_runner.py +107 -117
  230. package/harness/bundles/java/codex/scripts/harness_verification.py +79 -0
  231. package/harness/bundles/java/cursor/.harness-build.json +1 -1
  232. package/harness/bundles/java/cursor/contracts/build-profile-v3.schema.json +100 -0
  233. package/harness/bundles/java/cursor/contracts/fixtures/managed-execution.json +341 -0
  234. package/harness/bundles/java/cursor/contracts/process-identity.schema.json +132 -0
  235. package/harness/bundles/java/cursor/contracts/run-session.schema.json +142 -0
  236. package/harness/bundles/java/cursor/contracts/service-retirement-receipt.schema.json +85 -0
  237. package/harness/bundles/java/cursor/contracts/service-session.schema.json +147 -0
  238. package/harness/bundles/java/cursor/harness-apidoc/SKILL.md +1 -1
  239. package/harness/bundles/java/cursor/harness-archive/SKILL.md +1 -1
  240. package/harness/bundles/java/cursor/harness-codebase-map/SKILL.md +1 -1
  241. package/harness/bundles/java/cursor/harness-knowledge-ingest/SKILL.md +1 -1
  242. package/harness/bundles/java/cursor/harness-knowledge-query/SKILL.md +1 -1
  243. package/harness/bundles/java/cursor/harness-package/SKILL.md +1 -1
  244. package/harness/bundles/java/cursor/harness-plan/SKILL.md +1 -1
  245. package/harness/bundles/java/cursor/harness-review/SKILL.md +1 -1
  246. package/harness/bundles/java/cursor/harness-run/SKILL.md +1 -1
  247. package/harness/bundles/java/cursor/harness-submit/SKILL.md +1 -1
  248. package/harness/bundles/java/cursor/harness-submit/checklist.md +12 -0
  249. package/harness/bundles/java/cursor/harness-sync/SKILL.md +1 -1
  250. package/harness/bundles/java/cursor/harness-test/SKILL.md +1 -1
  251. package/harness/bundles/java/cursor/scripts/harness_archive.py +267 -22
  252. package/harness/bundles/java/cursor/scripts/harness_change.py +137 -2
  253. package/harness/bundles/java/cursor/scripts/harness_efficiency.py +153 -0
  254. package/harness/bundles/java/cursor/scripts/harness_environment.py +55 -25
  255. package/harness/bundles/java/cursor/scripts/harness_execution_contracts.py +596 -0
  256. package/harness/bundles/java/cursor/scripts/harness_integration.py +289 -52
  257. package/harness/bundles/java/cursor/scripts/harness_ledger.py +5 -0
  258. package/harness/bundles/java/cursor/scripts/harness_orchestration.py +344 -0
  259. package/harness/bundles/java/cursor/scripts/harness_process.py +1065 -0
  260. package/harness/bundles/java/cursor/scripts/harness_profile.py +244 -4
  261. package/harness/bundles/java/cursor/scripts/harness_runtime.py +543 -132
  262. package/harness/bundles/java/cursor/scripts/harness_service.py +1469 -194
  263. package/harness/bundles/java/cursor/scripts/harness_test_runner.py +107 -117
  264. package/harness/bundles/java/cursor/scripts/harness_verification.py +79 -0
  265. package/harness/manifests/general/claude-code.json +58 -26
  266. package/harness/manifests/general/codebuddy.json +58 -26
  267. package/harness/manifests/general/codex.json +58 -26
  268. package/harness/manifests/general/cursor.json +58 -26
  269. package/harness/manifests/java/claude-code.json +60 -28
  270. package/harness/manifests/java/codebuddy.json +60 -28
  271. package/harness/manifests/java/codex.json +60 -28
  272. package/harness/manifests/java/cursor.json +60 -28
  273. package/hunter-workflow-family.json +4 -4
  274. package/package.json +1 -1
@@ -77,6 +77,7 @@ import harness_paths as hp # noqa: E402
77
77
  import harness_phase as hphase # noqa: E402
78
78
  import harness_report_model as hrm # noqa: E402
79
79
  import harness_review as hr # noqa: E402
80
+ import harness_runtime as hruntime # noqa: E402
80
81
 
81
82
 
82
83
  # ---------------------------------------------------------------------------
@@ -1957,6 +1958,131 @@ def check_archive_exact_byte_policy(project_root: Path) -> dict[str, Any]:
1957
1958
  }
1958
1959
 
1959
1960
 
1961
+ def validate_sensitive_evidence_publication_gate(
1962
+ change_dir: Path,
1963
+ *,
1964
+ copy_root: Path | None = None,
1965
+ require_receipt: bool = False,
1966
+ ) -> dict[str, Any]:
1967
+ """Fail closed before freeze/copy when plaintext evidence is unresolved.
1968
+
1969
+ The receipt is deliberately self-excluded from the tree digest. It may
1970
+ therefore bind the exact publishable bytes without creating a recursive
1971
+ digest. Private quarantine paths are evidence metadata only and must be
1972
+ outside both the project/copy roots.
1973
+ """
1974
+ change_dir = change_dir.expanduser().resolve()
1975
+ copy_root = (copy_root or change_dir).expanduser().resolve()
1976
+ receipt_path = hruntime.sensitive_evidence_receipt_path(change_dir)
1977
+ candidates = hruntime.sensitive_evidence_candidates(change_dir)
1978
+ if candidates:
1979
+ return {
1980
+ "ok": False,
1981
+ "reasonCode": "SENSITIVE_EVIDENCE_UNQUARANTINED",
1982
+ "receiptPath": str(receipt_path),
1983
+ "unresolvedFailures": candidates,
1984
+ "nextAction": "Quarantine the original bytes before archive publication.",
1985
+ }
1986
+ if not receipt_path.is_file():
1987
+ if require_receipt:
1988
+ return {
1989
+ "ok": False,
1990
+ "reasonCode": "SECRET_SCAN_RECEIPT_MISSING",
1991
+ "receiptPath": str(receipt_path),
1992
+ "unresolvedFailures": [],
1993
+ }
1994
+ return {
1995
+ "ok": True,
1996
+ "reasonCode": "SECRET_SCAN_NOT_APPLICABLE",
1997
+ "receiptPath": str(receipt_path),
1998
+ "receiptRequired": False,
1999
+ "unresolvedFailures": [],
2000
+ }
2001
+ try:
2002
+ receipt = read_json(receipt_path)
2003
+ except (OSError, json.JSONDecodeError, TypeError) as exc:
2004
+ return {
2005
+ "ok": False,
2006
+ "reasonCode": "SECRET_SCAN_RECEIPT_INVALID",
2007
+ "receiptPath": str(receipt_path),
2008
+ "error": str(exc),
2009
+ }
2010
+ if not isinstance(receipt, dict):
2011
+ return {
2012
+ "ok": False,
2013
+ "reasonCode": "SECRET_SCAN_RECEIPT_INVALID",
2014
+ "receiptPath": str(receipt_path),
2015
+ "error": "receipt must be an object",
2016
+ }
2017
+ issues: list[dict[str, Any]] = []
2018
+ if receipt.get("schemaVersion") != 1:
2019
+ issues.append({"code": "SECRET_SCAN_SCHEMA_INVALID"})
2020
+ if receipt.get("rulesVersion") != hruntime.SECRET_SCAN_RULES_VERSION:
2021
+ issues.append({"code": "SECRET_SCAN_RULES_MISMATCH"})
2022
+ if receipt.get("changeId") != change_dir.name:
2023
+ issues.append({"code": "SECRET_SCAN_CHANGE_ID_MISMATCH"})
2024
+ if str(receipt.get("status") or "").upper() not in {"OK", "QUARANTINED"}:
2025
+ issues.append({"code": "SENSITIVE_EVIDENCE_QUARANTINE_FAILED"})
2026
+ unresolved = receipt.get("unresolvedFailures")
2027
+ if isinstance(unresolved, list) and unresolved:
2028
+ issues.append({"code": "SENSITIVE_EVIDENCE_QUARANTINE_FAILED", "count": len(unresolved)})
2029
+ elif unresolved not in (None, []):
2030
+ issues.append({"code": "SECRET_SCAN_UNRESOLVED_INVALID"})
2031
+ try:
2032
+ actual_digest = hruntime.publishable_tree_digest(change_dir)
2033
+ except OSError as exc:
2034
+ actual_digest = None
2035
+ issues.append({"code": "SECRET_SCAN_TREE_UNREADABLE", "error": str(exc)})
2036
+ if actual_digest is not None and receipt.get("publishableTreeDigest") != actual_digest:
2037
+ issues.append({
2038
+ "code": "SECRET_SCAN_TREE_DIGEST_MISMATCH",
2039
+ "expected": receipt.get("publishableTreeDigest"),
2040
+ "actual": actual_digest,
2041
+ })
2042
+ if receipt.get("publicationExcluded") is not True:
2043
+ issues.append({"code": "SECRET_SCAN_PUBLICATION_NOT_EXCLUDED"})
2044
+ project_root = find_project_root(change_dir)
2045
+ for entry in receipt.get("entries") or []:
2046
+ if not isinstance(entry, dict):
2047
+ issues.append({"code": "SECRET_SCAN_ENTRY_INVALID"})
2048
+ continue
2049
+ private_raw = entry.get("privatePath")
2050
+ if not isinstance(private_raw, str) or not private_raw.strip():
2051
+ issues.append({"code": "SECRET_SCAN_PRIVATE_PATH_MISSING"})
2052
+ continue
2053
+ private_path = Path(private_raw).expanduser().resolve()
2054
+ if (
2055
+ _path_is_within(private_path, copy_root)
2056
+ or _path_is_within(private_path, project_root)
2057
+ or _path_is_within(private_path, change_dir)
2058
+ ):
2059
+ issues.append({
2060
+ "code": "SECRET_SCAN_PRIVATE_PATH_IN_COPY_ROOT",
2061
+ "privatePath": str(private_path),
2062
+ })
2063
+ if not private_path.is_file():
2064
+ issues.append({
2065
+ "code": "SECRET_SCAN_PRIVATE_PATH_MISSING",
2066
+ "privatePath": str(private_path),
2067
+ })
2068
+ source_raw = entry.get("sourcePath")
2069
+ if isinstance(source_raw, str) and source_raw.strip():
2070
+ source_path = (change_dir / source_raw).resolve()
2071
+ if _path_is_within(source_path, change_dir) and source_path.exists():
2072
+ issues.append({
2073
+ "code": "SENSITIVE_EVIDENCE_SOURCE_REMAINS",
2074
+ "sourcePath": source_raw,
2075
+ })
2076
+ return {
2077
+ "ok": not issues,
2078
+ "reasonCode": "SECRET_SCAN_GATE_SATISFIED" if not issues else "SECRET_SCAN_GATE_BLOCKED",
2079
+ "receiptPath": str(receipt_path),
2080
+ "receipt": receipt,
2081
+ "issues": issues,
2082
+ "treeDigest": actual_digest,
2083
+ }
2084
+
2085
+
1960
2086
  # ---------------------------------------------------------------------------
1961
2087
  # status
1962
2088
  # ---------------------------------------------------------------------------
@@ -2001,6 +2127,22 @@ def check_status(
2001
2127
  }
2002
2128
  )
2003
2129
 
2130
+ sensitive_gate = validate_sensitive_evidence_publication_gate(
2131
+ change_dir,
2132
+ copy_root=change_dir,
2133
+ require_receipt=False,
2134
+ )
2135
+ checks["sensitive_evidence_publication"] = sensitive_gate
2136
+ if not sensitive_gate.get("ok"):
2137
+ blockers.append({
2138
+ "code": str(sensitive_gate.get("reasonCode") or "SECRET_SCAN_GATE_BLOCKED"),
2139
+ "message": str(
2140
+ sensitive_gate.get("nextAction")
2141
+ or sensitive_gate.get("error")
2142
+ or "sensitive evidence publication gate failed"
2143
+ ),
2144
+ })
2145
+
2004
2146
  # --- H-4 formal-layer minimum set ---
2005
2147
  plans_dir = change_dir / "plans"
2006
2148
  plan_files = (
@@ -2246,6 +2388,14 @@ def check_status(
2246
2388
  except Exception as exc: # noqa: BLE001 — preflight must not crash status
2247
2389
  preflight = {"ok": False, "items": [], "blocking": [], "error": str(exc)}
2248
2390
  checks["artifact_preflight"] = preflight
2391
+ if preflight.get("ok") is not True and not preflight.get("blocking"):
2392
+ blockers.append({
2393
+ "code": "artifact-preflight-invalid",
2394
+ "message": str(
2395
+ preflight.get("error")
2396
+ or "artifact event projection or preflight validation failed"
2397
+ ),
2398
+ })
2249
2399
  for item in preflight.get("blocking") or []:
2250
2400
  blockers.append({
2251
2401
  "code": "artifact-path-blocking",
@@ -6465,12 +6615,9 @@ def artifact_preflight(change_dir: Path) -> dict[str, Any]:
6465
6615
  return {"ok": True, "items": [], "blocking": []}
6466
6616
  change_id = change_dir.name
6467
6617
  project_root = find_project_root(change_dir)
6468
- for line in events_p.read_text(encoding="utf-8").splitlines():
6469
- try:
6470
- event = json.loads(line)
6471
- except json.JSONDecodeError:
6472
- continue
6473
- if not isinstance(event, dict) or event.get("type") != "artifact":
6618
+ events = he.apply_event_corrections(he.load_events(events_p))
6619
+ for event in events:
6620
+ if event.get("type") != "artifact":
6474
6621
  continue
6475
6622
  path = str(event.get("path") or "").strip()
6476
6623
  kind = str(event.get("kind") or "").strip()
@@ -6657,9 +6804,19 @@ def evaluate_artifact_budget(change_dir: Path) -> dict[str, Any]:
6657
6804
  except (OSError, ValueError, json.JSONDecodeError) as exc:
6658
6805
  return {
6659
6806
  "ok": False,
6660
- "code": "ARTIFACT_POLICY_INVALID",
6807
+ "code": "ARTIFACT_PREFLIGHT_INVALID",
6661
6808
  "message": str(exc),
6662
6809
  }
6810
+ if preflight.get("ok") is not True:
6811
+ return {
6812
+ "ok": False,
6813
+ "code": "ARTIFACT_PREFLIGHT_INVALID",
6814
+ "message": str(
6815
+ preflight.get("error")
6816
+ or "artifact event projection or preflight validation failed"
6817
+ ),
6818
+ "preflightBlocking": preflight.get("blocking") or [],
6819
+ }
6663
6820
  excluded_parts = {
6664
6821
  "node_modules",
6665
6822
  ".venv",
@@ -6697,7 +6854,7 @@ def evaluate_artifact_budget(change_dir: Path) -> dict[str, Any]:
6697
6854
  oversized = [
6698
6855
  item for item in entries if int(item["bytes"]) > max_file
6699
6856
  ]
6700
- ok = total <= max_total and not oversized and bool(preflight.get("ok"))
6857
+ ok = total <= max_total and not oversized
6701
6858
  return {
6702
6859
  "ok": ok,
6703
6860
  "code": (
@@ -6726,6 +6883,13 @@ def materialize_repository_artifacts(change_dir: Path) -> dict[str, Any]:
6726
6883
  change_dir = change_dir.resolve()
6727
6884
  project_root = find_project_root(change_dir)
6728
6885
  preflight = artifact_preflight(change_dir)
6886
+ if preflight.get("ok") is not True:
6887
+ raise ValueError(
6888
+ str(
6889
+ preflight.get("error")
6890
+ or "artifact event projection or preflight validation failed"
6891
+ )
6892
+ )
6729
6893
  copied: list[str] = []
6730
6894
  objects: list[dict[str, Any]] = []
6731
6895
  bytes_added = 0
@@ -7299,6 +7463,32 @@ def cmd_finalize(
7299
7463
  payload["error"] = f"archive target already exists: {archive_dir}"
7300
7464
  return 1, payload
7301
7465
 
7466
+ source_sensitive_gate = validate_sensitive_evidence_publication_gate(
7467
+ original_change_dir,
7468
+ copy_root=original_change_dir,
7469
+ require_receipt=False,
7470
+ )
7471
+ payload["steps"]["sensitive_evidence_source_gate"] = source_sensitive_gate
7472
+ if not source_sensitive_gate.get("ok"):
7473
+ payload["error"] = str(
7474
+ source_sensitive_gate.get("nextAction")
7475
+ or source_sensitive_gate.get("error")
7476
+ or "sensitive evidence publication gate failed"
7477
+ )
7478
+ payload["issues"] = [
7479
+ {
7480
+ "code": str(
7481
+ source_sensitive_gate.get("reasonCode")
7482
+ or "SECRET_SCAN_GATE_BLOCKED"
7483
+ ),
7484
+ "severity": "error",
7485
+ "message": payload["error"],
7486
+ }
7487
+ ]
7488
+ payload["original_preserved"] = original_change_dir.is_dir()
7489
+ payload["finalStatus"] = "FAIL"
7490
+ return 1, payload
7491
+
7302
7492
  exact_byte = check_archive_exact_byte_policy(project_root)
7303
7493
  payload["steps"]["archive_exact_byte"] = exact_byte
7304
7494
  if not exact_byte["ok"]:
@@ -7307,7 +7497,13 @@ def cmd_finalize(
7307
7497
  artifact_budget = evaluate_artifact_budget(original_change_dir)
7308
7498
  payload["steps"]["artifact_budget"] = artifact_budget
7309
7499
  if not artifact_budget.get("ok"):
7310
- payload["error"] = "artifact budget exceeded before staging"
7500
+ if artifact_budget.get("code") == "ARTIFACT_PREFLIGHT_INVALID":
7501
+ payload["error"] = str(
7502
+ artifact_budget.get("message")
7503
+ or "artifact validation failed before staging"
7504
+ )
7505
+ else:
7506
+ payload["error"] = "artifact budget exceeded before staging"
7311
7507
  payload["issues"] = [
7312
7508
  {
7313
7509
  "code": str(
@@ -7380,6 +7576,38 @@ def cmd_finalize(
7380
7576
  work_dir = operation_temp_dir
7381
7577
  before_manifest: dict[str, Any] | None = None
7382
7578
 
7579
+ # A source tree without sensitive evidence still receives a digest-bound
7580
+ # receipt in the isolated staging tree. This keeps legacy archives
7581
+ # compatible while making every published archive auditable.
7582
+ try:
7583
+ staged_receipt = hruntime.sensitive_evidence_receipt_path(work_dir)
7584
+ if not staged_receipt.is_file():
7585
+ hruntime.ensure_sensitive_evidence_scan_receipt(work_dir)
7586
+ staged_sensitive_gate = validate_sensitive_evidence_publication_gate(
7587
+ work_dir,
7588
+ copy_root=work_dir,
7589
+ require_receipt=True,
7590
+ )
7591
+ payload["steps"]["sensitive_evidence_publication"] = staged_sensitive_gate
7592
+ if not staged_sensitive_gate.get("ok"):
7593
+ payload["error"] = "sensitive evidence publication gate failed before freeze"
7594
+ payload["issues"] = [
7595
+ {
7596
+ "code": str(
7597
+ staged_sensitive_gate.get("reasonCode")
7598
+ or "SECRET_SCAN_GATE_BLOCKED"
7599
+ ),
7600
+ "severity": "error",
7601
+ "message": payload["error"],
7602
+ }
7603
+ ]
7604
+ _restore_finalize_failure()
7605
+ return 1, payload
7606
+ except (OSError, ValueError, json.JSONDecodeError) as exc:
7607
+ payload["error"] = f"sensitive evidence publication gate failed: {exc}"
7608
+ _restore_finalize_failure()
7609
+ return 1, payload
7610
+
7383
7611
  if split_state_dir is not None and split_state_dir.is_dir():
7384
7612
  _merge_runtime_state(split_state_dir, work_dir)
7385
7613
  payload["steps"]["split_state_merge"] = {
@@ -7478,19 +7706,36 @@ def cmd_finalize(
7478
7706
  "blockingCount": len(preflight.get("blocking") or []),
7479
7707
  "itemsCount": len(preflight.get("items") or []),
7480
7708
  }
7481
- if preflight.get("blocking"):
7482
- payload["error"] = (
7483
- f"artifact preflight blocking: "
7484
- f"{len(preflight['blocking'])} path(s) cannot be archived"
7485
- )
7486
- payload["issues"] = [
7487
- {
7488
- "code": "ARTIFACT_PATH_BLOCKING",
7489
- "severity": "error",
7490
- "message": f"{item.get('path', '')}: {item.get('reason', 'blocking')}",
7491
- }
7492
- for item in preflight["blocking"]
7493
- ]
7709
+ if preflight.get("ok") is not True:
7710
+ blocking_paths = preflight.get("blocking") or []
7711
+ if blocking_paths:
7712
+ payload["error"] = (
7713
+ f"artifact preflight blocking: "
7714
+ f"{len(blocking_paths)} path(s) cannot be archived"
7715
+ )
7716
+ payload["issues"] = [
7717
+ {
7718
+ "code": "ARTIFACT_PATH_BLOCKING",
7719
+ "severity": "error",
7720
+ "message": f"{item.get('path', '')}: {item.get('reason', 'blocking')}",
7721
+ }
7722
+ for item in blocking_paths
7723
+ ]
7724
+ else:
7725
+ payload["error"] = (
7726
+ "artifact preflight invalid: "
7727
+ + str(
7728
+ preflight.get("error")
7729
+ or "artifact event projection or preflight validation failed"
7730
+ )
7731
+ )
7732
+ payload["issues"] = [
7733
+ {
7734
+ "code": "ARTIFACT_PREFLIGHT_INVALID",
7735
+ "severity": "error",
7736
+ "message": payload["error"],
7737
+ }
7738
+ ]
7494
7739
  _restore_finalize_failure()
7495
7740
  payload["warnings"] = warnings
7496
7741
  payload["ok"] = False