harnery 0.36.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (432) hide show
  1. package/dist/commander.d.ts +9 -0
  2. package/dist/commander.d.ts.map +1 -1
  3. package/dist/commander.js +10 -1
  4. package/dist/commands/admission.d.ts +21 -0
  5. package/dist/commands/admission.d.ts.map +1 -0
  6. package/dist/commands/admission.js +565 -0
  7. package/dist/commands/agents.d.ts +7 -0
  8. package/dist/commands/agents.d.ts.map +1 -1
  9. package/dist/commands/agents.js +148 -47
  10. package/dist/commands/artifacts.d.ts.map +1 -1
  11. package/dist/commands/artifacts.js +73 -2
  12. package/dist/commands/browse-ai.d.ts +2 -2
  13. package/dist/commands/browse-ai.d.ts.map +1 -1
  14. package/dist/commands/browse-ai.js +6 -4
  15. package/dist/commands/browse.d.ts.map +1 -1
  16. package/dist/commands/browse.js +360 -21
  17. package/dist/commands/diagnostics.d.ts +4 -0
  18. package/dist/commands/diagnostics.d.ts.map +1 -0
  19. package/dist/commands/diagnostics.js +229 -0
  20. package/dist/commands/fetch.js +1 -0
  21. package/dist/commands/files.d.ts +12 -0
  22. package/dist/commands/files.d.ts.map +1 -1
  23. package/dist/commands/files.js +54 -1
  24. package/dist/commands/governor.d.ts.map +1 -1
  25. package/dist/commands/governor.js +4 -0
  26. package/dist/commands/ledger-v3.d.ts.map +1 -1
  27. package/dist/commands/ledger-v3.js +71 -2
  28. package/dist/commands/qa-record.d.ts +144 -0
  29. package/dist/commands/qa-record.d.ts.map +1 -0
  30. package/dist/commands/qa-record.js +0 -0
  31. package/dist/commands/qa-run.d.ts +8 -0
  32. package/dist/commands/qa-run.d.ts.map +1 -0
  33. package/dist/commands/qa-run.js +396 -0
  34. package/dist/commands/qa-status.d.ts +71 -0
  35. package/dist/commands/qa-status.d.ts.map +1 -0
  36. package/dist/commands/qa-status.js +490 -0
  37. package/dist/commands/qa-verify.d.ts +40 -0
  38. package/dist/commands/qa-verify.d.ts.map +1 -0
  39. package/dist/commands/qa-verify.js +180 -0
  40. package/dist/commands/resources.d.ts +4 -0
  41. package/dist/commands/resources.d.ts.map +1 -0
  42. package/dist/commands/resources.js +29 -0
  43. package/dist/commands/review-pack.d.ts +4 -0
  44. package/dist/commands/review-pack.d.ts.map +1 -0
  45. package/dist/commands/review-pack.js +1001 -0
  46. package/dist/commands/supervisor.d.ts +4 -0
  47. package/dist/commands/supervisor.d.ts.map +1 -0
  48. package/dist/commands/supervisor.js +101 -0
  49. package/dist/commands/web.d.ts.map +1 -1
  50. package/dist/commands/web.js +17 -0
  51. package/dist/commands/workflow.d.ts.map +1 -1
  52. package/dist/commands/workflow.js +4 -0
  53. package/dist/core/agents/cli.js +7 -3
  54. package/dist/core/agents/health.d.ts +17 -0
  55. package/dist/core/agents/health.d.ts.map +1 -0
  56. package/dist/core/agents/health.js +109 -0
  57. package/dist/core/agents/mailbox.d.ts +92 -0
  58. package/dist/core/agents/mailbox.d.ts.map +1 -0
  59. package/dist/core/agents/mailbox.js +325 -0
  60. package/dist/core/agents/qa-signal.d.ts +111 -0
  61. package/dist/core/agents/qa-signal.d.ts.map +1 -0
  62. package/dist/core/agents/qa-signal.js +231 -0
  63. package/dist/core/agents/reconcile-coordination-v3.d.ts +44 -0
  64. package/dist/core/agents/reconcile-coordination-v3.d.ts.map +1 -0
  65. package/dist/core/agents/reconcile-coordination-v3.js +58 -0
  66. package/dist/core/agents/render/prompt-context.d.ts +5 -0
  67. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  68. package/dist/core/agents/render/prompt-context.js +34 -13
  69. package/dist/core/agents/render/session-context.d.ts +8 -0
  70. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  71. package/dist/core/agents/render/session-context.js +34 -3
  72. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  73. package/dist/core/agents/rules/commit-conflict.js +50 -1
  74. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  75. package/dist/core/agents/rules/stop-hook.js +6 -10
  76. package/dist/core/agents/session-finalizer-v3.js +4 -1
  77. package/dist/core/agents/session-name-display.d.ts +20 -5
  78. package/dist/core/agents/session-name-display.d.ts.map +1 -1
  79. package/dist/core/agents/session-name-display.js +67 -7
  80. package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
  81. package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
  82. package/dist/core/agents/state/heartbeat-writer.d.ts +11 -0
  83. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  84. package/dist/core/agents/state/heartbeat-writer.js +17 -0
  85. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  86. package/dist/core/agents/state/live-coordination-view.js +1 -0
  87. package/dist/core/agents/state/live-coordination-writer.js +5 -0
  88. package/dist/core/artifacts/constants.d.ts +1 -1
  89. package/dist/core/artifacts/constants.js +1 -1
  90. package/dist/core/artifacts/index.d.ts +82 -6
  91. package/dist/core/artifacts/index.d.ts.map +1 -1
  92. package/dist/core/artifacts/index.js +410 -15
  93. package/dist/core/config.d.ts +20 -0
  94. package/dist/core/config.d.ts.map +1 -1
  95. package/dist/core/config.js +59 -0
  96. package/dist/core/diagnostics/advice.d.ts +9 -0
  97. package/dist/core/diagnostics/advice.d.ts.map +1 -0
  98. package/dist/core/diagnostics/advice.js +112 -0
  99. package/dist/core/diagnostics/bundle.d.ts +51 -0
  100. package/dist/core/diagnostics/bundle.d.ts.map +1 -0
  101. package/dist/core/diagnostics/bundle.js +968 -0
  102. package/dist/core/diagnostics/comparison.d.ts +5 -0
  103. package/dist/core/diagnostics/comparison.d.ts.map +1 -0
  104. package/dist/core/diagnostics/comparison.js +444 -0
  105. package/dist/core/diagnostics/contract.d.ts +245 -0
  106. package/dist/core/diagnostics/contract.d.ts.map +1 -0
  107. package/dist/core/diagnostics/contract.js +18 -0
  108. package/dist/core/diagnostics/identity.d.ts +3 -0
  109. package/dist/core/diagnostics/identity.d.ts.map +1 -0
  110. package/dist/core/diagnostics/identity.js +10 -0
  111. package/dist/core/diagnostics/index.d.ts +8 -0
  112. package/dist/core/diagnostics/index.d.ts.map +1 -0
  113. package/dist/core/diagnostics/index.js +7 -0
  114. package/dist/core/diagnostics/replay.d.ts +8 -0
  115. package/dist/core/diagnostics/replay.d.ts.map +1 -0
  116. package/dist/core/diagnostics/replay.js +213 -0
  117. package/dist/core/diagnostics/sanitize.d.ts +9 -0
  118. package/dist/core/diagnostics/sanitize.d.ts.map +1 -0
  119. package/dist/core/diagnostics/sanitize.js +84 -0
  120. package/dist/core/events/legacy-storage/compression.d.ts +13 -0
  121. package/dist/core/events/legacy-storage/compression.d.ts.map +1 -0
  122. package/dist/core/events/legacy-storage/compression.js +107 -0
  123. package/dist/core/events/legacy-storage/index.d.ts +1 -0
  124. package/dist/core/events/legacy-storage/index.d.ts.map +1 -1
  125. package/dist/core/events/legacy-storage/index.js +1 -0
  126. package/dist/core/events/v3/archive-retention.d.ts +33 -0
  127. package/dist/core/events/v3/archive-retention.d.ts.map +1 -0
  128. package/dist/core/events/v3/archive-retention.js +195 -0
  129. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  130. package/dist/core/events/v3/bootstrap.js +10 -0
  131. package/dist/core/events/v3/capabilities.d.ts +1 -1
  132. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  133. package/dist/core/events/v3/capabilities.js +1 -0
  134. package/dist/core/events/v3/coordination-view.d.ts +3 -0
  135. package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
  136. package/dist/core/events/v3/coordination-view.js +69 -8
  137. package/dist/core/events/v3/index.d.ts +1 -0
  138. package/dist/core/events/v3/index.d.ts.map +1 -1
  139. package/dist/core/events/v3/index.js +1 -0
  140. package/dist/core/events/v3/live-routing.d.ts.map +1 -1
  141. package/dist/core/events/v3/live-routing.js +1 -0
  142. package/dist/core/events/v3/producers/hook-base.d.ts +1 -1
  143. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  144. package/dist/core/events/v3/producers/hook-base.js +13 -2
  145. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  146. package/dist/core/events/v3/producers/intake.js +10 -2
  147. package/dist/core/events/v3/producers/recorder.d.ts +39 -0
  148. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  149. package/dist/core/events/v3/producers/recorder.js +350 -17
  150. package/dist/core/hooks/adapter/output.d.ts +8 -0
  151. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  152. package/dist/core/hooks/adapter/output.js +11 -1
  153. package/dist/core/hooks/cli.js +303 -219
  154. package/dist/core/hooks/health.d.ts +59 -0
  155. package/dist/core/hooks/health.d.ts.map +1 -0
  156. package/dist/core/hooks/health.js +84 -0
  157. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  158. package/dist/core/hooks/resolve/transcript.js +10 -3
  159. package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
  160. package/dist/core/hooks/session-name-presence.js +4 -1
  161. package/dist/core/qa-artifacts.d.ts +20 -0
  162. package/dist/core/qa-artifacts.d.ts.map +1 -0
  163. package/dist/core/qa-artifacts.js +110 -0
  164. package/dist/core/resources/contract.d.ts +96 -0
  165. package/dist/core/resources/contract.d.ts.map +1 -0
  166. package/dist/core/resources/contract.js +2 -0
  167. package/dist/core/resources/index.d.ts +6 -0
  168. package/dist/core/resources/index.d.ts.map +1 -0
  169. package/dist/core/resources/index.js +5 -0
  170. package/dist/core/resources/sampler.d.ts +34 -0
  171. package/dist/core/resources/sampler.d.ts.map +1 -0
  172. package/dist/core/resources/sampler.js +458 -0
  173. package/dist/core/resources/service-status.d.ts +3 -0
  174. package/dist/core/resources/service-status.d.ts.map +1 -0
  175. package/dist/core/resources/service-status.js +48 -0
  176. package/dist/core/resources/service.d.ts +26 -0
  177. package/dist/core/resources/service.d.ts.map +1 -0
  178. package/dist/core/resources/service.js +292 -0
  179. package/dist/core/resources/storage.d.ts +13 -0
  180. package/dist/core/resources/storage.d.ts.map +1 -0
  181. package/dist/core/resources/storage.js +30 -0
  182. package/dist/core/storage/atomic-json.d.ts +3 -0
  183. package/dist/core/storage/atomic-json.d.ts.map +1 -0
  184. package/dist/core/storage/atomic-json.js +15 -0
  185. package/dist/core/storage/builtins.d.ts.map +1 -1
  186. package/dist/core/storage/builtins.js +45 -6
  187. package/dist/core/storage/logger.d.ts +2 -0
  188. package/dist/core/storage/logger.d.ts.map +1 -1
  189. package/dist/core/storage/logger.js +2 -0
  190. package/dist/core/storage/query.d.ts +14 -0
  191. package/dist/core/storage/query.d.ts.map +1 -1
  192. package/dist/core/storage/query.js +51 -0
  193. package/dist/core/supervisor/activity.d.ts +4 -0
  194. package/dist/core/supervisor/activity.d.ts.map +1 -0
  195. package/dist/core/supervisor/activity.js +141 -0
  196. package/dist/core/supervisor/contract.d.ts +268 -0
  197. package/dist/core/supervisor/contract.d.ts.map +1 -0
  198. package/dist/core/supervisor/contract.js +35 -0
  199. package/dist/core/supervisor/explanations.d.ts +4 -0
  200. package/dist/core/supervisor/explanations.d.ts.map +1 -0
  201. package/dist/core/supervisor/explanations.js +71 -0
  202. package/dist/core/supervisor/findings.d.ts +20 -0
  203. package/dist/core/supervisor/findings.d.ts.map +1 -0
  204. package/dist/core/supervisor/findings.js +399 -0
  205. package/dist/core/supervisor/history.d.ts +9 -0
  206. package/dist/core/supervisor/history.d.ts.map +1 -0
  207. package/dist/core/supervisor/history.js +46 -0
  208. package/dist/core/supervisor/hook-health-alerts.d.ts +14 -0
  209. package/dist/core/supervisor/hook-health-alerts.d.ts.map +1 -0
  210. package/dist/core/supervisor/hook-health-alerts.js +70 -0
  211. package/dist/core/supervisor/hook-health-storage.d.ts +5 -0
  212. package/dist/core/supervisor/hook-health-storage.d.ts.map +1 -0
  213. package/dist/core/supervisor/hook-health-storage.js +24 -0
  214. package/dist/core/supervisor/hook-health.d.ts +72 -0
  215. package/dist/core/supervisor/hook-health.d.ts.map +1 -0
  216. package/dist/core/supervisor/hook-health.js +203 -0
  217. package/dist/core/supervisor/hooks.d.ts +10 -0
  218. package/dist/core/supervisor/hooks.d.ts.map +1 -0
  219. package/dist/core/supervisor/hooks.js +28 -0
  220. package/dist/core/supervisor/index.d.ts +15 -0
  221. package/dist/core/supervisor/index.d.ts.map +1 -0
  222. package/dist/core/supervisor/index.js +14 -0
  223. package/dist/core/supervisor/log-feed.d.ts +9 -0
  224. package/dist/core/supervisor/log-feed.d.ts.map +1 -0
  225. package/dist/core/supervisor/log-feed.js +103 -0
  226. package/dist/core/supervisor/service.d.ts +29 -0
  227. package/dist/core/supervisor/service.d.ts.map +1 -0
  228. package/dist/core/supervisor/service.js +450 -0
  229. package/dist/core/supervisor/services.d.ts +11 -0
  230. package/dist/core/supervisor/services.d.ts.map +1 -0
  231. package/dist/core/supervisor/services.js +155 -0
  232. package/dist/core/supervisor/status.d.ts +3 -0
  233. package/dist/core/supervisor/status.d.ts.map +1 -0
  234. package/dist/core/supervisor/status.js +48 -0
  235. package/dist/core/supervisor/storage.d.ts +30 -0
  236. package/dist/core/supervisor/storage.d.ts.map +1 -0
  237. package/dist/core/supervisor/storage.js +73 -0
  238. package/dist/core/supervisor/timeline.d.ts +3 -0
  239. package/dist/core/supervisor/timeline.d.ts.map +1 -0
  240. package/dist/core/supervisor/timeline.js +87 -0
  241. package/dist/core/workflow/admission.d.ts +23 -0
  242. package/dist/core/workflow/admission.d.ts.map +1 -0
  243. package/dist/core/workflow/admission.js +136 -0
  244. package/dist/core/workflow/engine.d.ts.map +1 -1
  245. package/dist/core/workflow/engine.js +77 -2
  246. package/dist/core/workflow/index.d.ts +3 -2
  247. package/dist/core/workflow/index.d.ts.map +1 -1
  248. package/dist/core/workflow/index.js +2 -1
  249. package/dist/core/workflow/proof.d.ts +2 -1
  250. package/dist/core/workflow/proof.d.ts.map +1 -1
  251. package/dist/core/workflow/proof.js +39 -1
  252. package/dist/core/workflow/run-state.d.ts +3 -2
  253. package/dist/core/workflow/run-state.d.ts.map +1 -1
  254. package/dist/core/workflow/run-state.js +8 -1
  255. package/dist/core/workflow/types.d.ts +33 -1
  256. package/dist/core/workflow/types.d.ts.map +1 -1
  257. package/dist/core/workflow/types.js +2 -1
  258. package/dist/lib/admission.d.ts +71 -0
  259. package/dist/lib/admission.d.ts.map +1 -0
  260. package/dist/lib/admission.js +264 -0
  261. package/dist/lib/agent-browser/client.d.ts +1 -1
  262. package/dist/lib/agent-browser/client.d.ts.map +1 -1
  263. package/dist/lib/agent-browser/client.js +1 -5
  264. package/dist/lib/browser/capture-fidelity.d.ts +39 -0
  265. package/dist/lib/browser/capture-fidelity.d.ts.map +1 -0
  266. package/dist/lib/browser/capture-fidelity.js +84 -0
  267. package/dist/lib/browser/client.d.ts +46 -1
  268. package/dist/lib/browser/client.d.ts.map +1 -1
  269. package/dist/lib/browser/client.js +168 -9
  270. package/dist/lib/browser/critique.d.ts +38 -1
  271. package/dist/lib/browser/critique.d.ts.map +1 -1
  272. package/dist/lib/browser/critique.js +34 -6
  273. package/dist/lib/browser/index.d.ts +5 -1
  274. package/dist/lib/browser/index.d.ts.map +1 -1
  275. package/dist/lib/browser/index.js +4 -0
  276. package/dist/lib/browser/page-review-judge.d.ts +64 -0
  277. package/dist/lib/browser/page-review-judge.d.ts.map +1 -0
  278. package/dist/lib/browser/page-review-judge.js +270 -0
  279. package/dist/lib/browser/page-review-pack.d.ts +613 -0
  280. package/dist/lib/browser/page-review-pack.d.ts.map +1 -0
  281. package/dist/lib/browser/page-review-pack.js +1751 -0
  282. package/dist/lib/browser/qa-run-contracts.d.ts +377 -0
  283. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -0
  284. package/dist/lib/browser/qa-run-contracts.js +361 -0
  285. package/dist/lib/browser/qa-run.d.ts +141 -0
  286. package/dist/lib/browser/qa-run.d.ts.map +1 -0
  287. package/dist/lib/browser/qa-run.js +1283 -0
  288. package/dist/lib/browser/request-diagnostics.d.ts +13 -0
  289. package/dist/lib/browser/request-diagnostics.d.ts.map +1 -0
  290. package/dist/lib/browser/request-diagnostics.js +18 -0
  291. package/dist/lib/browser/tiling.d.ts +19 -0
  292. package/dist/lib/browser/tiling.d.ts.map +1 -1
  293. package/dist/lib/browser/tiling.js +28 -0
  294. package/dist/lib/cookies/client.d.ts +9 -0
  295. package/dist/lib/cookies/client.d.ts.map +1 -1
  296. package/dist/lib/cookies/client.js +197 -44
  297. package/dist/lib/cookies/extra.d.ts +18 -0
  298. package/dist/lib/cookies/extra.d.ts.map +1 -0
  299. package/dist/lib/cookies/extra.js +14 -0
  300. package/dist/lib/cookies/index.d.ts +2 -1
  301. package/dist/lib/cookies/index.d.ts.map +1 -1
  302. package/dist/lib/cookies/index.js +2 -1
  303. package/dist/lib/coord-root-id.d.ts +9 -0
  304. package/dist/lib/coord-root-id.d.ts.map +1 -0
  305. package/dist/lib/coord-root-id.js +17 -0
  306. package/dist/lib/durable-job.d.ts +124 -0
  307. package/dist/lib/durable-job.d.ts.map +1 -0
  308. package/dist/lib/durable-job.js +296 -0
  309. package/dist/lib/http/client.d.ts +7 -1
  310. package/dist/lib/http/client.d.ts.map +1 -1
  311. package/dist/lib/http/client.js +2 -0
  312. package/dist/lib/instructions/apply.d.ts +3 -1
  313. package/dist/lib/instructions/apply.d.ts.map +1 -1
  314. package/dist/lib/instructions/apply.js +74 -3
  315. package/dist/lib/instructions/templates.d.ts.map +1 -1
  316. package/dist/lib/instructions/templates.js +11 -2
  317. package/package.json +19 -2
  318. package/src/commander.ts +75 -1
  319. package/src/commands/admission.ts +699 -0
  320. package/src/commands/agents.ts +189 -50
  321. package/src/commands/artifacts.ts +132 -18
  322. package/src/commands/browse-ai.ts +10 -5
  323. package/src/commands/browse.ts +496 -20
  324. package/src/commands/diagnostics.ts +271 -0
  325. package/src/commands/fetch.ts +1 -0
  326. package/src/commands/files.ts +102 -2
  327. package/src/commands/governor.ts +8 -0
  328. package/src/commands/ledger-v3.ts +82 -0
  329. package/src/commands/qa-record.ts +682 -0
  330. package/src/commands/qa-run.ts +503 -0
  331. package/src/commands/qa-status.ts +608 -0
  332. package/src/commands/qa-verify.ts +238 -0
  333. package/src/commands/resources.ts +38 -0
  334. package/src/commands/review-pack.ts +1281 -0
  335. package/src/commands/supervisor.ts +141 -0
  336. package/src/commands/web.ts +19 -0
  337. package/src/commands/workflow.ts +8 -0
  338. package/src/core/agents/cli.ts +7 -3
  339. package/src/core/agents/health.ts +142 -0
  340. package/src/core/agents/mailbox.ts +373 -0
  341. package/src/core/agents/qa-signal.ts +261 -0
  342. package/src/core/agents/reconcile-coordination-v3.ts +77 -0
  343. package/src/core/agents/render/prompt-context.ts +42 -12
  344. package/src/core/agents/render/session-context.ts +37 -3
  345. package/src/core/agents/rules/commit-conflict.ts +58 -1
  346. package/src/core/agents/rules/stop-hook.ts +6 -12
  347. package/src/core/agents/session-finalizer-v3.ts +4 -1
  348. package/src/core/agents/session-name-display.ts +78 -7
  349. package/src/core/agents/state/heartbeat-reader.ts +7 -0
  350. package/src/core/agents/state/heartbeat-writer.ts +23 -0
  351. package/src/core/agents/state/live-coordination-view.ts +1 -0
  352. package/src/core/agents/state/live-coordination-writer.ts +5 -0
  353. package/src/core/artifacts/constants.ts +1 -1
  354. package/src/core/artifacts/index.ts +565 -30
  355. package/src/core/config.ts +134 -2
  356. package/src/core/diagnostics/advice.ts +147 -0
  357. package/src/core/diagnostics/bundle.ts +1250 -0
  358. package/src/core/diagnostics/comparison.ts +565 -0
  359. package/src/core/diagnostics/contract.ts +311 -0
  360. package/src/core/diagnostics/identity.ts +11 -0
  361. package/src/core/diagnostics/index.ts +7 -0
  362. package/src/core/diagnostics/replay.ts +314 -0
  363. package/src/core/diagnostics/sanitize.ts +97 -0
  364. package/src/core/events/legacy-storage/compression.ts +130 -0
  365. package/src/core/events/legacy-storage/index.ts +1 -0
  366. package/src/core/events/v3/archive-retention.ts +251 -0
  367. package/src/core/events/v3/bootstrap.ts +10 -0
  368. package/src/core/events/v3/capabilities.ts +2 -0
  369. package/src/core/events/v3/coordination-view.ts +100 -11
  370. package/src/core/events/v3/index.ts +9 -0
  371. package/src/core/events/v3/live-routing.ts +1 -0
  372. package/src/core/events/v3/producers/hook-base.ts +14 -2
  373. package/src/core/events/v3/producers/intake.ts +10 -2
  374. package/src/core/events/v3/producers/recorder.ts +420 -17
  375. package/src/core/hooks/adapter/output.ts +12 -1
  376. package/src/core/hooks/cli.ts +332 -247
  377. package/src/core/hooks/health.ts +146 -0
  378. package/src/core/hooks/resolve/transcript.ts +10 -3
  379. package/src/core/hooks/session-name-presence.ts +6 -1
  380. package/src/core/qa-artifacts.ts +126 -0
  381. package/src/core/resources/contract.ts +105 -0
  382. package/src/core/resources/index.ts +5 -0
  383. package/src/core/resources/sampler.ts +590 -0
  384. package/src/core/resources/service-status.ts +62 -0
  385. package/src/core/resources/service.ts +337 -0
  386. package/src/core/resources/storage.ts +44 -0
  387. package/src/core/storage/atomic-json.ts +15 -0
  388. package/src/core/storage/builtins.ts +62 -6
  389. package/src/core/storage/logger.ts +2 -0
  390. package/src/core/storage/query.ts +58 -0
  391. package/src/core/supervisor/activity.ts +193 -0
  392. package/src/core/supervisor/contract.ts +312 -0
  393. package/src/core/supervisor/explanations.ts +104 -0
  394. package/src/core/supervisor/findings.ts +788 -0
  395. package/src/core/supervisor/history.ts +61 -0
  396. package/src/core/supervisor/hook-health-alerts.ts +108 -0
  397. package/src/core/supervisor/hook-health-storage.ts +25 -0
  398. package/src/core/supervisor/hook-health.ts +301 -0
  399. package/src/core/supervisor/hooks.ts +35 -0
  400. package/src/core/supervisor/index.ts +14 -0
  401. package/src/core/supervisor/log-feed.ts +131 -0
  402. package/src/core/supervisor/service.ts +511 -0
  403. package/src/core/supervisor/services.ts +203 -0
  404. package/src/core/supervisor/status.ts +59 -0
  405. package/src/core/supervisor/storage.ts +126 -0
  406. package/src/core/supervisor/timeline.ts +133 -0
  407. package/src/core/workflow/admission.ts +215 -0
  408. package/src/core/workflow/engine.ts +93 -1
  409. package/src/core/workflow/index.ts +10 -0
  410. package/src/core/workflow/proof.ts +54 -1
  411. package/src/core/workflow/run-state.ts +13 -1
  412. package/src/core/workflow/types.ts +39 -1
  413. package/src/lib/admission.ts +347 -0
  414. package/src/lib/agent-browser/client.ts +2 -10
  415. package/src/lib/browser/capture-fidelity.ts +98 -0
  416. package/src/lib/browser/client.ts +212 -10
  417. package/src/lib/browser/critique.ts +62 -7
  418. package/src/lib/browser/index.ts +65 -0
  419. package/src/lib/browser/page-review-judge.ts +360 -0
  420. package/src/lib/browser/page-review-pack.ts +2384 -0
  421. package/src/lib/browser/qa-run-contracts.ts +743 -0
  422. package/src/lib/browser/qa-run.ts +1462 -0
  423. package/src/lib/browser/request-diagnostics.ts +27 -0
  424. package/src/lib/browser/tiling.ts +32 -0
  425. package/src/lib/cookies/client.ts +228 -42
  426. package/src/lib/cookies/extra.ts +28 -0
  427. package/src/lib/cookies/index.ts +2 -0
  428. package/src/lib/coord-root-id.ts +23 -0
  429. package/src/lib/durable-job.ts +407 -0
  430. package/src/lib/http/client.ts +13 -1
  431. package/src/lib/instructions/apply.ts +81 -2
  432. package/src/lib/instructions/templates.ts +11 -2
