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
@@ -0,0 +1,215 @@
1
+ import { buildDiagnosticAdvice } from "../diagnostics/advice.ts";
2
+ import type { DiagnosticAdvice } from "../diagnostics/contract.ts";
3
+ import {
4
+ type EnsureSupervisorResult,
5
+ ensureSupervisorRunning,
6
+ readSupervisorFindings,
7
+ readSupervisorStatus,
8
+ registerSupervisorConsumer,
9
+ type SupervisorCapability,
10
+ type SupervisorFinding,
11
+ type SupervisorFindings,
12
+ type SupervisorStatus,
13
+ unregisterSupervisorConsumer,
14
+ } from "../supervisor/index.ts";
15
+ import type { WorkflowDiagnosticAdmissionObservation } from "./types.ts";
16
+
17
+ const DEFAULT_FRESH_CYCLE_WAIT_MS = 4_000;
18
+ const POLL_INTERVAL_MS = 50;
19
+
20
+ export interface WorkflowDiagnosticAdmissionRuntime {
21
+ now: () => Date;
22
+ wait: (milliseconds: number) => Promise<void>;
23
+ registerConsumer: (coordRoot: string, input: { id: string; pid?: number }) => unknown;
24
+ unregisterConsumer: (coordRoot: string, id: string) => void;
25
+ ensureSupervisor: (coordRoot: string) => Promise<EnsureSupervisorResult>;
26
+ readStatus: (coordRoot: string, nowMs?: number) => SupervisorStatus;
27
+ readFindings: (coordRoot: string) => SupervisorFindings | undefined;
28
+ }
29
+
30
+ export interface ObserveWorkflowDiagnosticAdmissionInput {
31
+ coordRoot: string;
32
+ runId: string;
33
+ freshCycleWaitMs?: number;
34
+ runtime?: Partial<WorkflowDiagnosticAdmissionRuntime>;
35
+ }
36
+
37
+ export async function observeWorkflowDiagnosticAdmission(
38
+ input: ObserveWorkflowDiagnosticAdmissionInput,
39
+ ): Promise<WorkflowDiagnosticAdmissionObservation> {
40
+ const runtime = admissionRuntime(input.runtime);
41
+ const requested = runtime.now();
42
+ const requestedAt = requested.toISOString();
43
+ const startedMs = requested.getTime();
44
+ const consumerId = `workflow-${input.runId}`;
45
+ let serviceState: WorkflowDiagnosticAdmissionObservation["service_state"] = "unavailable";
46
+
47
+ try {
48
+ runtime.registerConsumer(input.coordRoot, { id: consumerId });
49
+ const ensured = await runtime.ensureSupervisor(input.coordRoot);
50
+ serviceState = ensured.state;
51
+ if (ensured.state === "unavailable") {
52
+ return unavailableObservation(
53
+ runtime,
54
+ requestedAt,
55
+ startedMs,
56
+ serviceState,
57
+ "error",
58
+ "supervisor_unavailable",
59
+ ensured.error,
60
+ );
61
+ }
62
+
63
+ const deadlineMs = runtime.now().getTime() + normalizeWait(input.freshCycleWaitMs);
64
+ while (runtime.now().getTime() <= deadlineMs) {
65
+ const status = runtime.readStatus(input.coordRoot, runtime.now().getTime());
66
+ const sampledAt = status.record?.last_cycle_at;
67
+ if (status.running && sampledAt && Date.parse(sampledAt) >= requested.getTime()) {
68
+ const report = runtime.readFindings(input.coordRoot);
69
+ if (!report) {
70
+ return unavailableObservation(
71
+ runtime,
72
+ requestedAt,
73
+ startedMs,
74
+ serviceState,
75
+ "unsupported",
76
+ "source_missing",
77
+ );
78
+ }
79
+ const observedAt = runtime.now().toISOString();
80
+ return {
81
+ requested_at: requestedAt,
82
+ observed_at: observedAt,
83
+ wait_ms: elapsedMs(runtime, startedMs),
84
+ service_state: serviceState,
85
+ freshness: "fresh",
86
+ sampled_at: sampledAt,
87
+ advice: buildDiagnosticAdvice({
88
+ findings: mergeFindings(report),
89
+ sourceCapability: supportedCapability(),
90
+ evaluatedAt: observedAt,
91
+ }),
92
+ };
93
+ }
94
+ const remainingMs = deadlineMs - runtime.now().getTime();
95
+ if (remainingMs <= 0) break;
96
+ await runtime.wait(Math.min(POLL_INTERVAL_MS, remainingMs));
97
+ }
98
+ return unavailableObservation(
99
+ runtime,
100
+ requestedAt,
101
+ startedMs,
102
+ serviceState,
103
+ "expired",
104
+ "fresh_cycle_timeout",
105
+ );
106
+ } catch (error) {
107
+ return unavailableObservation(
108
+ runtime,
109
+ requestedAt,
110
+ startedMs,
111
+ serviceState,
112
+ "error",
113
+ "observation_failed",
114
+ error instanceof Error ? error.message : String(error),
115
+ );
116
+ } finally {
117
+ try {
118
+ runtime.unregisterConsumer(input.coordRoot, consumerId);
119
+ } catch {
120
+ // Admission is observer-only. Cleanup failure cannot affect dispatch.
121
+ }
122
+ }
123
+ }
124
+
125
+ export function failedWorkflowDiagnosticAdmissionObservation(
126
+ error: unknown,
127
+ requestedAt: Date,
128
+ observedAt = new Date(),
129
+ ): WorkflowDiagnosticAdmissionObservation {
130
+ const capability: SupervisorCapability = {
131
+ source_kind: "supervisor.findings",
132
+ state: "error",
133
+ reason_code: "observation_failed",
134
+ detail: (error instanceof Error ? error.message : String(error)).slice(0, 500),
135
+ };
136
+ return {
137
+ requested_at: requestedAt.toISOString(),
138
+ observed_at: observedAt.toISOString(),
139
+ wait_ms: Math.max(0, observedAt.getTime() - requestedAt.getTime()),
140
+ service_state: "unavailable",
141
+ freshness: "unavailable",
142
+ advice: buildDiagnosticAdvice({
143
+ findings: [],
144
+ sourceCapability: capability,
145
+ evaluatedAt: observedAt.toISOString(),
146
+ }),
147
+ };
148
+ }
149
+
150
+ function unavailableObservation(
151
+ runtime: WorkflowDiagnosticAdmissionRuntime,
152
+ requestedAt: string,
153
+ startedMs: number,
154
+ serviceState: WorkflowDiagnosticAdmissionObservation["service_state"],
155
+ state: Exclude<SupervisorCapability["state"], "supported">,
156
+ reasonCode: string,
157
+ detail?: string,
158
+ ): WorkflowDiagnosticAdmissionObservation {
159
+ const observedAt = runtime.now().toISOString();
160
+ const capability: SupervisorCapability = {
161
+ source_kind: "supervisor.findings",
162
+ state,
163
+ reason_code: reasonCode,
164
+ ...(detail ? { detail: detail.slice(0, 500) } : {}),
165
+ };
166
+ const advice: DiagnosticAdvice = buildDiagnosticAdvice({
167
+ findings: [],
168
+ sourceCapability: capability,
169
+ evaluatedAt: observedAt,
170
+ });
171
+ return {
172
+ requested_at: requestedAt,
173
+ observed_at: observedAt,
174
+ wait_ms: elapsedMs(runtime, startedMs),
175
+ service_state: serviceState,
176
+ freshness: "unavailable",
177
+ advice,
178
+ };
179
+ }
180
+
181
+ function mergeFindings(report: SupervisorFindings): SupervisorFinding[] {
182
+ const byId = new Map<string, SupervisorFinding>();
183
+ for (const finding of report.transitions) byId.set(finding.id, finding);
184
+ for (const finding of report.active) byId.set(finding.id, finding);
185
+ return [...byId.values()];
186
+ }
187
+
188
+ function supportedCapability(): SupervisorCapability {
189
+ return { source_kind: "supervisor.findings", state: "supported" };
190
+ }
191
+
192
+ function normalizeWait(value: number | undefined): number {
193
+ if (value === undefined) return DEFAULT_FRESH_CYCLE_WAIT_MS;
194
+ if (!Number.isFinite(value) || value < 0) return DEFAULT_FRESH_CYCLE_WAIT_MS;
195
+ return Math.min(Math.floor(value), 30_000);
196
+ }
197
+
198
+ function elapsedMs(runtime: WorkflowDiagnosticAdmissionRuntime, startedMs: number): number {
199
+ return Math.max(0, runtime.now().getTime() - startedMs);
200
+ }
201
+
202
+ function admissionRuntime(
203
+ overrides: Partial<WorkflowDiagnosticAdmissionRuntime> | undefined,
204
+ ): WorkflowDiagnosticAdmissionRuntime {
205
+ return {
206
+ now: () => new Date(),
207
+ wait: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
208
+ registerConsumer: registerSupervisorConsumer,
209
+ unregisterConsumer: unregisterSupervisorConsumer,
210
+ ensureSupervisor: ensureSupervisorRunning,
211
+ readStatus: readSupervisorStatus,
212
+ readFindings: readSupervisorFindings,
213
+ ...overrides,
214
+ };
215
+ }
@@ -35,6 +35,10 @@ import {
35
35
  policyDigest,
36
36
  summarizePolicyRequest,
37
37
  } from "../policy/index.ts";
