harnery 0.38.0 → 0.40.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 (378) hide show
  1. package/dist/commands/agents.d.ts.map +1 -1
  2. package/dist/commands/agents.js +32 -8
  3. package/dist/commands/artifacts.d.ts.map +1 -1
  4. package/dist/commands/artifacts.js +97 -6
  5. package/dist/commands/backup.d.ts +16 -0
  6. package/dist/commands/backup.d.ts.map +1 -1
  7. package/dist/commands/backup.js +239 -33
  8. package/dist/commands/browse.d.ts +8 -0
  9. package/dist/commands/browse.d.ts.map +1 -1
  10. package/dist/commands/browse.js +466 -231
  11. package/dist/commands/diagnostics.d.ts.map +1 -1
  12. package/dist/commands/diagnostics.js +6 -3
  13. package/dist/commands/ledger-v3.d.ts.map +1 -1
  14. package/dist/commands/ledger-v3.js +20 -4
  15. package/dist/commands/qa-run.d.ts.map +1 -1
  16. package/dist/commands/qa-run.js +26 -3
  17. package/dist/commands/qa-status.d.ts.map +1 -1
  18. package/dist/commands/qa-status.js +7 -2
  19. package/dist/commands/resources.d.ts.map +1 -1
  20. package/dist/commands/resources.js +23 -3
  21. package/dist/commands/review-pack.d.ts.map +1 -1
  22. package/dist/commands/review-pack.js +98 -23
  23. package/dist/commands/tunnel.d.ts.map +1 -1
  24. package/dist/commands/tunnel.js +2 -2
  25. package/dist/core/adapters/profiles.d.ts +1 -1
  26. package/dist/core/agents/canonical-emit.d.ts +3 -2
  27. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  28. package/dist/core/agents/canonical-emit.js +2 -0
  29. package/dist/core/agents/cli.js +13 -6
  30. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  31. package/dist/core/agents/live-authority-v3.js +5 -3
  32. package/dist/core/agents/live-lifecycle-v3.d.ts +2 -2
  33. package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
  34. package/dist/core/agents/render/prompt-context.d.ts +7 -5
  35. package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
  36. package/dist/core/agents/render/prompt-context.js +63 -8
  37. package/dist/core/agents/session-finalizer-v3.d.ts +2 -2
  38. package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
  39. package/dist/core/agents/state/live-coordination-view.d.ts +3 -3
  40. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  41. package/dist/core/agents/state/live-coordination-view.js +2 -1
  42. package/dist/core/agents/state/names.d.ts +35 -2
  43. package/dist/core/agents/state/names.d.ts.map +1 -1
  44. package/dist/core/agents/state/names.js +80 -5
  45. package/dist/core/agents/state/stale-sweep.d.ts +2 -1
  46. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  47. package/dist/core/agents/state/stale-sweep.js +23 -6
  48. package/dist/core/agents/turn-elapsed.d.ts +51 -0
  49. package/dist/core/agents/turn-elapsed.d.ts.map +1 -0
  50. package/dist/core/agents/turn-elapsed.js +91 -0
  51. package/dist/core/artifacts/activity.d.ts +14 -0
  52. package/dist/core/artifacts/activity.d.ts.map +1 -0
  53. package/dist/core/artifacts/activity.js +52 -0
  54. package/dist/core/artifacts/delivery-card.d.ts +39 -0
  55. package/dist/core/artifacts/delivery-card.d.ts.map +1 -0
  56. package/dist/core/artifacts/delivery-card.js +282 -0
  57. package/dist/core/artifacts/index.d.ts +42 -7
  58. package/dist/core/artifacts/index.d.ts.map +1 -1
  59. package/dist/core/artifacts/index.js +288 -76
  60. package/dist/core/artifacts/mutation-lock.d.ts +2 -0
  61. package/dist/core/artifacts/mutation-lock.d.ts.map +1 -0
  62. package/dist/core/artifacts/mutation-lock.js +91 -0
  63. package/dist/core/backup/host-snapshot.d.ts +18 -0
  64. package/dist/core/backup/host-snapshot.d.ts.map +1 -0
  65. package/dist/core/backup/host-snapshot.js +64 -0
  66. package/dist/core/config.d.ts +20 -5
  67. package/dist/core/config.d.ts.map +1 -1
  68. package/dist/core/config.js +44 -10
  69. package/dist/core/diagnostics/advice.d.ts +38 -3
  70. package/dist/core/diagnostics/advice.d.ts.map +1 -1
  71. package/dist/core/diagnostics/advice.js +103 -99
  72. package/dist/core/diagnostics/bundle.d.ts.map +1 -1
  73. package/dist/core/diagnostics/bundle.js +111 -47
  74. package/dist/core/diagnostics/comparison.d.ts.map +1 -1
  75. package/dist/core/diagnostics/comparison.js +3 -2
  76. package/dist/core/diagnostics/contract.d.ts +15 -31
  77. package/dist/core/diagnostics/contract.d.ts.map +1 -1
  78. package/dist/core/diagnostics/contract.js +2 -5
  79. package/dist/core/diagnostics/index.d.ts +2 -0
  80. package/dist/core/diagnostics/index.d.ts.map +1 -1
  81. package/dist/core/diagnostics/index.js +2 -0
  82. package/dist/core/diagnostics/pressure-contract.d.ts +260 -0
  83. package/dist/core/diagnostics/pressure-contract.d.ts.map +1 -0
  84. package/dist/core/diagnostics/pressure-contract.js +70 -0
  85. package/dist/core/diagnostics/pressure.d.ts +25 -0
  86. package/dist/core/diagnostics/pressure.d.ts.map +1 -0
  87. package/dist/core/diagnostics/pressure.js +1138 -0
  88. package/dist/core/diagnostics/replay.d.ts.map +1 -1
  89. package/dist/core/diagnostics/replay.js +90 -10
  90. package/dist/core/events/v3/adapter-id.d.ts +6 -0
  91. package/dist/core/events/v3/adapter-id.d.ts.map +1 -0
  92. package/dist/core/events/v3/adapter-id.js +7 -0
  93. package/dist/core/events/v3/archive-retention.d.ts.map +1 -1
  94. package/dist/core/events/v3/archive-retention.js +3 -2
  95. package/dist/core/events/v3/bootstrap.d.ts +41 -4
  96. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  97. package/dist/core/events/v3/bootstrap.js +120 -17
  98. package/dist/core/events/v3/capabilities.d.ts +16 -9
  99. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  100. package/dist/core/events/v3/capabilities.js +37 -2
  101. package/dist/core/events/v3/capability-drift.d.ts +2 -2
  102. package/dist/core/events/v3/capability-drift.d.ts.map +1 -1
  103. package/dist/core/events/v3/control-witness.d.ts +48 -5
  104. package/dist/core/events/v3/control-witness.d.ts.map +1 -1
  105. package/dist/core/events/v3/control-witness.js +91 -36
  106. package/dist/core/events/v3/control.d.ts.map +1 -1
  107. package/dist/core/events/v3/control.js +22 -2
  108. package/dist/core/events/v3/index.d.ts +2 -1
  109. package/dist/core/events/v3/index.d.ts.map +1 -1
  110. package/dist/core/events/v3/index.js +2 -1
  111. package/dist/core/events/v3/live-feed.d.ts +7 -1
  112. package/dist/core/events/v3/live-feed.d.ts.map +1 -1
  113. package/dist/core/events/v3/live-feed.js +21 -3
  114. package/dist/core/events/v3/live-routing.d.ts.map +1 -1
  115. package/dist/core/events/v3/live-routing.js +10 -2
  116. package/dist/core/events/v3/producers/command-recorder.d.ts +2 -2
  117. package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
  118. package/dist/core/events/v3/producers/command-recorder.js +2 -1
  119. package/dist/core/events/v3/producers/coordination-recorder.d.ts +2 -2
  120. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  121. package/dist/core/events/v3/producers/coordination-recorder.js +2 -1
  122. package/dist/core/events/v3/producers/hook-base.d.ts +2 -2
  123. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  124. package/dist/core/events/v3/producers/hook-base.js +15 -5
  125. package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
  126. package/dist/core/events/v3/producers/hook.js +17 -4
  127. package/dist/core/events/v3/producers/intake.d.ts +4 -4
  128. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  129. package/dist/core/events/v3/producers/intake.js +3 -2
  130. package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -1
  131. package/dist/core/events/v3/producers/producer-state-observer.js +2 -1
  132. package/dist/core/events/v3/producers/recorder.d.ts +16 -5
  133. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  134. package/dist/core/events/v3/producers/recorder.js +31 -9
  135. package/dist/core/events/v3/reader.d.ts.map +1 -1
  136. package/dist/core/events/v3/reader.js +10 -13
  137. package/dist/core/events/v3/runtime-build.d.ts.map +1 -1
  138. package/dist/core/events/v3/runtime-build.js +3 -2
  139. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +2 -2
  140. package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
  141. package/dist/core/events/v3/turn-telemetry.d.ts +2 -2
  142. package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
  143. package/dist/core/hooks/adapter/output.d.ts +16 -14
  144. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  145. package/dist/core/hooks/adapter/output.js +36 -38
  146. package/dist/core/hooks/backup-schedule.d.ts +34 -0
  147. package/dist/core/hooks/backup-schedule.d.ts.map +1 -0
  148. package/dist/core/hooks/backup-schedule.js +114 -0
  149. package/dist/core/hooks/cli.js +61 -18
  150. package/dist/core/hooks/codex-wsl-bridge.d.ts +2 -0
  151. package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -1
  152. package/dist/core/hooks/codex-wsl-bridge.js +18 -4
  153. package/dist/core/hooks/index.d.ts +1 -0
  154. package/dist/core/hooks/index.d.ts.map +1 -1
  155. package/dist/core/hooks/index.js +1 -0
  156. package/dist/core/hooks/prompt-context/contract.d.ts +61 -0
  157. package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -0
  158. package/dist/core/hooks/prompt-context/contract.js +102 -0
  159. package/dist/core/hooks/prompt-context/index.d.ts +5 -0
  160. package/dist/core/hooks/prompt-context/index.d.ts.map +1 -0
  161. package/dist/core/hooks/prompt-context/index.js +2 -0
  162. package/dist/core/hooks/prompt-context/runner.d.ts +24 -0
  163. package/dist/core/hooks/prompt-context/runner.d.ts.map +1 -0
  164. package/dist/core/hooks/prompt-context/runner.js +249 -0
  165. package/dist/core/qa-artifacts.d.ts +3 -0
  166. package/dist/core/qa-artifacts.d.ts.map +1 -1
  167. package/dist/core/qa-artifacts.js +25 -3
  168. package/dist/core/resources/contract.d.ts +69 -3
  169. package/dist/core/resources/contract.d.ts.map +1 -1
  170. package/dist/core/resources/contract.js +1 -1
  171. package/dist/core/resources/index.d.ts +1 -0
  172. package/dist/core/resources/index.d.ts.map +1 -1
  173. package/dist/core/resources/index.js +1 -0
  174. package/dist/core/resources/native.d.ts +36 -0
  175. package/dist/core/resources/native.d.ts.map +1 -0
  176. package/dist/core/resources/native.js +418 -0
  177. package/dist/core/resources/sampler.d.ts +2 -0
  178. package/dist/core/resources/sampler.d.ts.map +1 -1
  179. package/dist/core/resources/sampler.js +31 -1
  180. package/dist/core/resources/status.d.ts +61 -0
  181. package/dist/core/resources/status.d.ts.map +1 -0
  182. package/dist/core/resources/status.js +536 -0
  183. package/dist/core/resources/system.d.ts +27 -0
  184. package/dist/core/resources/system.d.ts.map +1 -0
  185. package/dist/core/resources/system.js +439 -0
  186. package/dist/core/semantic/contract.d.ts +13 -13
  187. package/dist/core/semantic/service.d.ts +2 -0
  188. package/dist/core/semantic/service.d.ts.map +1 -1
  189. package/dist/core/semantic/service.js +27 -4
  190. package/dist/core/storage/builtins.js +41 -0
  191. package/dist/core/supervisor/contract.d.ts +41 -3
  192. package/dist/core/supervisor/contract.d.ts.map +1 -1
  193. package/dist/core/supervisor/contract.js +3 -2
  194. package/dist/core/supervisor/findings.d.ts +3 -0
  195. package/dist/core/supervisor/findings.d.ts.map +1 -1
  196. package/dist/core/supervisor/findings.js +88 -0
  197. package/dist/core/supervisor/history.d.ts.map +1 -1
  198. package/dist/core/supervisor/history.js +14 -0
  199. package/dist/core/supervisor/ledger-state.d.ts +55 -0
  200. package/dist/core/supervisor/ledger-state.d.ts.map +1 -0
  201. package/dist/core/supervisor/ledger-state.js +0 -0
  202. package/dist/core/supervisor/service.d.ts.map +1 -1
  203. package/dist/core/supervisor/service.js +120 -7
  204. package/dist/core/supervisor/storage.d.ts +3 -1
  205. package/dist/core/supervisor/storage.d.ts.map +1 -1
  206. package/dist/core/supervisor/storage.js +4 -0
  207. package/dist/core/workflow/admission.d.ts +3 -0
  208. package/dist/core/workflow/admission.d.ts.map +1 -1
  209. package/dist/core/workflow/admission.js +28 -16
  210. package/dist/core/workflow/engine.js +2 -2
  211. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  212. package/dist/core/workflow/live-session-v3.js +6 -1
  213. package/dist/core/workflow/proof.d.ts.map +1 -1
  214. package/dist/core/workflow/proof.js +4 -3
  215. package/dist/lib/browser/capture-fidelity.d.ts +7 -0
  216. package/dist/lib/browser/capture-fidelity.d.ts.map +1 -1
  217. package/dist/lib/browser/capture-fidelity.js +17 -0
  218. package/dist/lib/browser/client.d.ts +9 -0
  219. package/dist/lib/browser/client.d.ts.map +1 -1
  220. package/dist/lib/browser/client.js +85 -37
  221. package/dist/lib/browser/index.d.ts +3 -1
  222. package/dist/lib/browser/index.d.ts.map +1 -1
  223. package/dist/lib/browser/index.js +2 -1
  224. package/dist/lib/browser/page-review-budget.d.ts +13 -0
  225. package/dist/lib/browser/page-review-budget.d.ts.map +1 -0
  226. package/dist/lib/browser/page-review-budget.js +251 -0
  227. package/dist/lib/browser/page-review-contracts.d.ts +127 -0
  228. package/dist/lib/browser/page-review-contracts.d.ts.map +1 -0
  229. package/dist/lib/browser/page-review-contracts.js +5 -0
  230. package/dist/lib/browser/page-review-evidence.d.ts +48 -0
  231. package/dist/lib/browser/page-review-evidence.d.ts.map +1 -0
  232. package/dist/lib/browser/page-review-evidence.js +340 -0
  233. package/dist/lib/browser/page-review-judge.d.ts +1 -1
  234. package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
  235. package/dist/lib/browser/page-review-judge.js +46 -38
  236. package/dist/lib/browser/page-review-pack.d.ts +44 -22
  237. package/dist/lib/browser/page-review-pack.d.ts.map +1 -1
  238. package/dist/lib/browser/page-review-pack.js +116 -36
  239. package/dist/lib/browser/page-review-source.d.ts +12 -0
  240. package/dist/lib/browser/page-review-source.d.ts.map +1 -0
  241. package/dist/lib/browser/page-review-source.js +22 -0
  242. package/dist/lib/browser/qa-run-contracts.d.ts +35 -9
  243. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
  244. package/dist/lib/browser/qa-run-contracts.js +48 -14
  245. package/dist/lib/browser/qa-run.d.ts.map +1 -1
  246. package/dist/lib/browser/qa-run.js +215 -68
  247. package/dist/lib/browser/qa-snapshot.d.ts +6 -0
  248. package/dist/lib/browser/qa-snapshot.d.ts.map +1 -1
  249. package/dist/lib/browser/qa-snapshot.js +259 -48
  250. package/dist/lib/browser/review-capture-transaction.d.ts +13 -0
  251. package/dist/lib/browser/review-capture-transaction.d.ts.map +1 -0
  252. package/dist/lib/browser/review-capture-transaction.js +79 -0
  253. package/dist/lib/browser/standalone-html.d.ts.map +1 -1
  254. package/dist/lib/browser/standalone-html.js +4 -2
  255. package/dist/lib/browser/thumbnail-association.d.ts +34 -0
  256. package/dist/lib/browser/thumbnail-association.d.ts.map +1 -0
  257. package/dist/lib/browser/thumbnail-association.js +158 -0
  258. package/dist/lib/browser/tiling.d.ts +30 -0
  259. package/dist/lib/browser/tiling.d.ts.map +1 -1
  260. package/dist/lib/browser/tiling.js +38 -0
  261. package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
  262. package/dist/lib/docs-metadata-managed.js +4 -1
  263. package/dist/lib/identities/assume.d.ts.map +1 -1
  264. package/dist/lib/identities/assume.js +7 -1
  265. package/dist/lib/instructions/templates.d.ts.map +1 -1
  266. package/dist/lib/instructions/templates.js +1 -0
  267. package/dist/lib/local-file-url.d.ts +12 -0
  268. package/dist/lib/local-file-url.d.ts.map +1 -1
  269. package/dist/lib/local-file-url.js +16 -2
  270. package/dist/lib/tunnel/state.d.ts +19 -4
  271. package/dist/lib/tunnel/state.d.ts.map +1 -1
  272. package/dist/lib/tunnel/state.js +53 -13
  273. package/package.json +7 -4
  274. package/schemas/config.schema.json +69 -2
  275. package/src/commands/agents.ts +42 -9
  276. package/src/commands/artifacts.ts +130 -6
  277. package/src/commands/backup.ts +287 -34
  278. package/src/commands/browse.ts +564 -267
  279. package/src/commands/diagnostics.ts +6 -3
  280. package/src/commands/ledger-v3.ts +20 -3
  281. package/src/commands/qa-run.ts +37 -3
  282. package/src/commands/qa-status.ts +11 -2
  283. package/src/commands/resources.ts +23 -3
  284. package/src/commands/review-pack.ts +165 -62
  285. package/src/commands/tunnel.ts +2 -1
  286. package/src/core/agents/canonical-emit.ts +4 -2
  287. package/src/core/agents/cli.ts +14 -6
  288. package/src/core/agents/live-authority-v3.ts +7 -3
  289. package/src/core/agents/live-lifecycle-v3.ts +2 -2
  290. package/src/core/agents/render/prompt-context.ts +68 -14
  291. package/src/core/agents/session-finalizer-v3.ts +2 -2
  292. package/src/core/agents/state/live-coordination-view.ts +4 -4
  293. package/src/core/agents/state/names.ts +92 -7
  294. package/src/core/agents/state/stale-sweep.ts +22 -8
  295. package/src/core/agents/turn-elapsed.ts +135 -0
  296. package/src/core/artifacts/activity.ts +71 -0
  297. package/src/core/artifacts/delivery-card.ts +375 -0
  298. package/src/core/artifacts/index.ts +385 -91
  299. package/src/core/artifacts/mutation-lock.ts +106 -0
  300. package/src/core/backup/host-snapshot.ts +76 -0
  301. package/src/core/config.ts +66 -13
  302. package/src/core/diagnostics/advice.ts +148 -120
  303. package/src/core/diagnostics/bundle.ts +138 -52
  304. package/src/core/diagnostics/comparison.ts +6 -2
  305. package/src/core/diagnostics/contract.ts +39 -42
  306. package/src/core/diagnostics/index.ts +2 -0
  307. package/src/core/diagnostics/pressure-contract.ts +294 -0
  308. package/src/core/diagnostics/pressure.ts +1361 -0
  309. package/src/core/diagnostics/replay.ts +116 -11
  310. package/src/core/events/v3/adapter-id.ts +12 -0
  311. package/src/core/events/v3/archive-retention.ts +3 -6
  312. package/src/core/events/v3/bootstrap.ts +163 -16
  313. package/src/core/events/v3/capabilities.ts +75 -25
  314. package/src/core/events/v3/capability-drift.ts +2 -2
  315. package/src/core/events/v3/control-witness.ts +172 -41
  316. package/src/core/events/v3/control.ts +34 -2
  317. package/src/core/events/v3/index.ts +3 -0
  318. package/src/core/events/v3/live-feed.ts +23 -5
  319. package/src/core/events/v3/live-routing.ts +14 -2
  320. package/src/core/events/v3/producers/command-recorder.ts +4 -4
  321. package/src/core/events/v3/producers/coordination-recorder.ts +4 -4
  322. package/src/core/events/v3/producers/hook-base.ts +21 -16
  323. package/src/core/events/v3/producers/hook.ts +21 -4
  324. package/src/core/events/v3/producers/intake.ts +6 -6
  325. package/src/core/events/v3/producers/producer-state-observer.ts +2 -1
  326. package/src/core/events/v3/producers/recorder.ts +50 -21
  327. package/src/core/events/v3/reader.ts +14 -13
  328. package/src/core/events/v3/runtime-build.ts +3 -2
  329. package/src/core/events/v3/runtime-telemetry-capabilities.ts +3 -3
  330. package/src/core/events/v3/turn-telemetry.ts +4 -4
  331. package/src/core/hooks/adapter/output.ts +50 -36
  332. package/src/core/hooks/backup-schedule.ts +147 -0
  333. package/src/core/hooks/cli.ts +65 -14
  334. package/src/core/hooks/codex-wsl-bridge.ts +21 -5
  335. package/src/core/hooks/index.ts +1 -0
  336. package/src/core/hooks/prompt-context/contract.ts +177 -0
  337. package/src/core/hooks/prompt-context/index.ts +22 -0
  338. package/src/core/hooks/prompt-context/runner.ts +303 -0
  339. package/src/core/qa-artifacts.ts +29 -3
  340. package/src/core/resources/contract.ts +76 -3
  341. package/src/core/resources/index.ts +1 -0
  342. package/src/core/resources/native.ts +481 -0
  343. package/src/core/resources/sampler.ts +46 -1
  344. package/src/core/resources/status.ts +717 -0
  345. package/src/core/resources/system.ts +530 -0
  346. package/src/core/semantic/service.ts +37 -3
  347. package/src/core/storage/builtins.ts +41 -0
  348. package/src/core/supervisor/contract.ts +45 -3
  349. package/src/core/supervisor/findings.ts +159 -0
  350. package/src/core/supervisor/history.ts +15 -0
  351. package/src/core/supervisor/ledger-state.ts +0 -0
  352. package/src/core/supervisor/service.ts +133 -5
  353. package/src/core/supervisor/storage.ts +7 -0
  354. package/src/core/workflow/admission.ts +33 -17
  355. package/src/core/workflow/engine.ts +2 -2
  356. package/src/core/workflow/live-session-v3.ts +6 -8
  357. package/src/core/workflow/proof.ts +4 -3
  358. package/src/lib/browser/capture-fidelity.ts +23 -0
  359. package/src/lib/browser/client.ts +96 -44
  360. package/src/lib/browser/index.ts +15 -1
  361. package/src/lib/browser/page-review-budget.ts +309 -0
  362. package/src/lib/browser/page-review-contracts.ts +129 -0
  363. package/src/lib/browser/page-review-evidence.ts +465 -0
  364. package/src/lib/browser/page-review-judge.ts +56 -40
  365. package/src/lib/browser/page-review-pack.ts +181 -43
  366. package/src/lib/browser/page-review-source.ts +30 -0
  367. package/src/lib/browser/qa-run-contracts.ts +62 -18
  368. package/src/lib/browser/qa-run.ts +259 -71
  369. package/src/lib/browser/qa-snapshot.ts +289 -48
  370. package/src/lib/browser/review-capture-transaction.ts +106 -0
  371. package/src/lib/browser/standalone-html.ts +4 -2
  372. package/src/lib/browser/thumbnail-association.ts +190 -0
  373. package/src/lib/browser/tiling.ts +63 -0
  374. package/src/lib/docs-metadata-managed.ts +4 -1
  375. package/src/lib/identities/assume.ts +12 -4
  376. package/src/lib/instructions/templates.ts +1 -0
  377. package/src/lib/local-file-url.ts +17 -2
  378. package/src/lib/tunnel/state.ts +70 -13
