@sentropic/h2a 0.85.25 → 0.87.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 (295) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/dist/bin.js +51 -2
  4. package/dist/bin.js.map +1 -1
  5. package/dist/cli-command-map.d.ts +119 -0
  6. package/dist/cli-command-map.d.ts.map +1 -0
  7. package/dist/cli-command-map.js +396 -0
  8. package/dist/cli-command-map.js.map +1 -0
  9. package/dist/cli-contract.d.ts.map +1 -1
  10. package/dist/cli-contract.js +39 -1
  11. package/dist/cli-contract.js.map +1 -1
  12. package/dist/cli.d.ts +25 -1
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/cli.js +356 -7
  15. package/dist/cli.js.map +1 -1
  16. package/dist/identity.d.ts +37 -3
  17. package/dist/identity.d.ts.map +1 -1
  18. package/dist/identity.js +0 -0
  19. package/dist/identity.js.map +1 -1
  20. package/dist/index.d.ts +7 -2
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +9 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/runtime/enrollment/ceremony.d.ts +542 -0
  25. package/dist/runtime/enrollment/ceremony.d.ts.map +1 -0
  26. package/dist/runtime/enrollment/ceremony.js +777 -0
  27. package/dist/runtime/enrollment/ceremony.js.map +1 -0
  28. package/dist/runtime/enrollment/index.d.ts +16 -0
  29. package/dist/runtime/enrollment/index.d.ts.map +1 -0
  30. package/dist/runtime/enrollment/index.js +16 -0
  31. package/dist/runtime/enrollment/index.js.map +1 -0
  32. package/dist/runtime/feed/descriptors.d.ts +261 -0
  33. package/dist/runtime/feed/descriptors.d.ts.map +1 -0
  34. package/dist/runtime/feed/descriptors.js +425 -0
  35. package/dist/runtime/feed/descriptors.js.map +1 -0
  36. package/dist/runtime/feed/index.d.ts +12 -0
  37. package/dist/runtime/feed/index.d.ts.map +1 -0
  38. package/dist/runtime/feed/index.js +12 -0
  39. package/dist/runtime/feed/index.js.map +1 -0
  40. package/dist/runtime/identity/index.d.ts +3 -3
  41. package/dist/runtime/identity/index.d.ts.map +1 -1
  42. package/dist/runtime/identity/index.js +2 -2
  43. package/dist/runtime/identity/index.js.map +1 -1
  44. package/dist/runtime/identity/live.d.ts +68 -0
  45. package/dist/runtime/identity/live.d.ts.map +1 -1
  46. package/dist/runtime/identity/live.js +78 -2
  47. package/dist/runtime/identity/live.js.map +1 -1
  48. package/dist/runtime/identity/readers.d.ts +89 -5
  49. package/dist/runtime/identity/readers.d.ts.map +1 -1
  50. package/dist/runtime/identity/readers.js +242 -33
  51. package/dist/runtime/identity/readers.js.map +1 -1
  52. package/dist/runtime/local-files/presence.d.ts +16 -1
  53. package/dist/runtime/local-files/presence.d.ts.map +1 -1
  54. package/dist/runtime/local-files/presence.js +32 -20
  55. package/dist/runtime/local-files/presence.js.map +1 -1
  56. package/dist/runtime/loop/index.d.ts +5 -0
  57. package/dist/runtime/loop/index.d.ts.map +1 -1
  58. package/dist/runtime/loop/index.js +48 -5
  59. package/dist/runtime/loop/index.js.map +1 -1
  60. package/dist/runtime/mcp/agent-launch.d.ts +15 -1
  61. package/dist/runtime/mcp/agent-launch.d.ts.map +1 -1
  62. package/dist/runtime/mcp/agent-launch.js +45 -4
  63. package/dist/runtime/mcp/agent-launch.js.map +1 -1
  64. package/dist/runtime/mcp/index.d.ts +1 -1
  65. package/dist/runtime/mcp/index.d.ts.map +1 -1
  66. package/dist/runtime/mcp/index.js +1 -1
  67. package/dist/runtime/mcp/index.js.map +1 -1
  68. package/dist/runtime/mcp/server.d.ts +3 -1
  69. package/dist/runtime/mcp/server.d.ts.map +1 -1
  70. package/dist/runtime/mcp/server.js +7 -2
  71. package/dist/runtime/mcp/server.js.map +1 -1
  72. package/dist/runtime/mcp/sessions.d.ts +19 -0
  73. package/dist/runtime/mcp/sessions.d.ts.map +1 -1
  74. package/dist/runtime/mcp/sessions.js +44 -2
  75. package/dist/runtime/mcp/sessions.js.map +1 -1
  76. package/dist/runtime/mcp/stdio.d.ts +8 -0
  77. package/dist/runtime/mcp/stdio.d.ts.map +1 -1
  78. package/dist/runtime/mcp/stdio.js +42 -0
  79. package/dist/runtime/mcp/stdio.js.map +1 -1
  80. package/dist/runtime/mcp-registry/broker.d.ts +175 -0
  81. package/dist/runtime/mcp-registry/broker.d.ts.map +1 -0
  82. package/dist/runtime/mcp-registry/broker.js +203 -0
  83. package/dist/runtime/mcp-registry/broker.js.map +1 -0
  84. package/dist/runtime/mcp-registry/broker.typecheck.d.ts +2 -0
  85. package/dist/runtime/mcp-registry/broker.typecheck.d.ts.map +1 -0
  86. package/dist/runtime/mcp-registry/broker.typecheck.js +48 -0
  87. package/dist/runtime/mcp-registry/broker.typecheck.js.map +1 -0
  88. package/dist/runtime/mirror/accept.d.ts +43 -5
  89. package/dist/runtime/mirror/accept.d.ts.map +1 -1
  90. package/dist/runtime/mirror/accept.js +55 -7
  91. package/dist/runtime/mirror/accept.js.map +1 -1
  92. package/dist/runtime/mirror/build.d.ts +23 -4
  93. package/dist/runtime/mirror/build.d.ts.map +1 -1
  94. package/dist/runtime/mirror/build.js +34 -4
  95. package/dist/runtime/mirror/build.js.map +1 -1
  96. package/dist/runtime/mirror/index.d.ts +3 -0
  97. package/dist/runtime/mirror/index.d.ts.map +1 -1
  98. package/dist/runtime/mirror/index.js +3 -0
  99. package/dist/runtime/mirror/index.js.map +1 -1
  100. package/dist/runtime/mirror/ingest.d.ts +109 -0
  101. package/dist/runtime/mirror/ingest.d.ts.map +1 -0
  102. package/dist/runtime/mirror/ingest.js +117 -0
  103. package/dist/runtime/mirror/ingest.js.map +1 -0
  104. package/dist/runtime/mirror/push-daemon.d.ts +376 -0
  105. package/dist/runtime/mirror/push-daemon.d.ts.map +1 -0
  106. package/dist/runtime/mirror/push-daemon.js +644 -0
  107. package/dist/runtime/mirror/push-daemon.js.map +1 -0
  108. package/dist/runtime/mirror/sanitize.d.ts +477 -0
  109. package/dist/runtime/mirror/sanitize.d.ts.map +1 -0
  110. package/dist/runtime/mirror/sanitize.js +625 -0
  111. package/dist/runtime/mirror/sanitize.js.map +1 -0
  112. package/dist/runtime/mirror/serve.d.ts.map +1 -1
  113. package/dist/runtime/mirror/serve.js +104 -24
  114. package/dist/runtime/mirror/serve.js.map +1 -1
  115. package/dist/runtime/reporting/report-ai.d.ts.map +1 -1
  116. package/dist/runtime/reporting/report-ai.js +1 -0
  117. package/dist/runtime/reporting/report-ai.js.map +1 -1
  118. package/dist/runtime/reporting/stdin.d.ts +2 -0
  119. package/dist/runtime/reporting/stdin.d.ts.map +1 -0
  120. package/dist/runtime/reporting/stdin.js +8 -0
  121. package/dist/runtime/reporting/stdin.js.map +1 -0
  122. package/dist/status-surface.d.ts +167 -0
  123. package/dist/status-surface.d.ts.map +1 -0
  124. package/dist/status-surface.js +670 -0
  125. package/dist/status-surface.js.map +1 -0
  126. package/dist/types.d.ts +17 -0
  127. package/dist/types.d.ts.map +1 -1
  128. package/dist/types.js +3 -0
  129. package/dist/types.js.map +1 -1
  130. package/dist/vendor/harness/skills/manifest.d.ts.map +1 -1
  131. package/dist/vendor/harness/skills/manifest.js +2 -0
  132. package/dist/vendor/harness/skills/manifest.js.map +1 -1
  133. package/focus-app/client/_app/immutable/assets/{0.BdzHFb9q.css → 0.CgEVz9YW.css} +1 -1
  134. package/focus-app/client/_app/immutable/assets/0.CgEVz9YW.css.br +0 -0
  135. package/focus-app/client/_app/immutable/assets/0.CgEVz9YW.css.gz +0 -0
  136. package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css +1 -0
  137. package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css.br +0 -0
  138. package/focus-app/client/_app/immutable/assets/2.DaTmt6o7.css.gz +0 -0
  139. package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css +1 -0
  140. package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css.br +0 -0
  141. package/focus-app/client/_app/immutable/assets/3.vWQUAHjz.css.gz +0 -0
  142. package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css +1 -0
  143. package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css.br +0 -0
  144. package/focus-app/client/_app/immutable/assets/AppShell.CDPwj3zU.css.gz +0 -0
  145. package/focus-app/client/_app/immutable/chunks/{Cj6wo28J.js → 1NK_OeRJ.js} +1 -1
  146. package/focus-app/client/_app/immutable/chunks/1NK_OeRJ.js.br +0 -0
  147. package/focus-app/client/_app/immutable/chunks/1NK_OeRJ.js.gz +0 -0
  148. package/focus-app/client/_app/immutable/chunks/{Bs3f1UbD.js → B1veta3r.js} +2 -2
  149. package/focus-app/client/_app/immutable/chunks/B1veta3r.js.br +0 -0
  150. package/focus-app/client/_app/immutable/chunks/B1veta3r.js.gz +0 -0
  151. package/focus-app/client/_app/immutable/chunks/{DEmooz0s.js → BZ4lcC0v.js} +1 -1
  152. package/focus-app/client/_app/immutable/chunks/BZ4lcC0v.js.br +0 -0
  153. package/focus-app/client/_app/immutable/chunks/BZ4lcC0v.js.gz +0 -0
  154. package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js +2 -0
  155. package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js.br +0 -0
  156. package/focus-app/client/_app/immutable/chunks/Bu7F9NOv.js.gz +0 -0
  157. package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js +1 -0
  158. package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js.br +0 -0
  159. package/focus-app/client/_app/immutable/chunks/C6KhNEX3.js.gz +0 -0
  160. package/focus-app/client/_app/immutable/chunks/DIljKPJN.js +1 -0
  161. package/focus-app/client/_app/immutable/chunks/DIljKPJN.js.br +0 -0
  162. package/focus-app/client/_app/immutable/chunks/DIljKPJN.js.gz +0 -0
  163. package/focus-app/client/_app/immutable/chunks/iXQate3J.js +2 -0
  164. package/focus-app/client/_app/immutable/chunks/iXQate3J.js.br +0 -0
  165. package/focus-app/client/_app/immutable/chunks/iXQate3J.js.gz +0 -0
  166. package/focus-app/client/_app/immutable/chunks/{ZxFklh9T.js → kCE9wz0g.js} +1 -1
  167. package/focus-app/client/_app/immutable/chunks/kCE9wz0g.js.br +0 -0
  168. package/focus-app/client/_app/immutable/chunks/kCE9wz0g.js.gz +0 -0
  169. package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js +1 -0
  170. package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js.br +0 -0
  171. package/focus-app/client/_app/immutable/chunks/x-hq5fDG.js.gz +0 -0
  172. package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js +2 -0
  173. package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js.br +0 -0
  174. package/focus-app/client/_app/immutable/entry/app.C1sDdCg5.js.gz +0 -0
  175. package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js +1 -0
  176. package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js.br +2 -0
  177. package/focus-app/client/_app/immutable/entry/start.X3j_A5RN.js.gz +0 -0
  178. package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js +5 -0
  179. package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js.br +0 -0
  180. package/focus-app/client/_app/immutable/nodes/0.gLl44WzG.js.gz +0 -0
  181. package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js +1 -0
  182. package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js.br +0 -0
  183. package/focus-app/client/_app/immutable/nodes/1.DUrghq2x.js.gz +0 -0
  184. package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js +1 -0
  185. package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js.br +0 -0
  186. package/focus-app/client/_app/immutable/nodes/2.Bp7JE7Pz.js.gz +0 -0
  187. package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js +12 -0
  188. package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js.br +0 -0
  189. package/focus-app/client/_app/immutable/nodes/3.Cml8enOG.js.gz +0 -0
  190. package/focus-app/client/_app/version.json +1 -1
  191. package/focus-app/client/_app/version.json.br +0 -0
  192. package/focus-app/client/_app/version.json.gz +0 -0
  193. package/focus-app/h2a-focus.json +108 -80
  194. package/focus-app/handler.js +7 -7
  195. package/focus-app/index.js +7 -7
  196. package/focus-app/server/chunks/chunks/AppShell.js-6Pi87dO0.js +1353 -0
  197. package/focus-app/server/chunks/chunks/AppShell.js-6Pi87dO0.js.map +1 -0
  198. package/focus-app/server/chunks/chunks/agent-memory-dossier.js-nmFG_rgx.js +1036 -0
  199. package/focus-app/server/chunks/chunks/agent-memory-dossier.js-nmFG_rgx.js.map +1 -0
  200. package/focus-app/server/chunks/chunks/{exports.js-DUTkELZq.js → exports.js-CdqPbjm1.js} +3 -3
  201. package/focus-app/server/chunks/chunks/{exports.js-DUTkELZq.js.map → exports.js-CdqPbjm1.js.map} +1 -1
  202. package/focus-app/server/chunks/chunks/h2a-bus.js-bLEJ_Adi.js +233 -0
  203. package/focus-app/server/chunks/chunks/h2a-bus.js-bLEJ_Adi.js.map +1 -0
  204. package/focus-app/server/chunks/chunks/{index.js-Di21TltP.js → index.js-laGHLarB.js} +5 -2
  205. package/focus-app/server/chunks/chunks/index.js-laGHLarB.js.map +1 -0
  206. package/focus-app/server/chunks/chunks/{internal.js-33vbd70h.js → internal.js-C6T8nHkl.js} +4 -4
  207. package/focus-app/server/chunks/chunks/{internal.js-33vbd70h.js.map → internal.js-C6T8nHkl.js.map} +1 -1
  208. package/focus-app/server/chunks/chunks/{root.js-DO1m-gJA.js → root.js-CtVQOgDw.js} +2 -2
  209. package/focus-app/server/chunks/chunks/{root.js-DO1m-gJA.js.map → root.js-CtVQOgDw.js.map} +1 -1
  210. package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/{_server.ts.js-j0NNcOSZ.js → _server.ts.js-hrbMnsV0.js} +13 -42
  211. package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-hrbMnsV0.js.map +1 -0
  212. package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/_server.ts.js-Dw4odGdV.js +138 -0
  213. package/focus-app/server/chunks/entries/endpoints/api/dossiers/agent-memory/include/_server.ts.js-Dw4odGdV.js.map +1 -0
  214. package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/_server.ts.js-BLjYv7vg.js +41 -0
  215. package/focus-app/server/chunks/entries/endpoints/api/h2a/targets/_server.ts.js-BLjYv7vg.js.map +1 -0
  216. package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-Dj3sETSX.js → error.svelte.js-RbeaNF5a.js} +4 -4
  217. package/focus-app/server/chunks/entries/fallbacks/{error.svelte.js-Dj3sETSX.js.map → error.svelte.js-RbeaNF5a.js.map} +1 -1
  218. package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-BoLsbuC2.js → _layout.svelte.js-e1E_I04z.js} +2 -2
  219. package/focus-app/server/chunks/entries/pages/{_layout.svelte.js-BoLsbuC2.js.map → _layout.svelte.js-e1E_I04z.js.map} +1 -1
  220. package/focus-app/server/chunks/entries/pages/{_page.svelte.js-QDldMYhk.js → _page.svelte.js-DbaEG23x.js} +31 -1373
  221. package/focus-app/server/chunks/entries/pages/_page.svelte.js-DbaEG23x.js.map +1 -0
  222. package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.server.ts.js-CFC-wn6U.js +88 -0
  223. package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.server.ts.js-CFC-wn6U.js.map +1 -0
  224. package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.svelte.js-BpR26NMa.js +1574 -0
  225. package/focus-app/server/chunks/entries/pages/dossier/agent-memory/_page.svelte.js-BpR26NMa.js.map +1 -0
  226. package/focus-app/server/chunks/{handler-Cp_5hLyY.js → handler-Be3dyNi0.js} +3 -3
  227. package/focus-app/server/chunks/{handler-Cp_5hLyY.js.map → handler-Be3dyNi0.js.map} +1 -1
  228. package/focus-app/server/chunks/{index.js-CBh7Wjqp.js → index.js-siUxMMnK.js} +3 -3
  229. package/focus-app/server/chunks/{index.js-CBh7Wjqp.js.map → index.js-siUxMMnK.js.map} +1 -1
  230. package/focus-app/server/chunks/manifest.js-CXJqSHHn.js +78 -0
  231. package/focus-app/server/chunks/manifest.js-CXJqSHHn.js.map +1 -0
  232. package/focus-app/server/chunks/nodes/0.js-leU6sfRR.js +9 -0
  233. package/focus-app/server/chunks/nodes/{0.js-4wlmdsk8.js.map → 0.js-leU6sfRR.js.map} +1 -1
  234. package/focus-app/server/chunks/nodes/1.js-os6QXm6B.js +9 -0
  235. package/focus-app/server/chunks/nodes/{1.js-B-LpY-lC.js.map → 1.js-os6QXm6B.js.map} +1 -1
  236. package/focus-app/server/chunks/nodes/2.js-DAaLjh93.js +19 -0
  237. package/focus-app/server/chunks/nodes/2.js-DAaLjh93.js.map +1 -0
  238. package/focus-app/server/chunks/nodes/3.js-Cmgi6Uy0.js +18 -0
  239. package/focus-app/server/chunks/nodes/3.js-Cmgi6Uy0.js.map +1 -0
  240. package/package.json +5 -5
  241. package/skills/h2a-run/SKILL.md +100 -0
  242. package/skills/harness/SKILL.md +3 -1
  243. package/skills/harness/review/SKILL.md +99 -8
  244. package/skills/harness/security/SKILL.md +55 -0
  245. package/skills/harness/track-report/SKILL.md +103 -0
  246. package/skills/harness/using-harness/SKILL.md +3 -1
  247. package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.br +0 -2
  248. package/focus-app/client/_app/immutable/assets/0.BdzHFb9q.css.gz +0 -0
  249. package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css +0 -1
  250. package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.br +0 -0
  251. package/focus-app/client/_app/immutable/assets/2.Ddxq02y4.css.gz +0 -0
  252. package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.br +0 -0
  253. package/focus-app/client/_app/immutable/chunks/Bs3f1UbD.js.gz +0 -0
  254. package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js +0 -1
  255. package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.br +0 -0
  256. package/focus-app/client/_app/immutable/chunks/Bv8OL8ib.js.gz +0 -0
  257. package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js +0 -2
  258. package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.br +0 -0
  259. package/focus-app/client/_app/immutable/chunks/CVq_IFFr.js.gz +0 -0
  260. package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.br +0 -0
  261. package/focus-app/client/_app/immutable/chunks/Cj6wo28J.js.gz +0 -0
  262. package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.br +0 -0
  263. package/focus-app/client/_app/immutable/chunks/DEmooz0s.js.gz +0 -0
  264. package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js +0 -2
  265. package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.br +0 -0
  266. package/focus-app/client/_app/immutable/chunks/DQIRXgdC.js.gz +0 -0
  267. package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.br +0 -0
  268. package/focus-app/client/_app/immutable/chunks/ZxFklh9T.js.gz +0 -0
  269. package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js +0 -1
  270. package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.br +0 -0
  271. package/focus-app/client/_app/immutable/chunks/_wRuVGPs.js.gz +0 -0
  272. package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js +0 -2
  273. package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.br +0 -0
  274. package/focus-app/client/_app/immutable/entry/app.6DKouWRt.js.gz +0 -0
  275. package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js +0 -1
  276. package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.br +0 -2
  277. package/focus-app/client/_app/immutable/entry/start.DlLmkUb7.js.gz +0 -0
  278. package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js +0 -5
  279. package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.br +0 -0
  280. package/focus-app/client/_app/immutable/nodes/0.CuSOF0Of.js.gz +0 -0
  281. package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js +0 -1
  282. package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.br +0 -0
  283. package/focus-app/client/_app/immutable/nodes/1.D39jdnqm.js.gz +0 -0
  284. package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js +0 -1
  285. package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.br +0 -0
  286. package/focus-app/client/_app/immutable/nodes/2.CnU8ifRl.js.gz +0 -0
  287. package/focus-app/server/chunks/chunks/index.js-Di21TltP.js.map +0 -1
  288. package/focus-app/server/chunks/entries/endpoints/api/decisions/inject/_server.ts.js-j0NNcOSZ.js.map +0 -1
  289. package/focus-app/server/chunks/entries/pages/_page.svelte.js-QDldMYhk.js.map +0 -1
  290. package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js +0 -56
  291. package/focus-app/server/chunks/manifest.js-Cm6cC7mC.js.map +0 -1
  292. package/focus-app/server/chunks/nodes/0.js-4wlmdsk8.js +0 -9
  293. package/focus-app/server/chunks/nodes/1.js-B-LpY-lC.js +0 -9
  294. package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js +0 -19
  295. package/focus-app/server/chunks/nodes/2.js-F6jp5eD9.js.map +0 -1
