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
@@ -0,0 +1,309 @@
1
+ import { createHash } from "node:crypto";
2
+ import {
3
+ PAGE_REVIEW_CAPTURE_PLAN_SCHEMA,
4
+ PAGE_REVIEW_DEFAULT_TILE_BUDGET,
5
+ PAGE_REVIEW_MAX_TILE_BUDGET,
6
+ type PageReviewBudgetCoverage,
7
+ type PageReviewCandidate,
8
+ type PageReviewCapturePlan,
9
+ type PageReviewContextAllocation,
10
+ type PageReviewRect,
11
+ type PageReviewTileBudgetAllocation,
12
+ } from "./page-review-contracts.ts";
13
+
14
+ const severityRank = { critical: 0, high: 1, medium: 2, low: 3, info: 4 };
15
+ const position = (a: PageReviewCandidate, b: PageReviewCandidate) =>
16
+ a.rect.y - b.rect.y || a.rect.x - b.rect.x || a.index - b.index || a.id.localeCompare(b.id);
17
+
18
+ export function validatePageReviewCapturePlan(value: unknown): PageReviewCapturePlan {
19
+ const fail = (detail: string): never => {
20
+ throw new Error(`Invalid page review capture plan: ${detail}; rerun planning.`);
21
+ };
22
+ if (!value || typeof value !== "object") fail("expected an object");
23
+ const p = value as PageReviewCapturePlan;
24
+ if (p.schema !== PAGE_REVIEW_CAPTURE_PLAN_SCHEMA) fail("unsupported schema");
25
+ for (const key of [
26
+ "context_id",
27
+ "viewport",
28
+ "state",
29
+ "source_digest",
30
+ "recipe_version",
31
+ ] as const) {
32
+ if (typeof p[key] !== "string" || !p[key].trim()) fail(`missing ${key}`);
33
+ }
34
+ if (p.theme !== "light" && p.theme !== "dark") fail("invalid theme");
35
+ if (!Number.isFinite(p.dpr) || p.dpr <= 0) fail("invalid DPR");
36
+ for (const key of ["viewport_width", "viewport_height", "page_width", "page_height"] as const) {
37
+ if (!Number.isSafeInteger(p[key]) || p[key] <= 0) fail(`invalid ${key}`);
38
+ }
39
+ if (!Array.isArray(p.candidates) || !p.candidates.length) fail("no candidates");
40
+ const seen = new Set<string>();
41
+ for (const c of p.candidates) {
42
+ if (!c || typeof c.id !== "string" || !c.id || seen.has(c.id))
43
+ fail("missing or duplicate candidate ID");
44
+ seen.add(c.id);
45
+ if (!Number.isSafeInteger(c.index) || c.index < 0 || typeof c.label !== "string")
46
+ fail(`invalid candidate ${c.id}`);
47
+ const r = c.rect;
48
+ if (
49
+ !r ||
50
+ ![r.x, r.y, r.width, r.height].every(Number.isSafeInteger) ||
51
+ r.x < 0 ||
52
+ r.y < 0 ||
53
+ r.width <= 0 ||
54
+ r.height <= 0 ||
55
+ r.x + r.width > p.page_width ||
56
+ r.y + r.height > p.page_height
57
+ )
58
+ fail(`invalid rectangle ${c.id}`);
59
+ if (c.scope !== undefined && (typeof c.scope !== "string" || !c.scope))
60
+ fail(`invalid scope ${c.id}`);
61
+ if (
62
+ !Array.isArray(c.gate_hits) ||
63
+ c.gate_hits.some(
64
+ (h) => !h || typeof h.check_id !== "string" || !h.check_id || !(h.severity in severityRank),
65
+ )
66
+ )
67
+ fail(`invalid gate hits ${c.id}`);
68
+ }
69
+ if (
70
+ p.required_scopes !== undefined &&
71
+ (!Array.isArray(p.required_scopes) ||
72
+ p.required_scopes.some((s) => typeof s !== "string" || !s))
73
+ )
74
+ fail("invalid required scopes");
75
+ const bands = p.candidates.filter((c) => c.scope === undefined).sort(position);
76
+ if (
77
+ !bands.length ||
78
+ bands[0].rect.y !== 0 ||
79
+ bands.at(-1)!.rect.y + bands.at(-1)!.rect.height !== p.page_height
80
+ )
81
+ fail("top and bottom page bands are required");
82
+ return p;
83
+ }
84
+
85
+ export function intervalUnion(
86
+ rects: readonly PageReviewRect[],
87
+ ): Array<{ start: number; end: number }> {
88
+ const out: Array<{ start: number; end: number }> = [];
89
+ for (const r of [...rects].sort((a, b) => a.y - b.y || a.height - b.height)) {
90
+ const last = out.at(-1);
91
+ if (last && r.y <= last.end) last.end = Math.max(last.end, r.y + r.height);
92
+ else out.push({ start: r.y, end: r.y + r.height });
93
+ }
94
+ return out;
95
+ }
96
+
97
+ export function allocationCoverage(
98
+ plan: PageReviewCapturePlan,
99
+ selectedIds: readonly string[],
100
+ ): PageReviewBudgetCoverage {
101
+ const selected = new Set(selectedIds);
102
+ const kept = plan.candidates.filter((c) => selected.has(c.id));
103
+ // A narrow scope cannot stand in for a full-width document band.
104
+ const reviewed = intervalUnion(
105
+ kept
106
+ .filter((c) => !c.scope && c.rect.x === 0 && c.rect.width === plan.page_width)
107
+ .map((c) => c.rect),
108
+ );
109
+ const uncovered: Array<{ start: number; end: number }> = [];
110
+ let cursor = 0;
111
+ for (const r of reviewed) {
112
+ if (r.start > cursor) uncovered.push({ start: cursor, end: r.start });
113
+ cursor = r.end;
114
+ }
115
+ if (cursor < plan.page_height) uncovered.push({ start: cursor, end: plan.page_height });
116
+ const missed = plan.candidates.filter((c) => !selected.has(c.id));
117
+ const scopes = new Set([
118
+ ...(plan.required_scopes ?? []),
119
+ ...plan.candidates.flatMap((c) => (c.scope ? [c.scope] : [])),
120
+ ]);
121
+ const omittedScopes = [...scopes]
122
+ .filter((s) => !plan.candidates.some((c) => c.scope === s) || missed.some((c) => c.scope === s))
123
+ .sort();
124
+ return {
125
+ page_height_px: plan.page_height,
126
+ reviewed_height_px: reviewed.reduce((sum, r) => sum + r.end - r.start, 0),
127
+ bands_total: plan.candidates.filter((c) => !c.scope).length,
128
+ bands_reviewed: kept.filter((c) => !c.scope).length,
129
+ capped: uncovered.length > 0 || omittedScopes.length > 0 || missed.some((c) => !c.scope),
130
+ selected_rectangles: kept.map((c) => ({ ...c.rect })),
131
+ reviewed_intervals: reviewed,
132
+ uncovered_intervals: uncovered,
133
+ omitted_gate_hits: [
134
+ ...new Set(missed.flatMap((c) => c.gate_hits.map((h) => h.check_id))),
135
+ ].sort(),
136
+ omitted_scopes: omittedScopes,
137
+ };
138
+ }
139
+
140
+ /** Reserve edges, prioritize gate hits, then distribute by remaining height. */
141
+ export function allocateTileBudget(
142
+ plans: PageReviewCapturePlan[],
143
+ budget = PAGE_REVIEW_DEFAULT_TILE_BUDGET,
144
+ ceilings?: Record<string, number>,
145
+ ): PageReviewTileBudgetAllocation {
146
+ if (!Number.isSafeInteger(budget) || budget < 1 || budget > PAGE_REVIEW_MAX_TILE_BUDGET)
147
+ throw new Error(`Tile budget must be an integer from 1 to ${PAGE_REVIEW_MAX_TILE_BUDGET}.`);
148
+ const rows = [...plans]
149
+ .map(validatePageReviewCapturePlan)
150
+ .sort((a, b) => a.context_id.localeCompare(b.context_id))
151
+ .map((plan) => {
152
+ const bands = plan.candidates.filter((c) => !c.scope).sort(position);
153
+ const edges = [bands[0], bands.at(-1)!].filter(
154
+ (c, i, a) => a.findIndex((x) => x.id === c.id) === i,
155
+ );
156
+ const ceiling = ceilings?.[plan.context_id] ?? budget;
157
+ if (!Number.isSafeInteger(ceiling) || ceiling < edges.length)
158
+ throw new Error(
159
+ `Context ${plan.context_id} requires a tile ceiling of at least ${edges.length} for its top and bottom bands (got ${ceiling}).`,
160
+ );
161
+ return { plan, ceiling, selected: new Set(edges.map((c) => c.id)) };
162
+ });
163
+ if (new Set(rows.map((r) => r.plan.context_id)).size !== rows.length)
164
+ throw new Error("Duplicate page review context ID.");
165
+ let used = rows.reduce((s, r) => s + r.selected.size, 0);
166
+ if (used > budget)
167
+ throw new Error(
168
+ `Tile budget requires at least ${used} to reserve every context's top and bottom bands (got ${budget}).`,
169
+ );
170
+ const hits = rows.flatMap((row) =>
171
+ row.plan.candidates
172
+ .filter((c) => c.gate_hits.length && !row.selected.has(c.id))
173
+ .map((c) => ({
174
+ row,
175
+ c,
176
+ rank: Math.min(...c.gate_hits.map((h) => severityRank[h.severity])),
177
+ })),
178
+ );
179
+ hits.sort(
180
+ (a, b) =>
181
+ a.rank - b.rank ||
182
+ a.row.plan.context_id.localeCompare(b.row.plan.context_id) ||
183
+ position(a.c, b.c),
184
+ );
185
+ for (const { row, c } of hits) {
186
+ if (used >= budget) break;
187
+ if (row.selected.size >= row.ceiling) continue;
188
+ row.selected.add(c.id);
189
+ used++;
190
+ }
191
+ const remaining = (row: (typeof rows)[number]) =>
192
+ row.plan.candidates.filter((c) => !row.selected.has(c.id)).sort(position);
193
+ while (used < budget) {
194
+ const eligible = rows
195
+ .map((row) => {
196
+ const candidates = remaining(row);
197
+ return {
198
+ row,
199
+ candidates,
200
+ capacity: Math.min(candidates.length, row.ceiling - row.selected.size),
201
+ height: intervalUnion(candidates.map((c) => c.rect)).reduce(
202
+ (s, r) => s + r.end - r.start,
203
+ 0,
204
+ ),
205
+ quota: 0,
206
+ fraction: 0,
207
+ };
208
+ })
209
+ .filter((r) => r.capacity > 0);
210
+ if (!eligible.length) break;
211
+ const slots = budget - used,
212
+ totalHeight = eligible.reduce((s, r) => s + r.height, 0);
213
+ for (const r of eligible) {
214
+ const exact = (slots * r.height) / totalHeight;
215
+ r.quota = Math.min(r.capacity, Math.floor(exact));
216
+ r.fraction = exact - Math.floor(exact);
217
+ }
218
+ let spare = slots - eligible.reduce((s, r) => s + r.quota, 0);
219
+ for (const r of [...eligible].sort(
220
+ (a, b) =>
221
+ b.fraction - a.fraction || a.row.plan.context_id.localeCompare(b.row.plan.context_id),
222
+ )) {
223
+ if (spare > 0 && r.quota < r.capacity) {
224
+ r.quota++;
225
+ spare--;
226
+ }
227
+ }
228
+ for (const r of eligible) {
229
+ for (let i = 0; i < r.quota; i++) {
230
+ const index = Math.floor(((i + 0.5) * r.candidates.length) / r.quota);
231
+ r.row.selected.add(r.candidates[index].id);
232
+ used++;
233
+ }
234
+ }
235
+ }
236
+ return {
237
+ budget,
238
+ used,
239
+ contexts: rows.map(({ plan, ceiling, selected }) => {
240
+ const selected_ids = plan.candidates
241
+ .filter((c) => selected.has(c.id))
242
+ .sort(position)
243
+ .map((c) => c.id);
244
+ return {
245
+ context_id: plan.context_id,
246
+ plan,
247
+ selected_ids,
248
+ ceiling,
249
+ omitted_candidates: plan.candidates
250
+ .filter((c) => !selected.has(c.id))
251
+ .map((c) => ({
252
+ id: c.id,
253
+ reason:
254
+ ceilings?.[plan.context_id] !== undefined && selected.size >= ceiling
255
+ ? ("ceiling" as const)
256
+ : ("budget" as const),
257
+ })),
258
+ coverage: allocationCoverage(plan, selected_ids),
259
+ };
260
+ }),
261
+ };
262
+ }
263
+
264
+ /** Gate-hit annotations are planning results; geometry and page state are authoritative at capture. */
265
+ export function capturePlanDigest(plan: PageReviewCapturePlan): string {
266
+ const { candidates, ...rest } = plan;
267
+ return createHash("sha256")
268
+ .update(JSON.stringify({ ...rest, candidates: candidates.map(({ gate_hits, ...c }) => c) }))
269
+ .digest("hex");
270
+ }
271
+
272
+ export function validatePageReviewAllocation(
273
+ value: unknown,
274
+ current: PageReviewCapturePlan,
275
+ ): PageReviewContextAllocation {
276
+ const allocation = value as PageReviewContextAllocation;
277
+ if (!allocation || typeof allocation !== "object")
278
+ throw new Error("Missing page review allocation; rerun planning.");
279
+ validatePageReviewCapturePlan(allocation.plan);
280
+ if (
281
+ allocation.context_id !== current.context_id ||
282
+ capturePlanDigest(allocation.plan) !== capturePlanDigest(current)
283
+ )
284
+ throw new Error(
285
+ "Page review capture geometry or source changed since planning; rerun the review.",
286
+ );
287
+ if (
288
+ !Array.isArray(allocation.selected_ids) ||
289
+ !allocation.selected_ids.length ||
290
+ new Set(allocation.selected_ids).size !== allocation.selected_ids.length ||
291
+ allocation.selected_ids.some((id) => !current.candidates.some((c) => c.id === id))
292
+ )
293
+ throw new Error("Invalid selected tile IDs in page review allocation.");
294
+ if (
295
+ !Number.isSafeInteger(allocation.ceiling) ||
296
+ allocation.selected_ids.length > allocation.ceiling
297
+ )
298
+ throw new Error("Page review allocation exceeds its context ceiling.");
299
+ const bands = current.candidates.filter((c) => !c.scope).sort(position);
300
+ if (
301
+ !allocation.selected_ids.includes(bands[0].id) ||
302
+ !allocation.selected_ids.includes(bands.at(-1)!.id)
303
+ )
304
+ throw new Error("Page review allocation must include top and bottom bands.");
305
+ const coverage = allocationCoverage(allocation.plan, allocation.selected_ids);
306
+ if (JSON.stringify(coverage) !== JSON.stringify(allocation.coverage))
307
+ throw new Error("Page review allocation coverage is inconsistent with selected tiles.");
308
+ return { ...allocation, coverage };
309
+ }
@@ -0,0 +1,129 @@
1
+ // Shared capture, allocation, and native-evidence contracts. Toolkit-only:
2
+ // capture and storage implement these shapes without importing coordination.
3
+ import type { CritiqueCoverage, CritiqueFinding } from "./critique.js";
4
+
5
+ export const PAGE_REVIEW_CAPTURE_PLAN_SCHEMA = "harnery-page-review-capture-plan/v1";
6
+ export const PAGE_REVIEW_NATIVE_EVIDENCE_SCHEMA = "harnery-page-review-native-evidence/v2";
7
+ export const PAGE_REVIEW_DECISIONS_SCHEMA = "harnery-page-review-decisions/v1";
8
+ export const PAGE_REVIEW_DEFAULT_TILE_BUDGET = 96;
9
+ export const PAGE_REVIEW_MAX_TILE_BUDGET = 400;
10
+
11
+ /** Rectangles are native image pixels, never CSS pixels or overview pixels. */
12
+ export interface PageReviewRect {
13
+ x: number;
14
+ y: number;
15
+ width: number;
16
+ height: number;
17
+ }
18
+
19
+ export interface PageReviewCandidate {
20
+ id: string;
21
+ index: number;
22
+ label: string;
23
+ rect: PageReviewRect;
24
+ scope?: string;
25
+ gate_hits: Array<{ check_id: string; severity: "critical" | "high" | "medium" | "low" | "info" }>;
26
+ }
27
+
28
+ /** Private diagnostic receipt, not an additional acceptance condition. Hash
29
+ * the referenced file bytes directly to reproduce source_digest. */
30
+ export interface PageReviewSourceEvidence {
31
+ path: string;
32
+ sha256: string;
33
+ bytes: number;
34
+ encoding: "utf8";
35
+ }
36
+
37
+ export interface PageReviewCapturePlan {
38
+ schema: typeof PAGE_REVIEW_CAPTURE_PLAN_SCHEMA;
39
+ context_id: string;
40
+ viewport: string;
41
+ viewport_width: number;
42
+ viewport_height: number;
43
+ theme: "light" | "dark";
44
+ state: string;
45
+ dpr: number;
46
+ page_width: number;
47
+ page_height: number;
48
+ /** Stable content/geometry signature; excludes capture timestamps. */
49
+ source_digest: string;
50
+ recipe_version: string;
51
+ required_scopes: string[];
52
+ candidates: PageReviewCandidate[];
53
+ }
54
+
55
+ export interface PageReviewBudgetCoverage extends CritiqueCoverage {
56
+ selected_rectangles: PageReviewRect[];
57
+ reviewed_intervals: Array<{ start: number; end: number }>;
58
+ uncovered_intervals: Array<{ start: number; end: number }>;
59
+ omitted_gate_hits: string[];
60
+ omitted_scopes: string[];
61
+ }
62
+
63
+ export interface PageReviewContextAllocation {
64
+ context_id: string;
65
+ plan: PageReviewCapturePlan;
66
+ selected_ids: string[];
67
+ ceiling: number;
68
+ omitted_candidates: Array<{ id: string; reason: "budget" | "ceiling" }>;
69
+ coverage: PageReviewBudgetCoverage;
70
+ }
71
+
72
+ export interface PageReviewTileBudgetAllocation {
73
+ budget: number;
74
+ used: number;
75
+ contexts: PageReviewContextAllocation[];
76
+ }
77
+
78
+ /** Pixel identity is meaningful only within an identical rendering contract. */
79
+ export interface PageReviewEvidenceContext {
80
+ viewport: string;
81
+ viewport_width: number;
82
+ viewport_height: number;
83
+ theme: "light" | "dark";
84
+ state: string;
85
+ dpr: number;
86
+ recipe_version: string;
87
+ rubric_digest: string;
88
+ critique_contract_version: number;
89
+ }
90
+
91
+ /** In-memory form. The snapshot store writes PNGs separately from metadata. */
92
+ export interface PageReviewNativeTile {
93
+ tile_id: string;
94
+ index: number;
95
+ label: string;
96
+ rect: PageReviewRect;
97
+ pixel_digest: string;
98
+ png: Buffer;
99
+ }
100
+
101
+ export interface PageReviewNativeEvidence {
102
+ schema: typeof PAGE_REVIEW_NATIVE_EVIDENCE_SCHEMA;
103
+ context: PageReviewEvidenceContext;
104
+ tiles: PageReviewNativeTile[];
105
+ }
106
+
107
+ export interface PageReviewDurableDecision {
108
+ finding_key: string;
109
+ tile_pixel_digest: string;
110
+ rect: PageReviewRect;
111
+ finding: Pick<CritiqueFinding, "severity" | "category" | "description">;
112
+ disposition: "artifact" | "not-a-defect" | "confirmed" | "duplicate-of-gate";
113
+ reviewer: string;
114
+ at: string;
115
+ note?: string;
116
+ }
117
+
118
+ /** Stored independently of baseline replacement and expiring pack directories. */
119
+ export interface PageReviewDecisionSlot {
120
+ schema: typeof PAGE_REVIEW_DECISIONS_SCHEMA;
121
+ target: string;
122
+ context: PageReviewEvidenceContext;
123
+ source_run: string;
124
+ source_revision: string | null;
125
+ reviewer: string;
126
+ reviewed_at: string;
127
+ complete: true;
128
+ decisions: PageReviewDurableDecision[];
129
+ }