failproofai 1.0.7 → 1.0.8-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  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/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js +4 -4
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page.js +4 -4
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  21. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
  22. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/audit/run/route.js +8 -7
  25. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  33. package/.next/standalone/.next/server/app/audit/page.js +9 -7
  34. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  36. package/.next/standalone/.next/server/app/index.html +1 -1
  37. package/.next/standalone/.next/server/app/index.rsc +15 -15
  38. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
  39. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  40. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  41. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  42. package/.next/standalone/.next/server/app/page.js +6 -6
  43. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  46. package/.next/standalone/.next/server/app/policies/page.js +11 -10
  47. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/page.js +8 -7
  51. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  54. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  55. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +6 -6
  56. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  59. package/.next/standalone/.next/server/app/projects/page.js +7 -6
  60. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +52 -8
  63. package/.next/standalone/.next/server/app/settings/page.js +12 -7
  64. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/chunks/{[externals]__1msfs-h._.js → [externals]__19_pzeq._.js} +1 -1
  67. package/.next/standalone/.next/server/chunks/{[externals]__1_bftcl._.js → [externals]__20kzpkf._.js} +1 -1
  68. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  69. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ttrwnd._.js +22 -0
  70. package/.next/standalone/.next/server/chunks/_09dz7xv._.js +21 -21
  71. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  72. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +16 -16
  74. package/.next/standalone/.next/server/chunks/{_1c3k-8x._.js → _1q5i8mb._.js} +2 -2
  75. package/.next/standalone/.next/server/chunks/lib_16xa545._.js +3 -0
  76. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  77. package/.next/standalone/.next/server/chunks/src_hooks_1aveq0u._.js +5 -0
  78. package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3._.js +4 -2
  80. package/.next/standalone/.next/server/chunks/ssr/[externals]__0ohnuzs._.js +3 -0
  81. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01bmjsj._.js +3 -0
  82. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +4 -0
  83. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +4 -0
  84. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__059yza8._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06pflha._.js +3 -0
  86. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0eip4_k._.js +22 -0
  87. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +4 -0
  88. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qcb0mg._.js +3 -0
  89. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +4 -0
  90. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0yrsbd_._.js +3 -0
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +4 -0
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12e7nhs._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__13d-wb6._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0bd3mje._.js → [root-of-the-server]__14o3ek1._.js} +2 -2
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15578wp._.js +4 -0
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19evfi8._.js +3 -0
  97. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dinjii._.js +3 -0
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m_svbe._.js +4 -0
  99. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0cxe_2_._.js → [root-of-the-server]__1mf3zp6._.js} +3 -3
  100. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +4 -0
  101. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +4 -0
  102. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qiz0e4._.js +3 -0
  103. package/.next/standalone/.next/server/chunks/ssr/_042cgl1._.js +3 -0
  104. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +3 -0
  106. package/.next/standalone/.next/server/chunks/ssr/{_166t73i._.js → _0o4xkpl._.js} +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/_0uyu3jf._.js +3 -0
  108. package/.next/standalone/.next/server/chunks/ssr/{_1-i_gzc._.js → _1-7sqrb._.js} +2 -2
  109. package/.next/standalone/.next/server/chunks/ssr/{_1es2j7i._.js → _1gb0ifp._.js} +5 -5
  110. package/.next/standalone/.next/server/chunks/ssr/{_1_qswah._.js → _1q46vxx._.js} +2 -2
  111. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +1 -1
  112. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +13 -13
  113. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  115. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  116. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  117. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0aiy-os._.js +1 -1
  119. package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_0drixxt._.js → node_modules_next_dist_0w6mzq5._.js} +4 -4
  120. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_18_d8l1._.js +151 -0
  121. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0-q0umm._.js +3 -0
  122. package/.next/standalone/.next/server/chunks/ssr/src_hooks_06kzv9d._.js +12 -0
  123. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0g194sy._.js +3 -0
  124. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4._.js +4 -2
  125. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1kx9e0d._.js +3 -0
  126. package/.next/standalone/.next/server/chunks/ssr/src_hooks_effective-reviewers_ts_1h4wtvo._.js +5 -0
  127. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
  129. package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me65._.js +1 -1
  130. package/.next/standalone/.next/server/chunks/ssr/src_hooks_semantic_pack-policies_ts_0gh_bu_._.js +3 -0
  131. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  132. package/.next/standalone/.next/server/pages/404.html +1 -1
  133. package/.next/standalone/.next/server/pages/500.html +1 -1
  134. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  135. package/.next/standalone/.next/server/server-reference-manifest.json +67 -23
  136. package/.next/standalone/.next/static/chunks/078gnymqoh3r4.js +1 -0
  137. package/.next/standalone/.next/static/chunks/{2mdh397ghgnvv.js → 0ahfwmbkpgfw4.js} +1 -1
  138. package/.next/standalone/.next/static/chunks/0bhidk90e-07f.css +2 -0
  139. package/.next/standalone/.next/static/chunks/1bu2-nv59ed6i.js +1 -0
  140. package/.next/standalone/.next/static/chunks/{0o6qlkgubtoex.js → 1v_tp3hm8wyhe.js} +1 -1
  141. package/.next/standalone/.next/static/chunks/2a405_e1o26ol.js +1 -0
  142. package/.next/standalone/.next/static/chunks/2qv4hshejedtx.css +1 -0
  143. package/.next/standalone/.next/static/chunks/2vo7qbdbvnc0o.js +69 -0
  144. package/.next/standalone/.next/static/chunks/{13i7-9is-vhys.js → 2z7i-yg59w4pn.js} +1 -1
  145. package/.next/standalone/.next/static/chunks/36uhh9el_oz8e.js +1 -0
  146. package/.next/standalone/.next/static/chunks/{0__8a7m868fvf.js → 3bgot5v6f6s3c.js} +1 -1
  147. package/.next/standalone/.next/static/chunks/3o3f1ibfci0p7.js +6 -0
  148. package/.next/standalone/PROBE-FOLLOWUP.md +186 -0
  149. package/.next/standalone/app/actions/get-jev-config.ts +604 -0
  150. package/.next/standalone/app/actions/pack-actions.ts +12 -0
  151. package/.next/standalone/app/actions/update-jev-config.ts +569 -0
  152. package/.next/standalone/app/components/jev-notices.tsx +96 -0
  153. package/.next/standalone/app/policies/hooks-client.tsx +14 -3
  154. package/.next/standalone/app/settings/jev-panel.tsx +630 -0
  155. package/.next/standalone/app/settings/page.tsx +20 -1
  156. package/.next/standalone/app/settings/settings-client.tsx +27 -1
  157. package/.next/standalone/app/settings/settings.css +79 -0
  158. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +22 -4
  159. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +14 -1
  160. package/.next/standalone/fp-cloud-cli/fp_cli/commands/keys_cmds.py +17 -3
  161. package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +3 -0
  162. package/.next/standalone/fp-cloud-cli/fp_cli/permissions.py +22 -0
  163. package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +169 -0
  164. package/.next/standalone/fp-cloud-cli/skill/references/commands.md +1 -1
  165. package/.next/standalone/fp-cloud-cli/tests/test_keys_queries.py +65 -0
  166. package/.next/standalone/fp-cloud-cli/tests/test_policy_check.py +61 -0
  167. package/.next/standalone/package.json +10 -10
  168. package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
  169. package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
  170. package/.next/standalone/sdk/typescript/scripts/release.mjs +30 -0
  171. package/.next/standalone/server.js +1 -1
  172. package/README.md +3 -2
  173. package/bin/failproofai.mjs +148 -4
  174. package/dist/cli.mjs +18537 -9492
  175. package/dist/index.js +19 -1
  176. package/dist/worker.mjs +10421 -3770
  177. package/package.json +10 -10
  178. package/pi-extension/index.ts +11 -0
  179. package/scripts/build-policy-pack.mjs +53 -2
  180. package/src/audit/features.ts +3 -2
  181. package/src/hooks/builtin-policies.ts +195 -8
  182. package/src/hooks/cloud-connection.ts +190 -1
  183. package/src/hooks/cloud-enrollment-cli.ts +57 -8
  184. package/src/hooks/cloud-introspect.ts +6 -0
  185. package/src/hooks/cloud-managed-policies.ts +22 -0
  186. package/src/hooks/configure-wizard.ts +26 -6
  187. package/src/hooks/custom-hooks-loader.ts +98 -10
  188. package/src/hooks/custom-hooks-registry.ts +45 -1
  189. package/src/hooks/effective-reviewers.ts +243 -0
  190. package/src/hooks/first-run-gate.ts +5 -0
  191. package/src/hooks/flush-cli.ts +35 -8
  192. package/src/hooks/fp-config.ts +266 -1
  193. package/src/hooks/fp-home.ts +23 -0
  194. package/src/hooks/fp-reset.ts +22 -4
  195. package/src/hooks/handler.ts +303 -7
  196. package/src/hooks/hook-activity-store.ts +118 -6
  197. package/src/hooks/hook-telemetry.ts +41 -0
  198. package/src/hooks/jev-activity.ts +385 -0
  199. package/src/hooks/jev-cli.ts +2172 -0
  200. package/src/hooks/jev-cloud-connection.ts +392 -0
  201. package/src/hooks/loader-utils.ts +6 -0
  202. package/src/hooks/manager.ts +45 -7
  203. package/src/hooks/pack-cli.ts +568 -37
  204. package/src/hooks/pack-failclosed.ts +3 -0
  205. package/src/hooks/pack-manifest.ts +489 -7
  206. package/src/hooks/pack-store.ts +194 -11
  207. package/src/hooks/policy-authority.ts +386 -0
  208. package/src/hooks/policy-catalog.ts +206 -0
  209. package/src/hooks/policy-evaluator.ts +963 -796
  210. package/src/hooks/policy-registry.ts +27 -1
  211. package/src/hooks/policy-reviewability.ts +258 -0
  212. package/src/hooks/policy-types.ts +128 -0
  213. package/src/hooks/semantic/combine.ts +581 -0
  214. package/src/hooks/semantic/compile.ts +176 -0
  215. package/src/hooks/semantic/decide.ts +408 -0
  216. package/src/hooks/semantic/envelope.ts +1255 -0
  217. package/src/hooks/semantic/evaluator.ts +556 -0
  218. package/src/hooks/semantic/facts.ts +298 -0
  219. package/src/hooks/semantic/intent.ts +1190 -0
  220. package/src/hooks/semantic/jev-client.ts +1155 -0
  221. package/src/hooks/semantic/jev-config.ts +1142 -0
  222. package/src/hooks/semantic/jev-review.ts +389 -0
  223. package/src/hooks/semantic/jev-stats.ts +289 -0
  224. package/src/hooks/semantic/jev-throttle.ts +427 -0
  225. package/src/hooks/semantic/pack-policies.ts +294 -0
  226. package/src/hooks/semantic/policies.ts +597 -0
  227. package/src/hooks/semantic/precondition-names.ts +60 -0
  228. package/src/hooks/semantic/preconditions.ts +58 -0
  229. package/src/hooks/semantic/redact.ts +2937 -0
  230. package/src/hooks/semantic/session-root.ts +116 -0
  231. package/src/hooks/semantic/types.ts +156 -0
  232. package/src/hooks/semver-precedence.ts +128 -0
  233. package/src/hooks/tui.ts +4 -0
  234. package/src/hooks/types.ts +1 -1
  235. package/src/hooks/worker-server.ts +121 -27
  236. package/src/index.ts +6 -0
  237. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cuho4x._.js +0 -3
  238. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1_r2rbg._.js +0 -24
  239. package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +0 -3
  240. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-_ki57._.js +0 -4
  241. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +0 -4
  242. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +0 -4
  243. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +0 -4
  244. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cg-bgc._.js +0 -5
  245. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cpu_mj._.js +0 -3
  246. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +0 -4
  247. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +0 -4
  248. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +0 -4
  249. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u3w0ll._.js +0 -22
  250. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17d_ffl._.js +0 -3
  251. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__19d9tgz._.js +0 -5
  252. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +0 -3
  253. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1jiwfsj._.js +0 -3
  254. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +0 -4
  255. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1phc187._.js +0 -3
  256. package/.next/standalone/.next/server/chunks/ssr/_06imw3p._.js +0 -5
  257. package/.next/standalone/.next/server/chunks/ssr/_0h_douw._.js +0 -3
  258. package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +0 -3
  259. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +0 -3
  260. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +0 -3
  261. package/.next/standalone/.next/static/chunks/094xgi4owxaqf.js +0 -1
  262. package/.next/standalone/.next/static/chunks/1rz20_pz828f3.js +0 -6
  263. package/.next/standalone/.next/static/chunks/2k9f4tyv04809.css +0 -1
  264. package/.next/standalone/.next/static/chunks/2klitrtzpaoe0.js +0 -1
  265. package/.next/standalone/.next/static/chunks/2rshywgeqsyzk.css +0 -2
  266. package/.next/standalone/.next/static/chunks/3pzx4chkhko9k.js +0 -1
  267. package/.next/standalone/.next/static/chunks/3rh5o7e16irrm.js +0 -69
  268. package/.next/standalone/.next/static/chunks/43ufqrz8qo3h-.js +0 -1
  269. /package/.next/standalone/.next/static/{PgeWCHmyVbjRznv2VO7KF → O_b5R1axf5cb4NxIXq2kS}/_buildManifest.js +0 -0
  270. /package/.next/standalone/.next/static/{PgeWCHmyVbjRznv2VO7KF → O_b5R1axf5cb4NxIXq2kS}/_clientMiddlewareManifest.js +0 -0
  271. /package/.next/standalone/.next/static/{PgeWCHmyVbjRznv2VO7KF → O_b5R1axf5cb4NxIXq2kS}/_ssgManifest.js +0 -0
