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,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
- }