38
+ import {
39
+ failedWorkflowDiagnosticAdmissionObservation,
40
+ observeWorkflowDiagnosticAdmission,
41
+ } from "./admission.ts";
38
42
  import { assertWorkflowRunId, createWorkflowApproval } from "./approvals.ts";
39
43
  import { freezeWorkflowAttemptContext } from "./attempt-context.ts";
40
44
  import { type BillingProbe, probeBilling } from "./billing.ts";
@@ -52,6 +56,7 @@ import {
52
56
  acquireWorkflowResumeLease,
53
57
  assertWorkflowRunResumable,
54
58
  assertWorkflowScriptUnchanged,
59
+ WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION,
55
60
  workflowScriptDigest,
56
61
  writeWorkflowRunManifest,
57
62
  } from "./run-state.ts";
@@ -71,12 +76,16 @@ import type {
71
76
  WorkflowAgentProof,
72
77
  WorkflowAttemptContext,
73
78
  WorkflowContext,
79
+ WorkflowDiagnosticAdmissionConfig,
80
+ WorkflowDiagnosticAdmissionObservation,
81
+ WorkflowDiagnosticAdmissionProof,
74
82
  WorkflowEvidenceRecord,
75
83
  WorkflowModule,
76
84
  WorkflowProof,
77
85
  WorkflowSandboxProjectionEvidence,
78
86
  WorkflowWorkContext,
79
87
  } from "./types.ts";
