failproofai 1.0.12-beta.2 → 1.0.13-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (374) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +13 -13
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js +2 -1
  8. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.rsc +2 -2
  12. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  13. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +2 -2
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  16. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page.js +4 -3
  18. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  21. package/.next/standalone/.next/server/app/_not-found.rsc +3 -3
  22. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/invite/route.js +6 -5
  26. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/audit/run/route.js +27 -26
  28. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/audit/status/route.js +4 -3
  30. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +6 -5
  32. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +6 -5
  34. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/auth/logout/route.js +6 -5
  36. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/auth/status/route.js +6 -5
  38. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +4 -3
  40. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  42. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  43. package/.next/standalone/.next/server/app/audit/page.js +7 -6
  44. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  45. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  46. package/.next/standalone/.next/server/app/index.html +1 -1
  47. package/.next/standalone/.next/server/app/index.rsc +3 -3
  48. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  49. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
  50. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  51. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  52. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  53. package/.next/standalone/.next/server/app/page.js +6 -5
  54. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  57. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  58. package/.next/standalone/.next/server/app/policies/page.js +5 -4
  59. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  62. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  63. package/.next/standalone/.next/server/app/project/[name]/page.js +21 -20
  64. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
  67. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  68. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  69. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +10 -9
  70. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  73. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  74. package/.next/standalone/.next/server/app/projects/page.js +7 -6
  75. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
  78. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
  79. package/.next/standalone/.next/server/app/settings/page.js +6 -5
  80. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  82. package/.next/standalone/.next/server/chunks/{[externals]__0vt9i6fqinjne._.js → [externals]__1h83uo-b1b6-2._.js} +1 -1
  83. package/.next/standalone/.next/server/chunks/[externals]__214wn4wh2x79y._.js +3 -0
  84. package/.next/standalone/.next/server/chunks/{[externals]__1rlxpymm37wel._.js → [root-of-the-server]__031qp1lkow_kc._.js} +2 -2
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__038kwryp970nh._.js +3 -0
  86. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0_hsnj_a2mvl_._.js → [root-of-the-server]__03s1za0hn71yp._.js} +2 -2
  87. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0wg9dk8x8bnau._.js → [root-of-the-server]__07a0sa6fuw5_b._.js} +2 -2
  88. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08atcie7jzswm._.js +3 -0
  89. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfudh2_4f._.js +1 -1
  90. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0car70pylmvor._.js +3 -0
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0spt0kv8azrpl._.js +1 -1
  92. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__12kq3x-h7t7i1._.js → [root-of-the-server]__0yvyp5b7jmlc4._.js} +2 -2
  93. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__02vous7mpi2xm._.js → [root-of-the-server]__145vo_drnuvas._.js} +2 -2
  94. package/.next/standalone/.next/server/chunks/{[externals]__0h0p9dmv_e7r7._.js → [root-of-the-server]__1a2d0ewycsp6k._.js} +2 -2
  95. package/.next/standalone/.next/server/chunks/{[externals]__1_407huhlmj1m._.js → [root-of-the-server]__1am_1tz0o0aqz._.js} +2 -2
  96. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__03i5o4a840guz._.js → [root-of-the-server]__1gxfzuvpyw30j._.js} +1 -1
  97. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1j6kfp0vzu5rw._.js +3 -0
  98. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1l0ayum_hqqsw._.js +3 -0
  99. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1lh8c0mmhdrbj._.js +3 -0
  100. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1o9rznwc0w7og._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0f_4g-vazrvxv._.js → [root-of-the-server]__1o_622x0fglpr._.js} +1 -1
  102. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1oclamblhzhrf._.js +68 -0
  103. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1v1-l-83czzsr._.js +63 -0
  104. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1a5zkndjwlc13._.js → [root-of-the-server]__1wwi53kkqhnfi._.js} +1 -1
  105. package/.next/standalone/.next/server/chunks/{_1y590mjzpkbos._.js → _02sa8fcu9_9xo._.js} +2 -2
  106. package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/_1-2owkp-1_987._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/_13ltj8a9z92o8._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/_15k37au70vjvg._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/_18rfu4__wjhwb._.js +1 -1
  112. package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +2 -2
  113. package/.next/standalone/.next/server/chunks/_1fz8m31sndkcu._.js +1 -1
  114. package/.next/standalone/.next/server/chunks/_1ogwigfb0163w._.js +1 -1
  115. package/.next/standalone/.next/server/chunks/_1vslkoe35wok6._.js +1 -1
  116. package/.next/standalone/.next/server/chunks/node_modules_@opentelemetry_api_build_esm_index_0oo58a7rymoxh.js +3 -0
  117. package/.next/standalone/.next/server/chunks/node_modules_@opentelemetry_api_build_esm_index_1jp9ij0_ddtgk.js +3 -0
  118. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oigsgz07._.js +2 -2
  119. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p77cu37y._.js +2 -2
  120. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
  121. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ffu2-38y03ic._.js → [root-of-the-server]__021vebe-4il8s._.js} +1 -1
  122. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__075uro8t92s0_._.js +14 -0
  123. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
  124. package/.next/standalone/.next/server/chunks/ssr/{[externals]__12qr51qgrrt6o._.js → [root-of-the-server]__097i34ct1o88x._.js} +2 -2
  125. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0alpzjn3450sr._.js +3 -0
  126. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0aup10z2o8zc1._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bioghlkjf7s7._.js +3 -0
  129. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01j58mdcdw0vn._.js → [root-of-the-server]__0ed1zh4scn7-k._.js} +1 -1
  130. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0naevg4bcoh54._.js → [root-of-the-server]__0evgy902m9h5e._.js} +2 -2
  131. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
  132. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__00l2u6j86cb8y._.js → [root-of-the-server]__0mhtkwwx1pxcq._.js} +2 -2
  133. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0nhm28v58ty9z._.js +3 -0
  134. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
  135. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vse4qi496ol-._.js +3 -0
  136. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__17r4zrwanhp6r._.js → [root-of-the-server]__0yb3u36xjy3b9._.js} +1 -1
  137. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0g8b0kyorya-t._.js → [root-of-the-server]__0ywj2u6ovfm_5._.js} +1 -1
  138. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0zn1d4blhd3bu._.js → [root-of-the-server]__10v5cyxvj64j4._.js} +1 -1
  140. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
  141. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
  142. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__190xwrr5zrfi3._.js +3 -0
  143. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
  144. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1vx7o8ukefudh._.js → [root-of-the-server]__1guwlpkyurdn9._.js} +1 -1
  145. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1k96jctukf65_._.js +3 -0
  146. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
  147. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1sj-wn2jp6va5._.js +3 -0
  148. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vofkb2oq7p7e._.js +1 -1
  149. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1s2-ck3k3rsoo._.js → [root-of-the-server]__20dt376-socef._.js} +1 -1
  150. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1lnfv02ucky7m._.js → [root-of-the-server]__2158020r_amn9._.js} +1 -1
  151. package/.next/standalone/.next/server/chunks/ssr/{_1fw0_nzkae5ao._.js → _0bc4f4quq6w47._.js} +2 -2
  152. package/.next/standalone/.next/server/chunks/ssr/_0bseae9u7g98r._.js +1 -1
  153. package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
  154. package/.next/standalone/.next/server/chunks/ssr/_0mouhaflye1ro._.js +1 -1
  155. package/.next/standalone/.next/server/chunks/ssr/_0ouu886szh6yj._.js +1 -1
  156. package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
  157. package/.next/standalone/.next/server/chunks/ssr/_1_ozgifqv1ssi._.js +1 -1
  158. package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
  159. package/.next/standalone/.next/server/chunks/ssr/_20hn4gn87nsjc._.js +1 -1
  160. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
  161. package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
  162. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
  163. package/.next/standalone/.next/server/chunks/ssr/app_components_project-list_tsx_1ke6anr0vt64h._.js +1 -1
  164. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
  165. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +1 -1
  166. package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
  167. package/.next/standalone/.next/server/chunks/ssr/{node_modules_09s4n108bqreq._.js → node_modules_0ptcnmeaxvd_a._.js} +22 -2
  168. package/.next/standalone/.next/server/chunks/ssr/node_modules_@opentelemetry_api_build_esm_index_0ntwr8lzj6p2i.js +3 -0
  169. package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_1fv03uigni8s5.js → node_modules_html-to-image_es_index_1jwgv0pf-gy96.js} +1 -1
  170. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0bz67659f5z-3._.js +32 -0
  171. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0janj0i6dqko7._.js +3 -3
  172. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0ocrceo0c9psx._.js +32 -0
  173. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1alv566ojmz5j._.js +32 -0
  174. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1khq67j4vo9y4._.js +3 -0
  175. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_shared_lib_0ftnv26hg1lry._.js +3 -0
  176. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dagmbznysrc2._.js +1 -1
  177. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuznb72p7z._.js +2 -2
  178. package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
  179. package/.next/standalone/.next/server/middleware-build-manifest.js +13 -13
  180. package/.next/standalone/.next/server/middleware.js +2 -2
  181. package/.next/standalone/.next/server/pages/404.html +1 -1
  182. package/.next/standalone/.next/server/pages/500.html +1 -1
  183. package/.next/standalone/.next/server/preview-props.json +3 -3
  184. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  185. package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
  186. package/.next/standalone/.next/static/chunks/0cbom4-ijx_a_.js +1 -0
  187. package/.next/standalone/.next/static/chunks/0u5weo5jdn2s8.js +1 -0
  188. package/.next/standalone/.next/static/chunks/{1c_jf6g5wnslk.js → 18-icoqze51kl.js} +1 -1
  189. package/.next/standalone/.next/static/chunks/2d-u90dt4-8rd.js +6 -0
  190. package/.next/standalone/.next/static/chunks/2n-bzb7pxe7hu.js +1 -0
  191. package/.next/standalone/.next/static/chunks/{2o6d37j425uci.js → 2zc7lg-jq353g.js} +1 -1
  192. package/.next/standalone/.next/static/chunks/{0tbm3vjm62h-2.js → 33djjf12bhcsv.js} +1 -1
  193. package/.next/standalone/.next/static/chunks/{42xptz88mtq3x.js → 38u_i3j5funpi.js} +1 -1
  194. package/.next/standalone/.next/static/chunks/{20py8k1gd_i1m.js → 3symuj7t4js-c.js} +1 -1
  195. package/.next/standalone/.next/static/chunks/{0ay__-d2h1xb5.js → 3vzut6zpdrvtx.js} +1 -1
  196. package/.next/standalone/.next/static/chunks/{063al_q720fkj.js → 3xgxl1s_in776.js} +2 -2
  197. package/.next/standalone/SECURITY.md +20 -4
  198. package/.next/standalone/fp-cloud-cli/CHANGELOG.md +34 -1
  199. package/.next/standalone/fp-cloud-cli/README.md +120 -0
  200. package/.next/standalone/fp-cloud-cli/fp_cli/_version.py +1 -1
  201. package/.next/standalone/fp-cloud-cli/fp_cli/app.py +15 -1
  202. package/.next/standalone/fp-cloud-cli/fp_cli/client.py +198 -7
  203. package/.next/standalone/fp-cloud-cli/fp_cli/cloud_output.py +523 -0
  204. package/.next/standalone/fp-cloud-cli/fp_cli/commands/_cloud.py +45 -0
  205. package/.next/standalone/fp-cloud-cli/fp_cli/commands/_write.py +3 -1
  206. package/.next/standalone/fp-cloud-cli/fp_cli/commands/account_cmds.py +171 -0
  207. package/.next/standalone/fp-cloud-cli/fp_cli/commands/agent_cmds.py +80 -7
  208. package/.next/standalone/fp-cloud-cli/fp_cli/commands/alerts_cmds.py +23 -0
  209. package/.next/standalone/fp-cloud-cli/fp_cli/commands/audits_cmds.py +2 -0
  210. package/.next/standalone/fp-cloud-cli/fp_cli/commands/contracts_cmds.py +67 -0
  211. package/.next/standalone/fp-cloud-cli/fp_cli/commands/dashboards_cmds.py +159 -0
  212. package/.next/standalone/fp-cloud-cli/fp_cli/commands/evaluators_cmds.py +380 -0
  213. package/.next/standalone/fp-cloud-cli/fp_cli/commands/events_cmds.py +14 -1
  214. package/.next/standalone/fp-cloud-cli/fp_cli/commands/incidents_cmds.py +82 -6
  215. package/.next/standalone/fp-cloud-cli/fp_cli/commands/list_cmds.py +4 -1
  216. package/.next/standalone/fp-cloud-cli/fp_cli/commands/orgs_cmds.py +17 -0
  217. package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +143 -1
  218. package/.next/standalone/fp-cloud-cli/fp_cli/commands/queries_cmds.py +70 -0
  219. package/.next/standalone/fp-cloud-cli/fp_cli/commands/sentiment_cmds.py +49 -0
  220. package/.next/standalone/fp-cloud-cli/fp_cli/commands/sessions_cmds.py +95 -1
  221. package/.next/standalone/fp-cloud-cli/fp_cli/commands/settings_cmds.py +2 -0
  222. package/.next/standalone/fp-cloud-cli/fp_cli/commands/usage_cmds.py +21 -1
  223. package/.next/standalone/fp-cloud-cli/fp_cli/commands/users_cmds.py +14 -0
  224. package/.next/standalone/fp-cloud-cli/fp_cli/errors.py +3 -0
  225. package/.next/standalone/fp-cloud-cli/fp_cli/evaluator_spec.py +266 -0
  226. package/.next/standalone/fp-cloud-cli/fp_cli/output.py +187 -81
  227. package/.next/standalone/fp-cloud-cli/fp_cli/theme.py +21 -24
  228. package/.next/standalone/fp-cloud-cli/skill/SKILL.md +124 -23
  229. package/.next/standalone/fp-cloud-cli/skill/agents/openai.yaml +2 -1
  230. package/.next/standalone/fp-cloud-cli/skill/references/commands.md +168 -16
  231. package/.next/standalone/fp-cloud-cli/tests/fake_cloud_smoke.py +312 -0
  232. package/.next/standalone/fp-cloud-cli/tests/test_cloud_account.py +125 -0
  233. package/.next/standalone/fp-cloud-cli/tests/test_cloud_agent.py +253 -0
  234. package/.next/standalone/fp-cloud-cli/tests/test_cloud_human_views.py +287 -0
  235. package/.next/standalone/fp-cloud-cli/tests/test_cloud_observability.py +116 -0
  236. package/.next/standalone/fp-cloud-cli/tests/test_cloud_transport.py +141 -0
  237. package/.next/standalone/fp-cloud-cli/tests/test_commands.py +3 -3
  238. package/.next/standalone/fp-cloud-cli/tests/test_dashboards_agent.py +3 -3
  239. package/.next/standalone/fp-cloud-cli/tests/test_evaluator_authoring.py +449 -0
  240. package/.next/standalone/fp-cloud-cli/tests/test_facets.py +1 -1
  241. package/.next/standalone/fp-cloud-cli/tests/test_help_table_coverage.py +15 -0
  242. package/.next/standalone/fp-cloud-cli/tests/test_operator.py +1 -1
  243. package/.next/standalone/fp-cloud-cli/tests/test_orgs.py +1 -1
  244. package/.next/standalone/fp-cloud-cli/tests/test_output.py +37 -37
  245. package/.next/standalone/fp-cloud-cli/tests/test_round4_behaviour.py +144 -0
  246. package/.next/standalone/fp-cloud-cli/tests/test_screen_language.py +80 -0
  247. package/.next/standalone/fp-cloud-cli/tests/test_session_reevaluate.py +33 -0
  248. package/.next/standalone/fp-cloud-cli/tests/test_staging_parity.py +198 -0
  249. package/.next/standalone/fp-cloud-cli/tests/test_whoami.py +1 -1
  250. package/.next/standalone/fp-cloud-cli/uv.lock +4 -4
  251. package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
  252. package/.next/standalone/node_modules/@next/env/package.json +1 -1
  253. package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
  254. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +24 -24
  255. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +26 -26
  256. package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +3 -3
  257. package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +13 -13
  258. package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
  259. package/.next/standalone/node_modules/next/dist/server/app-render/app-render.js +41 -40
  260. package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +1 -1
  261. package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-rendering-validation.js +814 -0
  262. package/.next/standalone/node_modules/next/dist/server/app-render/dynamic-rendering.js +1 -799
  263. package/.next/standalone/node_modules/next/dist/server/base-server.js +39 -5
  264. package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
  265. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
  266. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
  267. package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
  268. package/.next/standalone/node_modules/next/dist/server/lib/dedupe-fetch.js +4 -43
  269. package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch-symbol.js +13 -0
  270. package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +3 -7
  271. package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +3 -3
  272. package/.next/standalone/node_modules/next/dist/server/lib/router-utils/instrumentation-globals.external.js +77 -12
  273. package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
  274. package/.next/standalone/node_modules/next/dist/server/lib/trace/constants.js +12 -0
  275. package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +30 -14
  276. package/.next/standalone/node_modules/next/dist/server/next-server.js +10 -11
  277. package/.next/standalone/node_modules/next/dist/server/route-modules/pages/pages-handler.js +29 -23
  278. package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +85 -8
  279. package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +1 -1
  280. package/.next/standalone/node_modules/next/dist/server/web/adapter.js +124 -65
  281. package/.next/standalone/node_modules/next/dist/server/web/forward-trace-context.js +102 -0
  282. package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
  283. package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
  284. package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
  285. package/.next/standalone/node_modules/next/package.json +10 -10
  286. package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
  287. package/.next/standalone/node_modules/react/package.json +1 -1
  288. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
  289. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
  290. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +31 -27
  291. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +33 -27
  292. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +38 -30
  293. package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
  294. package/.next/standalone/node_modules/react-dom/package.json +2 -2
  295. package/.next/standalone/package.json +10 -10
  296. package/.next/standalone/sdk/python/CHANGELOG.md +8 -4
  297. package/.next/standalone/sdk/python/failproofai_sdk/evaluator/source.py +2 -2
  298. package/.next/standalone/sdk/python/pyproject.toml +2 -7
  299. package/.next/standalone/sdk/python/skill/references/frameworks.md +0 -15
  300. package/.next/standalone/sdk/python/tests/test_docs.py +1 -4
  301. package/.next/standalone/sdk/python/tests/test_evaluator_source.py +1 -1
  302. package/.next/standalone/sdk/python/tests/test_packaging.py +4 -7
  303. package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +2 -13
  304. package/.next/standalone/sdk/python/uv.lock +43 -905
  305. package/.next/standalone/sdk/typescript/CHANGELOG.md +52 -0
  306. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package-lock.json +7 -7
  307. package/.next/standalone/sdk/typescript/integration/fixtures/ai-5/package.json +2 -2
  308. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package-lock.json +7 -7
  309. package/.next/standalone/sdk/typescript/integration/fixtures/ai-6/package.json +1 -1
  310. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package-lock.json +7 -7
  311. package/.next/standalone/sdk/typescript/integration/fixtures/ai-7/package.json +1 -1
  312. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package-lock.json +4 -4
  313. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-1/package.json +1 -1
  314. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package-lock.json +4 -4
  315. package/.next/standalone/sdk/typescript/integration/fixtures/langchain-dup-core/package.json +1 -1
  316. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package-lock.json +3 -3
  317. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.11/package.json +3 -0
  318. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package-lock.json +4 -4
  319. package/.next/standalone/sdk/typescript/integration/fixtures/llamaindex-0.12/package.json +1 -1
  320. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package-lock.json +25 -25
  321. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-0/package.json +1 -1
  322. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +34 -22
  323. package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +3 -2
  324. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +10 -10
  325. package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +1 -1
  326. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/deno-npm.ts +1 -1
  327. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package-lock.json +7 -7
  328. package/.next/standalone/sdk/typescript/integration/fixtures/runtimes/package.json +1 -1
  329. package/.next/standalone/server.js +1 -1
  330. package/README.md +0 -6
  331. package/dist/cli.mjs +87 -38
  332. package/dist/worker.mjs +73 -28
  333. package/hermes-plugin/plugin.yaml +1 -1
  334. package/openclaw-plugin/daemon-client.js +254 -0
  335. package/openclaw-plugin/hooks.js +187 -0
  336. package/openclaw-plugin/index.js +17 -211
  337. package/package.json +10 -10
  338. package/scripts/sync-agent-cli-harnesses-prompt.md +26 -31
  339. package/src/hooks/agent-skill.ts +3 -0
  340. package/src/hooks/enforcement-capability.ts +1 -1
  341. package/src/hooks/fp-home.ts +1 -1
  342. package/src/hooks/handler.ts +22 -3
  343. package/src/hooks/integrations.ts +5 -2
  344. package/src/hooks/semantic/intent.ts +127 -24
  345. package/src/hooks/semantic/jev-review.ts +21 -2
  346. package/.next/standalone/.codex/hooks.json +0 -76
  347. package/.next/standalone/.cursor/hooks.json +0 -47
  348. package/.next/standalone/.factory/hooks.json +0 -112
  349. package/.next/standalone/.next/server/chunks/[externals]__1x24dzcbbq6-g._.js +0 -3
  350. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__a_je8fsn65._.js +0 -3
  351. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-oi4gdtmlo5._.js +0 -3
  352. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t9ufnv5hi2hq._.js +0 -327
  353. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1aaw59g-5uty7._.js +0 -322
  354. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hqpg6vgmfexv._.js +0 -3
  355. package/.next/standalone/.next/server/chunks/ssr/[externals]__0ilfh9mfnzsth._.js +0 -3
  356. package/.next/standalone/.next/server/chunks/ssr/[externals]__0ohnuzsaozaca._.js +0 -3
  357. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pwj2h2efe5f-._.js +0 -14
  358. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_0zuikgt2xho-v._.js +0 -271
  359. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_158jo-9mwvgad._.js +0 -291
  360. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_19r82zsxo2jj1._.js +0 -291
  361. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1dupwucoqt5qm._.js +0 -3
  362. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_shared_lib_03w27x2kh17_8._.js +0 -23
  363. package/.next/standalone/.next/static/chunks/1my3-5p47t7r-.js +0 -1
  364. package/.next/standalone/.next/static/chunks/21hckpmsc4g70.js +0 -6
  365. package/.next/standalone/.next/static/chunks/2hmex93ppj1ke.js +0 -1
  366. package/.next/standalone/.next/static/chunks/40oworn_-x12p.js +0 -1
  367. package/.next/standalone/.opencode/opencode.json +0 -4
  368. package/.next/standalone/.opencode/plugins/failproofai.mjs +0 -210
  369. package/.next/standalone/.pi/settings.json +0 -5
  370. package/.next/standalone/node_modules/react/cjs/react.development.js +0 -1330
  371. package/scripts/dev-hook.mjs +0 -333
  372. /package/.next/standalone/.next/static/{LHCtFxVG0mdvd4lsXAOFC → 1n2dyfTQb0MDajeqlipJy}/_buildManifest.js +0 -0
  373. /package/.next/standalone/.next/static/{LHCtFxVG0mdvd4lsXAOFC → 1n2dyfTQb0MDajeqlipJy}/_clientMiddlewareManifest.js +0 -0
  374. /package/.next/standalone/.next/static/{LHCtFxVG0mdvd4lsXAOFC → 1n2dyfTQb0MDajeqlipJy}/_ssgManifest.js +0 -0
