failproofai 1.0.0-beta.5 → 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 (367) 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/{2cqk4a9s893oy.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/{1bw4dfzflelcv.js → 23557z4e6dtsr.js} +1 -1
  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/{2k285z07qce47.js → 34fa65k0cldkj.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/{34sjdw8lv46e3.js → 35v07j9gc1pvr.js} +2 -2
  158. package/.next/standalone/.next/static/chunks/{1bkynffp3q1f7.js → 3f_939wi3kfnx.js} +22 -22
  159. package/.next/standalone/.next/static/chunks/{2v1rpzrh2i1wv.js → 3p1vpm2_-tfwm.js} +1 -1
  160. package/.next/standalone/.next/static/chunks/{0cr85wuc9gc9k.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 +17636 -15284
  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 +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]__094nop3._.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]__0u02miy._.js +0 -4
  267. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
  268. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1gak4pd._.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_12c_2cz.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/1tp9dex23zs8y.js +0 -1
  277. package/.next/standalone/.next/static/chunks/2s9g1dsde_ts1.js +0 -1
  278. package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
  279. package/.next/standalone/.next/static/chunks/3zdwnnthucs_1.css +0 -2
  280. package/.next/standalone/Cargo.lock +0 -2222
  281. package/.next/standalone/Cargo.toml +0 -9
  282. package/.next/standalone/crates/CLOUD_POLICIES.md +0 -136
  283. package/.next/standalone/crates/PROTOCOL.md +0 -122
  284. package/.next/standalone/crates/failproofaid/Cargo.toml +0 -25
  285. package/.next/standalone/crates/failproofaid/src/cloud_client.rs +0 -484
  286. package/.next/standalone/crates/failproofaid/src/cloud_policies.rs +0 -921
  287. package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
  288. package/.next/standalone/crates/failproofaid/src/main.rs +0 -639
  289. package/.next/standalone/crates/failproofaid/src/paths.rs +0 -201
  290. package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
  291. package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
  292. package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
  293. package/.next/standalone/crates/fpai-collect/Cargo.toml +0 -43
  294. package/.next/standalone/crates/fpai-collect/src/config.rs +0 -420
  295. package/.next/standalone/crates/fpai-collect/src/cursor.rs +0 -520
  296. package/.next/standalone/crates/fpai-collect/src/delivery.rs +0 -472
  297. package/.next/standalone/crates/fpai-collect/src/filetail.rs +0 -487
  298. package/.next/standalone/crates/fpai-collect/src/health.rs +0 -369
  299. package/.next/standalone/crates/fpai-collect/src/lib.rs +0 -34
  300. package/.next/standalone/crates/fpai-collect/src/redact.rs +0 -516
  301. package/.next/standalone/crates/fpai-collect/src/sources/claude/mod.rs +0 -279
  302. package/.next/standalone/crates/fpai-collect/src/sources/claude/transform.rs +0 -619
  303. package/.next/standalone/crates/fpai-collect/src/sources/codex/mod.rs +0 -156
  304. package/.next/standalone/crates/fpai-collect/src/sources/codex/transform.rs +0 -715
  305. package/.next/standalone/crates/fpai-collect/src/sources/copilot/mod.rs +0 -158
  306. package/.next/standalone/crates/fpai-collect/src/sources/copilot/transform.rs +0 -512
  307. package/.next/standalone/crates/fpai-collect/src/sources/goose/mod.rs +0 -511
  308. package/.next/standalone/crates/fpai-collect/src/sources/goose/transform.rs +0 -586
  309. package/.next/standalone/crates/fpai-collect/src/sources/hermes/mod.rs +0 -318
  310. package/.next/standalone/crates/fpai-collect/src/sources/hermes/transform.rs +0 -579
  311. package/.next/standalone/crates/fpai-collect/src/sources/hooks/mod.rs +0 -314
  312. package/.next/standalone/crates/fpai-collect/src/sources/hooks/transform.rs +0 -448
  313. package/.next/standalone/crates/fpai-collect/src/sources/mod.rs +0 -23
  314. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/mod.rs +0 -176
  315. package/.next/standalone/crates/fpai-collect/src/sources/openclaw/transform.rs +0 -500
  316. package/.next/standalone/crates/fpai-collect/src/sources/opencode/mod.rs +0 -315
  317. package/.next/standalone/crates/fpai-collect/src/sources/opencode/transform.rs +0 -493
  318. package/.next/standalone/crates/fpai-collect/src/sources/pi/mod.rs +0 -201
  319. package/.next/standalone/crates/fpai-collect/src/sources/pi/transform.rs +0 -533
  320. package/.next/standalone/crates/fpai-collect/src/spool.rs +0 -535
  321. package/.next/standalone/crates/fpai-collect/src/sqlitepoll.rs +0 -390
  322. package/.next/standalone/crates/fpai-collect/src/supervisor.rs +0 -423
  323. package/.next/standalone/crates/fpai-collect/src/uploader.rs +0 -600
  324. package/.next/standalone/crates/fpai-collect/tests/claude_source.rs +0 -739
  325. package/.next/standalone/crates/fpai-collect/tests/claude_subagents.rs +0 -394
  326. package/.next/standalone/crates/fpai-collect/tests/codex_source.rs +0 -976
  327. package/.next/standalone/crates/fpai-collect/tests/config.rs +0 -286
  328. package/.next/standalone/crates/fpai-collect/tests/copilot_source.rs +0 -1020
  329. package/.next/standalone/crates/fpai-collect/tests/delivery.rs +0 -281
  330. package/.next/standalone/crates/fpai-collect/tests/goose_source.rs +0 -1009
  331. package/.next/standalone/crates/fpai-collect/tests/hermes_source.rs +0 -1130
  332. package/.next/standalone/crates/fpai-collect/tests/hooks_source.rs +0 -622
  333. package/.next/standalone/crates/fpai-collect/tests/openclaw_source.rs +0 -855
  334. package/.next/standalone/crates/fpai-collect/tests/opencode_source.rs +0 -1478
  335. package/.next/standalone/crates/fpai-collect/tests/pi_source.rs +0 -1192
  336. package/.next/standalone/crates/fpai-collect/tests/supervisor.rs +0 -290
  337. package/.next/standalone/crates/fpai-collect/tests/uploader.rs +0 -506
  338. package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
  339. package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
  340. package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
  341. package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
  342. package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
  343. package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
  344. package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
  345. package/.next/standalone/integration-suite/Dockerfile +0 -47
  346. package/.next/standalone/integration-suite/README.md +0 -129
  347. package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
  348. package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
  349. package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
  350. package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
  351. package/.next/standalone/integration-suite/install-clis.sh +0 -136
  352. package/.next/standalone/integration-suite/probe-cli.sh +0 -248
  353. package/.next/standalone/integration-suite/report.js +0 -120
  354. package/.next/standalone/integration-suite/run.sh +0 -159
  355. package/.next/standalone/openclaw-plugin/index.js +0 -223
  356. package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
  357. package/.next/standalone/openclaw-plugin/package.json +0 -12
  358. package/.next/standalone/osv-scanner.toml +0 -17
  359. package/.next/standalone/pi-extension/index.ts +0 -524
  360. package/.next/standalone/pi-extension/package.json +0 -12
  361. package/.next/standalone/postcss.config.mjs +0 -8
  362. package/.next/standalone/readme-arch-hq.gif +0 -0
  363. package/.next/standalone/rust-toolchain.toml +0 -4
  364. package/src/auth/cli.ts +0 -371
  365. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → Ptn8aBQl_cnNgOd0ebyv0}/_buildManifest.js +0 -0
  366. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → Ptn8aBQl_cnNgOd0ebyv0}/_clientMiddlewareManifest.js +0 -0
  367. /package/.next/standalone/.next/static/{LOuwMmfomO6hQYfMQYs4K → Ptn8aBQl_cnNgOd0ebyv0}/_ssgManifest.js +0 -0