@@ -1 +1 @@
1
- {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../../src/core/diagnostics/replay.ts"],"names":[],"mappings":"AA0BA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAE3B,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAEvB,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAErD;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,sBAAsB,EACpC,UAAU,EAAE,oBAAoB,GAC/B,kBAAkB,CAkBpB;AAED,qEAAqE;AACrE,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,sBAAsB,EACpC,UAAU,EAAE,oBAAoB,GAC/B,kBAAkB,CAiDpB"}
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../../src/core/diagnostics/replay.ts"],"names":[],"mappings":"AAgCA,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAE3B,KAAK,oBAAoB,EAC1B,MAAM,eAAe,CAAC;AAOvB,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAErD;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,sBAAsB,EACpC,UAAU,EAAE,oBAAoB,GAC/B,kBAAkB,CAkBpB;AAED,qEAAqE;AACrE,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,sBAAsB,EACpC,UAAU,EAAE,oBAAoB,GAC/B,kBAAkB,CAwDpB"}
@@ -5,8 +5,11 @@ import { explainSupervisorFinding } from "../supervisor/explanations.js";
5
5
  import { updateSupervisorFindings } from "../supervisor/findings.js";
6
6
  import { projectHookHealth } from "../supervisor/hook-health.js";
7
7
  import { buildSupervisorTimeline } from "../supervisor/timeline.js";
8
- import { buildDiagnosticAdvice } from "./advice.js";
8
+ import { buildDiagnosticAdvice, pressureHistoryFromSupervisor, unknownPressureAssessment, } from "./advice.js";
9
9
  import { DIAGNOSTIC_EXPECTED_SCHEMA_VERSION, } from "./contract.js";
10
+ import { assessPressure } from "./pressure.js";
11
+ const PRESSURE_SOURCE = "supervisor.pressure";
12
+ const FINDINGS_SOURCE = "supervisor.findings";
10
13
  export function canonicalJson(value) {
11
14
  return JSON.stringify(sortValue(value));
12
15
  }
@@ -19,7 +22,7 @@ export function deriveCapturedExpected(observations, thresholds) {
19
22
  const findings = filterFindings(findingsProjection(sourceValue(observations, "supervisor.findings")), selection);
20
23
  const coordination = sourceValue(observations, "coordination.health");
21
24
  const relatedSources = coordination?.recent_events ?? [];
22
- return expected(thresholds, selection, findings, findings.map((finding) => diagnosticTimeline(finding, relatedSources)), findings.map(explainSupervisorFinding), observations);
25
+ return expected(thresholds, selection, findings, findings.map((finding) => diagnosticTimeline(finding, relatedSources)), findings.map(explainSupervisorFinding), capturedAdvice(observations, findings));
23
26
  }
24
27
  /** Re-run the pure finding engine from frozen source inputs only. */
25
28
  export function replayDiagnosticInputs(observations, thresholds) {
@@ -27,7 +30,14 @@ export function replayDiagnosticInputs(observations, thresholds) {
27
30
  neutralResource(observations.captured_at);
28
31
  const supervisor = optionalSource(observations, "supervisor.snapshot") ??
29
32
  neutralSupervisor(observations.captured_at);
30
- const history = optionalSource(observations, "supervisor.history") ?? neutralHistory();
33
+ // A captured history is untrusted JSON from a bundle that may predate the
34
+ // current point shape. Reading it unchecked would let an older capture reach
35
+ // the trend projection with no pressure readings on its points. The live
36
+ // observer and the dashboard validate the same way.
37
+ const capturedHistory = optionalSource(observations, "supervisor.history");
38
+ const history = capturedHistory?.schema_version === SUPERVISOR_HISTORY_SCHEMA_VERSION
39
+ ? capturedHistory
40
+ : neutralHistory();
31
41
  const logFeed = optionalSource(observations, "supervisor.log-feed") ??
32
42
  neutralLogFeed(observations.captured_at);
33
43
  const hookHealth = projectHookHealth(logFeed, new Date(observations.captured_at));
@@ -55,7 +65,81 @@ export function replayDiagnosticInputs(observations, thresholds) {
55
65
  });
56
66
  const findings = filterFindings(findingsProjection(evaluated), observations.selection);
57
67
  const relatedSources = coordination?.recent_events ?? [];
58
- return expected(thresholds, observations.selection, findings, findings.map((finding) => diagnosticTimeline(finding, relatedSources)), findings.map(explainSupervisorFinding), observations);
68
+ return expected(thresholds, observations.selection, findings, findings.map((finding) => diagnosticTimeline(finding, relatedSources)), findings.map(explainSupervisorFinding), replayedAdvice(observations, resource, history, evaluated));
69
+ }
70
+ /**
71
+ * The live assessment, exactly as the observer published it. Nothing is
72
+ * recomputed here, because `expected.json` freezes what the machine actually
73
+ * reported at capture time.
74
+ */
75
+ function capturedAdvice(observations, findings) {
76
+ const record = optionalSource(observations, PRESSURE_SOURCE);
77
+ const capability = capturedSourceCapability(observations, PRESSURE_SOURCE);
78
+ if (!record?.assessment) {
79
+ return unavailableAdvice(observations.captured_at, capability);
80
+ }
81
+ return buildDiagnosticAdvice({
82
+ assessment: record.assessment,
83
+ priorHysteresis: record.prior_hysteresis ?? null,
84
+ sourceCapability: capability,
85
+ activeFindingCount: openedCount(findings),
86
+ evaluatedAt: observations.captured_at,
87
+ });
88
+ }
89
+ /**
90
+ * Recompute the assessment from frozen inputs. `prior_hysteresis` comes from
91
+ * the captured record, so a transition that depended on the previous sample is
92
+ * reproduced instead of restarting from a cold state.
93
+ */
94
+ function replayedAdvice(observations, resource, history, evaluated) {
95
+ const record = optionalSource(observations, PRESSURE_SOURCE);
96
+ const capability = capturedSourceCapability(observations, PRESSURE_SOURCE);
97
+ if (!record?.assessment) {
98
+ return unavailableAdvice(observations.captured_at, capability);
99
+ }
100
+ const snapshotAvailable = optionalSource(observations, "resources.snapshot");
101
+ const findingsCapability = capturedSourceCapability(observations, FINDINGS_SOURCE);
102
+ const active = [...evaluated.active, ...evaluated.transitions].filter((finding) => finding.state === "opened");
103
+ const assessment = assessPressure({
104
+ snapshot: snapshotAvailable ? resource : null,
105
+ snapshot_reason: snapshotAvailable ? null : "captured_source_unavailable",
106
+ history: pressureHistoryFromSupervisor(history.points),
107
+ findings: active,
108
+ findings_capability: {
109
+ source_kind: findingsCapability.source_kind,
110
+ state: findingsCapability.state,
111
+ ...(findingsCapability.reason_code ? { reason_code: findingsCapability.reason_code } : {}),
112
+ },
113
+ prior: record.prior_hysteresis ?? null,
114
+ observer_generation: record.observer_generation,
115
+ // Recover the observer's exact clock. `observed_at` is the sample instant
116
+ // and `sample_age_ms` is how far past it the observer read, so the sum is
117
+ // the original `now`, which staleness and the OOM hold both depend on.
118
+ now_ms: Date.parse(record.assessment.observed_at) + (record.assessment.sample_age_ms ?? 0),
119
+ });
120
+ return buildDiagnosticAdvice({
121
+ assessment,
122
+ priorHysteresis: record.prior_hysteresis ?? null,
123
+ sourceCapability: capability,
124
+ activeFindingCount: openedCount(filterFindings(findingsProjection(evaluated), observations.selection)),
125
+ evaluatedAt: observations.captured_at,
126
+ });
127
+ }
128
+ function unavailableAdvice(capturedAt, capability) {
129
+ return buildDiagnosticAdvice({
130
+ assessment: unknownPressureAssessment({
131
+ observedAt: capturedAt,
132
+ reasonCode: "evidence_unavailable",
133
+ summary: `Local resource pressure cannot be determined because the published assessment is ${capability.state}${capability.reason_code ? ` (${capability.reason_code})` : ""}.`,
134
+ }),
135
+ priorHysteresis: null,
136
+ sourceCapability: capability,
137
+ activeFindingCount: 0,
138
+ evaluatedAt: capturedAt,
139
+ });
140
+ }
141
+ function openedCount(findings) {
142
+ return findings.filter((finding) => finding.state === "opened").length;
59
143
  }
60
144
  function diagnosticTimeline(finding, relatedSources) {
61
145
  return buildSupervisorTimeline(finding, relatedSources.filter((source) => {
@@ -63,7 +147,7 @@ function diagnosticTimeline(finding, relatedSources) {
63
147
  return Number.isFinite(delta) && delta <= 5 * 60_000;
64
148
  }));
65
149
  }
66
- function expected(thresholds, selection, findings, timelines, explanations, observations) {
150
+ function expected(thresholds, selection, findings, timelines, explanations, advice) {
67
151
  return {
68
152
  schema_version: DIAGNOSTIC_EXPECTED_SCHEMA_VERSION,
69
153
  threshold_digest: sha256(canonicalJson(thresholds)),
@@ -71,11 +155,7 @@ function expected(thresholds, selection, findings, timelines, explanations, obse
71
155
  findings,
72
156
  timelines: [...timelines].sort((left, right) => left.finding_id.localeCompare(right.finding_id)),
73
157
  explanations: [...explanations].sort((left, right) => left.finding_id.localeCompare(right.finding_id)),
74
- advice: buildDiagnosticAdvice({
75
- findings,
76
- sourceCapability: capturedSourceCapability(observations, "supervisor.findings"),
77
- evaluatedAt: observations.captured_at,
78
- }),
158
+ advice,
79
159
  };
80
160
  }
81
161
  function capturedSourceCapability(observations, sourceKind) {
@@ -0,0 +1,6 @@
1
+ import type { Adapter } from "../../adapter.js";
2
+ /** Harness identities that may produce or describe Event Ledger V3 evidence. */
3
+ export type EventAdapterIdV3 = Adapter | "openclaw";
4
+ /** Canonical event-adapter census. Workflow launch adapters remain in core/adapter.ts. */
5
+ export declare const EVENT_ADAPTER_IDS_V3: readonly ["claude-code", "codex", "cursor", "openclaw"];
6
+ //# sourceMappingURL=adapter-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter-id.d.ts","sourceRoot":"","sources":["../../../../src/core/events/v3/adapter-id.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAEhD,gFAAgF;AAChF,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,UAAU,CAAC;AAEpD,0FAA0F;AAC1F,eAAO,MAAM,oBAAoB,yDAKe,CAAC"}
@@ -0,0 +1,7 @@
1
+ /** Canonical event-adapter census. Workflow launch adapters remain in core/adapter.ts. */
2
+ export const EVENT_ADAPTER_IDS_V3 = [
3
+ "claude-code",
4
+ "codex",
5
+ "cursor",
6
+ "openclaw",
7
+ ];
@@ -1 +1 @@
1
- {"version":3,"file":"archive-retention.d.ts","sourceRoot":"","sources":["../../../../src/core/events/v3/archive-retention.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAYrE,OAAO,EAEL,KAAK,wBAAwB,EAE9B,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,4BAA4B,GACpC,UAAU,GACV,SAAS,GACT,aAAa,GACb,mBAAmB,GACnB,WAAW,GACX,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,4BAA4B,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,6BAA6B;IAC5C,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAAO,GAC3D,mBAAmB,EAAE,CA4CvB;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAAO,GAC1E,mBAAmB,EAAE,CAqCvB;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAA;CAAO,GACxB,6BAA6B,CAgC/B"}
1
+ {"version":3,"file":"archive-retention.d.ts","sourceRoot":"","sources":["../../../../src/core/events/v3/archive-retention.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAYrE,OAAO,EAAE,KAAK,wBAAwB,EAA4B,MAAM,iBAAiB,CAAC;AAE1F,MAAM,MAAM,4BAA4B,GACpC,UAAU,GACV,SAAS,GACT,aAAa,GACb,mBAAmB,GACnB,WAAW,GACX,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,4BAA4B,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAAC;IAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,6BAA6B;IAC5C,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAAO,GAC3D,mBAAmB,EAAE,CA4CvB;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,wBAAwB,CAAA;CAAO,GAC1E,mBAAmB,EAAE,CAqCvB;AAED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,IAAI,CAAA;CAAO,GACxB,6BAA6B,CAiC/B"}
@@ -1,7 +1,7 @@
1
1
  /** Bounded retention for complete, closed Event Ledger V3 epochs. */
2
2
  import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
3
3
  import { basename, join, relative, resolve } from "node:path";
4
- import { artifactAutoCleanIntervalHours, eventLedgerArchivePolicy, } from "../../config.js";
4
+ import { eventLedgerArchivePolicy } from "../../config.js";
5
5
  const ARCHIVE_PATTERN = /^epoch-[0-9]+(?:-[0-9]+)?$/;
6
6
  const AUTO_CLEAN_STAMP = ".harnery/event-v3-archive-auto-clean.json";
7
7
  export function eventV3ArchivesRoot(repoRoot) {
@@ -95,7 +95,8 @@ export function autoCleanEventV3Archives(repoRoot, opts = {}) {
95
95
  if (!policy.autoClean)
96
96
  return { ran: false, reason: "disabled", deleted: 0, bytes: 0 };
97
97
  const stampPath = join(resolve(repoRoot), AUTO_CLEAN_STAMP);
98
- const intervalMs = artifactAutoCleanIntervalHours() * 60 * 60 * 1000;
98
+ // Archive cleanup remains daily, independent of short-lived working files.
99
+ const intervalMs = 24 * 60 * 60 * 1000;
99
100
  try {
100
101
  const stamp = JSON.parse(readFileSync(stampPath, "utf8"));
101
102
  const last = Date.parse(stamp.last_run_at ?? "");
@@ -6,6 +6,16 @@ export interface InitializeEventLedgerV3Input {
6
6
  configDigest: `sha256:${string}`;
7
7
  approvalRecordId: string;
8
8
  forceNewEpoch?: boolean;
9
+ /**
10
+ * Activate a candidate epoch that was already created for this root.
11
+ *
12
+ * Unset, this activates a candidate that carries this initializer's producer
13
+ * identity and refuses every other one. Creation and activation are one
14
+ * locked step here, so such a candidate is the residue of a crash or a
15
+ * failed activation, never work in progress; a candidate from another
16
+ * producer is a deliberate cutover state. Set it explicitly to force either
17
+ * answer.
18
+ */
9
19
  resumeCandidate?: boolean;
10
20
  now?: () => Date;
11
21
  }
@@ -44,6 +54,30 @@ export declare function initializeEventLedgerV3(input: InitializeEventLedgerV3In
44
54
  * explicit recovery command.
45
55
  */
46
56
  export declare function refreshIncompatibleEventLedgerV3(coordRoot: string): RefreshIncompatibleEventLedgerV3Result;
57
+ export interface RepairStrandedEventLedgerV3CandidateResult {
58
+ state: "repaired" | "not_stranded" | "unavailable";
59
+ reason?: string;
60
+ control: EventV3ControlState;
61
+ }
62
+ /** The approval record every automatic stranded-candidate repair is bound to. */
63
+ export declare const EVENT_V3_STRANDED_CANDIDATE_APPROVAL_RECORD_ID: "harnery-runtime-v3-stranded-candidate";
64
+ /**
65
+ * Complete an epoch that was created but never activated.
66
+ *
67
+ * This initializer creates a candidate and activates it inside one lease, so a
68
+ * candidate carrying its producer identity is residue: some process published
69
+ * the genesis and died or failed before publishing the activation, and every
70
+ * hook afterwards served that half-built epoch with a candidate-only write
71
+ * gate. Finishing it is a repair, not a decision, and it is exactly as safe as
72
+ * the creation it completes: the same lease serializes it, the activation is
73
+ * derived from the immutable candidate packet, and no ledger row is edited or
74
+ * synthesized.
75
+ *
76
+ * A candidate from any other producer is a deliberate cutover state and is
77
+ * left untouched. A live bootstrap lease makes this a no-op rather than a
78
+ * failure, so the next boundary retries.
79
+ */
80
+ export declare function repairStrandedEventLedgerV3Candidate(coordRoot: string): RepairStrandedEventLedgerV3CandidateResult;
47
81
  export interface RotateOversizedEventLedgerV3Result {
48
82
  state: "rotated" | "not_oversized" | "not_active" | "disabled";
49
83
  active_bytes: number;
@@ -62,10 +96,13 @@ export interface RotateOversizedEventLedgerV3Result {
62
96
  * (events, spool, producer states, manifests) moves whole into the V3
63
97
  * archive, live sessions re-onboard into the new epoch on their next signal,
64
98
  * and the writer's epoch fence keeps in-flight producers of the old epoch
65
- * from ever committing into the new one. Only a currently valid, active
66
- * ledger rotates; integrity failures stay closed for the explicit recovery
67
- * command. The threshold comes from the isolated Event V3 config resolver
68
- * unless the caller pins one; a non-positive threshold disables rotation.
99
+ * from ever committing into the new one. A candidate epoch rotates on the same
100
+ * terms as an active one: its control pair is valid, every reader still
101
+ * validates all of its history, and refusing to bound it is how a stranded
102
+ * epoch grew to 100 MB. Integrity failures stay closed for the explicit
103
+ * recovery command. The threshold comes from the isolated Event V3 config
104
+ * resolver unless the caller pins one; a non-positive threshold disables
105
+ * rotation.
69
106
  */
70
107
  export declare function rotateOversizedEventLedgerV3(coordRoot: string, options?: {
71
108
  thresholdBytes?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../../src/core/events/v3/bootstrap.ts"],"names":[],"mappings":"AAoBA,OAAO,EAML,KAAK,mBAAmB,EAEzB,MAAM,cAAc,CAAC;AAStB,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,UAAU,MAAM,EAAE,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,QAAQ,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,sCAAsC;IACrD,KAAK,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CAC5D;AAOD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,gBAAgB,SAAiC,GAChD,OAAO,CAAC,mBAAmB,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC,CAenD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,4BAA4B,GAClC,6BAA6B,CAE/B;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,MAAM,GAChB,sCAAsC,CAgCxC;AAED,MAAM,WAAW,kCAAkC;IACjD,KAAK,EAAE,SAAS,GAAG,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CAC7D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,kCAAkC,CA8DpC"}
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../../src/core/events/v3/bootstrap.ts"],"names":[],"mappings":"AAsBA,OAAO,EAOL,KAAK,mBAAmB,EAEzB,MAAM,cAAc,CAAC;AAStB,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,UAAU,MAAM,EAAE,CAAC;IACjC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE,QAAQ,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,sCAAsC;IACrD,KAAK,EAAE,SAAS,GAAG,WAAW,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CAC5D;AAkBD;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,gBAAgB,SAAiC,GAChD,OAAO,CAAC,mBAAmB,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC,CAenD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,4BAA4B,GAClC,6BAA6B,CAE/B;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,MAAM,GAChB,sCAAsC,CAgCxC;AAED,MAAM,WAAW,0CAA0C;IACzD,KAAK,EAAE,UAAU,GAAG,cAAc,GAAG,aAAa,CAAC;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,mBAAmB,CAAC;CAC9B;AAED,iFAAiF;AACjF,eAAO,MAAM,8CAA8C,EACzD,uCAAgD,CAAC;AAEnD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oCAAoC,CAClD,SAAS,EAAE,MAAM,GAChB,0CAA0C,CA6B5C;AAWD,MAAM,WAAW,kCAAkC;IACjD,KAAK,EAAE,SAAS,GAAG,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,EAAE;QAAE,KAAK,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,kCAAkC,CA8DpC"}
@@ -1,8 +1,9 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
- import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, statSync, writeFileSync, } from "node:fs";
3
+ import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
4
4
  import { hostname } from "node:os";
5
5
  import { dirname, join, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
6
7
  import { fsyncParentDirectory } from "../../workflow/durable-record.js";
7
8
  import { acquireNoClobberLease } from "../../workflow/workspaces/leases.js";
8
9
  import { canonicalJsonV3, sha256V3 } from "./canonical.js";
@@ -15,6 +16,16 @@ import { reanchorArchivedHookProducersV3 } from "./producers/recorder.js";
15
16
  import { resolveEventLedgerRotateActiveBytesV3 } from "./rotation-config.js";
16
17
  import { currentHarneryRuntimeBuild, liveEventV3BuildId, livePlatformV3 } from "./runtime-build.js";
17
18
  import { drainReadyEventsV3 } from "./writer.js";
19
+ /**
20
+ * The control producer every epoch created by this initializer carries.
21
+ *
22
+ * It separates a stranded epoch from a deliberate one. A candidate minted here
23
+ * was always meant to be activated in the same locked step, so finishing it is
24
+ * a repair. A candidate published by any other producer (an operator cutover or
25
+ * rollback rehearsal) is a state someone chose, and automatic activation would
26
+ * overrule them.
27
+ */
28
+ const BOOTSTRAP_CONTROL_PRODUCER_ID = "prd_harnery-init";
18
29
  const BOOTSTRAP_LEASE_RETRIES = 12;
19
30
  const BOOTSTRAP_LEASE_RETRY_MS = 25;
20
31
  const BOOTSTRAP_LEASE_STALE_MS = 10_000;
@@ -84,6 +95,56 @@ export function refreshIncompatibleEventLedgerV3(coordRoot) {
84
95
  };
85
96
  });
86
97
  }
98
+ /** The approval record every automatic stranded-candidate repair is bound to. */
99
+ export const EVENT_V3_STRANDED_CANDIDATE_APPROVAL_RECORD_ID = "harnery-runtime-v3-stranded-candidate";
100
+ /**
101
+ * Complete an epoch that was created but never activated.
102
+ *
103
+ * This initializer creates a candidate and activates it inside one lease, so a
104
+ * candidate carrying its producer identity is residue: some process published
105
+ * the genesis and died or failed before publishing the activation, and every
106
+ * hook afterwards served that half-built epoch with a candidate-only write
107
+ * gate. Finishing it is a repair, not a decision, and it is exactly as safe as
108
+ * the creation it completes: the same lease serializes it, the activation is
109
+ * derived from the immutable candidate packet, and no ledger row is edited or
110
+ * synthesized.
111
+ *
112
+ * A candidate from any other producer is a deliberate cutover state and is
113
+ * left untouched. A live bootstrap lease makes this a no-op rather than a
114
+ * failure, so the next boundary retries.
115
+ */
116
+ export function repairStrandedEventLedgerV3Candidate(coordRoot) {
117
+ const root = resolve(coordRoot);
118
+ const observed = readEventV3ControlState(root);
119
+ const deliberateCandidate = observed.state === "candidate";
120
+ if (!strandedBootstrapCandidate(observed)) {
121
+ return {
122
+ state: "not_stranded",
123
+ control: observed,
124
+ ...(deliberateCandidate ? { reason: "candidate_not_bootstrap_created" } : {}),
125
+ };
126
+ }
127
+ try {
128
+ return withBootstrapLease(root, () => {
129
+ const current = readEventV3ControlState(root);
130
+ if (!strandedBootstrapCandidate(current))
131
+ return { state: "not_stranded", control: current };
132
+ const activated = activateCandidateEpoch(root, current.genesis, EVENT_V3_STRANDED_CANDIDATE_APPROVAL_RECORD_ID);
133
+ return { state: "repaired", control: activated.control };
134
+ });
135
+ }
136
+ catch (error) {
137
+ return {
138
+ state: "unavailable",
139
+ reason: error instanceof Error ? error.message : String(error),
140
+ control: observed,
141
+ };
142
+ }
143
+ }
144
+ function strandedBootstrapCandidate(control) {
145
+ return (control.state === "candidate" &&
146
+ control.genesis.event.producer.producer_id === BOOTSTRAP_CONTROL_PRODUCER_ID);
147
+ }
87
148
  /**
88
149
  * Archive a valid oversized epoch intact and start a fresh one.
89
150
  *
@@ -93,10 +154,13 @@ export function refreshIncompatibleEventLedgerV3(coordRoot) {
93
154
  * (events, spool, producer states, manifests) moves whole into the V3
94
155
  * archive, live sessions re-onboard into the new epoch on their next signal,
95
156
  * and the writer's epoch fence keeps in-flight producers of the old epoch
96
- * from ever committing into the new one. Only a currently valid, active
97
- * ledger rotates; integrity failures stay closed for the explicit recovery
98
- * command. The threshold comes from the isolated Event V3 config resolver
99
- * unless the caller pins one; a non-positive threshold disables rotation.
157
+ * from ever committing into the new one. A candidate epoch rotates on the same
158
+ * terms as an active one: its control pair is valid, every reader still
159
+ * validates all of its history, and refusing to bound it is how a stranded
160
+ * epoch grew to 100 MB. Integrity failures stay closed for the explicit
161
+ * recovery command. The threshold comes from the isolated Event V3 config
162
+ * resolver unless the caller pins one; a non-positive threshold disables
163
+ * rotation.
100
164
  */
101
165
  export function rotateOversizedEventLedgerV3(coordRoot, options = {}) {
102
166
  const root = resolve(coordRoot);
@@ -122,7 +186,7 @@ export function rotateOversizedEventLedgerV3(coordRoot, options = {}) {
122
186
  return { state: "not_oversized", active_bytes: activeBytes, threshold_bytes: threshold };
123
187
  }
124
188
  const current = readEventV3ControlState(root);
125
- if (current.state !== "active") {
189
+ if (current.state !== "active" && current.state !== "candidate") {
126
190
  return { state: "not_active", active_bytes: activeBytes, threshold_bytes: threshold };
127
191
  }
128
192
  // Flush durable ready rows into the epoch they were produced for, so the
@@ -164,13 +228,14 @@ export function rotateOversizedEventLedgerV3(coordRoot, options = {}) {
164
228
  function initializeEventLedgerV3Locked(input) {
165
229
  const root = resolve(input.coordRoot);
166
230
  let current = readEventV3ControlState(root);
167
- if (input.resumeCandidate && current.state === "repairable") {
231
+ const resumeCandidate = input.resumeCandidate ?? strandedBootstrapCandidate(current);
232
+ if (resumeCandidate && current.state === "repairable") {
168
233
  current = repairEventV3ControlPair(root);
169
234
  }
170
235
  if (!input.forceNewEpoch && current.state === "active") {
171
236
  return { state: "active", initialized: false, control: current };
172
237
  }
173
- if (!input.forceNewEpoch && input.resumeCandidate && current.state === "candidate") {
238
+ if (!input.forceNewEpoch && resumeCandidate && current.state === "candidate") {
174
239
  return activateCandidateEpoch(root, current.genesis, input.approvalRecordId);
175
240
  }
176
241
  if (!input.forceNewEpoch && current.state === "candidate") {
@@ -178,11 +243,10 @@ function initializeEventLedgerV3Locked(input) {
178
243
  }
179
244
  const now = input.now ?? (() => new Date());
180
245
  const createdAt = now().toISOString();
181
- const archivedEpoch = archiveCurrentEpoch(root, createdAt);
182
246
  const keys = loadOrCreateFingerprintKeyStoreV3(root, now);
183
247
  const harneryBuild = safeBuild(input.harneryBuild);
184
248
  const hostBuild = safeBuild(input.hostBuild);
185
- const producerId = "prd_harnery-init";
249
+ const producerId = BOOTSTRAP_CONTROL_PRODUCER_ID;
186
250
  const bootId = `boot_${createHash("sha256").update(`${root}\0${createdAt}`).digest("hex")}`;
187
251
  const buildId = liveEventV3BuildId(harneryBuild);
188
252
  const rootId = `root_${createHash("sha256").update(root).digest("hex")}`;
@@ -214,17 +278,35 @@ function initializeEventLedgerV3Locked(input) {
214
278
  platform: livePlatformV3(),
215
279
  },
216
280
  });
281
+ // Mint the complete control pair before any epoch bytes move. Every approval
282
+ // and validation failure then happens while the current epoch is still
283
+ // whole, so it can never leave a replaced epoch stranded in candidate state.
284
+ const activation = buildActivationManifestV3(activationInput(candidate, input.approvalRecordId));
285
+ const archivedEpoch = archiveCurrentEpoch(root, createdAt);
217
286
  publishControlFile(join(root, EVENT_V3_GENESIS_MANIFEST), candidate);
218
- const candidateState = repairEventV3ControlPair(root);
219
- if (candidateState.state !== "candidate") {
220
- throw new Error(`event_v3_candidate_initialization_failed:${candidateState.state}`);
287
+ let activated;
288
+ try {
289
+ activated = completeCandidateActivation(root, activation);
290
+ }
291
+ catch (error) {
292
+ // The epoch has already been replaced, so returning here would strand it.
293
+ // Retry the completion inside the same lease and, failing that, name the
294
+ // stranded epoch rather than reporting a successful initialization.
295
+ activated = completeStrandedCandidateActivation(root, activation, error);
221
296
  }
222
- const activated = activateCandidateEpoch(root, candidate, input.approvalRecordId);
223
297
  return {
224
298
  ...activated,
225
299
  ...(archivedEpoch ? { archived_epoch: archivedEpoch } : {}),
226
300
  };
227
301
  }
302
+ function completeStrandedCandidateActivation(root, activation, cause) {
303
+ try {
304
+ return completeCandidateActivation(root, activation);
305
+ }
306
+ catch {
307
+ throw new Error(`event_v3_epoch_stranded_before_activation:${cause instanceof Error ? cause.message : String(cause)}`);
308
+ }
309
+ }
228
310
  function runtimeCapabilityProfileCurrent(control) {
229
311
  const expected = Object.values(ADAPTER_CAPABILITY_PROFILES_V3).map((profile) => sha256V3(canonicalJsonV3(profile)));
230
312
  const approved = control.genesis.profile.adapter_capability_profile_digests;
@@ -275,8 +357,12 @@ function pidIsAlive(pid) {
275
357
  }
276
358
  }
277
359
  function activateCandidateEpoch(root, candidate, approvalRecordId) {
360
+ return completeCandidateActivation(root, buildActivationManifestV3(activationInput(candidate, approvalRecordId)));
361
+ }
362
+ /** The activation packet one exact candidate deserves, derived and pure. */
363
+ function activationInput(candidate, approvalRecordId) {
278
364
  const producer = candidate.event.producer;
279
- const activation = buildActivationManifestV3({
365
+ return {
280
366
  candidate,
281
367
  approval_record_id: approvalRecordId,
282
368
  activation_approved_at: candidate.profile.candidate_created_at,
@@ -288,7 +374,19 @@ function activateCandidateEpoch(root, candidate, approvalRecordId) {
288
374
  platform: producer.platform,
289
375
  ...(producer.bridge ? { bridge: producer.bridge } : {}),
290
376
  },
291
- });
377
+ };
378
+ }
379
+ /**
380
+ * Bring a published candidate to active: append the pre-minted genesis event
381
+ * if a crash left it missing, publish the activation manifest, then append its
382
+ * pre-minted event. Every step is idempotent, so the caller may retry it, and
383
+ * anything short of `active` throws with the state that blocked it.
384
+ */
385
+ function completeCandidateActivation(root, activation) {
386
+ const candidateState = repairEventV3ControlPair(root);
387
+ if (candidateState.state !== "candidate") {
388
+ throw new Error(`event_v3_candidate_initialization_failed:${candidateState.state}`);
389
+ }
292
390
  publishControlFile(join(root, EVENT_V3_ACTIVATION_MANIFEST), activation);
293
391
  const active = repairEventV3ControlPair(root);
294
392
  if (active.state !== "active") {
@@ -314,6 +412,11 @@ function archiveCurrentEpoch(root, createdAt) {
314
412
  function publishControlFile(path, value) {
315
413
  mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
316
414
  const temp = `${path}.tmp.${process.pid}`;
415
+ // A prior failed publish by this same pid would otherwise make every retry
416
+ // fail on the exclusive create, which is exactly how one transient error
417
+ // turns into a permanently stranded epoch.
418
+ if (existsSync(temp))
419
+ unlinkSync(temp);
317
420
  const fd = openSync(temp, "wx", 0o600);
318
421
  try {
319
422
  writeFileSync(fd, `${canonicalJsonV3(value)}\n`, "utf8");
@@ -335,7 +438,7 @@ function safeBuild(value) {
335
438
  .digest("hex");
336
439
  }
337
440
  function rootOfHarnery() {
338
- return resolve(import.meta.dir, "../../../..");
441
+ return resolve(dirname(fileURLToPath(import.meta.url)), "../../../..");
339
442
  }
340
443
  function repositoryBuild(root) {
341
444
  const result = spawnSync("git", ["-C", root, "rev-parse", "HEAD"], {
@@ -1,5 +1,6 @@
1
- import type { Adapter } from "../../adapter.js";
1
+ import type { EventAdapterIdV3 } from "./adapter-id.js";
2
2
  export type CapabilitySupportV3 = "native" | "derived" | "conditional" | "unsupported";
3
+ export type AdapterDurationCapabilityV3 = "turn_duration" | "tool_duration";
3
4
  export type CursorExecutionModeV3 = "local" | "cloud" | "unknown";
4
5
  export type AdapterWaitKindV3 = "permission" | "needs_input" | "decision" | "approval" | "scheduled" | "rate_limit" | "unknown";
5
6
  export declare const ADAPTER_WAIT_KINDS_V3: readonly AdapterWaitKindV3[];
@@ -12,27 +13,33 @@ export type AdapterSignalV3 = BaseAdapterSignalV3 | "model_usage" | "inference_t
12
13
  export interface AdapterCapabilityProfileV3 {
13
14
  format: "harnery-v3-adapter-capabilities";
14
15
  format_version: 1;
15
- adapter: Adapter;
16
+ adapter: EventAdapterIdV3;
16
17
  signals: Record<AdapterSignalV3, CapabilitySupportV3>;
17
18
  }
18
- export declare const ADAPTER_CAPABILITY_PROFILES_V3: Record<Adapter, AdapterCapabilityProfileV3>;
19
- export declare function adapterCapabilityProfileV3(adapter: Adapter): AdapterCapabilityProfileV3;
20
- export declare function adapterCapabilityProfileDigestV3(adapter: Adapter): `cap_${string}`;
21
- export declare function adapterSignalSupportV3(adapter: Adapter, signal: AdapterSignalV3): CapabilitySupportV3;
19
+ export declare const ADAPTER_CAPABILITY_PROFILES_V3: Record<EventAdapterIdV3, AdapterCapabilityProfileV3>;
20
+ export declare function adapterCapabilityProfileV3(adapter: EventAdapterIdV3): AdapterCapabilityProfileV3;
21
+ export declare function adapterCapabilityProfileDigestV3(adapter: EventAdapterIdV3): `cap_${string}`;
22
+ export declare function adapterSignalSupportV3(adapter: EventAdapterIdV3, signal: AdapterSignalV3): CapabilitySupportV3;
23
+ /**
24
+ * Duration support for terminal spans. Tool duration is part of the digested
25
+ * adapter profile. Turn duration predates that profile dimension, so keep its
26
+ * compatibility-preserving classification here until the next contract major.
27
+ */
28
+ export declare function adapterDurationSupportV3(adapter: EventAdapterIdV3, capability: AdapterDurationCapabilityV3): CapabilitySupportV3;
22
29
  /**
23
30
  * Adapter hooks only expose permission waits today. Other wait kinds can be
24
31
  * authored by coordination producers, but they are not observable from an
25
32
  * adapter's native turn channel.
26
33
  */
27
- export declare function adapterWaitKindSupportV3(adapter: Adapter, kind: AdapterWaitKindV3): CapabilitySupportV3;
34
+ export declare function adapterWaitKindSupportV3(adapter: EventAdapterIdV3, kind: AdapterWaitKindV3): CapabilitySupportV3;
28
35
  /** No current adapter supplies an independent completed-turn wait aggregate. */
29
- export declare function adapterTurnWaitCountSupportV3(_adapter: Adapter): CapabilitySupportV3;
36
+ export declare function adapterTurnWaitCountSupportV3(_adapter: EventAdapterIdV3): CapabilitySupportV3;
30
37
  /**
31
38
  * Per-kind wait matrix for native adapter turns. Span delivery and independent
32
39
  * completed-turn completeness are deliberately separate: observing a span
33
40
  * never proves that an absent span means zero.
34
41
  */
35
- export declare function adapterWaitCoverageMatrixV3(adapter: Adapter): Record<AdapterWaitKindV3, WaitKindCapabilityV3>;
42
+ export declare function adapterWaitCoverageMatrixV3(adapter: EventAdapterIdV3): Record<AdapterWaitKindV3, WaitKindCapabilityV3>;
36
43
  /**
37
44
  * Local Cursor sessions expose the generic tool channel. Cloud/private-worker
38
45
  * sessions cannot guarantee whole-turn delivery because hooks may start only
@@ -1 +1 @@
1
- {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../../src/core/events/v3/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGhD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,CAAC;AAEvF,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;AAElE,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,aAAa,GACb,UAAU,GACV,UAAU,GACV,WAAW,GACX,YAAY,GACZ,SAAS,CAAC;AAEd,eAAO,MAAM,qBAAqB,EAAE,SAAS,iBAAiB,EAQpD,CAAC;AAEX,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,mBAAmB,CAAC;IACnC,iBAAiB,EAAE,mBAAmB,CAAC;CACxC;AAED,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,aAAa,GACb,QAAQ,GACR,SAAS,GACT,iBAAiB,GACjB,sBAAsB,GACtB,cAAc,GACd,aAAa,GACb,cAAc,GACd,cAAc,GACd,eAAe,GACf,YAAY,GACZ,UAAU,GACV,OAAO,GACP,gBAAgB,GAChB,iBAAiB,GACjB,eAAe,GACf,gBAAgB,CAAC;AAErB,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,aAAa,GACb,kBAAkB,GAClB,gBAAgB,GAChB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,iCAAiC,CAAC;IAC1C,cAAc,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;CACvD;AAoED,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,OAAO,EAAE,0BAA0B,CAatF,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,0BAA0B,CAEvF;AAED,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,MAAM,EAAE,CAElF;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,eAAe,GACtB,mBAAmB,CAErB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,iBAAiB,GACtB,mBAAmB,CAErB;AAED,gFAAgF;AAChF,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,OAAO,GAAG,mBAAmB,CAEpF;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,GACf,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAUjD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,qBAAqB,GAAG,mBAAmB,CAI3F"}
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../../src/core/events/v3/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,CAAC;AAEvF,MAAM,MAAM,2BAA2B,GAAG,eAAe,GAAG,eAAe,CAAC;AAE5E,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;AAElE,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,aAAa,GACb,UAAU,GACV,UAAU,GACV,WAAW,GACX,YAAY,GACZ,SAAS,CAAC;AAEd,eAAO,MAAM,qBAAqB,EAAE,SAAS,iBAAiB,EAQpD,CAAC;AAEX,MAAM,WAAW,oBAAoB;IACnC,aAAa,EAAE,mBAAmB,CAAC;IACnC,iBAAiB,EAAE,mBAAmB,CAAC;CACxC;AAED,MAAM,MAAM,mBAAmB,GAC3B,eAAe,GACf,aAAa,GACb,QAAQ,GACR,SAAS,GACT,iBAAiB,GACjB,sBAAsB,GACtB,cAAc,GACd,aAAa,GACb,cAAc,GACd,cAAc,GACd,eAAe,GACf,YAAY,GACZ,UAAU,GACV,OAAO,GACP,gBAAgB,GAChB,iBAAiB,GACjB,eAAe,GACf,gBAAgB,CAAC;AAErB,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,aAAa,GACb,kBAAkB,GAClB,gBAAgB,GAChB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,iCAAiC,CAAC;IAC1C,cAAc,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAC;CACvD;AA4FD,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,gBAAgB,EAAE,0BAA0B,CAsB7F,CAAC;AAEJ,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,gBAAgB,GAAG,0BAA0B,CAEhG;AAED,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,MAAM,EAAE,CAE3F;AAED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EACzB,MAAM,EAAE,eAAe,GACtB,mBAAmB,CAErB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EACzB,UAAU,EAAE,2BAA2B,GACtC,mBAAmB,CAKrB;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,iBAAiB,GACtB,mBAAmB,CAErB;AAED,gFAAgF;AAChF,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,gBAAgB,GAAG,mBAAmB,CAE7F;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAUjD;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,qBAAqB,GAAG,mBAAmB,CAI3F"}
@@ -54,8 +54,28 @@ const BASE_SIGNAL_SUPPORT = {
54
54
  post_compaction: "unsupported",
55
55
  context_usage: "conditional",
56
56
  },
57
+ openclaw: {
58
+ session_start: "conditional",
59
+ session_end: "native",
60
+ prompt: "native",
61
+ turn_id: "native",
62
+ turn_completion: "native",
63
+ assistant_reply_text: "unsupported",
64
+ tool_request: "native",
65
+ tool_result: "native",
66
+ tool_failure: "conditional",
67
+ tool_call_id: "native",
68
+ tool_duration: "unsupported",
69
+ permission: "unsupported",
70
+ subagent: "unsupported",
71
+ shell: "native",
72
+ pre_compaction: "unsupported",
73
+ post_compaction: "unsupported",
74
+ context_usage: "unsupported",
75
+ model_identity: "unsupported",
76
+ },
57
77
  };
58
- function profile(adapter, economics) {
78
+ function profile(adapter, economics, harnessTiming = "derived") {
59
79
  return {
60
80
  format: "harnery-v3-adapter-capabilities",
61
81
  format_version: 1,
@@ -63,7 +83,7 @@ function profile(adapter, economics) {
63
83
  signals: {
64
84
  ...BASE_SIGNAL_SUPPORT[adapter],
65
85
  ...economics,
66
- harness_timing: "derived",
86
+ harness_timing: harnessTiming,
67
87
  capability_drift: "derived",
68
88
  },
69
89
  };
@@ -81,6 +101,10 @@ export const ADAPTER_CAPABILITY_PROFILES_V3 = {
81
101
  model_usage: "unsupported",
82
102
  inference_timing: "unsupported",
83
103
  }),
104
+ openclaw: profile("openclaw", {
105
+ model_usage: "unsupported",
106
+ inference_timing: "unsupported",
107
+ }, "unsupported"),
84
108
  };
85
109
  export function adapterCapabilityProfileV3(adapter) {
86
110
  return ADAPTER_CAPABILITY_PROFILES_V3[adapter];
@@ -91,6 +115,17 @@ export function adapterCapabilityProfileDigestV3(adapter) {
91
115
  export function adapterSignalSupportV3(adapter, signal) {
92
116
  return adapterCapabilityProfileV3(adapter).signals[signal];
93
117
  }
118
+ /**
119
+ * Duration support for terminal spans. Tool duration is part of the digested
120
+ * adapter profile. Turn duration predates that profile dimension, so keep its
121
+ * compatibility-preserving classification here until the next contract major.
122
+ */
123
+ export function adapterDurationSupportV3(adapter, capability) {
124
+ if (capability === "tool_duration") {
125
+ return adapterSignalSupportV3(adapter, "tool_duration");
126
+ }
127
+ return adapter === "openclaw" ? "unsupported" : "derived";
128
+ }
94
129
  /**
95
130
  * Adapter hooks only expose permission waits today. Other wait kinds can be
96
131
  * authored by coordination producers, but they are not observable from an