@@ -56,8 +56,9 @@ The gate above scans the lockfiles it is *given* (the `--lockfile` list in the
56
56
  workflow). GitHub's dependency graph reads **every** lockfile in the repository, so
57
57
  Dependabot alerts cover trees the gate does not — in particular the TypeScript SDK's
58
58
  integration fixtures, `sdk/typescript/integration/fixtures/*/package-lock.json`.
59
- Those are not in the scanner's list and are not a Dependabot *update* ecosystem in
60
- [`.github/dependabot.yml`](.github/dependabot.yml) either, so an alert is the only
59
+ Those are not in the scanner's list and get no Dependabot *version* updates either
60
+ (the four floor fixtures have entries in [`.github/dependabot.yml`](.github/dependabot.yml),
61
+ but only to restrain its security updates; see below), so an alert is the only
61
62
  thing that will ever mention them. Treat the alert list as authoritative for those
62
63
  paths, and see *Triaging a Dependabot alert in an integration fixture* below for how
63
64
  to resolve one.
@@ -118,17 +119,32 @@ That splits an alert in one of these lockfiles into two cases:
118
119
  the scanner does not read these lockfiles, so an `[[IgnoredVulns]]` entry for one
119
120
  would filter nothing and be reported as an unused ignore.
120
121
 
