failproofai 1.0.11 → 1.0.12-beta.1

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 (342) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +23 -23
  3. package/.next/standalone/.next/prerender-manifest.json +4 -4
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
  8. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.rsc +2 -2
  12. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  13. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  16. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page.js +3 -3
  18. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  21. package/.next/standalone/.next/server/app/_not-found.rsc +3 -3
  22. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/invite/route.js +5 -6
  26. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/audit/run/route.js +24 -24
  28. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/audit/status/route.js +2 -2
  30. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +4 -5
  32. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +6 -7
  34. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/auth/logout/route.js +6 -7
  36. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/auth/status/route.js +5 -6
  38. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +2 -2
  40. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  42. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  43. package/.next/standalone/.next/server/app/audit/page.js +4 -4
  44. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/index.html +1 -1
  47. package/.next/standalone/.next/server/app/index.rsc +3 -3
  48. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  49. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  50. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  51. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  52. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  53. package/.next/standalone/.next/server/app/page.js +2 -2
  54. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
  57. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  58. package/.next/standalone/.next/server/app/policies/page.js +7 -7
  59. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  62. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  63. package/.next/standalone/.next/server/app/project/[name]/page.js +7 -7
  64. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  67. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  68. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  69. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +8 -8
  70. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  73. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  74. package/.next/standalone/.next/server/app/projects/page.js +3 -3
  75. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +3 -3
  78. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  79. package/.next/standalone/.next/server/app/settings/page.js +10 -10
  80. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  82. package/.next/standalone/.next/server/chunks/{[externals]__0qkp92tjfvw8r._.js → [externals]__0vt9i6fqinjne._.js} +1 -1
  83. package/.next/standalone/.next/server/chunks/[externals]__1x24dzcbbq6-g._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__02vous7mpi2xm._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__03i5o4a840guz._.js +3 -0
  86. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__a_je8fsn65._.js +3 -0
  87. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_hsnj_a2mvl_._.js +3 -0
  88. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1izwqj_ij_9x_._.js → [root-of-the-server]__0f_4g-vazrvxv._.js} +1 -1
  89. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-oi4gdtmlo5._.js +3 -0
  90. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0swiyzbmvja2d._.js → [root-of-the-server]__0t9ufnv5hi2hq._.js} +5 -5
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wg9dk8x8bnau._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12kq3x-h7t7i1._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a5zkndjwlc13._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1r7kbfkiw2xmu._.js → [root-of-the-server]__1aaw59g-5uty7._.js} +12 -12
  95. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hqpg6vgmfexv._.js +3 -0
  96. package/.next/standalone/.next/server/chunks/_09dz7xva4ce_2._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/_0hf5q4xzyg40j._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
  100. package/.next/standalone/.next/server/chunks/_19011-u44143j._.js +1 -1
  101. package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +1 -1
  102. package/.next/standalone/.next/server/chunks/_1vslkoe35wok6._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/{_1ixl-kxq_ctsa._.js → _1y590mjzpkbos._.js} +2 -2
  104. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/src_hooks_0_em82s16zfym._.js +5 -0
  106. package/.next/standalone/.next/server/chunks/src_hooks_builtin-policies_ts_1yq5ybgx1v98e._.js +3 -0
  107. package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3h94wnn._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/src_hooks_daemon-client_ts_0il_yu1zc0291._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn_4twyh._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01j58mdcdw0vn._.js +3 -0
  111. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0588st-tpiuia._.js +3 -0
  112. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_a8z2ldp2v3n._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0vcyntk4snf0f._.js → [root-of-the-server]__0b78b0j8iyv6l._.js} +1 -1
  115. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ffu2-38y03ic._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g8b0kyorya-t._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
  119. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1_xbg2kx30wp-._.js → [root-of-the-server]__0naevg4bcoh54._.js} +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
  121. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__075uro8t92s0_._.js → [root-of-the-server]__0pwj2h2efe5f-._.js} +3 -3
  122. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0zn1d4blhd3bu._.js +3 -0
  123. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
  124. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17r4zrwanhp6r._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1lnfv02ucky7m._.js +3 -0
  129. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mc9-zlnh656_._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
  131. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1s2-ck3k3rsoo._.js +3 -0
  132. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1l1qgu5mfapkh._.js → [root-of-the-server]__1vx7o8ukefudh._.js} +1 -1
  133. package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
  134. package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
  135. package/.next/standalone/.next/server/chunks/ssr/_128ebxr83nk6g._.js +3 -0
  136. package/.next/standalone/.next/server/chunks/ssr/_1_ozgifqv1ssi._.js +1 -1
  137. package/.next/standalone/.next/server/chunks/ssr/{_1gb0ifpkowwub._.js → _1a3tubds7s7ow._.js} +10 -9
  138. package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
  140. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
  141. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
  142. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
  143. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +1 -1
  144. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
  145. package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_1f_ymmaonkksc.js → node_modules_html-to-image_es_index_1i8oid1gc7s1f.js} +1 -1
  146. package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
  147. package/.next/standalone/.next/server/chunks/ssr/src_hooks_06kzv9ddabn3_._.js +1 -1
  148. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0agdmptetetdt._.js +5 -0
  149. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0mdwgjisv4fub._.js +5 -0
  150. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4l1tzrm._.js +1 -1
  151. package/.next/standalone/.next/server/chunks/ssr/src_hooks_daemon-client_ts_0k41_i7jg6ndv._.js +1 -1
  152. package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me658zqmh_._.js +1 -1
  153. package/.next/standalone/.next/server/middleware-build-manifest.js +23 -23
  154. package/.next/standalone/.next/server/middleware.js +2 -2
  155. package/.next/standalone/.next/server/pages/404.html +1 -1
  156. package/.next/standalone/.next/server/pages/500.html +1 -1
  157. package/.next/standalone/.next/server/preview-props.json +3 -3
  158. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  159. package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
  160. package/.next/standalone/.next/static/chunks/{0frxv4_m-m2u5.js → 063al_q720fkj.js} +1 -1
  161. package/.next/standalone/.next/static/chunks/0_zfad4co-t2z.js +1 -0
  162. package/.next/standalone/.next/static/chunks/0jutamwqz8pg5.js +1 -0
  163. package/.next/standalone/.next/static/chunks/114hbolvrv94e.js +1 -0
  164. package/.next/standalone/.next/static/chunks/{37stoe-_yd852.js → 18433qz-8njv3.js} +1 -1
  165. package/.next/standalone/.next/static/chunks/{1kwj8uqxuv85t.js → 1b32-afqacaen.js} +1 -1
  166. package/.next/standalone/.next/static/chunks/{44a7k2_62qc-9.js → 1p-hsi58i-6h0.js} +2 -2
  167. package/.next/standalone/.next/static/chunks/{302llgh97ce6w.js → 2-tf6_7u623kd.js} +1 -1
  168. package/.next/standalone/.next/static/chunks/{1_c0dc7zqj1n7.js → 24w3x2da9sk49.js} +1 -1
  169. package/.next/standalone/.next/static/chunks/2tjfp9dirxnku.js +1 -0
  170. package/.next/standalone/.next/static/chunks/{16z6_d7sp61jm.js → 3-pku9qwv1yfu.js} +1 -1
  171. package/.next/standalone/.next/static/chunks/{15rm15u5a6dua.js → 42e8zab314654.js} +1 -1
  172. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +41 -0
  173. package/.next/standalone/fp-cloud-cli/README.md +42 -1
  174. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +117 -12
  175. package/.next/standalone/fp-cloud-cli/fp_cli/commands/fleet_cmds.py +285 -19
  176. package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +84 -18
  177. package/.next/standalone/fp-cloud-cli/fp_cli/enforcement.py +170 -6
  178. package/.next/standalone/fp-cloud-cli/fp_cli/models.py +89 -6
  179. package/.next/standalone/fp-cloud-cli/fp_cli/output.py +259 -21
  180. package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +8 -5
  181. package/.next/standalone/fp-cloud-cli/skill/SKILL.md +2 -2
  182. package/.next/standalone/fp-cloud-cli/skill/references/commands.md +17 -9
  183. package/.next/standalone/fp-cloud-cli/tests/test_cloud_jev.py +692 -0
  184. package/.next/standalone/fp-cloud-cli/tests/test_enforcement_logic.py +46 -0
  185. package/.next/standalone/fp-cloud-cli/tests/test_output.py +23 -0
  186. package/.next/standalone/fp-cloud-cli/uv.lock +6 -6
  187. package/.next/standalone/hermes-plugin/README.md +6 -4
  188. package/.next/standalone/hermes-plugin/__init__.py +16 -0
  189. package/.next/standalone/hermes-plugin/client.py +5 -1
  190. package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
  191. package/.next/standalone/node_modules/@next/env/package.json +1 -1
  192. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/context.js +72 -0
  193. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/diag.js +84 -0
  194. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/metrics.js +50 -0
  195. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/propagation.js +80 -0
  196. package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/trace.js +70 -0
  197. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/context-helpers.js +52 -0
  198. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/baggage-impl.js +44 -0
  199. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/symbol.js +12 -0
  200. package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/utils.js +41 -0
  201. package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/NoopContextManager.js +27 -0
  202. package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/context.js +52 -0
  203. package/.next/standalone/node_modules/@opentelemetry/api/build/src/context-api.js +16 -0
  204. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/ComponentLogger.js +47 -0
  205. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/consoleLogger.js +73 -0
  206. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/internal/logLevelLogger.js +34 -0
  207. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/types.js +33 -0
  208. package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag-api.js +20 -0
  209. package/.next/standalone/node_modules/@opentelemetry/api/build/src/index.js +71 -0
  210. package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/global-utils.js +60 -0
  211. package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/semver.js +111 -0
  212. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/Metric.js +18 -0
  213. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeter.js +118 -0
  214. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeterProvider.js +20 -0
  215. package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics-api.js +17 -0
  216. package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/NoopTextMapPropagator.js +23 -0
  217. package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/TextMapPropagator.js +36 -0
  218. package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation-api.js +17 -0
  219. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NonRecordingSpan.js +58 -0
  220. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracer.js +68 -0
  221. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracerProvider.js +21 -0
  222. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracer.js +46 -0
  223. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracerProvider.js +46 -0
  224. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/SamplingResult.js +33 -0
  225. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/context-utils.js +71 -0
  226. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-impl.js +94 -0
  227. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-validators.js +35 -0
  228. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/utils.js +16 -0
  229. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/invalid-span-constants.js +25 -0
  230. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/span_kind.js +38 -0
  231. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/spancontext-utils.js +66 -0
  232. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/status.js +29 -0
  233. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/trace_flags.js +18 -0
  234. package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace-api.js +17 -0
  235. package/.next/standalone/node_modules/@opentelemetry/api/build/src/version.js +10 -0
  236. package/.next/standalone/node_modules/@opentelemetry/api/package.json +96 -0
  237. package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
  238. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +2 -2
  239. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +2 -2
  240. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +1 -1
  241. package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
  242. package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +1 -1
  243. package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
  244. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
  245. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
  246. package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
  247. package/.next/standalone/node_modules/next/dist/server/lib/generate-agent-files.js +3 -3
  248. package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +1 -1
  249. package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
  250. package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +1 -1
  251. package/.next/standalone/node_modules/next/dist/server/typescript/rules/config.js +2 -2
  252. package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1 -1
  253. package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
  254. package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
  255. package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
  256. package/.next/standalone/node_modules/next/package.json +11 -11
  257. package/.next/standalone/package.json +11 -11
  258. package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
  259. package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
  260. package/.next/standalone/sdk/python/pyproject.toml +19 -0
  261. package/.next/standalone/sdk/python/uv.lock +520 -301
  262. package/.next/standalone/sdk/typescript/CHANGELOG.md +13 -0
  263. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +4 -13
  264. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +2 -1
  265. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +4 -13
  266. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +3 -0
  267. package/.next/standalone/sdk/typescript/package-lock.json +178 -162
  268. package/.next/standalone/sdk/typescript/package.json +1 -1
  269. package/.next/standalone/sdk/typescript/src/version.ts +1 -1
  270. package/.next/standalone/server.js +1 -1
  271. package/bin/failproofai.mjs +17 -1
  272. package/dist/cli.mjs +2866 -1124
  273. package/dist/worker.mjs +1450 -145
  274. package/hermes-plugin/README.md +6 -4
  275. package/hermes-plugin/__init__.py +16 -0
  276. package/hermes-plugin/client.py +5 -1
  277. package/hermes-plugin/plugin.yaml +1 -1
  278. package/package.json +11 -11
  279. package/src/hooks/agent-roster.ts +172 -0
  280. package/src/hooks/agent-targets.ts +60 -0
  281. package/src/hooks/cloud-connection.ts +97 -27
  282. package/src/hooks/cloud-enrollment-cli.ts +7 -4
  283. package/src/hooks/cloud-managed-policies.ts +380 -20
  284. package/src/hooks/cloud-policy-errors.ts +481 -0
  285. package/src/hooks/config-status.ts +1 -1
  286. package/src/hooks/custom-hooks-loader.ts +26 -3
  287. package/src/hooks/daemon-client.ts +9 -4
  288. package/src/hooks/daemon-service.ts +2 -1
  289. package/src/hooks/effective-reviewers.ts +22 -1
  290. package/src/hooks/fp-home.ts +6 -0
  291. package/src/hooks/handler.ts +235 -18
  292. package/src/hooks/health-probe.ts +15 -0
  293. package/src/hooks/integrations.ts +18 -11
  294. package/src/hooks/jev-cli.ts +197 -0
  295. package/src/hooks/jev-cloud-connection.ts +92 -0
  296. package/src/hooks/manager.ts +122 -16
  297. package/src/hooks/pack-failclosed.ts +2 -0
  298. package/src/hooks/pack-manifest.ts +8 -1
  299. package/src/hooks/policy-evaluator.ts +5 -1
  300. package/src/hooks/policy-registry.ts +3 -2
  301. package/src/hooks/policy-reviewability.ts +21 -5
  302. package/src/hooks/semantic/cloud-jev-health.ts +227 -0
  303. package/src/hooks/semantic/cloud-jev.ts +677 -0
  304. package/src/hooks/semantic/jev-client.ts +18 -1
  305. package/src/hooks/semantic/jev-config.ts +173 -3
  306. package/src/hooks/semantic/jev-review.ts +129 -10
  307. package/src/hooks/semantic/pack-policies.ts +2 -1
  308. package/src/hooks/semantic/types.ts +8 -0
  309. package/src/hooks/session-pause-cli.ts +1 -1
  310. package/src/hooks/worker-server.ts +5 -1
  311. package/.next/standalone/.next/server/chunks/[externals]__0hjaw70fchx66._.js +0 -3
  312. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07l68zv0hqdiu._.js +0 -3
  313. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0car70pylmvor._.js +0 -3
  314. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0u3i025_setk_._.js +0 -3
  315. package/.next/standalone/.next/server/chunks/[root-of-the-server]__10a2f6s636yc7._.js +0 -3
  316. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qt5u58xrcuk6._.js +0 -3
  317. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_077n_4ip5__fu._.js +0 -3
  318. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mqvvxcn6v0op._.js +0 -3
  319. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0pb7ds5g0vzgn._.js +0 -3
  320. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1gasm5xkeqmm3._.js +0 -3
  321. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1q1heqmkhh8l4._.js +0 -3
  322. package/.next/standalone/.next/server/chunks/src_hooks_1aveq0uhs2t1b._.js +0 -5
  323. package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7cyqlb2._.js +0 -3
  324. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0888k4s6spfmh._.js +0 -3
  325. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_bflu046ep5j._.js +0 -3
  326. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_lbstb5x2t15._.js +0 -3
  327. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fdwgktjfhedo._.js +0 -3
  328. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s4deza787asx._.js +0 -3
  329. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__18qe-hu0gwqm4._.js +0 -3
  330. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_p_9xe520fex._.js +0 -3
  331. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1fmhm8_s9i4re._.js +0 -3
  332. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1g76awtnmimd1._.js +0 -3
  333. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pczevlpk5lxh._.js +0 -3
  334. package/.next/standalone/.next/server/chunks/ssr/_0dc-of_bn0cim._.js +0 -3
  335. package/.next/standalone/.next/server/chunks/ssr/src_hooks_effective-reviewers_ts_1h4wtvo55j16x._.js +0 -5
  336. package/.next/standalone/.next/static/chunks/0m-tv1y6ghhtk.js +0 -1
  337. package/.next/standalone/.next/static/chunks/0ol2gj4ntfn56.js +0 -1
  338. package/.next/standalone/.next/static/chunks/3hj5_7i3nw4zj.js +0 -1
  339. package/.next/standalone/.next/static/chunks/3iyoapeoq_hup.js +0 -1
  340. /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_buildManifest.js +0 -0
  341. /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_clientMiddlewareManifest.js +0 -0
  342. /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_ssgManifest.js +0 -0
package/dist/worker.mjs CHANGED
@@ -26,8 +26,9 @@ var __esm = (fn, res, err) => () => {
26
26
  };
27
27
 
28
28
  // src/hooks/types.ts