@@ -1,390 +0,0 @@
1
- //! Generic poller for agents that keep sessions in SQLite.
2
- //!
3
- //! Everything format-specific lives behind [`SqliteFormat`]; the engine owns
4
- //! the connection, the watermark, and the spooling.
5
- //!
6
- //! # A rowid watermark is NOT sufficient, and that is the whole design
7
- //!
8
- //! The obvious poller reads `WHERE rowid > :last` and calls it done. Probing
9
- //! the real databases showed that is wrong for every one of them, in three
10
- //! different ways:
11
- //!
12
- //! * **opencode mutates rows for ~12 seconds after inserting them.** A tool
13
- //! part appears with `status:"running"` and an empty output, and the actual
14
- //! result is written by a later `UPDATE` to the same row. A rowid watermark
15
- //! ships every tool call with no result, forever, and looks like it is
16
- //! working.
17
- //! * **hermes deletes rows.** Rewind and compaction issue `DELETE FROM
18
- //! messages`, so rowids are not merely non-contiguous, the history behind the
19
- //! watermark changes.
20
- //! * **goose has `UPDATE messages SET content_json` and rewind deletes** in its
21
- //! binary, even though a happy-path session only appends.
22
- //!
23
- //! So a format declares its [`Watermark`], and the engine asks for rows the way
24
- //! that format actually orders its changes.
25
- //!
26
- //! # Open read-only, and never `immutable`
27
- //!
28
- //! `immutable=1` tells SQLite the file cannot change, which makes it skip the
29
- //! WAL entirely. That is catastrophic rather than merely stale here: goose's
30
- //! `sessions.db` main file contains **zero tables**, with all 1.25 MB of schema
31
- //! and rows sitting in an uncheckpointed `-wal`. Opening it `immutable` reads an
32
- //! empty database and reports success. `SQLITE_OPEN_READ_ONLY` alone reads the
33
- //! main file and its WAL together, which is what we want.
34
- //!
35
- //! Verified live: a reader polling opencode's database at 4 Hz throughout a
36
- //! 12-second tool call, while opencode was actively writing, saw zero
37
- //! `SQLITE_BUSY`.
38
- //!
39
- //! # All DB work happens on `spawn_blocking`
40
- //!
41
- //! `rusqlite` is synchronous. The connection is created and dropped inside the
42
- //! closure and never crosses an `await`, so it needs no `Send` bound and cannot
43
- //! be held across a yield point.
44
-
45
- use std::path::{Path, PathBuf};
46
-
47
- use rusqlite::{Connection, OpenFlags};
48
- use serde_json::Value;
49
-
50
- use crate::cursor::{CursorStore, FileCursor};
51
- use crate::spool::SpoolWriter;
52
- use crate::supervisor::{Shutdown, TaskError};
53
-
54
- /// How long to wait for a writer's lock before giving up on a query.
55
- const BUSY_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);
56
-
57
- /// How a format orders the changes the poller must pick up.
58
- #[derive(Debug, Clone, Copy, PartialEq, Eq)]
59
- pub enum Watermark {
60
- /// Monotonic insert id. Only correct where rows are never updated after
61
- /// insert AND never deleted.
62
- RowId,
63
- /// A last-modified column, so an updated row is re-read. Required for
64
- /// opencode, whose tool rows are filled in ~12s after they appear.
65
- UpdatedAt,
66
- }
67
-
68
- /// What one poll asked for and what it produced.
69
- #[derive(Debug, Default)]
70
- pub struct PollOutcome {
71
- pub events: Vec<Value>,
72
- /// The new watermark. Advanced only after the events are durably spooled.
73
- pub watermark: i64,
74
- /// True when the format hit its row limit, so the caller polls again
75
- /// immediately instead of sleeping — a backlog should drain, not trickle.
76
- pub more: bool,
77
- /// Rows examined. Reported so a poll that read a lot and emitted nothing is
78
- /// distinguishable from one that read nothing at all.
79
- pub rows_seen: u64,
80
- }
81
-
82
- /// One poll's inputs.
83
- #[derive(Debug, Clone)]
84
- pub struct PollRequest {
85
- pub watermark: i64,
86
- pub max_rows: u64,
87
- pub environment: String,
88
- pub agent_id: String,
89
- }
90
-
91
- /// The per-format adapter.
92
- #[derive(Clone, Copy)]
93
- pub struct SqliteFormat {
94
- /// Source kind — the spool filename prefix and log tag.
95
- pub kind: &'static str,
96
- pub watermark: Watermark,
97
- /// Read rows past the watermark and turn them into events.
98
- ///
99
- /// Runs on a blocking thread with a read-only connection. Must be pure with
100
- /// respect to `(connection contents, request)`: the server dedups on a
101
- /// content hash, so re-reading the same rows must produce the same bytes.
102
- pub poll: fn(&Connection, &PollRequest) -> rusqlite::Result<PollOutcome>,
103
- }
104
-
105
- #[derive(Debug, Clone)]
106
- pub struct Params {
107
- pub agent_id: String,
108
- pub environment: String,
109
- /// Machine this daemon runs on, stamped on every event. See `SpoolWriter`.
110
- pub machine_id: Option<String>,
111
- pub max_rows_per_poll: u64,
112
- pub max_batch_bytes: u64,
113
- /// Poll passes before yielding to the shutdown check. Bounds how long a
114
- /// backlog drain can ignore a stop request.
115
- pub max_drain_passes: u32,
116
- }
117
-
118
- pub struct Spec {
119
- pub format: SqliteFormat,
120
- pub db_path: PathBuf,
121
- pub spool_dir: PathBuf,
122
- pub state_dir: PathBuf,
123
- pub poll_interval: std::time::Duration,
124
- pub params: Params,
125
- }
126
-
127
- /// Poll until shutdown.
128
- pub async fn run(spec: Spec, sd: Shutdown) -> Result<(), TaskError> {
129
- let mut cursors = CursorStore::load(spec.state_dir.clone());
130
- tracing::info!(
131
- source = spec.format.kind,
132
- db = %spec.db_path.display(),
133
- present = spec.db_path.exists(),
134
- watermark = ?spec.format.watermark,
135
- "sqlite source started"
136
- );
137
-
138
- loop {
139
- for _ in 0..spec.params.max_drain_passes.max(1) {
140
- if sd.is_set() {
141
- return Ok(());
142
- }
143
- match poll_once(&spec, &mut cursors).await {
144
- Ok((events, more)) => {
145
- crate::health::report_poll(
146
- spec.format.kind,
147
- spec.db_path.exists(),
148
- events,
149
- cursors.len() as u64,
150
- );
151
- if !more {
152
- break; // nothing more waiting
153
- }
154
- // Hit the row limit — drain rather than trickle.
155
- }
156
- Err(err) => {
157
- tracing::warn!(source = spec.format.kind, %err, "poll failed; retrying next tick");
158
- crate::health::report_error(spec.format.kind, &err.to_string());
159
- break;
160
- }
161
- }
162
- }
163
- if !sd.sleep(spec.poll_interval).await {
164
- return Ok(());
165
- }
166
- }
167
- }
168
-
169
- /// One pass. Returns `(events spooled, more rows waiting)`.
170
- async fn poll_once(spec: &Spec, cursors: &mut CursorStore) -> Result<(u64, bool), TaskError> {
171
- if !spec.db_path.exists() {
172
- // Normal: the agent simply is not installed.
173
- return Ok((0, false));
174
- }
175
-
176
- // The cursor store is keyed on (dev, inode) for file tailers. A database is
177
- // one logical stream, so a fixed synthetic key keeps one entry per source
178
- // regardless of the file being replaced underneath us (a vacuum or a
179
- // restore changes the inode without changing the data).
180
- let key_inode = 0u64;
181
- let watermark = cursors
182
- .resume(0, key_inode, &spec.db_path)
183
- .map(|c| c.offset as i64)
184
- .unwrap_or(0);
185
-
186
- let request = PollRequest {
187
- watermark,
188
- max_rows: spec.params.max_rows_per_poll,
189
- environment: spec.params.environment.clone(),
190
- agent_id: spec.params.agent_id.clone(),
191
- };
192
-
193
- let db_path = spec.db_path.clone();
194
- let poll = spec.format.poll;
195
- // The connection is created and dropped INSIDE the closure, so it never
196
- // crosses an await and needs no Send bound.
197
- let outcome = tokio::task::spawn_blocking(move || -> rusqlite::Result<PollOutcome> {
198
- let conn = open_readonly(&db_path)?;
199
- poll(&conn, &request)
200
- })
201
- .await
202
- .map_err(|e| TaskError::from(format!("sqlite poll task failed: {e}")))?
203
- .map_err(|e| TaskError::from(e.to_string()))?;
204
-
205
- if outcome.events.is_empty() {
206
- // Still advance the watermark: a pass that legitimately produced no
207
- // events (rows filtered out, say) must not re-read them forever.
208
- if outcome.watermark > watermark {
209
- store_watermark(cursors, spec, outcome.watermark)?;
210
- }
211
- return Ok((0, outcome.more));
212
- }
213
-
214
- let mut writer = SpoolWriter::new(
215
- spec.spool_dir.clone(),
216
- spec.params.max_batch_bytes,
217
- spec.format.kind,
218
- spec.format.kind,
219
- )
220
- .with_machine_id(spec.params.machine_id.clone());
221
- let emitted = outcome.events.len() as u64;
222
- for event in outcome.events {
223
- writer.push(event).await.map_err(io_err)?;
224
- }
225
- // Flush BEFORE advancing. A crash between the two costs a re-ship the
226
- // server dedups; the other order loses the rows outright.
227
- writer.flush().await.map_err(io_err)?;
228
- store_watermark(cursors, spec, outcome.watermark)?;
229
-
230
- Ok((emitted, outcome.more))
231
- }
232
-
233
- fn store_watermark(
234
- cursors: &mut CursorStore,
235
- spec: &Spec,
236
- watermark: i64,
237
- ) -> Result<(), TaskError> {
238
- cursors.set(FileCursor {
239
- path: spec.db_path.clone(),
240
- dev: 0,
241
- inode: 0,
242
- offset: watermark.max(0) as u64,
243
- size_seen: 0,
244
- ..Default::default()
245
- });
246
- cursors.save().map_err(io_err)
247
- }
248
-
249
- /// Open read-only, WAL-aware, with a busy timeout.
250
- ///
251
- /// `SQLITE_OPEN_READ_ONLY` and deliberately NOT a `?immutable=1` URI — see the
252
- /// module docs for why that would read goose's database as empty.
253
- pub fn open_readonly(path: &Path) -> rusqlite::Result<Connection> {
254
- let conn = Connection::open_with_flags(
255
- path,
256
- OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_NO_MUTEX,
257
- )?;
258
- conn.busy_timeout(BUSY_TIMEOUT)?;
259
- Ok(conn)
260
- }
261
-
262
- fn io_err(e: std::io::Error) -> TaskError {
263
- TaskError::from(e.to_string())
264
- }
265
-
266
- /// Coerce a timestamp column to epoch milliseconds.
267
- ///
268
- /// The four SQLite agents disagree on units: hermes writes REAL epoch SECONDS,
269
- /// goose an INTEGER epoch seconds, opencode INTEGER milliseconds. Guessing from
270
- /// magnitude is the only thing that works across all of them without a
271
- /// per-source flag that would be wrong the first time a vendor changes.
272
- pub fn epoch_to_millis(v: f64) -> i64 {
273
- if v > 1e12 {
274
- v as i64 // already milliseconds
275
- } else if v > 1e9 {
276
- (v * 1000.0) as i64 // seconds
277
- } else {
278
- 0 // implausible; caller decides what to do with it
279
- }
280
- }
281
-
282
- #[cfg(test)]
283
- mod tests {
284
- use super::*;
285
-
286
- #[test]
287
- fn timestamp_units_are_inferred_from_magnitude() {
288
- // hermes REAL seconds, goose INTEGER seconds, opencode INTEGER millis.
289
- assert_eq!(epoch_to_millis(1_785_744_251.686), 1_785_744_251_686);
290
- assert_eq!(epoch_to_millis(1_785_744_251.0), 1_785_744_251_000);
291
- assert_eq!(epoch_to_millis(1_785_744_251_686.0), 1_785_744_251_686);
292
- // Implausible values are reported as zero rather than silently becoming
293
- // 1970, which would put events at the start of every timeline.
294
- assert_eq!(epoch_to_millis(0.0), 0);
295
- assert_eq!(epoch_to_millis(42.0), 0);
296
- }
297
-
298
- #[test]
299
- fn a_read_only_connection_cannot_write() {
300
- // The guarantee that matters: the daemon reads other products'
301
- // databases and must never be able to corrupt one.
302
- let dir = std::env::temp_dir().join(format!("fpai-sq-{}", std::process::id()));
303
- std::fs::create_dir_all(&dir).unwrap();
304
- let db = dir.join("t.db");
305
- {
306
- let c = Connection::open(&db).unwrap();
307
- c.execute_batch("CREATE TABLE t(a); INSERT INTO t VALUES (1);")
308
- .unwrap();
309
- }
310
- let ro = open_readonly(&db).unwrap();
311
- assert_eq!(
312
- ro.query_row("SELECT count(*) FROM t", [], |r| r.get::<_, i64>(0))
313
- .unwrap(),
314
- 1
315
- );
316
- assert!(
317
- ro.execute("INSERT INTO t VALUES (2)", []).is_err(),
318
- "a read-only handle must refuse writes"
319
- );
320
- std::fs::remove_dir_all(&dir).ok();
321
- }
322
-
323
- #[test]
324
- fn a_wal_database_is_read_through_its_wal_not_just_the_main_file() {
325
- // goose's main DB file contains ZERO tables, with everything in an
326
- // uncheckpointed -wal. A reader that only sees the main file reads an
327
- // empty database and reports success.
328
- let dir = std::env::temp_dir().join(format!("fpai-sqwal-{}", std::process::id()));
329
- std::fs::create_dir_all(&dir).unwrap();
330
- let db = dir.join("wal.db");
331
- let writer = Connection::open(&db).unwrap();
332
- writer.pragma_update(None, "journal_mode", "WAL").unwrap();
333
- writer
334
- .execute_batch("CREATE TABLE m(id INTEGER PRIMARY KEY, v TEXT);")
335
- .unwrap();
336
- writer
337
- .execute("INSERT INTO m(v) VALUES ('in-wal')", [])
338
- .unwrap();
339
- // Deliberately NOT checkpointed and NOT closed — this is goose's state.
340
-
341
- let ro = open_readonly(&db).unwrap();
342
- let n: i64 = ro
343
- .query_row("SELECT count(*) FROM m", [], |r| r.get(0))
344
- .unwrap();
345
- assert_eq!(
346
- n, 1,
347
- "the WAL contents must be visible to a read-only reader"
348
- );
349
-
350
- drop(writer);
351
- std::fs::remove_dir_all(&dir).ok();
352
- }
353
-
354
- #[test]
355
- fn reading_works_while_a_writer_holds_the_database() {
356
- // Verified live against opencode at 4 Hz through a 12s tool call with
357
- // zero SQLITE_BUSY; this pins the property in CI.
358
- let dir = std::env::temp_dir().join(format!("fpai-sqbusy-{}", std::process::id()));
359
- std::fs::create_dir_all(&dir).unwrap();
360
- let db = dir.join("busy.db");
361
- let writer = Connection::open(&db).unwrap();
362
- writer.pragma_update(None, "journal_mode", "WAL").unwrap();
363
- writer
364
- .execute_batch("CREATE TABLE m(id INTEGER PRIMARY KEY, v TEXT);")
365
- .unwrap();
366
-
367
- let ro = open_readonly(&db).unwrap();
368
- for i in 0..20 {
369
- writer
370
- .execute("INSERT INTO m(v) VALUES (?1)", [format!("row{i}")])
371
- .unwrap();
372
- let n: i64 = ro
373
- .query_row("SELECT count(*) FROM m", [], |r| r.get(0))
374
- .unwrap();
375
- assert_eq!(
376
- n,
377
- i + 1,
378
- "a concurrent reader must see committed rows immediately"
379
- );
380
- }
381
- drop(writer);
382
- std::fs::remove_dir_all(&dir).ok();
383
- }
384
-
385
- #[test]
386
- fn a_missing_database_is_an_error_not_a_panic() {
387
- // The agent simply is not installed. Common, and not a fault.
388
- assert!(open_readonly(Path::new("/nonexistent/fpai/none.db")).is_err());
389
- }
390
- }