@@ -0,0 +1,644 @@
1
+ /**
2
+ * EVO-13 / feed-contract P1 step 4a — the mirror push as an OPT-IN live daemon.
3
+ *
4
+ * `h2a remote mirror` is a ONE-SHOT push (build → sign → POST once). The
5
+ * ratified feed contract
6
+ * (`docs/superpowers/specs/2026-07-24-h2a-feed-contract-for-sentropic.md`,
7
+ * Part C) needs that same push to run continuously on a 15–30s beat, so the
8
+ * hosted read-only store stays warm for a UI that only ever pulls. A laptop
9
+ * behind NAT cannot accept inbound, so the data path must be push — the daemon
10
+ * is the pipeline, not a new trust boundary.
11
+ *
12
+ * This module changes NOTHING about what is pushed. It wraps the existing
13
+ * one-shot cycle (`buildInstanceMirror` → `sendRemoteEnvelope`) in the same
14
+ * supervisor idioms already shipped for the L1 objective loop
15
+ * (`runtime/loop/supervisor.ts`): opt-in only, a global kill-switch, an
16
+ * injectable clock, a drainable abort signal, and a per-beat summary that is
17
+ * observability — never control. The signed-envelope trust boundary, the
18
+ * payload shape, the sequence fencing and the accept-side verification are
19
+ * untouched.
20
+ *
21
+ * Safety properties, in the order they matter:
22
+ *
23
+ * - OPT-IN, NEVER DEFAULT-ON. Nothing here runs unless a caller explicitly
24
+ * asks for an interval. `h2a remote mirror` with no `--interval-ms` still
25
+ * takes the byte-identical one-shot path it took before this module existed.
26
+ * The global kill-switch `H2A_MIRROR_PUSH_OFF` hard-disables the loop even
27
+ * when a unit file or an operator asked for it — checked before the FIRST
28
+ * cycle, so a frozen daemon never emits a single request.
29
+ *
30
+ * - AUTH FAILURE STOPS, IT DOES NOT RETRY FOREVER. A 401/403 means the
31
+ * receiving side does not trust this instance's signing key (never enrolled,
32
+ * revoked, or — the live case today — the agent re-anchored and mints a
33
+ * different keypair than the one enrolled). No amount of retrying fixes
34
+ * that: it needs a human re-enrollment ceremony. So consecutive auth
35
+ * rejections are backed off and then the daemon STOPS with an actionable
36
+ * message, instead of hammering a rejecting endpoint indefinitely. Only a
37
+ * genuinely accepted push (`ok`) clears the counter — a transient error in
38
+ * between does NOT, because "network flap between two 401s" must not be a
39
+ * way to loop forever against a server that is refusing us.
40
+ *
41
+ * - NO OVERLAP. The daemon cannot overlap itself: it awaits each cycle before
42
+ * scheduling the next, so a slow push delays the next beat rather than
43
+ * stacking on top of it (and the slot arithmetic below then skips the beats
44
+ * that were missed). The exported runner ALSO carries an in-flight guard, for
45
+ * the different case of two concurrent callers sharing one runner: the second
46
+ * gets `skipped-overlap` without building or sending anything. That guard is
47
+ * defence for external callers, not what protects the daemon's own loop.
48
+ *
49
+ * - NO DRIFT. Cycles are scheduled against a monotonic slot anchor
50
+ * (`anchor + n × interval`), not by sleeping a fixed interval after each
51
+ * cycle, so per-cycle duration does not accumulate into lateness. Slots
52
+ * already in the past are skipped rather than fired back-to-back. A small
53
+ * bounded jitter de-synchronises several agents pushing to one endpoint.
54
+ *
55
+ * - TRANSIENT ERRORS KEEP LOOPING. A network throw, a 5xx or a 429 is the
56
+ * endpoint's problem, not ours: exponential backoff (capped), then carry on.
57
+ *
58
+ * - A STATUS MUST NOT BE WIDER THAN ITS EVIDENCE. The dividing line for every
59
+ * stop rule above is "can this self-heal": a network outage can, a refused
60
+ * key / a refused request / a root that cannot build this instance's mirror
61
+ * cannot. The non-self-healing cases therefore TERMINATE rather than idle,
62
+ * because idling would make this process the dishonest layer. Consider a
63
+ * wrong `H2A_ROOT`: nothing is ever sent, so the feed downstream correctly
64
+ * starts reporting those rows `stale` once `mirroredAt` stops advancing —
65
+ * while `systemctl status` would still read `active (running)`. The two
66
+ * layers would disagree and the only honest signal would be the one FURTHEST
67
+ * from the operator, in a UI nobody is watching. The signal nearest the fault
68
+ * has to be at least as honest as the far one, so we exit 1 and say why.
69
+ * Correspondingly, the per-cycle line reports what the push CONTAINED (seq +
70
+ * counts), so a successful push of an empty mirror is never mistaken for a
71
+ * healthy feed.
72
+ *
73
+ * - DRAINABLE. `signal` is honored before each cycle and inside every sleep,
74
+ * so SIGTERM stops promptly instead of finishing the schedule.
75
+ *
76
+ * - LOGS ARE SAFE BY CONSTRUCTION. The per-cycle line carries an outcome, an
77
+ * HTTP status, a closed-vocabulary rejection reason and a redacted endpoint.
78
+ * It NEVER carries key material, a token, a request body or a response body.
79
+ * Everything free-form (an error message) goes through `sanitizeForLog`.
80
+ */
81
+ import { createLocalStore } from "../local-files/index.js";
82
+ import { sendRemoteEnvelope } from "../remote/client.js";
83
+ import { buildInstanceMirror } from "./build.js";
84
+ /**
85
+ * Default beat. The ratified contract asks for 15–30s; 20s sits in the middle
86
+ * and keeps a UI's worst-case staleness under the 90s presence keepalive
87
+ * window, so a `stale` row means the pipeline really is down.
88
+ */
89
+ export const DEFAULT_MIRROR_PUSH_INTERVAL_MS = 20_000;
90
+ /**
91
+ * Floor the CLI enforces on `--interval-ms`. The library itself accepts any
92
+ * positive interval (tests drive it at millisecond speed against a fake
93
+ * transport); the operator-facing surface refuses anything that would hammer a
94
+ * hosted endpoint faster than the contract's own range.
95
+ */
96
+ export const MIN_MIRROR_PUSH_INTERVAL_MS = 5_000;
97
+ /** Bounded de-synchronisation jitter, as a fraction of the interval (±10%). */
98
+ export const MIRROR_PUSH_JITTER_FRACTION = 0.1;
99
+ /** First transient-failure backoff; doubles per consecutive failure. */
100
+ export const MIRROR_PUSH_BACKOFF_BASE_MS = 5_000;
101
+ /** Backoff ceiling — a long outage retries every 5 min, not every 5 hours. */
102
+ export const MIRROR_PUSH_BACKOFF_MAX_MS = 300_000;
103
+ /**
104
+ * How many CONSECUTIVE auth rejections are tolerated (each backed off) before
105
+ * the daemon stops. 3 absorbs a key-rotation race on the accept side while
106
+ * still stopping in well under a minute of real rejection.
107
+ */
108
+ export const DEFAULT_MIRROR_AUTH_FAILURE_LIMIT = 3;
109
+ /**
110
+ * How many CONSECUTIVE non-auth rejections (a 4xx that is not 401/403) are
111
+ * tolerated before the daemon stops. Some of these genuinely self-heal — a
112
+ * stale-sequence or replay rejection clears as `seq` advances — which is why the
113
+ * budget is looser than the auth one. But a permanently malformed request or a
114
+ * wrong path returning 404 will never heal, and retrying it forever is the same
115
+ * failure mode as retrying a refused key: a unit that reads "active (running)"
116
+ * while pushing nothing. 5 tolerates a real fencing race, then stops.
117
+ */
118
+ export const DEFAULT_MIRROR_REJECT_LIMIT = 5;
119
+ /**
120
+ * How many CONSECUTIVE local build failures are tolerated before the daemon
121
+ * stops. `buildInstanceMirror` throwing means this root does not know this
122
+ * instance — overwhelmingly because `H2A_ROOT` points somewhere the agent never
123
+ * registered, the misconfiguration the shipped unit file explicitly warns about.
124
+ * A wrong root NEVER self-heals, and looping on it forever is the worst possible
125
+ * failure shape: no request is ever sent, yet `systemctl status` reads
126
+ * `active (running)` indefinitely, so monitoring keyed on systemd state reads
127
+ * green while the feed is dead. It must terminate loudly instead. 5 leaves room
128
+ * for a genuinely transient race (an agent re-registering, a root being created).
129
+ *
130
+ * The contract-level argument (from the feed contract's own architect): in this
131
+ * failure mode the feed WOULD report `stale` correctly, because `mirroredAt` stops
132
+ * advancing — so the honest signal exists, but only at the layer furthest from the
133
+ * operator. Idling here would ship a daemon that claims health next to a contract
134
+ * written specifically to refuse claiming it.
135
+ */
136
+ export const DEFAULT_MIRROR_BUILD_FAILURE_LIMIT = 5;
137
+ /** Name of the global kill-switch env var. */
138
+ export const MIRROR_PUSH_OFF_ENV = "H2A_MIRROR_PUSH_OFF";
139
+ /**
140
+ * Global kill-switch for the live mirror push. When `H2A_MIRROR_PUSH_OFF` is
141
+ * set to any non-empty, non-"0"/"false" value, NO mirror push daemon runs
142
+ * anywhere, regardless of flags or unit files. Same semantics as
143
+ * `H2A_LOOP_AUTOTICK_OFF` for the objective-loop supervisor — one lever to
144
+ * freeze the pipeline without editing any invocation.
145
+ */
146
+ export function mirrorPushGloballyDisabled(env = process.env) {
147
+ const v = env[MIRROR_PUSH_OFF_ENV];
148
+ if (v === undefined)
149
+ return false;
150
+ const norm = v.trim().toLowerCase();
151
+ return norm !== "" && norm !== "0" && norm !== "false";
152
+ }
153
+ /**
154
+ * Emitted when the daemon stops because the endpoint keeps rejecting the request
155
+ * itself (not the key). Like the auth stop, retrying cannot fix a permanently
156
+ * malformed request or a wrong path.
157
+ */
158
+ export const MIRROR_PUSH_REJECTED_MESSAGE = "mirror push STOPPED: the endpoint rejected this mirror on every attempt with a 4xx that is not an auth failure. " +
159
+ "The request itself is being refused, so retrying cannot fix it — check that --url points at the ingester's mirror path " +
160
+ "(a wrong path typically answers 404) and that this instance's clock is accurate (a skewed clock is refused as expired/future). " +
161
+ "The per-cycle status lines carry the endpoint and the rejection reason. Nothing further will be pushed until the daemon is restarted.";
162
+ /**
163
+ * Emitted when the daemon is asked to push to something that is not a usable
164
+ * http(s) endpoint. Returned BEFORE any cycle runs, because a URL `fetch` cannot
165
+ * even parse would otherwise be retried forever as a transient network failure.
166
+ */
167
+ /**
168
+ * Emitted when the daemon stops because it cannot even BUILD a mirror locally.
169
+ * Names the likely cause, because this failure never reaches the network and so
170
+ * leaves no server-side trace for the operator to correlate against.
171
+ */
172
+ export const MIRROR_PUSH_BUILD_FAILED_MESSAGE = "mirror push STOPPED: this h2a root does not know the instance being mirrored, on every attempt. " +
173
+ "Nothing was ever sent, and this cannot self-heal by retrying. " +
174
+ "Check that --instance names an instance registered in THIS root and that H2A_ROOT / --root points at the root where that agent actually registers " +
175
+ "(h2a discover --root <root> lists them). Nothing further will be pushed until the daemon is restarted.";
176
+ export const MIRROR_PUSH_INVALID_URL_MESSAGE = "mirror push NOT STARTED: the push target is not a usable http(s) URL, so no request could ever succeed. " +
177
+ "Set --url to the ingester's full mirror endpoint (for example https://host/h2a/mirror). " +
178
+ "If this is a systemd unit, its ExecStart placeholder was not filled in.";
179
+ /**
180
+ * The actionable message emitted when the daemon stops on repeated auth
181
+ * rejection. Deliberately explicit: the failure is NOT retryable and the
182
+ * operator must know exactly which human act unblocks it.
183
+ */
184
+ export const MIRROR_PUSH_REENROLLMENT_MESSAGE = "mirror push STOPPED: the endpoint rejected this instance's signing key (HTTP 401/403) on every attempt. " +
185
+ "This is not a transient error and retrying cannot fix it — the key is not enrolled on the receiving side " +
186
+ "(never enrolled, revoked, or the agent re-anchored and now signs with a different keypair). " +
187
+ "RE-ENROLLMENT IS REQUIRED: enroll this instance's CURRENT public key on the receiving side, then restart the daemon. " +
188
+ "Nothing further will be pushed until then.";
189
+ /** Accept-side rejection vocabulary (`runtime/mirror/accept.ts`). */
190
+ const MIRROR_REJECTION_REASONS = new Set([
191
+ "malformed",
192
+ "not-mirror",
193
+ "no-signature",
194
+ "unauthorized-key",
195
+ "bad-signature",
196
+ "invalid-timestamp",
197
+ "expired",
198
+ "future",
199
+ "replayed",
200
+ "stale-sequence",
201
+ "instance-key-mismatch"
202
+ ]);
203
+ /**
204
+ * Strip anything that could be secret out of free-form text before it is
205
+ * logged. Defence in depth: nothing here is SUPPOSED to see key material, but a
206
+ * thrown error can carry whatever the thrower put in it, and this daemon holds a
207
+ * private key in memory. PEM blocks, bearer tokens and token-ish query params
208
+ * are replaced; the result is length-capped so a giant blob cannot be smuggled
209
+ * out one line at a time.
210
+ */
211
+ export function sanitizeForLog(text) {
212
+ return (text
213
+ .replace(/-----BEGIN[\s\S]*?-----END[^-]*-----/g, "[redacted-key]")
214
+ .replace(/-----BEGIN[\s\S]*/g, "[redacted-key]")
215
+ // URL userinfo (https://user:password@host) anywhere in free-form text.
216
+ .replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+@/gi, "$1[redacted]@")
217
+ .replace(/\b(bearer|basic)\s+[\w.\-+/=]+/gi, "$1 [redacted]")
218
+ // Credential-ish parameters. The name prefix is matched explicitly rather
219
+ // than with `\b`, because `\b` does not fire after an underscore — which
220
+ // let every `access_token=` / `session_key=` form through untouched.
221
+ .replace(/([\w.-]*(?:token|key|secret|password|passwd|signature|credential)s?)=([^&\s]+)/gi, "$1=[redacted]")
222
+ // HEADER form (`X-Api-Key: literal`, `cookie: sid=…`). The `name=value`
223
+ // rule above cannot see these, because the delimiter is a colon.
224
+ .replace(/^([ \t]*[\w-]*(?:token|key|secret|password|passwd|auth|authorization|cookie|credential)s?)[ \t]*:[ \t]*\S.*$/gim, "$1: [redacted]")
225
+ .slice(0, 300));
226
+ }
227
+ /**
228
+ * Text of a caught value, for a value that is NOT guaranteed to be an `Error`.
229
+ * A rejection can carry anything — a string, an object, `undefined` from a bare
230
+ * `Promise.reject()` — and this daemon's whole contract is that a cycle never
231
+ * throws. Reading `.message` off a non-Error would itself throw, escape the
232
+ * classifier, and land in the CLI's unsanitized fatal handler.
233
+ *
234
+ * EVERY read is inside the `try`, deliberately. Accessing `.message` is not a
235
+ * safe operation: it can be a getter that throws (including on a real `Error`
236
+ * subclass), so a guard that only wraps the `String()` fallback still lets a
237
+ * hostile object escape. The whole inspection is therefore fallible-by-default.
238
+ */
239
+ function errorText(error) {
240
+ try {
241
+ if (error instanceof Error && typeof error.message === "string")
242
+ return error.message;
243
+ const message = error?.message;
244
+ if (typeof message === "string")
245
+ return message;
246
+ return String(error);
247
+ }
248
+ catch {
249
+ // A hostile `message` getter or `toString` still must not break the cycle.
250
+ return "[unrepresentable error]";
251
+ }
252
+ }
253
+ /**
254
+ * True when a logging failure means the status sink is GONE for good rather than
255
+ * momentarily unhappy — a closed or destroyed stream. A piped stdout that the
256
+ * reader closed (`| head -3`, a journald restart) surfaces as EPIPE and never
257
+ * reopens, so the honest response is to stop, not to keep pushing unobservably.
258
+ */
259
+ function isClosedStreamError(error) {
260
+ let code;
261
+ try {
262
+ code = error?.code;
263
+ }
264
+ catch {
265
+ return false;
266
+ }
267
+ return code === "EPIPE" || code === "ERR_STREAM_DESTROYED" || code === "ERR_STREAM_WRITE_AFTER_END";
268
+ }
269
+ /**
270
+ * Read the non-secret shape of the envelope about to be pushed: its sequence
271
+ * number and the cardinality of each collection. Never its contents. Defensive
272
+ * about shape, because a caller can inject any `buildImpl`.
273
+ */
274
+ function payloadShapeOf(envelope) {
275
+ const body = envelope.body;
276
+ const count = (v) => (Array.isArray(v) ? v.length : 0);
277
+ return {
278
+ ...(typeof body?.seq === "number" ? { seq: body.seq } : {}),
279
+ registrations: count(body?.registrations),
280
+ presence: count(body?.presence),
281
+ subagents: count(body?.subagents)
282
+ };
283
+ }
284
+ /**
285
+ * True when `url` is something a push could actually reach: parseable, and
286
+ * http(s). Anything else — an unfilled placeholder, a typo, a `file:` or `ws:`
287
+ * scheme — makes `fetch` throw a parse error that would otherwise be classified
288
+ * as a retryable network failure and retried forever.
289
+ */
290
+ export function isPushableHttpUrl(url) {
291
+ if (typeof url !== "string" || url.trim() === "")
292
+ return false;
293
+ let parsed;
294
+ try {
295
+ parsed = new URL(url);
296
+ }
297
+ catch {
298
+ return false;
299
+ }
300
+ return parsed.protocol === "http:" || parsed.protocol === "https:";
301
+ }
302
+ /**
303
+ * Reduce a URL to scheme + host + path. Drops query and userinfo, which are the
304
+ * two places a credential can hide in a URL, and keeps enough for an operator to
305
+ * recognise which endpoint is being pushed to.
306
+ */
307
+ export function redactEndpoint(url) {
308
+ try {
309
+ const u = new URL(url);
310
+ return `${u.protocol}//${u.host}${u.pathname}`;
311
+ }
312
+ catch {
313
+ return "[unparseable-url]";
314
+ }
315
+ }
316
+ /** True for a status that means "your key is not trusted here". */
317
+ function isAuthRejection(status) {
318
+ return status === 401 || status === 403;
319
+ }
320
+ /** True for a status worth retrying: server-side or rate-limit. */
321
+ function isTransientStatus(status) {
322
+ return status === 408 || status === 429 || status >= 500;
323
+ }
324
+ /** Pull the closed-vocabulary rejection reason out of an accept-side body. */
325
+ function rejectionReasonOf(body) {
326
+ if (!body || typeof body !== "object")
327
+ return undefined;
328
+ const reason = body.reason;
329
+ if (typeof reason === "string" && MIRROR_REJECTION_REASONS.has(reason))
330
+ return reason;
331
+ return undefined;
332
+ }
333
+ /**
334
+ * Create the guarded one-cycle runner: build → sign → POST once, classified.
335
+ *
336
+ * The returned function is the ONLY thing that touches the network. It carries an
337
+ * in-flight guard for CONCURRENT callers of the same runner: while one cycle is
338
+ * running, a second call returns `skipped-overlap` immediately without building
339
+ * an envelope or issuing a request. (The daemon itself awaits each cycle, so it
340
+ * never trips this guard on its own — see the module header.) Exposed so a caller
341
+ * or a test can drive single cycles without the timer loop, exactly as
342
+ * `runSupervisorBeat` is exposed next to `runLoopSupervisor`.
343
+ *
344
+ * Never throws: every failure is classified into a {@link MirrorPushOutcome}.
345
+ */
346
+ export function createMirrorPushRunner(options) {
347
+ const nowFn = options.now ?? (() => Date.now());
348
+ const build = options.buildImpl ??
349
+ ((nowMs) => buildInstanceMirror(createLocalStore({ root: options.root }), options.instance, nowMs));
350
+ const send = options.sendImpl ?? sendRemoteEnvelope;
351
+ let inFlight = false;
352
+ return async function runCycle() {
353
+ // OVERLAP GUARD: a slow push must not stack. Checked before any work, so a
354
+ // skipped cycle costs nothing and, crucially, sends nothing.
355
+ if (inFlight)
356
+ return { outcome: "skipped-overlap", durationMs: 0 };
357
+ inFlight = true;
358
+ const startedAt = nowFn();
359
+ try {
360
+ let envelope;
361
+ try {
362
+ envelope = build(startedAt);
363
+ }
364
+ catch (error) {
365
+ // Local build failure (e.g. the instance is not in this root's
366
+ // registry). Not fatal: an agent can re-register, so we back off and
367
+ // keep looping rather than tearing the daemon down. No request was made.
368
+ return {
369
+ outcome: "build-failed",
370
+ error: sanitizeForLog(errorText(error)),
371
+ durationMs: nowFn() - startedAt
372
+ };
373
+ }
374
+ // Read once, before the send, so the shape is reported even for a failed
375
+ // push (the envelope is what WAS attempted).
376
+ const payload = payloadShapeOf(envelope);
377
+ let status;
378
+ let body;
379
+ try {
380
+ const res = await send(options.url, envelope, {
381
+ by: options.instance,
382
+ privateKeyPem: options.privateKeyPem
383
+ });
384
+ status = res.status;
385
+ body = res.body;
386
+ }
387
+ catch (error) {
388
+ // Transport threw: DNS, refused, TLS, timeout. Retryable.
389
+ return {
390
+ outcome: "transient",
391
+ error: sanitizeForLog(errorText(error)),
392
+ durationMs: nowFn() - startedAt,
393
+ payload
394
+ };
395
+ }
396
+ const durationMs = nowFn() - startedAt;
397
+ const reason = rejectionReasonOf(body);
398
+ if (status >= 200 && status < 300) {
399
+ return { outcome: "ok", status, durationMs, payload };
400
+ }
401
+ if (isAuthRejection(status)) {
402
+ // The key itself is refused. Counted toward the stop budget.
403
+ return { outcome: "auth-rejected", status, ...(reason ? { reason } : {}), durationMs, payload };
404
+ }
405
+ if (isTransientStatus(status)) {
406
+ return { outcome: "transient", status, ...(reason ? { reason } : {}), durationMs, payload };
407
+ }
408
+ // Other 4xx: a rejected envelope (stale sequence, replay, clock skew).
409
+ // Some of these self-heal as the sequence advances, so we keep looping —
410
+ // but backed off, so a permanently malformed push is not a hot loop.
411
+ return { outcome: "rejected", status, ...(reason ? { reason } : {}), durationMs, payload };
412
+ }
413
+ finally {
414
+ inFlight = false;
415
+ }
416
+ };
417
+ }
418
+ /** Abort-aware sleep. Resolves early (does not reject) when aborted. */
419
+ function delay(ms, signal) {
420
+ return new Promise((resolve) => {
421
+ if (signal?.aborted)
422
+ return resolve();
423
+ const timer = setTimeout(() => {
424
+ signal?.removeEventListener("abort", onAbort);
425
+ resolve();
426
+ }, ms);
427
+ function onAbort() {
428
+ clearTimeout(timer);
429
+ resolve();
430
+ }
431
+ signal?.addEventListener("abort", onAbort, { once: true });
432
+ });
433
+ }
434
+ /**
435
+ * Run the live mirror push until `signal` aborts, `max` cycles elapse, or the
436
+ * endpoint has refused this key often enough to stop (see
437
+ * {@link MIRROR_PUSH_REENROLLMENT_MESSAGE}).
438
+ *
439
+ * This is what the systemd `--user` unit runs. It is NEVER on any default code
440
+ * path: no caller reaches it without an explicit interval, and the kill-switch
441
+ * short-circuits it before the first request.
442
+ */
443
+ export async function runMirrorPushDaemon(options) {
444
+ const env = options.env ?? process.env;
445
+ const nowFn = options.now ?? (() => Date.now());
446
+ const random = options.random ?? (() => Math.random());
447
+ const sleep = options.sleep ?? delay;
448
+ const intervalMs = options.intervalMs && options.intervalMs > 0
449
+ ? options.intervalMs
450
+ : DEFAULT_MIRROR_PUSH_INTERVAL_MS;
451
+ const authLimit = options.authFailureLimit && options.authFailureLimit > 0
452
+ ? options.authFailureLimit
453
+ : DEFAULT_MIRROR_AUTH_FAILURE_LIMIT;
454
+ const rejectLimit = options.rejectLimit && options.rejectLimit > 0
455
+ ? options.rejectLimit
456
+ : DEFAULT_MIRROR_REJECT_LIMIT;
457
+ const buildLimit = options.buildFailureLimit && options.buildFailureLimit > 0
458
+ ? options.buildFailureLimit
459
+ : DEFAULT_MIRROR_BUILD_FAILURE_LIMIT;
460
+ const backoffBase = options.backoffBaseMs && options.backoffBaseMs > 0
461
+ ? options.backoffBaseMs
462
+ : MIRROR_PUSH_BACKOFF_BASE_MS;
463
+ const backoffMax = options.backoffMaxMs && options.backoffMaxMs > 0
464
+ ? options.backoffMaxMs
465
+ : MIRROR_PUSH_BACKOFF_MAX_MS;
466
+ const endpoint = redactEndpoint(options.url);
467
+ let cycles = 0;
468
+ let ok = 0;
469
+ let failures = 0;
470
+ let skippedOverlap = 0;
471
+ let authFailures = 0;
472
+ let rejections = 0;
473
+ let buildFailures = 0;
474
+ let logFailures = 0;
475
+ let consecutiveFailures = 0;
476
+ const finish = (stopReason, message) => ({
477
+ cycles,
478
+ ok,
479
+ failures,
480
+ skippedOverlap,
481
+ authFailures,
482
+ rejections,
483
+ buildFailures,
484
+ logFailures,
485
+ stopReason,
486
+ ...(message ? { message } : {})
487
+ });
488
+ // KILL-SWITCH, checked BEFORE the first cycle: a frozen daemon must not emit
489
+ // a single request, not even one.
490
+ if (mirrorPushGloballyDisabled(env))
491
+ return finish("kill-switch");
492
+ if (options.signal?.aborted)
493
+ return finish("aborted");
494
+ // A target `fetch` cannot even parse would throw a parse TypeError that this
495
+ // daemon would classify as a retryable network failure and retry forever. Stop
496
+ // before the first cycle instead — the CLI refuses such a URL up front, but the
497
+ // library is public API and must not be loopable into that state either.
498
+ if (!isPushableHttpUrl(options.url)) {
499
+ return finish("config-invalid", MIRROR_PUSH_INVALID_URL_MESSAGE);
500
+ }
501
+ const runCycle = options.runner ?? createMirrorPushRunner(options);
502
+ // Monotonic slot anchor — cycle n is due at `anchor + n × intervalMs`, so a
503
+ // slow cycle does not push every later cycle late (no drift). Re-anchored
504
+ // after a backoff, whose delay is deliberate rather than lateness.
505
+ let anchor = nowFn();
506
+ let slot = 0;
507
+ for (;;) {
508
+ // Re-checked each cycle so a mutated environment freezes an already-running
509
+ // daemon at the next beat instead of only at (re)start.
510
+ if (mirrorPushGloballyDisabled(env))
511
+ return finish("kill-switch");
512
+ if (options.signal?.aborted)
513
+ return finish("aborted");
514
+ const result = await runCycle();
515
+ cycles += 1;
516
+ if (result.outcome === "skipped-overlap") {
517
+ skippedOverlap += 1;
518
+ }
519
+ else if (result.outcome === "ok") {
520
+ ok += 1;
521
+ consecutiveFailures = 0;
522
+ // Only a genuinely ACCEPTED push clears either stop budget.
523
+ authFailures = 0;
524
+ rejections = 0;
525
+ buildFailures = 0;
526
+ }
527
+ else {
528
+ failures += 1;
529
+ consecutiveFailures += 1;
530
+ if (result.outcome === "auth-rejected")
531
+ authFailures += 1;
532
+ if (result.outcome === "rejected")
533
+ rejections += 1;
534
+ if (result.outcome === "build-failed")
535
+ buildFailures += 1;
536
+ }
537
+ /**
538
+ * Emit the status line. OBSERVABILITY MUST NOT BREAK THE PIPELINE: `onCycle`
539
+ * is caller-supplied and writes to a stream the caller owns, so it can throw
540
+ * — the common case being EPIPE once a piped stdout closes (`| head -3`, a
541
+ * journald restart). Unguarded, that rejection escaped the daemon into the
542
+ * CLI's raw fatal handler and pinned the unit `failed` with a message
543
+ * matching none of the documented stops.
544
+ *
545
+ * A dead sink is not a reason to keep pushing blind, though: a closed stream
546
+ * never reopens, so we stop CLEANLY (exit 0, no message) instead of running
547
+ * unobservable. Any other logging error is counted and ignored.
548
+ *
549
+ * Returns false when the caller should stop.
550
+ */
551
+ const emit = async (nextInMs) => {
552
+ if (!options.onCycle)
553
+ return true;
554
+ try {
555
+ await options.onCycle({
556
+ cycle: cycles,
557
+ at: new Date(nowFn()).toISOString(),
558
+ instance: options.instance,
559
+ endpoint,
560
+ outcome: result.outcome,
561
+ ...(result.status !== undefined ? { status: result.status } : {}),
562
+ ...(result.reason ? { reason: result.reason } : {}),
563
+ ...(result.error ? { error: result.error } : {}),
564
+ durationMs: result.durationMs,
565
+ ...(result.payload?.seq !== undefined ? { seq: result.payload.seq } : {}),
566
+ ...(result.payload
567
+ ? {
568
+ registrations: result.payload.registrations,
569
+ presence: result.payload.presence,
570
+ subagents: result.payload.subagents
571
+ }
572
+ : {}),
573
+ ...(nextInMs !== undefined ? { nextInMs } : {}),
574
+ authFailures,
575
+ rejections,
576
+ buildFailures
577
+ });
578
+ return true;
579
+ }
580
+ catch (error) {
581
+ logFailures += 1;
582
+ return !isClosedStreamError(error);
583
+ }
584
+ };
585
+ // AUTH STOP: the budget is spent, so stop instead of hammering a server
586
+ // that is refusing this key. Backoff already happened between attempts.
587
+ if (authFailures >= authLimit) {
588
+ await emit(undefined);
589
+ return finish("auth-stop", MIRROR_PUSH_REENROLLMENT_MESSAGE);
590
+ }
591
+ // REJECT STOP: the same reasoning for a request the endpoint keeps refusing
592
+ // on non-auth grounds. A looser budget, because a fencing rejection can
593
+ // genuinely clear — but not an unbounded one, because a wrong path cannot.
594
+ if (rejections >= rejectLimit) {
595
+ await emit(undefined);
596
+ return finish("reject-stop", MIRROR_PUSH_REJECTED_MESSAGE);
597
+ }
598
+ // BUILD STOP: we cannot even assemble a mirror. Nothing was sent and nothing
599
+ // will be, so idling `active (running)` forever would report green while the
600
+ // feed is dead. A wrong H2A_ROOT never self-heals — terminate loudly.
601
+ if (buildFailures >= buildLimit) {
602
+ await emit(undefined);
603
+ return finish("build-stop", MIRROR_PUSH_BUILD_FAILED_MESSAGE);
604
+ }
605
+ if (options.max !== undefined && cycles >= options.max) {
606
+ await emit(undefined);
607
+ return finish("max-cycles");
608
+ }
609
+ if (options.signal?.aborted) {
610
+ await emit(undefined);
611
+ return finish("aborted");
612
+ }
613
+ // Schedule the next cycle: backoff after a failure, otherwise the next
614
+ // monotonic slot with bounded jitter.
615
+ let waitMs;
616
+ if (consecutiveFailures > 0) {
617
+ const exp = Math.min(backoffMax, backoffBase * 2 ** (consecutiveFailures - 1));
618
+ waitMs = Math.max(0, Math.round(exp * (1 + MIRROR_PUSH_JITTER_FRACTION * (random() * 2 - 1))));
619
+ // The backoff wait is intentional, so the drift anchor restarts from here.
620
+ anchor = nowFn() + waitMs;
621
+ slot = 0;
622
+ }
623
+ else {
624
+ slot += 1;
625
+ let due = anchor + slot * intervalMs;
626
+ // A cycle that overran one or more whole slots must not fire the missed
627
+ // ones back-to-back: skip straight to the next slot in the future.
628
+ while (due <= nowFn()) {
629
+ slot += 1;
630
+ due = anchor + slot * intervalMs;
631
+ }
632
+ const jitter = intervalMs * MIRROR_PUSH_JITTER_FRACTION * (random() * 2 - 1);
633
+ waitMs = Math.max(0, Math.round(due - nowFn() + jitter));
634
+ }
635
+ // A dead status sink stops the daemon cleanly rather than leaving it to push
636
+ // where nobody can see what it is doing.
637
+ if (!(await emit(waitMs)))
638
+ return finish("log-unavailable");
639
+ await sleep(waitMs, options.signal);
640
+ if (options.signal?.aborted)
641
+ return finish("aborted");
642
+ }
643
+ }
644
+ //# sourceMappingURL=push-daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-daemon.js","sourceRoot":"","sources":["../../../src/runtime/mirror/push-daemon.ts"],"names":[],"mappings":"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"}