29
- var CODEX_EVENT_MAP, CODEX_TOOL_MAP, HERMES_TOOL_MAP, HERMES_TOOL_INPUT_MAP, HERMES_EVENT_MAP, COPILOT_TOOL_MAP, COPILOT_TOOL_INPUT_MAP, CURSOR_EVENT_MAP, CURSOR_TOOL_MAP, OPENCODE_TOOL_MAP, OPENCODE_TOOL_INPUT_MAP, PI_EVENT_MAP, PI_TOOL_MAP, PI_TOOL_INPUT_MAP, OPENCLAW_EVENT_MAP, OPENCLAW_TOOL_MAP, OPENCLAW_TOOL_INPUT_MAP, FACTORY_TOOL_MAP, DEVIN_TOOL_MAP, ANTIGRAVITY_EVENT_MAP, ANTIGRAVITY_TOOL_MAP, ANTIGRAVITY_TOOL_INPUT_MAP, GOOSE_TOOL_MAP, GOOSE_TOOL_INPUT_MAP, HOOK_EVENT_TYPES, CLAUDE_INSTALL_EVENT_TYPES;
29
+ var INTEGRATION_TYPES, CODEX_EVENT_MAP, CODEX_TOOL_MAP, HERMES_TOOL_MAP, HERMES_TOOL_INPUT_MAP, HERMES_EVENT_MAP, COPILOT_TOOL_MAP, COPILOT_TOOL_INPUT_MAP, CURSOR_EVENT_MAP, CURSOR_TOOL_MAP, OPENCODE_TOOL_MAP, OPENCODE_TOOL_INPUT_MAP, PI_EVENT_MAP, PI_TOOL_MAP, PI_TOOL_INPUT_MAP, OPENCLAW_EVENT_MAP, OPENCLAW_TOOL_MAP, OPENCLAW_TOOL_INPUT_MAP, FACTORY_TOOL_MAP, DEVIN_TOOL_MAP, ANTIGRAVITY_EVENT_MAP, ANTIGRAVITY_TOOL_MAP, ANTIGRAVITY_TOOL_INPUT_MAP, GOOSE_TOOL_MAP, GOOSE_TOOL_INPUT_MAP, HOOK_EVENT_TYPES, CLAUDE_INSTALL_EVENT_TYPES;
30
30
  var init_types = __esm(() => {
31
+ INTEGRATION_TYPES = ["claude", "codex", "copilot", "cursor", "opencode", "pi", "hermes", "openclaw", "factory", "devin", "antigravity", "goose"];
31
32
  CODEX_EVENT_MAP = {
32
33
  session_start: "SessionStart",
33
34
  pre_tool_use: "PreToolUse",
@@ -381,7 +382,7 @@ function failproofaiHome(home) {
381
382
  return resolve(home, ".failproofai");
382
383
  return process.env.FAILPROOFAI_HOME || resolve(homedir(), ".failproofai");
383
384
  }
384
- var LAYOUT_VERSION = 4, at = (...parts) => resolve(failproofaiHome(), ...parts), atHome = (home, ...parts) => home ? resolve(failproofaiHome(home), ...parts) : at(...parts), versionFile = (home) => atHome(home, "VERSION"), configFile = (home) => atHome(home, "config.json"), credentialsFile = (home) => atHome(home, "credentials.json"), jevConfigFile = (home) => atHome(home, "jev.json"), policiesDir = (home) => atHome(home, "policies"), customPoliciesDir, globalPolicyConfigFile = (home) => atHome(home, "policies-config.json"), cloudPoliciesDir = (home) => resolve(policiesDir(home), "cloud-policies"), packsDir = (home) => resolve(policiesDir(home), "packs"), packsInstalledFile = (home) => resolve(packsDir(home), "installed.json"), hookActivityDir = (home) => atHome(home, "hook-activity"), stateDir = (home) => atHome(home, "state"), shimsDir = (home) => resolve(stateDir(home), "shims"), sessionPauseDir = () => resolve(stateDir(), "sessions"), semanticDir = () => resolve(stateDir(), "semantic"), telemetryIdFile = (home) => resolve(stateDir(home), "telemetry-id"), codexSessionPathsFile = (home) => resolve(stateDir(home), "codex-session-paths.json"), logsDir = (home) => atHome(home, "logs"), legacy;
385
+ var LAYOUT_VERSION = 4, at = (...parts) => resolve(failproofaiHome(), ...parts), atHome = (home, ...parts) => home ? resolve(failproofaiHome(home), ...parts) : at(...parts), versionFile = (home) => atHome(home, "VERSION"), configFile = (home) => atHome(home, "config.json"), credentialsFile = (home) => atHome(home, "credentials.json"), jevConfigFile = (home) => atHome(home, "jev.json"), agentRosterFile = (home) => atHome(home, "agents", "roster.json"), policiesDir = (home) => atHome(home, "policies"), customPoliciesDir, globalPolicyConfigFile = (home) => atHome(home, "policies-config.json"), cloudPoliciesDir = (home) => resolve(policiesDir(home), "cloud-policies"), packsDir = (home) => resolve(policiesDir(home), "packs"), packsInstalledFile = (home) => resolve(packsDir(home), "installed.json"), hookActivityDir = (home) => atHome(home, "hook-activity"), stateDir = (home) => atHome(home, "state"), shimsDir = (home) => resolve(stateDir(home), "shims"), sessionPauseDir = () => resolve(stateDir(), "sessions"), semanticDir = () => resolve(stateDir(), "semantic"), telemetryIdFile = (home) => resolve(stateDir(home), "telemetry-id"), codexSessionPathsFile = (home) => resolve(stateDir(home), "codex-session-paths.json"), logsDir = (home) => atHome(home, "logs"), legacy;
385
386
  var init_fp_home = __esm(() => {
386
387
  customPoliciesDir = policiesDir;
387
388
  legacy = {
@@ -1165,9 +1166,55 @@ function instruct(reason) {
1165
1166
  }
1166
1167
 
1167
1168
  // package.json
1168
- var version = "1.0.11";
1169
+ var version = "1.0.12-beta.1";
1169
1170
  var init_package = () => {};
1170
1171
 
1172
+ // src/hooks/agent-targets.ts
1173
+ function validAgentIdentity(value) {
1174
+ if (!value || typeof value !== "object" || Array.isArray(value))
1175
+ return false;
1176
+ const agent = value;
1177
+ return Object.keys(agent).every((key) => key === "integration" || key === "instanceId") && typeof agent.integration === "string" && integrations.has(agent.integration) && typeof agent.instanceId === "string" && INSTANCE_ID_RE.test(agent.instanceId);
1178
+ }
1179
+ function parseAgentTargets(value, schemaVersion) {
1180
+ if (value === undefined || value === null)
1181
+ return;
1182
+ if (schemaVersion < 3 || !Array.isArray(value) || value.length < 1 || value.length > 32) {
1183
+ throw new Error("invalid agentTargets in cloud-managed active manifest");
1184
+ }
1185
+ const seen = new Set;
1186
+ return value.map((raw) => {
1187
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
1188
+ throw new Error("invalid agentTargets in cloud-managed active manifest");
1189
+ }
1190
+ const entry = raw;
1191
+ if (Object.keys(entry).some((key) => key !== "integration" && key !== "instanceId") || typeof entry.integration !== "string" || !integrations.has(entry.integration) || entry.instanceId !== undefined && (typeof entry.instanceId !== "string" || !INSTANCE_ID_RE.test(entry.instanceId))) {
1192
+ throw new Error("invalid agentTargets in cloud-managed active manifest");
1193
+ }
1194
+ const key = `${entry.integration}\x00${entry.instanceId ?? ""}`;
1195
+ if (seen.has(key))
1196
+ throw new Error("duplicate agentTargets in cloud-managed active manifest");
1197
+ seen.add(key);
1198
+ return {
1199
+ integration: entry.integration,
1200
+ ...entry.instanceId !== undefined ? { instanceId: entry.instanceId } : {}
1201
+ };
1202
+ });
1203
+ }
1204
+ function agentTargetsMatch(targets, agent) {
1205
+ if (targets === undefined)
1206
+ return true;
1207
+ if (!validAgentIdentity(agent))
1208
+ return false;
1209
+ return targets.some((target) => target.integration === agent.integration && (target.instanceId === undefined || target.instanceId === agent.instanceId));
1210
+ }
1211
+ var INSTANCE_ID_RE, integrations;
1212
+ var init_agent_targets = __esm(() => {
1213
+ init_types();
1214
+ INSTANCE_ID_RE = /^agt_[0-9a-f]{16,32}$/;
1215
+ integrations = new Set(INTEGRATION_TYPES);
1216
+ });
1217
+
1171
1218
  // src/hooks/policy-types.ts
1172
1219
  function effectiveAuthority(p) {
1173
1220
  if (p.alwaysOn === true)
@@ -1298,11 +1345,22 @@ var init_policy_authority = __esm(() => {
1298
1345
 
1299
1346
  // src/hooks/cloud-managed-policies.ts
1300
1347
  import { createHash } from "node:crypto";
1301
- import { existsSync as existsSync4, readFileSync as readFileSync2, realpathSync, rmSync } from "node:fs";
1348
+ import { existsSync as existsSync4, readFileSync as readFileSync2, realpathSync, rmSync, statSync as statSync3 } from "node:fs";
1302
1349
  import { isAbsolute, relative, resolve as resolve3 } from "node:path";
1303
1350
  function cloudManagedPolicyRoot() {
1304
1351
  return process.env.FAILPROOFAI_CLOUD_POLICY_DIR ?? cloudPoliciesDir();
1305
1352
  }
1353
+ function disconnectedByConfig() {
1354
+ try {
1355
+ const raw = JSON.parse(readFileSync2(configFile(), "utf8"));
1356
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
1357
+ return false;
1358
+ const mode = raw.mode;
1359
+ return !!mode && typeof mode === "object" && !Array.isArray(mode) && mode.kind === "oss";
1360
+ } catch {
1361
+ return false;
1362
+ }
1363
+ }
1306
1364
  function parseManifest(value) {
1307
1365
  if (!value || typeof value !== "object")
1308
1366
  throw new Error("active manifest is not an object");
@@ -1338,20 +1396,150 @@ function resolveManagedPath(root, candidate) {
1338
1396
  }
1339
1397
  return realFile;
1340
1398
  }
1341
- function readActiveCloudManagedPolicies() {
1342
- const root = cloudManagedPolicyRoot();
1343
- const activePath = resolve3(root, "active.json");
1344
- if (!existsSync4(activePath))
1399
+ function parseCloudJevMode(raw) {
1400
+ return raw === "off" || raw === "observe" || raw === "enforce" ? raw : null;
1401
+ }
1402
+ function cloudJevAsks(mode) {
1403
+ return mode === "observe" || mode === "enforce";
1404
+ }
1405
+ function fileVersion(path) {
1406
+ try {
1407
+ const s = statSync3(path, { bigint: true });
1408
+ return `${s.dev}:${s.ino}:${s.mode}:${s.size}:${s.mtimeNs}:${s.ctimeNs}`;
1409
+ } catch (err) {
1410
+ const code = err.code;
1411
+ if (code === "ENOENT" || code === "ENOTDIR")
1412
+ return null;
1413
+ throw err;
1414
+ }
1415
+ }
1416
+ function readActiveJson() {
1417
+ if (disconnectedByConfig()) {
1418
+ activeJsonCache = null;
1419
+ return;
1420
+ }
1421
+ const path = resolve3(cloudManagedPolicyRoot(), "active.json");
1422
+ const version = fileVersion(path);
1423
+ if (version === null) {
1424
+ activeJsonCache = null;
1425
+ return;
1426
+ }
1427
+ if (activeJsonCache && activeJsonCache.path === path && activeJsonCache.version === version)
1428
+ return activeJsonCache.value;
1429
+ const value = JSON.parse(readFileSync2(path, "utf8"));
1430
+ activeJsonCache = { path, version, value };
1431
+ return value;
1432
+ }
1433
+ function readActiveRaw() {
1434
+ const raw = readActiveJson();
1435
+ if (raw === undefined)
1436
+ return null;
1437
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
1438
+ throw new Error("active manifest is not an object");
1439
+ const record = raw;
1440
+ if (!ACCEPTED_ACTIVE_SCHEMA_VERSIONS.includes(record.schemaVersion)) {
1441
+ throw new Error(`unsupported active manifest schema ${String(record.schemaVersion)}`);
1442
+ }
1443
+ return record;
1444
+ }
1445
+ function readCloudAgentScopeRequired() {
1446
+ try {
1447
+ return readActiveRaw()?.schemaVersion === 3;
1448
+ } catch {
1449
+ return false;
1450
+ }
1451
+ }
1452
+ function readCloudJevMode() {
1453
+ try {
1454
+ return parseCloudJevMode(readActiveRaw()?.jevMode);
1455
+ } catch {
1456
+ return null;
1457
+ }
1458
+ }
1459
+ function readCloudJevState() {
1460
+ let active;
1461
+ try {
1462
+ active = readActiveRaw();
1463
+ } catch {
1464
+ return noCloudJev();
1465
+ }
1466
+ if (!active)
1467
+ return noCloudJev();
1468
+ const rawMode = active.jevMode;
1469
+ const jevMode = parseCloudJevMode(rawMode);
1470
+ const errors = [];
1471
+ if (rawMode !== undefined && rawMode !== null && jevMode === null) {
1472
+ errors.push({ id: "jevMode", version: null, kind: "daemon", message: `unknown Jev mode ${JSON.stringify(rawMode)} ignored` });
1473
+ }
1474
+ const deployment = Number.isSafeInteger(active.deployment) ? active.deployment : null;
1475
+ return { jevMode, deployment, errors };
1476
+ }
1477
+ function cloudReviewerName(policyId, name) {
1478
+ return `cloud:${policyId}/${name}`;
1479
+ }
1480
+ function cloudAuthorityDeclaration(policy, mode) {
1481
+ if (policy.authority !== "reviewable")
1482
+ return policy.authority ? { authority: policy.authority } : {};
1483
+ if (policy.effect === "observe" || !cloudJevAsks(mode))
1484
+ return { authority: "hard" };
1485
+ return {
1486
+ authority: "reviewable",
1487
+ reviewedBy: (policy.reviewedBy ?? []).map((n) => CLOUD_REVIEWER_RE.test(n) ? n : cloudReviewerName(policy.id, n))
1488
+ };
1489
+ }
1490
+ function withCloudAuthority(policy, mode) {
1491
+ const { authority: _authority, reviewedBy: _reviewedBy, ...rest } = policy;
1492
+ return { ...rest, ...cloudAuthorityDeclaration(policy, mode) };
1493
+ }
1494
+ function cloudReviewerNames(policies, mode) {
1495
+ const out = [];
1496
+ for (const policy of policies) {
1497
+ const declared = cloudAuthorityDeclaration(policy, mode);
1498
+ if (declared.authority === "reviewable")
1499
+ out.push(...declared.reviewedBy ?? []);
1500
+ }
1501
+ return out;
1502
+ }
1503
+ function readCloudAuthorityInputs(agent = null) {
1504
+ try {
1505
+ const raw = readActiveJson();
1506
+ if (raw === undefined)
1507
+ return [];
1508
+ const manifest = parseManifest(raw);
1509
+ return manifest.policies.flatMap((policy) => {
1510
+ if (typeof policy.id !== "string")
1511
+ return [];
1512
+ const targets = parseAgentTargets(policy.agentTargets, manifest.schemaVersion);
1513
+ if (!agentTargetsMatch(targets, agent))
1514
+ return [];
1515
+ return [{
1516
+ id: policy.id,
1517
+ effect: policy.effect === "observe" ? "observe" : "enforce",
1518
+ ...targets ? { agentTargets: targets } : {},
1519
+ ...authorityFieldsOf(policy)
1520
+ }];
1521
+ });
1522
+ } catch {
1345
1523
  return [];
1524
+ }
1525
+ }
1526
+ function readActiveCloudManagedPolicies(agent = null) {
1527
+ return readActiveCloudManagedPoliciesFor((targets) => agentTargetsMatch(targets, agent));
1528
+ }
1529
+ function readActiveCloudManagedPoliciesFor(applies) {
1530
+ const root = cloudManagedPolicyRoot();
1346
1531
  let raw;
1347
1532
  try {
1348
- raw = JSON.parse(readFileSync2(activePath, "utf8"));
1533
+ raw = readActiveJson();
1349
1534
  } catch (err) {
1350
1535
  throw new Error(`failed to read cloud-managed active manifest: ${err instanceof Error ? err.message : String(err)}`);
1351
1536
  }
1537
+ if (raw === undefined)
1538
+ return [];
1352
1539
  const manifest = parseManifest(raw);
1540
+ const applicable = manifest.policies.filter((policy) => applies(parseAgentTargets(policy.agentTargets, manifest.schemaVersion)));
1353
1541
  const seen = new Set;
1354
- return manifest.policies.map((policy) => {
1542
+ return applicable.map((policy) => {
1355
1543
  if (!POLICY_ID_RE.test(policy.id) || policy.id === "." || policy.id === "..") {
1356
1544
  throw new Error(`unsafe cloud-managed policy id ${JSON.stringify(policy.id)}`);
1357
1545
  }
@@ -1380,17 +1568,20 @@ function readActiveCloudManagedPolicies() {
1380
1568
  sha256: policy.sha256,
1381
1569
  path,
1382
1570
  deployment: manifest.deployment,
1571
+ ...parseAgentTargets(policy.agentTargets, manifest.schemaVersion) ? { agentTargets: parseAgentTargets(policy.agentTargets, manifest.schemaVersion) } : {},
1383
1572
  ...authorityFieldsOf(policy)
1384
1573
  };
1385
1574
  });
1386
1575
  }
1387
- var ACCEPTED_ACTIVE_SCHEMA_VERSIONS, SHA256_RE, POLICY_ID_RE;
1576
+ var ACCEPTED_ACTIVE_SCHEMA_VERSIONS, SHA256_RE, POLICY_ID_RE, CLOUD_POLICY_ERRORS_FILE = "errors.json", JEV_BUDGET_FILE = "jev-budget.json", noCloudJev = () => ({ jevMode: null, deployment: null, errors: [] }), activeJsonCache = null, CLOUD_REVIEWER_RE;
1388
1577
  var init_cloud_managed_policies = __esm(() => {
1389
1578
  init_fp_home();
1579
+ init_agent_targets();
1390
1580
  init_policy_authority();
1391
- ACCEPTED_ACTIVE_SCHEMA_VERSIONS = [1, 2];
1581
+ ACCEPTED_ACTIVE_SCHEMA_VERSIONS = [1, 2, 3];
1392
1582
  SHA256_RE = /^[a-f0-9]{64}$/;
1393
1583
  POLICY_ID_RE = /^[A-Za-z0-9._-]{1,128}$/;
1584
+ CLOUD_REVIEWER_RE = /^cloud:[^/]+\/./;
1394
1585
  });
1395
1586
 
1396
1587
  // src/hooks/semver-precedence.ts
@@ -1918,6 +2109,11 @@ function effectiveReviewerNames() {
1918
2109
  names = reviewerNamesFor(packs);
1919
2110
  cachedContested = contestedSemanticNames(packs);
1920
2111
  } catch {}
2112
+ try {
2113
+ const cloud = cloudReviewerNames(readCloudAuthorityInputs(reviewerAgent), readCloudJevMode());
2114
+ if (cloud.length > 0)
2115
+ names = new Set([...names, ...cloud]);
2116
+ } catch {}
1921
2117
  cached = names;
1922
2118
  return names;
1923
2119
  }
@@ -1935,14 +2131,16 @@ function reviewerNamesFor(packs) {
1935
2131
  return NO_REVIEWERS;
1936
2132
  return new Set(declared);
1937
2133
  }
1938
- function forgetEffectiveReviewerNames(cli) {
2134
+ function forgetEffectiveReviewerNames(cli, agent = null) {
1939
2135
  cached = null;
1940
2136
  reviewerCli = cli;
2137
+ reviewerAgent = agent;
1941
2138
  }
1942
- var cached = null, cachedContested, reviewerCli;
2139
+ var cached = null, cachedContested, reviewerCli, reviewerAgent = null;
1943
2140
  var init_effective_reviewers = __esm(() => {
1944
2141
  init_pack_manifest();
1945
2142
  init_policy_authority();
2143
+ init_cloud_managed_policies();
1946
2144
  cachedContested = new Map;
1947
2145
  });
1948
2146
 
@@ -2009,11 +2207,11 @@ function getPoliciesForEvent(eventType, toolName) {
2009
2207
  cache.set(key, result);
2010
2208
  return result;
2011
2209
  }
2012
- function clearPolicies(cli) {
2210
+ function clearPolicies(cli, agent = null) {
2013
2211
  const g = globalThis;
2014
2212
  g[REGISTRY_KEY] = [];
2015
2213
  setIndexCache(null);
2016
- forgetEffectiveReviewerNames(cli);
2214
+ forgetEffectiveReviewerNames(cli, agent);
2017
2215
  }
2018
2216
  var REGISTRY_KEY = "__FAILPROOFAI_POLICY_REGISTRY__", INDEX_CACHE_KEY = "__FAILPROOFAI_POLICY_INDEX_CACHE__", DEFAULT_POLICY_NAMESPACE = "failproofai";
2019
2217
  var init_policy_registry = __esm(() => {
@@ -2023,7 +2221,7 @@ var init_policy_registry = __esm(() => {
2023
2221
 
2024
2222
  // src/hooks/builtin-policies.ts
2025
2223
  import { resolve as resolve5, join as join2 } from "node:path";
2026
- import { statSync as statSync3 } from "node:fs";
2224
+ import { statSync as statSync4 } from "node:fs";
2027
2225
  import { readFile, writeFile } from "node:fs/promises";
2028
2226
  import { execSync, execFileSync } from "node:child_process";
2029
2227
  import { homedir as homedir3 } from "node:os";
@@ -2568,7 +2766,7 @@ function destroysFailproofaiState(command, depth = 0) {
2568
2766
  }
2569
2767
  function statGitHeadMtimeMs(cwd) {
2570
2768
  try {
2571
- return statSync3(join2(cwd, ".git", "HEAD")).mtimeMs;
2769
+ return statSync4(join2(cwd, ".git", "HEAD")).mtimeMs;
2572
2770
  } catch {
2573
2771
  return null;
2574
2772
  }
@@ -4386,7 +4584,7 @@ import {
4386
4584
  mkdirSync as mkdirSync3,
4387
4585
  renameSync as renameSync2,
4388
4586
  rmSync as rmSync2,
4389
- statSync as statSync4,
4587
+ statSync as statSync5,
4390
4588
  writeFileSync as writeFileSync2
4391
4589
  } from "node:fs";
4392
4590
  import { dirname as dirname2 } from "node:path";
@@ -4401,12 +4599,12 @@ function writeJsonAtomically(filePath, value, opts = {}) {
4401
4599
  try {
4402
4600
  writeFileSync2(tmp, JSON.stringify(value, null, 2), { mode });
4403
4601
  try {
4404
- if ((statSync4(tmp).mode & 63) !== 0)
4602
+ if ((statSync5(tmp).mode & 63) !== 0)
4405
4603
  chmodSync(tmp, mode);
4406
4604
  } catch {}
4407
4605
  renameSync2(tmp, filePath);
4408
4606
  try {
4409
- if ((statSync4(filePath).mode & 63) !== 0)
4607
+ if ((statSync5(filePath).mode & 63) !== 0)
4410
4608
  chmodSync(filePath, mode);
4411
4609
  } catch {}
4412
4610
  } catch (err) {
@@ -4429,7 +4627,7 @@ import {
4429
4627
  openSync,
4430
4628
  readFileSync as readFileSync4,
4431
4629
  readSync,
4432
- statSync as statSync5,
4630
+ statSync as statSync6,
4433
4631
  writeFileSync as writeFileSync3
4434
4632
  } from "node:fs";
4435
4633
  import { dirname as dirname3 } from "node:path";
@@ -4586,6 +4784,13 @@ function projectConfig(parsed) {
4586
4784
  function isAgentTraced(id, config = readConfig()) {
4587
4785
  return !config.agents || config.agents.selected.includes(id);
4588
4786
  }
4787
+ function readCredentials() {
4788
+ try {
4789
+ return projectCredentials(JSON.parse(readFileSync4(credentialsFile(), "utf8")));
4790
+ } catch {
4791
+ return {};
4792
+ }
4793
+ }
4589
4794
  function projectCredentials(parsed) {
4590
4795
  {
4591
4796
  const cloud = parsed.cloud;
@@ -4661,7 +4866,7 @@ function readJevCloudCredential() {
4661
4866
  if (meaningful) {
4662
4867
  let dirMode = null;
4663
4868
  try {
4664
- const m = statSync5(dirname3(path)).mode & 511;
4869
+ const m = statSync6(dirname3(path)).mode & 511;
4665
4870
  if ((m & DIR_WRITABLE_BY_OTHERS) !== 0)
4666
4871
  dirMode = m;
4667
4872
  } catch {}
@@ -5008,7 +5213,7 @@ async function evaluatePolicies(eventType, payload, session, config, twoTier) {
5008
5213
  twoTier: {
5009
5214
  activity: combined.activity,
5010
5215
  decidedByJev: combined.decidedByJev,
5011
- ...combined.decidedByJev && review.kind === "answered" && review.origin ? { jevOrigin: review.origin } : {},
5216
+ ...(combined.decidedByJev || combined.observeVerdict) && review.kind === "answered" && review.origin ? { jevOrigin: review.origin } : {},
5012
5217
  ...combined.observeVerdict ? { observeVerdict: combined.observeVerdict } : {}
5013
5218
  }
5014
5219
  };
@@ -6069,7 +6274,7 @@ async function loadSingleFile(absPath, opts) {
6069
6274
  return null;
6070
6275
  } catch (err) {
6071
6276
  const msg = err instanceof Error ? err.message : String(err);
6072
- const errorType = /Cannot find module|MODULE_NOT_FOUND|ENOENT/i.test(msg) ? "module_not_found" : /SyntaxError|Unexpected token/i.test(msg) ? "syntax_error" : /timed out loading module/i.test(msg) ? "load_timeout" : "runtime_error";
6277
+ const errorType = /Cannot find module|MODULE_NOT_FOUND|Cannot find package/i.test(msg) ? "module_not_found" : /ENOENT/i.test(msg) ? "file_not_found" : /SyntaxError|Unexpected token/i.test(msg) ? "syntax_error" : /timed out loading module/i.test(msg) ? "load_timeout" : "runtime_error";
6073
6278
  trackHookEvent(getInstanceId(), "custom_hooks_load_error", {
6074
6279
  error_type: errorType,
6075
6280
  is_convention: !!opts?.conventionScope,
@@ -6129,8 +6334,11 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
6129
6334
  const conventionEnabled = opts?.customPoliciesEnabled !== false;
6130
6335
  const loadedPaths = new Set;
6131
6336
  const cloudManagedByPath = new Map;
6337
+ const cloudIdsByPath = new Map;
6338
+ const cloudFailures = new Map;
6132
6339
  for (const policy of opts?.cloudManagedPolicies ?? []) {
6133
6340
  const key = resolve7(policy.path);
6341
+ cloudIdsByPath.set(key, [...cloudIdsByPath.get(key) ?? [], policy.id]);
6134
6342
  const existing = cloudManagedByPath.get(key);
6135
6343
  if (!existing) {
6136
6344
  cloudManagedByPath.set(key, policy);
@@ -6211,6 +6419,10 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
6211
6419
  for (const id of packIdsByPath.get(absPath) ?? [pack.id])
6212
6420
  packFailures.set(id, failure);
6213
6421
  }
6422
+ if (failure && cloudManaged) {
6423
+ for (const id of cloudIdsByPath.get(absPath) ?? [cloudManaged.id])
6424
+ cloudFailures.set(id, failure);
6425
+ }
6214
6426
  for (const hook of getCustomHooks().slice(hooksBefore)) {
6215
6427
  const tagged = hook;
6216
6428
  if (cloudManaged) {
@@ -6227,6 +6439,11 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
6227
6439
  }
6228
6440
  } else {
6229
6441
  hookLogWarn(`custom policy path not found: ${absPath}`);
6442
+ if (cloudManaged) {
6443
+ const missing = { type: "path_missing", reason: `path missing: ${absPath}` };
6444
+ for (const id of cloudIdsByPath.get(absPath) ?? [cloudManaged.id])
6445
+ cloudFailures.set(id, missing);
6446
+ }
6230
6447
  if (pack) {
6231
6448
  const missing = { type: "path_missing", reason: `path missing: ${absPath}` };
6232
6449
  for (const id of packIdsByPath.get(absPath) ?? [pack.id])
@@ -6309,7 +6526,7 @@ async function loadAllCustomHooks(customPoliciesPaths, opts) {
6309
6526
  if (winner && ids.length > 1)
6310
6527
  packAliases.set(winner.id, ids);
6311
6528
  }
6312
- return { hooks: allHooks, conventionSources, packFailures, packAliases };
6529
+ return { hooks: allHooks, conventionSources, packFailures, packAliases, cloudFailures };
6313
6530
  }
6314
6531
  var LOADING_KEY = "__FAILPROOFAI_LOADING_HOOKS__", CONVENTION_FILE_RE, loadSequence = 0, policyModuleCache, POLICY_MODULE_CACHE_MAX_ENTRIES = 500, LOADABLE_EXT_RE, warnedSemanticOutsidePack;
6315
6532
  var init_custom_hooks_loader = __esm(() => {
@@ -6337,7 +6554,7 @@ import {
6337
6554
  readdirSync as readdirSync2,
6338
6555
  mkdirSync as mkdirSync5,
6339
6556
  existsSync as existsSync9,
6340
- statSync as statSync6,
6557
+ statSync as statSync7,
6341
6558
  unlinkSync
6342
6559
  } from "node:fs";
6343
6560
  import { join as join4 } from "node:path";
@@ -6358,7 +6575,7 @@ function acquireLock() {
6358
6575
  if (e.code !== "EEXIST")
6359
6576
  return;
6360
6577
  try {
6361
- const s = statSync6(lockPath);
6578
+ const s = statSync7(lockPath);
6362
6579
  if (Date.now() - s.mtimeMs > LOCK_STALE_MS) {
6363
6580
  writeFileSync4(lockPath, String(process.pid), "utf-8");
6364
6581
  return;
@@ -7156,7 +7373,7 @@ var init_cursor_projects = __esm(() => {
7156
7373
  });
7157
7374
 
7158
7375
  // lib/sqlite-reader.ts
7159
- import { existsSync as existsSync10, readFileSync as readFileSync6, statSync as statSync7 } from "node:fs";
7376
+ import { existsSync as existsSync10, readFileSync as readFileSync6, statSync as statSync8 } from "node:fs";
7160
7377
  import initSqlJs from "sql.js/dist/sql-asm.js";
7161
7378
  async function tryNodeSqlite(dbPath) {
7162
7379
  try {
@@ -7180,8 +7397,8 @@ function loadSqlJs() {
7180
7397
  sqlPromise = initSqlJs();
7181
7398
  return sqlPromise;
7182
7399
  }
7183
- function fileVersion(path) {
7184
- const stat = statSync7(path);
7400
+ function fileVersion2(path) {
7401
+ const stat = statSync8(path);
7185
7402
  return { size: stat.size, mtimeMs: stat.mtimeMs, ctimeMs: stat.ctimeMs };
7186
7403
  }
7187
7404
  function sameVersion(a, b) {
@@ -7268,9 +7485,9 @@ function applyCommittedWal(db, wal) {
7268
7485
  function readPortableSnapshot(dbPath) {
7269
7486
  const walPath = `${dbPath}-wal`;
7270
7487
  for (let attempt = 0;attempt < 3; attempt += 1) {
7271
- const before = fileVersion(dbPath);
7488
+ const before = fileVersion2(dbPath);
7272
7489
  const main = readFileSync6(dbPath);
7273
- const afterMain = fileVersion(dbPath);
7490
+ const afterMain = fileVersion2(dbPath);
7274
7491
  if (!sameVersion(before, afterMain))
7275
7492
  continue;
7276
7493
  let wal = null;
@@ -7280,7 +7497,7 @@ function readPortableSnapshot(dbPath) {
7280
7497
  if (error.code !== "ENOENT")
7281
7498
  throw error;
7282
7499
  }
7283
- const afterWal = fileVersion(dbPath);
7500
+ const afterWal = fileVersion2(dbPath);
7284
7501
  if (!sameVersion(before, afterWal))
7285
7502
  continue;
7286
7503
  return wal ? applyCommittedWal(main, wal) : main;
@@ -8218,7 +8435,7 @@ var init_openclaw_db = __esm(() => {
8218
8435
 
8219
8436
  // lib/openclaw-sessions.ts
8220
8437
  import { readFile as readFile7 } from "node:fs/promises";
8221
- import { readdirSync as readdirSync4, statSync as statSync8 } from "node:fs";
8438
+ import { readdirSync as readdirSync4, statSync as statSync9 } from "node:fs";
8222
8439
  import { homedir as homedir11 } from "node:os";
8223
8440
  import { join as join14 } from "node:path";
8224
8441
  function openclawHome() {
@@ -8371,7 +8588,7 @@ function listOpenClawTranscripts() {
8371
8588
  continue;
8372
8589
  const transcriptPath = join14(sessionsDir, file);
8373
8590
  try {
8374
- const st = statSync8(transcriptPath);
8591
+ const st = statSync9(transcriptPath);
8375
8592
  out.push({
8376
8593
  agentId,
8377
8594
  sessionId,
@@ -8614,7 +8831,7 @@ var init_openclaw_projects = __esm(() => {
8614
8831
 
8615
8832
  // lib/factory-sessions.ts
8616
8833
  import { readFile as readFile8 } from "node:fs/promises";
8617
- import { readdirSync as readdirSync5, statSync as statSync9 } from "node:fs";
8834
+ import { readdirSync as readdirSync5, statSync as statSync10 } from "node:fs";
8618
8835
  import { homedir as homedir12 } from "node:os";
8619
8836
  import { join as join16 } from "node:path";
8620
8837
  function factoryHome() {
@@ -8782,7 +8999,7 @@ function listFactoryTranscripts() {
8782
8999
  continue;
8783
9000
  const transcriptPath = join16(projectPath, file);
8784
9001
  try {
8785
- const st = statSync9(transcriptPath);
9002
+ const st = statSync10(transcriptPath);
8786
9003
  out.push({ projectName, cwd, sessionId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
8787
9004
  } catch {}
8788
9005
  }
@@ -9201,7 +9418,7 @@ var init_devin_projects = __esm(() => {
9201
9418
 
9202
9419
  // lib/antigravity-sessions.ts
9203
9420
  import { readFile as readFile9 } from "node:fs/promises";
9204
- import { readdirSync as readdirSync6, statSync as statSync10 } from "node:fs";
9421
+ import { readdirSync as readdirSync6, statSync as statSync11 } from "node:fs";
9205
9422
  import { homedir as homedir14 } from "node:os";
9206
9423
  import { join as join18 } from "node:path";
9207
9424
  function antigravityHome() {
@@ -9336,7 +9553,7 @@ function listAntigravityTranscripts() {
9336
9553
  continue;
9337
9554
  const transcriptPath = join18(root, conversationId, rel);
9338
9555
  try {
9339
- const st = statSync10(transcriptPath);
9556
+ const st = statSync11(transcriptPath);
9340
9557
  if (!st.isFile())
9341
9558
  continue;
9342
9559
  out.push({ conversationId, transcriptPath, mtimeMs: st.mtimeMs, sizeBytes: st.size });
@@ -9349,7 +9566,7 @@ function findAntigravityTranscript(conversationId) {
9349
9566
  return null;
9350
9567
  const transcriptPath = join18(antigravityBrainRoot(), conversationId, antigravityTranscriptRelPath());
9351
9568
  try {
9352
- if (statSync10(transcriptPath).isFile())
9569
+ if (statSync11(transcriptPath).isFile())
9353
9570
  return transcriptPath;
9354
9571
  } catch {}
9355
9572
  return null;
@@ -10258,7 +10475,7 @@ var init_log_entries = __esm(() => {
10258
10475
  });
10259
10476
 
10260
10477
  // lib/codex-sessions.ts
10261
- import { readFileSync as readFileSync8, readdirSync as readdirSync7, existsSync as existsSync13, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, statSync as statSync11 } from "node:fs";
10478
+ import { readFileSync as readFileSync8, readdirSync as readdirSync7, existsSync as existsSync13, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, statSync as statSync12 } from "node:fs";
10262
10479
  import { readFile as readFile11 } from "node:fs/promises";
10263
10480
  import { dirname as dirname6, join as join24 } from "node:path";
10264
10481
  import { homedir as homedir16 } from "node:os";
@@ -10586,7 +10803,7 @@ var init_resolve_permission_mode = __esm(() => {
10586
10803
  });
10587
10804
 
10588
10805
  // lib/copilot-sessions.ts
10589
- import { readFileSync as readFileSync10, readdirSync as readdirSync8, existsSync as existsSync14, statSync as statSync12 } from "node:fs";
10806
+ import { readFileSync as readFileSync10, readdirSync as readdirSync8, existsSync as existsSync14, statSync as statSync13 } from "node:fs";
10590
10807
  import { readFile as readFile12 } from "node:fs/promises";
10591
10808
  import { join as join25, resolve as resolve10, sep as sep2 } from "node:path";
10592
10809
  import { homedir as homedir17 } from "node:os";
@@ -10803,7 +11020,7 @@ var init_copilot_sessions = __esm(() => {
10803
11020
  });
10804
11021
 
10805
11022
  // lib/cursor-sessions.ts
10806
- import { readFileSync as readFileSync11, readdirSync as readdirSync9, existsSync as existsSync15, statSync as statSync13 } from "node:fs";
11023
+ import { readFileSync as readFileSync11, readdirSync as readdirSync9, existsSync as existsSync15, statSync as statSync14 } from "node:fs";
10807
11024
  import { readFile as readFile13 } from "node:fs/promises";
10808
11025
  import { basename as basename3, join as join26, resolve as resolve11, sep as sep3 } from "node:path";
10809
11026
  import { homedir as homedir18 } from "node:os";
@@ -11059,7 +11276,7 @@ var init_cursor_sessions = __esm(() => {
11059
11276
  });
11060
11277
 
11061
11278
  // lib/pi-sessions.ts
11062
- import { readFileSync as readFileSync12, readdirSync as readdirSync10, existsSync as existsSync16, statSync as statSync14 } from "node:fs";
11279
+ import { readFileSync as readFileSync12, readdirSync as readdirSync10, existsSync as existsSync16, statSync as statSync15 } from "node:fs";
11063
11280
  import { readFile as readFile14 } from "node:fs/promises";
11064
11281
  import { join as join27, resolve as resolve12, sep as sep4 } from "node:path";
11065
11282
  import { homedir as homedir19 } from "node:os";
@@ -11320,6 +11537,238 @@ var init_resolve_transcript_path = __esm(() => {
11320
11537
  init_factory_sessions();
11321
11538
  init_antigravity_sessions();
11322
11539
  });
11540
+ // src/hooks/cloud-policy-errors.ts
11541
+ import { randomUUID as randomUUID2 } from "node:crypto";
11542
+ import { chmodSync as chmodSync3, existsSync as existsSync17, readFileSync as readFileSync13, renameSync as renameSync4, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "node:fs";
11543
+ import { homedir as homedir20 } from "node:os";
11544
+ import { resolve as resolve13 } from "node:path";
11545
+ function isPackDropEntry(e) {
11546
+ return e.id.startsWith("pack:") && (e.message.startsWith(JEV_BUDGET) || e.message.startsWith(JEV_NAME_CLASH));
11547
+ }
11548
+ function redactLocalPaths(message, home = safeHomedir()) {
11549
+ let text = message;
11550
+ const base = home?.replace(/\/+$/, "") ?? "";
11551
+ if (base.length > 1) {
11552
+ let out = "";
11553
+ let rest = text;
11554
+ for (let at = rest.indexOf(base);at >= 0; at = rest.indexOf(base)) {
11555
+ const next = rest.charAt(at + base.length);
11556
+ const whole = next === "" || next === "/" || next === ":" || PATH_END.test(next);
11557
+ out += rest.slice(0, at) + (whole ? "~" : base);
11558
+ rest = rest.slice(at + base.length);
11559
+ }
11560
+ text = out + rest;
11561
+ }
11562
+ return text.replace(/(^|[\s"'`(\[<{=,]|:(?!\/\/(?!\/)))(\/[^\s"'`)\]>},;]*)/g, (_m, lead, path) => {
11563
+ const last = path.replace(/\/+$/, "").split("/").pop() ?? "";
11564
+ return lead + (last === "" ? "/" : last);
11565
+ });
11566
+ }
11567
+ function safeHomedir() {
11568
+ try {
11569
+ return homedir20();
11570
+ } catch {
11571
+ return null;
11572
+ }
11573
+ }
11574
+ function cloudPolicyErrorsPath() {
11575
+ return resolve13(cloudManagedPolicyRoot(), CLOUD_POLICY_ERRORS_FILE);
11576
+ }
11577
+ function readCloudPolicyErrors() {
11578
+ try {
11579
+ const raw = JSON.parse(readFileSync13(cloudPolicyErrorsPath(), "utf8"));
11580
+ if (!Array.isArray(raw.errors))
11581
+ return null;
11582
+ return raw.errors.filter((e) => !!e && typeof e === "object" && typeof e.id === "string" && typeof e.message === "string" && KINDS.has(e.kind) && (e.version === null || Number.isSafeInteger(e.version)));
11583
+ } catch {
11584
+ return null;
11585
+ }
11586
+ }
11587
+ function serialize(errors) {
11588
+ const list = errors.map((e) => ({ id: e.id, version: e.version, kind: e.kind, message: redactLocalPaths(e.message) }));
11589
+ return `${JSON.stringify({ errors: list }, null, 2)}
11590
+ `;
11591
+ }
11592
+ function writeCloudPolicyErrors(errors) {
11593
+ try {
11594
+ const root = cloudManagedPolicyRoot();
11595
+ if (!existsSync17(resolve13(root, "active.json")))
11596
+ return "skipped";
11597
+ const path = cloudPolicyErrorsPath();
11598
+ const text = serialize(errors);
11599
+ if (lastWritten && lastWritten.path === path && lastWritten.text === text && existsSync17(path))
11600
+ return "unchanged";
11601
+ let current = null;
11602
+ try {
11603
+ current = readFileSync13(path, "utf8");
11604
+ } catch {
11605
+ current = null;
11606
+ }
11607
+ if (current === text) {
11608
+ lastWritten = { path, text };
11609
+ return "unchanged";
11610
+ }
11611
+ if (current === null && errors.length === 0)
11612
+ return "skipped";
11613
+ writeAtomic(path, text);
11614
+ lastWritten = { path, text };
11615
+ return "written";
11616
+ } catch {
11617
+ return "failed";
11618
+ }
11619
+ }
11620
+ function cloudLoadCheckedPath() {
11621
+ return resolve13(cloudManagedPolicyRoot(), CLOUD_LOAD_CHECKED_FILE);
11622
+ }
11623
+ function readCloudLoadChecked() {
11624
+ try {
11625
+ const raw = JSON.parse(readFileSync13(cloudLoadCheckedPath(), "utf8"));
11626
+ if (!Number.isSafeInteger(raw.deployment) || !Array.isArray(raw.checked))
11627
+ return null;
11628
+ return { deployment: raw.deployment, checked: raw.checked.filter((c) => typeof c === "string") };
11629
+ } catch {
11630
+ return null;
11631
+ }
11632
+ }
11633
+ function recordCloudLoadChecked(deployment, policies) {
11634
+ try {
11635
+ if (!existsSync17(resolve13(cloudManagedPolicyRoot(), "active.json")))
11636
+ return;
11637
+ const path = cloudLoadCheckedPath();
11638
+ const prior = readCloudLoadChecked();
11639
+ const base = prior && prior.deployment === deployment ? prior.checked : [];
11640
+ const next = [...new Set([...base, ...policies.map((p) => `${p.id}@${p.version}`)])].sort();
11641
+ if (prior && prior.deployment === deployment && next.length === base.length)
11642
+ return;
11643
+ const text = `${JSON.stringify({ deployment, checked: next }, null, 2)}
11644
+ `;
11645
+ writeAtomic(path, text);
11646
+ } catch {}
11647
+ }
11648
+ function kindOf(policy) {
11649
+ return policy.authority === "reviewable" && (policy.reviewedBy?.length ?? 0) > 0 ? "both" : "regex";
11650
+ }
11651
+ function collectCloudPolicyErrors(input) {
11652
+ const out = [];
11653
+ if (input.manifestError) {
11654
+ out.push({ id: "active.json", version: null, kind: "daemon", message: `Cloud policies could not be loaded: ${input.manifestError}` });
11655
+ }
11656
+ if (input.agentScopeUnresolved) {
11657
+ out.push({
11658
+ id: "agentScope",
11659
+ version: null,
11660
+ kind: "daemon",
11661
+ message: "agent_scope_unresolved: this hook's agent profile is unknown; targeted Cloud policies did not match"
11662
+ });
11663
+ }
11664
+ for (const policy of input.jsPolicies) {
11665
+ const failure = input.jsFailures?.get(policy.id);
11666
+ if (failure) {
11667
+ out.push({ id: policy.id, version: policy.version, kind: kindOf(policy), message: `policy did not load (${failure.type}): ${failure.reason}` });
11668
+ }
11669
+ }
11670
+ out.push(...input.jev.errors);
11671
+ out.push(...input.budgetDrops ?? []);
11672
+ if (input.jevProblem) {
11673
+ out.push({ id: "jevMode", version: null, kind: "daemon", message: input.jevProblem });
11674
+ }
11675
+ out.push(...input.health ?? []);
11676
+ const seen = new Set;
11677
+ return out.map((e) => ({ ...e, message: redactLocalPaths(e.message) })).filter((e) => {
11678
+ const key = `${e.id}\x00${e.version}\x00${e.kind}\x00${e.message}`;
11679
+ if (seen.has(key))
11680
+ return false;
11681
+ seen.add(key);
11682
+ return true;
11683
+ });
11684
+ }
11685
+ function jevBudgetPath() {
11686
+ return resolve13(cloudManagedPolicyRoot(), JEV_BUDGET_FILE);
11687
+ }
11688
+ function readJevBudgetRecord() {
11689
+ try {
11690
+ const raw = JSON.parse(readFileSync13(jevBudgetPath(), "utf8"));
11691
+ if (typeof raw.machineId !== "string" || !(raw.deployment === null || Number.isSafeInteger(raw.deployment)) || raw.jevMode !== "observe" && raw.jevMode !== "enforce" || !Array.isArray(raw.dropped)) {
11692
+ return null;
11693
+ }
11694
+ const dropped = raw.dropped.filter((d) => !!d && typeof d.packId === "string" && typeof d.name === "string").map((d) => ({ packId: d.packId, name: d.name, ...d.clash === true ? { clash: true } : {} }));
11695
+ return { machineId: raw.machineId, deployment: raw.deployment, jevMode: raw.jevMode, dropped };
11696
+ } catch {
11697
+ return null;
11698
+ }
11699
+ }
11700
+ function budgetEntries(dropped) {
11701
+ return [...dropped].sort((a, b) => dropKey(a) < dropKey(b) ? -1 : dropKey(a) > dropKey(b) ? 1 : 0).map((d) => ({
11702
+ id: `pack:${d.packId}`,
11703
+ version: null,
11704
+ kind: "daemon",
11705
+ message: d.clash ? `${JEV_NAME_CLASH}: ${d.name} (the FailproofAI Cloud check is used)` : `${JEV_BUDGET}: dropped ${d.name}`
11706
+ }));
11707
+ }
11708
+ function installedPackIds() {
11709
+ try {
11710
+ const path = resolve13(packsRoot(), "installed.json");
11711
+ if (!existsSync17(path))
11712
+ return new Set;
11713
+ const raw = JSON.parse(readFileSync13(path, "utf8"));
11714
+ if (!Array.isArray(raw.packs))
11715
+ return null;
11716
+ return new Set(raw.packs.map((p) => p && typeof p === "object" ? p.id : null).filter((id) => typeof id === "string"));
11717
+ } catch {
11718
+ return null;
11719
+ }
11720
+ }
11721
+ function readJevBudgetDrops(key, installed = null) {
11722
+ const record = readJevBudgetRecord();
11723
+ if (!record || !sameKey(record, key))
11724
+ return [];
11725
+ return budgetEntries(installed ? record.dropped.filter((d) => installed.has(d.packId)) : record.dropped);
11726
+ }
11727
+ function recordJevBudgetDrops(key, drops) {
11728
+ try {
11729
+ if (drops.length === 0 || !existsSync17(resolve13(cloudManagedPolicyRoot(), "active.json")))
11730
+ return;
11731
+ const current = readJevBudgetRecord();
11732
+ const base = current && sameKey(current, key) ? current.dropped : [];
11733
+ const seen = new Set(base.map(dropKey));
11734
+ const added = [];
11735
+ for (const d of drops) {
11736
+ const id = dropKey(d);
11737
+ if (seen.has(id))
11738
+ continue;
11739
+ seen.add(id);
11740
+ added.push({ packId: d.packId, name: d.name, ...d.clash === true ? { clash: true } : {} });
11741
+ }
11742
+ if (current && sameKey(current, key) && added.length === 0)
11743
+ return;
11744
+ const record = { ...key, dropped: [...base, ...added] };
11745
+ writeAtomic(jevBudgetPath(), `${JSON.stringify(record, null, 2)}
11746
+ `);
11747
+ const report = (readCloudPolicyErrors() ?? []).filter((e) => !isPackDropEntry(e));
11748
+ writeCloudPolicyErrors([...report, ...budgetEntries(record.dropped)]);
11749
+ } catch {}
11750
+ }
11751
+ function writeAtomic(path, text) {
11752
+ const tmp = `${path}.tmp-${process.pid}-${randomUUID2()}`;
11753
+ try {
11754
+ writeFileSync6(tmp, text, { mode: 384, flag: "wx" });
11755
+ chmodSync3(tmp, 384);
11756
+ renameSync4(tmp, path);
11757
+ } catch (err) {
11758
+ try {
11759
+ rmSync3(tmp, { force: true });
11760
+ } catch {}
11761
+ throw err;
11762
+ }
11763
+ }
11764
+ var JEV_BUDGET = "jev_budget", JEV_NAME_CLASH = "jev_name_clash", PATH_END, KINDS, lastWritten = null, CLOUD_LOAD_CHECKED_FILE = "load-checked.json", sameKey = (a, b) => a.machineId === b.machineId && a.deployment === b.deployment && a.jevMode === b.jevMode, dropKey = (d) => `${d.packId}\x00${d.name}\x00${d.clash === true}`;
11765
+ var init_cloud_policy_errors = __esm(() => {
11766
+ init_cloud_managed_policies();
11767
+ init_pack_manifest();
11768
+ PATH_END = /[\s"'`)\]>},;]/;
11769
+ KINDS = new Set(["regex", "jev", "both", "daemon"]);
11770
+ });
11771
+
11323
11772
  // src/hooks/pack-failclosed.ts
11324
11773
  function declaredList(value) {
11325
11774
  if (value === undefined || value === null)
@@ -11448,6 +11897,7 @@ var PERMANENT_LOAD_FAILURES;
11448
11897
  var init_pack_failclosed = __esm(() => {
11449
11898
  PERMANENT_LOAD_FAILURES = new Set([
11450
11899
  "module_not_found",
11900
+ "file_not_found",
11451
11901
  "syntax_error",
11452
11902
  "runtime_error",
11453
11903
  "path_missing"
@@ -11455,13 +11905,13 @@ var init_pack_failclosed = __esm(() => {
11455
11905
  });
11456
11906
 
11457
11907
  // src/hooks/session-pause.ts
11458
- import { existsSync as existsSync17, mkdirSync as mkdirSync7, readdirSync as readdirSync11, readFileSync as readFileSync13, rmSync as rmSync3 } from "node:fs";
11908
+ import { existsSync as existsSync18, mkdirSync as mkdirSync7, readdirSync as readdirSync11, readFileSync as readFileSync14, rmSync as rmSync4 } from "node:fs";
11459
11909
  import { createHash as createHash5 } from "node:crypto";
11460
- import { join as join28, resolve as resolve13 } from "node:path";
11910
+ import { join as join28, resolve as resolve14 } from "node:path";
11461
11911
  function pauseStateDir() {
11462
11912
  const override = process.env.FAILPROOFAI_STATE_DIR;
11463
11913
  if (override)
11464
- return resolve13(override, "sessions");
11914
+ return resolve14(override, "sessions");
11465
11915
  return sessionPauseDir();
11466
11916
  }
11467
11917
  function pauseFilePath(sessionId) {
@@ -11495,9 +11945,9 @@ function readActivePause(sessionId, now = Date.now()) {
11495
11945
  return null;
11496
11946
  try {
11497
11947
  const path = pauseFilePath(sessionId);
11498
- if (!existsSync17(path))
11948
+ if (!existsSync18(path))
11499
11949
  return null;
11500
- const stored = parseStored(JSON.parse(readFileSync13(path, "utf8")));
11950
+ const stored = parseStored(JSON.parse(readFileSync14(path, "utf8")));
11501
11951
  if (!stored)
11502
11952
  return null;
11503
11953
  if (stored.expiresAt <= now)
@@ -11517,6 +11967,12 @@ var init_session_pause = __esm(() => {
11517
11967
  PAUSE_CEILING_MS = 8 * 60 * 60000;
11518
11968
  });
11519
11969
 
11970
+ // src/hooks/health-probe.ts
11971
+ function isHealthProbe(eventType, parsed) {
11972
+ return eventType === "SessionStart" && parsed.source === HEALTH_PROBE_SOURCE && parsed.session_id === undefined;
11973
+ }
11974
+ var HEALTH_PROBE_SOURCE = "failproofai-health-probe";
11975
+
11520
11976
  // src/hooks/daemon-download.ts
11521
11977
  var init_daemon_download = __esm(() => {
11522
11978
  init_package();
@@ -11536,15 +11992,15 @@ var init_daemon_service = __esm(() => {
11536
11992
  // src/hooks/fp-reset.ts
11537
11993
  import {
11538
11994
  copyFileSync,
11539
- existsSync as existsSync18,
11995
+ existsSync as existsSync19,
11540
11996
  mkdirSync as mkdirSync8,
11541
- readFileSync as readFileSync14,
11997
+ readFileSync as readFileSync15,
11542
11998
  readdirSync as readdirSync12,
11543
- renameSync as renameSync4,
11544
- rmSync as rmSync4,
11999
+ renameSync as renameSync5,
12000
+ rmSync as rmSync5,
11545
12001
  rmdirSync,
11546
- statSync as statSync15,
11547
- writeFileSync as writeFileSync6
12002
+ statSync as statSync16,
12003
+ writeFileSync as writeFileSync7
11548
12004
  } from "node:fs";
11549
12005
  function layoutWarningForHook() {
11550
12006
  const state = detectLayout();
@@ -11553,7 +12009,7 @@ function layoutWarningForHook() {
11553
12009
  if (state.kind === "future") {
11554
12010
  return `[failproofai] this directory was written by a newer version (layout ${state.found} vs ${LAYOUT_VERSION}) — policies are NOT being enforced. ` + `Upgrade failproofai.`;
11555
12011
  }
11556
- if (existsSync18(globalPolicyConfigFile()))
12012
+ if (existsSync19(globalPolicyConfigFile()))
11557
12013
  return null;
11558
12014
  return `[failproofai] setup predates this version — global policies are NOT being enforced. ` + `Run \`failproofai config\` to re-create it.`;
11559
12015
  }
@@ -11565,7 +12021,7 @@ var init_fp_reset = __esm(() => {
11565
12021
  });
11566
12022
 
11567
12023
  // src/hooks/untraced-note.ts
11568
- import { existsSync as existsSync19, readFileSync as readFileSync15 } from "node:fs";
12024
+ import { existsSync as existsSync20, readFileSync as readFileSync16 } from "node:fs";
11569
12025
  import { join as join29 } from "node:path";
11570
12026
  function untracedNotePath(home) {
11571
12027
  return join29(stateDir(home), "untraced-notes.json");
@@ -11577,8 +12033,8 @@ function noteUntracedAgent(cli, sessionId, config) {
11577
12033
  const key = `${cli}:${sessionId ?? "no-session"}`;
11578
12034
  const path = untracedNotePath();
11579
12035
  let seen = [];
11580
- if (existsSync19(path)) {
11581
- const parsed = JSON.parse(readFileSync15(path, "utf8"));
12036
+ if (existsSync20(path)) {
12037
+ const parsed = JSON.parse(readFileSync16(path, "utf8"));
11582
12038
  if (Array.isArray(parsed))
11583
12039
  seen = parsed.filter((k) => typeof k === "string");
11584
12040
  }
@@ -11599,12 +12055,142 @@ var init_untraced_note = __esm(() => {
11599
12055
  init_hook_logger();
11600
12056
  });
11601
12057
 
12058
+ // src/hooks/agent-roster.ts
12059
+ import { lstatSync, readFileSync as readFileSync17, statSync as statSync17 } from "node:fs";
12060
+ import { homedir as homedir21 } from "node:os";
12061
+ import { dirname as dirname7, resolve as resolve15 } from "node:path";
12062
+ function installedHookAt(path, cli) {
12063
+ try {
12064
+ const stat = statSync17(path);
12065
+ if (!stat.isFile() || stat.size > 131072)
12066
+ return false;
12067
+ const text = readFileSync17(path, "utf8");
12068
+ if (text.includes("failproofai"))
12069
+ return true;
12070
+ if (cli !== "pi")
12071
+ return false;
12072
+ const config = JSON.parse(text);
12073
+ if (!config || typeof config !== "object" || Array.isArray(config))
12074
+ return false;
12075
+ const packages = config.packages;
12076
+ return Array.isArray(packages) && packages.some((entry) => typeof entry === "string" && /(?:^|\/)pi-extension\/?$/.test(entry));
12077
+ } catch {
12078
+ return false;
12079
+ }
12080
+ }
12081
+ function runtimeAgentSettingsPath(cli, cwd, userHome = homedir21(), hookScope) {
12082
+ if (cli === "hermes") {
12083
+ if (hookScope && hookScope !== "user")
12084
+ return null;
12085
+ const home = process.env.HERMES_HOME;
12086
+ return resolve15(home?.trim() ? home : resolve15(userHome, ".hermes"), "config.yaml");
12087
+ }
12088
+ if (cli === "openclaw") {
12089
+ if (hookScope && hookScope !== "user")
12090
+ return null;
12091
+ const config = process.env.OPENCLAW_CONFIG_PATH;
12092
+ if (config?.trim())
12093
+ return resolve15(config);
12094
+ const state = process.env.OPENCLAW_STATE_DIR || process.env.OPENCLAW_HOME;
12095
+ return resolve15(state?.trim() ? state : resolve15(userHome, ".openclaw"), "openclaw.json");
12096
+ }
12097
+ const relative = USER_SETTINGS[cli];
12098
+ if (!relative)
12099
+ return null;
12100
+ const override = cli === "codex" ? process.env.CODEX_HOME : cli === "claude" ? process.env.CLAUDE_CONFIG_DIR : undefined;
12101
+ const user = resolve15(override?.trim() ? override : userHome, override?.trim() ? cli === "codex" ? "hooks.json" : "settings.json" : relative);
12102
+ if (hookScope === "user")
12103
+ return user;
12104
+ const scopeFiles = hookScope === "local" ? cli === "claude" ? [".claude/settings.local.json"] : [] : hookScope === "project" ? (PROJECT_SETTINGS[cli] ?? []).filter((name) => name !== ".claude/settings.local.json") : PROJECT_SETTINGS[cli] ?? [];
12105
+ const matches = new Set;
12106
+ if (hookScope === undefined && installedHookAt(user, cli))
12107
+ matches.add(user);
12108
+ let dir = resolve15(cwd ?? process.cwd());
12109
+ const userRoot = resolve15(userHome);
12110
+ for (let depth = 0;depth < 16 && dir !== userRoot; depth++) {
12111
+ for (const candidate of scopeFiles) {
12112
+ const path = resolve15(dir, candidate);
12113
+ if (installedHookAt(path, cli))
12114
+ matches.add(path);
12115
+ }
12116
+ const parent = dirname7(dir);
12117
+ if (parent === dir)
12118
+ break;
12119
+ dir = parent;
12120
+ }
12121
+ if (matches.size > 1)
12122
+ return null;
12123
+ if (hookScope === "project" || hookScope === "local")
12124
+ return matches.values().next().value ?? null;
12125
+ return matches.values().next().value ?? user;
12126
+ }
12127
+ function readRuntimeAgentIdentity(cli, settingsPath) {
12128
+ if (!settingsPath)
12129
+ return null;
12130
+ try {
12131
+ const path = agentRosterFile();
12132
+ const stat = lstatSync(path);
12133
+ if (!stat.isFile() || (stat.mode & 63) !== 0 || stat.size > MAX_ROSTER_BYTES)
12134
+ return null;
12135
+ const roster = JSON.parse(readFileSync17(path, "utf8"));
12136
+ if (!roster || typeof roster !== "object" || Array.isArray(roster))
12137
+ return null;
12138
+ const data = roster;
12139
+ if (data.schemaVersion !== 1 || !Array.isArray(data.agents) || data.agents.length > MAX_ROSTER_AGENTS)
12140
+ return null;
12141
+ const absolute = resolve15(settingsPath);
12142
+ const agent = data.agents.find((entry) => {
12143
+ if (!entry || typeof entry !== "object" || Array.isArray(entry))
12144
+ return false;
12145
+ const record = entry;
12146
+ return record.integration === cli && record.settingsPath === absolute && validAgentIdentity({ integration: record.integration, instanceId: record.instanceId });
12147
+ });
12148
+ const instanceId = agent?.instanceId;
12149
+ return validAgentIdentity({ integration: cli, instanceId }) ? { integration: cli, instanceId } : null;
12150
+ } catch {
12151
+ return null;
12152
+ }
12153
+ }
12154
+ var MAX_ROSTER_AGENTS = 256, MAX_ROSTER_BYTES = 4000000, USER_SETTINGS, PROJECT_SETTINGS;
12155
+ var init_agent_roster = __esm(() => {
12156
+ init_fp_home();
12157
+ init_agent_targets();
12158
+ USER_SETTINGS = {
12159
+ claude: ".claude/settings.json",
12160
+ codex: ".codex/hooks.json",
12161
+ copilot: ".copilot/hooks/failproofai.json",
12162
+ cursor: ".cursor/hooks.json",
12163
+ opencode: ".config/opencode/opencode.json",
12164
+ pi: ".pi/agent/settings.json",
12165
+ factory: ".factory/hooks.json",
12166
+ devin: ".config/devin/config.json",
12167
+ antigravity: ".gemini/config/hooks.json",
12168
+ goose: ".agents/plugins/failproofai/hooks/hooks.json"
12169
+ };
12170
+ PROJECT_SETTINGS = {
12171
+ claude: [".claude/settings.local.json", ".claude/settings.json"],
12172
+ codex: [".codex/hooks.json"],
12173
+ copilot: [".github/hooks/failproofai.json"],
12174
+ cursor: [".cursor/hooks.json"],
12175
+ opencode: [".opencode/opencode.json"],
12176
+ pi: [".pi/settings.json"],
12177
+ factory: [".factory/hooks.json"],
12178
+ devin: [".devin/config.json"],
12179
+ antigravity: [".agents/hooks.json"],
12180
+ goose: [".agents/plugins/failproofai/hooks/hooks.json"]
12181
+ };
12182
+ });
12183
+
11602
12184
  // src/hooks/semantic/jev-config.ts
11603
- import { closeSync as closeSync2, constants as fsConstants2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2, statSync as statSync16 } from "node:fs";
11604
- import { dirname as dirname7 } from "node:path";
12185
+ import { closeSync as closeSync2, constants as fsConstants2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2, statSync as statSync18 } from "node:fs";
12186
+ import { dirname as dirname8 } from "node:path";
11605
12187
  function parseJevMode(raw) {
11606
12188
  return raw === "off" || raw === "observe" || raw === "enforce" ? raw : null;
11607
12189
  }
12190
+ function jevCloudBaseUrl(cloudBase) {
12191
+ const url = new URL(cloudBase);
12192
+ return `${url.origin}${url.pathname.replace(/\/+$/, "")}${JEV_CLOUD_BASE_PATH}`;
12193
+ }
11608
12194
  function jevConfigPath() {
11609
12195
  return jevConfigFile();
11610
12196
  }
@@ -11746,7 +12332,12 @@ function validateJevConfig(raw, envKey, cloud) {
11746
12332
  missingKey: true
11747
12333
  };
11748
12334
  }
11749
- const cfg = { provider: kind, apiKey, mode: DEFAULT_JEV_MODE, timeoutMs: JEV_CONFIG_DEFAULT_TIMEOUT_MS };
12335
+ const cfg = {
12336
+ provider: kind,
12337
+ apiKey,
12338
+ mode: DEFAULT_JEV_MODE,
12339
+ timeoutMs: kind === JEV_CLOUD_PROVIDER ? CLOUD_JEV_TIMEOUT_MS : JEV_CONFIG_DEFAULT_TIMEOUT_MS
12340
+ };
11750
12341
  if (o.baseUrl !== undefined) {
11751
12342
  const r = validateBaseUrl(o.baseUrl);
11752
12343
  if (!r.ok)
@@ -11832,7 +12423,7 @@ function looseConfigDirMode(path) {
11832
12423
  if (!modesAreMeaningful())
11833
12424
  return null;
11834
12425
  try {
11835
- const mode = statSync16(dirname7(path)).mode & 511;
12426
+ const mode = statSync18(dirname8(path)).mode & 511;
11836
12427
  return (mode & DIR_WRITABLE_BY_OTHERS2) !== 0 ? mode : null;
11837
12428
  } catch {
11838
12429
  return null;
@@ -11893,8 +12484,8 @@ function inspectJevConfig() {
11893
12484
  path,
11894
12485
  mode,
11895
12486
  reason: "too-open",
11896
- problem: `its directory ${dirname7(path)} is ${dirMode.toString(8).padStart(4, "0")} — other users can write there, ` + `so they can put their own config in its place; it must be owner-only (chmod 700 ${dirname7(path)})`,
11897
- fix: `chmod 700 ${dirname7(path)}`
12487
+ problem: `its directory ${dirname8(path)} is ${dirMode.toString(8).padStart(4, "0")} — other users can write there, ` + `so they can put their own config in its place; it must be owner-only (chmod 700 ${dirname8(path)})`,
12488
+ fix: `chmod 700 ${dirname8(path)}`
11898
12489
  };
11899
12490
  }
11900
12491
  if (st.size > MAX_CONFIG_BYTES)
@@ -11996,7 +12587,80 @@ function loadJevConfig() {
11996
12587
  return null;
11997
12588
  }
11998
12589
  }
11999
- var DEFAULT_JEV_MODE = "enforce", JEV_PROVIDER_KINDS, JEV_CLOUD_PROVIDER = "failproofai", JEV_API_KEY_ENV = "FAILPROOFAI_JEV_API_KEY", JEV_CONFIG_DEFAULT_TIMEOUT_MS = 3000, MIN_JEV_TIMEOUT_MS = 100, MAX_JEV_TIMEOUT_MS = 1e4, JEV_CALIBRATED_FAMILY, MAX_CONFIG_BYTES, OPEN_FLAGS, VERSIONED_MODEL_RE, CLOUDFLARE_ACCOUNT_ID_RE, API_KEY_RE, MODEL_RE, LOOPBACK_HOSTS, CREDENTIAL_PARAM_PARTS, CREDENTIAL_PARAM_NAMES, QUOTABLE_PARAM_RE, CREDENTIAL_PREFIX_RE, KEY_STAND_IN = "supplied-by-the-environment", DIR_WRITABLE_BY_OTHERS2 = 18, KEY_LACKS_JEV_PROBLEM = "this machine is connected to FailproofAI Cloud, but no Jev key is stored for that connection (its key lacks jev:evaluate, or the connect could not confirm it)";
12590
+ function loadJevConfigForCloudMode(mode) {
12591
+ if (mode === "off")
12592
+ return { config: null, machineId: null, problem: null };
12593
+ const key = `${mode}\x00${jevInputsVersion()}`;
12594
+ if (cloudModeMemo?.key === key)
12595
+ return cloudModeMemo.value;
12596
+ const value = computeCloudModeConfig(mode);
12597
+ cloudModeMemo = { key, value };
12598
+ return value;
12599
+ }
12600
+ function jevInputsVersion() {
12601
+ const credentials = credentialsFile();
12602
+ const config = configFile();
12603
+ return [
12604
+ process.platform,
12605
+ credentials,
12606
+ statVersion(credentials),
12607
+ statVersion(dirname8(credentials)),
12608
+ config,
12609
+ statVersion(config)
12610
+ ].join("\x00");
12611
+ }
12612
+ function statVersion(path) {
12613
+ try {
12614
+ const st = statSync18(path, { bigint: true });
12615
+ return `${st.dev}:${st.ino}:${st.mode}:${st.size}:${st.mtimeNs}:${st.ctimeNs}`;
12616
+ } catch (err) {
12617
+ return `-${err.code ?? "error"}`;
12618
+ }
12619
+ }
12620
+ function computeCloudModeConfig(mode) {
12621
+ try {
12622
+ if (readConfig().collector.sessions !== true) {
12623
+ return { config: null, machineId: null, problem: TRANSCRIPTS_DISABLED_PROBLEM };
12624
+ }
12625
+ const credential = readJevCloudCredential();
12626
+ if (credential.status === "absent")
12627
+ return { config: null, machineId: null, problem: JEV_UNCONFIGURED_PROBLEM };
12628
+ if (credential.status === "refused") {
12629
+ return {
12630
+ config: null,
12631
+ machineId: null,
12632
+ problem: `${JEV_UNCONFIGURED_PROBLEM}: the FailproofAI Cloud Jev credential is refused — ${credential.problem}`
12633
+ };
12634
+ }
12635
+ const machineId = readCredentials().cloud?.machineId || null;
12636
+ if (!machineId) {
12637
+ return {
12638
+ config: null,
12639
+ machineId: null,
12640
+ problem: `${JEV_UNCONFIGURED_PROBLEM}: this machine has no FailproofAI Cloud machine id (no policy connection in credentials.json)`
12641
+ };
12642
+ }
12643
+ const raw = {
12644
+ provider: JEV_CLOUD_PROVIDER,
12645
+ baseUrl: jevCloudBaseUrl(cloudBaseFor(credential.credential)),
12646
+ mode,
12647
+ timeoutMs: CLOUD_JEV_TIMEOUT_MS
12648
+ };
12649
+ const r = validateJevConfig(raw, null, credential.credential);
12650
+ return r.ok ? { config: r.value, machineId, problem: null } : { config: null, machineId, problem: `${JEV_UNCONFIGURED_PROBLEM}: the FailproofAI Cloud Jev credential — ${r.problem}` };
12651
+ } catch (err) {
12652
+ return { config: null, machineId: null, problem: `${JEV_UNCONFIGURED_PROBLEM}: ${err instanceof Error ? err.message : String(err)}` };
12653
+ }
12654
+ }
12655
+ function cloudBaseFor(credential) {
12656
+ try {
12657
+ const cloud = readCredentials().cloud;
12658
+ if (cloud?.url && new URL(cloud.url).origin === new URL(credential.url).origin)
12659
+ return cloud.url;
12660
+ } catch {}
12661
+ return credential.url;
12662
+ }
12663
+ var DEFAULT_JEV_MODE = "enforce", JEV_PROVIDER_KINDS, JEV_CLOUD_PROVIDER = "failproofai", JEV_CLOUD_BASE_PATH = "/enforcement/v1/jev", JEV_API_KEY_ENV = "FAILPROOFAI_JEV_API_KEY", JEV_CONFIG_DEFAULT_TIMEOUT_MS = 3000, CLOUD_JEV_TIMEOUT_MS = 5000, MIN_JEV_TIMEOUT_MS = 100, MAX_JEV_TIMEOUT_MS = 1e4, JEV_CALIBRATED_FAMILY, MAX_CONFIG_BYTES, OPEN_FLAGS, VERSIONED_MODEL_RE, CLOUDFLARE_ACCOUNT_ID_RE, API_KEY_RE, MODEL_RE, LOOPBACK_HOSTS, CREDENTIAL_PARAM_PARTS, CREDENTIAL_PARAM_NAMES, QUOTABLE_PARAM_RE, CREDENTIAL_PREFIX_RE, KEY_STAND_IN = "supplied-by-the-environment", DIR_WRITABLE_BY_OTHERS2 = 18, KEY_LACKS_JEV_PROBLEM = "this machine is connected to FailproofAI Cloud, but no Jev key is stored for that connection (its key lacks jev:evaluate, or the connect could not confirm it)", JEV_UNCONFIGURED_PROBLEM = "jev_unconfigured", TRANSCRIPTS_DISABLED_PROBLEM = "transcripts_disabled", cloudModeMemo = null;
12000
12664
  var init_jev_config = __esm(() => {
12001
12665
  init_fp_config();
12002
12666
  init_fp_home();
@@ -12015,10 +12679,127 @@ var init_jev_config = __esm(() => {
12015
12679
  CREDENTIAL_PREFIX_RE = /^(?:(?:sk|rk)[-_]|gh[pousr]_|github_pat_|glpat-|xox[abprs]-|AKIA[0-9A-Z]{12}|AIza[0-9A-Za-z_-]{20}|hf_[A-Za-z0-9]{16}|vck_)/;
12016
12680
  });
12017
12681
 
12682
+ // src/hooks/semantic/cloud-jev-health.ts
12683
+ function forScope(scope) {
12684
+ if (state.scope !== scope)
12685
+ state = fresh(scope);
12686
+ return state;
12687
+ }
12688
+ function cloudJevGate(scope, at = clock()) {
12689
+ const s = forScope(scope);
12690
+ if (s.openUntil === null)
12691
+ return { ask: true, probe: false };
12692
+ if (at < s.openUntil || s.probing)
12693
+ return { ask: false };
12694
+ s.probing = true;
12695
+ return { ask: true, probe: true };
12696
+ }
12697
+ function classifyCloudJevReview(review, opts = { reachedCloud: true }) {
12698
+ if (review.kind === "answered")
12699
+ return opts.reachedCloud ? "answered" : "neutral";
12700
+ if (review.kind !== "fallback")
12701
+ return "neutral";
12702
+ const code = review.reason;
12703
+ if (code === "http-429" || code === "rate-limited")
12704
+ return "rate-limited";
12705
+ if (FAILURES.has(code) || /^http-5\d\d$/.test(code))
12706
+ return "failed";
12707
+ return "neutral";
12708
+ }
12709
+ function recordCloudJevResult(scope, result, code, probe, at = clock()) {
12710
+ if (state.scope !== scope)
12711
+ return;
12712
+ const s = state;
12713
+ if (probe)
12714
+ s.probing = false;
12715
+ switch (result) {
12716
+ case "answered":
12717
+ s.failures = 0;
12718
+ s.lastFailure = null;
12719
+ s.openUntil = null;
12720
+ s.rateLimited = [];
12721
+ break;
12722
+ case "rate-limited":
12723
+ s.rateLimited.push(at);
12724
+ if (code === "http-429") {
12725
+ s.failures = 0;
12726
+ s.openUntil = null;
12727
+ }
12728
+ break;
12729
+ case "failed":
12730
+ s.failures += 1;
12731
+ s.lastFailure = code;
12732
+ if (probe || s.failures >= BREAKER_FAILURES)
12733
+ s.openUntil = at + BREAKER_OPEN_MS;
12734
+ break;
12735
+ case "neutral":
12736
+ break;
12737
+ }
12738
+ }
12739
+ function isCloudJevHealthMessage(message) {
12740
+ return message.startsWith(JEV_RATE_LIMITED) || message.startsWith(JEV_UNAVAILABLE);
12741
+ }
12742
+ function cloudJevHealthErrors(at = clock()) {
12743
+ const s = state;
12744
+ const out = [];
12745
+ s.rateLimited = s.rateLimited.filter((t) => at - t < RATE_LIMIT_WINDOW_MS);
12746
+ const n = s.rateLimited.length;
12747
+ if (n === 0) {
12748
+ s.reportedRate = null;
12749
+ } else {
12750
+ if (s.reportedRate === null || at - s.reportedRate.at >= REPORT_REFRESH_MS)
12751
+ s.reportedRate = { n, at };
12752
+ const minutes = Math.round(RATE_LIMIT_WINDOW_MS / 60000);
12753
+ const count = s.reportedRate.n;
12754
+ out.push({
12755
+ id: "jevMode",
12756
+ version: null,
12757
+ kind: "daemon",
12758
+ message: `${JEV_RATE_LIMITED}: ${count} call${count === 1 ? "" : "s"} fell back to regex in the last ${minutes} min`
12759
+ });
12760
+ }
12761
+ if (s.openUntil !== null) {
12762
+ out.push({
12763
+ id: "jevMode",
12764
+ version: null,
12765
+ kind: "daemon",
12766
+ message: `${JEV_UNAVAILABLE}: FailproofAI Cloud Jev failed ${BREAKER_FAILURES} or more calls in a row ` + `(last: ${s.lastFailure ?? "error"}), so tool calls skip it for ${BREAKER_OPEN_MS / 1000} s at a time ` + "and the regex decides alone"
12767
+ });
12768
+ }
12769
+ return out;
12770
+ }
12771
+ function reportCloudJevHealth(at = clock()) {
12772
+ try {
12773
+ const entries = cloudJevHealthErrors(at);
12774
+ const text = JSON.stringify(entries);
12775
+ if (text === state.lastReport)
12776
+ return;
12777
+ state.lastReport = text;
12778
+ const report = (readCloudPolicyErrors() ?? []).filter((e) => !(e.id === "jevMode" && isCloudJevHealthMessage(e.message)));
12779
+ writeCloudPolicyErrors([...report, ...entries]);
12780
+ } catch {}
12781
+ }
12782
+ var BREAKER_FAILURES = 3, BREAKER_OPEN_MS = 60000, RATE_LIMIT_WINDOW_MS, REPORT_REFRESH_MS = 30000, JEV_RATE_LIMITED = "jev_rate_limited", JEV_UNAVAILABLE = "jev_unavailable", BREAKER_SKIP_REASON = "unavailable", fresh = (scope) => ({
12783
+ scope,
12784
+ failures: 0,
12785
+ lastFailure: null,
12786
+ openUntil: null,
12787
+ probing: false,
12788
+ rateLimited: [],
12789
+ reportedRate: null,
12790
+ lastReport: "[]"
12791
+ }), state, clock = () => performance.now(), FAILURES;
12792
+ var init_cloud_jev_health = __esm(() => {
12793
+ init_cloud_policy_errors();
12794
+ RATE_LIMIT_WINDOW_MS = 10 * 60000;
12795
+ state = fresh("");
12796
+ FAILURES = new Set(["timeout", "network", "malformed", "model-mismatch", "upstream-error", "error"]);
12797
+ });
12798
+
12018
12799
  // src/hooks/semantic/facts.ts
12019
- import { existsSync as existsSync20, readFileSync as readFileSync16, statSync as statSync17 } from "node:fs";
12020
- import { homedir as homedir20 } from "node:os";
12021
- import { dirname as dirname8, isAbsolute as isAbsolute3, resolve as resolve14 } from "node:path";
12800
+ import { existsSync as existsSync21, readFileSync as readFileSync18, statSync as statSync19 } from "node:fs";
12801
+ import { homedir as homedir22 } from "node:os";
12802
+ import { dirname as dirname9, isAbsolute as isAbsolute3, resolve as resolve16 } from "node:path";
12022
12803
  function classifyTool(toolName) {
12023
12804
  if (SHELL_TOOLS.has(toolName))
12024
12805
  return { toolClass: "shell", toolIsKnown: true };
@@ -12197,10 +12978,10 @@ function pathFact(token, base, projectRoot, home) {
12197
12978
  const slash = t.lastIndexOf("/");
12198
12979
  t = slash === -1 ? "." : slash === 0 ? "/" : t.slice(0, slash);
12199
12980
  }
12200
- const resolved = isAbsolute3(t) ? resolve14(t) : resolve14(base, t);
12981
+ const resolved = isAbsolute3(t) ? resolve16(t) : resolve16(base, t);
12201
12982
  return { asWritten: token, resolved, relation: relationOf(resolved, projectRoot, home) };
12202
12983
  }
12203
- function extractPaths(toolInput, cwd, projectRoot, scanned, home = homedir20()) {
12984
+ function extractPaths(toolInput, cwd, projectRoot, scanned, home = homedir22()) {
12204
12985
  const base0 = cwd ?? home;
12205
12986
  const facts = [];
12206
12987
  const seen = new Set;
@@ -12242,10 +13023,10 @@ function extractPaths(toolInput, cwd, projectRoot, scanned, home = homedir20())
12242
13023
  function findGitDir(start) {
12243
13024
  let dir = start;
12244
13025
  for (let i = 0;i < 40; i++) {
12245
- const candidate = resolve14(dir, ".git");
12246
- if (existsSync20(candidate))
13026
+ const candidate = resolve16(dir, ".git");
13027
+ if (existsSync21(candidate))
12247
13028
  return candidate;
12248
- const parent = dirname8(dir);
13029
+ const parent = dirname9(dir);
12249
13030
  if (parent === dir)
12250
13031
  return null;
12251
13032
  dir = parent;
@@ -12256,7 +13037,7 @@ function findProjectRoot(cwd) {
12256
13037
  if (!cwd)
12257
13038
  return null;
12258
13039
  const gitDir = findGitDir(cwd);
12259
- return gitDir ? dirname8(gitDir) : cwd;
13040
+ return gitDir ? dirname9(gitDir) : cwd;
12260
13041
  }
12261
13042
  function readCurrentBranch(cwd) {
12262
13043
  if (!cwd)
@@ -12265,15 +13046,15 @@ function readCurrentBranch(cwd) {
12265
13046
  const gitPath = findGitDir(cwd);
12266
13047
  if (!gitPath)
12267
13048
  return null;
12268
- let headFile = resolve14(gitPath, "HEAD");
12269
- if (statSync17(gitPath).isFile()) {
12270
- const pointer = readFileSync16(gitPath, "utf8").trim();
13049
+ let headFile = resolve16(gitPath, "HEAD");
13050
+ if (statSync19(gitPath).isFile()) {
13051
+ const pointer = readFileSync18(gitPath, "utf8").trim();
12271
13052
  const m = /^gitdir:\s*(.+)$/.exec(pointer);
12272
13053
  if (!m)
12273
13054
  return null;
12274
- headFile = resolve14(dirname8(gitPath), m[1], "HEAD");
13055
+ headFile = resolve16(dirname9(gitPath), m[1], "HEAD");
12275
13056
  }
12276
- const head = readFileSync16(headFile, "utf8").trim();
13057
+ const head = readFileSync18(headFile, "utf8").trim();
12277
13058
  const ref = /^ref:\s*refs\/heads\/(.+)$/.exec(head);
12278
13059
  return ref ? ref[1] : null;
12279
13060
  } catch {
@@ -14815,31 +15596,31 @@ __export(exports_intent, {
14815
15596
  readIntent: () => readIntent
14816
15597
  });
14817
15598
  import {
14818
- chmodSync as chmodSync3,
15599
+ chmodSync as chmodSync4,
14819
15600
  closeSync as closeSync3,
14820
15601
  mkdirSync as mkdirSync9,
14821
15602
  openSync as openSync3,
14822
15603
  readdirSync as readdirSync13,
14823
- readFileSync as readFileSync17,
15604
+ readFileSync as readFileSync19,
14824
15605
  readSync as readSync3,
14825
- renameSync as renameSync5,
14826
- statSync as statSync18,
15606
+ renameSync as renameSync6,
15607
+ statSync as statSync20,
14827
15608
  unlinkSync as unlinkSync2,
14828
- writeFileSync as writeFileSync7
15609
+ writeFileSync as writeFileSync8
14829
15610
  } from "node:fs";
14830
- import { dirname as dirname9, resolve as resolve15 } from "node:path";
15611
+ import { dirname as dirname10, resolve as resolve17 } from "node:path";
14831
15612
  function modesAreMeaningful2() {
14832
15613
  return process.platform !== "win32";
14833
15614
  }
14834
15615
  function storeDirChain() {
14835
- const home = resolve15(failproofaiHome());
15616
+ const home = resolve17(failproofaiHome());
14836
15617
  const chain = [];
14837
15618
  let dir = sessionsDir();
14838
15619
  for (let i = 0;i < 8; i++) {
14839
15620
  chain.push(dir);
14840
15621
  if (dir === home)
14841
15622
  break;
14842
- const parent = dirname9(dir);
15623
+ const parent = dirname10(dir);
14843
15624
  if (parent === dir)
14844
15625
  break;
14845
15626
  dir = parent;
@@ -14852,15 +15633,15 @@ function looseIntentStoreDir() {
14852
15633
  for (const dir of storeDirChain()) {
14853
15634
  let mode;
14854
15635
  try {
14855
- mode = statSync18(dir).mode & 511;
15636
+ mode = statSync20(dir).mode & 511;
14856
15637
  } catch {
14857
15638
  continue;
14858
15639
  }
14859
15640
  if ((mode & DIR_WRITABLE_BY_OTHERS3) === 0)
14860
15641
  continue;
14861
15642
  try {
14862
- chmodSync3(dir, mode & ~DIR_WRITABLE_BY_OTHERS3);
14863
- if ((statSync18(dir).mode & DIR_WRITABLE_BY_OTHERS3) !== 0)
15643
+ chmodSync4(dir, mode & ~DIR_WRITABLE_BY_OTHERS3);
15644
+ if ((statSync20(dir).mode & DIR_WRITABLE_BY_OTHERS3) !== 0)
14864
15645
  return dir;
14865
15646
  } catch {
14866
15647
  return dir;
@@ -14870,7 +15651,7 @@ function looseIntentStoreDir() {
14870
15651
  }
14871
15652
  function readIntentFile(sessionId) {
14872
15653
  try {
14873
- const parsed = JSON.parse(readFileSync17(intentFile(sessionId), "utf8"));
15654
+ const parsed = JSON.parse(readFileSync19(intentFile(sessionId), "utf8"));
14874
15655
  return Array.isArray(parsed?.prompts) ? parsed : { prompts: [] };
14875
15656
  } catch {
14876
15657
  return { prompts: [] };
@@ -14887,8 +15668,8 @@ function appendPrompt(sessionId, entry) {
14887
15668
  const target = intentFile(sessionId);
14888
15669
  const isNew = !fileExists2(target);
14889
15670
  const tmp = `${target}.${process.pid}.tmp`;
14890
- writeFileSync7(tmp, JSON.stringify(file), { mode: 384 });
14891
- renameSync5(tmp, target);
15671
+ writeFileSync8(tmp, JSON.stringify(file), { mode: 384 });
15672
+ renameSync6(tmp, target);
14892
15673
  if (isNew)
14893
15674
  pruneExpiredSessions(entry.at);
14894
15675
  return true;
@@ -14898,7 +15679,7 @@ function appendPrompt(sessionId, entry) {
14898
15679
  }
14899
15680
  function fileExists2(path) {
14900
15681
  try {
14901
- statSync18(path);
15682
+ statSync20(path);
14902
15683
  return true;
14903
15684
  } catch {
14904
15685
  return false;
@@ -14911,9 +15692,9 @@ function pruneExpiredSessions(now = Date.now()) {
14911
15692
  for (const name of readdirSync13(dir)) {
14912
15693
  if (!SESSION_FILE_RE3.test(name))
14913
15694
  continue;
14914
- const path = resolve15(dir, name);
15695
+ const path = resolve17(dir, name);
14915
15696
  try {
14916
- const st = statSync18(path);
15697
+ const st = statSync20(path);
14917
15698
  if (st.isFile() && now - st.mtimeMs > INTENT_MAX_AGE_MS) {
14918
15699
  unlinkSync2(path);
14919
15700
  removed++;
@@ -15222,7 +16003,7 @@ function visitLinesBackwards(transcriptPath, maxBytes, visit) {
15222
16003
  return;
15223
16004
  let fd;
15224
16005
  try {
15225
- const st = statSync18(path);
16006
+ const st = statSync20(path);
15226
16007
  if (!st.isFile() || st.size === 0)
15227
16008
  return;
15228
16009
  fd = openSync3(path, "r");
@@ -15295,7 +16076,7 @@ function readIntent(sessionId, now = Date.now()) {
15295
16076
  const agent = latest && typeof latest.agent === "string" && latest.agent.length > 0 ? latest.agent : null;
15296
16077
  return { userSaid: prompts.map((p) => p.text), agentLastMessage: agent };
15297
16078
  }
15298
- var MAX_RECORDED_PROMPTS = 5, INTENT_MAX_AGE_MS, MAX_CLOCK_SKEW_MS, SESSION_ID_RE2, sessionsDir = () => resolve15(semanticDir(), "sessions"), intentFile = (sessionId) => resolve15(sessionsDir(), `${sessionId}.json`), DIR_WRITABLE_BY_OTHERS3 = 18, SESSION_FILE_RE3, NON_HUMAN_PREFIXES, CONTINUATION_PREFIX = "This session is being continued from a previous conversation", IDE_MACHINE_OPENERS, IDE_AMBIGUOUS_OPENERS, IDE_REQUEST_HEADINGS, obj = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : undefined, CLAUDE_MACHINE_SOURCES, claudeMachineTurn = (payload) => typeof payload.source === "string" && CLAUDE_MACHINE_SOURCES.has(payload.source), piMachineTurn = (payload) => payload.input_source === "extension" || payload.source === "extension", openclawMachineRun = (payload) => {
16079
+ var MAX_RECORDED_PROMPTS = 5, INTENT_MAX_AGE_MS, MAX_CLOCK_SKEW_MS, SESSION_ID_RE2, sessionsDir = () => resolve17(semanticDir(), "sessions"), intentFile = (sessionId) => resolve17(sessionsDir(), `${sessionId}.json`), DIR_WRITABLE_BY_OTHERS3 = 18, SESSION_FILE_RE3, NON_HUMAN_PREFIXES, CONTINUATION_PREFIX = "This session is being continued from a previous conversation", IDE_MACHINE_OPENERS, IDE_AMBIGUOUS_OPENERS, IDE_REQUEST_HEADINGS, obj = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : undefined, CLAUDE_MACHINE_SOURCES, claudeMachineTurn = (payload) => typeof payload.source === "string" && CLAUDE_MACHINE_SOURCES.has(payload.source), piMachineTurn = (payload) => payload.input_source === "extension" || payload.source === "extension", openclawMachineRun = (payload) => {
15299
16080
  const meta = obj(payload.openclaw);
15300
16081
  if (!meta)
15301
16082
  return false;
@@ -15485,6 +16266,10 @@ function normalizeNative(body, sentModel, opts) {
15485
16266
  if (!body || typeof body !== "object" || Array.isArray(body))
15486
16267
  throw new JevError("malformed", "Jev returned no object");
15487
16268
  const b = body;
16269
+ const cloud = opts.cloudReply && b.cloud !== undefined ? { cloud: b.cloud } : {};
16270
+ if ((typeof b.answers !== "object" || b.answers === null) && "cloud" in cloud && b.error === undefined) {
16271
+ return { model: typeof b.model === "string" ? scrubSecret(b.model, opts.apiKey) : "", answers: {}, ...cloud };
16272
+ }
15488
16273
  if (typeof b.answers !== "object" || b.answers === null) {
15489
16274
  if (b.error !== undefined) {
15490
16275
  const code = typeof b.error === "object" && b.error !== null ? b.error.code : undefined;
@@ -15512,7 +16297,8 @@ function normalizeNative(body, sentModel, opts) {
15512
16297
  model,
15513
16298
  answers: b.answers,
15514
16299
  ...usage ? { usage } : {},
15515
- ...unverified ? { modelUnverified: true } : {}
16300
+ ...unverified ? { modelUnverified: true } : {},
16301
+ ...cloud
15516
16302
  };
15517
16303
  }
15518
16304
  function nativeTransport(opts) {
@@ -15710,7 +16496,8 @@ function transportForConfig(input) {
15710
16496
  apiKey: cfg.apiKey,
15711
16497
  model: route.model,
15712
16498
  allowUnreported: false,
15713
- derivedBase: true
16499
+ derivedBase: true,
16500
+ cloudReply: true
15714
16501
  })),
15715
16502
  via: "failproofai",
15716
16503
  model: route.model
@@ -15880,8 +16667,8 @@ var init_pack_policies = __esm(() => {
15880
16667
 
15881
16668
  // src/hooks/semantic/evaluator.ts
15882
16669
  import { createHash as createHash6 } from "node:crypto";
15883
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync10, renameSync as renameSync6, statSync as statSync19 } from "node:fs";
15884
- import { resolve as resolve16 } from "node:path";
16670
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync10, renameSync as renameSync7, statSync as statSync21 } from "node:fs";
16671
+ import { resolve as resolve18 } from "node:path";
15885
16672
  function storeCut(message) {
15886
16673
  return typeof message === "string" && message.length >= MAX_USER_MESSAGE_CHARS - STORE_CUT_SLACK && OMISSION_MARK.test(message);
15887
16674
  }
@@ -16054,14 +16841,14 @@ function appendVerdictLog(row) {
16054
16841
  const file = verdictLogFile();
16055
16842
  mkdirSync10(semanticDir(), { recursive: true, mode: 448 });
16056
16843
  try {
16057
- if (statSync19(file).size > VERDICT_LOG_MAX_BYTES)
16058
- renameSync6(file, `${file}.1`);
16844
+ if (statSync21(file).size > VERDICT_LOG_MAX_BYTES)
16845
+ renameSync7(file, `${file}.1`);
16059
16846
  } catch {}
16060
16847
  appendFileSync3(file, JSON.stringify(row) + `
16061
16848
  `, { mode: 384 });
16062
16849
  } catch {}
16063
16850
  }
16064
- var DEFAULT_JEV_TIMEOUT_MS = 3000, OMISSION_MARK, STORE_CUT_SLACK = 64, VERDICT_LOG_MAX_BYTES, verdictLogFile = () => resolve16(semanticDir(), "verdicts.jsonl");
16851
+ var DEFAULT_JEV_TIMEOUT_MS = 3000, OMISSION_MARK, STORE_CUT_SLACK = 64, VERDICT_LOG_MAX_BYTES, verdictLogFile = () => resolve18(semanticDir(), "verdicts.jsonl");
16065
16852
  var init_evaluator = __esm(() => {
16066
16853
  init_fp_home();
16067
16854
  init_compile();
@@ -16075,6 +16862,387 @@ var init_evaluator = __esm(() => {
16075
16862
  VERDICT_LOG_MAX_BYTES = 5 * 1024 * 1024;
16076
16863
  });
16077
16864
 
16865
+ // src/hooks/semantic/cloud-jev.ts
16866
+ function noul2(probe) {
16867
+ return {
16868
+ type: "noul",
16869
+ instructions: probe.instructions,
16870
+ ...probe.criteria ? { criteria: { ...probe.criteria } } : {}
16871
+ };
16872
+ }
16873
+ function cloudGlobalQuestions(intent, userSaidCount) {
16874
+ const questions = { [INJECTION_PROBE.id]: noul2(INJECTION_PROBE) };
16875
+ if (userSaidCount > 0) {
16876
+ if (intent === "v1")
16877
+ for (const probe of TASK_PROBES)
16878
+ questions[probe.id] = noul2(probe);
16879
+ else
16880
+ questions[SCOPE_PROBE.id] = noul2(SCOPE_PROBE);
16881
+ }
16882
+ return questions;
16883
+ }
16884
+ function secretWords(toolInput) {
16885
+ const text = (typeof toolInput.command === "string" ? toolInput.command : Object.entries(toolInput).filter(([key, v]) => typeof v === "string" && v.length <= 300 && !/content|old_string|new_string|body|text|prompt/i.test(key)).map(([, v]) => v).join(`
16886
+ `)).slice(0, MAX_SECRET_SCAN_CHARS);
16887
+ try {
16888
+ return redactSecretsDetailed(text, { blunt: false }).found.map((s) => s.toLowerCase()).filter((s) => s.length > 0);
16889
+ } catch {
16890
+ return [];
16891
+ }
16892
+ }
16893
+ function cloudTargetScan(toolInput, scan = scanTargets(toolInput)) {
16894
+ const secrets = scan.groups.length > 0 ? secretWords(toolInput) : [];
16895
+ const hidden = (word) => secrets.some((s) => s === word || word.length >= 8 && s.includes(word) || s.length >= 8 && word.includes(s));
16896
+ const groups = [];
16897
+ let chars = 2;
16898
+ let complete = scan.complete;
16899
+ for (const group of scan.groups) {
16900
+ const words = [...new Set([...group].map((w) => hidden(w) ? REDACTED_TARGET_WORD : w))].sort();
16901
+ const cost = JSON.stringify(words).length + 1;
16902
+ if (chars + cost > MAX_TARGET_SCAN_CHARS) {
16903
+ complete = false;
16904
+ break;
16905
+ }
16906
+ chars += cost;
16907
+ groups.push(words);
16908
+ }
16909
+ return { groups, complete };
16910
+ }
16911
+ function cloudFacts(facts) {
16912
+ const scrub = (s) => s === null ? null : redactSecrets(s, { blunt: false }).text;
16913
+ return {
16914
+ toolName: facts.toolName,
16915
+ toolClass: facts.toolClass,
16916
+ toolIsKnown: facts.toolIsKnown,
16917
+ cwd: scrub(facts.cwd),
16918
+ projectRoot: scrub(facts.projectRoot),
16919
+ currentGitBranch: scrub(facts.currentGitBranch),
16920
+ paths: facts.paths.map((p) => ({ asWritten: scrub(p.asWritten) ?? "", resolved: scrub(p.resolved) ?? "", relation: p.relation })),
16921
+ permissionMode: facts.permissionMode
16922
+ };
16923
+ }
16924
+ function buildCloudBlock(prepared, input, machineId, agent) {
16925
+ const scan = scanTargets(input.toolInput);
16926
+ const block = {
16927
+ v: agent === undefined ? CLOUD_BLOCK_VERSION : 2,
16928
+ machineId,
16929
+ ...agent ? { agent } : {},
16930
+ intentMode: prepared.intent,
16931
+ facts: cloudFacts(prepared.facts),
16932
+ targetScan: cloudTargetScan(input.toolInput, scan),
16933
+ userSaid: prepared.userSaid.map((turn) => redactSecrets(turn, { blunt: true }).text.replace(REDACTION_MARKER, REDACTED_SAID)),
16934
+ agentLastMessage: prepared.agentLastMessage,
16935
+ userSaidCut: prepared.userSaidCut,
16936
+ localPolicies: prepared.selected.map((p) => p.name)
16937
+ };
16938
+ if (blockBytes(block) > MAX_CLOUD_BLOCK_BYTES) {
16939
+ block.userSaid = prepared.userSaid.length > 0 ? [""] : [];
16940
+ block.userSaidCut = false;
16941
+ block.targetScan = { ...block.targetScan, complete: false };
16942
+ }
16943
+ if (blockBytes(block) > MAX_CLOUD_BLOCK_BYTES) {
16944
+ block.targetScan = { groups: [], complete: false };
16945
+ }
16946
+ if (block.targetScan.complete && namingReadings(block.intentMode, scan.groups, prepared.userSaid, prepared.agentLastMessage) !== namingReadings(block.intentMode, block.targetScan.groups.map((g) => new Set(g)), block.userSaid, block.agentLastMessage)) {
16947
+ block.targetScan = { ...block.targetScan, complete: false };
16948
+ }
16949
+ return block;
16950
+ }
16951
+ function namingReadings(intent, groups, userSaid, agentLastMessage) {
16952
+ const scan = { targets: new Set, groups, complete: true };
16953
+ const said = intent === "v1" && agentLastMessage ? [...userSaid, agentLastMessage] : userSaid;
16954
+ return [groups.length, userSaid.length > 0, everyTargetNamed(scan, said), intent === "v1" && partlyNamed(scan, said)].join();
16955
+ }
16956
+ function buildCloudRequest(prepared, input, machineId, agent) {
16957
+ const own = prepared.compiled.request;
16958
+ return {
16959
+ model: own.model,
16960
+ state: own.state,
16961
+ questions: { ...own.questions, ...cloudGlobalQuestions(prepared.intent, prepared.userSaid.length) },
16962
+ cloud: buildCloudBlock(prepared, input, machineId, agent)
16963
+ };
16964
+ }
16965
+ function malformed(what) {
16966
+ throw new JevError("malformed", `FailproofAI Cloud's reply: ${what}`);
16967
+ }
16968
+ function nullableProbability(v, what) {
16969
+ if (v === null || v === undefined)
16970
+ return null;
16971
+ if (!isProbability(v))
16972
+ malformed(`${what} is not a probability`);
16973
+ return v;
16974
+ }
16975
+ function names(v, what) {
16976
+ if (v === undefined || v === null)
16977
+ return [];
16978
+ if (!Array.isArray(v) || v.length > MAX_LIST || !v.every(isName2))
16979
+ malformed(`${what} is not a list of names`);
16980
+ return [...v];
16981
+ }
16982
+ function parseOutcome(raw, i) {
16983
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
16984
+ malformed(`outcome ${i} is not an object`);
16985
+ const o = raw;
16986
+ if (!isName2(o.policy))
16987
+ malformed(`outcome ${i} has no policy name`);
16988
+ if (o.mode !== "deny" && o.mode !== "instruct")
16989
+ malformed(`outcome ${i} has no mode`);
16990
+ if (!isProbability(o.evidence))
16991
+ malformed(`outcome ${i} has no evidence`);
16992
+ if (typeof o.targetNamedByUser !== "boolean" || typeof o.escalatedByInjection !== "boolean") {
16993
+ malformed(`outcome ${i} is missing a flag`);
16994
+ }
16995
+ if (typeof o.verdict !== "string" || !VERDICTS.has(o.verdict))
16996
+ malformed(`outcome ${i} has no verdict`);
16997
+ if (o.intent !== undefined && (typeof o.intent !== "string" || !INTENTS.has(o.intent)))
16998
+ malformed(`outcome ${i} has an unknown intent`);
16999
+ if (o.targetScanIncomplete !== undefined && o.targetScanIncomplete !== true)
17000
+ malformed(`outcome ${i} has a bad targetScanIncomplete`);
17001
+ if (o.userCanOverride !== undefined && typeof o.userCanOverride !== "boolean")
17002
+ malformed(`outcome ${i} has a bad userCanOverride`);
17003
+ const origin = o.origin;
17004
+ if (!origin || typeof origin !== "object" || typeof origin.cloudPolicyId !== "string" || !POLICY_ID_RE2.test(origin.cloudPolicyId) || !Number.isSafeInteger(origin.cloudVersion) || origin.cloudVersion < 0) {
17005
+ malformed(`outcome ${i} has no Cloud origin`);
17006
+ }
17007
+ return {
17008
+ policy: o.policy,
17009
+ mode: o.mode,
17010
+ ...typeof o.userCanOverride === "boolean" ? { userCanOverride: o.userCanOverride } : {},
17011
+ origin: { packId: `cloud:${origin.cloudPolicyId}`, packVersion: String(origin.cloudVersion) },
17012
+ evidence: o.evidence,
17013
+ exempt: nullableProbability(o.exempt, `outcome ${i} exempt`),
17014
+ userAsked: nullableProbability(o.userAsked, `outcome ${i} userAsked`),
17015
+ targetNamedByUser: o.targetNamedByUser,
17016
+ escalatedByInjection: o.escalatedByInjection,
17017
+ verdict: o.verdict,
17018
+ ...o.intent !== undefined ? { intent: o.intent } : {},
17019
+ ...o.targetScanIncomplete === true ? { targetScanIncomplete: true } : {}
17020
+ };
17021
+ }
17022
+ function parseCloudReply(raw) {
17023
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
17024
+ malformed("no cloud block");
17025
+ const block = raw;
17026
+ const v = block.verdict;
17027
+ if (!v || typeof v !== "object" || Array.isArray(v))
17028
+ malformed("no verdict");
17029
+ if (typeof v.decision !== "string" || !DECISIONS2.has(v.decision))
17030
+ malformed("verdict has no decision");
17031
+ if (v.reason !== null && v.reason !== undefined && typeof v.reason !== "string")
17032
+ malformed("verdict reason is not text");
17033
+ if (!Array.isArray(v.outcomes) || v.outcomes.length > MAX_LIST)
17034
+ malformed("verdict has no outcomes list");
17035
+ if (v.beyondTask !== undefined && typeof v.beyondTask !== "boolean")
17036
+ malformed("verdict beyondTask is not a flag");
17037
+ const outcomes = v.outcomes.map(parseOutcome);
17038
+ const asked = names(block.asked, "asked");
17039
+ const askedSet = new Set(asked);
17040
+ const seen = new Set;
17041
+ outcomes.forEach((o, i) => {
17042
+ if (!askedSet.has(o.policy))
17043
+ malformed(`outcome ${i} answers ${JSON.stringify(o.policy)}, which Cloud did not ask`);
17044
+ const key = `${o.origin?.packId ?? ""}\x00${o.policy}`;
17045
+ if (seen.has(key))
17046
+ malformed(`outcome ${i} answers ${JSON.stringify(o.policy)} twice`);
17047
+ seen.add(key);
17048
+ });
17049
+ if (outcomes.some((o) => o.verdict === "deny") && v.decision !== "deny")
17050
+ malformed("a check denied but the verdict does not");
17051
+ return {
17052
+ verdict: {
17053
+ decision: v.decision,
17054
+ reason: typeof v.reason === "string" ? v.reason.length > MAX_CLOUD_REASON_CHARS ? `${v.reason.slice(0, MAX_CLOUD_REASON_CHARS - 1)}…` : v.reason : null,
17055
+ outcomes,
17056
+ injectionSuspected: nullableProbability(v.injectionSuspected, "injectionSuspected"),
17057
+ scopeWithinRequest: nullableProbability(v.scopeWithinRequest, "scopeWithinRequest"),
17058
+ beyondTask: v.beyondTask === true
17059
+ },
17060
+ asked,
17061
+ droppedLocal: names(block.droppedLocal, "droppedLocal"),
17062
+ droppedCloud: names(block.droppedCloud, "droppedCloud")
17063
+ };
17064
+ }
17065
+ function joinLines(reasons) {
17066
+ const lines = [];
17067
+ for (const reason of reasons) {
17068
+ if (!reason)
17069
+ continue;
17070
+ for (const line of reason.split(`
17071
+ `))
17072
+ if (!lines.includes(line))
17073
+ lines.push(line);
17074
+ }
17075
+ return lines.length > 0 ? lines.join(`
17076
+ `) : null;
17077
+ }
17078
+ function mergeCloudVerdict(cloud, local) {
17079
+ const decision = RANK2[cloud.decision] >= RANK2[local.decision] ? cloud.decision : local.decision;
17080
+ let reason;
17081
+ if (decision === "deny") {
17082
+ reason = cloud.decision === "deny" ? cloud.reason ?? local.reason : local.reason;
17083
+ } else if (decision === "instruct") {
17084
+ reason = joinLines([cloud, local].filter((v) => v.decision === "instruct").map((v) => v.reason));
17085
+ } else {
17086
+ reason = joinLines([cloud.reason, local.reason]);
17087
+ }
17088
+ const beyond = cloud.beyondTask === undefined && local.beyondTask === undefined ? undefined : cloud.beyondTask === true || local.beyondTask === true;
17089
+ return {
17090
+ decision,
17091
+ reason,
17092
+ outcomes: [...cloud.outcomes, ...local.outcomes],
17093
+ injectionSuspected: local.injectionSuspected ?? cloud.injectionSuspected,
17094
+ scopeWithinRequest: local.scopeWithinRequest ?? cloud.scopeWithinRequest,
17095
+ ...beyond !== undefined ? { beyondTask: beyond } : {}
17096
+ };
17097
+ }
17098
+ function envNumber2(name, fallback) {
17099
+ const n = Number(process.env[name]);
17100
+ return Number.isFinite(n) && n > 0 ? n : fallback;
17101
+ }
17102
+ function expectedQuestions(request, prepared, dropped) {
17103
+ if (dropped.size === 0)
17104
+ return request;
17105
+ const questions = Object.fromEntries(Object.entries(request.questions).filter(([id]) => {
17106
+ const owner = prepared.compiled.owners.get(id);
17107
+ return !(typeof owner === "string" && dropped.has(owner));
17108
+ }));
17109
+ return { ...request, questions };
17110
+ }
17111
+ function presentAnswers(response) {
17112
+ const out = {};
17113
+ const answers = response.answers && typeof response.answers === "object" ? response.answers : {};
17114
+ for (const [id, a] of Object.entries(answers)) {
17115
+ const p = a?.noul;
17116
+ if (isProbability(p))
17117
+ out[id] = p;
17118
+ }
17119
+ return out;
17120
+ }
17121
+ async function evaluateCloudSemantic(input, opts) {
17122
+ const started = performance.now();
17123
+ const elapsed = () => Math.round(performance.now() - started);
17124
+ const tool = classifyTool(input.toolName);
17125
+ if (tool.toolIsKnown && tool.toolClass === "other") {
17126
+ return {
17127
+ status: "ok",
17128
+ verdict: { ...EMPTY_ALLOW, outcomes: [] },
17129
+ answers: {},
17130
+ latencyMs: elapsed(),
17131
+ inputTokens: null,
17132
+ questionCount: 0,
17133
+ truncated: false,
17134
+ requestCut: false,
17135
+ redactions: 0,
17136
+ model: opts.model ?? DEFAULT_JEV_MODEL,
17137
+ modelVerified: true,
17138
+ via: "none",
17139
+ cloud: { asked: [], droppedLocal: [], droppedCloud: [] }
17140
+ };
17141
+ }
17142
+ let prepared;
17143
+ let request;
17144
+ try {
17145
+ prepared = prepareSemantic(input, opts);
17146
+ request = buildCloudRequest(prepared, input, opts.machineId, opts.agent);
17147
+ } catch (err) {
17148
+ return {
17149
+ status: "degraded",
17150
+ reason: `prepare: ${err instanceof Error ? err.message : String(err)}`,
17151
+ latencyMs: elapsed(),
17152
+ questionCount: 0,
17153
+ truncated: false,
17154
+ requestCut: false
17155
+ };
17156
+ }
17157
+ const questionCount = Object.keys(request.questions).length;
17158
+ const { cloud: _block, ...forwarded } = request;
17159
+ const oversized = prepared.oversized || JSON.stringify(forwarded).length > MAX_REQUEST_CHARS;
17160
+ const truncated = prepared.truncated || oversized;
17161
+ const requestCut = prepared.requestCut || oversized;
17162
+ const degraded = (reason) => ({
17163
+ status: "degraded",
17164
+ reason,
17165
+ latencyMs: elapsed(),
17166
+ questionCount,
17167
+ truncated,
17168
+ requestCut
17169
+ });
17170
+ const transport = opts.transport;
17171
+ if (!transport)
17172
+ return degraded("no-transport");
17173
+ const via = opts.via ?? "failproofai";
17174
+ if (opts.signal?.aborted)
17175
+ return degraded("aborted");
17176
+ try {
17177
+ const timeout = AbortSignal.timeout(opts.timeoutMs ?? envNumber2("FAILPROOFAI_JEV_TIMEOUT_MS", DEFAULT_JEV_TIMEOUT_MS));
17178
+ const signal = opts.signal ? AbortSignal.any([timeout, opts.signal]) : timeout;
17179
+ const response = await transport(request, signal);
17180
+ const reply = parseCloudReply(response.cloud);
17181
+ const own = new Map(prepared.selected.map((p) => [p.name, p]));
17182
+ const dropped = new Set(reply.droppedLocal.filter((name) => own.has(name)));
17183
+ const kept = prepared.selected.filter((p) => !dropped.has(p.name));
17184
+ const shortCircuit = kept.length === 0 && reply.asked.length === 0 && reply.verdict.outcomes.length === 0;
17185
+ const answers = shortCircuit ? presentAnswers(response) : readAnswers(expectedQuestions(request, prepared, dropped), response);
17186
+ const local = prepared.intent === "v1" ? decideV1(kept, answers, input.toolInput, prepared.userSaid, prepared.agentLastMessage, {
17187
+ ...opts.v1,
17188
+ userSaidCut: prepared.userSaidCut
17189
+ }) : decide(kept, answers, input.toolInput, prepared.userSaid, opts.thresholds ?? DEFAULT_THRESHOLDS, prepared.userSaidCut);
17190
+ return {
17191
+ status: "ok",
17192
+ verdict: mergeCloudVerdict(reply.verdict, local),
17193
+ answers,
17194
+ latencyMs: elapsed(),
17195
+ inputTokens: typeof response.usage?.input_tokens === "number" ? response.usage.input_tokens : null,
17196
+ questionCount,
17197
+ truncated,
17198
+ requestCut,
17199
+ redactions: prepared.envelope.redactions,
17200
+ model: response.model || request.model,
17201
+ modelVerified: response.modelUnverified !== true,
17202
+ via,
17203
+ cloud: {
17204
+ asked: reply.asked,
17205
+ droppedLocal: [...dropped].map((name) => ({ name, packId: own.get(name)?.origin?.packId ?? null })),
17206
+ droppedCloud: reply.droppedCloud
17207
+ }
17208
+ };
17209
+ } catch (err) {
17210
+ if (opts.signal?.aborted)
17211
+ return degraded("aborted");
17212
+ if (err instanceof JevError)
17213
+ return degraded(err.code);
17214
+ if (err instanceof Error && (err.name === "TimeoutError" || err.name === "AbortError"))
17215
+ return degraded("timeout");
17216
+ return degraded(`error: ${err instanceof Error ? err.message : String(err)}`);
17217
+ }
17218
+ }
17219
+ var CLOUD_BLOCK_VERSION = 1, MAX_TARGET_SCAN_CHARS = 64000, MAX_CLOUD_BLOCK_BYTES = 240000, blockBytes = (block) => Buffer.byteLength(JSON.stringify(block), "utf8"), REDACTED_TARGET_WORD = "\x00redacted", MAX_SECRET_SCAN_CHARS, REDACTION_MARKER, REDACTED_SAID = "\x00", POLICY_ID_RE2, MAX_NAME_CHARS = 256, MAX_LIST = 4096, MAX_CLOUD_REASON_CHARS = 8192, isProbability = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 && v <= 1, isName2 = (v) => typeof v === "string" && v.length > 0 && v.length <= MAX_NAME_CHARS, DECISIONS2, VERDICTS, INTENTS, RANK2, EMPTY_ALLOW;
17220
+ var init_cloud_jev = __esm(() => {
17221
+ init_compile();
17222
+ init_decide();
17223
+ init_envelope();
17224
+ init_facts();
17225
+ init_evaluator();
17226
+ init_jev_client();
17227
+ init_policies();
17228
+ init_redact();
17229
+ MAX_SECRET_SCAN_CHARS = 4 * MAX_TARGET_SCAN_CHARS;
17230
+ REDACTION_MARKER = /<redacted:[^>]*>/g;
17231
+ POLICY_ID_RE2 = /^[A-Za-z0-9._-]{1,128}$/;
17232
+ DECISIONS2 = new Set(["allow", "deny", "instruct"]);
17233
+ VERDICTS = new Set(["deny", "instruct", "overridden", "none"]);
17234
+ INTENTS = new Set(["op-requested", "task-step", "downgraded-task-step"]);
17235
+ RANK2 = { allow: 0, instruct: 1, deny: 2 };
17236
+ EMPTY_ALLOW = {
17237
+ decision: "allow",
17238
+ reason: null,
17239
+ outcomes: [],
17240
+ injectionSuspected: null,
17241
+ scopeWithinRequest: null,
17242
+ beyondTask: false
17243
+ };
17244
+ });
17245
+
16078
17246
  // src/hooks/semantic/jev-throttle.ts
16079
17247
  var exports_jev_throttle = {};
16080
17248
  __export(exports_jev_throttle, {
@@ -16285,10 +17453,10 @@ var init_jev_throttle = __esm(() => {
16285
17453
  });
16286
17454
 
16287
17455
  // src/hooks/semantic/session-root.ts
16288
- import { mkdirSync as mkdirSync11, readdirSync as readdirSync14, readFileSync as readFileSync18, statSync as statSync20, unlinkSync as unlinkSync3, writeFileSync as writeFileSync8 } from "node:fs";
16289
- import { isAbsolute as isAbsolute4, resolve as resolve17 } from "node:path";
17456
+ import { mkdirSync as mkdirSync11, readdirSync as readdirSync14, readFileSync as readFileSync20, statSync as statSync22, unlinkSync as unlinkSync3, writeFileSync as writeFileSync9 } from "node:fs";
17457
+ import { isAbsolute as isAbsolute4, resolve as resolve19 } from "node:path";
16290
17458
  function validRoot(v) {
16291
- return typeof v === "string" && isAbsolute4(v) && resolve17(v) === v && v !== "/";
17459
+ return typeof v === "string" && isAbsolute4(v) && resolve19(v) === v && v !== "/";
16292
17460
  }
16293
17461
  function storeIsOurs() {
16294
17462
  if (process.platform === "win32")
@@ -16296,7 +17464,7 @@ function storeIsOurs() {
16296
17464
  if (looseIntentStoreDir() !== null)
16297
17465
  return false;
16298
17466
  try {
16299
- const mode = statSync20(rootsDir()).mode & 511;
17467
+ const mode = statSync22(rootsDir()).mode & 511;
16300
17468
  return (mode & DIR_WRITABLE_BY_OTHERS4) === 0;
16301
17469
  } catch {
16302
17470
  return true;
@@ -16304,7 +17472,7 @@ function storeIsOurs() {
16304
17472
  }
16305
17473
  function readPinned(sessionId) {
16306
17474
  try {
16307
- const parsed = JSON.parse(readFileSync18(rootFile(sessionId), "utf8"));
17475
+ const parsed = JSON.parse(readFileSync20(rootFile(sessionId), "utf8"));
16308
17476
  return validRoot(parsed?.root) ? parsed.root : null;
16309
17477
  } catch {
16310
17478
  return null;
@@ -16317,9 +17485,9 @@ function pruneSessionRoots(now = Date.now()) {
16317
17485
  for (const name of readdirSync14(dir)) {
16318
17486
  if (!ROOT_FILE_RE.test(name))
16319
17487
  continue;
16320
- const path = resolve17(dir, name);
17488
+ const path = resolve19(dir, name);
16321
17489
  try {
16322
- const st = statSync20(path);
17490
+ const st = statSync22(path);
16323
17491
  if (st.isFile() && now - st.mtimeMs > SESSION_ROOT_MAX_AGE_MS) {
16324
17492
  unlinkSync3(path);
16325
17493
  removed++;
@@ -16344,12 +17512,12 @@ function sessionProjectRoot(sessionId, cwd, now = Date.now()) {
16344
17512
  if (!validRoot(live))
16345
17513
  return live;
16346
17514
  mkdirSync11(rootsDir(), { recursive: true, mode: 448 });
16347
- writeFileSync8(rootFile(sessionId), JSON.stringify({ root: live, at: now }), { mode: 384, flag: "wx" });
17515
+ writeFileSync9(rootFile(sessionId), JSON.stringify({ root: live, at: now }), { mode: 384, flag: "wx" });
16348
17516
  pruneSessionRoots(now);
16349
17517
  } catch {}
16350
17518
  return live;
16351
17519
  }
16352
- var SESSION_ID_RE3, ROOT_FILE_RE, SESSION_ROOT_MAX_AGE_MS, DIR_WRITABLE_BY_OTHERS4 = 18, rootsDir = () => resolve17(semanticDir(), "roots"), rootFile = (sessionId) => resolve17(rootsDir(), `${sessionId}.json`);
17520
+ var SESSION_ID_RE3, ROOT_FILE_RE, SESSION_ROOT_MAX_AGE_MS, DIR_WRITABLE_BY_OTHERS4 = 18, rootsDir = () => resolve19(semanticDir(), "roots"), rootFile = (sessionId) => resolve19(rootsDir(), `${sessionId}.json`);
16353
17521
  var init_session_root = __esm(() => {
16354
17522
  init_fp_home();
16355
17523
  init_facts();
@@ -16387,6 +17555,13 @@ function resolveTimeout(cfg) {
16387
17555
  return DEFAULT_JEV_TIMEOUT_MS;
16388
17556
  return Math.min(MAX_JEV_TIMEOUT_MS2, Math.max(MIN_JEV_TIMEOUT_MS2, t));
16389
17557
  }
17558
+ function reviewerKey(o) {
17559
+ const packId = o.origin?.packId;
17560
+ return packId !== undefined && packId.startsWith("cloud:") ? cloudReviewerName(packId.slice("cloud:".length), o.policy) : o.policy;
17561
+ }
17562
+ function isCloudOutcome(o) {
17563
+ return o.origin?.packId?.startsWith("cloud:") === true;
17564
+ }
16390
17565
  function jevDecider(outcome) {
16391
17566
  const wanted = outcome.verdict.decision === "deny" ? "deny" : "instruct";
16392
17567
  return outcome.verdict.outcomes.find((o) => o.verdict === wanted);
@@ -16409,6 +17584,10 @@ function toReview(outcome, cached = false) {
16409
17584
  const latencyMs = sent && !cached ? outcome.latencyMs : null;
16410
17585
  const model = sent ? outcome.model : null;
16411
17586
  const outcomes = outcome.verdict.outcomes;
17587
+ const cloudAsked = "cloud" in outcome ? new Set(outcome.cloud.asked) : null;
17588
+ const unvouched = outcomes.some((o) => isCloudOutcome(o) && !(cloudAsked?.has(o.policy) ?? false));
17589
+ if (unvouched)
17590
+ return { kind: "fallback", reason: "malformed", latencyMs, model: null };
16412
17591
  const injection = sent ? outcome.verdict.injectionSuspected : null;
16413
17592
  const warned = (o) => o.verdict === "instruct" && o.intent !== "downgraded-task-step";
16414
17593
  return {
@@ -16417,8 +17596,8 @@ function toReview(outcome, cached = false) {
16417
17596
  reason: outcome.verdict.reason,
16418
17597
  policyName: jevPolicyName(outcome),
16419
17598
  ...jevDecider(outcome)?.origin ? { origin: jevDecider(outcome)?.origin } : {},
16420
- asked: sent ? outcomes.map((o) => o.policy) : [],
16421
- notDenied: sent ? outcomes.filter((o) => o.verdict !== "deny" && !warned(o)).map((o) => o.policy) : [],
17599
+ asked: sent ? outcomes.map(reviewerKey) : [],
17600
+ notDenied: sent ? outcomes.filter((o) => o.verdict !== "deny" && !warned(o)).map(reviewerKey) : [],
16422
17601
  injectionAsked: injection !== null,
16423
17602
  injected: injection !== null && injection >= DEFAULT_THRESHOLDS_V1.injection,
16424
17603
  unclearableWarned: outcomes.some((o) => o.mode === "deny" && warned(o)),
@@ -16450,11 +17629,22 @@ function startJevReview(cfg, call) {
16450
17629
  let throttled;
16451
17630
  try {
16452
17631
  route = transportForConfig(cfg);
16453
- throttled = throttle.throttleTransport(route.transport, { scope: throttleScope(cfg, route) });
17632
+ const scope = call.cloud ? `${throttleScope(cfg, route)}\x00cloud\x00${call.cloud.machineId}\x00${call.cloud.deployment ?? "-"}` : throttleScope(cfg, route);
17633
+ throttled = throttle.throttleTransport(route.transport, { scope });
16454
17634
  } catch (err) {
16455
17635
  const reason = err instanceof JevError ? err.code : "config";
16456
17636
  return handle(Promise.resolve({ kind: "fallback", reason, latencyMs: null, model: null }));
16457
17637
  }
17638
+ const cloud = call.cloud;
17639
+ const healthScope = cloud ? JSON.stringify([cfg.baseUrl ?? null, cloud.machineId]) : "";
17640
+ let probe = false;
17641
+ if (cloud) {
17642
+ const gate = cloudJevGate(healthScope);
17643
+ if (!gate.ask) {
17644
+ return handle(Promise.resolve({ kind: "fallback", reason: BREAKER_SKIP_REASON, latencyMs: null, model: null }));
17645
+ }
17646
+ probe = gate.probe;
17647
+ }
16458
17648
  let intent;
16459
17649
  try {
16460
17650
  intent = intentReader.readIntent(call.sessionId);
@@ -16473,6 +17663,7 @@ function startJevReview(cfg, call) {
16473
17663
  agentLastMessage: intent.agentLastMessage
16474
17664
  };
16475
17665
  let cached = false;
17666
+ let reachedCloud = false;
16476
17667
  const transport = async (request, signal) => {
16477
17668
  const response = await throttled(request, signal);
16478
17669
  cached = servedFromCache2(response);
@@ -16480,7 +17671,7 @@ function startJevReview(cfg, call) {
16480
17671
  };
16481
17672
  const timeoutMs = resolveTimeout(cfg);
16482
17673
  let abandoned = false;
16483
- const answered = evaluateSemantic(input, {
17674
+ const options = {
16484
17675
  transport,
16485
17676
  cli: call.cli,
16486
17677
  via: route.via,
@@ -16489,9 +17680,25 @@ function startJevReview(cfg, call) {
16489
17680
  intent: "v1",
16490
17681
  v1: { thresholds: DEFAULT_THRESHOLDS_V1 },
16491
17682
  signal: controller.signal
16492
- }).then((outcome) => {
17683
+ };
17684
+ const evaluated = cloud ? evaluateCloudSemantic(input, {
17685
+ ...options,
17686
+ machineId: cloud.machineId,
17687
+ agent: cloud.agent,
17688
+ ...call.localPaused ? { policies: [] } : {}
17689
+ }) : evaluateSemantic(input, options);
17690
+ const answered = evaluated.then((outcome) => {
16493
17691
  const hit = cached && outcome.status === "ok";
17692
+ reachedCloud = outcome.status === "ok" && !hit && outcome.via !== "none";
16494
17693
  const review = toReview(outcome, hit);
17694
+ if (cloud && !abandoned && outcome.status === "ok" && "cloud" in outcome && outcome.cloud.droppedLocal.length > 0) {
17695
+ const cloudNames = new Set([...outcome.cloud.asked, ...outcome.cloud.droppedCloud]);
17696
+ recordJevBudgetDrops({ machineId: cloud.machineId, deployment: cloud.deployment, jevMode: cloud.mode }, outcome.cloud.droppedLocal.map((d) => ({
17697
+ packId: d.packId ?? "unknown",
17698
+ name: d.name,
17699
+ ...cloudNames.has(d.name) ? { clash: true } : {}
17700
+ })));
17701
+ }
16495
17702
  if (!(outcome.status === "degraded" && outcome.reason === "aborted")) {
16496
17703
  const row = verdictLogRow(input, hit ? { ...outcome, inputTokens: null } : outcome, {
16497
17704
  sessionId: call.sessionId,
@@ -16499,7 +17706,8 @@ function startJevReview(cfg, call) {
16499
17706
  eventType: call.eventType,
16500
17707
  applied: abandoned || review.kind !== "answered" ? "legacy-fallback" : mode === "observe" ? "observe" : "two-tier"
16501
17708
  });
16502
- appendVerdictLog(hit ? { ...row, cached: true } : row);
17709
+ const withCloud = outcome.status === "ok" && "cloud" in outcome ? { ...row, cloud: outcome.cloud } : row;
17710
+ appendVerdictLog(hit ? { ...withCloud, cached: true } : withCloud);
16503
17711
  }
16504
17712
  return review;
16505
17713
  }).catch(() => ({ kind: "fallback", reason: "error", latencyMs: null, model: null }));
@@ -16511,16 +17719,27 @@ function startJevReview(cfg, call) {
16511
17719
  resolve({ kind: "fallback", reason: "timeout", latencyMs: timeoutMs + JEV_DEADLINE_GRACE_MS, model: null });
16512
17720
  }, timeoutMs + JEV_DEADLINE_GRACE_MS);
16513
17721
  });
16514
- return handle(Promise.race([answered, expired]).finally(() => {
17722
+ const raced = Promise.race([answered, expired]).finally(() => {
16515
17723
  if (deadline !== undefined)
16516
17724
  clearTimeout(deadline);
17725
+ });
17726
+ if (!cloud)
17727
+ return handle(raced);
17728
+ return handle(raced.then((review) => {
17729
+ recordCloudJevResult(healthScope, classifyCloudJevReview(review, { reachedCloud }), review.kind === "fallback" ? review.reason : null, probe);
17730
+ reportCloudJevHealth();
17731
+ return review;
16517
17732
  }));
16518
17733
  }
16519
17734
  var throttle, intentReader, ALWAYS_ON, MIN_JEV_TIMEOUT_MS2 = 100, MAX_JEV_TIMEOUT_MS2 = 1e4, JEV_DEADLINE_GRACE_MS = 250;
16520
17735
  var init_jev_review = __esm(() => {
16521
17736
  init_builtin_policies();
17737
+ init_cloud_managed_policies();
17738
+ init_cloud_policy_errors();
16522
17739
  init_policy_registry();
16523
17740
  init_decide();
17741
+ init_cloud_jev();
17742
+ init_cloud_jev_health();
16524
17743
  init_evaluator();
16525
17744
  init_intent();
16526
17745
  init_jev_client();
@@ -16669,7 +17888,7 @@ var init_enforcement_capability = __esm(() => {
16669
17888
  });
16670
17889
 
16671
17890
  // src/hooks/handler.ts
16672
- import { existsSync as existsSync21 } from "node:fs";
17891
+ import { existsSync as existsSync22 } from "node:fs";
16673
17892
  function canonicalizeEventType(raw, cli) {
16674
17893
  if (cli === "codex") {
16675
17894
  const mapped = CODEX_EVENT_MAP[raw];
@@ -16727,9 +17946,23 @@ function isHumanAuthoredGate(rawEventType, cli) {
16727
17946
  function jevForcedOff(opts) {
16728
17947
  return process.env.FAILPROOFAI_EVALUATOR === "legacy" || !!opts?.forceDecision;
16729
17948
  }
16730
- async function readJevConfig() {
17949
+ async function readJevConfig(agent) {
16731
17950
  try {
16732
- if (!existsSync21(jevConfigFile()))
17951
+ const cloud = readCloudJevState();
17952
+ if (cloud.jevMode === "off")
17953
+ return null;
17954
+ if (cloudJevAsks(cloud.jevMode)) {
17955
+ await Promise.resolve().then(() => init_jev_config());
17956
+ const resolved = loadJevConfigForCloudMode(cloud.jevMode);
17957
+ if (!resolved.config || !resolved.machineId)
17958
+ return null;
17959
+ return {
17960
+ config: resolved.config,
17961
+ defaultMode: DEFAULT_JEV_MODE,
17962
+ cloud: { machineId: resolved.machineId, deployment: cloud.deployment, mode: cloud.jevMode, agent: agent ?? null }
17963
+ };
17964
+ }
17965
+ if (!existsSync22(jevConfigFile()))
16733
17966
  return null;
16734
17967
  await Promise.resolve().then(() => init_jev_config());
16735
17968
  const config = loadJevConfig();
@@ -16739,20 +17972,72 @@ async function readJevConfig() {
16739
17972
  return null;
16740
17973
  }
16741
17974
  }
16742
- async function startTwoTier(canonicalEventType, parsed, session, cli, opts, activePause) {
17975
+ function jevAttribution(origin) {
17976
+ if (!origin)
17977
+ return {};
17978
+ if (origin.packId.startsWith("cloud:")) {
17979
+ const version = Number(origin.packVersion);
17980
+ return {
17981
+ cloudPolicyId: origin.packId.slice("cloud:".length),
17982
+ ...Number.isSafeInteger(version) ? { cloudVersion: version } : {}
17983
+ };
17984
+ }
17985
+ return origin;
17986
+ }
17987
+ async function recordCloudPolicyErrors(input) {
17988
+ try {
17989
+ const jev = readCloudJevState();
17990
+ const managed = input.manifestError !== null || input.jsPolicies.length > 0 || jev.jevMode !== null || jev.errors.length > 0 || input.agentScopeUnresolved === true;
17991
+ if (!managed && !existsSync22(cloudPolicyErrorsPath()))
17992
+ return;
17993
+ let jevProblem = null;
17994
+ let budgetDrops = [];
17995
+ let health = [];
17996
+ if (cloudJevAsks(jev.jevMode)) {
17997
+ await Promise.resolve().then(() => init_jev_config());
17998
+ const resolved = loadJevConfigForCloudMode(jev.jevMode);
17999
+ jevProblem = resolved.problem;
18000
+ if (resolved.machineId) {
18001
+ budgetDrops = existsSync22(jevBudgetPath()) ? readJevBudgetDrops({ machineId: resolved.machineId, deployment: jev.deployment, jevMode: jev.jevMode }, installedPackIds()) : [];
18002
+ }
18003
+ await Promise.resolve().then(() => init_cloud_jev_health());
18004
+ health = cloudJevHealthErrors();
18005
+ }
18006
+ writeCloudPolicyErrors(collectCloudPolicyErrors({
18007
+ manifestError: input.manifestError,
18008
+ jsPolicies: input.jsPolicies,
18009
+ jsFailures: input.jsFailures,
18010
+ jev,
18011
+ jevProblem,
18012
+ budgetDrops,
18013
+ health,
18014
+ agentScopeUnresolved: input.agentScopeUnresolved
18015
+ }));
18016
+ if (input.jsPolicies.length > 0)
18017
+ recordCloudLoadChecked(input.jsPolicies[0].deployment, input.jsPolicies);
18018
+ } catch (err) {
18019
+ hookLogInfo(`could not record Cloud policy errors: ${err instanceof Error ? err.message : String(err)}`);
18020
+ }
18021
+ }
18022
+ async function startTwoTier(canonicalEventType, parsed, session, cli, opts, activePause, agent) {
16743
18023
  if (!JEV_GATE_EVENTS.has(canonicalEventType))
16744
18024
  return null;
16745
18025
  if (isHumanAuthoredGate(session.rawHookEventName, cli))
16746
18026
  return null;
16747
18027
  if (typeof parsed.tool_name !== "string" || parsed.tool_name.length === 0)
16748
18028
  return null;
16749
- if (jevForcedOff(opts) || activePause)
18029
+ if (jevForcedOff(opts))
18030
+ return null;
18031
+ const cloudAsks = cloudJevAsks(readCloudJevMode());
18032
+ if (activePause && !cloudAsks)
16750
18033
  return null;
16751
- if (!jevChecksInstalled())
18034
+ if (!cloudAsks && !jevChecksInstalled())
16752
18035
  return null;
16753
- const loaded = await readJevConfig();
18036
+ const loaded = await readJevConfig(agent);
16754
18037
  if (!loaded)
16755
18038
  return null;
18039
+ if (activePause && !loaded.cloud)
18040
+ return null;
16756
18041
  const cfg = loaded.config;
16757
18042
  try {
16758
18043
  await Promise.resolve().then(() => init_jev_review());
@@ -16763,7 +18048,9 @@ async function startTwoTier(canonicalEventType, parsed, session, cli, opts, acti
16763
18048
  cwd: session.cwd,
16764
18049
  permissionMode: session.permissionMode,
16765
18050
  sessionId: session.sessionId,
16766
- cli
18051
+ cli,
18052
+ ...loaded.cloud ? { cloud: loaded.cloud } : {},
18053
+ ...activePause ? { localPaused: true } : {}
16767
18054
  });
16768
18055
  } catch (err) {
16769
18056
  hookLogInfo(`Jev review could not start (${err instanceof Error ? err.message : String(err)})`);
@@ -16792,7 +18079,7 @@ async function captureJevIntent(canonicalEventType, decision, parsed, session, c
16792
18079
  if (canonicalEventType !== "UserPromptSubmit" || jevForcedOff(opts))
16793
18080
  return;
16794
18081
  try {
16795
- if (!jevChecksInstalled())
18082
+ if (!cloudJevAsks(readCloudJevMode()) && !jevChecksInstalled())
16796
18083
  return;
16797
18084
  if (!await readJevConfig())
16798
18085
  return;
@@ -16834,6 +18121,9 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
16834
18121
  });
16835
18122
  }
16836
18123
  }
18124
+ if (isHealthProbe(eventType, parsed)) {
18125
+ return { exitCode: 0, stdout: "", stderr: "" };
18126
+ }
16837
18127
  normalizeCliPayload(cli, parsed);
16838
18128
  const canonicalEventType = canonicalizeEventType(eventType, cli);
16839
18129
  const rawToolName = parsed.tool_name;
@@ -16857,6 +18147,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
16857
18147
  rawHookEventName: eventType,
16858
18148
  cli
16859
18149
  };
18150
+ const runtimeAgent = readRuntimeAgentIdentity(cli, opts?.agentSettingsPath ?? runtimeAgentSettingsPath(cli, session.cwd));
16860
18151
  let config;
16861
18152
  let customHooksList = [];
16862
18153
  let conventionHookNames = new Set;
@@ -16873,7 +18164,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
16873
18164
  registerPolicy("failproofai/daemon-unreachable", "Fail-closed: the failproofaid daemon could not be reached for this daemon-configured scope.", async () => ({ decision: decision.decision, reason: decision.reason }), {});
16874
18165
  } else {
16875
18166
  config = readMergedHooksConfig(session.cwd);
16876
- clearPolicies(cli);
18167
+ clearPolicies(cli, runtimeAgent);
16877
18168
  activePause = readActivePause(session.sessionId);
16878
18169
  const packsInstalledHere = hasInstalledRegexPacks();
16879
18170
  const legacyNames = activePause || packsInstalledHere ? [] : config.enabledPolicies;
@@ -16883,17 +18174,19 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
16883
18174
  }
16884
18175
  const enabledBuiltinNames = new Set(legacyNames);
16885
18176
  let cloudManagedPolicies = [];
18177
+ let cloudManifestError = null;
16886
18178
  try {
16887
- cloudManagedPolicies = readActiveCloudManagedPolicies();
18179
+ cloudManagedPolicies = readActiveCloudManagedPolicies(runtimeAgent);
16888
18180
  } catch (err) {
16889
18181
  const msg = err instanceof Error ? err.message : String(err);
18182
+ cloudManifestError = msg;
16890
18183
  hookLogWarn(`[failproofai] cloud-managed policies could NOT be loaded and are not being enforced: ${msg}. Local policies are unaffected. Run \`failproofai config --status\` to check this machine's enrolment.`);
16891
18184
  trackHookEvent(getInstanceId(), "cloud_managed_load_error", {
16892
18185
  event_type: eventType,
16893
18186
  cli
16894
18187
  });
16895
18188
  }
16896
- cloudDeployment = cloudManagedPolicies[0]?.deployment;
18189
+ cloudDeployment = cloudManagedPolicies[0]?.deployment ?? readCloudJevState().deployment ?? undefined;
16897
18190
  let installedPacks = [];
16898
18191
  try {
16899
18192
  const packResult = readInstalledPacks();
@@ -16911,10 +18204,12 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
16911
18204
  ...cloudManagedPolicies.map((policy) => policy.path),
16912
18205
  ...installedPacks.map((pack) => pack.path)
16913
18206
  ];
18207
+ const cloudJevMode = readCloudJevMode();
18208
+ const cloudForLoading = cloudManagedPolicies.map((policy) => withCloudAuthority(policy, cloudJevMode));
16914
18209
  const loadResult = await loadAllCustomHooks(allExplicitPaths, {
16915
18210
  sessionCwd: session.cwd,
16916
18211
  customPoliciesEnabled: config.customPoliciesEnabled,
16917
- ...cloudManagedPolicies.length > 0 ? { cloudManagedPolicies } : {},
18212
+ ...cloudForLoading.length > 0 ? { cloudManagedPolicies: cloudForLoading } : {},
16918
18213
  ...installedPacks.length > 0 ? { packs: installedPacks } : {}
16919
18214
  });
16920
18215
  customHooksList = loadResult.hooks;
@@ -16994,6 +18289,12 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
16994
18289
  warnAuthority(refusedAuthorityWarning(registeredName, refused));
16995
18290
  registerPolicy(registeredName, hook.description ?? "", fn, hook.match ?? {}, -1, pack?.policies.find((p) => p.name === hook.name)?.params, authority);
16996
18291
  }
18292
+ await recordCloudPolicyErrors({
18293
+ manifestError: cloudManifestError,
18294
+ jsPolicies: cloudManagedPolicies,
18295
+ jsFailures: loadResult.cloudFailures,
18296
+ agentScopeUnresolved: runtimeAgent === null && readCloudAgentScopeRequired()
18297
+ });
16997
18298
  if (!activePause) {
16998
18299
  const guards = missingGuards({
16999
18300
  errors: packErrors,
@@ -17040,7 +18341,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
17040
18341
  }
17041
18342
  hookLogInfo(`event=${canonicalEventType} cli=${cli} policies=${config.enabledPolicies.length} custom=${customHooksList.length} convention=${conventionHookNames.size}`);
17042
18343
  }
17043
- const twoTier = await startTwoTier(canonicalEventType, parsed, session, cli, opts, activePause);
18344
+ const twoTier = await startTwoTier(canonicalEventType, parsed, session, cli, opts, activePause, runtimeAgent);
17044
18345
  const matchedBeforeRelease = twoTier ? getPoliciesForEvent(canonicalEventType, parsed.tool_name).map((p) => p.name) : null;
17045
18346
  const result = twoTier ? await evaluatePolicies(canonicalEventType, parsed, session, config, {
17046
18347
  ...twoTier,
@@ -17077,7 +18378,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
17077
18378
  cwd: session.cwd,
17078
18379
  permissionMode: session.permissionMode,
17079
18380
  hookEventName: session.hookEventName,
17080
- ...result.policyName && result.twoTier?.decidedByJev ? { policySource: "jev", ...jevOrigin } : {},
18381
+ ...result.policyName && result.twoTier?.decidedByJev ? { policySource: "jev", ...jevAttribution(jevOrigin) } : {},
17081
18382
  ...result.policyName && !result.twoTier?.decidedByJev ? (() => {
17082
18383
  const attribution = policyAttribution.get(result.policyName);
17083
18384
  return {
@@ -17088,6 +18389,7 @@ async function evaluateHookEvent(eventType, cli = "claude", stdinPayload, opts)
17088
18389
  ...attribution?.packVersion ? { packVersion: attribution.packVersion } : {}
17089
18390
  };
17090
18391
  })() : {},
18392
+ ...!result.policyName && observeVerdict ? { policyName: observeVerdict.policyName, ...jevAttribution(result.twoTier?.jevOrigin) } : {},
17091
18393
  ...cloudDeployment !== undefined ? { cloudDeployment } : {},
17092
18394
  ...observedResults.length > 0 ? { observed: observedResults } : {},
17093
18395
  ...activePause ? { pausedBy: activePause.setBy, pauseExpiresAt: activePause.expiresAt } : {}
@@ -17163,23 +18465,25 @@ var init_handler = __esm(() => {
17163
18465
  init_telemetry_id();
17164
18466
  init_hook_logger();
17165
18467
  init_cloud_managed_policies();
18468
+ init_cloud_policy_errors();
17166
18469
  init_pack_manifest();
17167
18470
  init_pack_failclosed();
17168
18471
  init_session_pause();
17169
18472
  init_fp_home();
17170
18473
  init_fp_reset();
17171
18474
  init_untraced_note();
18475
+ init_agent_roster();
17172
18476
  JEV_GATE_EVENTS = new Set(["PreToolUse", "PermissionRequest"]);
17173
18477
  });
17174
18478
 
17175
18479
  // src/hooks/worker-server.ts
17176
18480
  import { createConnection, createServer } from "node:net";
17177
- import { existsSync as existsSync22, unlinkSync as unlinkSync4 } from "node:fs";
18481
+ import { existsSync as existsSync23, unlinkSync as unlinkSync4 } from "node:fs";
17178
18482
  function isWorkerHookRequest(msg) {
17179
18483
  if (!msg || typeof msg !== "object")
17180
18484
  return false;
17181
18485
  const m = msg;
17182
- return m.type === "hook" && typeof m.hookEvent === "string" && typeof m.cli === "string" && typeof m.stdin === "string" && (m.cwd === undefined || m.cwd === null || typeof m.cwd === "string");
18486
+ return m.type === "hook" && typeof m.hookEvent === "string" && typeof m.cli === "string" && typeof m.stdin === "string" && (m.cwd === undefined || m.cwd === null || typeof m.cwd === "string") && (m.agentSettingsPath === undefined || m.agentSettingsPath === null || typeof m.agentSettingsPath === "string");
17183
18487
  }
17184
18488
  function encodeFrame(value) {
17185
18489
  const body = Buffer.from(JSON.stringify(value), "utf8");
@@ -17274,6 +18578,7 @@ function handleConnection(socket, shutdown) {
17274
18578
  const result = await evaluateHookEvent(request.hookEvent, request.cli, request.stdin, {
17275
18579
  awaitTelemetryFlush: false,
17276
18580
  fallbackCwd: request.cwd ?? undefined,
18581
+ agentSettingsPath: request.agentSettingsPath ?? undefined,
17277
18582
  releaseRegistry: release
17278
18583
  });
17279
18584
  deliver(encodeFrame({
@@ -17340,14 +18645,14 @@ function requestExistingWorkerShutdown(socketPath) {
17340
18645
  function startWorkerServer(socketPath, shutdown) {
17341
18646
  const server = createServer((socket) => handleConnection(socket, shutdown ?? (() => server.close())));
17342
18647
  const listen = () => {
17343
- if (existsSync22(socketPath)) {
18648
+ if (existsSync23(socketPath)) {
17344
18649
  try {
17345
18650
  unlinkSync4(socketPath);
17346
18651
  } catch {}
17347
18652
  }
17348
18653
  server.listen(socketPath);
17349
18654
  };
17350
- if (!existsSync22(socketPath))
18655
+ if (!existsSync23(socketPath))
17351
18656
  listen();
17352
18657
  else
17353
18658
  requestExistingWorkerShutdown(socketPath).then(listen, (err) => server.emit("error", err));
@@ -17363,13 +18668,13 @@ var init_worker_server = __esm(() => {
17363
18668
 
17364
18669
  // bin/failproofai-worker.mjs
17365
18670
  import { realpathSync as realpathSync2 } from "node:fs";
17366
- import { dirname as dirname10, resolve as resolve18 } from "node:path";
18671
+ import { dirname as dirname11, resolve as resolve20 } from "node:path";
17367
18672
  import { fileURLToPath } from "node:url";
17368
18673
  if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
17369
- process.env.FAILPROOFAI_PACKAGE_ROOT = resolve18(dirname10(realpathSync2(fileURLToPath(import.meta.url))), "..");
18674
+ process.env.FAILPROOFAI_PACKAGE_ROOT = resolve20(dirname11(realpathSync2(fileURLToPath(import.meta.url))), "..");
17370
18675
  }
17371
18676
  if (!process.env.FAILPROOFAI_DIST_PATH) {
17372
- process.env.FAILPROOFAI_DIST_PATH = resolve18(dirname10(realpathSync2(fileURLToPath(import.meta.url))), "..", "dist");
18677
+ process.env.FAILPROOFAI_DIST_PATH = resolve20(dirname11(realpathSync2(fileURLToPath(import.meta.url))), "..", "dist");
17373
18678
  }
17374
18679
  var socketPath = process.env.FAILPROOFAI_WORKER_SOCKET;
17375
18680
  if (!socketPath) {