failproofai 1.0.0-beta.5 → 1.0.0-beta.7

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 (368) 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]__0c_qcgp._.js +3 -0
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0kbc9bs._.js +3 -0
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +10 -10
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1a2hcb_._.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/_0r-dsre._.js +3 -0
  128. package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
  129. package/.next/standalone/.next/server/chunks/ssr/_0se484m._.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/_0uz7o9y._.js +3 -0
  131. package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
  132. package/.next/standalone/.next/server/chunks/ssr/_194yh9u._.js +3 -0
  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/0945ybz3fsvba.js +1 -0
  150. package/.next/standalone/.next/static/chunks/{0cr85wuc9gc9k.js → 0gr76ps8_zm26.js} +1 -1
  151. package/.next/standalone/.next/static/chunks/{2cqk4a9s893oy.js → 0m-m7wgtxdoav.js} +1 -1
  152. package/.next/standalone/.next/static/chunks/{1tp9dex23zs8y.js → 11l6oh9cyb35a.js} +1 -1
  153. package/.next/standalone/.next/static/chunks/166f8qnh03jqc.js +6 -0
  154. package/.next/standalone/.next/static/chunks/1bm0q12hgs22l.css +2 -0
  155. package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
  156. package/.next/standalone/.next/static/chunks/{2s9g1dsde_ts1.js → 2aej0vi1fm87m.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/{1bkynffp3q1f7.js → 2bxld6-rym3ah.js} +22 -22
  158. package/.next/standalone/.next/static/chunks/{2v1rpzrh2i1wv.js → 2p2kz4aj1tooj.js} +1 -1
  159. package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
  160. package/.next/standalone/.next/static/chunks/36pc3_8fpb6ic.js +1 -0
  161. package/.next/standalone/.next/static/chunks/{2k285z07qce47.js → 3t1wr_kx6brwc.js} +1 -1
  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 +202 -86
  197. package/dist/cli.mjs +17803 -15346
  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 +160 -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 +25 -43
  229. package/src/hooks/configure-wizard.ts +750 -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 +605 -29
  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 +355 -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-attempt.ts +179 -0
  246. package/src/hooks/onboarding-lock.ts +119 -0
  247. package/src/hooks/policy-types.ts +0 -7
  248. package/src/hooks/session-pause-cli.ts +15 -13
  249. package/src/hooks/session-pause.ts +36 -4
  250. package/src/hooks/setup-state.ts +256 -0
  251. package/src/hooks/tui.ts +4 -4
  252. package/src/hooks/worker-server.ts +53 -1
  253. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0f8nu8d._.js +0 -3
  254. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0szqzl8._.js +0 -3
  255. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
  256. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
  257. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
  258. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
  259. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
  260. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
  261. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__094nop3._.js +0 -3
  262. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
  263. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
  264. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ls0gsr._.js +0 -4
  265. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n_uvv0._.js +0 -3
  266. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
  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]__1gak4pd._.js +0 -3
  270. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1j4u3yd._.js +0 -4
  271. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
  272. package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
  273. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_12c_2cz.js +0 -3
  274. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
  275. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
  276. package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
  277. package/.next/standalone/.next/static/chunks/1bw4dfzflelcv.js +0 -1
  278. package/.next/standalone/.next/static/chunks/34sjdw8lv46e3.js +0 -6
  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/Cargo.lock +0 -2222
  282. package/.next/standalone/Cargo.toml +0 -9
  283. package/.next/standalone/crates/CLOUD_POLICIES.md +0 -136
  284. package/.next/standalone/crates/PROTOCOL.md +0 -122
  285. package/.next/standalone/crates/failproofaid/Cargo.toml +0 -25
  286. package/.next/standalone/crates/failproofaid/src/cloud_client.rs +0 -484
  287. package/.next/standalone/crates/failproofaid/src/cloud_policies.rs +0 -921
  288. package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
  289. package/.next/standalone/crates/failproofaid/src/main.rs +0 -639
  290. package/.next/standalone/crates/failproofaid/src/paths.rs +0 -201
  291. package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
  292. package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
  293. package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
  294. package/.next/standalone/crates/fpai-collect/Cargo.toml +0 -43
  295. package/.next/standalone/crates/fpai-collect/src/config.rs +0 -420
  296. package/.next/standalone/crates/fpai-collect/src/cursor.rs +0 -520
  297. package/.next/standalone/crates/fpai-collect/src/delivery.rs +0 -472
  298. package/.next/standalone/crates/fpai-collect/src/filetail.rs +0 -487
  299. package/.next/standalone/crates/fpai-collect/src/health.rs +0 -369
  300. package/.next/standalone/crates/fpai-collect/src/lib.rs +0 -34
  301. package/.next/standalone/crates/fpai-collect/src/redact.rs +0 -516
  302. package/.next/standalone/crates/fpai-collect/src/sources/claude/mod.rs +0 -279
  303. package/.next/standalone/crates/fpai-collect/src/sources/claude/transform.rs +0 -619
  304. package/.next/standalone/crates/fpai-collect/src/sources/codex/mod.rs +0 -156
  305. package/.next/standalone/crates/fpai-collect/src/sources/codex/transform.rs +0 -715
  306. package/.next/standalone/crates/fpai-collect/src/sources/copilot/mod.rs +0 -158
  307. package/.next/standalone/crates/fpai-collect/src/sources/copilot/transform.rs +0 -512
  308. package/.next/standalone/crates/fpai-collect/src/sources/goose/mod.rs +0 -511
  309. package/.next/standalone/crates/fpai-collect/src/sources/goose/transform.rs +0 -586
  310. package/.next/standalone/crates/fpai-collect/src/sources/hermes/mod.rs +0 -318
  311. package/.next/standalone/crates/fpai-collect/src/sources/hermes/transform.rs +0 -579
  312. package/.next/standalone/crates/fpai-collect/src/sources/hooks/mod.rs +0 -314
  313. package/.next/standalone/crates/fpai-collect/src/sources/hooks/transform.rs +0 -448
  314. package/.next/standalone/crates/fpai-collect/src/sources/mod.rs +0 -23
  315. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/mod.rs +0 -176
  316. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/transform.rs +0 -500
  317. package/.next/standalone/crates/fpai-collect/src/sources/opencode/mod.rs +0 -315
  318. package/.next/standalone/crates/fpai-collect/src/sources/opencode/transform.rs +0 -493
  319. package/.next/standalone/crates/fpai-collect/src/sources/pi/mod.rs +0 -201
  320. package/.next/standalone/crates/fpai-collect/src/sources/pi/transform.rs +0 -533
  321. package/.next/standalone/crates/fpai-collect/src/spool.rs +0 -535
  322. package/.next/standalone/crates/fpai-collect/src/sqlitepoll.rs +0 -390
  323. package/.next/standalone/crates/fpai-collect/src/supervisor.rs +0 -423
  324. package/.next/standalone/crates/fpai-collect/src/uploader.rs +0 -600
  325. package/.next/standalone/crates/fpai-collect/tests/claude_source.rs +0 -739
  326. package/.next/standalone/crates/fpai-collect/tests/claude_subagents.rs +0 -394
  327. package/.next/standalone/crates/fpai-collect/tests/codex_source.rs +0 -976
  328. package/.next/standalone/crates/fpai-collect/tests/config.rs +0 -286
  329. package/.next/standalone/crates/fpai-collect/tests/copilot_source.rs +0 -1020
  330. package/.next/standalone/crates/fpai-collect/tests/delivery.rs +0 -281
  331. package/.next/standalone/crates/fpai-collect/tests/goose_source.rs +0 -1009
  332. package/.next/standalone/crates/fpai-collect/tests/hermes_source.rs +0 -1130
  333. package/.next/standalone/crates/fpai-collect/tests/hooks_source.rs +0 -622
  334. package/.next/standalone/crates/fpai-collect/tests/openclaw_source.rs +0 -855
  335. package/.next/standalone/crates/fpai-collect/tests/opencode_source.rs +0 -1478
  336. package/.next/standalone/crates/fpai-collect/tests/pi_source.rs +0 -1192
  337. package/.next/standalone/crates/fpai-collect/tests/supervisor.rs +0 -290
  338. package/.next/standalone/crates/fpai-collect/tests/uploader.rs +0 -506
  339. package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
  340. package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
  341. package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
  342. package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
  343. package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
  344. package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
  345. package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
  346. package/.next/standalone/integration-suite/Dockerfile +0 -47
  347. package/.next/standalone/integration-suite/README.md +0 -129
  348. package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
  349. package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
  350. package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
  351. package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
  352. package/.next/standalone/integration-suite/install-clis.sh +0 -136
  353. package/.next/standalone/integration-suite/probe-cli.sh +0 -248
  354. package/.next/standalone/integration-suite/report.js +0 -120
  355. package/.next/standalone/integration-suite/run.sh +0 -159
  356. package/.next/standalone/openclaw-plugin/index.js +0 -223
  357. package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
  358. package/.next/standalone/openclaw-plugin/package.json +0 -12
  359. package/.next/standalone/osv-scanner.toml +0 -17
  360. package/.next/standalone/pi-extension/index.ts +0 -524
  361. package/.next/standalone/pi-extension/package.json +0 -12
  362. package/.next/standalone/postcss.config.mjs +0 -8
  363. package/.next/standalone/readme-arch-hq.gif +0 -0
  364. package/.next/standalone/rust-toolchain.toml +0 -4
  365. package/src/auth/cli.ts +0 -371
  366. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → LUaLkKg40nSkHrIajexIk}/_buildManifest.js +0 -0
  367. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → LUaLkKg40nSkHrIajexIk}/_clientMiddlewareManifest.js +0 -0
  368. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → LUaLkKg40nSkHrIajexIk}/_ssgManifest.js +0 -0
