failproofai 1.0.12-beta.1 → 1.0.12

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 (236) 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.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +2 -2
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  12. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +3 -3
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  24. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  30. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  32. package/.next/standalone/.next/server/app/index.html +1 -1
  33. package/.next/standalone/.next/server/app/index.rsc +3 -3
  34. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  35. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  36. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  37. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  38. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  41. package/.next/standalone/.next/server/app/policies/page.js +2 -2
  42. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  44. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  48. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  49. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  51. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  52. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  55. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
  58. package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
  59. package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +2 -2
  60. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
  61. package/.next/standalone/.next/server/chunks/src_hooks_0_em82s16zfym._.js +1 -1
  62. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
  63. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
  64. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
  65. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
  66. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
  67. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
  68. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__167mipqmjprq5._.js +3 -0
  69. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
  70. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
  71. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
  72. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0b78b0j8iyv6l._.js → [root-of-the-server]__1vofkb2oq7p7e._.js} +1 -1
  73. package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/ssr/{_1a3tubds7s7ow._.js → _0ouu886szh6yj._.js} +4 -4
  75. package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
  76. package/.next/standalone/.next/server/chunks/ssr/_1d98fyfrcaqhy._.js +3 -0
  77. package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
  78. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
  79. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
  80. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +2 -2
  83. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_1i8oid1gc7s1f.js → node_modules_html-to-image_es_index_0tqc05n832v7a.js} +1 -1
  85. package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0agdmptetetdt._.js +1 -1
  87. package/.next/standalone/.next/server/chunks/ssr/src_hooks_0mdwgjisv4fub._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589gp4p60j._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me658zqmh_._.js +1 -1
  90. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  91. package/.next/standalone/.next/server/pages/404.html +1 -1
  92. package/.next/standalone/.next/server/pages/500.html +1 -1
  93. package/.next/standalone/.next/server/preview-props.json +3 -3
  94. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  95. package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
  96. package/.next/standalone/.next/static/chunks/{1b32-afqacaen.js → 0el9n3h9_zp5m.js} +1 -1
  97. package/.next/standalone/.next/static/chunks/0k7g_8x3o6gd-.js +1 -0
  98. package/.next/standalone/.next/static/chunks/{42e8zab314654.js → 0umzct31duk5g.js} +1 -1
  99. package/.next/standalone/.next/static/chunks/{24w3x2da9sk49.js → 0wobqgosirs8p.js} +1 -1
  100. package/.next/standalone/.next/static/chunks/12rug3jilwqzs.js +1 -0
  101. package/.next/standalone/.next/static/chunks/{2-tf6_7u623kd.js → 1kduj74-715jh.js} +1 -1
  102. package/.next/standalone/.next/static/chunks/2701amhrbsbot.js +1 -0
  103. package/.next/standalone/.next/static/chunks/{18433qz-8njv3.js → 27cavoc8paelg.js} +1 -1
  104. package/.next/standalone/.next/static/chunks/{0_zfad4co-t2z.js → 2ve23a7keupjw.js} +1 -1
  105. package/.next/standalone/.next/static/chunks/3bv6xaoitjpnh.js +6 -0
  106. package/.next/standalone/app/actions/update-jev-config.ts +5 -3
  107. package/.next/standalone/app/settings/jev-panel.tsx +1 -1
  108. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +28 -18
  109. package/.next/standalone/fp-cloud-cli/README.md +127 -9
  110. package/.next/standalone/fp-cloud-cli/fp_cli/app.py +15 -1
  111. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +199 -34
  112. package/.next/standalone/fp-cloud-cli/fp_cli/cloud_output.py +523 -0
  113. package/.next/standalone/fp-cloud-cli/fp_cli/commands/_cloud.py +45 -0
  114. package/.next/standalone/fp-cloud-cli/fp_cli/commands/_write.py +3 -1
  115. package/.next/standalone/fp-cloud-cli/fp_cli/commands/account_cmds.py +171 -0
  116. package/.next/standalone/fp-cloud-cli/fp_cli/commands/agent_cmds.py +80 -7
  117. package/.next/standalone/fp-cloud-cli/fp_cli/commands/alerts_cmds.py +23 -0
  118. package/.next/standalone/fp-cloud-cli/fp_cli/commands/audits_cmds.py +2 -0
  119. package/.next/standalone/fp-cloud-cli/fp_cli/commands/contracts_cmds.py +67 -0
  120. package/.next/standalone/fp-cloud-cli/fp_cli/commands/dashboards_cmds.py +159 -0
  121. package/.next/standalone/fp-cloud-cli/fp_cli/commands/evaluators_cmds.py +380 -0
  122. package/.next/standalone/fp-cloud-cli/fp_cli/commands/events_cmds.py +14 -1
  123. package/.next/standalone/fp-cloud-cli/fp_cli/commands/fleet_cmds.py +12 -216
  124. package/.next/standalone/fp-cloud-cli/fp_cli/commands/incidents_cmds.py +82 -6
  125. package/.next/standalone/fp-cloud-cli/fp_cli/commands/list_cmds.py +4 -1
  126. package/.next/standalone/fp-cloud-cli/fp_cli/commands/orgs_cmds.py +17 -0
  127. package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +143 -1
  128. package/.next/standalone/fp-cloud-cli/fp_cli/commands/queries_cmds.py +70 -0
  129. package/.next/standalone/fp-cloud-cli/fp_cli/commands/sentiment_cmds.py +49 -0
  130. package/.next/standalone/fp-cloud-cli/fp_cli/commands/sessions_cmds.py +95 -1
  131. package/.next/standalone/fp-cloud-cli/fp_cli/commands/settings_cmds.py +2 -0
  132. package/.next/standalone/fp-cloud-cli/fp_cli/commands/usage_cmds.py +21 -1
  133. package/.next/standalone/fp-cloud-cli/fp_cli/commands/users_cmds.py +14 -0
  134. package/.next/standalone/fp-cloud-cli/fp_cli/enforcement.py +7 -53
  135. package/.next/standalone/fp-cloud-cli/fp_cli/errors.py +3 -0
  136. package/.next/standalone/fp-cloud-cli/fp_cli/evaluator_spec.py +266 -0
  137. package/.next/standalone/fp-cloud-cli/fp_cli/output.py +189 -152
  138. package/.next/standalone/fp-cloud-cli/fp_cli/theme.py +21 -24
  139. package/.next/standalone/fp-cloud-cli/skill/SKILL.md +124 -23
  140. package/.next/standalone/fp-cloud-cli/skill/agents/openai.yaml +2 -1
  141. package/.next/standalone/fp-cloud-cli/skill/references/commands.md +173 -22
  142. package/.next/standalone/fp-cloud-cli/tests/fake_cloud_smoke.py +312 -0
  143. package/.next/standalone/fp-cloud-cli/tests/test_cloud_account.py +125 -0
  144. package/.next/standalone/fp-cloud-cli/tests/test_cloud_agent.py +253 -0
  145. package/.next/standalone/fp-cloud-cli/tests/test_cloud_human_views.py +287 -0
  146. package/.next/standalone/fp-cloud-cli/tests/test_cloud_jev.py +32 -197
  147. package/.next/standalone/fp-cloud-cli/tests/test_cloud_observability.py +116 -0
  148. package/.next/standalone/fp-cloud-cli/tests/test_cloud_transport.py +141 -0
  149. package/.next/standalone/fp-cloud-cli/tests/test_commands.py +3 -3
  150. package/.next/standalone/fp-cloud-cli/tests/test_dashboards_agent.py +3 -3
  151. package/.next/standalone/fp-cloud-cli/tests/test_evaluator_authoring.py +449 -0
  152. package/.next/standalone/fp-cloud-cli/tests/test_facets.py +1 -1
  153. package/.next/standalone/fp-cloud-cli/tests/test_help_table_coverage.py +15 -0
  154. package/.next/standalone/fp-cloud-cli/tests/test_operator.py +1 -1
  155. package/.next/standalone/fp-cloud-cli/tests/test_orgs.py +1 -1
  156. package/.next/standalone/fp-cloud-cli/tests/test_output.py +37 -37
  157. package/.next/standalone/fp-cloud-cli/tests/test_round4_behaviour.py +144 -0
  158. package/.next/standalone/fp-cloud-cli/tests/test_screen_language.py +80 -0
  159. package/.next/standalone/fp-cloud-cli/tests/test_session_reevaluate.py +33 -0
  160. package/.next/standalone/fp-cloud-cli/tests/test_staging_parity.py +198 -0
  161. package/.next/standalone/fp-cloud-cli/tests/test_whoami.py +1 -1
  162. package/.next/standalone/hermes-plugin/__init__.py +11 -0
  163. package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
  164. package/.next/standalone/package.json +11 -10
  165. package/.next/standalone/sdk/python/uv.lock +31 -8
  166. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package-lock.json +68 -176
  167. package/.next/standalone/sdk/typescript/integration/fixtures/ai-4/package.json +2 -2
  168. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +4 -4
  169. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +1 -1
  170. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package-lock.json +7 -7
  171. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package.json +1 -1
  172. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package-lock.json +7 -7
  173. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package.json +1 -1
  174. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package-lock.json +98 -115
  175. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-0.3/package.json +3 -3
  176. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package-lock.json +4 -4
  177. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package.json +1 -1
  178. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +4 -4
  179. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +1 -1
  180. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package-lock.json +149 -171
  181. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package.json +2 -2
  182. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package-lock.json +4 -4
  183. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package.json +1 -1
  184. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +25 -25
  185. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +1 -1
  186. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +7 -7
  187. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +1 -1
  188. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +10 -10
  189. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +1 -1
  190. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package-lock.json +7 -7
  191. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package.json +1 -1
  192. package/.next/standalone/server.js +1 -1
  193. package/dist/cli.mjs +1760 -638
  194. package/dist/worker.mjs +426 -76
  195. package/hermes-plugin/__init__.py +11 -0
  196. package/hermes-plugin/plugin.yaml +1 -1
  197. package/package.json +11 -10
  198. package/src/audit/open-browser.ts +24 -7
  199. package/src/hooks/agent-roster.ts +9 -1
  200. package/src/hooks/agent-skill.ts +206 -0
  201. package/src/hooks/cloud-connection.ts +27 -51
  202. package/src/hooks/cloud-introspect.ts +5 -2
  203. package/src/hooks/cloud-login.ts +248 -0
  204. package/src/hooks/cloud-managed-policies.ts +54 -4
  205. package/src/hooks/codex-system-hooks.ts +10 -4
  206. package/src/hooks/config-status.ts +9 -3
  207. package/src/hooks/configure-wizard.ts +356 -32
  208. package/src/hooks/delivery-health.ts +47 -2
  209. package/src/hooks/effective-reviewers.ts +14 -0
  210. package/src/hooks/fp-config.ts +19 -0
  211. package/src/hooks/fp-home.ts +1 -1
  212. package/src/hooks/handler.ts +43 -5
  213. package/src/hooks/hook-activity-store.ts +7 -1
  214. package/src/hooks/integrations.ts +18 -3
  215. package/src/hooks/jev-activity.ts +117 -1
  216. package/src/hooks/jev-cli.ts +7 -9
  217. package/src/hooks/manager.ts +80 -46
  218. package/src/hooks/policy-evaluator.ts +17 -0
  219. package/src/hooks/policy-reviewability.ts +4 -2
  220. package/src/hooks/semantic/cloud-jev.ts +219 -28
  221. package/src/hooks/semantic/combine.ts +26 -1
  222. package/src/hooks/semantic/intent.ts +127 -24
  223. package/src/hooks/semantic/jev-client.ts +1 -1
  224. package/src/hooks/semantic/jev-config.ts +6 -27
  225. package/src/hooks/semantic/jev-review.ts +111 -4
  226. package/src/hooks/tui.ts +280 -0
  227. package/src/hooks/uninstall-cli.ts +12 -1
  228. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0588st-tpiuia._.js +0 -3
  229. package/.next/standalone/.next/server/chunks/ssr/_128ebxr83nk6g._.js +0 -3
  230. package/.next/standalone/.next/static/chunks/0jutamwqz8pg5.js +0 -1
  231. package/.next/standalone/.next/static/chunks/114hbolvrv94e.js +0 -1
  232. package/.next/standalone/.next/static/chunks/1p-hsi58i-6h0.js +0 -6
  233. package/.next/standalone/.next/static/chunks/3-pku9qwv1yfu.js +0 -1
  234. /package/.next/standalone/.next/static/{xq8UgF5yFxty1VWxY2hyn → D7LY1YSrw96ZxKSpxxrFw}/_buildManifest.js +0 -0
  235. /package/.next/standalone/.next/static/{xq8UgF5yFxty1VWxY2hyn → D7LY1YSrw96ZxKSpxxrFw}/_clientMiddlewareManifest.js +0 -0
  236. /package/.next/standalone/.next/static/{xq8UgF5yFxty1VWxY2hyn → D7LY1YSrw96ZxKSpxxrFw}/_ssgManifest.js +0 -0