88
+ import { WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION } from "./types.ts";
80
89
  import { parseStageOutput, validateAgainstSchema } from "./validate.ts";
81
90
  import { freezeWorkflowWorkContext } from "./work-context.ts";
82
91
  import {
@@ -317,6 +326,11 @@ async function executeWorkflow(
317
326
  const approvalAddressee = frozen?.approval_addressee ?? opts.approvalAddressee ?? "operator";
318
327
  const subscriptionOnly = frozen?.subscription_only ?? Boolean(opts.subscriptionOnly);
319
328
  const allowApiBilling = frozen?.allow_api_billing ?? Boolean(opts.allowApiBilling);
329
+ const diagnosticAdmissionConfig = frozen?.diagnostic_admission
330
+ ? normalizeDiagnosticAdmissionConfig(frozen.diagnostic_admission)
331
+ : resumeState
332
+ ? undefined
333
+ : normalizeDiagnosticAdmissionConfig(opts.diagnosticAdmission);
320
334
  const startedAt = resumeState?.manifest.started_at ?? new Date().toISOString();
321
335
  const t0 = resumeState ? Date.parse(startedAt) : Date.now();
322
336
  const scriptSha256 = resumeState?.manifest.script.sha256 ?? workflowScriptDigest(absScript);
@@ -386,6 +400,7 @@ async function executeWorkflow(
386
400
  after: resumeState.manifest.repository_before,
387
401
  agents: [],
388
402
  evidence: [],
403
+ diagnosticAdmission: initialDiagnosticAdmissionProof(diagnosticAdmissionConfig),
389
404
  adapterEvidence: opts.adapterEvidence,
390
405
  adapterAttestations: opts.adapterAttestations,
391
406
  sandboxProjection: sandboxProjectionEvidence(
@@ -454,7 +469,7 @@ async function executeWorkflow(
454
469
  writeWorkflowRunManifest({
455
470
  coordRoot: opts.coordRoot,
456
471
  manifest: {
457
- schema_version: 1,
472
+ schema_version: WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION,
458
473
  run_id: runId,
459
474
  work_item_id: opts.workItemId,
460
475
  work_context: workContext,
@@ -468,6 +483,7 @@ async function executeWorkflow(
468
483
  default_adapter: defaultAdapter,
469
484
  max_agents: maxAgents,
470
485
  concurrency,
486
+ diagnostic_admission: diagnosticAdmissionConfig,
471
487
  subscription_only: subscriptionOnly,
472
488
  allow_api_billing: allowApiBilling,
473
489
  approval_mode: approvalMode,
@@ -581,6 +597,8 @@ async function executeWorkflow(
581
597
  history?.policyDecisions.map((decision) => [decision.id, decision]),
582
598
  );
583
599
  const acceptanceIds = new Set(meta.acceptance.map((criterion) => criterion.id));
600
+ let diagnosticAdmission = initialDiagnosticAdmissionProof(diagnosticAdmissionConfig);
601
+ let diagnosticAdmissionPromise: Promise<void> | undefined;
584
602
 
585
603
  const transcript = (event: string, data: Record<string, unknown>): void => {
586
604
  appendWorkflowTranscriptEvent(opts.coordRoot, runId, event, { stage: currentStage, ...data });
@@ -601,6 +619,46 @@ async function executeWorkflow(
601
619
  });
602
620
  };
603
621
 
622
+ const ensureDiagnosticAdmissionObserved = async (): Promise<void> => {
623
+ if (!diagnosticAdmissionConfig) return;
624
+ diagnosticAdmissionPromise ??= (async () => {
625
+ const requestedAt = new Date();
626
+ let observation: WorkflowDiagnosticAdmissionObservation;
627
+ try {
628
+ observation = await (
629
+ opts.observeDiagnosticAdmission ??
630
+ ((coordRoot, observationRunId) =>
631
+ observeWorkflowDiagnosticAdmission({
632
+ coordRoot,
633
+ runId: observationRunId,
634
+ }))
635
+ )(opts.coordRoot, runId);
636
+ } catch (error) {
637
+ observation = failedWorkflowDiagnosticAdmissionObservation(error, requestedAt);
638
+ }
639
+ diagnosticAdmission = {
640
+ schema_version: WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION,
641
+ mode: "shadow",
642
+ trigger: "before-first-dispatch",
643
+ state: "observed",
644
+ action: "none",
645
+ observation,
646
+ };
647
+ transcript("diagnostic.admission", {
648
+ schema_version: diagnosticAdmission.schema_version,
649
+ mode: diagnosticAdmission.mode,
650
+ trigger: diagnosticAdmission.trigger,
651
+ action: diagnosticAdmission.action,
652
+ observation,
653
+ });
654
+ log(
655
+ `[admission] shadow pressure=${observation.advice.pressure} ` +
656
+ `recommendation=${observation.advice.fan_out_recommendation}; dispatch unchanged`,
657
+ );
658
+ })();
659
+ await diagnosticAdmissionPromise;
660
+ };
661
+
604
662
  // Bounded concurrency gate shared by every spawn in the run — direct
605
663
  // `agent()` calls and `parallel()` thunks draw from the same slot pool, so
606
664
  // the cap holds even when a script nests parallel() inside loops.
@@ -936,6 +994,7 @@ async function executeWorkflow(
936
994
 
937
995
  await acquire();
938
996
  try {
997
+ await ensureDiagnosticAdmissionObserved();
939
998
  transcript("agent.start", {
940
999
  id,
941
1000
  label,
@@ -1227,6 +1286,7 @@ async function executeWorkflow(
1227
1286
  after: snapshotRepo(executionCwd),
1228
1287
  agents: Array.from(agentProofs.values()),
1229
1288
  evidence: evidenceRecords,
1289
+ diagnosticAdmission,
1230
1290
  adapterEvidence: opts.adapterEvidence,
1231
1291
  adapterAttestations: opts.adapterAttestations,
1232
1292
  sandboxProjection: sandboxProjectionEvidence(filesystemPolicy, gitWrite),
@@ -1270,6 +1330,7 @@ async function executeWorkflow(
1270
1330
  mode: subscriptionOnly ? "subscription" : p.mode,
1271
1331
  })),
1272
1332
  policy: proof.policy?.summary,
1333
+ diagnosticAdmission,
1273
1334
  workspaceBinding,
1274
1335
  };
1275
1336
  return report;
@@ -1308,6 +1369,7 @@ async function executeWorkflow(
1308
1369
  after: snapshotRepo(executionCwd),
1309
1370
  agents: Array.from(agentProofs.values()),
1310
1371
  evidence: evidenceRecords,
1372
+ diagnosticAdmission,
1311
1373
  adapterEvidence: opts.adapterEvidence,
1312
1374
  adapterAttestations: opts.adapterAttestations,
1313
1375
  sandboxProjection: sandboxProjectionEvidence(filesystemPolicy, gitWrite),
@@ -1485,6 +1547,36 @@ function round4(n: number): number {
1485
1547
  return Math.round(n * 10_000) / 10_000;
1486
1548
  }
1487
1549
 
1550
+ function normalizeDiagnosticAdmissionConfig(
1551
+ value: WorkflowDiagnosticAdmissionConfig | undefined,
1552
+ ): WorkflowDiagnosticAdmissionConfig | undefined {
1553
+ if (value === undefined) return undefined;
1554
+ if (
1555
+ value.schema_version !== WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION ||
1556
+ value.mode !== "shadow"
1557
+ ) {
1558
+ throw new Error("diagnosticAdmission must use schema_version 1 and mode shadow");
1559
+ }
1560
+ return {
1561
+ schema_version: WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION,
1562
+ mode: "shadow",
1563
+ };
1564
+ }
1565
+
1566
+ function initialDiagnosticAdmissionProof(
1567
+ config: WorkflowDiagnosticAdmissionConfig | undefined,
1568
+ ): WorkflowDiagnosticAdmissionProof | undefined {
1569
+ if (!config) return undefined;
1570
+ return {
1571
+ schema_version: WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION,
1572
+ mode: "shadow",
1573
+ trigger: "before-first-dispatch",
1574
+ state: "not-needed",
1575
+ action: "none",
1576
+ reason_code: "no-dispatch",
1577
+ };
1578
+ }
1579
+
1488
1580
  function assertAgentCapacity(agentsSpawned: number, maxAgents: number): void {
1489
1581
  if (agentsSpawned >= maxAgents) {
1490
1582
  throw new Error(
@@ -1,3 +1,9 @@
1
+ export {
2
+ failedWorkflowDiagnosticAdmissionObservation,
3
+ type ObserveWorkflowDiagnosticAdmissionInput,
4
+ observeWorkflowDiagnosticAdmission,
5
+ type WorkflowDiagnosticAdmissionRuntime,
6
+ } from "./admission.ts";
1
7
  export type {
2
8
  CreateWorkflowApprovalInput,
3
9
  ResolveWorkflowApprovalInput,
@@ -72,6 +78,9 @@ export type {
72
78
  WorkflowAttemptPriorContext,
73
79
  WorkflowAttemptUnresolvedCriterion,
74
80
  WorkflowContext,
81
+ WorkflowDiagnosticAdmissionConfig,
82
+ WorkflowDiagnosticAdmissionObservation,
83
+ WorkflowDiagnosticAdmissionProof,
75
84
  WorkflowEvidenceInput,
76
85
  WorkflowEvidenceRecord,
77
86
  WorkflowMeta,
@@ -87,6 +96,7 @@ export type {
87
96
  } from "./types.ts";
88
97
  export {
89
98
  WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION,
99
+ WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION,
90
100
  WORKFLOW_PROOF_SCHEMA_VERSION,
91
101
  WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION,
92
102
  } from "./types.ts";
@@ -24,6 +24,7 @@ import type {
24
24
  SpawnFailureClass,
25
25
  WorkflowAgentProof,
26
26
  WorkflowAttemptContext,
27
+ WorkflowDiagnosticAdmissionProof,
27
28
  WorkflowEvidenceInput,
28
29
  WorkflowEvidenceRecord,
29
30
  WorkflowMeta,
@@ -35,7 +36,11 @@ import type {
35
36
  WorkflowSandboxProjectionEvidence,
36
37
  WorkflowWorkContext,
37
38
  } from "./types.ts";
38
- import { EVIDENCE_KINDS, WORKFLOW_PROOF_SCHEMA_VERSION } from "./types.ts";
39
+ import {
40
+ EVIDENCE_KINDS,
41
+ WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION,
42
+ WORKFLOW_PROOF_SCHEMA_VERSION,
43
+ } from "./types.ts";
39
44
  import { isCanonicalWorkflowWorkContext } from "./work-context.ts";
40
45
  import type {
41
46
  WorkspaceAttestation,
@@ -84,6 +89,7 @@ export interface BuildWorkflowProofInput {
84
89
  after: RepoSnapshot;
85
90
  agents: WorkflowAgentProof[];
86
91
  evidence: WorkflowEvidenceRecord[];
92
+ diagnosticAdmission?: WorkflowDiagnosticAdmissionProof;
87
93
  adapterEvidence?: Readonly<Record<string, AdapterEvidenceCapability | undefined>>;
88
94
  /** Filesystem policy actually projected into children (ADR 0039). */
89
95
  sandboxProjection?: WorkflowSandboxProjectionEvidence;
@@ -299,6 +305,7 @@ export function buildWorkflowProof(input: BuildWorkflowProofInput): WorkflowProo
299
305
  agents,
300
306
  evidence: input.evidence,
301
307
  policy: input.policy ? buildPolicyProof(input.policy) : undefined,
308
+ ...(input.diagnosticAdmission ? { diagnostic_admission: input.diagnosticAdmission } : {}),
302
309
  execution:
303
310
  input.workspaceBinding && input.workspaceAttestation
304
311
  ? buildExecutionEvidence(input.status, input.workspaceBinding, input.workspaceAttestation)
@@ -385,6 +392,7 @@ export function readWorkflowProof(coordRoot: string, runId: string): WorkflowPro
385
392
  (!proof.run.work_item_id ||
386
393
  !proof.run.work_context ||
387
394
  !isCanonicalWorkflowAttemptContext(proof.run.attempt_context))) ||
395
+ !validDiagnosticAdmissionProof(proof.diagnostic_admission) ||
388
396
  (proof.execution !== undefined &&
389
397
  !isWorkspaceExecutionEvidence(proof.execution, runId, proof.run.status))
390
398
  ) {
@@ -410,6 +418,42 @@ export function readWorkflowProof(coordRoot: string, runId: string): WorkflowPro
410
418
  return proof;
411
419
  }
412
420
 
421
+ function validDiagnosticAdmissionProof(
422
+ value: WorkflowDiagnosticAdmissionProof | undefined,
423
+ ): boolean {
424
+ if (value === undefined) return true;
425
+ if (
426
+ value.schema_version !== WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION ||
427
+ value.mode !== "shadow" ||
428
+ value.trigger !== "before-first-dispatch" ||
429
+ value.action !== "none" ||
430
+ (value.state !== "not-needed" && value.state !== "observed")
431
+ ) {
432
+ return false;
433
+ }
434
+ if (value.state === "not-needed") {
435
+ return value.reason_code === "no-dispatch" && value.observation === undefined;
436
+ }
437
+ const observation = value.observation;
438
+ return (
439
+ value.reason_code === undefined &&
440
+ observation !== undefined &&
441
+ validTimestamp(observation.requested_at) &&
442
+ validTimestamp(observation.observed_at) &&
443
+ Number.isSafeInteger(observation.wait_ms) &&
444
+ observation.wait_ms >= 0 &&
445
+ ["running", "started", "unavailable"].includes(observation.service_state) &&
446
+ ["fresh", "unavailable"].includes(observation.freshness) &&
447
+ (observation.sampled_at === undefined || validTimestamp(observation.sampled_at)) &&
448
+ observation.advice?.schema_version === 1 &&
449
+ observation.advice.observer_only === true
450
+ );
451
+ }
452
+
453
+ function validTimestamp(value: unknown): value is string {
454
+ return typeof value === "string" && value.length > 0 && Number.isFinite(Date.parse(value));
455
+ }
456
+
413
457
  function buildExecutionEvidence(
414
458
  workflowStatus: "succeeded" | "failed",
415
459
  binding: WorkspaceBinding,
@@ -458,6 +502,15 @@ export function renderWorkflowProof(proof: WorkflowProof): string {
458
502
  `${proof.policy.summary.denied} denied, ${proof.policy.summary.asked} asked`,
459
503
  );
460
504
  }
505
+ if (proof.diagnostic_admission) {
506
+ const observation = proof.diagnostic_admission.observation;
507
+ lines.push(
508
+ observation
509
+ ? `admission: shadow ${observation.advice.pressure}; ` +
510
+ `${observation.advice.fan_out_recommendation}; action none`
511
+ : "admission: shadow not needed; no real child dispatch",
512
+ );
513
+ }
461
514
  const repo = proof.repository;
462
515
  const drift = repo.drift;
463
516
  lines.push(
@@ -26,9 +26,11 @@ import { readJsonRecord, writeImmutableJson } from "./durable-record.ts";
26
26
  import { normalizeWorkflowSpecialists } from "./specialists.ts";
27
27
  import type {
28
28
  WorkflowAttemptContext,
29
+ WorkflowDiagnosticAdmissionConfig,
29
30
  WorkflowSpecialistProfile,
30
31
  WorkflowWorkContext,
31
32
  } from "./types.ts";
33
+ import { WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION } from "./types.ts";
32
34
  import { isCanonicalWorkflowWorkContext } from "./work-context.ts";
33
35
  import type {
34
36
  WorkspaceAllocationRequest,
@@ -41,7 +43,7 @@ import {
41
43
  isWorkspaceCompatibilityExecutionEvidence,
42
44
  } from "./workspaces/validate.ts";
43
45
 
44
- export const WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION = 1 as const;
46
+ export const WORKFLOW_RUN_MANIFEST_SCHEMA_VERSION = 2 as const;
45
47
 
46
48
  const MANIFEST_LIMIT_BYTES = 256 * 1024;
47
49
  const FOREIGN_LEASE_STALE_MS = 24 * 60 * 60 * 1_000;
@@ -61,6 +63,7 @@ export interface WorkflowRunManifest {
61
63
  default_adapter: string;
62
64
  max_agents: number;
63
65
  concurrency: number;
66
+ diagnostic_admission?: WorkflowDiagnosticAdmissionConfig;
64
67
  subscription_only: boolean;
65
68
  allow_api_billing: boolean;
66
69
  approval_mode: "deny" | "park";
@@ -274,6 +277,7 @@ function validExecution(value: WorkflowRunManifest["execution"]): boolean {
274
277
  value.default_adapter.length > 0 &&
275
278
  positiveSafeInteger(value.max_agents) &&
276
279
  positiveSafeInteger(value.concurrency) &&
280
+ validDiagnosticAdmission(value.diagnostic_admission) &&
277
281
  typeof value.subscription_only === "boolean" &&
278
282
  typeof value.allow_api_billing === "boolean" &&
279
283
  (value.approval_mode === "deny" || value.approval_mode === "park") &&
@@ -292,6 +296,14 @@ function validExecution(value: WorkflowRunManifest["execution"]): boolean {
292
296
  );
293
297
  }
294
298
 
299
+ function validDiagnosticAdmission(value: WorkflowDiagnosticAdmissionConfig | undefined): boolean {
300
+ return (
301
+ value === undefined ||
302
+ (value.schema_version === WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION &&
303
+ value.mode === "shadow")
304
+ );
305
+ }
306
+
295
307
  function readManifestWorkspaceRequest(
296
308
  coordRoot: string,
297
309
  runId: string,
@@ -7,6 +7,7 @@
7
7
  * Design record: decision 0015 (portable coordination-aware workflows).
8
8
  */
9
9
 
10
+ import type { DiagnosticAdvice } from "../diagnostics/contract.ts";
10
11
  import type {
11
12
  DispatchCostEstimator,
12
13
  ExternalMutationRequest,
@@ -24,7 +25,8 @@ import type {
24
25
  WorkspaceProvider,
25
26
  } from "./workspaces/index.ts";
26
27
 
27
- export const WORKFLOW_PROOF_SCHEMA_VERSION = 1 as const;
28
+ export const WORKFLOW_PROOF_SCHEMA_VERSION = 2 as const;
29
+ export const WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION = 1 as const;
28
30
  export const WORKFLOW_WORK_CONTEXT_SCHEMA_VERSION = 1 as const;
29
31
  export const WORKFLOW_ATTEMPT_CONTEXT_SCHEMA_VERSION = 1 as const;
30
32
 
@@ -46,6 +48,31 @@ export type AcceptanceStatus = "satisfied" | "unsatisfied" | "unknown";
46
48
  export type WorkflowRunStatus = "succeeded" | "failed";
47
49
  export type WorkflowApprovalMode = "deny" | "park";
48
50
 
51
+ export interface WorkflowDiagnosticAdmissionConfig {
52
+ schema_version: typeof WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION;
53
+ mode: "shadow";
54
+ }
55
+
56
+ export interface WorkflowDiagnosticAdmissionObservation {
57
+ requested_at: string;
58
+ observed_at: string;
59
+ wait_ms: number;
60
+ service_state: "running" | "started" | "unavailable";
61
+ freshness: "fresh" | "unavailable";
62
+ sampled_at?: string;
63
+ advice: DiagnosticAdvice;
64
+ }
65
+
66
+ export interface WorkflowDiagnosticAdmissionProof {
67
+ schema_version: typeof WORKFLOW_DIAGNOSTIC_ADMISSION_SCHEMA_VERSION;
68
+ mode: "shadow";
69
+ trigger: "before-first-dispatch";
70
+ state: "not-needed" | "observed";
71
+ action: "none";
72
+ reason_code?: "no-dispatch";
73
+ observation?: WorkflowDiagnosticAdmissionObservation;
74
+ }
75
+
49
76
  export interface AcceptanceCriterion {
50
77
  /** Stable identifier referenced by evidence, for example `tests-pass`. */
51
78
  id: string;
@@ -221,6 +248,8 @@ export interface WorkflowProof {
221
248
  agents: WorkflowAgentProof[];
222
249
  evidence: WorkflowEvidenceRecord[];
223
250
  policy?: WorkflowPolicyProof;
251
+ /** Observer-only local pressure recorded before the first real child dispatch. */
252
+ diagnostic_admission?: WorkflowDiagnosticAdmissionProof;
224
253
  /** Immutable terminal provider evidence for isolated execution. */
225
254
  execution?: WorkspaceExecutionEvidence;
226
255
  repository: WorkflowRepoEvidence;
@@ -557,6 +586,13 @@ export interface EngineOpts {
557
586
  maxAgents?: number;
558
587
  /** Concurrent-subagent cap for parallel() (default 4). */
559
588
  concurrency?: number;
589
+ /** Opt-in observer-only pressure sample before the first real child dispatch. */
590
+ diagnosticAdmission?: WorkflowDiagnosticAdmissionConfig;
591
+ /** Admission observer override for tests. */
592
+ observeDiagnosticAdmission?: (
593
+ coordRoot: string,
594
+ runId: string,
595
+ ) => Promise<WorkflowDiagnosticAdmissionObservation>;
560
596
  /** Working directory children spawn in (default: coordRoot). */
561
597
  cwd?: string;
562
598
  /** Progress sink (default: process.stderr). */
@@ -639,6 +675,8 @@ export interface RunReport {
639
675
  billing: Array<{ adapter: AdapterName; mode: BillingMode }>;
640
676
  /** Policy verdict totals when the host supplied a policy. */
641
677
  policy?: WorkflowPolicyProof["summary"];
678
+ /** Observer-only pressure sample. Never changes dispatch in shadow mode. */
679
+ diagnosticAdmission?: WorkflowDiagnosticAdmissionProof;
642
680
  /** Isolated workspace binding when this run requested a provider capability. */
643
681
  workspaceBinding?: WorkspaceBinding;
644
682
  }