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,311 @@
1
+ import type {
2
+ SupervisorCapability,
3
+ SupervisorFinding,
4
+ SupervisorFindingExplanation,
5
+ SupervisorTimeline,
6
+ } from "../supervisor/contract.ts";
7
+
8
+ export const DIAGNOSTIC_BUNDLE_SCHEMA_VERSION = 3 as const;
9
+ export const DIAGNOSTIC_COMMAND_SCHEMA_VERSION = 1 as const;
10
+ export const DIAGNOSTIC_INPUT_SCHEMA_VERSION = 2 as const;
11
+ export const DIAGNOSTIC_EXPECTED_SCHEMA_VERSION = 3 as const;
12
+ export const DIAGNOSTIC_SUMMARY_SCHEMA_VERSION = 1 as const;
13
+ export const DIAGNOSTIC_ADVICE_SCHEMA_VERSION = 1 as const;
14
+ export const DIAGNOSTIC_COMPARISON_SCHEMA_VERSION = 1 as const;
15
+
16
+ export const DIAGNOSTIC_ADVICE_LIMITS = {
17
+ max_contributing_findings: 8,
18
+ max_reasons: 4,
19
+ } as const;
20
+
21
+ export type DiagnosticPressure = "normal" | "elevated" | "critical" | "unknown";
22
+ export type DiagnosticFanOutRecommendation =
23
+ | "proceed"
24
+ | "use-caution"
25
+ | "avoid-new-fan-out"
26
+ | "unknown";
27
+
28
+ export interface DiagnosticAdviceFinding {
29
+ finding_id: string;
30
+ finding_kind: string;
31
+ severity: "warning" | "critical";
32
+ summary: string;
33
+ scope_kind: string;
34
+ scope_id: string;
35
+ occurrence_count: number;
36
+ owner_kind?: "agent" | "service";
37
+ owner_id?: string;
38
+ workload_relationship?: "active-work" | "unexpected-idle-growth" | "unknown";
39
+ }
40
+
41
+ export interface DiagnosticAdviceReason {
42
+ code:
43
+ | "critical_findings_active"
44
+ | "warning_findings_active"
45
+ | "findings_source_unavailable"
46
+ | "no_active_pressure_findings";
47
+ summary: string;
48
+ finding_ids: readonly string[];
49
+ }
50
+
51
+ export interface DiagnosticAdvice {
52
+ schema_version: typeof DIAGNOSTIC_ADVICE_SCHEMA_VERSION;
53
+ evaluated_at: string;
54
+ pressure: DiagnosticPressure;
55
+ fan_out_recommendation: DiagnosticFanOutRecommendation;
56
+ observer_only: true;
57
+ summary: string;
58
+ source_capability: SupervisorCapability;
59
+ active_finding_count: number;
60
+ contributing_finding_count: number;
61
+ omitted_contributing_finding_count: number;
62
+ contributing_findings: readonly DiagnosticAdviceFinding[];
63
+ reasons: readonly DiagnosticAdviceReason[];
64
+ }
65
+
66
+ export const DIAGNOSTIC_BUNDLE_FILES = [
67
+ "diagnostic-manifest.json",
68
+ "inputs/observations.json",
69
+ "inputs/thresholds.json",
70
+ "expected.json",
71
+ "summary.json",
72
+ ] as const;
73
+
74
+ export type DiagnosticBundleFilePath = (typeof DIAGNOSTIC_BUNDLE_FILES)[number];
75
+
76
+ export interface DiagnosticBundleFile {
77
+ path: Exclude<DiagnosticBundleFilePath, "diagnostic-manifest.json">;
78
+ media_type: "application/json";
79
+ bytes: number;
80
+ sha256: string;
81
+ }
82
+
83
+ export interface DiagnosticBundleSource {
84
+ source_kind: string;
85
+ schema_version?: number;
86
+ capability: SupervisorCapability["state"];
87
+ entry_count: number;
88
+ omitted_count: number;
89
+ file: "inputs/observations.json";
90
+ }
91
+
92
+ export interface DiagnosticBundleManifest {
93
+ schema_version: typeof DIAGNOSTIC_BUNDLE_SCHEMA_VERSION;
94
+ artifact_id: string;
95
+ captured_at: string;
96
+ machine_id: string;
97
+ finding_id?: string;
98
+ time_range: { start_at: string; end_at: string };
99
+ engine_version: string;
100
+ threshold_digest: string;
101
+ sources: readonly DiagnosticBundleSource[];
102
+ capabilities: readonly SupervisorCapability[];
103
+ files: readonly DiagnosticBundleFile[];
104
+ replay: {
105
+ input_file: "inputs/observations.json";
106
+ thresholds_file: "inputs/thresholds.json";
107
+ expected_file: "expected.json";
108
+ };
109
+ }
110
+
111
+ export interface DiagnosticSelection {
112
+ finding_id?: string;
113
+ start_at: string;
114
+ end_at: string;
115
+ }
116
+
117
+ export interface DiagnosticCapturedSource {
118
+ source_kind: string;
119
+ capability: SupervisorCapability["state"];
120
+ schema_version?: number;
121
+ observed_at?: string;
122
+ value?: unknown;
123
+ reason_code?: string;
124
+ }
125
+
126
+ export interface DiagnosticObservations {
127
+ schema_version: typeof DIAGNOSTIC_INPUT_SCHEMA_VERSION;
128
+ captured_at: string;
129
+ selection: DiagnosticSelection;
130
+ sources: readonly DiagnosticCapturedSource[];
131
+ }
132
+
133
+ export interface DiagnosticThresholds {
134
+ schema_version: typeof DIAGNOSTIC_INPUT_SCHEMA_VERSION;
135
+ values: Readonly<Record<string, unknown>>;
136
+ }
137
+
138
+ export interface DiagnosticExpected {
139
+ schema_version: typeof DIAGNOSTIC_EXPECTED_SCHEMA_VERSION;
140
+ threshold_digest: string;
141
+ selection: DiagnosticSelection;
142
+ findings: readonly SupervisorFinding[];
143
+ timelines: readonly SupervisorTimeline[];
144
+ explanations: readonly SupervisorFindingExplanation[];
145
+ advice: DiagnosticAdvice;
146
+ }
147
+
148
+ export interface DiagnosticSummary {
149
+ schema_version: typeof DIAGNOSTIC_SUMMARY_SCHEMA_VERSION;
150
+ artifact_id: string;
151
+ captured_at: string;
152
+ machine_id: string;
153
+ machine_id_kind: "pseudonymous";
154
+ selection: DiagnosticSelection;
155
+ source_count: number;
156
+ supported_source_count: number;
157
+ sanitized_value_count: number;
158
+ omitted_value_count: number;
159
+ total_bytes: number;
160
+ }
161
+
162
+ export interface ValidatedDiagnosticBundle {
163
+ path: string;
164
+ manifest: DiagnosticBundleManifest;
165
+ observations: DiagnosticObservations;
166
+ thresholds: DiagnosticThresholds;
167
+ expected: DiagnosticExpected;
168
+ summary: DiagnosticSummary;
169
+ }
170
+
171
+ export interface DiagnosticReplayResult {
172
+ schema_version: typeof DIAGNOSTIC_COMMAND_SCHEMA_VERSION;
173
+ artifact_id: string;
174
+ replayed_at: string;
175
+ matched: boolean;
176
+ threshold_digest: string;
177
+ expected_digest: string;
178
+ actual_digest: string;
179
+ finding_count: number;
180
+ }
181
+
182
+ export type DiagnosticComparisonImpact =
183
+ | "regression"
184
+ | "worsened"
185
+ | "changed"
186
+ | "improved"
187
+ | "recovery"
188
+ | "unchanged";
189
+
190
+ export type DiagnosticFindingChangeClass = "added" | "resolved" | "persistent";
191
+
192
+ export interface DiagnosticFindingFieldChange {
193
+ field:
194
+ | "severity"
195
+ | "state"
196
+ | "occurrence_count"
197
+ | "peak_observed_value"
198
+ | "owner"
199
+ | "workload_relationship";
200
+ before: string | number | null;
201
+ after: string | number | null;
202
+ impact: "worsened" | "improved" | "changed";
203
+ }
204
+
205
+ export interface DiagnosticFindingComparison {
206
+ fingerprint: string;
207
+ change_class: DiagnosticFindingChangeClass;
208
+ impact: DiagnosticComparisonImpact;
209
+ before?: SupervisorFinding;
210
+ after?: SupervisorFinding;
211
+ field_changes: readonly DiagnosticFindingFieldChange[];
212
+ }
213
+
214
+ export interface DiagnosticBundleComparisonRef {
215
+ artifact_id: string;
216
+ captured_at: string;
217
+ machine_id: string;
218
+ engine_version: string;
219
+ threshold_digest: string;
220
+ finding_count: number;
221
+ pressure: DiagnosticPressure;
222
+ }
223
+
224
+ export interface DiagnosticCapabilityComparison {
225
+ source_kind: string;
226
+ change: "added" | "removed" | "changed" | "unchanged";
227
+ before?: SupervisorCapability;
228
+ after?: SupervisorCapability;
229
+ }
230
+
231
+ export interface DiagnosticHookAggregateSummary {
232
+ key: string;
233
+ hook_name: string;
234
+ adapter: string;
235
+ invocation_count: number;
236
+ degraded_count: number;
237
+ faulted_count: number;
238
+ retry_count: number;
239
+ duration_p95_ms: number;
240
+ rss_end_max_bytes: number;
241
+ }
242
+
243
+ export interface DiagnosticHookHealthSummary {
244
+ invocation_count: number;
245
+ degraded_count: number;
246
+ faulted_count: number;
247
+ slow_count: number;
248
+ high_memory_count: number;
249
+ retry_count: number;
250
+ aggregates: readonly DiagnosticHookAggregateSummary[];
251
+ }
252
+
253
+ export interface DiagnosticShadowAdmissionSummary {
254
+ record_count: number;
255
+ observed_count: number;
256
+ not_needed_count: number;
257
+ unavailable_count: number;
258
+ normal_count: number;
259
+ elevated_count: number;
260
+ critical_count: number;
261
+ unknown_count: number;
262
+ max_wait_ms: number;
263
+ }
264
+
265
+ export interface DiagnosticOptionalSourceComparison<T> {
266
+ before_capability: SupervisorCapability;
267
+ after_capability: SupervisorCapability;
268
+ before?: T;
269
+ after?: T;
270
+ }
271
+
272
+ export interface DiagnosticComparisonWarning {
273
+ code:
274
+ | "threshold_digest_changed"
275
+ | "engine_version_changed"
276
+ | "machine_changed"
277
+ | "capture_order_reversed"
278
+ | "duplicate_fingerprint"
279
+ | "source_capability_changed"
280
+ | "hook_health_unavailable"
281
+ | "shadow_admission_unavailable";
282
+ summary: string;
283
+ }
284
+
285
+ export interface DiagnosticBundleComparison {
286
+ schema_version: typeof DIAGNOSTIC_COMPARISON_SCHEMA_VERSION;
287
+ observer_only: true;
288
+ before: DiagnosticBundleComparisonRef;
289
+ after: DiagnosticBundleComparisonRef;
290
+ comparability: "comparable" | "partial";
291
+ warnings: readonly DiagnosticComparisonWarning[];
292
+ advice: {
293
+ before: DiagnosticAdvice;
294
+ after: DiagnosticAdvice;
295
+ direction: "escalated" | "deescalated" | "unchanged" | "changed";
296
+ };
297
+ findings: {
298
+ total: number;
299
+ regressions: number;
300
+ worsened: number;
301
+ changed: number;
302
+ improved: number;
303
+ recoveries: number;
304
+ unchanged: number;
305
+ rows: readonly DiagnosticFindingComparison[];
306
+ };
307
+ capabilities: readonly DiagnosticCapabilityComparison[];
308
+ hook_health: DiagnosticOptionalSourceComparison<DiagnosticHookHealthSummary>;
309
+ shadow_admission: DiagnosticOptionalSourceComparison<DiagnosticShadowAdmissionSummary>;
310
+ comparison_digest: string;
311
+ }
@@ -0,0 +1,11 @@
1
+ import { createHash } from "node:crypto";
2
+ import { resolveMachineLabel } from "../../lib/machine.ts";
3
+
4
+ /** Stable within one machine label, but not reversible to that label. */
5
+ export function pseudonymousMachineId(machineLabel = resolveMachineLabel()): string {
6
+ const digest = createHash("sha256")
7
+ .update("harnery-diagnostic-machine-v1\0")
8
+ .update(machineLabel)
9
+ .digest("hex");
10
+ return `machine_${digest}`;
11
+ }
@@ -0,0 +1,7 @@
1
+ export * from "./advice.ts";
2
+ export * from "./bundle.ts";
3
+ export * from "./comparison.ts";
4
+ export * from "./contract.ts";
5
+ export * from "./identity.ts";
6
+ export * from "./replay.ts";
7
+ export * from "./sanitize.ts";
@@ -0,0 +1,314 @@
1
+ import { createHash } from "node:crypto";
2
+ import type { CoordinationHealthSnapshot } from "../agents/health.ts";
3
+ import type { ResourceSnapshot } from "../resources/contract.ts";
4
+ import { RESOURCE_SNAPSHOT_SCHEMA_VERSION } from "../resources/contract.ts";
5
+ import type {
6
+ ObservedHookHealth,
7
+ ObservedServiceHealth,
8
+ SupervisorActivitySnapshot,
9
+ SupervisorFinding,
10
+ SupervisorFindingExplanation,
11
+ SupervisorFindings,
12
+ SupervisorHistory,
13
+ SupervisorLogFeed,
14
+ SupervisorSnapshot,
15
+ SupervisorTimeline,
16
+ } from "../supervisor/contract.ts";
17
+ import {
18
+ SUPERVISOR_HISTORY_SCHEMA_VERSION,
19
+ SUPERVISOR_LOG_FEED_SCHEMA_VERSION,
20
+ SUPERVISOR_SNAPSHOT_SCHEMA_VERSION,
21
+ } from "../supervisor/contract.ts";
22
+ import { explainSupervisorFinding } from "../supervisor/explanations.ts";
23
+ import { updateSupervisorFindings } from "../supervisor/findings.ts";
24
+ import { projectHookHealth } from "../supervisor/hook-health.ts";
25
+ import { buildSupervisorTimeline } from "../supervisor/timeline.ts";
26
+ import { buildDiagnosticAdvice } from "./advice.ts";
27
+ import {
28
+ DIAGNOSTIC_EXPECTED_SCHEMA_VERSION,
29
+ type DiagnosticExpected,
30
+ type DiagnosticObservations,
31
+ type DiagnosticSelection,
32
+ type DiagnosticThresholds,
33
+ } from "./contract.ts";
34
+
35
+ export function canonicalJson(value: unknown): string {
36
+ return JSON.stringify(sortValue(value));
37
+ }
38
+
39
+ export function sha256(value: string | Buffer): string {
40
+ return createHash("sha256").update(value).digest("hex");
41
+ }
42
+
43
+ /** Record the live engine's frozen output. Replay never uses this as an input. */
44
+ export function deriveCapturedExpected(
45
+ observations: DiagnosticObservations,
46
+ thresholds: DiagnosticThresholds,
47
+ ): DiagnosticExpected {
48
+ const selection = observations.selection;
49
+ const findings = filterFindings(
50
+ findingsProjection(sourceValue(observations, "supervisor.findings")),
51
+ selection,
52
+ );
53
+ const coordination = sourceValue(observations, "coordination.health") as
54
+ | CoordinationHealthSnapshot
55
+ | undefined;
56
+ const relatedSources = coordination?.recent_events ?? [];
57
+ return expected(
58
+ thresholds,
59
+ selection,
60
+ findings,
61
+ findings.map((finding) => diagnosticTimeline(finding, relatedSources)),
62
+ findings.map(explainSupervisorFinding),
63
+ observations,
64
+ );
65
+ }
66
+
67
+ /** Re-run the pure finding engine from frozen source inputs only. */
68
+ export function replayDiagnosticInputs(
69
+ observations: DiagnosticObservations,
70
+ thresholds: DiagnosticThresholds,
71
+ ): DiagnosticExpected {
72
+ const resource =
73
+ optionalSource<ResourceSnapshot>(observations, "resources.snapshot") ??
74
+ neutralResource(observations.captured_at);
75
+ const supervisor =
76
+ optionalSource<SupervisorSnapshot>(observations, "supervisor.snapshot") ??
77
+ neutralSupervisor(observations.captured_at);
78
+ const history =
79
+ optionalSource<SupervisorHistory>(observations, "supervisor.history") ?? neutralHistory();
80
+ const logFeed =
81
+ optionalSource<SupervisorLogFeed>(observations, "supervisor.log-feed") ??
82
+ neutralLogFeed(observations.captured_at);
83
+ const hookHealth = projectHookHealth(logFeed, new Date(observations.captured_at));
84
+ const coordination = optionalSource<CoordinationHealthSnapshot>(
85
+ observations,
86
+ "coordination.health",
87
+ );
88
+ const activity = optionalSource<SupervisorActivitySnapshot>(observations, "supervisor.activity");
89
+ const currentProjection = optionalSource<SupervisorFindings>(observations, "supervisor.findings");
90
+ const observedAt =
91
+ currentProjection?.active[0]?.observed_at ??
92
+ currentProjection?.transitions.at(-1)?.observed_at ??
93
+ resource.sampled_at;
94
+ // The frozen projection supplies lifecycle state only. Candidates, severity,
95
+ // attribution, workload context, and evidence are all re-evaluated from the
96
+ // captured source observations. Without this prior state, a replay would
97
+ // mint fresh IDs and discard recurrence and peak history for open episodes.
98
+ const evaluated = updateSupervisorFindings({
99
+ previous: currentProjection,
100
+ resource,
101
+ services: supervisor.services as readonly ObservedServiceHealth[],
102
+ hooks: supervisor.hooks as readonly ObservedHookHealth[],
103
+ history,
104
+ logFeed,
105
+ hookHealth,
106
+ coordination,
107
+ activity,
108
+ now: new Date(observedAt),
109
+ });
110
+ const findings = filterFindings(findingsProjection(evaluated), observations.selection);
111
+ const relatedSources = coordination?.recent_events ?? [];
112
+ return expected(
113
+ thresholds,
114
+ observations.selection,
115
+ findings,
116
+ findings.map((finding) => diagnosticTimeline(finding, relatedSources)),
117
+ findings.map(explainSupervisorFinding),
118
+ observations,
119
+ );
120
+ }
121
+
122
+ function diagnosticTimeline(
123
+ finding: SupervisorFinding,
124
+ relatedSources: readonly CoordinationHealthSnapshot["recent_events"][number][],
125
+ ): SupervisorTimeline {
126
+ return buildSupervisorTimeline(
127
+ finding,
128
+ relatedSources.filter((source) => {
129
+ const delta = Math.abs(Date.parse(source.observed_at) - Date.parse(finding.observed_at));
130
+ return Number.isFinite(delta) && delta <= 5 * 60_000;
131
+ }),
132
+ );
133
+ }
134
+
135
+ function expected(
136
+ thresholds: DiagnosticThresholds,
137
+ selection: DiagnosticSelection,
138
+ findings: readonly SupervisorFinding[],
139
+ timelines: readonly SupervisorTimeline[],
140
+ explanations: readonly SupervisorFindingExplanation[],
141
+ observations: DiagnosticObservations,
142
+ ): DiagnosticExpected {
143
+ return {
144
+ schema_version: DIAGNOSTIC_EXPECTED_SCHEMA_VERSION,
145
+ threshold_digest: sha256(canonicalJson(thresholds)),
146
+ selection,
147
+ findings,
148
+ timelines: [...timelines].sort((left, right) =>
149
+ left.finding_id.localeCompare(right.finding_id),
150
+ ),
151
+ explanations: [...explanations].sort((left, right) =>
152
+ left.finding_id.localeCompare(right.finding_id),
153
+ ),
154
+ advice: buildDiagnosticAdvice({
155
+ findings,
156
+ sourceCapability: capturedSourceCapability(observations, "supervisor.findings"),
157
+ evaluatedAt: observations.captured_at,
158
+ }),
159
+ };
160
+ }
161
+
162
+ function capturedSourceCapability(
163
+ observations: DiagnosticObservations,
164
+ sourceKind: string,
165
+ ): import("../supervisor/contract.ts").SupervisorCapability {
166
+ const source = observations.sources.find((candidate) => candidate.source_kind === sourceKind);
167
+ return source
168
+ ? {
169
+ source_kind: sourceKind,
170
+ state: source.capability,
171
+ reason_code: source.reason_code,
172
+ }
173
+ : {
174
+ source_kind: sourceKind,
175
+ state: "unsupported",
176
+ reason_code: "source_missing",
177
+ };
178
+ }
179
+
180
+ function findingsProjection(value: unknown): readonly SupervisorFinding[] {
181
+ const record = object(value);
182
+ return [
183
+ ...collectNamedRecords<SupervisorFinding>(record?.active),
184
+ ...collectNamedRecords<SupervisorFinding>(record?.transitions),
185
+ ];
186
+ }
187
+
188
+ function filterFindings(
189
+ rows: readonly SupervisorFinding[],
190
+ selection: DiagnosticSelection,
191
+ ): SupervisorFinding[] {
192
+ const deduped = new Map(rows.map((finding) => [finding.id, finding]));
193
+ return [...deduped.values()]
194
+ .filter((finding) => {
195
+ if (selection.finding_id) return finding.id === selection.finding_id;
196
+ const observed = Date.parse(finding.observed_at);
197
+ return observed >= Date.parse(selection.start_at) && observed <= Date.parse(selection.end_at);
198
+ })
199
+ .sort(
200
+ (left, right) =>
201
+ left.observed_at.localeCompare(right.observed_at) || left.id.localeCompare(right.id),
202
+ );
203
+ }
204
+
205
+ function optionalSource<T>(
206
+ observations: DiagnosticObservations,
207
+ sourceKind: string,
208
+ ): T | undefined {
209
+ const source = observations.sources.find((candidate) => candidate.source_kind === sourceKind);
210
+ return source?.capability === "supported" && source.value !== undefined
211
+ ? (source.value as T)
212
+ : undefined;
213
+ }
214
+
215
+ function neutralResource(sampledAt: string): ResourceSnapshot {
216
+ return {
217
+ schema_version: RESOURCE_SNAPSHOT_SCHEMA_VERSION,
218
+ sampled_at: sampledAt,
219
+ interval_ms: null,
220
+ sample_duration_ms: 0,
221
+ collector_cpu_ms: 0,
222
+ platform: "linux",
223
+ namespace: "unknown",
224
+ support: {
225
+ state: "unsupported",
226
+ sampler: "unsupported",
227
+ reason: "captured-source-unavailable",
228
+ },
229
+ machine: {
230
+ cpu_percent: null,
231
+ cpu_logical_count: 0,
232
+ load_average: null,
233
+ memory_total_bytes: null,
234
+ memory_available_bytes: null,
235
+ memory_used_bytes: null,
236
+ memory_percent: null,
237
+ swap_total_bytes: null,
238
+ swap_used_bytes: null,
239
+ process_count: 0,
240
+ },
241
+ groups: [],
242
+ processes: [],
243
+ visible_process_count: 0,
244
+ omitted_process_count: 0,
245
+ unattributed_process_count: 0,
246
+ };
247
+ }
248
+
249
+ function neutralSupervisor(sampledAt: string): SupervisorSnapshot {
250
+ return {
251
+ schema_version: SUPERVISOR_SNAPSHOT_SCHEMA_VERSION,
252
+ sampled_at: sampledAt,
253
+ sequence: 0,
254
+ collector_duration_ms: 0,
255
+ resource_sample_duration_ms: 0,
256
+ services: [],
257
+ hooks: [],
258
+ active_finding_count: 0,
259
+ history_point_count: 0,
260
+ log_record_count: 0,
261
+ live_consumer_count: 0,
262
+ attributed_agent_count: 0,
263
+ };
264
+ }
265
+
266
+ function neutralHistory(): SupervisorHistory {
267
+ return {
268
+ schema_version: SUPERVISOR_HISTORY_SCHEMA_VERSION,
269
+ interval_ms: 10_000,
270
+ max_points: 90,
271
+ points: [],
272
+ };
273
+ }
274
+
275
+ function neutralLogFeed(capturedAt: string): SupervisorLogFeed {
276
+ return {
277
+ schema_version: SUPERVISOR_LOG_FEED_SCHEMA_VERSION,
278
+ captured_at: capturedAt,
279
+ sequence: 0,
280
+ lanes: [],
281
+ total_records: 0,
282
+ unavailable_families: 0,
283
+ };
284
+ }
285
+
286
+ function sourceValue(observations: DiagnosticObservations, sourceKind: string): unknown {
287
+ return observations.sources.find((source) => source.source_kind === sourceKind)?.value;
288
+ }
289
+
290
+ function collectNamedRecords<T>(value: unknown): T[] {
291
+ if (Array.isArray(value)) return value.filter(isObject) as T[];
292
+ const record = object(value);
293
+ if (!record) return [];
294
+ if (Array.isArray(record.rows)) return record.rows.filter(isObject) as T[];
295
+ return Object.values(record).filter(isObject) as T[];
296
+ }
297
+
298
+ function sortValue(value: unknown): unknown {
299
+ if (Array.isArray(value)) return value.map(sortValue);
300
+ if (!isObject(value)) return value;
301
+ return Object.fromEntries(
302
+ Object.entries(value)
303
+ .sort(([left], [right]) => left.localeCompare(right))
304
+ .map(([key, item]) => [key, sortValue(item)]),
305
+ );
306
+ }
307
+
308
+ function object(value: unknown): Record<string, unknown> | undefined {
309
+ return isObject(value) ? value : undefined;
310
+ }
311
+
312
+ function isObject(value: unknown): value is Record<string, unknown> {
313
+ return !!value && typeof value === "object" && !Array.isArray(value);
314
+ }