@@ -17,6 +17,9 @@ command**, **`--json` to parse**, **branch on exit codes**.
17
17
  - [issues](#issues)
18
18
  - [query](#query)
19
19
  - [agent](#agent)
20
+ - [policies · fleet · guardrails](#policies--fleet--guardrails)
21
+ - [Author an evaluator](#author-an-evaluator)
22
+ - [Cloud dashboard parity](#cloud-dashboard-parity)
20
23
 
21
24
  ## Global options
22
25
  Set on the CLI, **before** the subcommand. Precedence: flag > env var > config file (`~/.failproofai/fpcli/cli-auth.json`, mode 0600).
@@ -29,6 +32,9 @@ Set on the CLI, **before** the subcommand. Precedence: flag > env var > config f
29
32
  | `--api-key <k>` | `FP_API_KEY` | Scoped API key — authenticate as a credential instead of as a signed-in user. Never saved to the config file. |
30
33
  | `--json` | `FP_JSON` | Machine-readable JSON to stdout, nothing else. |
31
34
  | `--insecure` / `--secure` | `FP_INSECURE` | Skip / require TLS verification (for self-signed dev certs; saved at login). |
35
+ | `--timeout <secs>` | | Per-request HTTP timeout in seconds (default 30). Server-side limits (e.g. the policy composer's 30s) are not lifted by it. |
36
+ | `--quiet` / `-q` | | Suppress status lines and hints on stderr. |
37
+ | `--no-color` | `NO_COLOR` | Plain, uncoloured human output. |
32
38
  | `--version` | | Print version (also `fp version`). |
33
39
 
34
40
  Config dir resolves as `FP_HOME` > `$FAILPROOFAI_HOME/fpcli` > `~/.failproofai/fpcli`; `FP_HOME` is used as-is, `FAILPROOFAI_HOME` gets `fpcli/` appended. Telemetry is currently disabled globally while its send path is made fully non-blocking. `FP_ANALYTICS_DISABLED=1` and `DO_NOT_TRACK=1` remain supported opt-out controls for when telemetry is re-enabled.
@@ -49,17 +55,18 @@ Exactly one credential is in play per invocation, chosen in this order:
49
55
  - **The key is never persisted.** A session token is saved by `login` and expires on its own; an API key is valid until someone revokes it, so the CLI keeps it out of the config file entirely. Supply it per invocation, normally via `FP_API_KEY`.
50
56
  - **`--api-key ""` means "no override", not "fall back".** Mode stays *key*, the credential is empty, and the command exits 4 — it will not quietly use a saved session. (Same rule as `--token ""`.) An empty *environment variable* is a different story: `FP_API_KEY=""` reads as unset and falls through to the next credential, so an unset CI variable can silently run as whichever human is logged in on that machine. Pass the flag if you need the strict behaviour.
51
57
  - **A rejected key is exit 4**, same as an expired session. Report it; don't retry and don't switch credentials.
52
- - **Session-only commands:** `login`, `logout`, `orgs *`, `agent *`, `keys update`, and all of `policies *`, `fleet *`, `guardrails *`. In key mode each exits **2** *before making any request* — there's no user to sign in or switch orgs for, no private assistant thread to own, and the enforcement write routes are root-only and deliberately absent from `/v1`. `keys update` is in this list and not a special case: it calls `deny_in_key_mode` as the FIRST statement of the command body, so it exits 2 with zero HTTP calls like the rest, because `keys:update` cannot be granted to any API key.
58
+ - **Session-only commands:** `login`, `logout`, `orgs *` (incl. `orgs create`), `agent *` (incl. `agent brief`), `keys update`, `evaluators draft`, `query compose`, `slack *`, `plan`, `plan claim`, and every `policies` subcommand except `test`, plus all of `fleet *` and `guardrails *`. `policies test` runs locally and makes no request, so it works with a key too. In key mode each session-only command exits **2** *before making any request* — there's no user to sign in or switch orgs for, no private assistant thread to own, and the enforcement write routes are root-only and deliberately absent from `/v1`. `keys update` is in this list and not a special case: it calls `deny_in_key_mode` as the FIRST statement of the command body, so it exits 2 with zero HTTP calls like the rest, because `keys:update` cannot be granted to any API key.
59
+ - **Key-only command:** `usage windows` is served on the versioned API only — with a signed-in session it exits **2** without a request and asks for `--api-key`.
53
60
  - **Name the org when using a key.** Key mode sends the org only when you supply it (`--org <slug>` / `FP_ORG`) — it never reuses the saved active org from `login`. A key bound to one organization only ever acts on that one; a key that is not bound to a single organization falls back to the deployment's default, and you get plausible-looking data from the wrong tenant with no error and no warning. Naming the key's own org is a no-op; naming a different one is rejected. Both beat guessing.
54
61
 
55
62
  ## Shared input conventions
56
63
  - **`--json`** on any command → pure JSON on stdout (no Rich chrome). Mutations under `--json` auto-skip their confirm prompt.
57
64
  - **`--yes` / `-y`** explicitly skips a confirm prompt. (Confirms are also auto-skipped on a non-TTY — i.e. whenever Claude runs it — so always confirm with the user yourself first.)
58
65
  - **`--all` + `--limit`**: `--limit` (`-n`) defaults to **50**; `--all` auto-paginates (client chunks of 200) **up to `--limit`**, NOT without bound. So a bare `--all` still stops at 50 rows. For a full sweep on `events/sessions/evals/errors`, pass a high explicit cap: **`--all --limit 1000`** (or higher). To just get window totals, use `--aggregate` (covers the whole window regardless of row caps).
59
- - **`--fields a,b,c`** projects only those keys (where supported: sessions/evals, keys, query list).
66
+ - **`--fields a,b,c`** projects only those keys (where supported: `events`, `errors`, `sessions`, `evals`, `keys list`, `query list`). `events --fields payload` switches to the full feed.
60
67
  - **Policy source** (`policies publish` / `policies test`) comes from a path, `@path`, a pipe, `-`, or an interactive paste. A path that is not readable UTF-8 text — a binary file pointed at by mistake — is refused by name (**exit 2**), as is a missing path; neither reaches the server.
61
68
  - **`--since <window>`** relative window — one of `15m`, `1h`, `6h`, `24h`, `7d`, `all` (any other value is a usage error, exit 2). `--from`/`--to` take ISO timestamps **with `T` and a timezone** (e.g. `2026-06-01T00:00:00Z`) — space-separated or tz-less is a usage error (exit 2).
62
- - **`--file payload.json`** (or `--file -` for stdin) supplies a full JSON request body on `alerts`, `settings set`, and `users create/update` — mutually exclusive with the discrete flags. Saved-query SQL uses `--sql @file.sql`.
69
+ - **`--file payload.json`** (or `--file -` for stdin) supplies a JSON request body on `alerts create/update`, `audits create/edit`, `settings set`, `roles create/update`, `dashboards create/update` and `dashboards tiles add/update/layout`, `audits contracts create/update`, `alerts issues --create`, and `evaluators create/deploy/dry-run` (an evaluator spec). On `alerts` the flags layer on top of the file; elsewhere the file and the discrete flags are mutually exclusive. `users create/update` take **no** `--file`. Saved-query SQL uses `--sql @file.sql`.
63
70
  - **Multi-value filters** are CSV → `IN (...)` (union within a filter, AND across filters): `--event-type tool_use,tool_result`. `--search` is repeated/OR (matches ANY term), payload-only.
64
71
 
65
72
  ## Identity
@@ -90,7 +97,9 @@ free-text term, so broad searches can still be expensive. To get the raw `payloa
90
97
  into the **full feed** with `--full` (or `--fields payload`) — that read is slow at scale,
91
98
  so keep it bounded (pair `--full` with one `--session-id`).
92
99
  e.g. `fp --json events --full --session-id run-1 --all | jq '.events[].payload'`.
93
- Filters: `--session-id <id>` `--agent-id <id>` `--event-type <csv>` `--env <csv>` `--since <window>` / `--from`/`--to` `--search <term>` (repeatable, payload OR-match).
100
+ Filters: `--session-id <id>` `--agent-id <id>` `--event-type <csv>` `--env <csv>` `--since <window>` / `--from`/`--to` `--search <term>` (repeatable, payload OR-match). Paging/shape: `--limit/-n` (50) `--all` `--cursor <c>` `--page-size N` `--order asc|desc` `--fields a,b` `--full`.
101
+
102
+ `fp events latency [--since <window>]` — latency and token aggregate (the breakdowns page's numbers).
94
103
 
95
104
  #### Getting the raw payload
96
105
  The default `events`/`errors` reads are payload-free. Only `--full` (or `--fields payload`)
@@ -103,24 +112,28 @@ scale.
103
112
  - **Precise / by id (avoids the heavy list query):** `fp --json query run --sql "SELECT id, event_type, payload FROM events WHERE session_id = '<SESSION_ID>' ORDER BY ts"` — or `WHERE id = <EVENT_ID>`. Reads `payload` directly via the read-only SQL runner; a bounded `WHERE` is fast.
104
113
 
105
114
  ### sessions
106
- `fp sessions [filters] [--all]` — agent runs: time/env/agent/session/status (no scores). Filters: `--session-id --agent-id --env --status <error|...> --since`. JSON rows still carry `scores`.
115
+ `fp sessions [filters] [--all]` — agent runs: time/env/agent/session/status (no scores). Filters: `--session-id --agent-id --env --status <error|...> --since --from --to`. Paging/shape: `--limit/-n` `--all` `--cursor` `--page-size` `--fields` `--full-ids`; `--agents` expands each run's agent roster. JSON rows still carry `scores`.
116
+
117
+ Sub-commands on one session: `sessions show <id>` (overview + event timeline), `sessions export <id> [--out FILE]` (full session JSON; `--out` refuses to overwrite), `sessions history <id>` (its evaluation history), `sessions re-evaluate <id>` (re-runs every enabled evaluator on it; needs `evaluations:trigger`; a write — confirm first).
118
+
119
+ `fp sessions import FILE... [--format auto|failproofai|claude|codex] [--env ENV] [--dry-run]` — import sessions from files (event JSONL, Claude Code transcripts, Codex rollouts; `.gz` accepted), as the dashboard's Import sessions dialog does. Each file is sent on its own; sessions already in the org are skipped whole; secrets are redacted the way the collector redacts them live. Claude Code / Codex files take the session id from the file name, so pass the original files. (`failproofai` = FailproofAI's own event JSONL.) `--dry-run` converts and reports, storing nothing. Needs `events:add`. JSON `{files:[{file, result}]}`.
107
120
 
108
121
  ### evals
109
122
  `fp evals [filters] [--score key:min..max] [--scores-full] [--all]` — evaluation results + scores.
110
123
  `fp evals --aggregate [--since 7d]` — rollup: `{total, status_counts, score_stats, timeline}` (status mix + per-metric score stats). `--score helpfulness:..0.5` = max 0.5; `helpfulness:0.8..` = min 0.8; `helpfulness:0.5..0.9` = range.
111
124
 
112
125
  ### errors
113
- `fp errors [filters] [--all]` — errored events (time/event/env/agent/session/summary), from the light payload-free feed; the `summary` is the server-computed field, and `--json` rows carry no payload. For a run's raw payload use `fp events --full --session-id <id>`. Filters incl. `--error-type <csv>`.
126
+ `fp errors [filters] [--all]` — errored events (time/event/env/agent/session/summary), from the light payload-free feed; the `summary` is the server-computed field, and `--json` rows carry no payload. For a run's raw payload use `fp events --full --session-id <id>`. Filters: `--error-type <csv>` `--event-type <csv>` `--env` `--agent-id` `--session-id` `--search <term>` `--since`/`--from`/`--to`; paging/shape `--limit/-n` `--all` `--cursor` `--page-size` `--order` `--fields` `--full-ids`.
114
127
  `fp errors --aggregate [--since 7d]` — `{total, sessions, agents, last_ts, bins}`.
115
128
 
116
129
  ### usage
117
130
  `fp usage` — the active org's current fixed 30-day metering window, grouped for human
118
131
  reading. Needs `usage:read`. `fp --json usage` returns the dashboard contract unchanged:
119
132
  `org_id`, `billing_anchor`, `window`, `usage`, `calculated_at`, and `stale_after`. It has no
120
- filters or subcommands and is read-only; limits and enforcement are not part of this command.
133
+ filters and is read-only. `usage windows` lists the metering windows — **API key only** (`--api-key` with `usage:read`): the dashboard has no session route for it, so a signed-in session gets exit 2 before any request.
121
134
 
122
135
  ### list
123
- `fp list <kind>` — discover valid filter values. Kinds: `envs agents event_types score_filters models hooks tools error_types`. JSON `{kind, values}`. Run this before filtering by a value you're unsure of.
136
+ `fp list <kind>` — discover valid filter values. Kinds: `envs agents event_types score_filters models hooks tools error_types trigger_events eval_envs metric_keys` (`eval_envs` = environments with evaluation results, `metric_keys` = evaluation metric names; both need `evaluations:read`). JSON `{kind, values}`. Run this before filtering by a value you're unsure of.
124
137
 
125
138
  ## keys
126
139
  API keys; the secret is shown **once** on create/regenerate (capture it then). Referenced by **name**.
@@ -137,9 +150,10 @@ Permission token format (for `--add`/`--remove`): `slug:action` flat, or `slug:a
137
150
  Referenced by **email** (UUID id also accepted).
138
151
  - `users list [--show-id] [--active-only]` — `[lock] email · access · perms · joined · status`.
139
152
  - `users show <email>` — identity + all grants.
140
- - `users create [EMAIL] [--permission-set <set>] [--add tok] [--remove tok]` — `--permission-set` one of the builtin sets (`admin`/`standard`/`read-only`) or a custom set name (client-validated; unknown → exit 2). `--add`/`--remove` take compact permission tokens.
153
+ - `users create EMAIL [--permission-set <set>] [--add tok] [--remove tok]` (EMAIL is required) — `--permission-set` one of the builtin sets (`admin`/`standard`/`read-only`) or a custom set name (client-validated; unknown → exit 2). `--add`/`--remove` take compact permission tokens.
141
154
  - `users update <email>` — assign a set, or incrementally `--add`/`--remove`. Predicts the resulting grants and confirms.
142
155
  - `users disable <email>` / `users enable <email>` — disable has protected/self guards.
156
+ - `users delete <id>` — remove a member **by id** (not email); also revokes their CLI key. `users defaults` — the grants a new member gets.
143
157
 
144
158
  **Multi-token `--add`:** Click options aren't variadic — `--add a b` breaks. Use `--add a,b` (comma), `--add a --add b` (repeat), or `--add "a b"` (quoted).
145
159
 
@@ -150,6 +164,20 @@ A fixed registry — you read/inspect/change existing keys, you cannot create ne
150
164
  - `settings set <key> (--value V | --json-value JSON | --file f)` — exactly one value source. Unknown key → exit 6. No-op if unchanged. Server validation errors surface as `✗ <message>` (e.g. range bounds). Some keys are sensitive (signing secrets, sign-in allowlist) — confirm carefully.
151
165
  - `allowed_sign_ins` restricts which of the organization's members may sign in; it does not grant access to anyone else. An **empty list means no restriction** (every member can sign in), so clearing it widens access rather than removing it. A non-empty list admits only matching addresses and locks out every other member. Entries are exact addresses or `*@domain.tld`; a bare `*` is rejected — use an empty list. Saving a list that does not include your own address is refused, because you could not sign in again.
152
166
 
167
+ ## alerts
168
+ Alert rules, referenced by **name** (a UUID-shaped id is also accepted). Reads need `alerts:read`, writes `alerts:write`.
169
+ - `alerts list [--show-id]` — `name · severity · trigger · status · open issues`, newest first.
170
+ - `alerts show <name>` — identity + trigger + evaluation + channels cards.
171
+ - `alerts create <name> [--file alert.json] [--description …] [--severity info|warning|critical] [--trigger-kind metric_threshold|custom_sql|evaluation_score|eval_compound|per_event] [--trigger-spec JSON] [--channels JSON] [--eval-interval-secs N] [--min-breaches N] [--eval-window N]` — `--trigger-kind` + `--trigger-spec` (the condition, shaped per kind) and `--severity` are the core; the rest have server defaults. `--file` is a full AlertInput and the flags layer on top. Name collision → exit 2. New alerts start enabled. JSON `{id, created_at}`.
172
+ e.g. `fp alerts create high-errors --trigger-kind metric_threshold --severity warning --trigger-spec '{"metric":"error_count","op":">","value":50,"window_secs":900}'`
173
+ - `alerts update <name> [--name NEW] [same flags as create] [--yes]` — flag-only edits re-send the current alert with your change (the server replaces the whole alert, so this needs read **and** write); `--file` replaces it wholesale. Confirms first. JSON `{id, updated_at}`.
174
+ - `alerts delete <name> [--yes]` — amber preview incl. the open-issue count it orphans, then confirm. Cannot be undone.
175
+ - `alerts test <name> [--channels JSON] [--yes]` — **really sends** a test notification to the alert's channels (or the `--channels` override; default slack/webhook/email). Success means dispatched, not delivered. JSON `{ok, synthetic_incident_id}`.
176
+ - `alerts recipients` — the recipient directory the dashboard's pickers use (members and saved addresses).
177
+ - `alerts issues <alert-id> [--create (--title T [--summary S] | --file body.json)]` — list the issues one alert raised, or raise one under it (needs `issues:create`).
178
+
179
+ Alert **channels** (default email recipients, Slack webhook, generic webhook URL + signing secret) are org settings: `fp settings schema` lists the `alerts.*` keys, `fp settings set` changes them.
180
+
153
181
  ## audits
154
182
  Scheduled sweeps over agent activity, and the **findings** they produce. Audits are referenced by **name** (UUID id also accepted); findings by **id** (short ids shown in the table, `--show-id` for the full ones).
155
183
  - `audits list [--enabled-only] [--show-id]` — `created · name · every · findings · status · last run`; disabled audits are dimmed and the footer carries the on/off split plus the open-finding total.
@@ -172,6 +200,7 @@ Context is a **separate sub-resource on purpose**: `audits edit` read-merges the
172
200
  - `audits resolve <id> [--yes]` — you fixed it. Leaves **no** suppression, so a genuine recurrence reopens the issue it graduated to. Confirms first.
173
201
  - `audits reopen <id>` — back to `open` **and** clears any mute/dismiss suppression. The undo for the three above.
174
202
  - `audits assign <id> --to <email>` — set the owner; the status is untouched. `--to` is required (exit 2 without it).
203
+ - `audits contracts list|show <id>|create|update <id>` — **agent contracts**: what each agent is supposed to do, read by every audit. `create --agent-id <agent> --body "markdown"|@file.md` (or `--file` API JSON `{agent_id, body, enabled}`); `update <id> [--agent-id] [--body] [--enabled|--disabled] [--file]` keeps unmentioned fields. Body ≤ 5000 chars. There is no delete. Reads `audits:read`, writes `audits:write`.
175
204
 
176
205
  The title column truncates to whatever width is left so the fixed columns always survive — read the full text with `audits finding <id>` or `--json`. A bad `--status`, `--window-mode`, `--sensitivity`, a non-ISO-8601 `--schedule-anchor`, or an out-of-range `--schedule-interval-secs`/`--lookback-window-secs` is rejected before any request (exit 2). `--schedule-anchor` pins the fixed UTC slot runs land on (`anchor + N * interval`), so a slow run or `audits run` can't drift the cadence; omit it on create and the server uses the next 09:00 UTC. An unknown audit name → exit 6; an unknown or malformed finding id → calm `✗ no finding …`, exit 6. Reads need `audits:read`, every mutation `audits:write`.
177
206
 
@@ -181,11 +210,13 @@ The title column truncates to whatever width is left so the fixed columns always
181
210
 
182
211
  ## issues
183
212
  The single board for everything needing human attention — alert breaches (`source: alert`), hand-raised issues (`manual`), and audit findings (`audit`). Referenced by id (short ids accepted, `--show-id` shows them). This group was **renamed from `incidents`**; the old name no longer exists. Reads and ack/comment need `issues:read`; opening, assigning, and subscribing others need `issues:create`; resolving, closing, archiving and clearing need `issues:close` (and `clear` also needs `audits:write`, because it resolves the findings behind the issues).
184
- - `issues list [--state firing|acknowledged|resolved|closed] [--alert-id <id>] [--limit N] [--show-id]` — there is **no** `--severity` filter on this command. Archived issues are hidden.
185
- - `issues count`
213
+ - `issues list [--state firing|acknowledged|resolved|closed] [--alert-id <id>] [--limit N] [--show-id] [inbox filters]` — there is **no** `--severity` filter on this command. Archived issues are hidden unless `--archived only|all`.
214
+ - **Inbox filters** (all CSV, all optional, on `list`, `count` and `facets`): `--agent-id` · `--env` · `--machine` · `--source alert|audit|manual` · `--audit-id` · `--assignee <email>|me|unassigned` · `--archived false|only|all` · `--search <text>` (title or summary, case-insensitive) · `--since <window>` (opened within). `count` and `facets` also take `--alert-id`.
215
+ - `issues count [--state …] [filters]` — JSON `{count}`; with no `--state` the server counts open ones (firing + acknowledged).
216
+ - `issues facets [--state …] [filters]` — the values each filter can take right now, with counts (the inbox filter bar).
186
217
  - `issues show <id>` — identity + comments + subscribers + **activity log** (read this before acting). An audit-born issue (`source: audit`) carries the full finding it graduated from and back-links to the audit/run.
187
218
  - `issues ack <id>` · `issues assign <id> --assignee <member>` (repeatable; omit to clear all assignees; each must be an operator) · `issues resolve <id>` (calm confirm). **On an audit issue these stay in sync with the finding** — resolving the issue resolves the underlying audit finding, so it can't reappear on the next run (equivalently, triage it with `audits resolve <finding-id>`; both surfaces agree).
188
- - `issues close <id>` (calm confirm) — the second terminal state: **"we're done with it", not "we fixed it"** (won't fix / not a problem / stale). The difference from `resolve` is what happens next: a **resolved** issue REOPENS when its audit finding recurs, a **closed** one does not. On an audit issue this marks the finding `dismissed`; it does **not** write the org-wide fingerprint suppression that `audits dismiss` writes, so closing one issue never hides that pattern in your other audits. Exit 9 if the issue already ended — an issue ends once, and neither terminal state may overwrite the other.
219
+ - `issues close <id>` (calm confirm) — the second terminal state: **"we're done with it", not "we fixed it"** (won't fix / not a problem / stale). The difference from `resolve` is what happens next: a **resolved** issue REOPENS when its audit finding recurs, a **closed** one does not. On an audit issue this marks the finding `dismissed`; it does **not** write the org-wide fingerprint suppression that `audits dismiss` writes, so closing one issue never hides that pattern in your other audits. If the issue already ended the server answers 409 and `fp` exits **1** — an issue ends once, and neither terminal state may overwrite the other.
189
220
  - `issues archive <id>` · `issues unarchive <id>` — take an issue off the board / put it back. **Orthogonal to state**: archiving resolves nothing and never overwrites how an issue ended, and it works on a live issue too. No confirm (it destroys nothing). A fresh alert breach or a recurring audit finding un-archives a live issue automatically, so archive can hide a problem but cannot keep hiding one that is still happening; a `closed` issue is the exception and stays hidden.
190
221
  - `issues clear (--audit <id> | --all-audits | --everything) [--dry-run] [--yes]` — **the "we changed our agents, give us a fresh board" command.** Resolves every open issue in the scope in one server-side transaction, plus the audit findings behind them. Exactly one scope flag is required. Needs `issues:close` **and** `audits:write`. **Nothing is deleted and nothing is suppressed** — a pattern the agent changes genuinely fixed stays gone, one they did not comes back on the next run and reopens its issue; for permanent silence use `audits mute`/`dismiss` instead. Always `--dry-run` first: the count comes from the server using the same scope predicate the write uses, so it is the real size of the scope — but it is a count, not a lease: the write re-runs the predicate, so anything that entered the scope since the preview is cleared too, and the closing line reports what actually changed.
191
222
  - `issues open --summary <text> (--title <text> | --alert-id <id>) [--title ...] [--severity ...]` — `--title` is **required** for a standalone issue (nothing to borrow a name from); with `--alert-id` it is optional and defaults to the alert's name. Missing `--title` on the standalone path → exit 2.
@@ -210,7 +241,8 @@ Saved ClickHouse SQL + ad-hoc runner. Saved queries referenced by **name**.
210
241
  Built-in assistant. Chats referenced by a **short chat-id** (first 8 hex; prefix-resolved).
211
242
  - `agent health` · `agent models` (available models for `--model`, default marked).
212
243
  - `agent chats` — `chat-id · title · messages · updated`.
213
- - `agent ask "MESSAGE" [--chat <short-id>] [--model <m>]` — starts a new chat (prints its short id) or continues `--chat`. On a TTY the answer renders as Markdown; piped/non-TTY prints the raw answer to stdout.
244
+ - `agent ask "MESSAGE" [--chat <short-id>] [--model <m>] [--page-context <text>] [--approve]` — starts a new chat (prints its short id) or continues `--chat`. On a TTY the answer renders as Markdown; piped/non-TTY prints the raw answer to stdout. Charts/tables the assistant produces are rendered (their SQL runs through `queries:run`, SELECT/WITH only). When the assistant asks to **write** something, a terminal prompts; scripts and `--json` decline unless `--approve` was given — only pass it when the user explicitly authorized the write.
245
+ - `agent brief [--range 24h|7d]` — the assistant-curated home brief.
214
246
  - `agent show <short-id>` — transcript. `agent rename <short-id> --title "…"` · `agent delete <short-id>`.
215
247
  - Ambiguous prefix → exit 2; unknown chat → exit 6.
216
248
 
@@ -228,21 +260,26 @@ Cloud-managed enforcement, split the way the dashboard splits it: `policies` wri
228
260
  - `both` — JavaScript plus its own Jev checks, deployed and toggled as one. FailproofAI Cloud makes the JavaScript's verdict `reviewable` by exactly its own checks (`authority`/`reviewedBy` are derived by the server, never sent).
229
261
 
230
262
  Without `--kind` it follows from what you give (`--semantic` alone is `jev`, with source `both`); a kind that contradicts its inputs is **exit 2**, before anything is sent. `fp` checks only the shape of the file (a non-empty list of named objects, ≤24); the server checks the rest — the limits, FailproofAI's 16 reserved check names (**422 `reserved_jev_name`**), and names unique across the org — and names the declaration it refused. SOURCE is a path, `@path`, `-`, a pipe, or omitted to paste on a TTY (Ctrl-D ends); `--semantic` takes a path, `@path` or `-` (only one of the two may be stdin). The JavaScript is **parse-checked with node** before it is sent; nothing downstream does this, and a broken policy otherwise fails on the machine at enforcement time. `--no-verify` skips it, and a host without node publishes with a warning rather than a block. JavaScript carrying Jev fields — `semanticPolicies.add(...)`, or `authority: "reviewable"` on a registration — is refused before sending (**exit 1**, not skipped by `--no-verify`; commented-out code does not count): put Jev checks in `--semantic` (`--kind both`), where they take effect. **Publishing deploys nothing** — the version is unused until `fleet deploy` puts it on a machine.
231
- - `policies enable <id>` · `policies disable <id> [-y]` — **disable REMOVES the policy from every deployment carrying it**, reissuing each affected machine at a new generation (visible in `fleet history`). `enable` is the exact inverse — it puts the policy back into every deployment it was removed from, reissuing those machines again. Nothing needs redeploying by hand, and `machinesUpdated` in the JSON reports the count for both directions.
232
- - `policies test [SOURCE] [--tool Bash] [--command "…"] [--file PATH] [--event PreToolUse] [--expect allow|deny|instruct]` — run a policy LOCALLY and print what it decides. Executes the real file (bare `import { deny } from "failproofai"` and all) against a synthetic context; nothing is published, nothing installed. Needs `node`. `--expect` asserts the decision and exits 1 when it differs — a correct `deny` is a PASSING test, so the decision alone never sets the exit code. JSON `{ok, decision, policies:[{name,decision,reason}], expected, met}`; `decision` is the strictest any registered policy returned.
263
+ - `policies enable <id> [-y]` · `policies disable <id> [-y]` — **disable REMOVES the policy from every deployment carrying it**, reissuing each affected machine at a new generation (visible in `fleet history`). `enable` is the exact inverse — it puts the policy back into every deployment it was removed from, reissuing those machines again. Nothing needs redeploying by hand, and `machinesUpdated` in the JSON reports the count for both directions.
264
+ - `policies test [SOURCE] [--tool Bash] [--command "…"] [--file PATH] [--event PreToolUse] [--expect allow|deny|instruct]` — run a policy LOCALLY and print what it decides. Makes no request, so unlike the rest of `policies` it also works with an API key. Executes the real file (bare `import { deny } from "failproofai"` and all) against a synthetic context; nothing is published, nothing installed. Needs `node`. `--expect` asserts the decision and exits 1 when it differs — a correct `deny` is a PASSING test, so the decision alone never sets the exit code. JSON `{ok, decision, policies:[{name,decision,reason}], expected, met}`; `decision` is the strictest any registered policy returned.
265
+ - `policies author "<intent>" [--kind regex|jev|both]` — the assistant authors a vetted policy grounded on your org's events (with coverage). Draft only — nothing is published. `--kind jev` asks for Jev checks, `--kind both` for JavaScript plus its checks; default regex.
266
+ - `policies backtest [FILE_OR_ID] [--kind regex|jev|both] [--semantic checks.json] [--hours N] [--agent-id A] [--env E] [--run] [--sample N]` — replay a policy against calls your agents already made. A local `.mjs` (or `@path`, `-`) or a published **regex** id is replayed module-only, as always. A published `jev`/`both` id, or `--semantic` (alone = `jev`, with a source file = `both`), runs the every-kind backtest: by default a free **estimate**; `--run` actually asks Jev about up to `--sample` (≤50) stored calls and **spends the org's Jev allowance** — confirm with the user first. `--hours` defaults to 168 for jev/both. Needs `policies:write` and `events:read`.
267
+ - `policies candidacy --issue <issue-id>` — "could a policy prevent this issue?"; read-only verdict with a suggested intent.
233
268
  - `policies compose "<description>" [--out FILE] [--publish ID]` — the assistant drafts policy source from plain English. Prints it and stops by default: a generated policy that deploys itself is one nobody read. `--publish` still syntax-checks first. Needs `policies:write` for BOTH the draft and the publish — `POST /api/agent/compose-policy` is `withAuth("policies:write")`; `agent:use` gates the assistant's other routes and is not checked on this one. The composer has a **30s server-side limit** — a long or vague description simply does not finish, and raising `--timeout` does not help because the cut is not client-side. Retry with something shorter and more specific.
234
269
  - `policies delete <id> [-y]` — archives. **A machine already carrying the policy keeps enforcing it** until redeployed; `disable` is what stops enforcement everywhere.
235
270
 
236
271
  ### fleet
237
272
  - `fleet list` — `machine · label · pol · intended · applied · seen · events · state`. `intended` is the generation deployed, `applied` what the machine last collected (they differ until it polls), and `seen` how long since it last reported anything — a machine can be in sync and dead, or alive and behind, which are different problems. `state` reads `N errors` when the machine reported policies it could not apply. JSON `{machines, deployments}` with raw epoch-ms timestamps plus the computed `drifted`; a machine carries `policyErrors`/`policyErrorsAt` and `jevMode` when the server has them.
238
- - `fleet show <machine>` — the set the machine is told to run, **and whether it has collected it**. Reads both the deployment and the machine record, so it reports `not yet collected` / `machine is on #N` / `collected` alongside who deployed it, when, and last-seen. A machine can be told to run a policy it has never picked up; the policy list alone cannot tell you which. Also the **Jev mode** FailproofAI Cloud sets on it (`local` when none) and the **policy errors** the machine last reported — `[{id, version, kind: regex|jev|both|daemon, message}]`: a policy that did not load, `jev_unconfigured` (a Jev mode, and the machine's key does not carry Jev), `transcripts_disabled` (a Jev mode on a machine connected with `--no-transcripts`, which never asks), `jev_budget: dropped <name>` (an installed pack's check FailproofAI Cloud left out of a request for the question budget). Whatever is listed there is not enforcing. JSON `{machine, deployment}` with raw timestamps and both label fields; `deployment: null` when nothing is deployed.
239
- - `fleet deploy <machine> [--add REF]… [--remove ID]… [--set REF]… [--jev-mode off|observe|enforce|local] [--create] [-y]`
273
+ - `fleet show <machine>` — the set the machine is told to run, **and whether it has collected it**. Reads both the deployment and the machine record, so it reports `not yet collected` / `machine is on #N` / `collected` alongside who deployed it, when, and last-seen. A machine can be told to run a policy it has never picked up; the policy list alone cannot tell you which. Also the **Jev mode** FailproofAI Cloud derived for it from its policies (`local` when none) and the **policy errors** the machine last reported — `[{id, version, kind: regex|jev|both|daemon, message}]`: a policy that did not load, `jev_unconfigured` (a Jev mode, and the machine's key does not carry Jev), `transcripts_disabled` (a Jev mode on a machine connected with `--no-transcripts`, which never asks), `jev_budget: dropped <name>` (an installed pack's check FailproofAI Cloud left out of a request for the question budget). Whatever is listed there is not enforcing. JSON `{machine, deployment}` with raw timestamps and both label fields; `deployment: null` when nothing is deployed.
274
+ - `fleet deploy <machine> [--add REF]… [--remove ID]… [--set REF]… [--target POLICY=INTEGRATION[/agt_ID]]… [--all-agents POLICY]… [--create] [-y]`
240
275
 
241
276
  **A deploy REPLACES the whole set.** The endpoint takes the full list and does not merge. `--add`/`--remove` are a read-modify-write: the CLI reads the current set, applies the delta, prints the complete result, writes that. `--set` replaces everything and is refused alongside `--add`/`--remove`.
242
277
 
243
- REF is `id`, `id@version`, `id:effect`, or `id@version:effect`. Effect is `enforce` (default) or `observe`. A bare `--add` of an already-deployed policy **keeps its pinned version** — pass `id@version` to move it. Every kind deploys the same way (a `both` policy's JavaScript and its checks go together); the effect applies to JavaScript only, so `observe` on a `jev` policy is refused (**exit 2**) — watch Jev through the mode instead — and an `observe` `both` policy sends only its (observed) JavaScript: its Jev checks are not asked while it is observed.
278
+ REF is `id`, `id@version`, `id:effect`, or `id@version:effect`. Effect is `enforce` (default) or `observe`. A bare `--add` of an already-deployed policy **keeps its pinned version** — pass `id@version` to move it. Every kind deploys the same way (a `both` policy's JavaScript and its checks go together), and `observe` applies to every kind: a `jev` policy's checks, or both halves of a `both` policy, are asked and recorded and decide nothing.
279
+
280
+ There is no Jev mode to set: FailproofAI Cloud turns Jev on for a machine while a `jev` or `both` policy is deployed to it, and off when none is. Jev checks run on FailproofAI Cloud; nothing is installed on the machine. The machine sends each checked tool call of an agent such a policy targets to FailproofAI Cloud on its Cloud Jev credential; without one it reports `jev_unconfigured`, and connected with `--no-transcripts` it never asks and reports `transcripts_disabled`.
244
281
 
245
- `--jev-mode` sets the machine's Jev mode from FailproofAI Cloud and **overrides the machine's own, a local `off` included**: `observe` asks Jev and logs it while the regex policies decide; `enforce` lets Jev's checks **block** calls (every `jev` policy's deny checks) as well as clear the regex verdicts they review; `off` stops Jev there; `local` hands the choice back to the machine. The mode is the **machine's**: it also governs the checks of every pack installed there. Omitted, it is left as it is (the request carries no `jevMode`). `--jev-mode` with no change to the set changes **only the mode**, through its own route (like `fleet jev-mode`), so disabled policies' assignments and any concurrent edit are untouched; the plan shows `jev mode <from> → <to>` and the JSON adds `jevModeOnly: true`. On a machine with no deployment yet, it deploys the (empty) set with the mode. Jev checks run on FailproofAI Cloud; nothing is installed on the machine. Under `observe`/`enforce` the machine sends each checked tool call to FailproofAI Cloud on its Cloud Jev credential (its `jev.json` is not used); without one it reports `jev_unconfigured`, and connected with `--no-transcripts` it never asks and reports `transcripts_disabled`.
282
+ **Agent targets.** By default an assignment covers every agent on the machine. `--target POLICY=INTEGRATION` scopes it to one integration (e.g. `no-prod-db=claude`), `--target POLICY=INTEGRATION/agt_ID` to one agent profile from `fleet show`'s roster; repeat `--target` for the same policy to OR several selectors. `--all-agents POLICY` clears a policy's scope back to every agent. The policy must be in the resulting set (add it in the same command if needed). Targets ride along in the plan, `fleet show`, `history`, `rollback` and the JSON.
246
283
 
247
284
  Deploying to an id that has never checked in is refused (a typo would mint a machine); `--create` allows it for pre-staging.
248
285
 
@@ -252,10 +289,9 @@ Cloud-managed enforcement, split the way the dashboard splits it: `policies` wri
252
289
 
253
290
  **Exit codes.** A malformed ref (`bad ref!!`, `id:banana`, empty), or `--set` combined with `--add`/`--remove`, is a usage error → **exit 2**, like every other bad flag value. A ref that parses but names something that does not exist (`--add ghost-policy`, an unpublished `@version`) is **exit 1**; an unknown machine is **exit 6**. Branch on these rather than on the message.
254
291
 
255
- JSON `{plan:{result,added,removed,changed,unchanged,noop[,jevMode:{from,to,changed}]}, deployment, applied}` — the plan is included so a harness does not recompute the diff.
256
- - `fleet jev-mode <machine>… <mode>` · `fleet jev-mode --all <mode> [-y]` — set the Jev mode FailproofAI Cloud gives machines (`off|observe|enforce|local`) and **nothing else**: the policy set is never read back or rewritten. A machine already on the mode is skipped; `--all` covers every machine with a deployment and skips the rest; a named machine with no deployment is refused before anything is written (`fleet deploy <machine> --jev-mode <mode>` gives it its first). Each change is a new generation in `fleet history`. One machine's failure does not stop the others; the exit code is 1 and the JSON row carries `error`. A bad mode, or `--all` with machine ids, is **exit 2**. JSON `{mode, applied, machines:[{machineId, from, to, changed, deployment?, error?}]}`.
292
+ JSON `{plan:{result,added,removed,changed,unchanged,noop}, deployment, applied}` — the plan is included so a harness does not recompute the diff.
257
293
  - `fleet diff [machine]` — intent vs delivery per machine, with a `drifted` flag. A machine id nobody has reported under is refused (exit 6), not rendered as an empty fleet.
258
- - `fleet history <machine>` · `fleet rollback <machine> <generation> [-y]` — rollback mints a NEW generation carrying the old set; history stays append-only. The `change` column uses the deploy plan's vocabulary: `+` added, `-` removed, `~` same policy at a different version or effect (an enforce → observe flip is a policy that stopped blocking, so it is never "no change"), and `~ jev <from>→<to>` for a Jev mode change. The `jev` column is the mode FailproofAI Cloud set with each generation (`local` = none). **A rollback restores that generation's Jev mode too**, `local` included: the prompt and the result say `jev mode <now> → <then>`, and the JSON adds `jevModeBefore`.
294
+ - `fleet history <machine>` · `fleet rollback <machine> <generation> [-y]` — rollback mints a NEW generation carrying the old set; history stays append-only. The `change` column uses the deploy plan's vocabulary: `+` added, `-` removed, `~` same policy at a different version or effect (an enforce → observe flip is a policy that stopped blocking, so it is never "no change"), and `~ jev <from>→<to>` for a Jev mode change. The `jev` column is the mode FailproofAI Cloud had with each generation (`local` = none); a rollback's prompt and result say `jev mode <now> → <then>` when it differs, and the JSON adds `jevModeBefore`.
259
295
  - `fleet rename <machine> "<label>"` — a human label; the id never changes. The server stores it as an override beside the machine's self-asserted label. An empty label **clears** the override (the machine falls back to its own label, else its id) and the CLI says so rather than reporting a rename to nothing. A machine that has never checked in cannot be renamed → exit 6.
260
296
 
261
297
  ### guardrails
@@ -263,3 +299,118 @@ Cloud-managed enforcement, split the way the dashboard splits it: `policies` wri
263
299
  - `guardrails timeline [--since …] [--machine ID]` — one row per time bucket: a bar scaled to the busiest bucket with the blocked share in red, plus total / denied / instructed counts. Answers *when* enforcement bit, which the summary's sparkline only sketches.
264
300
  - A `(no policy)` row is **normal**: most evaluations are allows nothing objected to, and the row keeps the denominator visible.
265
301
  - Coverage comes from the control plane, decision counts from reported telemetry — a machine can be deployed-to and silent, or reporting and undeployed.
302
+
303
+ ## Author an evaluator
304
+
305
+ Every invocation accepts global `--json` **before** the command. `evals` reads
306
+ results; `evaluators` authors definitions. Code is one restricted Python expression.
307
+ Judge/Jev use JSON envelopes inside `evaluator_source`. Never execute downloaded
308
+ or model-authored source locally merely to inspect it.
309
+
310
+ | Command | Flags / behavior |
311
+ | --- | --- |
312
+ | `evaluators list` | `--key K`, `--all` (include disabled versions) |
313
+ | `evaluators show K[@V]` | full source; specify version when ambiguous |
314
+ | `evaluators create` | `--key K --name N`, optional `--version V` (default `1`), repeated `--label`, `--condition EXPR\|@file`, exactly one source below, repeated `--dry-run-on SESSION`, `--disabled`, explicit `--force` to override failed previews |
315
+ | `evaluators deploy K` | same sources/metadata, optional `--version`; numeric versions auto-increment; keeps the previous version's `--condition`/`--label` unless given; creates first, then disables predecessors; `--backfill 7d` (1–90d, any kind — judge/Jev spend model budget); `--force` to override failed previews |
316
+ | `evaluators draft "intent"` | session only; `--kind code\|judge\|jev`, `--out spec.json` (refuses to overwrite) |
317
+ | `evaluators dry-run` | source flags or `--file`; repeated `--session` (max 10), none = compile only; judge refused, Jev spends budget |
318
+ | `evaluators enable\|disable K[@V]` | toggle definition |
319
+ | `evaluators label K[@V]` | repeated `--add` / `--remove` |
320
+ | `evaluators instances\|schema\|jobs` | managed instances, event schema profile, jobs |
321
+ | `evaluators backfill` | `--from T --to T`, optional `--key K`, `--dry-run`; increasing range ≤90 days; code, judge and Jev; queues only missing (session, evaluator) pairs; `--dry-run` counts them first |
322
+
323
+ Sources:
324
+
325
+ - Code: `--code path.py` (or `-` for stdin), `--result-kind score|metric|assertion`,
326
+ optional `--timeout S` (0.001–3600 seconds).
327
+ - Judge: `--judge --criteria TEXT`, optional repeated `--step TEXT`, `--threshold X`.
328
+ Steps must describe continuous grading, not “score 0/1”.
329
+ - Jev binary: `--jev noul --instructions TEXT --true TEXT --false TEXT`, optional threshold.
330
+ - Jev rubric: `--jev score --instructions TEXT --level Worst --level Middle --level Best`.
331
+ 3–5 distinct, case-insensitive levels, **worst first**.
332
+ - `--file spec.json`: the API body below; do not combine with discrete spec flags.
333
+ `deploy KEY --file spec.json --version 2` may override the version.
334
+
335
+ Spec file (exact API fields; no `id`, `enabled`, `kind` or draft `reasoning`):
336
+
337
+ ```json
338
+ {
339
+ "eval_key": "error_free",
340
+ "display_name": "Error free",
341
+ "eval_version": "1",
342
+ "result_kind": "score",
343
+ "labels": ["reliability"],
344
+ "condition_source": null,
345
+ "evaluator_source": "EvalResult(score=Score(1.0 if session.count(\"error\") == 0 else 0.0), reasoning=\"Error-free session\")",
346
+ "timeout_seconds": 5
347
+ }
348
+ ```
349
+
350
+ Judge source string: `{"kind":"judge","criteria":"Grade relevance","threshold":0.7,"steps":["Assess specificity on a continuous scale"]}`.
351
+ Jev source string: `{"kind":"jev","type":"noul","instructions":"Was the request resolved?","criteria":{"true":"Resolved","false":"Unresolved"},"threshold":0.8}`.
352
+ Judge/Jev require `result_kind: "score"`; thresholds are 0–1 or null.
353
+
354
+ Code, judge and Jev end to end:
355
+
356
+ ```bash
357
+ fp --json evaluators draft "Measure error-free sessions with code" --kind code --out error-free.json
358
+ # Read the draft's eval_key, review its source, then create.
359
+ fp --json evaluators create --file error-free.json --dry-run-on run-001
360
+ fp --json evaluators dry-run --file error-free.json --session run-001
361
+ fp --json evaluators deploy error_free --file error-free.json --version 2
362
+
363
+ fp --json evaluators create --key relevance --name Relevance --judge --criteria "Grade relevance" --threshold 0.7
364
+ fp --json evaluators deploy relevance --version 2 --judge --criteria "Grade relevance and completeness" --threshold 0.8
365
+
366
+ fp --json evaluators create --key resolution --name Resolution --jev noul --instructions "Was the request resolved?" --true "Resolved" --false "Unresolved"
367
+ fp --json evaluators dry-run --jev noul --instructions "Was the request resolved?" --true "Resolved" --false "Unresolved" --session run-001
368
+ fp --json evaluators deploy resolution --version 2 --jev score --instructions "Grade resolution quality" --level "Unresolved" --level "Partly resolved" --level "Fully resolved"
369
+ fp --json sessions re-evaluate run-001
370
+ fp --json sessions history run-001
371
+ fp --json evaluators list --all
372
+ ```
373
+
374
+ Check draft keys before copying these examples. Human output shows each preview's
375
+ score/reasoning/error before writing. A failed `--dry-run-on` prevents creation
376
+ unless `--force` is explicitly authorized. Deploy's positional key may supply a
377
+ missing `eval_key` in a spec file. A failed predecessor disable leaves the new version published: inspect
378
+ `list --all` and recover with explicit `disable KEY@VERSION`, not another create.
379
+ API 409 can mean no enabled managed instance or an existing version; 422 can mean
380
+ the org has 100 enabled keys. Read the error, do not rename/retry silently.
381
+
382
+ ## Cloud dashboard parity
383
+
384
+ Unknown-route 404s exit 6 with “not available on this FailproofAI Cloud yet”.
385
+ Missing-record 404s also exit 6 but preserve the server's record-not-found message;
386
+ an empty response on a record-scoped request identifies the missing record path.
387
+ Session-only commands exit 2 before HTTP in key mode.
388
+ Human output uses mint/pink open screens and full ids; legacy `--full-ids`
389
+ remains accepted. Exports refuse to overwrite existing files.
390
+
391
+ Use global `--json` for API objects or `--out` to save a session/query JSON
392
+ export. Without either, human mode renders a readable view rather than raw
393
+ structures. CSV query export remains pipeable CSV.
394
+
395
+ | Commands | Options / notes |
396
+ | --- | --- |
397
+ | `dashboards list\|show ID\|create\|update ID\|delete ID` | create `--name`, `--description`, optional `--file` definition; update selected fields |
398
+ | `dashboards tiles ID list\|add\|update TILE\|remove TILE\|layout` | add `--query ID --chart line\|area\|bar\|stacked_bar\|pie\|kpi\|table`, `--title`; update supports same flags or `--file`; layout `--file` with `{tiles:[{id,pos_x,pos_y,pos_w,pos_h}]}` |
399
+ | `sessions show\|export\|history\|re-evaluate ID` | export `--out`; show includes overview + event timeline |
400
+ | `sessions import FILE...` | `--format auto\|failproofai\|claude\|codex`, `--env`, `--dry-run`; see [sessions](#sessions) |
401
+ | `events latency` | `--since` |
402
+ | `sentiment summary\|messages\|sessions\|session ID` | list reads accept `--since`; messages/sessions `--limit`; messages `--session-id` |
403
+ | `query compose "question"` | session; `--run` |
404
+ | `query export [ID]` | or `--sql TEXT\|@file`; `--format csv\|json`, `--out`; with `--json`, CSV is `{format,content}` |
405
+ | `alerts recipients` / `alerts issues ID` | issues: optional `--create --title --summary` or `--create --file` |
406
+ | `audits contracts list\|show ID\|create\|update ID` | `--agent-id`, `--body TEXT\|@file`, or `--file` API JSON; update `--enabled/--disabled` |
407
+ | `policies author "intent" [--kind]`\|`backtest [FILE_OR_ID] [--kind --semantic --hours --agent-id --env --run --sample]`\|`candidacy --issue ID` | session; drafts/replays only, never auto-publishes; see [policies](#policies) |
408
+ | `issues facets` | inbox filter values; see [issues](#issues) |
409
+ | `agent ask "question"` / `agent brief` | session; ask renders artifacts and prompts for approval on a terminal; scripts/JSON decline unless `--approve`; brief `--range 24h\|7d` |
410
+ | `orgs create --name N [--slug S]` | session; omitted slug derives from name; never auto-switches |
411
+ | `roles list\|show NAME\|create\|update NAME\|delete NAME` | permission sets; create `--name --permission`; update `--permission` replaces or `--add/--remove` merges; `--description`, `--file`; builtins immutable |
412
+ | `users delete ID` / `users defaults` | deletion is by id, not email |
413
+ | `usage windows` / `plan` / `plan claim OFFER` | usage windows is API-key only; plan (offers + trial) and claim are session-only — each refuses the other mode before HTTP |
414
+ | `settings context-windows list\|set MODEL TOKENS\|delete MODEL` | tokens 0–1000000; model names may contain `/` |
415
+ | `otel status\|enable\|disable` | Cloud org switch `otel.ingest_enabled`, not local collector configuration |
416
+ | `slack status\|disconnect` | session only |