failproofai 1.0.0-beta.2 → 1.0.0-beta.21

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 (381) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +2 -1
  3. package/.next/standalone/.next/build-manifest.json +6 -6
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/required-server-files.json +1 -1
  6. package/.next/standalone/.next/routes-manifest.json +6 -0
  7. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  8. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page.js +3 -1
  10. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  14. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  15. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  16. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  18. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  20. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  21. package/.next/standalone/.next/server/app/_not-found/page.js +3 -1
  22. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  24. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  25. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  26. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  27. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  28. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  29. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  30. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  31. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  32. package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
  33. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -3
  35. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/audit/status/route.js +1 -1
  37. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +3 -1
  39. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +3 -2
  41. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/auth/logout/route.js +3 -2
  43. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +3 -2
  45. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -2
  47. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  49. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  51. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  52. package/.next/standalone/.next/server/app/audit/page.js +5 -3
  53. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  55. package/.next/standalone/.next/server/app/index.html +1 -1
  56. package/.next/standalone/.next/server/app/index.rsc +15 -15
  57. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  58. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  59. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  60. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  61. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  62. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  63. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  64. package/.next/standalone/.next/server/app/page.js +3 -1
  65. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
  68. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +30 -18
  69. package/.next/standalone/.next/server/app/policies/page.js +5 -3
  70. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  71. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  72. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  73. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  74. package/.next/standalone/.next/server/app/project/[name]/page.js +4 -2
  75. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  78. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  79. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  80. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +6 -4
  81. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  82. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  83. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  84. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  85. package/.next/standalone/.next/server/app/projects/page.js +4 -2
  86. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  87. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  88. package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
  89. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +18 -0
  90. package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +6 -0
  91. package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
  92. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +53 -0
  93. package/.next/standalone/.next/server/app/settings/page.js +18 -0
  94. package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
  95. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
  96. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
  97. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  98. package/.next/standalone/.next/server/chunks/[externals]__0h9_83k._.js +3 -0
  99. package/.next/standalone/.next/server/chunks/{[externals]__1nl3dvw._.js → [externals]__0r-zamh._.js} +2 -2
  100. package/.next/standalone/.next/server/chunks/[externals]__1ifpkx-._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l4vuqm._.js → [root-of-the-server]__00ni9za._.js} +2 -2
  102. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
  103. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08y94xv._.js +3 -0
  104. package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +3 -0
  107. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-dh5jy._.js → [root-of-the-server]__0effm9m._.js} +2 -2
  108. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g0vcwt._.js +3 -0
  109. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__18d-9oi._.js → [root-of-the-server]__0ix8gm7._.js} +2 -2
  110. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0h3lfmp._.js → [root-of-the-server]__0ji11a-._.js} +2 -2
  111. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__10oa-v9._.js → [root-of-the-server]__0ojwjxl._.js} +2 -2
  112. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__16le-kd._.js → [root-of-the-server]__0pbp9fe._.js} +2 -2
  113. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
  114. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vb5fl2._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sb_5m8._.js → [root-of-the-server]__131ebum._.js} +4 -4
  116. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
  118. package/.next/standalone/.next/server/chunks/[root-of-the-server]__20d06rh._.js +3 -0
  119. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +3 -0
  120. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +3 -0
  121. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +3 -0
  122. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +5 -5
  123. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -1
  124. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -1
  125. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/[externals]__1aq139v._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-wfhrp._.js +3 -0
  128. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06bp_fg._.js +5 -0
  129. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__074qmkp._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1apb7k_._.js → [root-of-the-server]__0_1tiya._.js} +2 -2
  131. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__170799-._.js → [root-of-the-server]__0spkm68._.js} +11 -11
  132. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t281d4._.js +3 -0
  133. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17itmx-._.js +5 -0
  134. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01od0m6._.js → [root-of-the-server]__1n2vcv4._.js} +2 -2
  135. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qapotl._.js +1 -1
  136. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +3 -0
  137. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tlvv9a._.js +3 -0
  138. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
  139. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +3 -0
  140. package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +3 -0
  141. package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
  142. package/.next/standalone/.next/server/chunks/ssr/_0vo2qyt._.js +3 -0
  143. package/.next/standalone/.next/server/chunks/ssr/_0xej-0e._.js +3 -0
  144. package/.next/standalone/.next/server/chunks/ssr/_10399ge._.js +3 -0
  145. package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
  146. package/.next/standalone/.next/server/chunks/ssr/_149k9oy._.js +3 -0
  147. package/.next/standalone/.next/server/chunks/ssr/_1_hwp06._.js +3 -0
  148. package/.next/standalone/.next/server/chunks/ssr/_1ctse6u._.js +3 -0
  149. package/.next/standalone/.next/server/chunks/ssr/_1e19atl._.js +1 -1
  150. package/.next/standalone/.next/server/chunks/ssr/_1mnhi_r._.js +3 -0
  151. package/.next/standalone/.next/server/chunks/ssr/_1ror7k9._.js +3 -0
  152. package/.next/standalone/.next/server/chunks/ssr/_1sdgprl._.js +5 -0
  153. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  154. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  155. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  156. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dwo94s.js +4 -0
  157. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -1
  158. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +3 -0
  159. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +4 -0
  160. package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
  161. package/.next/standalone/.next/server/middleware.js +2 -2
  162. package/.next/standalone/.next/server/pages/404.html +1 -1
  163. package/.next/standalone/.next/server/pages/500.html +1 -1
  164. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  165. package/.next/standalone/.next/server/server-reference-manifest.json +74 -20
  166. package/.next/standalone/.next/static/chunks/{03fmihek9n986.js → 06zgzyh3wv1ig.js} +1 -1
  167. package/.next/standalone/.next/static/chunks/0km-jn9o5xyqs.css +2 -0
  168. package/.next/standalone/.next/static/chunks/{1hdhteui932bq.js → 0qmo2t50kpb30.js} +1 -1
  169. package/.next/standalone/.next/static/chunks/{2sbelanzvxvv0.js → 113g8wtal6_c4.js} +22 -22
  170. package/.next/standalone/.next/static/chunks/16p68cybetr31.js +1 -0
  171. package/.next/standalone/.next/static/chunks/18wqn0_3mzylf.js +1 -0
  172. package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
  173. package/.next/standalone/.next/static/chunks/{0fi645si-uiiq.js → 1xq1m8h14tnlj.js} +1 -1
  174. package/.next/standalone/.next/static/chunks/{3hp8ulqknybil.js → 1y3vwogqb88dx.js} +1 -1
  175. package/.next/standalone/.next/static/chunks/{3vs4ay36tjds_.js → 1zmh-b0ulrqu7.js} +1 -1
  176. package/.next/standalone/.next/static/chunks/23kev26by1e4f.js +1 -0
  177. package/.next/standalone/.next/static/chunks/299lhw60e8gr6.js +1 -0
  178. package/.next/standalone/.next/static/chunks/{18rvdw5v72364.js → 2adbpdaxp5ygq.js} +1 -1
  179. package/.next/standalone/.next/static/chunks/{2j94uwkb4s3qr.js → 2kbqcw-6swmav.js} +1 -1
  180. package/.next/standalone/.next/static/chunks/2n9n5m0963pdg.js +6 -0
  181. package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
  182. package/.next/standalone/.next/static/chunks/{31feojxhjyjpl.js → 30nrrpwymht5m.js} +1 -1
  183. package/.next/standalone/.next/static/chunks/31coz11ia5vc4.js +1 -0
  184. package/.next/standalone/.next/static/chunks/{turbopack-1lsv92x7klwrn.js → turbopack-3diub4ctvn1n0.js} +1 -1
  185. package/.next/standalone/SECURITY.md +8 -2
  186. package/.next/standalone/app/actions/get-active-pauses.ts +16 -0
  187. package/.next/standalone/app/actions/get-hooks-config.ts +2 -2
  188. package/.next/standalone/app/actions/get-scheduled-audit.ts +70 -0
  189. package/.next/standalone/app/actions/update-scheduled-audit.ts +44 -0
  190. package/.next/standalone/app/api/audit/run/route.ts +28 -0
  191. package/.next/standalone/app/api/audit/status/route.ts +13 -1
  192. package/.next/standalone/app/api/auth/status/route.ts +1 -1
  193. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +1 -3
  194. package/.next/standalone/app/audit/_components/audit-progress-strip.tsx +1 -1
  195. package/.next/standalone/app/audit/_components/auth-dialog.css +159 -0
  196. package/.next/standalone/app/audit/_components/auth-dialog.tsx +3 -0
  197. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -1
  198. package/.next/standalone/app/audit/_components/empty-state.tsx +0 -1
  199. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +1 -1
  200. package/.next/standalone/app/audit/_components/quirks-section.tsx +0 -1
  201. package/.next/standalone/app/audit/_components/report-footer.tsx +0 -2
  202. package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
  203. package/.next/standalone/app/audit/_components/strengths-section.tsx +0 -1
  204. package/.next/standalone/app/audit/audit-styles.css +6 -149
  205. package/.next/standalone/app/components/pause-notices.tsx +111 -0
  206. package/.next/standalone/app/components/raw-log-viewer.tsx +1 -1
  207. package/.next/standalone/app/components/toast.tsx +1 -1
  208. package/.next/standalone/app/policies/hooks-client.tsx +84 -8
  209. package/.next/standalone/app/settings/page.tsx +31 -0
  210. package/.next/standalone/app/settings/settings-client.tsx +487 -0
  211. package/.next/standalone/components/navbar.tsx +2 -0
  212. package/.next/standalone/lib/auth/api-server-client.ts +2 -3
  213. package/.next/standalone/lib/auth/auth-store.ts +4 -5
  214. package/.next/standalone/lib/codex-sessions.ts +2 -1
  215. package/.next/standalone/lib/dashboard-host.ts +101 -0
  216. package/.next/standalone/lib/install-check.ts +22 -7
  217. package/.next/standalone/lib/pi-sessions.ts +99 -14
  218. package/.next/standalone/lib/telemetry-enabled.ts +54 -0
  219. package/.next/standalone/lib/telemetry-id.ts +52 -1
  220. package/.next/standalone/lib/telemetry.ts +8 -4
  221. package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
  222. package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
  223. package/.next/standalone/node_modules/react/package.json +3 -3
  224. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
  225. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
  226. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
  227. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
  228. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
  229. package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
  230. package/.next/standalone/node_modules/react-dom/package.json +4 -4
  231. package/.next/standalone/package.json +23 -12
  232. package/.next/standalone/proxy.ts +111 -1
  233. package/.next/standalone/server.js +1 -1
  234. package/bin/failproofai-worker.mjs +1 -1
  235. package/bin/failproofai.mjs +1041 -81
  236. package/bin/failproofaid-shim.mjs +4 -4
  237. package/dist/cli.mjs +18513 -10474
  238. package/dist/worker.mjs +1223 -299
  239. package/lib/auth/api-server-client.ts +2 -3
  240. package/lib/auth/auth-store.ts +4 -5
  241. package/lib/codex-sessions.ts +2 -1
  242. package/lib/dashboard-host.ts +101 -0
  243. package/lib/install-check.ts +22 -7
  244. package/lib/pi-sessions.ts +99 -14
  245. package/lib/telemetry-enabled.ts +54 -0
  246. package/lib/telemetry-id.ts +52 -1
  247. package/lib/telemetry.ts +8 -4
  248. package/package.json +23 -12
  249. package/scripts/build-daemon-packages.mjs +247 -0
  250. package/scripts/daemon-platforms.mjs +42 -0
  251. package/scripts/dev-hook.mjs +46 -5
  252. package/scripts/install-telemetry.mjs +8 -1
  253. package/scripts/launch.ts +25 -3
  254. package/scripts/parse-script-args.ts +27 -1
  255. package/scripts/prune-standalone.mjs +26 -0
  256. package/scripts/publish-aliases.mjs +62 -41
  257. package/scripts/repro-npm-install.sh +155 -0
  258. package/scripts/translate-docs/cache.ts +1 -1
  259. package/scripts/translate-docs/cli.ts +2 -2
  260. package/scripts/translate-docs/mintlify-nav.ts +1 -1
  261. package/scripts/translate-docs/readme-translator.ts +163 -4
  262. package/scripts/validate-mdx.ts +153 -13
  263. package/src/audit/audit-lock.ts +285 -0
  264. package/src/audit/audit-schedule.ts +111 -0
  265. package/src/audit/cache.ts +18 -5
  266. package/src/audit/cli-adapters/goose.ts +2 -1
  267. package/src/audit/cli-adapters/hermes.ts +28 -10
  268. package/src/audit/cli.ts +191 -35
  269. package/src/audit/dashboard-cache.ts +2 -3
  270. package/src/audit/report.ts +0 -1
  271. package/src/hooks/backfill-cli.ts +247 -0
  272. package/src/hooks/builtin-policies.ts +391 -3
  273. package/src/hooks/cloud-connection.ts +354 -0
  274. package/src/hooks/cloud-enrollment-cli.ts +439 -0
  275. package/src/hooks/cloud-enrollment.ts +284 -0
  276. package/src/hooks/cloud-introspect.ts +147 -0
  277. package/src/hooks/cloud-managed-policies.ts +206 -0
  278. package/src/hooks/collector-config.ts +218 -0
  279. package/src/hooks/configure-wizard.ts +1211 -233
  280. package/src/hooks/custom-hooks-loader.ts +243 -37
  281. package/src/hooks/daemon-client.ts +136 -33
  282. package/src/hooks/daemon-download.ts +264 -31
  283. package/src/hooks/daemon-service.ts +1124 -76
  284. package/src/hooks/first-run-gate.ts +50 -0
  285. package/src/hooks/flush-cli.ts +180 -0
  286. package/src/hooks/fp-config.ts +835 -0
  287. package/src/hooks/fp-home.ts +714 -0
  288. package/src/hooks/fp-reset.ts +1363 -0
  289. package/src/hooks/handler.ts +185 -6
  290. package/src/hooks/harness-cli.ts +386 -0
  291. package/src/hooks/hook-activity-store.ts +171 -24
  292. package/src/hooks/hook-logger.ts +2 -2
  293. package/src/hooks/hook-telemetry.ts +5 -1
  294. package/src/hooks/hooks-config.ts +4 -3
  295. package/src/hooks/integrations.ts +0 -1
  296. package/src/hooks/loader-utils.ts +172 -9
  297. package/src/hooks/manager.ts +41 -5
  298. package/src/hooks/migrations.ts +450 -0
  299. package/src/hooks/onboarding-attempt.ts +195 -0
  300. package/src/hooks/onboarding-lock.ts +118 -0
  301. package/src/hooks/policy-types.ts +28 -0
  302. package/src/hooks/session-pause-cli.ts +159 -0
  303. package/src/hooks/session-pause.ts +267 -0
  304. package/src/hooks/setup-state.ts +256 -0
  305. package/src/hooks/tui.ts +209 -9
  306. package/src/hooks/uninstall-cli.ts +418 -0
  307. package/src/hooks/worker-server.ts +134 -15
  308. package/.next/standalone/.next/server/chunks/[externals]__14odj07._.js +0 -3
  309. package/.next/standalone/.next/server/chunks/[externals]__1s61mel._.js +0 -3
  310. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0id_xf7._.js +0 -3
  311. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0longh-._.js +0 -3
  312. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
  313. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
  314. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
  315. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
  316. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
  317. package/.next/standalone/.next/server/chunks/ssr/[externals]__1_g_b3t._.js +0 -3
  318. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0114ewg._.js +0 -4
  319. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
  320. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
  321. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
  322. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0nb0syg._.js +0 -3
  323. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
  324. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +0 -4
  325. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uno39i._.js +0 -3
  326. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
  327. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ath6v_._.js +0 -4
  328. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1psjybo._.js +0 -3
  329. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
  330. package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
  331. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0oy_-36.js +0 -3
  332. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
  333. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
  334. package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
  335. package/.next/standalone/.next/static/chunks/0zbxssxh53n-3.js +0 -1
  336. package/.next/standalone/.next/static/chunks/2mazwb1qmur1p.js +0 -1
  337. package/.next/standalone/.next/static/chunks/2pujpnfx4pws6.css +0 -2
  338. package/.next/standalone/.next/static/chunks/33u59vf_8xpd-.js +0 -1
  339. package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
  340. package/.next/standalone/.next/static/chunks/3s7myk_co0gbh.js +0 -1
  341. package/.next/standalone/.next/static/chunks/40k1_v4os4cw6.js +0 -6
  342. package/.next/standalone/Cargo.lock +0 -428
  343. package/.next/standalone/Cargo.toml +0 -9
  344. package/.next/standalone/crates/PROTOCOL.md +0 -122
  345. package/.next/standalone/crates/failproofaid/Cargo.toml +0 -18
  346. package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
  347. package/.next/standalone/crates/failproofaid/src/main.rs +0 -83
  348. package/.next/standalone/crates/failproofaid/src/paths.rs +0 -172
  349. package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
  350. package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
  351. package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
  352. package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
  353. package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
  354. package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
  355. package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
  356. package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
  357. package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
  358. package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
  359. package/.next/standalone/integration-suite/Dockerfile +0 -47
  360. package/.next/standalone/integration-suite/README.md +0 -129
  361. package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
  362. package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
  363. package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
  364. package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
  365. package/.next/standalone/integration-suite/install-clis.sh +0 -136
  366. package/.next/standalone/integration-suite/probe-cli.sh +0 -248
  367. package/.next/standalone/integration-suite/report.js +0 -120
  368. package/.next/standalone/integration-suite/run.sh +0 -159
  369. package/.next/standalone/openclaw-plugin/index.js +0 -223
  370. package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
  371. package/.next/standalone/openclaw-plugin/package.json +0 -12
  372. package/.next/standalone/osv-scanner.toml +0 -17
  373. package/.next/standalone/pi-extension/index.ts +0 -524
  374. package/.next/standalone/pi-extension/package.json +0 -12
  375. package/.next/standalone/postcss.config.mjs +0 -8
  376. package/.next/standalone/readme-arch-hq.gif +0 -0
  377. package/.next/standalone/rust-toolchain.toml +0 -4
  378. package/src/auth/cli.ts +0 -371
  379. /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_buildManifest.js +0 -0
  380. /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_clientMiddlewareManifest.js +0 -0
  381. /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_ssgManifest.js +0 -0
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Why the last first-run setup stopped, and whether it is worth offering again.
3
+ *
4
+ * # The problem this exists for
5
+ *
6
+ * Setup is deliberately all-or-nothing: every abort path writes NOTHING, so a
7
+ * machine that could not be configured is left exactly as it was found rather
8
+ * than carrying half a configuration (a `daemonConfigured` flag with no daemon
9
+ * behind it denies every tool call across all twelve CLIs). That invariant is
10
+ * right and is not changed here.
11
+ *
12
+ * But it left onboarding with no memory. `isConfigured()` reads three signals —
13
+ * a global policy config, live user-scope hooks, the legacy marker — and an
14
+ * abort sets none of them, so "never tried" and "tried twenty times and could
15
+ * not finish" are indistinguishable. On a machine without passwordless sudo,
16
+ * every single command relaunched the whole wizard, forever.
17
+ *
18
+ * # What this is NOT
19
+ *
20
+ * Not a fourth "configured" signal. Nothing here may make `isConfigured()` true.
21
+ * A machine that failed setup is unconfigured and must keep saying so — to the
22
+ * hook path, to `--status`, and to the wizard when it is asked for by name.
23
+ * This only changes whether the wizard is *offered unprompted*.
24
+ *
25
+ * # Re-offering
26
+ *
27
+ * A hint that never becomes an offer again is its own failure: the common case
28
+ * is someone who hits the sudo prompt, gives up, and comes back later able to
29
+ * elevate. So each reason carries a cheap local check for whether its blocker
30
+ * is gone, and the wizard offers itself again the moment one is:
31
+ *
32
+ * needs_root -> elevation is now possible without a prompt
33
+ * daemon_failed -> the service manager now reports something different
34
+ * cancelled -> the CLI version changed; an upgrade is a fair moment to
35
+ * ask again, and nothing else about a deliberate cancel
36
+ * should re-nag
37
+ * unsupported_platform -> the CLI version changed (a future release might
38
+ * support this platform)
39
+ *
40
+ * Every probe is local and takes milliseconds. None of them runs on the hook
41
+ * path — `--hook` never reaches the first-run gate at all.
42
+ */
43
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
44
+ import { dirname } from "node:path";
45
+ import { onboardingAttemptFile } from "./fp-home";
46
+ import type { WizardAbort } from "./configure-wizard";
47
+
48
+ /** Bumped only for a deliberate shape change; an unreadable record is ignored. */
49
+ const SCHEMA_VERSION = 1;
50
+
51
+ export interface OnboardingAttempt {
52
+ schemaVersion: number;
53
+ /** Why the wizard stopped. */
54
+ reason: WizardAbort;
55
+ /** The CLI that made the attempt, so an upgrade can re-offer. */
56
+ cliVersion: string;
57
+ /**
58
+ * What the service manager said at the time. Compared, never trusted — the
59
+ * point is only whether it has CHANGED since.
60
+ */
61
+ daemonStatus: string;
62
+ /** Epoch ms, for support and for nothing else. */
63
+ at: number;
64
+ }
65
+
66
+ export function readOnboardingAttempt(): OnboardingAttempt | null {
67
+ const path = onboardingAttemptFile();
68
+ if (!existsSync(path)) return null;
69
+ try {
70
+ const raw = JSON.parse(readFileSync(path, "utf8")) as Partial<OnboardingAttempt>;
71
+ if (raw.schemaVersion !== SCHEMA_VERSION) return null;
72
+ if (typeof raw.reason !== "string" || typeof raw.cliVersion !== "string") return null;
73
+ return {
74
+ schemaVersion: SCHEMA_VERSION,
75
+ reason: raw.reason as WizardAbort,
76
+ cliVersion: raw.cliVersion,
77
+ daemonStatus: typeof raw.daemonStatus === "string" ? raw.daemonStatus : "",
78
+ at: typeof raw.at === "number" ? raw.at : 0,
79
+ };
80
+ } catch {
81
+ // A corrupt record reads as "no record", which degrades to today's
82
+ // behaviour — offering the wizard. Never to "configured".
83
+ return null;
84
+ }
85
+ }
86
+
87
+ /** Best-effort: a machine that cannot record this simply keeps being offered. */
88
+ export function recordOnboardingAttempt(
89
+ reason: WizardAbort,
90
+ cliVersion: string,
91
+ daemonStatus: string,
92
+ now: number = Date.now(),
93
+ ): void {
94
+ try {
95
+ const path = onboardingAttemptFile();
96
+ mkdirSync(dirname(path), { recursive: true });
97
+ const record: OnboardingAttempt = {
98
+ schemaVersion: SCHEMA_VERSION,
99
+ reason,
100
+ cliVersion,
101
+ daemonStatus,
102
+ at: now,
103
+ };
104
+ writeFileSync(path, JSON.stringify(record, null, 2), "utf8");
105
+ } catch {
106
+ // best-effort
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Called on a completed apply. A stale record would keep suppressing the offer
112
+ * on a machine that has since been reconfigured by hand and un-configured again.
113
+ */
114
+ export function clearOnboardingAttempt(): void {
115
+ try {
116
+ rmSync(onboardingAttemptFile(), { force: true });
117
+ } catch {
118
+ // best-effort
119
+ }
120
+ }
121
+
122
+ export interface RetryProbe {
123
+ /** Elevation is possible without prompting. */
124
+ canElevate: () => boolean;
125
+ /** What the service manager says right now. */
126
+ daemonStatus: () => string;
127
+ /** This CLI's version. */
128
+ cliVersion: string;
129
+ }
130
+
131
+ /**
132
+ * Whether the thing that stopped setup last time has since changed.
133
+ *
134
+ * `true` means offer the wizard again; `false` means a one-line hint. An
135
+ * unrecognised reason returns `true` — an unknown blocker is one we cannot
136
+ * prove is still present, and the safe direction is offering setup rather than
137
+ * silently withholding it.
138
+ */
139
+ export function blockerCleared(attempt: OnboardingAttempt, probe: RetryProbe): boolean {
140
+ switch (attempt.reason) {
141
+ case "needs_root":
142
+ return probe.canElevate();
143
+ case "daemon_failed":
144
+ // Any movement at all: not-installed -> stopped, stopped -> running, or a
145
+ // platform that has gained a service manager. Comparing rather than
146
+ // demanding "running" is what lets a partially-repaired machine be
147
+ // offered setup again instead of waiting for a state it cannot reach on
148
+ // its own.
149
+ return probe.daemonStatus() !== attempt.daemonStatus || probe.canElevate();
150
+ case "cancelled":
151
+ // A deliberate stop. Re-asking on the next command is exactly the nagging
152
+ // this module removes — but an upgrade is a new thing to say, so it is
153
+ // allowed to ask once more.
154
+ return probe.cliVersion !== attempt.cliVersion;
155
+ case "unsupported_platform":
156
+ // A permanent property of the machine, not the invocation — nagging every
157
+ // command would just repeat the hard-fail. Only a new release is a reason
158
+ // to ask again (it might add support for this platform).
159
+ return probe.cliVersion !== attempt.cliVersion;
160
+ case "not_a_tty":
161
+ case "running_as_sudo":
162
+ // Both are properties of the invocation, not of the machine, so the next
163
+ // one may well be fine.
164
+ return true;
165
+ default:
166
+ return true;
167
+ }
168
+ }
169
+
170
+ /** The one line shown instead of relaunching the wizard. */
171
+ export function attemptHintLines(attempt: OnboardingAttempt): string[] {
172
+ const why: Record<string, string> = {
173
+ needs_root: "it needs root to install the failproofaid service",
174
+ daemon_failed: "the failproofaid service could not be started",
175
+ cancelled: "it was cancelled",
176
+ unsupported_platform: "failproofaid does not run on this platform",
177
+ not_a_tty: "there was no terminal to ask in",
178
+ running_as_sudo: "it was run under sudo",
179
+ };
180
+ const detail = why[attempt.reason] ?? "it did not finish";
181
+ // Every other reason is fixable by the user right now, so the generic
182
+ // retry is correct. unsupported_platform is not — blockerCleared only
183
+ // re-offers it on a CLI version change, and `failproofai config` would
184
+ // hit the exact same hard-fail in the meantime.
185
+ const action =
186
+ attempt.reason === "unsupported_platform"
187
+ ? "Check for a failproofai update — this platform may be supported by a newer release."
188
+ : "Run `failproofai config` when you are ready.";
189
+ return [
190
+ ``,
191
+ `[failproofai] Setup is not finished — ${detail}.`,
192
+ ` ${action}`,
193
+ ``,
194
+ ];
195
+ }
@@ -0,0 +1,118 @@
1
+ /**
2
+ * A single-holder guard around first-run onboarding.
3
+ *
4
+ * Onboarding used to fire only on a bare `failproofai`. It now fires on any
5
+ * command an unconfigured machine runs, which makes concurrent runs a real
6
+ * shape rather than a theoretical one: two terminals, `failproofai audit` in
7
+ * each, and both draw a wizard. They would then race on the same settings
8
+ * files and, worse, both try to install the system service — two `sudo`
9
+ * prompts and two `systemctl enable` calls against one unit.
10
+ *
11
+ * ## Why liveness, not a timeout
12
+ *
13
+ * The obvious lock carries a timestamp and is treated as stale after N
14
+ * seconds. That cannot work here: the holder is a human answering questions,
15
+ * so any N short enough to recover promptly from a crash is also short enough
16
+ * to evict someone who walked away mid-setup. So the lock records a PID and is
17
+ * considered held only while that process is actually alive — which recovers
18
+ * instantly from a crash or a Ctrl-C, and never evicts a live wizard no matter
19
+ * how long it sits.
20
+ *
21
+ * ## Failure direction
22
+ *
23
+ * Every failure here resolves to "do not onboard". A lock we cannot take is
24
+ * indistinguishable from one already held, and skipping onboarding costs a
25
+ * user one printed hint, where wrongly proceeding costs a duplicated install.
26
+ * The command the user typed always runs either way.
27
+ */
28
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
29
+ import { homedir } from "node:os";
30
+ import { onboardingLockFile, stateDir } from "./fp-home";
31
+
32
+ interface LockBody {
33
+ pid: number;
34
+ startedAt: number;
35
+ }
36
+
37
+ export function onboardingLockPath(home: string = homedir()): string {
38
+ return onboardingLockFile(home);
39
+ }
40
+
41
+ /**
42
+ * Whether `pid` is a live process this user can signal.
43
+ *
44
+ * `kill(pid, 0)` performs the permission and existence checks without
45
+ * delivering a signal. `EPERM` means the process exists but belongs to another
46
+ * user — still alive, so still holding the lock.
47
+ */
48
+ function processAlive(pid: number): boolean {
49
+ if (!Number.isInteger(pid) || pid <= 0) return false;
50
+ try {
51
+ process.kill(pid, 0);
52
+ return true;
53
+ } catch (err) {
54
+ return (err as NodeJS.ErrnoException)?.code === "EPERM";
55
+ }
56
+ }
57
+
58
+ function readLock(path: string): LockBody | null {
59
+ try {
60
+ const parsed = JSON.parse(readFileSync(path, "utf8")) as Partial<LockBody>;
61
+ if (typeof parsed.pid !== "number") return null;
62
+ return { pid: parsed.pid, startedAt: Number(parsed.startedAt) || 0 };
63
+ } catch {
64
+ // Absent, unreadable, or truncated by a crash mid-write. All three mean
65
+ // "no live holder we can prove", and the liveness check below is what
66
+ // actually decides.
67
+ return null;
68
+ }
69
+ }
70
+
71
+ export interface OnboardingLock {
72
+ /** Release the lock. Safe to call more than once. */
73
+ release(): void;
74
+ }
75
+
76
+ /**
77
+ * Take the onboarding lock, or return `null` if another live process holds it.
78
+ *
79
+ * There is a small window between the liveness check and the write in which
80
+ * two processes could both decide the lock is free. That is accepted
81
+ * deliberately: closing it needs `O_EXCL` plus stale-file recovery, which
82
+ * reintroduces exactly the timeout problem this design avoids — and the
83
+ * consequence of losing that race is two wizards, which is the situation
84
+ * before this existed, not something worse.
85
+ */
86
+ export function acquireOnboardingLock(home: string = homedir()): OnboardingLock | null {
87
+ const path = onboardingLockPath(home);
88
+ try {
89
+ const held = readLock(path);
90
+ // Our own PID appearing here means a previous run in this same process
91
+ // already holds it — re-entering is fine and must not deadlock.
92
+ if (held && held.pid !== process.pid && processAlive(held.pid)) return null;
93
+
94
+ mkdirSync(stateDir(home), { recursive: true });
95
+ const body: LockBody = { pid: process.pid, startedAt: Date.now() };
96
+ writeFileSync(path, JSON.stringify(body), "utf8");
97
+
98
+ let released = false;
99
+ return {
100
+ release() {
101
+ if (released) return;
102
+ released = true;
103
+ try {
104
+ // Only remove a lock still recorded as ours: if this process was
105
+ // evicted as dead and another wizard took over, deleting the file
106
+ // would release someone else's lock.
107
+ const current = readLock(path);
108
+ if (!current || current.pid === process.pid) rmSync(path, { force: true });
109
+ } catch {
110
+ /* best effort — a stray lock is reclaimed by the liveness check */
111
+ }
112
+ },
113
+ };
114
+ } catch {
115
+ // Unwritable home, read-only filesystem, whatever it is: treat as held.
116
+ return null;
117
+ }
118
+ }
@@ -80,8 +80,36 @@ export interface LlmConfig {
80
80
  model?: string;
81
81
  }
82
82
 
83
+ /**
84
+ * The collector's non-secret settings. The ingest credential deliberately does
85
+ * NOT live here: this file is written with a bare `writeFileSync`, so it
86
+ * inherits the umask and lands at 0664 inside a 0775 `~/.failproofai/` — an API
87
+ * key here would be readable by every local user. It lives in
88
+ * `~/.failproofai/ingest.json` at 0600 instead.
89
+ *
90
+ * Read by the Rust daemon (`crates/fpai-collect/src/config.rs`); the field
91
+ * names must stay in step with the `Settings` struct there.
92
+ */
93
+ export interface CollectorConfig {
94
+ /**
95
+ * Ship agent session transcripts. Defaults to false and is a SEPARATE opt-in
96
+ * from configuring a key, because transcripts carry prompts, file contents
97
+ * and whatever was pasted into a terminal.
98
+ */
99
+ sessions?: boolean;
100
+ /** Ship hook activity. Carries decisions and tool names, never file contents. */
101
+ hooks?: boolean;
102
+ /** `decisions` keeps every deny/instruct exact and aggregates the ~99% allows. */
103
+ hooksVerbosity?: "all" | "decisions" | "off";
104
+ redact?: "minimal" | "off";
105
+ /** Label stamped on every event. Must not contain a comma — ingest skips those lines. */
106
+ environment?: string;
107
+ }
108
+
83
109
  export interface HooksConfig {
84
110
  enabledPolicies: string[];
111
+ /** Collector settings; see {@link CollectorConfig}. Absent means unconfigured. */
112
+ collector?: CollectorConfig;
85
113
  llm?: LlmConfig;
86
114
  policyParams?: Record<string, Record<string, unknown>>;
87
115
  /** Explicit custom policy files, loaded in array order. */
@@ -0,0 +1,159 @@
1
+ /**
2
+ * `failproofai config --pause | --resume | --status`.
3
+ *
4
+ * Lives on `config` rather than as its own verb because `config` is the single
5
+ * place this product configures anything. The state it writes is NOT config
6
+ * though — see session-pause.ts for why a pause must never reach a file that
7
+ * gets committed.
8
+ */
9
+ import {
10
+ PAUSE_CEILING_MS,
11
+ clearPause,
12
+ formatDuration,
13
+ listActivePauses,
14
+ parsePauseDuration,
15
+ readActivePause,
16
+ resolveSessionForCwd,
17
+ writePause,
18
+ type ActivePause,
19
+ } from "./session-pause";
20
+
21
+ export interface PauseCommandOptions {
22
+ action: "pause" | "resume" | "status";
23
+ /** Raw `--pause <duration>` argument, if any. */
24
+ duration?: string;
25
+ /** Explicit `--session <id>`. */
26
+ sessionId?: string;
27
+ /** `--all`. */
28
+ all?: boolean;
29
+ cwd?: string;
30
+ now?: number;
31
+ }
32
+
33
+ export interface PauseCommandResult {
34
+ exitCode: number;
35
+ lines: string[];
36
+ /** For telemetry; never the session id itself. */
37
+ affected: number;
38
+ }
39
+
40
+ /**
41
+ * The ceiling on a single `--pause`.
42
+ *
43
+ * Took a `cwd` and consulted `readMergedHooksConfig(cwd).maxPauseMs` to let a
44
+ * project LOWER it. That path was dead: the merge in `hooks-config.ts` builds
45
+ * its result field by field and never emits `maxPauseMs`, so the lookup could
46
+ * only ever read `undefined` — and the two tests that claimed to cover it
47
+ * `vi.mock`ed `readMergedHooksConfig` to return a field the real function
48
+ * cannot produce, which is why the gap survived. The knob is removed rather
49
+ * than wired up: nothing documented it, nothing could have used it, and the
50
+ * hard ceiling was doing all the work already.
51
+ *
52
+ * Kept as a function, and still the only thing `--pause` measures against, so
53
+ * reinstating a config lowering later is a change in one place.
54
+ */
55
+ export function effectiveCeilingMs(): number {
56
+ return PAUSE_CEILING_MS;
57
+ }
58
+
59
+ function describe(pause: ActivePause, now: number): string {
60
+ const remaining = formatDuration(Math.max(0, pause.expiresAt - now));
61
+ const at = new Date(pause.expiresAt).toLocaleTimeString();
62
+ const where = pause.cwd ? ` · ${pause.cwd}` : "";
63
+ return ` ${pause.sessionId} ${remaining} left (until ${at})${where}`;
64
+ }
65
+
66
+ export function runPauseCommand(opts: PauseCommandOptions): PauseCommandResult {
67
+ const now = opts.now ?? Date.now();
68
+ const cwd = opts.cwd ?? process.cwd();
69
+
70
+ if (opts.action === "status") {
71
+ const active = listActivePauses(now);
72
+ if (active.length === 0) {
73
+ return { exitCode: 0, lines: ["Enforcement is active — nothing is paused."], affected: 0 };
74
+ }
75
+ return {
76
+ exitCode: 0,
77
+ lines: [
78
+ `Enforcement paused for ${active.length} session${active.length === 1 ? "" : "s"}:`,
79
+ ...active.map((p) => describe(p, now)),
80
+ "",
81
+ "Cloud-managed policies keep enforcing regardless.",
82
+ "Resume early with: failproofai config --resume",
83
+ ],
84
+ affected: active.length,
85
+ };
86
+ }
87
+
88
+ if (opts.action === "resume") {
89
+ if (opts.all) {
90
+ const active = listActivePauses(now);
91
+ let cleared = 0;
92
+ for (const pause of active) if (clearPause(pause.sessionId)) cleared++;
93
+ return {
94
+ exitCode: 0,
95
+ lines: [cleared === 0 ? "Nothing was paused." : `Resumed enforcement for ${cleared} session(s).`],
96
+ affected: cleared,
97
+ };
98
+ }
99
+ const sessionId = opts.sessionId ?? resolveSessionForCwd(cwd, undefined, now);
100
+ if (!sessionId) {
101
+ return { exitCode: 0, lines: ["Nothing was paused for this directory."], affected: 0 };
102
+ }
103
+ const cleared = clearPause(sessionId);
104
+ return {
105
+ exitCode: 0,
106
+ lines: [cleared ? "Enforcement resumed." : "Nothing was paused for that session."],
107
+ affected: cleared ? 1 : 0,
108
+ };
109
+ }
110
+
111
+ // pause
112
+ let durationMs: number;
113
+ try {
114
+ durationMs = parsePauseDuration(opts.duration, effectiveCeilingMs());
115
+ } catch (err) {
116
+ return { exitCode: 1, lines: [err instanceof Error ? err.message : String(err)], affected: 0 };
117
+ }
118
+
119
+ const sessionId = opts.sessionId ?? resolveSessionForCwd(cwd, undefined, now);
120
+ if (!sessionId) {
121
+ // Deliberately an error, not a guess. Pausing the wrong session would leave
122
+ // the user believing enforcement is off while it is on, or vice versa.
123
+ return {
124
+ exitCode: 1,
125
+ lines: [
126
+ "No recent agent session found for this directory.",
127
+ "",
128
+ "A pause applies to one agent session, and the session id only appears once",
129
+ "an agent has run at least one tool call here. Either run your agent first,",
130
+ "or name the session explicitly:",
131
+ "",
132
+ " failproofai config --pause --session <id>",
133
+ "",
134
+ "Session ids are listed in the dashboard's activity view.",
135
+ ],
136
+ affected: 0,
137
+ };
138
+ }
139
+
140
+ const existing = readActivePause(sessionId, now);
141
+ const pause = writePause({ sessionId, durationMs, cwd, setBy: "cli", now });
142
+ const until = new Date(pause.expiresAt).toLocaleTimeString();
143
+
144
+ return {
145
+ exitCode: 0,
146
+ lines: [
147
+ existing
148
+ ? `Enforcement pause extended · ${formatDuration(durationMs)} · resumes at ${until}`
149
+ : `Enforcement paused · ${formatDuration(durationMs)} · resumes at ${until}`,
150
+ "",
151
+ " Builtin, custom and convention policies are suspended for this session.",
152
+ " Cloud-managed policies keep enforcing.",
153
+ "",
154
+ "It lifts on its own — no action needed. To end it early:",
155
+ " failproofai config --resume",
156
+ ],
157
+ affected: 1,
158
+ };
159
+ }