failproofai 1.0.0-beta.4 → 1.0.0-beta.6

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 (369) 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 +3 -3
  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/server-reference-manifest.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page.js +3 -1
  9. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  10. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  14. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  15. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  16. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page.js +3 -1
  20. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  21. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  22. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  24. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  25. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  26. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  27. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  28. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  29. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  30. package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
  31. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -3
  33. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/audit/status/route.js +1 -1
  35. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +2 -1
  37. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +3 -2
  39. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/auth/logout/route.js +3 -2
  41. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +3 -2
  43. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -2
  45. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  47. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  49. package/.next/standalone/.next/server/app/audit/page.js +5 -3
  50. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/app/index.html +1 -1
  53. package/.next/standalone/.next/server/app/index.rsc +15 -15
  54. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  55. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  56. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  57. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  58. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  59. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  60. package/.next/standalone/.next/server/app/page.js +3 -1
  61. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  62. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  63. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +10 -10
  64. package/.next/standalone/.next/server/app/policies/page.js +4 -2
  65. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  68. package/.next/standalone/.next/server/app/project/[name]/page.js +4 -2
  69. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  72. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  73. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +6 -4
  74. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  76. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  77. package/.next/standalone/.next/server/app/projects/page.js +4 -2
  78. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  80. package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
  81. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +18 -0
  82. package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +6 -0
  83. package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
  84. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +53 -0
  85. package/.next/standalone/.next/server/app/settings/page.js +18 -0
  86. package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
  87. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
  88. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
  89. package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
  90. package/.next/standalone/.next/server/chunks/{[externals]__1nl3dvw._.js → [externals]__0r-zamh._.js} +2 -2
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +3 -0
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +3 -0
  95. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g0vcwt._.js +3 -0
  96. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0h3lfmp._.js → [root-of-the-server]__0ky_n0r._.js} +2 -2
  97. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__18d-9oi._.js → [root-of-the-server]__0lk_935._.js} +2 -2
  98. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1p7s8-d._.js → [root-of-the-server]__0pbp9fe._.js} +2 -2
  99. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
  100. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__10oa-v9._.js → [root-of-the-server]__0v2fpxe._.js} +2 -2
  101. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sb_5m8._.js → [root-of-the-server]__131ebum._.js} +3 -3
  102. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-dh5jy._.js → [root-of-the-server]__1_ps0jw._.js} +2 -2
  103. package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l4vuqm._.js → [root-of-the-server]__1a7i2q4._.js} +1 -1
  104. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1iny24d._.js +3 -0
  106. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tyedjt._.js +3 -0
  108. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +5 -0
  109. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +5 -0
  110. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +5 -0
  111. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +5 -5
  112. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06bp_fg._.js +5 -0
  114. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__074qmkp._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +10 -10
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_a_gwn._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1a2hcb_._.js +3 -0
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1e7-pa7._.js +3 -0
  119. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0rtdfof._.js → [root-of-the-server]__1rdruw4._.js} +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +3 -0
  121. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tyf0tc._.js +5 -0
  122. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
  123. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +3 -0
  124. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0rag5dg._.js → [root-of-the-server]__1yw368c._.js} +2 -2
  125. package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +3 -0
  126. package/.next/standalone/.next/server/chunks/ssr/_04mekdy._.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/_0igtyj5._.js +3 -0
  128. package/.next/standalone/.next/server/chunks/ssr/_0r-dsre._.js +3 -0
  129. package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/_0se484m._.js +3 -0
  131. package/.next/standalone/.next/server/chunks/ssr/_0uz7o9y._.js +3 -0
  132. package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
  133. package/.next/standalone/.next/server/chunks/ssr/_1fahg9e._.js +3 -0
  134. package/.next/standalone/.next/server/chunks/ssr/_1gmzkwj._.js +5 -0
  135. package/.next/standalone/.next/server/chunks/ssr/_1w8sola._.js +3 -0
  136. package/.next/standalone/.next/server/chunks/ssr/_1w_6p9g._.js +3 -0
  137. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  138. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  140. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dwo94s.js +4 -0
  141. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +3 -0
  142. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +5 -0
  143. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  144. package/.next/standalone/.next/server/middleware.js +2 -2
  145. package/.next/standalone/.next/server/pages/404.html +1 -1
  146. package/.next/standalone/.next/server/pages/500.html +1 -1
  147. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  148. package/.next/standalone/.next/server/server-reference-manifest.json +54 -12
  149. package/.next/standalone/.next/static/chunks/{2c90h1g6x8z8y.js → 0_2n13i94rnw5.js} +1 -1
  150. package/.next/standalone/.next/static/chunks/1bm0q12hgs22l.css +2 -0
  151. package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
  152. package/.next/standalone/.next/static/chunks/23557z4e6dtsr.js +1 -0
  153. package/.next/standalone/.next/static/chunks/28zkwzu50puki.js +1 -0
  154. package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
  155. package/.next/standalone/.next/static/chunks/3081gykdubv8b.js +1 -0
  156. package/.next/standalone/.next/static/chunks/{06jakt_xhoolk.js → 34fa65k0cldkj.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/35v07j9gc1pvr.js +6 -0
  158. package/.next/standalone/.next/static/chunks/{2zb3m1tzq6h98.js → 3f_939wi3kfnx.js} +22 -22
  159. package/.next/standalone/.next/static/chunks/{31cqiv_cpgj9m.js → 3p1vpm2_-tfwm.js} +1 -1
  160. package/.next/standalone/.next/static/chunks/{0ue9ak_xexiqh.js → 3rbpw_waieafm.js} +1 -1
  161. package/.next/standalone/.next/static/chunks/40ffnfpkeyvb0.js +1 -0
  162. package/.next/standalone/app/actions/get-hooks-config.ts +2 -1
  163. package/.next/standalone/app/actions/get-scheduled-audit.ts +70 -0
  164. package/.next/standalone/app/actions/update-scheduled-audit.ts +44 -0
  165. package/.next/standalone/app/api/audit/run/route.ts +28 -0
  166. package/.next/standalone/app/api/audit/status/route.ts +13 -1
  167. package/.next/standalone/app/api/auth/status/route.ts +1 -1
  168. package/.next/standalone/app/audit/_components/auth-dialog.css +159 -0
  169. package/.next/standalone/app/audit/_components/auth-dialog.tsx +3 -0
  170. package/.next/standalone/app/audit/audit-styles.css +6 -149
  171. package/.next/standalone/app/settings/page.tsx +31 -0
  172. package/.next/standalone/app/settings/settings-client.tsx +488 -0
  173. package/.next/standalone/components/navbar.tsx +2 -0
  174. package/.next/standalone/lib/auth/api-server-client.ts +2 -3
  175. package/.next/standalone/lib/auth/auth-store.ts +4 -4
  176. package/.next/standalone/lib/codex-sessions.ts +2 -1
  177. package/.next/standalone/lib/dashboard-host.ts +101 -0
  178. package/.next/standalone/lib/install-check.ts +22 -7
  179. package/.next/standalone/lib/pi-sessions.ts +99 -14
  180. package/.next/standalone/lib/telemetry-enabled.ts +54 -0
  181. package/.next/standalone/lib/telemetry-id.ts +52 -1
  182. package/.next/standalone/lib/telemetry.ts +8 -4
  183. package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
  184. package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
  185. package/.next/standalone/node_modules/react/package.json +3 -3
  186. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
  187. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
  188. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
  189. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
  190. package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
  191. package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
  192. package/.next/standalone/node_modules/react-dom/package.json +4 -4
  193. package/.next/standalone/package.json +7 -6
  194. package/.next/standalone/proxy.ts +89 -1
  195. package/.next/standalone/server.js +1 -1
  196. package/bin/failproofai.mjs +197 -80
  197. package/dist/cli.mjs +17699 -15345
  198. package/dist/worker.mjs +1620 -257
  199. package/lib/auth/api-server-client.ts +2 -3
  200. package/lib/auth/auth-store.ts +4 -4
  201. package/lib/codex-sessions.ts +2 -1
  202. package/lib/dashboard-host.ts +101 -0
  203. package/lib/install-check.ts +22 -7
  204. package/lib/pi-sessions.ts +99 -14
  205. package/lib/telemetry-enabled.ts +54 -0
  206. package/lib/telemetry-id.ts +52 -1
  207. package/lib/telemetry.ts +8 -4
  208. package/package.json +7 -6
  209. package/scripts/install-telemetry.mjs +8 -1
  210. package/scripts/launch.ts +25 -3
  211. package/scripts/parse-script-args.ts +17 -1
  212. package/scripts/prune-standalone.mjs +20 -0
  213. package/scripts/translate-docs/readme-translator.ts +163 -4
  214. package/scripts/validate-mdx.ts +153 -13
  215. package/src/audit/audit-lock.ts +285 -0
  216. package/src/audit/audit-schedule.ts +111 -0
  217. package/src/audit/cache.ts +18 -4
  218. package/src/audit/cli-adapters/goose.ts +2 -1
  219. package/src/audit/cli-adapters/hermes.ts +28 -10
  220. package/src/audit/cli.ts +191 -35
  221. package/src/audit/dashboard-cache.ts +2 -1
  222. package/src/hooks/builtin-policies.ts +100 -3
  223. package/src/hooks/cloud-connection.ts +163 -14
  224. package/src/hooks/cloud-enrollment-cli.ts +119 -21
  225. package/src/hooks/cloud-enrollment.ts +87 -17
  226. package/src/hooks/cloud-introspect.ts +147 -0
  227. package/src/hooks/cloud-managed-policies.ts +33 -2
  228. package/src/hooks/collector-config.ts +32 -40
  229. package/src/hooks/configure-wizard.ts +696 -318
  230. package/src/hooks/custom-hooks-loader.ts +125 -11
  231. package/src/hooks/daemon-client.ts +83 -17
  232. package/src/hooks/daemon-download.ts +54 -2
  233. package/src/hooks/daemon-service.ts +595 -27
  234. package/src/hooks/first-run-gate.ts +39 -0
  235. package/src/hooks/fp-config.ts +497 -0
  236. package/src/hooks/fp-home.ts +342 -0
  237. package/src/hooks/fp-reset.ts +332 -0
  238. package/src/hooks/handler.ts +42 -1
  239. package/src/hooks/hook-activity-store.ts +35 -20
  240. package/src/hooks/hook-logger.ts +2 -1
  241. package/src/hooks/hook-telemetry.ts +5 -1
  242. package/src/hooks/hooks-config.ts +4 -3
  243. package/src/hooks/loader-utils.ts +166 -5
  244. package/src/hooks/manager.ts +5 -4
  245. package/src/hooks/onboarding-lock.ts +119 -0
  246. package/src/hooks/policy-types.ts +0 -7
  247. package/src/hooks/session-pause-cli.ts +15 -13
  248. package/src/hooks/session-pause.ts +36 -4
  249. package/src/hooks/setup-state.ts +256 -0
  250. package/src/hooks/tui.ts +4 -4
  251. package/src/hooks/worker-server.ts +53 -1
  252. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0f8nu8d._.js +0 -3
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0szqzl8._.js +0 -3
  254. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
  255. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
  256. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
  257. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
  258. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
  259. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
  260. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0cmdyn_._.js +0 -3
  261. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
  262. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
  263. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ls0gsr._.js +0 -4
  264. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n_uvv0._.js +0 -3
  265. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
  266. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0sdrz-j._.js +0 -3
  267. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +0 -4
  268. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
  269. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1j4u3yd._.js +0 -4
  270. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
  271. package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
  272. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1q9xxca.js +0 -3
  273. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
  274. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
  275. package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
  276. package/.next/standalone/.next/static/chunks/0oe2-hp0_2tzs.js +0 -6
  277. package/.next/standalone/.next/static/chunks/1fw3pxobk_otl.js +0 -1
  278. package/.next/standalone/.next/static/chunks/3h5_3u46gu9jx.js +0 -1
  279. package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
  280. package/.next/standalone/.next/static/chunks/3zdwnnthucs_1.css +0 -2
  281. package/.next/standalone/.next/static/chunks/43a1ywqsg9bq9.js +0 -1
  282. package/.next/standalone/Cargo.lock +0 -2222
  283. package/.next/standalone/Cargo.toml +0 -9
  284. package/.next/standalone/crates/CLOUD_POLICIES.md +0 -136
  285. package/.next/standalone/crates/PROTOCOL.md +0 -122
  286. package/.next/standalone/crates/failproofaid/Cargo.toml +0 -25
  287. package/.next/standalone/crates/failproofaid/src/cloud_client.rs +0 -484
  288. package/.next/standalone/crates/failproofaid/src/cloud_policies.rs +0 -921
  289. package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
  290. package/.next/standalone/crates/failproofaid/src/main.rs +0 -532
  291. package/.next/standalone/crates/failproofaid/src/paths.rs +0 -201
  292. package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
  293. package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
  294. package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
  295. package/.next/standalone/crates/fpai-collect/Cargo.toml +0 -43
  296. package/.next/standalone/crates/fpai-collect/src/config.rs +0 -412
  297. package/.next/standalone/crates/fpai-collect/src/cursor.rs +0 -520
  298. package/.next/standalone/crates/fpai-collect/src/delivery.rs +0 -472
  299. package/.next/standalone/crates/fpai-collect/src/filetail.rs +0 -484
  300. package/.next/standalone/crates/fpai-collect/src/health.rs +0 -369
  301. package/.next/standalone/crates/fpai-collect/src/lib.rs +0 -34
  302. package/.next/standalone/crates/fpai-collect/src/redact.rs +0 -516
  303. package/.next/standalone/crates/fpai-collect/src/sources/claude/mod.rs +0 -279
  304. package/.next/standalone/crates/fpai-collect/src/sources/claude/transform.rs +0 -619
  305. package/.next/standalone/crates/fpai-collect/src/sources/codex/mod.rs +0 -156
  306. package/.next/standalone/crates/fpai-collect/src/sources/codex/transform.rs +0 -715
  307. package/.next/standalone/crates/fpai-collect/src/sources/copilot/mod.rs +0 -158
  308. package/.next/standalone/crates/fpai-collect/src/sources/copilot/transform.rs +0 -512
  309. package/.next/standalone/crates/fpai-collect/src/sources/goose/mod.rs +0 -511
  310. package/.next/standalone/crates/fpai-collect/src/sources/goose/transform.rs +0 -586
  311. package/.next/standalone/crates/fpai-collect/src/sources/hermes/mod.rs +0 -318
  312. package/.next/standalone/crates/fpai-collect/src/sources/hermes/transform.rs +0 -579
  313. package/.next/standalone/crates/fpai-collect/src/sources/hooks/mod.rs +0 -310
  314. package/.next/standalone/crates/fpai-collect/src/sources/hooks/transform.rs +0 -448
  315. package/.next/standalone/crates/fpai-collect/src/sources/mod.rs +0 -23
  316. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/mod.rs +0 -176
  317. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/transform.rs +0 -500
  318. package/.next/standalone/crates/fpai-collect/src/sources/opencode/mod.rs +0 -315
  319. package/.next/standalone/crates/fpai-collect/src/sources/opencode/transform.rs +0 -493
  320. package/.next/standalone/crates/fpai-collect/src/sources/pi/mod.rs +0 -201
  321. package/.next/standalone/crates/fpai-collect/src/sources/pi/transform.rs +0 -533
  322. package/.next/standalone/crates/fpai-collect/src/spool.rs +0 -458
  323. package/.next/standalone/crates/fpai-collect/src/sqlitepoll.rs +0 -387
  324. package/.next/standalone/crates/fpai-collect/src/supervisor.rs +0 -423
  325. package/.next/standalone/crates/fpai-collect/src/uploader.rs +0 -600
  326. package/.next/standalone/crates/fpai-collect/tests/claude_source.rs +0 -738
  327. package/.next/standalone/crates/fpai-collect/tests/claude_subagents.rs +0 -393
  328. package/.next/standalone/crates/fpai-collect/tests/codex_source.rs +0 -975
  329. package/.next/standalone/crates/fpai-collect/tests/config.rs +0 -286
  330. package/.next/standalone/crates/fpai-collect/tests/copilot_source.rs +0 -1019
  331. package/.next/standalone/crates/fpai-collect/tests/delivery.rs +0 -281
  332. package/.next/standalone/crates/fpai-collect/tests/goose_source.rs +0 -1008
  333. package/.next/standalone/crates/fpai-collect/tests/hermes_source.rs +0 -1129
  334. package/.next/standalone/crates/fpai-collect/tests/hooks_source.rs +0 -621
  335. package/.next/standalone/crates/fpai-collect/tests/openclaw_source.rs +0 -854
  336. package/.next/standalone/crates/fpai-collect/tests/opencode_source.rs +0 -1478
  337. package/.next/standalone/crates/fpai-collect/tests/pi_source.rs +0 -1191
  338. package/.next/standalone/crates/fpai-collect/tests/supervisor.rs +0 -290
  339. package/.next/standalone/crates/fpai-collect/tests/uploader.rs +0 -506
  340. package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
  341. package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
  342. package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
  343. package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
  344. package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
  345. package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
  346. package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
  347. package/.next/standalone/integration-suite/Dockerfile +0 -47
  348. package/.next/standalone/integration-suite/README.md +0 -129
  349. package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
  350. package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
  351. package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
  352. package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
  353. package/.next/standalone/integration-suite/install-clis.sh +0 -136
  354. package/.next/standalone/integration-suite/probe-cli.sh +0 -248
  355. package/.next/standalone/integration-suite/report.js +0 -120
  356. package/.next/standalone/integration-suite/run.sh +0 -159
  357. package/.next/standalone/openclaw-plugin/index.js +0 -223
  358. package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
  359. package/.next/standalone/openclaw-plugin/package.json +0 -12
  360. package/.next/standalone/osv-scanner.toml +0 -17
  361. package/.next/standalone/pi-extension/index.ts +0 -524
  362. package/.next/standalone/pi-extension/package.json +0 -12
  363. package/.next/standalone/postcss.config.mjs +0 -8
  364. package/.next/standalone/readme-arch-hq.gif +0 -0
  365. package/.next/standalone/rust-toolchain.toml +0 -4
  366. package/src/auth/cli.ts +0 -371
  367. /package/.next/standalone/.next/static/{StV6Lay7Q1cU4ysYCFJmH → Ptn8aBQl_cnNgOd0ebyv0}/_buildManifest.js +0 -0
  368. /package/.next/standalone/.next/static/{StV6Lay7Q1cU4ysYCFJmH → Ptn8aBQl_cnNgOd0ebyv0}/_clientMiddlewareManifest.js +0 -0
  369. /package/.next/standalone/.next/static/{StV6Lay7Q1cU4ysYCFJmH → Ptn8aBQl_cnNgOd0ebyv0}/_ssgManifest.js +0 -0
@@ -126,13 +126,6 @@ export interface HooksConfig {
126
126
  * Only ever written explicitly as `false`.
127
127
  */
128
128
  customPoliciesEnabled?: boolean;
129
- /**
130
- * Upper bound, in ms, on how long `failproofai config --pause` may suspend
131
- * enforcement. Only ever LOWERS the built-in 8h ceiling — a value above it is
132
- * clamped back down, because a ceiling a project can raise is not a ceiling.
133
- * Absent means the built-in ceiling applies.
134
- */
135
- maxPauseMs?: number;
136
129
  /**
137
130
  * Record of the convention policies (`.failproofai/policies/*policies.mjs`)
138
131
  * discovered at this scope the last time a failproofai command ran.
@@ -17,7 +17,6 @@ import {
17
17
  writePause,
18
18
  type ActivePause,
19
19
  } from "./session-pause";
20
- import { readMergedHooksConfig } from "./hooks-config";
21
20
 
22
21
  export interface PauseCommandOptions {
23
22
  action: "pause" | "resume" | "status";
@@ -39,18 +38,21 @@ export interface PauseCommandResult {
39
38
  }
40
39
 
41
40
  /**
42
- * The ceiling, after any config lowering. A project may tighten this; nothing
43
- * may loosen it, so a config asking for 24h still gets 8h.
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.
44
54
  */
45
- export function effectiveCeilingMs(cwd?: string): number {
46
- try {
47
- const configured = readMergedHooksConfig(cwd).maxPauseMs;
48
- if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) {
49
- return Math.min(configured, PAUSE_CEILING_MS);
50
- }
51
- } catch {
52
- // An unreadable config must not remove the ceiling.
53
- }
55
+ export function effectiveCeilingMs(): number {
54
56
  return PAUSE_CEILING_MS;
55
57
  }
56
58
 
@@ -109,7 +111,7 @@ export function runPauseCommand(opts: PauseCommandOptions): PauseCommandResult {
109
111
  // pause
110
112
  let durationMs: number;
111
113
  try {
112
- durationMs = parsePauseDuration(opts.duration, effectiveCeilingMs(cwd));
114
+ durationMs = parsePauseDuration(opts.duration, effectiveCeilingMs());
113
115
  } catch (err) {
114
116
  return { exitCode: 1, lines: [err instanceof Error ? err.message : String(err)], affected: 0 };
115
117
  }
@@ -27,6 +27,7 @@ import { createHash } from "node:crypto";
27
27
  import { join, resolve } from "node:path";
28
28
  import { writeJsonAtomically } from "../../lib/atomic-write";
29
29
  import { getAllHookActivityEntries } from "./hook-activity-store";
30
+ import { sessionPauseDir } from "./fp-home";
30
31
 
31
32
  const SCHEMA_VERSION = 1;
32
33
 
@@ -44,6 +45,19 @@ export interface ActivePause {
44
45
  sessionId: string;
45
46
  /** Epoch ms. */
46
47
  pausedAt: number;
48
+ /**
49
+ * Epoch ms of the FIRST pause in this unbroken run, which the ceiling is
50
+ * measured from.
51
+ *
52
+ * `pausedAt` moves to now on every renewal, so a ceiling measured from it is
53
+ * not a ceiling at all: `--pause 8h` every seven hours suspends enforcement
54
+ * indefinitely, one legal command at a time, and each individual pause passes
55
+ * every check. This field is what makes 8h mean 8h. Carried forward by
56
+ * `writePause` while a pause is still live, and reset once one has expired —
57
+ * the limit is on how long enforcement can stay off in one stretch, not a
58
+ * daily quota.
59
+ */
60
+ firstPausedAt: number;
47
61
  /** Epoch ms. Always finite — there is no unbounded pause. */
48
62
  expiresAt: number;
49
63
  /** Free-form provenance, e.g. "cli". Recorded so the activity log can say who. */
@@ -59,7 +73,7 @@ interface StoredPause extends ActivePause {
59
73
  export function pauseStateDir(): string {
60
74
  const override = process.env.FAILPROOFAI_STATE_DIR;
61
75
  if (override) return resolve(override, "sessions");
62
- return join(homedir(), ".failproofai", "state", "sessions");
76
+ return sessionPauseDir();
63
77
  }
64
78
 
65
79
  /**
@@ -119,11 +133,22 @@ function parseStored(raw: unknown): StoredPause | null {
119
133
  if (p.schemaVersion !== SCHEMA_VERSION) return null;
120
134
  if (typeof p.sessionId !== "string" || p.sessionId.length === 0) return null;
121
135
  if (!Number.isFinite(p.pausedAt) || !Number.isFinite(p.expiresAt)) return null;
136
+ const pausedAt = p.pausedAt as number;
137
+ // A file written before this field existed measures its ceiling from the
138
+ // only start it recorded. Same meaning for a pause that was never renewed.
139
+ const firstPausedAt = Number.isFinite(p.firstPausedAt) ? (p.firstPausedAt as number) : pausedAt;
122
140
  return {
123
141
  schemaVersion: SCHEMA_VERSION,
124
142
  sessionId: p.sessionId,
125
- pausedAt: p.pausedAt as number,
126
- expiresAt: p.expiresAt as number,
143
+ pausedAt,
144
+ firstPausedAt,
145
+ // Clamped at READ time, not only at write. The ceiling has to hold against
146
+ // a file this process did not write: `~/.failproofai/state/sessions/` is
147
+ // owner-writable by design, and an `expiresAt` a year out would otherwise
148
+ // be honoured on every subsequent tool call forever. Enforcing it here
149
+ // means the bound is a property of the pause, not of the path that created
150
+ // it.
151
+ expiresAt: Math.min(p.expiresAt as number, firstPausedAt + PAUSE_CEILING_MS),
127
152
  setBy: typeof p.setBy === "string" ? p.setBy : "unknown",
128
153
  ...(typeof p.cwd === "string" ? { cwd: p.cwd } : {}),
129
154
  };
@@ -159,10 +184,17 @@ export function writePause(opts: {
159
184
  now?: number;
160
185
  }): ActivePause {
161
186
  const now = opts.now ?? Date.now();
187
+ // Carry the run's original start forward while a pause is still live, so a
188
+ // renewal extends the same stretch rather than starting a fresh ceiling.
189
+ const existing = readActivePause(opts.sessionId, now);
190
+ const firstPausedAt = existing?.firstPausedAt ?? now;
162
191
  const pause: ActivePause = {
163
192
  sessionId: opts.sessionId,
164
193
  pausedAt: now,
165
- expiresAt: now + opts.durationMs,
194
+ firstPausedAt,
195
+ // The requested duration, but never past the ceiling measured from the
196
+ // start of the run. A renewal can shorten a pause; it cannot outrun 8h.
197
+ expiresAt: Math.min(now + opts.durationMs, firstPausedAt + PAUSE_CEILING_MS),
166
198
  setBy: opts.setBy ?? "cli",
167
199
  ...(opts.cwd ? { cwd: opts.cwd } : {}),
168
200
  };
@@ -0,0 +1,256 @@
1
+ /**
2
+ * What is already set up on this machine, and where.
3
+ *
4
+ * Two questions live here, both of which used to be answered ad hoc in two
5
+ * different places:
6
+ *
7
+ * 1. "Has this user ever completed setup?" — drives first-run onboarding.
8
+ * 2. "Is this cwd a project, a home directory, or both?" — drives which
9
+ * scope the wizard offers to configure.
10
+ *
11
+ * Both are pure functions over the filesystem so they can be unit-tested
12
+ * without a TTY, a wizard, or a real home directory. Every path is derived
13
+ * from an injectable `home`/`cwd` rather than read from the environment at
14
+ * call time, because the wizard, the CLI entry point and the tests each have
15
+ * a different idea of where "home" is.
16
+ */
17
+ import { existsSync, realpathSync, statSync } from "node:fs";
18
+ import { dirname, resolve } from "node:path";
19
+ import { homedir } from "node:os";
20
+ import { getIntegration } from "./integrations";
21
+ import { INTEGRATION_TYPES } from "./types";
22
+ import { globalPolicyConfigFile, launcherMarker as layoutLauncherMarker } from "./fp-home";
23
+
24
+ /** Which config a wizard run is going to write. */
25
+ export type SetupTarget = "user" | "project" | "both";
26
+
27
+ export interface SetupState {
28
+ /** Absolute cwd this was resolved against. */
29
+ cwd: string;
30
+ /** Absolute home directory this was resolved against. */
31
+ home: string;
32
+ /**
33
+ * The directory a project-scope write would land in — the nearest ancestor
34
+ * holding a `.failproofai/`, else `cwd` itself. Never the home directory:
35
+ * `~/.failproofai` is the GLOBAL config, and treating it as a project root
36
+ * would make a wizard run from `~` offer to "configure this project" and
37
+ * then write the global file under a project label.
38
+ */
39
+ projectRoot: string;
40
+ /** `~/.failproofai/policies-config.json` exists. */
41
+ hasGlobalConfig: boolean;
42
+ /** `<projectRoot>/.failproofai/policies-config.json` exists. */
43
+ hasProjectConfig: boolean;
44
+ /** Any agent CLI has failproofai hooks installed at user scope. */
45
+ hasGlobalHooks: boolean;
46
+ /** The legacy first-run marker written by earlier versions. */
47
+ hasLegacyMarker: boolean;
48
+ /** cwd resolves to the home directory itself. */
49
+ inHomeDir: boolean;
50
+ }
51
+
52
+ export function globalConfigPath(home: string = homedir()): string {
53
+ return globalPolicyConfigFile(home);
54
+ }
55
+
56
+ export function projectConfigPath(projectRoot: string): string {
57
+ return resolve(projectRoot, ".failproofai", "policies-config.json");
58
+ }
59
+
60
+ function legacyMarkerPath(home: string): string {
61
+ return layoutLauncherMarker(home);
62
+ }
63
+
64
+ function isDir(path: string): boolean {
65
+ try {
66
+ return statSync(path).isDirectory();
67
+ } catch {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * The nearest ancestor of `start` holding a `.failproofai/` directory, or
74
+ * `start` itself when there is none.
75
+ *
76
+ * Mirrors `hooks-config.findProjectConfigDir`, but takes `home` as a
77
+ * parameter instead of calling `homedir()` — the wizard needs to resolve this
78
+ * against a caller-supplied home in tests, and the two must not disagree
79
+ * about where the walk stops or the wizard would offer to write a project
80
+ * config at a path the policy loader never reads.
81
+ */
82
+ export function findProjectRoot(start: string, home: string = homedir()): string {
83
+ // Both sides real-resolved for the same reason `detectSetupState` does it:
84
+ // a symlinked home would never equal the walked path, so the walk would run
85
+ // straight past home and could claim `~` — whose `.failproofai/` is the
86
+ // global config — as a project root.
87
+ const resolvedHome = realResolve(home);
88
+ let dir = realResolve(start);
89
+ while (dir !== resolvedHome) {
90
+ if (isDir(resolve(dir, ".failproofai"))) return dir;
91
+ const parent = dirname(dir);
92
+ if (parent === dir) break;
93
+ dir = parent;
94
+ }
95
+ return resolve(start);
96
+ }
97
+
98
+ /**
99
+ * Whether any agent CLI carries failproofai hooks at user scope.
100
+ *
101
+ * Deliberately ignores project scope: a checkout that happens to contain
102
+ * committed project hooks (this repo does) must not convince the wizard that
103
+ * the MACHINE has been set up.
104
+ */
105
+ export function hasGlobalHooksInstalled(): boolean {
106
+ for (const id of INTEGRATION_TYPES) {
107
+ try {
108
+ if (getIntegration(id).hooksInstalledInSettings("user")) return true;
109
+ } catch {
110
+ // A malformed settings file is not evidence of an install.
111
+ }
112
+ }
113
+ return false;
114
+ }
115
+
116
+ /**
117
+ * `resolve()` plus symlink resolution, falling back to the lexical path.
118
+ *
119
+ * `$HOME` is very often a symlink (`/home/x` → `/mnt/data/x`, macOS
120
+ * `/tmp` → `/private/tmp`) while a shell's cwd reports the real path. Compared
121
+ * lexically, the two never match: `inHomeDir` reads false while standing in
122
+ * home, and the wizard offers to "configure this project" pointing at the home
123
+ * directory — whose `.failproofai/` is the GLOBAL config. Comparing real paths
124
+ * is what makes "am I in my home directory" answerable.
125
+ *
126
+ * Falls back to the lexical path when the target does not exist (a cwd that
127
+ * has been deleted, a home that has not been created yet), because a missing
128
+ * path is not a reason to fail detection.
129
+ */
130
+ function realResolve(path: string): string {
131
+ const lexical = resolve(path);
132
+ try {
133
+ return realpathSync(lexical);
134
+ } catch {
135
+ return lexical;
136
+ }
137
+ }
138
+
139
+ export function detectSetupState(
140
+ cwd: string = process.cwd(),
141
+ home: string = homedir(),
142
+ ): SetupState {
143
+ const resolvedCwd = realResolve(cwd);
144
+ const resolvedHome = realResolve(home);
145
+ const projectRoot = findProjectRoot(resolvedCwd, resolvedHome);
146
+
147
+ return {
148
+ cwd: resolvedCwd,
149
+ home: resolvedHome,
150
+ projectRoot,
151
+ hasGlobalConfig: existsSync(globalConfigPath(resolvedHome)),
152
+ // When cwd IS home, `projectRoot` is home and its `.failproofai` is the
153
+ // global config — reporting that as a project config would double-count
154
+ // one file as two scopes and offer "Both" for a single target.
155
+ hasProjectConfig:
156
+ projectRoot !== resolvedHome && existsSync(projectConfigPath(projectRoot)),
157
+ hasGlobalHooks: hasGlobalHooksInstalled(),
158
+ hasLegacyMarker: existsSync(legacyMarkerPath(resolvedHome)),
159
+ inHomeDir: resolvedCwd === resolvedHome,
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Whether this machine has ever completed setup.
165
+ *
166
+ * Deliberately NOT just the marker file. The marker is one of three
167
+ * independent signals, and any of them means "configured":
168
+ *
169
+ * • a global policies-config.json — the wizard, or `policies --install`,
170
+ * has written real configuration
171
+ * • user-scope hooks in any agent CLI — enforcement is live even if the
172
+ * config file was hand-deleted
173
+ * • the legacy marker — so users onboarded by an earlier version are never
174
+ * shown the wizard a second time
175
+ *
176
+ * Relying on the marker alone made deleting one file re-run onboarding on a
177
+ * fully configured machine; relying on hooks alone re-ran it for anyone who
178
+ * had uninstalled hooks but kept their policy config. Requiring all three
179
+ * would never fire for a genuinely fresh install. The union is the only
180
+ * combination that is right in each case.
181
+ */
182
+ export function isConfigured(state: SetupState = detectSetupState()): boolean {
183
+ return state.hasGlobalConfig || state.hasGlobalHooks || state.hasLegacyMarker;
184
+ }
185
+
186
+ export interface TargetChoice {
187
+ label: string;
188
+ value: SetupTarget;
189
+ hint: string;
190
+ /** True when this target would UPDATE existing config rather than create it. */
191
+ existing: boolean;
192
+ }
193
+
194
+ /**
195
+ * The scope choices to offer, ordered so the most likely intent is first
196
+ * (and therefore pre-selected).
197
+ *
198
+ * The ordering rule is "what did the user point us at": run from inside a
199
+ * project, the project comes first; run from home — where there is no project
200
+ * to configure — only the global row is offered, because a "Just this
201
+ * project" row pointing at `~` would write `~/.failproofai/` and call the
202
+ * machine-wide config a project.
203
+ */
204
+ export function buildTargetChoices(state: SetupState): TargetChoice[] {
205
+ const globalRow: TargetChoice = {
206
+ label: state.hasGlobalConfig ? "Update my global policies" : "Set up global policies",
207
+ value: "user",
208
+ hint: "applies in every project on this machine",
209
+ existing: state.hasGlobalConfig,
210
+ };
211
+
212
+ // From home (or anywhere with no project marker above it) there is no
213
+ // second target to offer.
214
+ if (state.inHomeDir || state.projectRoot === state.home) {
215
+ return [globalRow];
216
+ }
217
+
218
+ const projectRow: TargetChoice = {
219
+ label: state.hasProjectConfig
220
+ ? "Update this project's policies"
221
+ : "Set up this project's policies",
222
+ value: "project",
223
+ hint: homeify(state.projectRoot, state.home),
224
+ existing: state.hasProjectConfig,
225
+ };
226
+
227
+ const bothRow: TargetChoice = {
228
+ label: "Both",
229
+ value: "both",
230
+ hint: "global defaults, plus overrides for this project",
231
+ existing: state.hasGlobalConfig && state.hasProjectConfig,
232
+ };
233
+
234
+ // Inside a project, the project is the likelier intent — unless nothing
235
+ // global exists yet, in which case the machine has never been set up and
236
+ // configuring only this one project would leave every other project
237
+ // unprotected without saying so.
238
+ return state.hasGlobalConfig
239
+ ? [projectRow, globalRow, bothRow]
240
+ : [globalRow, projectRow, bothRow];
241
+ }
242
+
243
+ /** `/home/x/y` → `~/y`, for display only. */
244
+ export function homeify(path: string, home: string = homedir()): string {
245
+ const resolvedHome = resolve(home);
246
+ const resolvedPath = resolve(path);
247
+ if (resolvedPath === resolvedHome) return "~";
248
+ return resolvedPath.startsWith(resolvedHome + "/")
249
+ ? `~${resolvedPath.slice(resolvedHome.length)}`
250
+ : resolvedPath;
251
+ }
252
+
253
+ /** The scopes a `SetupTarget` expands to. */
254
+ export function scopesFor(target: SetupTarget): Array<"user" | "project"> {
255
+ return target === "both" ? ["user", "project"] : [target];
256
+ }
package/src/hooks/tui.ts CHANGED
@@ -112,10 +112,10 @@ export function colorsEnabled(out: TTYOut): boolean {
112
112
 
113
113
  /**
114
114
  * The raw ANSI opening sequence for a brand role, for callers that assemble
115
- * their own strings instead of using `paint()`'s wrappers (`src/audit/cli.ts`,
116
- * `src/auth/cli.ts`). Those files previously hardcoded their own 256-colour
117
- * palette — a green and a blue that appear nowhere in the brand — so `audit`
118
- * and `auth` looked like different products from `config`. Routing them here
115
+ * their own strings instead of using `paint()`'s wrappers (`src/audit/cli.ts`).
116
+ * That file previously hardcoded its own 256-colour palette — a green and a
117
+ * blue that appear nowhere in the brand — so `audit` looked like a different
118
+ * product from `config`. Routing it here
119
119
  * keeps HUES the single source of truth: change a hue once and every surface
120
120
  * follows. Emits truecolor where the terminal advertises it, basic ANSI
121
121
  * otherwise; the caller still decides *whether* to colour at all.
@@ -54,15 +54,67 @@ function encodeFrame(value: unknown): Buffer {
54
54
  return Buffer.concat([header, body]);
55
55
  }
56
56
 
57
+ /**
58
+ * Last-resort deadline on a single queued task.
59
+ *
60
+ * Deliberately far above `daemon-client.ts`'s 30s `DAEMON_RESPONSE_TIMEOUT_MS`:
61
+ * by the time this fires the client has long since given up and fail-closed, so
62
+ * nothing legitimate is waiting. It exists only to detect a task that will never
63
+ * settle at all.
64
+ */
65
+ const TASK_DEADLINE_MS = 60_000;
66
+
57
67
  /**
58
68
  * Serializes every request across every connection through one chain, so
59
69
  * `evaluateHookEvent` calls never overlap. `.catch()` on each link keeps the
60
70
  * chain alive even if a handler throws unexpectedly — one bad request must
61
71
  * never wedge every request queued behind it.
72
+ *
73
+ * `.catch()` covers a task that REJECTS. It does nothing for one that never
74
+ * SETTLES, and that state is reachable: a policy file with a top-level `await`
75
+ * that never resolves hangs its `import()`, so the task neither resolves nor
76
+ * rejects and every hook queued behind it waits forever. Each client then burns
77
+ * its own 30s budget and fail-closed denies — every tool call, every CLI on the
78
+ * machine, until someone restarts the daemon. This is a class the warm worker
79
+ * creates: in the one-shot path the identical file hangs one hook process and
80
+ * the agent CLI's own timeout reaps it.
81
+ *
82
+ * `custom-hooks-loader.ts` bounds that import directly, which is the graceful
83
+ * fix and covers the known cause. This is the backstop for the ones nobody
84
+ * thought of, and it EXITS rather than continuing: the orphaned task is still
85
+ * running and still holds the `globalThis` policy registry this chain exists to
86
+ * serialize access to, so letting the next request proceed would trade a wedge
87
+ * for silent cross-request registry corruption. Exiting hands the supervisor a
88
+ * process it will respawn clean (`worker.rs`'s `ensure_started` respawns a
89
+ * worker whose `try_wait()` reports it gone), which costs one cold start and
90
+ * denies the in-flight requests — the same fail-closed outcome they were headed
91
+ * for anyway, but recovered on the next call instead of never.
62
92
  */
93
+ const WEDGED_EXIT_CODE = 75;
94
+
63
95
  let processingChain: Promise<void> = Promise.resolve();
64
96
  function enqueue(task: () => Promise<void>): void {
65
- processingChain = processingChain.then(task).catch(() => {});
97
+ processingChain = processingChain
98
+ .then(
99
+ () =>
100
+ new Promise<void>((settle) => {
101
+ const timer = setTimeout(() => {
102
+ hookLogWarn(
103
+ `worker: a request did not settle within ${TASK_DEADLINE_MS}ms; ` +
104
+ `exiting so the supervisor can respawn a clean worker`,
105
+ );
106
+ process.exit(WEDGED_EXIT_CODE);
107
+ }, TASK_DEADLINE_MS);
108
+ // Never let the deadline itself hold the event loop open.
109
+ timer.unref?.();
110
+ const done = () => {
111
+ clearTimeout(timer);
112
+ settle();
113
+ };
114
+ void task().then(done, done);
115
+ }),
116
+ )
117
+ .catch(() => {});
66
118
  }
67
119
 
68
120
  function handleConnection(socket: Socket): void {