@@ -8,13 +8,22 @@
8
8
  * expired, inactive, untracked managed unit is deletable.
9
9
  */
10
10
  import { spawnSync } from "node:child_process";
11
- import { randomUUID } from "node:crypto";
12
- import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
11
+ import { createHash, randomUUID } from "node:crypto";
12
+ import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmdirSync, rmSync, writeFileSync, } from "node:fs";
13
13
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
14
14
  import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.js";
15
- import { artifactAutoCleanEnabled, artifactAutoCleanIntervalHours, artifactDefaultRetentionDays, } from "../config.js";
15
+ import { artifactAutoCleanEnabled, artifactAutoCleanIntervalHours, artifactDefaultRetentionDays, artifactMaxBytes, artifactMaxUnitBytes, } from "../config.js";
16
16
  import { ARTIFACT_MANIFEST, ARTIFACT_SCHEMA_VERSION, ARTIFACTS_DIR } from "./constants.js";
17
17
  export { ARTIFACT_MANIFEST, ARTIFACT_SCHEMA_VERSION, ARTIFACTS_DIR } from "./constants.js";
18
+ export function artifactCapabilities() {
19
+ return {
20
+ schema_version: ARTIFACT_SCHEMA_VERSION,
21
+ holds: true,
22
+ atomic_create_holds: true,
23
+ owner_scoped_unhold: true,
24
+ explicit_v1_migration: true,
25
+ };
26
+ }
18
27
  export function artifactsRoot(repoRoot) {
19
28
  return join(resolve(repoRoot), ARTIFACTS_DIR);
20
29
  }