122
+ Dependabot's own security updates know neither case. Given a case-2 advisory they
123
+ reach the fix by moving the framework, which is how #838, #931 and #935 happened
124
+ (#935 opened three minutes after #934 put the pins back). So each floor fixture —
125
+ `ai-4`, `langchain-0.3`, `llamaindex-0.11`, `mastra-0` — has a security-updates-only
126
+ entry in [`.github/dependabot.yml`](.github/dependabot.yml)
127
+ (`open-pull-requests-limit: 0`) whose `ignore` ranges hold its framework on its
128
+ line, and zod on 3 where that framework requires it; a fix that stays on the line
129
+ still arrives. A new floor fixture needs its own entry, and
130
+ `__tests__/ci/ts-sdk-fixture-pins.test.ts` fails without one. A Dependabot PR that
131
+ moves a pin anyway fails that same test: close it rather than merge it.
132
+
121
133
  ### Accepted, with no fix available
122
134
 
123
135
  | Advisory | Package | Fixtures | Why it stays |
124
136
  |---|---|---|---|
125
137
  | [GHSA-rwvc-j5jr-mgvh](https://github.com/advisories/GHSA-rwvc-j5jr-mgvh) (low, CVSS 3.7) | `ai@4.3.19` | `ai-4`, `mastra-0` | A filetype-whitelist bypass on **file upload**. Fixed in `ai@5.0.52` — the major the `ai-4` fixture exists to stay below, and one `@mastra/core@0.24.9` cannot take either (it requires `ai@^4`). Neither fixture uploads a file or exposes an upload surface; each runs one scripted agent against an in-process model. |
126
138
  | [GHSA-866g-f22w-33x8](https://github.com/advisories/GHSA-866g-f22w-33x8) (low, CVSS 4.3) | `@ai-sdk/provider-utils@2.2.8` | `ai-4`, `mastra-0` | Unbounded response-body reads in `createJsonResponseHandler` and its siblings. Fixed in `3.0.28`; `2.2.8` ships *inside* `ai@4.3.19`, which uses the v2 API, so the fix is the same blocked major as the row above. Exploiting it needs a hostile **model-provider HTTP response**; these fixtures never call one. |
139
+ | [GHSA-mrhx-c7xc-m3w5](https://github.com/advisories/GHSA-mrhx-c7xc-m3w5) (high, CVSS 7.5) | `zod@3.25.76` | `ai-4`, `langchain-0.3`, `llamaindex-0.11`; nested in `langchain-dup-core` and `mastra-0` | An array schema keeps every failing element's validation issues, uncapped, so one oversized input can exhaust memory. Fixed only in `4.6.6`: no zod 3 release carries the fix, and `3.25.76` is the newest. Each copy is held to `^3` by the release its fixture pins — `ai@4.3.19` and its `@ai-sdk/*` packages peer on `^3.23.8`, `@langchain/core@0.3.80` (in `langchain-dup-core`, the vendored provider's own copy) and `@langchain/langgraph@0.4.10` depend on `^3.25.32`, `@llamaindex/core@0.6.8` and `@llamaindex/workflow@1.1.5` need `^3.23.8`, and in `mastra-0`, `zod-from-json-schema-v3` (`zod-from-json-schema@0.0.5`, which builds zod 3 schemas for `@mastra/core` and `@mastra/mcp`) depends on `^3.24.2`. Exploiting it needs untrusted input validated against one of those schemas; each fixture validates only its own scripted tool arguments. |
127
140
 
128
- Both rows are bounded by the same facts: these are test fixtures — `"private": true`,
141
+ Every row is bounded by the same facts: these are test fixtures — `"private": true`,
129
142
  never published, installed with `--ignore-scripts`, and run only in CI against
130
143
  scripted in-process models. Re-check them whenever the supported framework floor
131
- moves; dropping `ai` 4.x from the matrix is what actually retires them.
144
+ moves. The first two rows retire once `ai` 4.x has left the matrix, which takes
145
+ `mastra-0` as well as `ai-4`, because `@mastra/core@0.24.9` requires `ai@^4`. The
146
+ zod row retires only once `ai` 4.x, LangChain 0.3, LlamaIndex 0.11 and Mastra 0.x
147
+ have all left it.
132
148
 
133
149
  ## Maintainer setup (one-time)
134
150
 
@@ -1,9 +1,32 @@
1
1
  # Changelog — `fp` CLI
2
2
 
3
- ## 0.0.2b0 — 2026-09-22
3
+ ## 0.0.3b0 — 2026-10-25
4
+
5
+ Open for the next release. `0.0.2` published on 2026-10-25 and the `bump` job
6
+ moved the version here automatically; nothing has landed against `0.0.3b0` yet.
7
+ Add entries as changes merge — this section becomes the GitHub Release body when
8
+ it ships.
9
+
10
+ ## 0.0.2 — 2026-10-25
11
+
12
+ **Stable release.** The `0.0.2b0` line the `bump` job opened after `0.0.1` is cut stable
13
+ here rather than published, because the server endpoints these commands drive are now
14
+ deployed to FailproofAI Cloud and the CLI should not trail them as a pre-release.
15
+
16
+ Nothing about the command surface changes at the cut: the entries below are the entire
17
+ diff from `0.0.1`, and the `bump` job opens `0.0.3b0` after the upload.
4
18
 
5
19
  ### Added
6
20
 
21
+ - Hosted evaluator authoring for code, LLM judge and Jev: create/deploy, AI draft specs, dry-run, labels, toggles, instances, schema, jobs and backfill.
22
+ - Dashboards and tiles; session overview/export/history/re-evaluate; latency and sentiment; query composition/export; alert recipients/issues and agent contracts.
23
+ - Policy author/backtest/candidacy, assistant artifact tables, fail-closed interactive write approvals, and agent-curated home briefs.
24
+ - Organization creation, permission-set roles, member deletion/defaults, usage windows, offers/trial, model context windows, OTEL and Slack controls.
25
+ - `fp policies backtest` covers every policy kind: a published `jev`/`both` policy, or `--semantic checks.json` (with or without a source file), runs the dashboard's every-kind backtest — a free estimate by default, `--run [--sample N]` to spend Jev allowance. New `--kind --semantic --hours --agent-id --env --run --sample`; a regex file or id still uses the module backtest.
26
+ - `fp policies author --kind regex|jev|both` asks the assistant for Jev checks or a hybrid policy.
27
+ - `fp issues list|count` take the inbox filters (`--agent-id --env --machine --source --audit-id --assignee --archived --search --since`, and `count --alert-id`); new `fp issues facets` lists the values they can take.
28
+ - `fp sessions import FILE...` imports Claude Code transcripts, Codex rollouts or event JSONL (`--format --env --dry-run`), as the dashboard's import dialog does.
29
+ - `fp list trigger_events`, `fp list eval_envs` and `fp list metric_keys`.
7
30
  - `fp fleet deploy --target POLICY=INTEGRATION[/agt_ID]` scopes a machine's assignment; repeat the flag to include multiple alternatives. `--all-agents POLICY` explicitly clears its scope. Deploy plans, show, history, rollback and JSON readback retain assignment targets.
8
31
  - `fp policies publish <id> --kind regex|jev|both [--source f.mjs] [--semantic f.json]`: a
9
32
  FailproofAI Cloud policy can carry Jev checks — `jev` (declarations only, no JavaScript) or
@@ -41,6 +64,9 @@
41
64
 
42
65
  ### Changed
43
66
 
67
+ - New Cloud API families work in key mode; unsupported session-only commands deny before HTTP and unknown-route 404s exit 6 with an availability message.
68
+ - Shared screens use the mint/pink wordmark and grey labels, without boxes/rules or shortened ids; existing JSON contracts are unchanged.
69
+ - The agent skill, command reference, README and Cloud CLI docs include end-to-end evaluator workflows. No version bump or release is performed.
44
70
  - `fp policies publish`'s refusal of Jev fields in the JavaScript now says where Jev checks go:
45
71
  the policy's own declarations, `--kind both --semantic checks.json`.
46
72
  - `fp guardrails summary` shows how many machines run Jev in each mode, reading the summary's
@@ -56,6 +82,13 @@
56
82
 
57
83
  ### Fixed
58
84
 
85
+ - Remove the unused colour-keyed permission rank, document full-id rendering, emit UTC `Z` timestamps for deploy backfills, and report approval-answer failures without a traceback while restoring the terminal (#885).
86
+ - Reject natural-language binary judge steps, distinguish unknown routes from missing records on 404, normalize standalone backfill ranges to UTC `Z`, expose all subcommands in help, and render artifact headers before titles with consistent session-only wording (#885).
87
+ - New Cloud commands use deliberate human summaries/tables and actionable empty states at 80/140 columns without raw response blobs. Evaluator previews display before writes and require explicit `--force` after failures; plan/claim deny key mode, deploy specs can omit the positional key, and older settings-route 404s degrade clearly. Existing JSON payloads stay unchanged (#885).
88
+ - `fp evaluators deploy` keeps the previous version's condition and labels unless `--condition`/`--label` change them, so a new version no longer silently widens to every session (#885).
89
+ - Evaluation backfill covers code, LLM judge and Jev evaluators, as FailproofAI Cloud now does: `fp evaluators deploy --backfill` no longer refuses judge/Jev, and both commands warn that judge/Jev backfills spend model budget instead of saying they are skipped.
90
+ - `fp usage windows` says it needs an API key (the dashboard has no session route for it) instead of reporting the route as unavailable.
91
+ - `fp issues close --help` no longer claims exit 9 for an issue that already ended: it is exit 1, as it always was, and it names `fp audits dismiss` rather than a command that does not exist.
59
92
  - `fp fleet history` keeps `gen`, `when` and `jev` visible at 80 columns (rollback needs `gen`): the policy list is shortened, then dropped, and `change` wraps first.
60
93
  - `fp fleet show` and `fp fleet history` name an exact-profile target by the profile label the machine reports (`claude/.claude-work`, with the `agt_…` id kept in `show`), falling back to the bare id.
61
94
 
@@ -211,6 +211,126 @@ These commands are **session-only** (`fp login`). They are absent from the
211
211
  versioned API an API key authenticates against, so `--api-key` exits 2 with the
212
212
  reason rather than failing at the request.
213
213
 
214
+ ## Author an evaluator
215
+
216
+ `fp evaluators` authors hosted definitions; `fp evals` continues to read results.
217
+ Creation enables a definition by default. Check `fp evaluators instances` first:
218
+ Cloud needs an enabled managed instance. Writes need `evaluations:trigger`;
219
+ session dry-runs and `evaluators schema` also need `events:read`.
220
+
221
+ Write `error_free.py` as a restricted Python expression (no imports or functions):
222
+
223
+ ```python
224
+ EvalResult(score=Score(1.0 if session.count("error") == 0 else 0.0), reasoning="Error-free session")
225
+ ```
226
+
227
+ ```bash
228
+ fp --json evaluators create --key error_free --name "Error free" --code error_free.py \
229
+ --result-kind score --dry-run-on run-001
230
+ fp --json evaluators dry-run --code error_free.py --session run-001
231
+ fp --json evaluators deploy error_free --code error_free.py --version 2 --dry-run-on run-001
232
+ fp --json evaluators list --key error_free --all
233
+ ```
234
+
235
+ LLM judge (Cloud selects the model; judge dry-runs are refused):
236
+
237
+ ```bash
238
+ fp --json evaluators create --key relevance --name Relevance --judge \
239
+ --criteria "Grade how directly the answer addresses the request" --threshold 0.7
240
+ fp --json evaluators deploy relevance --version 2 --judge \
241
+ --criteria "Grade relevance and completeness" --threshold 0.8
242
+ fp --json sessions re-evaluate run-001
243
+ fp --json sessions history run-001
244
+ ```
245
+
246
+ Jev binary or graded rubric:
247
+
248
+ ```bash
249
+ fp --json evaluators create --key resolved --name Resolved --jev noul \
250
+ --instructions "Was the request resolved?" --true "Resolved" --false "Unresolved"
251
+ fp --json evaluators dry-run --jev noul --instructions "Was the request resolved?" \
252
+ --true "Resolved" --false "Unresolved" --session run-001
253
+ fp --json evaluators deploy resolved --version 2 --jev score \
254
+ --instructions "Grade resolution quality" \
255
+ --level "Unresolved" --level "Partly resolved" --level "Fully resolved"
256
+ ```
257
+
258
+ Jev dry-runs spend model budget. Rubrics need 3–5 distinct levels, worst first.
259
+ Thresholds are 0–1; judge/Jev always return a score. `deploy` creates the new
260
+ immutable version before disabling older enabled versions. If disabling fails,
261
+ the CLI names the published id; inspect `list --all` and recover explicitly.
262
+ `--backfill 7d` works for every kind (judge/Jev spend model budget); `evaluators backfill --from T --to T` accepts ≤90 days and `--dry-run` counts the work first.
263
+
264
+ Human output shows each `--dry-run-on` session's outcome before creation or
265
+ deployment. Any failed run stops the write; after reviewing the failure, an
266
+ explicit `--force` overrides this guard. Existing `--json` response shapes stay
267
+ unchanged.
268
+
269
+ AI drafting is session-only and writes an API spec that create/deploy accept:
270
+
271
+ ```bash
272
+ fp login
273
+ fp --json evaluators draft "Measure error-free sessions with code" --kind code --out evaluator.json
274
+ # Review the spec, especially eval_key and evaluator_source, before enabling it.
275
+ fp --json evaluators create --file evaluator.json --dry-run-on run-001
276
+ fp --json evaluators dry-run --file evaluator.json
277
+ ```
278
+
279
+ Spec fields: `eval_key`, `display_name`, `eval_version`, `result_kind`, `labels`,
280
+ `condition_source`, `evaluator_source`, `timeout_seconds`. Judge/Jev sources are
281
+ JSON envelope **strings**, not nested objects. `--file` is exclusive with discrete
282
+ spec flags; deploy may override a file's version. Files written by the CLI are
283
+ created exclusively, so existing files are never silently replaced.
284
+ See [the command reference](skill/references/commands.md#author-an-evaluator).
285
+
286
+ ## Dashboard parity
287
+
288
+ ```text
289
+ fp dashboards list|show|create|update|delete
290
+ fp dashboards tiles <id> list|add|update|remove|layout
291
+ fp sessions show|export|history|re-evaluate <id>
292
+ fp events latency
293
+ fp sentiment summary|messages|sessions|session <id>
294
+ fp query compose "question" [--run] # session
295
+ fp query export [<id>] [--sql SQL] --format csv|json [--out FILE]
296
+ fp alerts recipients
297
+ fp alerts issues <id> [--create --title ... --summary ...]
298
+ fp audits contracts list|show|create|update
299
+ fp policies author "intent"|backtest <file-or-id>|candidacy --issue <id> # session
300
+ fp agent brief [--range 24h|7d] # session
301
+ fp orgs create --name N [--slug S] # session
302
+ fp roles list|show|create|update|delete
303
+ fp users delete <id>
304
+ fp users defaults
305
+ fp usage windows
306
+ fp plan # session
307
+ fp plan claim <offer> # session
308
+ fp settings context-windows list|set <model> <tokens>|delete <model>
309
+ fp otel status|enable|disable
310
+ fp slack status|disconnect # session
311
+ ```
312
+
313
+ `fp agent ask` runs artifact SQL through the permission-gated query runner and
314
+ renders tables/stats. It prompts before approving a write on a terminal.
315
+ Scripts and `--json` **decline** unless you explicitly pass `--approve`.
316
+ Normal create/update commands keep their existing non-interactive confirmation
317
+ behavior; assistant approvals are a separate safety boundary.
318
+
319
+ All new commands accept the global `--json` before the command. Session-only
320
+ commands fail before HTTP in API-key mode, with exit 2 and a `fp login` hint.
321
+ Unknown-route 404s exit 6 with “not available on this FailproofAI Cloud yet”.
322
+ Missing-record 404s also exit 6 but report that the record was not found.
323
+ `plan` and `plan claim` require a signed-in person and deny API-key mode before
324
+ HTTP with the standard `fp login` message.
325
+ Human screens use the mint/pink wordmark, grey labels, open tables and full ids;
326
+ existing JSON shapes are unchanged.
327
+
328
+ Human commands show summaries, tables and wrapped text rather than response
329
+ objects. Use global `--json` for raw API results. For `sessions export` or
330
+ `query export --format json`, use `--out FILE` to save the JSON; without either
331
+ option, the terminal shows a readable session or query view. CSV exports remain
332
+ plain CSV for piping.
333
+
214
334
  ## Configuration
215
335
 
216
336
  | Setting | Flag | Env var | Default |
@@ -1 +1 @@
1
- __version__ = "0.0.2b0"
1
+ __version__ = "0.0.3b0"
@@ -17,12 +17,15 @@ from . import orgs as orgsmod
17
17
  from ._context import AppState
18
18
  from ._version import __version__
19
19
  from .commands import (
20
+ account_cmds,
20
21
  agent_cmds,
21
22
  alerts_cmds,
22
23
  audits_cmds,
23
24
  auth_cmds,
25
+ dashboards_cmds,
24
26
  errors_cmds,
25
27
  evals_cmds,
28
+ evaluators_cmds,
26
29
  events_cmds,
27
30
  fleet_cmds,
28
31
  guardrails_cmds,
@@ -33,6 +36,7 @@ from .commands import (
33
36
  policies_cmds,
34
37
  queries_cmds,
35
38
  sessions_cmds,
39
+ sentiment_cmds,
36
40
  settings_cmds,
37
41
  usage_cmds,
38
42
  users_cmds,
@@ -128,6 +132,12 @@ app = typer.Typer(
128
132
  # function Typer calls for this; falls back silently if its internals change.
129
133
  try: # pragma: no cover - exercised via real command output, not unit assertions
130
134
  import typer.rich_utils as _rich_utils
135
+ # Keep generated subcommand help on the same shared screen primitives.
136
+ _rich_utils.Panel = output.Panel
137
+ _rich_utils.Table = output.Table
138
+ _rich_utils.STYLE_OPTION = output.theme.PINK
139
+ _rich_utils.STYLE_COMMANDS_TABLE_FIRST_COLUMN = output.theme.PINK
140
+ _rich_utils.STYLE_OPTION_ENVVAR = output.theme.LABEL
131
141
 
132
142
  import re as _re
133
143
 
@@ -327,7 +337,7 @@ def main(
327
337
  "must be a positive number of seconds.", param_hint="--timeout"
328
338
  )
329
339
  cfg = cfgmod.load_config()
330
- output.configure(no_color=no_color, quiet=quiet, json=json_output)
340
+ output.configure(no_color=no_color, quiet=quiet, json=json_output, context=ctx.invoked_subcommand or "Cloud")
331
341
  # Resolve the credential BEFORE telemetry starts: the distinct-id depends on it.
332
342
  # `get_parameter_source` is what separates a flag from its env var — the values
333
343
  # alone cannot, and the precedence rules differ between the two (see resolve_auth).
@@ -452,6 +462,9 @@ orgs_cmds.register(app)
452
462
  events_cmds.register(app)
453
463
  sessions_cmds.register(app)
454
464
  evals_cmds.register(app)
465
+ evaluators_cmds.register(app)
466
+ dashboards_cmds.register(app)
467
+ sentiment_cmds.register(app)
455
468
  errors_cmds.register(app)
456
469
  usage_cmds.register(app)
457
470
  list_cmds.register(app)
@@ -466,6 +479,7 @@ agent_cmds.register(app)
466
479
  policies_cmds.register(app)
467
480
  fleet_cmds.register(app)
468
481
  guardrails_cmds.register(app)
482
+ account_cmds.register(app)
469
483
 
470
484
 
471
485
  def _elapsed_ms(start: float) -> int:
@@ -31,6 +31,7 @@ from .errors import (
31
31
  ApiError,
32
32
  AuthError,
33
33
  ForbiddenError,
34
+ FpCliError,
34
35
  KeyModeUnsupportedError,
35
36
  NetworkError,
36
37
  NotFoundError,
@@ -134,6 +135,14 @@ _V1_MECHANICAL_FAMILIES = frozenset(
134
135
  "alerts",
135
136
  "audits",
136
137
  "evaluations",
138
+ "evaluator-definitions",
139
+ "evaluator-instances",
140
+ "evaluator-schema-profile",
141
+ "evaluation-jobs",
142
+ "dashboards",
143
+ "otel",
144
+ "offers",
145
+ "team-trial",
137
146
  "events",
138
147
  "issues",
139
148
  "keys",
@@ -152,6 +161,7 @@ _V1_MECHANICAL_FAMILIES = frozenset(
152
161
  # family rule, which is why this must stay exact-match.
153
162
  _V1_RENAMED = {
154
163
  "/api/evaluations/score-keys": "/v1/evaluations/score_keys",
164
+ "/api/evaluations/metric-keys": "/v1/evaluations/metric_keys",
155
165
  }
156
166
 
157
167
  # Families with no `/v1` route, and why — the message a user actually sees.
@@ -173,6 +183,8 @@ _V1_NO_EQUIVALENT = {
173
183
  "cloud-managed policies are an operator surface — the fleet routes are "
174
184
  "deliberately absent from /v1, which is internet-facing"
175
185
  ),
186
+ "integrations": "dashboard integration routes need a signed-in session",
187
+ "orgs": "organization creation needs a signed-in user",
176
188
  }
177
189
 
178
190
 
@@ -375,6 +387,40 @@ def _required_permission(response: httpx.Response) -> Optional[str]:
375
387
  return None
376
388
 
377
389
 
390
+ def _unknown_route_response(response: httpx.Response) -> Optional[bool]:
391
+ """Use explicit 404 details first; an empty/generic reply is ambiguous."""
392
+ try:
393
+ data = response.json()
394
+ except ValueError:
395
+ return None
396
+ if not isinstance(data, dict):
397
+ return None
398
+ code = data.get("code") or data.get("error_code") or data.get("error") or ""
399
+ if isinstance(code, dict):
400
+ code = code.get("code", "")
401
+ code = str(code).lower()
402
+ if code in ("unknown_route", "route_not_found", "unknown_endpoint", "endpoint_not_found"):
403
+ return True
404
+ if code in ("record_not_found", "resource_not_found", "entity_not_found", "session_not_found", "query_not_found"):
405
+ return False
406
+ message = _extract_error(response)
407
+ if not message:
408
+ return None
409
+ lower = message.lower().strip().rstrip(".")
410
+ if re.search(
411
+ r"\b(?:unknown|unrecognized|unsupported|missing|no such)\s+(?:api\s+)?(?:route|endpoint)\b"
412
+ r"|\b(?:route|endpoint)\b.*\b(?:not found|not available|does not exist|absent|unknown)\b"
413
+ r"|\bcannot (?:get|post|put|patch|delete)\s+/",
414
+ lower,
415
+ ):
416
+ return True
417
+ if lower in ("not found", "not_found", "404", "404 not found"):
418
+ return None
419
+ # A specific response ("session not found", "offer expired", etc.) came
420
+ # from a handler, rather than the router. Do not replace its useful detail.
421
+ return False
422
+
423
+
378
424
  def _raise_for_status(response: httpx.Response, ctx: ClientContext) -> None:
379
425
  key_mode = ctx.auth_mode is AuthMode.API_KEY
380
426
  if response.status_code < 400:
@@ -474,7 +520,9 @@ def _raise_for_status(response: httpx.Response, ctx: ClientContext) -> None:
474
520
  request_id=request_id,
475
521
  hint="point --base-url at the server itself, e.g. http://localhost:8080",
476
522
  )
477
- raise NotFoundError(message or "Not found.", request_id=request_id)
523
+ error = NotFoundError(message or "Not found.", request_id=request_id)
524
+ error.route_unknown = _unknown_route_response(response)
525
+ raise error
478
526
  if response.status_code == 429:
479
527
  retry_after = response.headers.get("retry-after")
480
528
  wait = f" Retry after {retry_after}s." if retry_after else " Please wait a moment and try again."
@@ -606,6 +654,121 @@ def _delete(ctx: ClientContext, path: str) -> Any:
606
654
  return _request_json(ctx, "DELETE", path)
607
655
 
608
656
 
657
+ def cloud_request(
658
+ ctx: ClientContext, method: str, path: str, *,
659
+ body: Any = None, params: Optional[Dict[str, Any]] = None,
660
+ ) -> Any:
661
+ """New Cloud capabilities, with a predictable older-deployment failure.
662
+
663
+ Existing callers retain their response and error contracts. Paths still pass
664
+ through the credential and identifier guards; this is not a second transport.
665
+ """
666
+ try:
667
+ if method == "GET":
668
+ return _get_json(ctx, path, params)
669
+ return _request_json(ctx, method, path, json_body=body, params=params)
670
+ except (NotFoundError, ApiError) as exc:
671
+ if isinstance(exc, ApiError) and exc.status != 404:
672
+ raise
673
+ raise _cloud_not_found(exc, path, body=body, params=params) from exc
674
+
675
+
676
+ def _cloud_not_found(exc: FpCliError, path: str, *, body=None, params=None) -> NotFoundError:
677
+ """Classify ambiguous 404s from the request; never claim a record is a route.
678
+
679
+ Top-level collections and named capability endpoints have no record segment.
680
+ Scoped collections (/dashboards/ID/tiles) and actions on records default to a
681
+ missing record unless the response explicitly says the route is unknown.
682
+ """
683
+ route_unknown = getattr(exc, "route_unknown", None)
684
+ if isinstance(exc, ApiError):
685
+ # The transport only raises HTTP 404 ApiError for an HTML front door.
686
+ route_unknown = True
687
+ if route_unknown is None:
688
+ segments = path.removeprefix("/api/").split("/")
689
+ family = segments[0]
690
+ capability = len(segments) == 1 or (
691
+ family == "agent" and len(segments) == 2
692
+ or family == "otel" and segments == ["otel", "status"]
693
+ or family == "offers" and segments[1:] in (["me"], ["claim"])
694
+ or family == "team-trial" and segments == ["team-trial", "me"]
695
+ or family == "integrations" and segments == ["integrations", "slack"]
696
+ or family == "events" and segments in (
697
+ ["events", "summary"], ["events", "latency_aggregate"],
698
+ ["events", "sentiment"], ["events", "sentiment", "messages"],
699
+ ["events", "sentiment", "sessions"],
700
+ )
701
+ or family == "evaluator-definitions" and segments == ["evaluator-definitions", "dry-run"]
702
+ or family == "evaluations" and segments == ["evaluations", "backfill"]
703
+ or family == "queries" and segments[1:] in (["run"], ["schema"])
704
+ or family == "audits" and segments == ["audits", "contracts"]
705
+ or family == "alerts" and segments == ["alerts", "recipients"]
706
+ or family == "users" and segments == ["users", "defaults"]
707
+ or family == "usage" and segments == ["usage", "windows"]
708
+ or family == "settings" and segments == ["settings", "model-context-windows"]
709
+ or family == "settings" and len(segments) == 2
710
+ )
711
+ # Some collection operations name their target in a query or body.
712
+ request_body = body if isinstance(body, dict) else {}
713
+ record_selected = (
714
+ (params or {}).get("session_id") or (params or {}).get("model")
715
+ or request_body.get("query_id") or request_body.get("callId")
716
+ or request_body.get("session_ids") or request_body.get("offer_key")
717
+ or request_body.get("conversationId")
718
+ )
719
+ route_unknown = capability and not record_selected
720
+ if route_unknown:
721
+ return NotFoundError(
722
+ "not available on this FailproofAI Cloud yet",
723
+ hint="upgrade your Cloud deployment to use this route",
724
+ request_id=exc.request_id,
725
+ )
726
+ message = exc.message
727
+ if message.lower().strip().rstrip(".") in (
728
+ "not found", "not_found", "record_not_found", "resource_not_found",
729
+ "entity_not_found", "session_not_found", "query_not_found",
730
+ ):
731
+ message = f"Record not found at {path}"
732
+ return NotFoundError(message, request_id=exc.request_id)
733
+
734
+
735
+ def import_events_file(
736
+ ctx: ClientContext, data: bytes, params: Dict[str, Any],
737
+ ) -> Any:
738
+ """POST /api/events/import — one file's bytes (gzip accepted), as the dashboard's
739
+ import dialog sends it. ``params``: format, path, environment, dry_run, existing_before."""
740
+ clean = {k: v for k, v in params.items() if v is not None} or None
741
+ url = _path(ctx, "/api/events/import")
742
+ try:
743
+ with _client(ctx) as client:
744
+ response = client.request(
745
+ "POST", url, content=data, params=clean,
746
+ headers={"Content-Type": "application/octet-stream"},
747
+ )
748
+ except httpx.RequestError as exc:
749
+ raise NetworkError(
750
+ f"Cannot reach FailproofAI Cloud at {ctx.base_url}: {exc}",
751
+ request_id=_sent_request_id(exc),
752
+ )
753
+ _raise_for_status(response, ctx)
754
+ if not response.content:
755
+ return {}
756
+ try:
757
+ return response.json()
758
+ except ValueError:
759
+ raise ApiError("The dashboard returned an invalid import response.")
760
+
761
+
762
+ def cloud_stream(ctx: ClientContext, path: str, body: Dict[str, Any]) -> Iterator[Dict[str, Any]]:
763
+ """Dashboard SSE with the same additive-capability 404 contract."""
764
+ try:
765
+ yield from _stream_sse(ctx, path, body)
766
+ except (NotFoundError, ApiError) as exc:
767
+ if isinstance(exc, ApiError) and exc.status != 404:
768
+ raise
769
+ raise _cloud_not_found(exc, path, body=body) from exc
770
+
771
+
609
772
  # --- Auth / identity --------------------------------------------------------
610
773
 
611
774
 
@@ -793,6 +956,10 @@ _FACET_PATHS = {
793
956
  # Evaluation score keys (a distinct endpoint, not /api/events) — the source for
794
957
  # the sessions-page score-filter dropdown; needs `evaluations:read`.
795
958
  "score_filters": "/api/evaluations/score-keys",
959
+ # Evaluation-side facets: environments with evaluation results, and metric
960
+ # keys (the server returns {name, unit, count}; `list` shows the names).
961
+ "eval_environments": "/api/evaluations/environments",
962
+ "metric_keys": "/api/evaluations/metric-keys",
796
963
  }
797
964
  FACET_KINDS = tuple(_FACET_PATHS.keys())
798
965
 
@@ -800,7 +967,9 @@ FACET_KINDS = tuple(_FACET_PATHS.keys())
800
967
  def list_facet(ctx: ClientContext, kind: str) -> List[str]:
801
968
  """GET /api/events/<kind> — distinct facet values (a bare JSON array)."""
802
969
  data = _get_json(ctx, _FACET_PATHS[kind])
803
- return [str(x) for x in data] if isinstance(data, list) else []
970
+ if not isinstance(data, list):
971
+ return []
972
+ return [str(x.get("name", "")) if isinstance(x, dict) else str(x) for x in data]
804
973
 
805
974
 
806
975
  def get_usage(ctx: ClientContext) -> Dict[str, Any]:
@@ -1195,20 +1364,28 @@ def list_incidents(
1195
1364
  state: Optional[str] = None,
1196
1365
  alert_id: Optional[str] = None,
1197
1366
  limit: Optional[int] = None,
1367
+ filters: Optional[Dict[str, Any]] = None,
1198
1368
  ) -> List[Incident]:
1199
1369
  """GET /api/issues (or /api/alerts/{id}/issues when alert_id given). The
1200
1370
  alert-scoped path honours ``state``/``limit`` too — pass them so the filters aren't silently
1201
1371
  dropped on that path (``_get_json`` omits None params)."""
1202
- if alert_id:
1372
+ extra = {k: v for k, v in (filters or {}).items() if v is not None}
1373
+ if alert_id and not extra:
1203
1374
  data = _get_json(ctx, f"/api/alerts/{alert_id}/issues", {"state": state, "limit": limit})
1375
+ elif alert_id:
1376
+ # The board's own filters live on /issues, which takes alert_id as one of them.
1377
+ data = _get_json(ctx, "/api/issues", {"state": state, "limit": limit, "alert_id": alert_id, **extra})
1204
1378
  else:
1205
- data = _get_json(ctx, "/api/issues", {"state": state, "limit": limit})
1379
+ data = _get_json(ctx, "/api/issues", {"state": state, "limit": limit, **extra})
1206
1380
  return [Incident.from_dict(i) for i in (data if isinstance(data, list) else [])]
1207
1381
 
1208
1382
 
1209
- def count_incidents(ctx: ClientContext, *, state: Optional[str] = None) -> int:
1383
+ def count_incidents(
1384
+ ctx: ClientContext, *, state: Optional[str] = None, filters: Optional[Dict[str, Any]] = None,
1385
+ ) -> int:
1210
1386
  """GET /api/issues/count — {count}."""
1211
- data = _get_json(ctx, "/api/issues/count", {"state": state})
1387
+ extra = {k: v for k, v in (filters or {}).items() if v is not None}
1388
+ data = _get_json(ctx, "/api/issues/count", {"state": state, **extra})
1212
1389
  if not isinstance(data, dict):
1213
1390
  return 0
1214
1391
  try:
@@ -1532,6 +1709,8 @@ def agent_chat_oneshot(
1532
1709
  conversation_id: Optional[str] = None,
1533
1710
  page_context: Optional[str] = None,
1534
1711
  model: Optional[str] = None,
1712
+ on_ask_user: Optional[Callable[[Dict[str, Any]], None]] = None,
1713
+ on_artifact: Optional[Callable[[Dict[str, Any]], None]] = None,
1535
1714
  ) -> Dict[str, Any]:
1536
1715
  """POST /api/agent/chat — accumulate the streamed answer.
1537
1716
 
@@ -1551,20 +1730,32 @@ def agent_chat_oneshot(
1551
1730
  body["pageContext"] = page_context
1552
1731
  if model:
1553
1732
  body["model"] = model
1733
+ if on_artifact:
1734
+ body["pageActions"] = [{"action": "open_artifact"}, {"action": "home"}]
1554
1735
  parts: List[str] = []
1555
1736
  tools: List[str] = []
1556
1737
  interrupted = False
1557
1738
  error: Optional[str] = None
1558
- for ev in _stream_sse(ctx, "/api/agent/chat", body):
1739
+ for ev in cloud_stream(ctx, "/api/agent/chat", body):
1559
1740
  kind = ev.get("type")
1560
1741
  if kind == "text-delta":
1561
1742
  parts.append(str(ev.get("text", "")))
1562
1743
  elif kind == "tool-start":
1563
1744
  tools.append(str(ev.get("tool", "")))
1564
1745
  elif kind == "ask-user":
1746
+ if on_ask_user and ev.get("callId"):
1747
+ on_ask_user(ev)
1748
+ continue
1565
1749
  interrupted = True
1566
1750
  error = str(ev.get("question") or "the assistant needs interactive input")
1567
1751
  break
1752
+ elif kind == "ui-action" and on_artifact:
1753
+ if ev.get("action") == "open_artifact" and isinstance(ev.get("artifact"), dict):
1754
+ on_artifact(ev["artifact"])
1755
+ elif ev.get("action") == "home" and isinstance(ev.get("home"), dict):
1756
+ for block in ev["home"].get("blocks", []):
1757
+ if isinstance(block, dict):
1758
+ on_artifact(block)
1568
1759
  elif kind == "error":
1569
1760
  error = str(ev.get("message", "assistant error"))
1570
1761
  elif kind == "done":