@@ -7,6 +7,8 @@
7
7
  */
8
8
  import type { HookEventType } from "./types";
9
9
  import type { PolicyFunction, PolicyMatcher, PolicyParamsSchema, RegisteredPolicy } from "./policy-types";
10
+ import { effectiveReviewerNames, forgetEffectiveReviewerNames } from "./effective-reviewers";
11
+ import { resolvePolicyAuthority, type AuthorityDeclaration } from "./policy-authority";
10
12
 
11
13
  const REGISTRY_KEY = "__FAILPROOFAI_POLICY_REGISTRY__";
12
14
  const INDEX_CACHE_KEY = "__FAILPROOFAI_POLICY_INDEX_CACHE__";
@@ -58,15 +60,34 @@ export function registerPolicy(
58
60
  match: PolicyMatcher,
59
61
  priority: number = 0,
60
62
  params?: PolicyParamsSchema,
63
+ /**
64
+ * The policy's authority declaration, as its source wrote it. Judged HERE,
65
+ * so the registry only ever holds an effective value: `reviewable` with a
66
+ * clean `reviewedBy`, or `hard`. See `resolvePolicyAuthority`.
67
+ *
68
+ * Absent means the caller declared nothing, and the entry then carries no
69
+ * authority field at all — which `effectiveAuthority` reads as hard.
70
+ */
71
+ meta?: AuthorityDeclaration,
61
72
  ): void {
62
73
  const canonical = normalizePolicyName(name);
63
74
  const registry = getRegistry();
64
75
  const idx = registry.findIndex((p) => p.name === canonical);
76
+ // Judged against the reviewers this MACHINE can ask, not against the ones this
77
+ // build compiled in. A pack that ships its own `semantic` set replaces the
78
+ // compiled one, so its policies name checks that exist here and nowhere in
79
+ // `SEMANTIC_POLICY_NAMES` — and judging them by the builtin list would
80
+ // downgrade the whole rewritten set to `hard` while reporting nothing but a
81
+ // warning. `effectiveReviewerNames` reads the manifest — already where a
82
+ // pack's `reviewedBy` itself comes from — once per registration pass.
83
+ const authority = meta ? resolvePolicyAuthority(meta, effectiveReviewerNames()) : undefined;
65
84
  const entry: RegisteredPolicy = {
66
85
  name: canonical, description, fn, match, priority,
67
86
  // Absent stays absent: `evaluatePolicies` distinguishes "declares a schema"
68
87
  // from "declares none", and a spread `params: undefined` is neither.
69
88
  ...(params ? { params } : {}),
89
+ ...(authority ? { authority: authority.authority } : {}),
90
+ ...(authority?.reviewedBy ? { reviewedBy: authority.reviewedBy } : {}),
70
91
  };
71
92
  if (idx >= 0) {
72
93
  registry[idx] = entry;
@@ -106,10 +127,15 @@ export function getPoliciesForEvent(
106
127
  return result;
107
128
  }
108
129
 
109
- export function clearPolicies(): void {
130
+ /** `cli`: the agent this pass registers for, which scopes the Jev reviewer set. */
131
+ export function clearPolicies(cli?: string): void {
110
132
  const g = globalThis as GlobalWithRegistry;
111
133
  g[REGISTRY_KEY] = [];
112
134
  setIndexCache(null);
135
+ // The reviewer set describes the policies that are about to be registered, so
136
+ // it is rebuilt with them. Dropping it here is also what keeps one read per
137
+ // evaluation instead of one per policy.
138
+ forgetEffectiveReviewerNames(cli);
113
139
  }
114
140
 
115
141
  /**
@@ -0,0 +1,258 @@
1
+ /**
2
+ * How much of what this machine enforces Jev is allowed to CLEAR — the
3
+ * diagnostic half of `policy-authority.ts`, and nothing else.
4
+ *
5
+ * ## The silence this exists to break
6
+ *
7
+ * Authority decides one thing: whether Jev may clear a regex policy's deny or
8
+ * instruct (`combine.ts`, which returns early unless the authority is
9
+ * `reviewable`). Absent means `hard`, and that default is right — it is what
10
+ * keeps an unknown pack, cloud or custom policy from being weakened by a
11
+ * classifier nobody asked about it.
12
+ *
13
+ * It is also completely silent. `authority` and `reviewedBy` reach a pack
14
+ * through its manifest, and the only thing that writes them there is
15
+ * `scripts/build-policy-pack.mjs`, which ships WITH this release. So a pack
16
+ * published before it declares none, every policy in it resolves to `hard`
17
+ * with nothing downgraded, and `warnAuthority` — which only speaks when a
18
+ * `reviewable` declaration was not honored — has nothing to say. The result a
19
+ * customer gets is the deny half of the two-tier evaluator working exactly as
20
+ * documented, the clear half unable to fire once, and no diagnostic anywhere:
21
+ * `jev status` says `on`, the fallback rate says the calls are being answered,
22
+ * and `cleared` says `nothing` forever.
23
+ *
24
+ * This module counts. It changes no policy's authority and no verdict, it is
25
+ * never imported from the hook path, and a machine with no `jev.json` never
26
+ * reaches a caller of it.
27
+ *
28
+ * ## What "enabled" means here
29
+ *
30
+ * The same thing it means in `handler.ts`, read from the same files, without
31
+ * loading or executing a policy:
32
+ *
33
+ * - **Installed packs** — each pack's manifest entries, narrowed by its
34
+ * `enabled` selection (absent means the whole pack). A pack's `clis`
35
+ * narrowing is NOT applied: there is no agent CLI in a status command, and
36
+ * the honest answer to "what could Jev clear on this machine" spans all of
37
+ * them.
38
+ * - **Builtins** — this build's catalog, under the same migration shim the
39
+ * handler applies: they enforce only while no pack is installed. The
40
+ * `alwaysOn` guard is counted always, because it registers always (and is
41
+ * hard always, so it can only ever lower the ratio).
42
+ * - **Cloud assignments** — the active deployment's records, whose authority is
43
+ * declared by whoever deployed them. One record per assignment; an artifact
44
+ * that registers several hooks is still one central decision.
45
+ *
46
+ * Two things are deliberately NOT counted, and `customFiles` is what says so
47
+ * out loud when it matters:
48
+ *
49
+ * - **Policies from the user's own files.** A custom hook declares its
50
+ * authority inside the module, so counting one means importing and running
51
+ * somebody's JavaScript — from a settings page, on every read. The count of
52
+ * custom policy FILES the hook loads (configured paths and the project and
53
+ * user convention files) is reported instead, the summary says in words that
54
+ * those policies were not counted, and no "never" is diagnosed beside them.
55
+ * - **A session pause.** It suspends local policy for minutes, and a warning
56
+ * about a policy set that is coming back shortly would be noise.
57
+ */
58
+ import { readActiveCloudManagedPolicies } from "./cloud-managed-policies";
59
+ import { jevPacks } from "./effective-reviewers";
60
+ import { resolve } from "node:path";
61
+ import { discoverPolicyFiles } from "./custom-hooks-loader";
62
+ import { customPoliciesDir } from "./fp-home";
63
+ import { configuredCustomPolicyPaths, findProjectConfigDir, readMergedHooksConfig } from "./hooks-config";
64
+ import { hasInstalledPacks, readInstalledPacks } from "./pack-manifest";
65
+ import { resolvePolicyAuthority, SEMANTIC_REVIEWER_NAMES } from "./policy-authority";
66
+ import { POLICY_CATALOG } from "./policy-catalog";
67
+ import { normalizePolicyName } from "./policy-registry";
68
+ import type { HooksConfig } from "./policy-types";
69
+ // A CLI and dashboard module, never on the hook path, so it may ask the
70
+ // resolver itself (`pack-cli.ts` does the same).
71
+ import { semanticPoliciesFromPacks } from "./semantic/pack-policies";
72
+
73
+ /** Anything that carries an authority declaration: a catalog entry, a pack entry, a cloud record. */
74
+ export interface AuthorityRecord {
75
+ authority?: unknown;
76
+ reviewedBy?: unknown;
77
+ alwaysOn?: boolean;
78
+ }
79
+
80
+ export interface ReviewableCoverage {
81
+ /** Enabled policies whose authority could be read without running code. */
82
+ enabled: number;
83
+ /** Of those, the ones Jev may clear a deny or an instruct from. */
84
+ reviewable: number;
85
+ /**
86
+ * Custom policy files the hook loads — configured paths and the project and
87
+ * user convention files — whose policies are not in the counts above.
88
+ */
89
+ customFiles: number;
90
+ }
91
+
92
+ /** The command that replaces a pack with one built by this release. */
93
+ export const RETAKE_PACK_COMMAND = "failproofai policies add FailproofAI/policies";
94
+
95
+ /**
96
+ * Count a policy set by the authority it would REGISTER with —
97
+ * `resolvePolicyAuthority`, the rule `registerPolicy` applies — so this cannot
98
+ * report a clear that would not happen or hide one that would.
99
+ *
100
+ * Deliberately not `effectiveAuthority`, the looser §7 contract `jev-review.ts`
101
+ * asks at evaluation time. That one needs a single non-empty name and is right
102
+ * where it is asked, because by then the registry holds a `reviewedBy` that
103
+ * registration already cleaned, and on cleaned records the two rules agree.
104
+ * Nothing counted HERE has been through registration: these records are read
105
+ * straight off a pack manifest, this build's catalog and the cloud deployment.
106
+ * So a declaration naming a check this build does not have — `reviewedBy:
107
+ * ["future-check"]`, which is what a pack built against a NEWER semantic set
108
+ * looks like here — is reviewable to the loose rule and hard in the registry,
109
+ * and counting it would report a clear that can never happen while
110
+ * `reviewableProblem` stayed silent about the machine it exists to warn.
111
+ */
112
+ export function countReviewable(
113
+ policies: Iterable<AuthorityRecord>,
114
+ /**
115
+ * The semantic checks that can be asked on this machine. Defaults to the
116
+ * compiled-in set; `surveyReviewableCoverage` passes the pack's when one
117
+ * declares its own, because otherwise this diagnostic reports "0 of 11
118
+ * reviewable" on exactly the machines the feature was built for — the ones
119
+ * running a pack that carries both tiers.
120
+ */
121
+ knownReviewers?: ReadonlySet<string>,
122
+ ): {
123
+ enabled: number;
124
+ reviewable: number;
125
+ } {
126
+ let enabled = 0;
127
+ let reviewable = 0;
128
+ for (const p of policies) {
129
+ enabled += 1;
130
+ if (resolvePolicyAuthority(p, knownReviewers).authority === "reviewable") reviewable += 1;
131
+ }
132
+ return { enabled, reviewable };
133
+ }
134
+
135
+ /**
136
+ * What this machine's enabled policy set looks like to Jev. Reads three files
137
+ * and no policy: see the header for what is in the counts and what is not.
138
+ *
139
+ * Every source is wrapped, and an unreadable one contributes nothing rather
140
+ * than throwing — the same fail-open posture `handler.ts` takes for packs and
141
+ * cloud policies, for the same reason: this is a diagnostic, and one corrupt
142
+ * byte must not replace a settings page with an error boundary.
143
+ */
144
+ export function surveyReviewableCoverage(cwd?: string): ReviewableCoverage {
145
+ const records: AuthorityRecord[] = [];
146
+
147
+ let packsInstalled = false;
148
+ /**
149
+ * The reviewers a pack brought with it. Collected from the SAME read as the
150
+ * policies rather than through `effectiveReviewerNames()`, which would re-read
151
+ * and re-verify every artifact for an answer already in hand — and would, for
152
+ * one read of a manifest being rewritten underneath, be able to disagree with
153
+ * the records counted here.
154
+ *
155
+ * A pack's `enabled` selection is deliberately not applied: it narrows which
156
+ * of its REGEX policies register, and its semantic set is not selectable.
157
+ */
158
+ let reviewers: ReadonlySet<string> | undefined;
159
+ try {
160
+ packsInstalled = hasInstalledPacks();
161
+ const packs = readInstalledPacks().packs;
162
+ for (const pack of packs) {
163
+ const selected = pack.enabled;
164
+ records.push(...(selected ? pack.policies.filter((p) => selected.includes(p.name)) : pack.policies));
165
+ }
166
+ // The names of the questions a request will actually carry: only the packs
167
+ // whose checks take part (an observe pack's do not), minus a reserved or
168
+ // contested name AND minus a check the question budget drops — which the
169
+ // hook path's manifest-only `reviewerNamesFor` cannot see. Anything else and
170
+ // the panel and `jev status` promise a clear that cannot happen.
171
+ const asked = semanticPoliciesFromPacks(jevPacks(packs));
172
+ reviewers = asked.fromPack ? new Set(asked.policies.map((p) => p.name)) : SEMANTIC_REVIEWER_NAMES;
173
+ } catch {
174
+ // An unreadable manifest enforces nothing; `readInstalledPacks` already
175
+ // reports that to the hook log on the path that cares.
176
+ }
177
+
178
+ let config: HooksConfig;
179
+ try {
180
+ config = readMergedHooksConfig(cwd);
181
+ } catch {
182
+ config = { enabledPolicies: [] };
183
+ }
184
+ // The migration shim, exactly as `handler.ts` applies it: this build's
185
+ // builtins enforce only until a pack is installed.
186
+ const legacyEnabled = new Set(packsInstalled ? [] : config.enabledPolicies.map(normalizePolicyName));
187
+ for (const policy of POLICY_CATALOG) {
188
+ if (policy.alwaysOn || legacyEnabled.has(normalizePolicyName(policy.name))) records.push(policy);
189
+ }
190
+
191
+ try {
192
+ for (const assignment of readActiveCloudManagedPolicies()) {
193
+ records.push({ authority: assignment.authority, reviewedBy: assignment.reviewedBy });
194
+ }
195
+ } catch {
196
+ // Same fail-open as the handler's own read of this file.
197
+ }
198
+
199
+ // Every file `loadAllCustomHooks` would load, by resolved path so a file
200
+ // both named and discovered (or a project root that IS home) counts once.
201
+ let customFiles = 0;
202
+ try {
203
+ // Relative paths against the project root, as the loader resolves them.
204
+ const projectRoot = findProjectConfigDir(cwd ?? process.cwd());
205
+ const files = new Set(configuredCustomPolicyPaths(config).map((p) => resolve(projectRoot, p)));
206
+ if (config.customPoliciesEnabled !== false) {
207
+ const projectDir = resolve(projectRoot, ".failproofai", "policies");
208
+ for (const dir of [projectDir, customPoliciesDir()]) for (const f of discoverPolicyFiles(dir)) files.add(f);
209
+ }
210
+ customFiles = files.size;
211
+ } catch {
212
+ customFiles = 0;
213
+ }
214
+
215
+ return { ...countReviewable(records, reviewers), customFiles };
216
+ }
217
+
218
+ /**
219
+ * The one line both surfaces show: the count, in the words `jev status` and the
220
+ * dashboard panel must agree on. A non-zero count is worth saying too — it is
221
+ * how someone learns how much of their policy set Jev can act on at all.
222
+ */
223
+ export function reviewableSummary(coverage: ReviewableCoverage): string {
224
+ const { enabled, reviewable } = coverage;
225
+ // Said out loud rather than folded into the number, because a custom policy
226
+ // CAN be reviewable and this count would not know: reading that declaration
227
+ // means importing and running the file it lives in.
228
+ const tail = coverage.customFiles > 0 ? " (policies from your own files are not counted)" : "";
229
+ if (enabled === 0) return `No policies are enabled here, so there is nothing for Jev to clear${tail}.`;
230
+ const noun = enabled === 1 ? "1 enabled policy is" : `${enabled} enabled policies are`;
231
+ if (reviewable === 0) return `0 of ${noun} reviewable${tail}.`;
232
+ return `${reviewable} of ${noun} reviewable: Jev may clear a deny or an instruction from those, and from no others${tail}.`;
233
+ }
234
+
235
+ /**
236
+ * Why Jev can never clear anything here, and what fixes it — or null when it
237
+ * can clear something, which needs no explanation.
238
+ *
239
+ * It states the observation before naming the usual cause, because the cause is
240
+ * the usual one and not the only one: a machine can also reach zero by enabling
241
+ * only hard policies, or by having nothing but the self-protection guard. The
242
+ * remedy is the same in each case, and it is one command.
243
+ *
244
+ * Nothing is diagnosed for an empty policy set: there is no clear to lose, and
245
+ * an authority warning to someone who enforces nothing answers a question they
246
+ * did not ask.
247
+ */
248
+ export function reviewableProblem(coverage: ReviewableCoverage): string | null {
249
+ // Policies from the user's own files were not counted and may be reviewable,
250
+ // so "never" cannot be said honestly; the summary already says what was skipped.
251
+ if (coverage.enabled === 0 || coverage.reviewable > 0 || coverage.customFiles > 0) return null;
252
+ return (
253
+ "Jev can add a deny or an instruction on this machine, but it can never clear one. " +
254
+ "No enabled policy is marked reviewable — a policy pack published before this release carries no such marks — " +
255
+ `so re-take the pack (\`${RETAKE_PACK_COMMAND}\`) to get a marked copy, ` +
256
+ "or enforce this build's builtin policies, which carry them."
257
+ );
258
+ }
@@ -43,6 +43,54 @@ export interface RegisteredPolicy {
43
43
  * the user's OWN configured `policyParams` for it, not merely the defaults.
44
44
  */
45
45
  params?: PolicyParamsSchema;
46
+ /** Whether Jev may clear this policy's deny/instruct; see {@link effectiveAuthority}. */
47
+ authority?: PolicyAuthority;
48
+ /**
49
+ * The semantic policies (`src/hooks/semantic/policies.ts`) that must all be
50
+ * asked, and each clear (see {@link PolicyAuthority}), before Jev clears this
51
+ * policy.
52
+ */
53
+ reviewedBy?: string[];
54
+ }
55
+
56
+ /**
57
+ * Who has the last word on a policy's deny or instruct when Jev is configured.
58
+ *
59
+ * - `hard`: final. Jev can never clear it.
60
+ * - `reviewable`: Jev may clear it, but only through the semantic policies
61
+ * named in `reviewedBy`, and only when every one of them was actually asked
62
+ * and each answered `none`, `overridden`, or a deny the human's task
63
+ * softened to a warning (`combine.ts`, "A check that fired without consent
64
+ * keeps the floor").
65
+ * A named check that was NOT asked always keeps the verdict standing.
66
+ */
67
+ export type PolicyAuthority = "hard" | "reviewable";
68
+
69
+ /**
70
+ * The authority a policy actually has. `reviewable` only when it is declared
71
+ * `reviewable`, names at least one semantic policy in `reviewedBy`, and is not
72
+ * `alwaysOn`. Anything else — absent, invalid, an empty `reviewedBy`, the
73
+ * self-protection guard — is `hard`, so an unknown custom, cloud or third-party
74
+ * policy can never be weakened by Jev.
75
+ *
76
+ * This is the §7 contract every task builds against, and it is deliberately
77
+ * the looser of two rules: one usable name is enough here. REGISTRATION is
78
+ * stricter — `resolvePolicyAuthority` in `policy-authority.ts` makes the whole
79
+ * declaration hard if any entry is malformed or is not a semantic policy this
80
+ * build has, and that is what `registerPolicy` stores. So a registered policy's
81
+ * `reviewedBy` is already clean, and the two rules agree on everything that
82
+ * reaches the registry.
83
+ */
84
+ export function effectiveAuthority(p: {
85
+ authority?: unknown;
86
+ reviewedBy?: unknown;
87
+ alwaysOn?: boolean;
88
+ }): PolicyAuthority {
89
+ if (p.alwaysOn === true) return "hard";
90
+ if (p.authority !== "reviewable") return "hard";
91
+ if (!Array.isArray(p.reviewedBy)) return "hard";
92
+ const named = p.reviewedBy.filter((n) => typeof n === "string" && n.length > 0);
93
+ return named.length > 0 ? "reviewable" : "hard";
46
94
  }
47
95
 
48
96
  export interface PolicyParamsSchema {
@@ -89,6 +137,10 @@ export interface BuiltinPolicyDefinition {
89
137
  * secondary line in the audit report. e.g. "Could leak code from neighboring
90
138
  * repos to the model." */
91
139
  impact?: string;
140
+ /** See {@link PolicyAuthority}. Absent means `hard`. */
141
+ authority?: PolicyAuthority;
142
+ /** See {@link RegisteredPolicy.reviewedBy}. */
143
+ reviewedBy?: string[];
92
144
  }
93
145
 
94
146
  export interface CustomHook {
@@ -98,6 +150,82 @@ export interface CustomHook {
98
150
  events?: HookEventType[];
99
151
  };
100
152
  fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
153
+ /**
154
+ * See {@link PolicyAuthority}. Absent means `hard`.
155
+ *
156
+ * Honored for the user's own local policy files (explicit paths and
157
+ * `.failproofai/policies/`). For a pack policy the pack's MANIFEST decides,
158
+ * and for a cloud-managed one the cloud ARTIFACT record does — the same split
159
+ * as `params`, so the declaration a user reviewed in a listing is the one
160
+ * that takes effect.
161
+ */
162
+ authority?: PolicyAuthority;
163
+ /** See {@link RegisteredPolicy.reviewedBy}. */
164
+ reviewedBy?: string[];
165
+ }
166
+
167
+ /**
168
+ * The tool classes a semantic policy may be asked about.
169
+ *
170
+ * A structural copy of `ToolClass` in `src/hooks/semantic/types.ts`, and
171
+ * deliberately not an import of it. This module is the public API's type
172
+ * surface — every custom policy file and every pack entry imports it — and the
173
+ * semantic modules must stay off the import graph of a machine with no
174
+ * `jev.json` (see `precondition-names.ts` for what that costs when it slips).
175
+ * A type import would be erased, but the two lists still have to agree, so
176
+ * `__tests__/hooks/semantic/pack-semantic-registry.test.ts` pins them.
177
+ */
178
+ export type SemanticToolClass = "shell" | "write" | "read" | "network" | "other";
179
+
180
+ /** One yes/no question in a semantic policy, as a pack declares it. */
181
+ export interface SemanticProbeDeclaration {
182
+ /** Lowercase slug, unique within the policy. The answer map is keyed `<policy>.<id>`. */
183
+ id: string;
184
+ instructions: string;
185
+ criteria?: { true: string; false: string };
186
+ }
187
+
188
+ /**
189
+ * A semantic (Jev) policy as its author DECLARES it — a question set, not code.
190
+ *
191
+ * The compiled-in equivalent is `SemanticPolicy` in `semantic/types.ts`, and
192
+ * the one difference is the whole reason both exist: there, `precondition` is a
193
+ * function over the computed facts; here it is the NAME of one, because a
194
+ * declaration has to survive a trip through a JSON manifest and because a
195
+ * downloaded artifact must not hand this process an expression to evaluate on
196
+ * every tool call. `semantic/preconditions.ts` binds the name to its predicate.
197
+ *
198
+ * There is no `fn` and no `match`: a semantic policy never executes locally and
199
+ * is never selected by event or tool name — `appliesTo` and `precondition`
200
+ * decide what it is asked about, and Jev answers it. That is also why it is
201
+ * registered through `semanticPolicies`, its own namespace, rather than as a
202
+ * variant of `customPolicies.add`.
203
+ */
204
+ export interface SemanticPolicyDeclaration {
205
+ /** Short slug. Reported as `semantic/<name>`, and what a `reviewedBy` names. */
206
+ name: string;
207
+ /** Past-tense phrase for what was caught, e.g. "Deleted something irreplaceable". */
208
+ title: string;
209
+ appliesTo: SemanticToolClass[];
210
+ /** `deny` blocks on strong evidence and warns on moderate; `instruct` only ever warns. */
211
+ mode: "deny" | "instruct";
212
+ /**
213
+ * Whether the human's own explicit request may clear this policy.
214
+ *
215
+ * Required, with no default anywhere in the stack. It is the field that
216
+ * decides whether a prompt injection can talk its way past the policy, and a
217
+ * default for it would be a security decision made by absence — the author
218
+ * would never learn which way it went.
219
+ */
220
+ userCanOverride: boolean;
221
+ /** A name from `PACK_PRECONDITION_NAMES`. Absent, or `"always"`, means no precondition. */
222
+ precondition?: string;
223
+ /** Every probe must hold for the policy to fire (conjunction). 1–6 of them. */
224
+ probes: SemanticProbeDeclaration[];
225
+ /** If this holds, the policy does not fire — the documented exceptions. */
226
+ exempt?: SemanticProbeDeclaration;
227
+ /** Shown to the agent when the policy fires. */
228
+ guidance: string;
101
229
  }
102
230
 
103
231
  export interface LlmConfig {