@@ -23,6 +32,9 @@ export function configuredArtifactRetentionDays(repoRoot) {
23
32
  return artifactDefaultRetentionDays(repoRoot);
24
33
  }
25
34
  export function createArtifact(repoRoot, input) {
35
+ return withArtifactLock(repoRoot, () => createArtifactUnlocked(repoRoot, input));
36
+ }
37
+ function createArtifactUnlocked(repoRoot, input) {
26
38
  const now = input.now ?? new Date();
27
39
  assertValidDate(now, "now");
28
40
  const slug = normalizeSlug(input.slug);
@@ -31,11 +43,17 @@ export function createArtifact(repoRoot, input) {
31
43
  const purpose = input.purpose.trim();
32
44
  if (!purpose)
33
45
  throw new Error("purpose must not be empty");
34
- const retentionDays = positiveDays(input.retentionDays);
46
+ const expiresAt = input.retentionMinutes !== undefined
47
+ ? addMinutes(now, positiveMinutes(input.retentionMinutes))
48
+ : addDays(now, positiveDays(input.retentionDays));
35
49
  const artifactId = input.id ?? randomUUID();
36
50
  if (!isSafeId(artifactId)) {
37
51
  throw new Error("artifact id must use ASCII letters, digits, hyphens, or underscores");
38
52
  }
53
+ const holds = (input.holds ?? []).map((hold) => makeHold(hold, input.actor, now));
54
+ if (new Set(holds.map((hold) => hold.id)).size !== holds.length) {
55
+ throw new Error("duplicate hold id");
56
+ }
39
57
  const root = artifactsRoot(repoRoot);
40
58
  mkdirSync(root, { recursive: true });
41
59
  const date = now.toISOString().slice(0, 10);
@@ -43,14 +61,16 @@ export function createArtifact(repoRoot, input) {
43
61
  mkdirSync(path);
44
62
  const manifest = {
45
63
  schema_version: ARTIFACT_SCHEMA_VERSION,
64
+ holds,
46
65
  artifact_id: artifactId,
47
66
  slug,
48
67
  purpose,
49
68
  created_at: now.toISOString(),
50
69
  created_by: input.actor,
51
70
  retention: {
52
- expires_at: addDays(now, retentionDays).toISOString(),
71
+ expires_at: expiresAt.toISOString(),
53
72
  },
73
+ ...(input.big ? { oversize_acknowledged: true } : {}),
54
74
  };
55
75
  atomicWriteManifest(path, manifest);
56
76
  return { path, manifest };
@@ -75,17 +95,22 @@ export function inventoryArtifacts(repoRoot, opts = {}) {
75
95
  for (const name of names) {
76
96
  rows.push(classifyArtifactPath(repoRoot, join(root, name), now, freshnessSeconds));
77
97
  }
78
- return rows;
98
+ return applyArtifactBudgets(repoRoot, rows);
79
99
  }
80
100
  export function showArtifact(repoRoot, ref, opts = {}) {
81
101
  const path = resolveArtifactRef(repoRoot, ref);
82
- const entry = classifyArtifactPath(repoRoot, path, opts.now ?? new Date(), opts.freshnessSeconds ?? 600);
102
+ const entry = inventoryArtifacts(repoRoot, opts).find((row) => row.path === path);
103
+ if (!entry)
104
+ throw new Error(`artifact "${ref}" was not found`);
83
105
  const parsed = readManifest(path);
84
106
  if (!parsed.ok)
85
107
  throw new Error(parsed.reason);
86
108
  return { entry, manifest: parsed.manifest };
87
109
  }
88
110
  export function renewArtifact(repoRoot, ref, days, reason, input = {}) {
111
+ return withArtifactLock(repoRoot, () => renewArtifactUnlocked(repoRoot, ref, days, reason, input));
112
+ }
113
+ function renewArtifactUnlocked(repoRoot, ref, days, reason, input) {
89
114
  const now = input.now ?? new Date();
90
115
  assertValidDate(now, "now");
91
116
  const retentionDays = positiveDays(days);
@@ -108,6 +133,9 @@ export function renewArtifact(repoRoot, ref, days, reason, input = {}) {
108
133
  return manifest;
109
134
  }
110
135
  export function releaseArtifact(repoRoot, ref, input = {}) {
136
+ return withArtifactLock(repoRoot, () => releaseArtifactUnlocked(repoRoot, ref, input));
137
+ }
138
+ function releaseArtifactUnlocked(repoRoot, ref, input) {
111
139
  const now = input.now ?? new Date();
112
140
  assertValidDate(now, "now");
113
141
  const path = resolveArtifactRef(repoRoot, ref);
@@ -122,20 +150,187 @@ export function releaseArtifact(repoRoot, ref, input = {}) {
122
150
  atomicWriteManifest(path, manifest);
123
151
  return manifest;
124
152
  }
153
+ export function holdArtifact(repoRoot, ref, input) {
154
+ const hold = makeHold(input, input.actor, input.now ?? new Date());
155
+ return withArtifactLock(repoRoot, () => {
156
+ const path = resolveArtifactRef(repoRoot, ref);
157
+ const parsed = readManifest(path);
158
+ if (!parsed.ok)
159
+ throw new Error(parsed.reason);
160
+ const previous = parsed.manifest.holds.find((item) => item.id === hold.id);
161
+ if (previous) {
162
+ if (previous.set_by.instance_id !== input.actor.instance_id ||
163
+ previous.reason !== hold.reason) {
164
+ throw new Error("hold id already exists with a different owner or reason");
165
+ }
166
+ return parsed.manifest;
167
+ }
168
+ const manifest = { ...parsed.manifest, holds: [...parsed.manifest.holds, hold] };
169
+ atomicWriteManifest(path, manifest);
170
+ return manifest;
171
+ });
172
+ }
173
+ export function unholdArtifact(repoRoot, ref, id, input) {
174
+ if (!validHoldId(id))
175
+ throw new Error("invalid hold id");
176
+ if (!validActor(input.actor))
177
+ throw new Error("a valid hold actor is required");
178
+ return withArtifactLock(repoRoot, () => {
179
+ const path = resolveArtifactRef(repoRoot, ref);
180
+ const parsed = readManifest(path);
181
+ if (!parsed.ok)
182
+ throw new Error(parsed.reason);
183
+ const hold = parsed.manifest.holds.find((item) => item.id === id);
184
+ if (!hold)
185
+ return parsed.manifest;
186
+ if (hold.set_by.instance_id !== input.actor.instance_id) {
187
+ throw new Error("only the hold owner may remove this hold");
188
+ }
189
+ const manifest = {
190
+ ...parsed.manifest,
191
+ holds: parsed.manifest.holds.filter((item) => item.id !== id),
192
+ };
193
+ atomicWriteManifest(path, manifest);
194
+ return manifest;
195
+ });
196
+ }
197
+ /** Adopt untracked loose files and legacy directories without changing directory paths. */
198
+ export function adoptUnmanagedArtifactFiles(repoRoot, input) {
199
+ if (input.yes)
200
+ return withArtifactLock(repoRoot, () => adoptUnmanagedArtifactFilesUnlocked(repoRoot, input));
201
+ return adoptUnmanagedArtifactFilesUnlocked(repoRoot, input);
202
+ }
203
+ function adoptUnmanagedArtifactFilesUnlocked(repoRoot, input) {
204
+ const now = input.now ?? new Date();
205
+ const candidates = [];
206
+ for (const row of inventoryArtifacts(repoRoot, { now })) {
207
+ if (row.classification !== "unmanaged")
208
+ continue;
209
+ try {
210
+ const stat = lstatSync(row.path);
211
+ if (stat.isSymbolicLink() || containsTrackedPath(repoRoot, row.path))
212
+ continue;
213
+ if (stat.isFile()) {
214
+ candidates.push({ path: row.path, name: row.name, bytes: stat.size, kind: "file" });
215
+ continue;
216
+ }
217
+ if (stat.isDirectory() && !existsSync(join(row.path, ARTIFACT_MANIFEST))) {
218
+ const bytes = safeTreeSize(row.path);
219
+ if (bytes !== null && normalizeSlug(row.name)) {
220
+ candidates.push({ path: row.path, name: row.name, bytes, kind: "directory" });
221
+ }
222
+ }
223
+ }
224
+ catch {
225
+ // A racing or unreadable entry stays unmanaged.
226
+ }
227
+ }
228
+ const candidateBytes = candidates.reduce((sum, row) => sum + row.bytes, 0);
229
+ const fileBytes = candidates.reduce((sum, row) => sum + (row.kind === "file" ? row.bytes : 0), 0);
230
+ const maxUnitBytes = artifactMaxUnitBytes(repoRoot);
231
+ const requiresBig = fileBytes > maxUnitBytes ||
232
+ candidates.some((row) => row.kind === "directory" && row.bytes > maxUnitBytes);
233
+ const preview = {
234
+ candidates,
235
+ candidate_bytes: candidateBytes,
236
+ requires_big: requiresBig,
237
+ adopted_artifact_id: null,
238
+ adopted_path: null,
239
+ adopted_directories: 0,
240
+ };
241
+ if (!input.yes || candidates.length === 0)
242
+ return preview;
243
+ if (requiresBig && !input.big) {
244
+ throw new Error("unmanaged adoption exceeds the per-bundle ceiling; repeat with --big");
245
+ }
246
+ // Revalidate every exact source before creating a destination. A changed,
247
+ // tracked, linked, or non-regular entry aborts the whole adoption.
248
+ for (const candidate of candidates) {
249
+ const stat = lstatSync(candidate.path);
250
+ const bytes = stat.isDirectory() ? safeTreeSize(candidate.path) : stat.size;
251
+ if (stat.isSymbolicLink() ||
252
+ bytes !== candidate.bytes ||
253
+ containsTrackedPath(repoRoot, candidate.path)) {
254
+ throw new Error(`unmanaged entry changed before adoption: ${candidate.name}`);
255
+ }
256
+ if (candidate.kind === "file" ? !stat.isFile() : !stat.isDirectory()) {
257
+ throw new Error(`unmanaged entry changed before adoption: ${candidate.name}`);
258
+ }
259
+ }
260
+ const files = candidates.filter((candidate) => candidate.kind === "file");
261
+ const created = files.length
262
+ ? createArtifactUnlocked(repoRoot, {
263
+ slug: "adopted-unmanaged",
264
+ purpose: input.purpose,
265
+ retentionDays: input.retentionDays,
266
+ actor: input.actor,
267
+ now,
268
+ big: input.big,
269
+ })
270
+ : null;
271
+ for (const candidate of files)
272
+ renameSync(candidate.path, join(created.path, candidate.name));
273
+ const retentionDays = positiveDays(input.retentionDays);
274
+ const directories = candidates.filter((candidate) => candidate.kind === "directory");
275
+ for (const candidate of directories) {
276
+ atomicWriteManifest(candidate.path, {
277
+ schema_version: ARTIFACT_SCHEMA_VERSION,
278
+ holds: [],
279
+ artifact_id: randomUUID(),
280
+ slug: normalizeSlug(candidate.name),
281
+ purpose: `${input.purpose}: ${candidate.name}`,
282
+ created_at: now.toISOString(),
283
+ created_by: input.actor,
284
+ retention: { expires_at: addDays(now, retentionDays).toISOString() },
285
+ ...(input.big ? { oversize_acknowledged: true } : {}),
286
+ });
287
+ }
288
+ return {
289
+ ...preview,
290
+ adopted_artifact_id: created?.manifest.artifact_id ?? null,
291
+ adopted_path: created?.path ?? null,
292
+ adopted_directories: directories.length,
293
+ };
294
+ }
125
295
  export function cleanArtifacts(repoRoot, opts = {}) {
296
+ if (!opts.yes)
297
+ return inventoryArtifacts(repoRoot, opts);
298
+ try {
299
+ return withArtifactLock(repoRoot, () => cleanArtifactsUnlocked(repoRoot, opts));
300
+ }
301
+ catch (error) {
302
+ return inventoryArtifacts(repoRoot, opts).map((row) => row.action === "would-delete"
303
+ ? {
304
+ ...row,
305
+ classification: "unknown",
306
+ action: "keep",
307
+ reason: errorMessage("cleanup refused", error),
308
+ }
309
+ : row);
310
+ }
311
+ }
312
+ function cleanArtifactsUnlocked(repoRoot, opts) {
126
313
  const now = opts.now ?? new Date();
127
314
  const freshnessSeconds = opts.freshnessSeconds ?? 600;
128
315
  const rows = inventoryArtifacts(repoRoot, { now, freshnessSeconds });
129
316
  if (!opts.yes)
130
317
  return rows;
131
318
  return rows.map((entry) => {
132
- if (entry.classification !== "managed-expired")
319
+ if (entry.action !== "would-delete")
133
320
  return entry;
134
321
  // Reclassify immediately before removal. A renewal, release-state change,
135
322
  // heartbeat, symlink swap, or tracked file added since inventory must win.
136
- const current = classifyArtifactPath(repoRoot, entry.path, now, freshnessSeconds);
137
- if (current.classification !== "managed-expired")
323
+ const current = inventoryArtifacts(repoRoot, { now, freshnessSeconds }).find((row) => row.path === entry.path);
324
+ if (!current) {
325
+ return { ...entry, classification: "unknown", reason: "entry disappeared", action: "keep" };
326
+ }
327
+ if (current.action !== "would-delete" ||
328
+ current.artifact_id !== entry.artifact_id ||
329
+ current.bytes !== entry.bytes ||
330
+ current.last_modified_at !== entry.last_modified_at ||
331
+ current.expires_at !== entry.expires_at) {
138
332
  return current;
333
+ }
139
334
  try {
140
335
  const top = lstatSync(current.path);
141
336
  if (!top.isDirectory() || top.isSymbolicLink()) {
@@ -264,7 +459,16 @@ function classifyArtifactPath(repoRoot, path, now, freshnessSeconds) {
264
459
  last_modified_at: new Date(effectiveLastModifiedMs).toISOString(),
265
460
  expires_at: effectiveExpiresAt,
266
461
  owner_instance_id: manifest.created_by?.instance_id ?? null,
462
+ oversize_acknowledged: manifest.oversize_acknowledged === true,
267
463
  });
464
+ if (manifest.holds.length > 0) {
465
+ return {
466
+ ...base,
467
+ classification: "managed-held",
468
+ reason: `held: ${manifest.holds.map((hold) => hold.id).join(", ")}`,
469
+ action: "keep",
470
+ };
471
+ }
268
472
  if (base.bytes === null || lastModifiedMs === null) {
269
473
  return {
270
474
  ...base,
@@ -309,6 +513,38 @@ function classifyArtifactPath(repoRoot, path, now, freshnessSeconds) {
309
513
  action: "would-delete",
310
514
  };
311
515
  }
516
+ function applyArtifactBudgets(repoRoot, inputRows) {
517
+ const maxUnitBytes = artifactMaxUnitBytes(repoRoot);
518
+ const maxBytes = artifactMaxBytes(repoRoot);
519
+ const rows = inputRows.map((row) => ({ ...row }));
520
+ for (const row of rows) {
521
+ if (row.classification === "managed-current" &&
522
+ row.bytes !== null &&
523
+ row.bytes > maxUnitBytes &&
524
+ !row.oversize_acknowledged) {
525
+ row.classification = "managed-oversize";
526
+ row.reason = `bundle uses ${row.bytes} bytes, above the ${maxUnitBytes}-byte ceiling without --big`;
527
+ row.action = "would-delete";
528
+ }
529
+ }
530
+ const managedBytes = rows.reduce((sum, row) => sum + (row.artifact_id && row.bytes !== null ? row.bytes : 0), 0);
531
+ let retainedBytes = managedBytes -
532
+ rows.reduce((sum, row) => sum + (row.action === "would-delete" && row.bytes !== null ? row.bytes : 0), 0);
533
+ if (retainedBytes <= maxBytes)
534
+ return rows;
535
+ const candidates = rows
536
+ .filter((row) => row.classification === "managed-current" && row.action === "keep" && row.bytes !== null)
537
+ .sort((left, right) => `${left.expires_at ?? ""}\0${left.created_at ?? ""}\0${left.name}`.localeCompare(`${right.expires_at ?? ""}\0${right.created_at ?? ""}\0${right.name}`));
538
+ for (const row of candidates) {
539
+ if (retainedBytes <= maxBytes)
540
+ break;
541
+ row.classification = "managed-over-budget";
542
+ row.reason = `repository artifact budget is ${maxBytes} bytes; earliest-expiring inactive bundles are removed first`;
543
+ row.action = "would-delete";
544
+ retainedBytes -= row.bytes ?? 0;
545
+ }
546
+ return rows;
547
+ }
312
548
  function readManifest(path) {
313
549
  const manifestPath = join(path, ARTIFACT_MANIFEST);
314
550
  if (!existsSync(manifestPath)) {
@@ -316,11 +552,24 @@ function readManifest(path) {
316
552
  }
317
553
  let value;
318
554
  try {
555
+ const unit = lstatSync(path);
556
+ const stat = lstatSync(manifestPath);
557
+ if (!unit.isDirectory() ||
558
+ unit.isSymbolicLink() ||
559
+ !stat.isFile() ||
560
+ stat.isSymbolicLink() ||
561
+ stat.size > 1024 * 1024) {
562
+ return { ok: false, reason: "manifest must be a bounded regular file in a direct directory" };
563
+ }
319
564
  value = JSON.parse(readFileSync(manifestPath, "utf8"));
320
565
  }
321
566
  catch (error) {
322
567
  return { ok: false, reason: errorMessage("manifest is unreadable", error) };
323
568
  }
569
+ return parseArtifactManifest(value);
570
+ }
571
+ /** Validate only the current schema. Legacy conversion belongs to migrateArtifacts. */
572
+ export function parseArtifactManifest(value) {
324
573
  if (!value || typeof value !== "object" || Array.isArray(value)) {
325
574
  return { ok: false, reason: "manifest must be a JSON object" };
326
575
  }
@@ -328,6 +577,11 @@ function readManifest(path) {
328
577
  if (m.schema_version !== ARTIFACT_SCHEMA_VERSION) {
329
578
  return { ok: false, reason: `unsupported schema_version ${String(m.schema_version)}` };
330
579
  }
580
+ if (!Array.isArray(m.holds) ||
581
+ m.holds.some((hold) => !validHold(hold)) ||
582
+ new Set(m.holds.map((hold) => hold.id)).size !== m.holds.length) {
583
+ return { ok: false, reason: "invalid holds" };
584
+ }
331
585
  if (!isSafeId(m.artifact_id))
332
586
  return { ok: false, reason: "invalid artifact_id" };
333
587
  if (typeof m.slug !== "string" || !m.slug || normalizeSlug(m.slug) !== m.slug) {
@@ -357,16 +611,147 @@ function readManifest(path) {
357
611
  if (m.released_by !== undefined && !validActor(m.released_by)) {
358
612
  return { ok: false, reason: "invalid released_by" };
359
613
  }
614
+ if (m.oversize_acknowledged !== undefined && typeof m.oversize_acknowledged !== "boolean") {
615
+ return { ok: false, reason: "invalid oversize_acknowledged" };
616
+ }
360
617
  return { ok: true, manifest: m };
361
618
  }
362
619
  function atomicWriteManifest(path, manifest) {
363
620
  const target = join(path, ARTIFACT_MANIFEST);
364
621
  const tmp = `${target}.tmp.${process.pid}.${randomUUID().slice(0, 8)}`;
365
- writeFileSync(tmp, `${JSON.stringify(manifest, null, 2)}\n`, {
366
- encoding: "utf8",
367
- mode: 0o600,
368
- });
369
- renameSync(tmp, target);
622
+ try {
623
+ writeFileSync(tmp, `${JSON.stringify(manifest, null, 2)}\n`, {
624
+ encoding: "utf8",
625
+ mode: 0o600,
626
+ flag: "wx",
627
+ });
628
+ renameSync(tmp, target);
629
+ }
630
+ finally {
631
+ rmSync(tmp, { force: true });
632
+ }
633
+ }
634
+ /** Explicit, bounded v1 cutover. Preview never writes; every applied unit keeps its exact preimage. */
635
+ export function migrateArtifacts(repoRoot, opts = {}) {
636
+ const migrate = () => {
637
+ const root = artifactsRoot(repoRoot);
638
+ if (!existsSync(root))
639
+ return [];
640
+ return readdirSync(root)
641
+ .sort()
642
+ .map((name) => {
643
+ const path = join(root, name);
644
+ try {
645
+ const stat = lstatSync(path);
646
+ if (stat.isSymbolicLink() || !stat.isDirectory())
647
+ throw new Error("not a direct directory");
648
+ if (containsTrackedPath(repoRoot, path))
649
+ throw new Error("artifact contains tracked files");
650
+ const target = join(path, ARTIFACT_MANIFEST);
651
+ const manifestStat = lstatSync(target);
652
+ if (!manifestStat.isFile() ||
653
+ manifestStat.isSymbolicLink() ||
654
+ manifestStat.size > 1024 * 1024) {
655
+ throw new Error("manifest is not a bounded regular file");
656
+ }
657
+ const preimage = readFileSync(target, "utf8");
658
+ const legacy = JSON.parse(preimage);
659
+ if (legacy?.schema_version !== 1) {
660
+ return {
661
+ path,
662
+ action: "keep",
663
+ reason: `schema_version ${String(legacy?.schema_version)} is not a migration source`,
664
+ };
665
+ }
666
+ if (Object.hasOwn(legacy, "holds"))
667
+ throw new Error("v1 manifest unexpectedly contains holds");
668
+ const parsed = parseArtifactManifest({
669
+ ...legacy,
670
+ schema_version: ARTIFACT_SCHEMA_VERSION,
671
+ holds: [],
672
+ });
673
+ if (!parsed.ok)
674
+ throw new Error(parsed.reason);
675
+ const digest = createHash("sha256").update(preimage).digest("hex");
676
+ const preimagePath = join(resolve(repoRoot), ".harnery/artifact-migrations", `${digest}.v1.json`);
677
+ if (!opts.yes)
678
+ return {
679
+ path,
680
+ action: "would-migrate",
681
+ reason: "valid v1 manifest",
682
+ preimage_path: preimagePath,
683
+ };
684
+ mkdirSync(dirname(preimagePath), { recursive: true });
685
+ try {
686
+ writeFileSync(preimagePath, preimage, { flag: "wx", mode: 0o600 });
687
+ }
688
+ catch (error) {
689
+ if (error.code !== "EEXIST" ||
690
+ lstatSync(preimagePath).isSymbolicLink() ||
691
+ readFileSync(preimagePath, "utf8") !== preimage)
692
+ throw error;
693
+ }
694
+ if (readFileSync(target, "utf8") !== preimage)
695
+ throw new Error("manifest changed before migration");
696
+ atomicWriteManifest(path, parsed.manifest);
697
+ return {
698
+ path,
699
+ action: "migrated",
700
+ reason: "v1 preimage preserved; identity and retention unchanged",
701
+ preimage_path: preimagePath,
702
+ };
703
+ }
704
+ catch (error) {
705
+ return { path, action: "keep", reason: errorMessage("migration refused", error) };
706
+ }
707
+ });
708
+ };
709
+ return opts.yes ? withArtifactLock(repoRoot, migrate) : migrate();
710
+ }
711
+ /** A persistent directory lock fails closed on contention or a crashed owner. */
712
+ function withArtifactLock(repoRoot, action) {
713
+ const lock = join(resolve(repoRoot), ".harnery/artifacts-mutation.lock");
714
+ mkdirSync(dirname(lock), { recursive: true });
715
+ try {
716
+ mkdirSync(lock);
717
+ }
718
+ catch (error) {
719
+ throw new Error(errorMessage("artifact store mutation lock unavailable; retry after its owner finishes", error));
720
+ }
721
+ try {
722
+ return action();
723
+ }
724
+ finally {
725
+ rmdirSync(lock);
726
+ }
727
+ }
728
+ function validHoldId(value) {
729
+ return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/.test(value);
730
+ }
731
+ function validHold(value) {
732
+ if (!value || typeof value !== "object" || Array.isArray(value))
733
+ return false;
734
+ const hold = value;
735
+ return (validHoldId(hold.id) &&
736
+ typeof hold.reason === "string" &&
737
+ !!hold.reason.trim() &&
738
+ validActor(hold.set_by) &&
739
+ validIso(hold.set_at));
740
+ }
741
+ function makeHold(input, actor, now) {
742
+ assertValidDate(now, "now");
743
+ if (!validActor(actor))
744
+ throw new Error("a valid hold actor is required");
745
+ if (!validHoldId(input.id))
746
+ throw new Error("invalid hold id");
747
+ if (typeof input.reason !== "string" || !input.reason.trim())
748
+ throw new Error("hold reason must not be empty");
749
+ return {
750
+ id: input.id,
751
+ reason: input.reason.trim(),
752
+ set_by: { ...actor },
753
+ set_at: now.toISOString(),
754
+ };
370
755
  }
371
756
  function ownerLiveness(repoRoot, instanceId, now, freshnessSeconds) {
372
757
  try {
@@ -460,6 +845,7 @@ function rowFor(path, name, repoRoot, classification, reason, bytes = safeTreeSi
460
845
  last_modified_at: null,
461
846
  expires_at: null,
462
847
  owner_instance_id: null,
848
+ oversize_acknowledged: false,
463
849
  };
464
850
  }
465
851
  function normalizeSlug(value) {
@@ -481,6 +867,15 @@ function positiveDays(value) {
481
867
  function addDays(date, days) {
482
868
  return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
483
869
  }
870
+ function positiveMinutes(value) {
871
+ if (!Number.isInteger(value) || value <= 0 || value > 3650 * 24 * 60) {
872
+ throw new Error("retention minutes must be between 1 and 5256000");
873
+ }
874
+ return value;
875
+ }
876
+ function addMinutes(date, minutes) {
877
+ return new Date(date.getTime() + minutes * 60 * 1000);
878
+ }
484
879
  function isSafeId(value) {
485
880
  return (typeof value === "string" &&
486
881
  value.length >= 8 &&
@@ -185,6 +185,14 @@ export declare function coordFreshnessSeconds(coordRoot?: string | null): number
185
185
  * `0` (or a negative value) disables automatic rotation.
186
186
  */
187
187
  export declare function eventLedgerRotateActiveBytes(coordRoot?: string | null): number;
188
+ export interface EventLedgerArchivePolicy {
189
+ maxBytes: number;
190
+ maxAgeDays: number;
191
+ keepMin: number;
192
+ autoClean: boolean;
193
+ }
194
+ /** Bounded retention for closed V3 epochs under `ledgers/v3-archives`. */
195
+ export declare function eventLedgerArchivePolicy(coordRoot?: string | null): EventLedgerArchivePolicy;
188
196
  /**
189
197
  * Resolve the standalone dashboard port.
190
198
  *
@@ -200,6 +208,10 @@ export declare function sessionFinalizationConfig(coordRoot?: string | null): Se
200
208
  * `artifacts.default_retention_days` -> 3 days.
201
209
  */
202
210
  export declare function artifactDefaultRetentionDays(coordRoot?: string | null): number;
211
+ /** Soft repository budget for managed working artifacts. */
212
+ export declare function artifactMaxBytes(coordRoot?: string | null): number;
213
+ /** Size at which one bundle requires an explicit `artifacts create --big` acknowledgement. */
214
+ export declare function artifactMaxUnitBytes(coordRoot?: string | null): number;
203
215
  /**
204
216
  * Whether the daily SessionStart sweep of expired artifact workspaces runs.
205
217
  * Precedence: `HARNERY_ARTIFACT_AUTO_CLEAN` (0/false disables) ->
@@ -208,6 +220,14 @@ export declare function artifactDefaultRetentionDays(coordRoot?: string | null):
208
220
  * `artifacts clean --yes`.
209
221
  */
210
222
  export declare function artifactAutoCleanEnabled(coordRoot?: string | null): boolean;
223
+ /**
224
+ * Whether `qa-run` and `review-pack create` sweep expired page review packs
225
+ * out of the artifact store before starting. Precedence:
226
+ * `HARNERY_REVIEW_PACK_AUTO_CLEAN` (1/true enables, 0/false disables) ->
227
+ * `review_pack.auto_clean` -> disabled. The sweep deletes only packs whose
228
+ * manifest says `managed: true` with `retention.expires_at` in the past.
229
+ */
230
+ export declare function reviewPackAutoCleanEnabled(coordRoot?: string | null): boolean;
211
231
  /**
212
232
  * Sweep cadence in hours. Env-only (`HARNERY_ARTIFACT_AUTO_CLEAN_INTERVAL_HOURS`,
213
233
  * mainly for tests): the cadence is an implementation detail, not policy, and
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}