@@ -1,639 +0,0 @@
1
- mod cloud_client;
2
- pub mod cloud_policies;
3
- mod lock;
4
- mod paths;
5
- mod server;
6
- mod worker;
7
-
8
- use std::sync::Arc;
9
- use std::sync::atomic::{AtomicBool, Ordering};
10
- use std::time::Duration;
11
-
12
- fn main() {
13
- let args: Vec<String> = std::env::args().collect();
14
- if args.iter().any(|a| a == "--version" || a == "-v") {
15
- println!("failproofaid {}", env!("CARGO_PKG_VERSION"));
16
- return;
17
- }
18
-
19
- if let Err(err) = run() {
20
- eprintln!("[failproofaid] {err}");
21
- std::process::exit(1);
22
- }
23
- }
24
-
25
- /// Install a log subscriber, or the collector's diagnostics go nowhere.
26
- ///
27
- /// `tracing` drops every event when no subscriber is registered, silently. The
28
- /// uploader reports "the server accepted the request but stored NONE of its
29
- /// events" through it — the single most important signal that a transform is
30
- /// systematically malformed — so without this that failure is invisible.
31
- ///
32
- /// Writes to stderr, which is where the daemon's existing `eprintln!` output
33
- /// already goes and what systemd/launchd capture. `RUST_LOG` overrides the
34
- /// default level.
35
- fn init_logging() {
36
- use tracing_subscriber::EnvFilter;
37
- let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
38
- let _ = tracing_subscriber::fmt()
39
- .with_env_filter(filter)
40
- .with_writer(std::io::stderr)
41
- .try_init();
42
- }
43
-
44
- fn run() -> Result<(), Box<dyn std::error::Error>> {
45
- init_logging();
46
- let lock_path = paths::lock_path()?;
47
- paths::ensure_run_dir()?;
48
- let _singleton = lock::acquire(&lock_path)?;
49
-
50
- let socket_path = paths::socket_path()?;
51
- let worker_socket_path = paths::worker_socket_path()?;
52
- let worker = Arc::new(worker::Worker::new(
53
- worker_socket_path,
54
- worker::WorkerCommand::from_env(),
55
- ));
56
- // Pre-warm off the startup path: the socket must be accepting
57
- // connections promptly (a service manager / health check shouldn't wait
58
- // on a Node cold start), but a request that arrives before warm-up
59
- // finishes still gets a correct, just slightly slower, answer — `call()`
60
- // -> `ensure_started()` shares the same lock and simply waits for
61
- // whichever spawn (this one or its own) is already in flight.
62
- {
63
- let warm_worker = worker.clone();
64
- std::thread::spawn(move || warm_worker.warm());
65
- }
66
- // The shutdown flag and its signal handler are installed BEFORE anything
67
- // long-running starts, so the collector below can observe the same flag
68
- // the socket server does. One SIGTERM then stops both; a second signal
69
- // path would be one more thing to get wrong during shutdown.
70
- let shutdown = Arc::new(AtomicBool::new(false));
71
- install_signal_handler(shutdown.clone());
72
-
73
- // Cloud policy integrity is a maintenance-lane responsibility, never a
74
- // hook-path operation. The monitor is useful before cloud transport lands:
75
- // it keeps the active generation and content-addressed artifact cache in
76
- // agreement and reports when both verified copies have been lost.
77
- let cloud_policy_store = cloud_policies::PolicyStore::new(paths::cloud_managed_policy_dir()?);
78
- // One lane, resolving enrolment per tick rather than once at startup.
79
- // `failproofai config --connect` writes its credential file without root,
80
- // and this is a SYSTEM unit — so noticing it only on restart would put
81
- // `sudo systemctl restart` back into a flow built to avoid it. The lane
82
- // also does integrity repair whether or not the machine is enrolled.
83
- let cloud_monitor = cloud_client::spawn_maintenance(
84
- cloud_policy_store,
85
- shutdown.clone(),
86
- cloud_client::poll_interval_from_env(),
87
- cloud_policy_reconcile_interval(),
88
- );
89
-
90
- // Log/hook collection. Runs on its own thread with its own Tokio runtime
91
- // so it can never share fate with the accept loop — this daemon fails
92
- // closed, so a collector fault would otherwise deny every tool call on the
93
- // machine (see fpai_collect::supervisor). It observes the same `shutdown`
94
- // flag the server and the cloud monitor do, so one SIGTERM stops all three.
95
- //
96
- // INERT until ingest is configured. But the config is not necessarily
97
- // ready at startup: `failproofai config` installs the daemon and THEN
98
- // connects, so the very first daemon start usually sees no ingest yet. A
99
- // manager thread waits for the config to become enabled and starts the
100
- // collector once it is — the collector's analogue of the cloud lane
101
- // re-resolving enrolment per tick, so enabling collection takes effect
102
- // within one interval with no restart and no root (see
103
- // `spawn_collector_manager`). The manager owns the collector's lifecycle,
104
- // including draining it on shutdown.
105
- let collector_mgr = spawn_collector_manager(shutdown.clone());
106
-
107
- let srv = server::Server::bind(&socket_path, worker)?;
108
- eprintln!("[failproofaid] listening on {}", socket_path.display());
109
-
110
- let run_result = srv.run_until(shutdown);
111
-
112
- // Join the manager, which drains the collector within its flush budget
113
- // before returning. Done before `?` so a server error still gives the
114
- // collector a chance to flush instead of dropping buffered events.
115
- let _ = collector_mgr.join();
116
- let _ = cloud_monitor.join();
117
-
118
- run_result?;
119
- Ok(())
120
- }
121
-
122
- /// The collector tasks to supervise for this process.
123
- ///
124
- /// Returns an empty list — and therefore starts no thread and no runtime —
125
- /// unless an ingest credential is configured AND at least one stream is
126
- /// enabled. That is the normal state, so an install that has not opted in
127
- /// pays nothing for this code path existing.
128
- ///
129
- /// A configuration error is logged and treated as "off" rather than being
130
- /// propagated: collection failing to start must never stop the daemon from
131
- /// serving the socket, because the CLI fails closed and a daemon that refused
132
- /// to boot over a malformed `ingest.json` would deny every tool call on the
133
- /// machine. The error is loud so it is fixable, not silent.
134
- /// Own the collector's lifecycle on a dedicated thread.
135
- ///
136
- /// The collector config is not necessarily complete when the daemon starts:
137
- /// `failproofai config` installs the service, so the daemon comes up, and only
138
- /// THEN runs the connect step that writes `ingest.json` and the collector
139
- /// block. Resolving the config once at startup therefore left a freshly-set-up
140
- /// machine shipping nothing until the next manual restart — the exact confusion
141
- /// a user hit while testing.
142
- ///
143
- /// This mirrors what the cloud-policy lane already does: it re-resolves its
144
- /// config every tick precisely so `--connect` needs no root (restarting a
145
- /// system unit does). The collector follows the same rule — it waits for the
146
- /// config to become enabled, then starts once. Enabling collection thus takes
147
- /// effect within one poll interval, no restart, no sudo.
148
- ///
149
- /// It starts the collector once and does not tear it back down on a later
150
- /// `--disconnect` — that remains a restart, matching today's behaviour and
151
- /// avoiding a second start against the set-once health registry. The gap this
152
- /// closes is the common one: enabled *after* startup never taking effect.
153
- fn spawn_collector_manager(daemon_shutdown: Arc<AtomicBool>) -> std::thread::JoinHandle<()> {
154
- let interval = collector_config_poll_interval();
155
- std::thread::Builder::new()
156
- .name("fpai-collect-mgr".to_string())
157
- .spawn(move || {
158
- // Wait until collection is enabled. A cheap config read each tick,
159
- // not the full task build, so an incomplete config waits quietly
160
- // rather than logging on every interval.
161
- loop {
162
- if daemon_shutdown.load(Ordering::Relaxed) {
163
- return;
164
- }
165
- if collector_is_enabled() {
166
- break;
167
- }
168
- let deadline = std::time::Instant::now() + interval;
169
- while std::time::Instant::now() < deadline {
170
- if daemon_shutdown.load(Ordering::Relaxed) {
171
- return;
172
- }
173
- std::thread::sleep(Duration::from_millis(200));
174
- }
175
- }
176
-
177
- // Enabled — build and start. `collector_tasks()` logs "collector
178
- // enabled" once; `spawn_supervised` returns None only if the config
179
- // flipped back to disabled between the check and the build, or the
180
- // runtime failed to start.
181
- let Some(collector) =
182
- fpai_collect::spawn_supervised(collector_tasks(), daemon_shutdown.clone())
183
- else {
184
- return;
185
- };
186
-
187
- while !daemon_shutdown.load(Ordering::Relaxed) {
188
- std::thread::sleep(Duration::from_millis(200));
189
- }
190
- collector.join_with_flush(fpai_collect::DEFAULT_FLUSH_BUDGET);
191
- })
192
- .expect("failed to spawn the collector manager thread")
193
- }
194
-
195
- /// Cheap "should the collector be running?" check — reads the two small config
196
- /// files. Any error resolves to `false`; the full `collector_tasks()` build
197
- /// logs the reason when it acts on an enabled config.
198
- fn collector_is_enabled() -> bool {
199
- let Ok(home) = paths::failproofai_home() else {
200
- return false;
201
- };
202
- fpai_collect::config::load(&home)
203
- .map(|cfg| cfg.is_enabled())
204
- .unwrap_or(false)
205
- }
206
-
207
- /// How often to re-check whether the collector config has become enabled.
208
- /// Short by default — it is two small JSON reads — so enabling collection after
209
- /// a fresh setup is prompt. `FAILPROOFAI_COLLECTOR_CONFIG_POLL_MS` overrides it.
210
- fn collector_config_poll_interval() -> Duration {
211
- const DEFAULT_MS: u64 = 5_000;
212
- const MINIMUM_MS: u64 = 500;
213
- let ms = std::env::var("FAILPROOFAI_COLLECTOR_CONFIG_POLL_MS")
214
- .ok()
215
- .and_then(|v| v.parse::<u64>().ok())
216
- .unwrap_or(DEFAULT_MS);
217
- Duration::from_millis(ms.max(MINIMUM_MS))
218
- }
219
-
220
- fn collector_tasks() -> Vec<fpai_collect::TaskSpec> {
221
- let home = match paths::failproofai_home() {
222
- Ok(home) => home,
223
- Err(err) => {
224
- eprintln!("[failproofaid] collector disabled: {err}");
225
- return Vec::new();
226
- }
227
- };
228
-
229
- let cfg = match fpai_collect::config::load(&home) {
230
- Ok(cfg) => cfg,
231
- Err(err) => {
232
- eprintln!("[failproofaid] collector disabled: {err}");
233
- return Vec::new();
234
- }
235
- };
236
-
237
- if !cfg.is_enabled() {
238
- return Vec::new();
239
- }
240
-
241
- // `is_enabled()` already established there is one.
242
- let Some(ingest) = cfg.ingest.clone() else {
243
- return Vec::new();
244
- };
245
-
246
- let uploader = match fpai_collect::Uploader::new(
247
- ingest.url.clone(),
248
- ingest.key.clone(),
249
- cfg.failed_dir.clone(),
250
- ) {
251
- Ok(u) => std::sync::Arc::new(u),
252
- Err(err) => {
253
- eprintln!("[failproofaid] collector disabled: {err}");
254
- return Vec::new();
255
- }
256
- };
257
-
258
- eprintln!(
259
- "[failproofaid] collector enabled: sessions={} hooks={} ({:?}) -> {}",
260
- cfg.settings.sessions, cfg.settings.hooks, cfg.settings.hooks_verbosity, ingest.url,
261
- );
262
-
263
- // One `Delivery` shared by both tasks, so they share an upload semaphore
264
- // and an in-flight set. Separate ones would let the watcher and a
265
- // concurrent sweep POST the same batch twice.
266
- let delivery = std::sync::Arc::new(fpai_collect::Delivery::new(uploader));
267
-
268
- let watch_delivery = delivery.clone();
269
- let watch_dirs = cfg.spool_dirs.clone();
270
- let sweep_delivery = delivery;
271
- let sweep_dirs = cfg.spool_dirs.clone();
272
- let failed_dir = cfg.failed_dir.clone();
273
-
274
- let mut tasks = Vec::new();
275
-
276
- // Install the process health registry BEFORE any source starts, so no poll
277
- // reports into a registry that does not exist yet. The writer publishes it
278
- // on an interval and deletes it on clean shutdown — absence means "no
279
- // daemon", where a stale file makes a stopped daemon look like a running
280
- // one whose sources all went quiet.
281
- let health = std::sync::Arc::new(fpai_collect::Health::new());
282
- fpai_collect::health::install(health.clone());
283
- let health_file = fpai_collect::health_path(&home);
284
- tasks.push(fpai_collect::TaskSpec::new("health", move |sd| {
285
- fpai_collect::health::writer_task(
286
- health.clone(),
287
- health_file.clone(),
288
- fpai_collect::health::WRITE_INTERVAL,
289
- sd,
290
- )
291
- }));
292
-
293
- if cfg.settings.hooks {
294
- // Hook activity: one source covering every CLI failproofai is
295
- // installed in, because the store is CLI-agnostic — each row names its
296
- // own integration. Reads the same store the dashboard's activity tab
297
- // does, and never writes to it.
298
- let store_dir = home.join("cache").join("hook-activity");
299
- let state_dir = home.join("cursors").join("hooks");
300
- let spool_dir = cfg.own_spool_dir.clone();
301
- let verbosity = cfg.settings.hooks_verbosity;
302
- let environment = cfg.settings.environment.clone();
303
- let machine_id = cfg.settings.machine_id.clone();
304
- tasks.push(fpai_collect::TaskSpec::new("hook-activity", move |sd| {
305
- fpai_collect::sources::hooks::run(
306
- store_dir.clone(),
307
- state_dir.clone(),
308
- spool_dir.clone(),
309
- verbosity,
310
- environment.clone(),
311
- machine_id.clone(),
312
- sd,
313
- )
314
- }));
315
- }
316
-
317
- if cfg.settings.sessions {
318
- // Session transcripts, gated on the `sessions` opt-in because — unlike
319
- // hook activity — these carry prompts, file contents and whatever was
320
- // pasted into a terminal.
321
- //
322
- // Every source is registered the same way regardless of which engine it
323
- // uses, so adding one is a row here plus its own module.
324
- let spool = cfg.own_spool_dir.clone();
325
- let env = cfg.settings.environment.clone();
326
- let machine = cfg.settings.machine_id.clone();
327
- let cursors = home.join("cursors");
328
-
329
- use fpai_collect::sources::{claude, codex, copilot, openclaw, pi};
330
- file_source(
331
- &mut tasks,
332
- "claude",
333
- claude::FORMAT,
334
- vec![claude_projects_root()],
335
- claude::DEFAULT_AGENT_ID,
336
- &spool,
337
- &cursors,
338
- &env,
339
- machine.as_deref(),
340
- );
341
- // Subagent transcripts live under the SAME root, claimed by a second
342
- // format. A separate source, not a second predicate: `is_source_file`
343
- // is a bare fn, and each source needs its own cursor store — one store
344
- // writes its whole map atomically, so two sharing a file would clobber
345
- // each other and the loser would re-ship from zero after every restart.
346
- file_source(
347
- &mut tasks,
348
- "claude-subagent",
349
- claude::SUBAGENT_FORMAT,
350
- vec![claude_projects_root()],
351
- claude::SUBAGENT_DEFAULT_AGENT_ID,
352
- &spool,
353
- &cursors,
354
- &env,
355
- machine.as_deref(),
356
- );
357
- file_source(
358
- &mut tasks,
359
- "codex",
360
- codex::FORMAT,
361
- vec![codex_sessions_root()],
362
- codex::DEFAULT_AGENT_ID,
363
- &spool,
364
- &cursors,
365
- &env,
366
- machine.as_deref(),
367
- );
368
- file_source(
369
- &mut tasks,
370
- "copilot",
371
- copilot::FORMAT,
372
- vec![copilot::session_state_root()],
373
- copilot::DEFAULT_AGENT_ID,
374
- &spool,
375
- &cursors,
376
- &env,
377
- machine.as_deref(),
378
- );
379
- file_source(
380
- &mut tasks,
381
- "openclaw",
382
- openclaw::FORMAT,
383
- openclaw::default_roots(),
384
- openclaw::DEFAULT_AGENT_ID,
385
- &spool,
386
- &cursors,
387
- &env,
388
- machine.as_deref(),
389
- );
390
- file_source(
391
- &mut tasks,
392
- "pi",
393
- pi::FORMAT,
394
- vec![pi::sessions_root()],
395
- pi::DEFAULT_AGENT_ID,
396
- &spool,
397
- &cursors,
398
- &env,
399
- machine.as_deref(),
400
- );
401
-
402
- use fpai_collect::sources::{goose, hermes, opencode};
403
- sqlite_source(
404
- &mut tasks,
405
- "goose",
406
- goose::FORMAT,
407
- goose::db_path(),
408
- goose::DEFAULT_AGENT_ID,
409
- &spool,
410
- cursors.join("goose"),
411
- &env,
412
- machine.as_deref(),
413
- );
414
- sqlite_source(
415
- &mut tasks,
416
- "opencode",
417
- opencode::FORMAT,
418
- opencode::default_db_path(),
419
- opencode::DEFAULT_AGENT_ID,
420
- &spool,
421
- cursors.join("opencode"),
422
- &env,
423
- machine.as_deref(),
424
- );
425
-
426
- // Hermes profiles are SEPARATE databases, and the SQLite poller keys its
427
- // cursor on a fixed synthetic id — so two profiles sharing one state
428
- // directory would clobber each other's watermark and each would re-read
429
- // from zero after every restart. Each database gets its own.
430
- for (i, db) in hermes::default_db_paths().into_iter().enumerate() {
431
- let state = cursors.join("hermes").join(profile_dir_name(&db, i));
432
- sqlite_source(
433
- &mut tasks,
434
- "hermes",
435
- hermes::FORMAT,
436
- db,
437
- hermes::DEFAULT_AGENT_ID,
438
- &spool,
439
- state,
440
- &env,
441
- machine.as_deref(),
442
- );
443
- }
444
- }
445
-
446
- tasks.extend([
447
- // Latency: delivers a batch within milliseconds of it being published.
448
- fpai_collect::TaskSpec::new("spool-watcher", move |sd| {
449
- fpai_collect::delivery::watch(watch_delivery.clone(), watch_dirs.clone(), sd)
450
- }),
451
- // Guarantee: delivers anything the watcher never saw — published while
452
- // the daemon was stopped, or on a filesystem with no event support —
453
- // and retries parked batches on a much slower cadence.
454
- fpai_collect::TaskSpec::new("spool-sweeper", move |sd| {
455
- fpai_collect::delivery::sweep(
456
- sweep_delivery.clone(),
457
- sweep_dirs.clone(),
458
- failed_dir.clone(),
459
- sd,
460
- )
461
- }),
462
- ]);
463
-
464
- tasks
465
- }
466
-
467
- /// Where Claude Code keeps its transcripts.
468
- ///
469
- /// `CLAUDE_PROJECTS_PATH` overrides it, matching the env var the TypeScript
470
- /// side already honours, so a machine that has moved the directory is captured
471
- /// by both halves rather than one.
472
- fn claude_projects_root() -> std::path::PathBuf {
473
- if let Some(p) = std::env::var_os("CLAUDE_PROJECTS_PATH") {
474
- return std::path::PathBuf::from(p);
475
- }
476
- let home = std::env::var_os("HOME")
477
- .map(std::path::PathBuf::from)
478
- .unwrap_or_default();
479
- home.join(".claude").join("projects")
480
- }
481
-
482
- /// Register one file-tailing source.
483
- #[allow(clippy::too_many_arguments)]
484
- fn file_source(
485
- tasks: &mut Vec<fpai_collect::TaskSpec>,
486
- name: &'static str,
487
- format: fpai_collect::filetail::Format,
488
- roots: Vec<std::path::PathBuf>,
489
- default_agent_id: &'static str,
490
- spool_dir: &std::path::Path,
491
- cursor_root: &std::path::Path,
492
- environment: &str,
493
- machine_id: Option<&str>,
494
- ) {
495
- let spool_dir = spool_dir.to_path_buf();
496
- // One cursor store per source, never shared: the store writes its whole map
497
- // atomically, so two sources sharing a file would clobber each other and the
498
- // loser would re-read from zero after every restart.
499
- let state_dir = cursor_root.join(name);
500
- let environment = environment.to_string();
501
- let machine_id = machine_id.map(str::to_string);
502
- tasks.push(fpai_collect::TaskSpec::new(name, move |sd| {
503
- fpai_collect::filetail::run(
504
- fpai_collect::filetail::Spec {
505
- format,
506
- roots: roots.clone(),
507
- spool_dir: spool_dir.clone(),
508
- state_dir: state_dir.clone(),
509
- poll_interval: std::time::Duration::from_secs(2),
510
- params: fpai_collect::filetail::Params {
511
- agent_id: default_agent_id.to_string(),
512
- environment: environment.clone(),
513
- machine_id: machine_id.clone(),
514
- end_idle_mins: 10,
515
- max_read_bytes: 32 * 1024 * 1024,
516
- max_batch_bytes: fpai_collect::spool::DEFAULT_MAX_BATCH_BYTES,
517
- // Never the whole history by default. A normal machine holds
518
- // hundreds of megabytes of transcripts, and shipping all of
519
- // it on first start is not a reasonable default.
520
- since_days: Some(7),
521
- },
522
- },
523
- sd,
524
- )
525
- }));
526
- }
527
-
528
- /// Register one SQLite-polling source.
529
- #[allow(clippy::too_many_arguments)]
530
- fn sqlite_source(
531
- tasks: &mut Vec<fpai_collect::TaskSpec>,
532
- name: &'static str,
533
- format: fpai_collect::sqlitepoll::SqliteFormat,
534
- db_path: std::path::PathBuf,
535
- default_agent_id: &'static str,
536
- spool_dir: &std::path::Path,
537
- state_dir: std::path::PathBuf,
538
- environment: &str,
539
- machine_id: Option<&str>,
540
- ) {
541
- let spool_dir = spool_dir.to_path_buf();
542
- let environment = environment.to_string();
543
- let machine_id = machine_id.map(str::to_string);
544
- tasks.push(fpai_collect::TaskSpec::new(name, move |sd| {
545
- fpai_collect::sqlitepoll::run(
546
- fpai_collect::sqlitepoll::Spec {
547
- format,
548
- db_path: db_path.clone(),
549
- spool_dir: spool_dir.clone(),
550
- state_dir: state_dir.clone(),
551
- poll_interval: std::time::Duration::from_secs(5),
552
- params: fpai_collect::sqlitepoll::Params {
553
- agent_id: default_agent_id.to_string(),
554
- environment: environment.clone(),
555
- machine_id: machine_id.clone(),
556
- max_rows_per_poll: 2000,
557
- max_batch_bytes: fpai_collect::spool::DEFAULT_MAX_BATCH_BYTES,
558
- max_drain_passes: 20,
559
- },
560
- },
561
- sd,
562
- )
563
- }));
564
- }
565
-
566
- /// A stable, filesystem-safe directory name for one Hermes profile database.
567
- ///
568
- /// Derived from the profile directory rather than an index alone, so adding a
569
- /// profile cannot renumber an existing one and silently reset its watermark.
570
- fn profile_dir_name(db: &std::path::Path, index: usize) -> String {
571
- let name = db
572
- .parent()
573
- .and_then(|p| p.file_name())
574
- .and_then(|n| n.to_str())
575
- .unwrap_or("default");
576
- let safe: String = name
577
- .chars()
578
- .map(|c| if c.is_ascii_alphanumeric() { c } else { '-' })
579
- .take(32)
580
- .collect();
581
- if safe.trim_matches('-').is_empty() {
582
- format!("profile-{index}")
583
- } else {
584
- safe
585
- }
586
- }
587
-
588
- /// Where OpenAI Codex keeps its rollout logs.
589
- fn codex_sessions_root() -> std::path::PathBuf {
590
- if let Some(p) = std::env::var_os("CODEX_HOME") {
591
- return std::path::PathBuf::from(p).join("sessions");
592
- }
593
- let home = std::env::var_os("HOME")
594
- .map(std::path::PathBuf::from)
595
- .unwrap_or_default();
596
- home.join(".codex").join("sessions")
597
- }
598
-
599
- fn cloud_policy_reconcile_interval() -> Duration {
600
- const DEFAULT_MS: u64 = 30_000;
601
- const MINIMUM_MS: u64 = 100;
602
- let configured = std::env::var("FAILPROOFAI_CLOUD_POLICY_RECONCILE_MS")
603
- .ok()
604
- .and_then(|value| value.parse::<u64>().ok())
605
- .unwrap_or(DEFAULT_MS);
606
- Duration::from_millis(configured.max(MINIMUM_MS))
607
- }
608
-
609
- /// Requests a clean shutdown (socket file removal, lock release via Drop)
610
- /// on SIGTERM/SIGINT instead of dying mid-accept-loop — this is how a
611
- /// systemd `stop`/launchd unload is expected to end the process.
612
- fn install_signal_handler(shutdown: Arc<AtomicBool>) {
613
- static SHUTDOWN_REQUESTED: AtomicBool = AtomicBool::new(false);
614
-
615
- extern "C" fn handle_signal(_sig: libc::c_int) {
616
- SHUTDOWN_REQUESTED.store(true, Ordering::Relaxed);
617
- }
618
-
619
- unsafe {
620
- libc::signal(
621
- libc::SIGTERM,
622
- handle_signal as *const () as libc::sighandler_t,
623
- );
624
- libc::signal(
625
- libc::SIGINT,
626
- handle_signal as *const () as libc::sighandler_t,
627
- );
628
- }
629
-
630
- std::thread::spawn(move || {
631
- loop {
632
- if SHUTDOWN_REQUESTED.load(Ordering::Relaxed) {
633
- shutdown.store(true, Ordering::Relaxed);
634
- return;
635
- }
636
- std::thread::sleep(std::time::Duration::from_millis(50));
637
- }
638
- });
639
- }