failproofai 1.0.0-beta.14 → 1.0.0-beta.16

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 (190) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +5 -5
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js +2 -1
  8. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  13. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  14. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  15. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  16. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  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 +2 -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 +14 -14
  24. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  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 +9 -9
  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 +1 -1
  30. package/.next/standalone/.next/server/app/api/audit/invite/route.js +1 -1
  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.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +1 -1
  36. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/auth/logout/route.js +1 -1
  38. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +1 -1
  40. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/api/auth/status/route.js +1 -1
  42. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  43. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  45. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  46. package/.next/standalone/.next/server/app/audit/page.js +2 -1
  47. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/index.html +1 -1
  50. package/.next/standalone/.next/server/app/index.rsc +14 -14
  51. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  52. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  53. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  54. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +9 -9
  55. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  56. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  57. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  58. package/.next/standalone/.next/server/app/page.js +2 -1
  59. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  60. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  61. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  62. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +10 -10
  63. package/.next/standalone/.next/server/app/policies/page.js +2 -1
  64. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  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 +2 -1
  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/build-manifest.json +2 -2
  72. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  73. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  74. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -1
  75. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  76. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  77. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  78. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  79. package/.next/standalone/.next/server/app/projects/page.js +2 -1
  80. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  82. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
  83. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
  84. package/.next/standalone/.next/server/app/settings/page.js +2 -1
  85. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  86. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  87. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
  88. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +1 -1
  90. package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +1 -1
  91. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hxmox-._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__12y_xo0._.js → [root-of-the-server]__0no2gzh._.js} +2 -2
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +2 -2
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17itmx-._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
  99. package/.next/standalone/.next/server/chunks/ssr/{_202d777._.js → _09tcu2b._.js} +1 -1
  100. package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +1 -1
  101. package/.next/standalone/.next/server/chunks/ssr/_0vo2qyt._.js +1 -1
  102. package/.next/standalone/.next/server/chunks/ssr/_0xej-0e._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/_10399ge._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/ssr/_149k9oy._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/_1_hwp06._.js +1 -1
  106. package/.next/standalone/.next/server/chunks/ssr/_1mnhi_r._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/_1ror7k9._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  109. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +4 -0
  112. package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
  113. package/.next/standalone/.next/server/pages/404.html +1 -1
  114. package/.next/standalone/.next/server/pages/500.html +1 -1
  115. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  116. package/.next/standalone/.next/server/server-reference-manifest.json +15 -15
  117. package/.next/standalone/.next/static/chunks/{0mot4rr-baiiq.js → 0fx3tgb_n0vz5.js} +1 -1
  118. package/.next/standalone/.next/static/chunks/{1_0nr2fuuslbb.js → 16yzosmvpinbh.js} +1 -1
  119. package/.next/standalone/.next/static/chunks/{0ynhunx0nt0n-.js → 1_as8528fwqxf.js} +1 -1
  120. package/.next/standalone/.next/static/chunks/{1tyg866lrq4kh.js → 1nsy22eg5q-pi.js} +1 -1
  121. package/.next/standalone/.next/static/chunks/{2zilodg05qgcf.js → 2f2h7g8sm0bhr.js} +1 -1
  122. package/.next/standalone/.next/static/chunks/{0pkz6r-cgdr3-.js → 2n6wkcj5q_0yd.js} +2 -2
  123. package/.next/standalone/.next/static/chunks/{30f--ye1ly8m6.js → 2okcei5v0-xrx.js} +1 -1
  124. package/.next/standalone/.next/static/chunks/{31fmsp1soxi07.js → 2rl5gq4xl8oa2.js} +1 -1
  125. package/.next/standalone/.next/static/chunks/{1wn2p7yzbcifa.js → 3vsiw3ayz3c7_.js} +1 -1
  126. package/.next/standalone/.next/static/chunks/{2hiai8kvhjcov.js → 3xp43uu8jj8t4.js} +1 -1
  127. package/.next/standalone/.next/static/chunks/43kqvfa-2jq0g.js +1 -0
  128. package/.next/standalone/.next/static/chunks/{turbopack-3diub4ctvn1n0.js → turbopack-0ud32mdjjcn6y.js} +1 -1
  129. package/.next/standalone/SECURITY.md +8 -2
  130. package/.next/standalone/app/actions/get-hooks-config.ts +0 -1
  131. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +1 -3
  132. package/.next/standalone/app/audit/_components/audit-progress-strip.tsx +1 -1
  133. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -1
  134. package/.next/standalone/app/audit/_components/empty-state.tsx +0 -1
  135. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +1 -1
  136. package/.next/standalone/app/audit/_components/quirks-section.tsx +0 -1
  137. package/.next/standalone/app/audit/_components/report-footer.tsx +0 -2
  138. package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
  139. package/.next/standalone/app/audit/_components/strengths-section.tsx +0 -1
  140. package/.next/standalone/app/components/pause-notices.tsx +1 -1
  141. package/.next/standalone/app/components/raw-log-viewer.tsx +1 -1
  142. package/.next/standalone/app/components/toast.tsx +1 -1
  143. package/.next/standalone/app/policies/hooks-client.tsx +3 -2
  144. package/.next/standalone/app/settings/settings-client.tsx +1 -2
  145. package/.next/standalone/lib/auth/auth-store.ts +0 -1
  146. package/.next/standalone/package.json +10 -12
  147. package/.next/standalone/server.js +1 -1
  148. package/bin/failproofai.mjs +253 -33
  149. package/bin/failproofaid-shim.mjs +4 -4
  150. package/dist/cli.mjs +6337 -3869
  151. package/dist/worker.mjs +26 -21
  152. package/lib/auth/auth-store.ts +0 -1
  153. package/package.json +10 -12
  154. package/scripts/dev-hook.mjs +46 -5
  155. package/scripts/translate-docs/cache.ts +1 -1
  156. package/scripts/translate-docs/cli.ts +2 -2
  157. package/scripts/translate-docs/mintlify-nav.ts +1 -1
  158. package/src/audit/cache.ts +0 -1
  159. package/src/audit/dashboard-cache.ts +0 -2
  160. package/src/audit/report.ts +0 -1
  161. package/src/hooks/builtin-policies.ts +1 -1
  162. package/src/hooks/cloud-enrollment-cli.ts +0 -2
  163. package/src/hooks/cloud-enrollment.ts +1 -2
  164. package/src/hooks/cloud-managed-policies.ts +0 -1
  165. package/src/hooks/collector-config.ts +4 -20
  166. package/src/hooks/configure-wizard.ts +0 -4
  167. package/src/hooks/custom-hooks-loader.ts +0 -1
  168. package/src/hooks/daemon-client.ts +4 -28
  169. package/src/hooks/daemon-download.ts +0 -1
  170. package/src/hooks/daemon-service.ts +108 -16
  171. package/src/hooks/fp-config.ts +226 -12
  172. package/src/hooks/fp-home.ts +270 -56
  173. package/src/hooks/fp-reset.ts +482 -73
  174. package/src/hooks/hook-logger.ts +0 -1
  175. package/src/hooks/integrations.ts +0 -1
  176. package/src/hooks/loader-utils.ts +1 -1
  177. package/src/hooks/manager.ts +1 -1
  178. package/src/hooks/migrations.ts +381 -0
  179. package/src/hooks/onboarding-lock.ts +1 -2
  180. package/src/hooks/session-pause.ts +0 -1
  181. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1uyc-z4._.js +0 -3
  182. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vlyx3j._.js +0 -3
  183. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mmefsr._.js +0 -5
  184. package/.next/standalone/.next/static/chunks/2yy1767yfda67.js +0 -1
  185. package/.next/standalone/ino.ujh3/.failproofai/VERSION +0 -4
  186. package/.next/standalone/ino.ujh3/.failproofai/state/last-version +0 -1
  187. package/.next/standalone/ino.ujh3/.failproofai/state/telemetry-id +0 -1
  188. /package/.next/standalone/.next/static/{ZbPDZe0dNBNdNmo31aq_e → kSTfP_Tzl760gYDnYr-JC}/_buildManifest.js +0 -0
  189. /package/.next/standalone/.next/static/{ZbPDZe0dNBNdNmo31aq_e → kSTfP_Tzl760gYDnYr-JC}/_clientMiddlewareManifest.js +0 -0
  190. /package/.next/standalone/.next/static/{ZbPDZe0dNBNdNmo31aq_e → kSTfP_Tzl760gYDnYr-JC}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "1.0.0-beta.14",
3
+ "version": "1.0.0-beta.16",
4
4
  "description": "The easiest way to manage policies that keep your AI agents reliable, on-task, and running autonomously — for Claude Code & the Agents SDK",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs",
@@ -99,14 +99,12 @@
99
99
  },
100
100
  "dependencies": {
101
101
  "html-to-image": "^1.11.13",
102
- "html2canvas": "^1.4.1",
103
102
  "posthog-node": "^5.47.7",
104
103
  "sql.js": "^1.14.1",
105
104
  "yaml": "^2.9.0"
106
105
  },
107
106
  "overrides": {
108
- "postcss": "8.5.23",
109
- "nanoid": "3.3.17",
107
+ "postcss": "8.5.26",
110
108
  "eslint-plugin-react-hooks": "7.0.1",
111
109
  "vite": "8.0.16",
112
110
  "undici": "7.29.0",
@@ -114,15 +112,15 @@
114
112
  "sharp": "0.35.0"
115
113
  },
116
114
  "optionalDependencies": {
117
- "@failproofai/failproofaid-linux-x64": "1.0.0-beta.14",
118
- "@failproofai/failproofaid-linux-arm64": "1.0.0-beta.14",
119
- "@failproofai/failproofaid-darwin-x64": "1.0.0-beta.14",
120
- "@failproofai/failproofaid-darwin-arm64": "1.0.0-beta.14"
115
+ "@failproofai/failproofaid-linux-x64": "1.0.0-beta.16",
116
+ "@failproofai/failproofaid-linux-arm64": "1.0.0-beta.16",
117
+ "@failproofai/failproofaid-darwin-x64": "1.0.0-beta.16",
118
+ "@failproofai/failproofaid-darwin-arm64": "1.0.0-beta.16"
121
119
  },
122
120
  "failproofaidBinaries": {
123
- "linux-x64": "969fa920cb6e06a607d4a97bd17078519929b9b7cfd78e1bbf4ed6bd8d21e300",
124
- "linux-arm64": "79caf004fced34e827e7566346fd5b47852e3e8a1fd4e41bb7ecd85e68d76e24",
125
- "darwin-x64": "0b81018cb2a851c62f5b561d8027dee6897f34cebe32d695ce531c58b70aecf4",
126
- "darwin-arm64": "eb91832ea41d569110cc58d15efa9e18151d5f13daa6aca2b968e72ab57dee41"
121
+ "linux-x64": "b82471309d2e52724781d8074bae55444892030eb1b48305ef74053bb7938931",
122
+ "linux-arm64": "5a0bdc9f726844e7ed109c896bb894e84a51c7592fe4aed26eceea78c97fde04",
123
+ "darwin-x64": "08881822befb31fe13974d2861fc50b6b2c1c72741986656e8f9087586202d88",
124
+ "darwin-arm64": "cc85096de72f3e5813145b7c906ea6a2d4788f39f4dae6a86532d88107802cab"
127
125
  }
128
126
  }
@@ -9,7 +9,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
9
9
  const hostname = process.env.HOSTNAME || '0.0.0.0'
10
10
 
11
11
  let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
12
- const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.0-beta.14"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":false,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"partialFallbacks":false,"dynamicOnHover":false,"varyParams":false,"prefetchInlining":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":false,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","outputFileTracingExcludes":{"*":["node_modules/@img/**","node_modules/sharp/**"]},"turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"distDirRoot":".next"}
12
+ const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.0-beta.16"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":false,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"partialFallbacks":false,"dynamicOnHover":false,"varyParams":false,"prefetchInlining":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":false,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","outputFileTracingExcludes":{"*":["node_modules/@img/**","node_modules/sharp/**"]},"turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"distDirRoot":".next"}
13
13
 
14
14
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
15
15
 
@@ -327,26 +327,6 @@ COMMANDS
327
327
  harness remove-path <h> <p> Stop capturing that path
328
328
  harness --help, -h Show this help for the harness command
329
329
 
330
- Each agent CLI is watched wherever its own installer put it. Extra paths add
331
- the places it did not: a second profile, a team share, a per-user home.
332
-
333
- failproofai harness add-path openclaw user1=/srv/.openclaw-user1
334
- failproofai harness add-path openclaw user2=/srv/.openclaw-user2
335
- failproofai harness add-path hermes user1=/srv/.hermes-user1/state.db
336
-
337
- LABEL PER-USER PATHS EXPLICITLY. An agent id comes from the cwd recorded
338
- inside the transcript, identical in every copy of a project, so unlabelled
339
- paths merge two people into one agent whose sessions interleave. Omitting the
340
- label derives one from the folder name — fine for .openclaw-user1, but
341
- /home/u1/.openclaw and /home/u2/.openclaw both derive "openclaw" and the
342
- second is refused. A path overlapping one already captured is refused too.
343
-
344
- FAILPROOFAI_<HARNESS>_EXTRA_PATHS overrides the file for containers:
345
- FAILPROOFAI_OPENCLAW_EXTRA_PATHS="user1=/srv/.openclaw-user1,user2=/srv/.openclaw-user2"
346
-
347
- Written to ~/.failproofai/config.json; the daemon picks it up in seconds —
348
- no restart, no sudo. Session collection must be on for any of it to be read.
349
-
350
330
  audit Audit your agent's behavior, then open the
351
331
  dashboard at http://localhost:8020/audit
352
332
  audit --help, -h Show this help for the audit command
@@ -363,6 +343,18 @@ COMMANDS
363
343
  --wait Block until the spool drains (or --timeout)
364
344
  --timeout <secs> How long to wait with --wait (default: 60)
365
345
 
346
+ update Finish an upgrade npm cannot: migrate
347
+ ~/.failproofai to this version's layout, put the
348
+ matching daemon binary in place, restart it.
349
+ Run after \`npm install -g failproofai@latest\`.
350
+ --no-daemon Migrate the home only
351
+
352
+ migrate Run pending layout migrations on their own,
353
+ keyed on the layout in ~/.failproofai/VERSION
354
+ (not the npm version, so skipping releases with
355
+ no layout change runs nothing)
356
+ --dry-run Print the steps and change nothing
357
+
366
358
  uninstall Remove failproofai from this machine: hook
367
359
  entries from every agent CLI, and the daemon
368
360
  service. Run this BEFORE \`npm rm -g failproofai\`
@@ -465,7 +457,6 @@ LINKS
465
457
  // past the help block above and reach here, so without this a user typing
466
458
  // `failproofai policies --help` had their home reset by a question. The
467
459
  // adjacent, far less destructive first-run gate exempted help from the start.
468
- let layoutWasReset = false;
469
460
  {
470
461
  const isHelpOrVersion =
471
462
  args.includes("--help") || args.includes("-h") || args.includes("--version") || args.includes("-v");
@@ -484,12 +475,23 @@ LINKS
484
475
  console.error(warning);
485
476
  process.exit(1);
486
477
  }
487
- } else if (!isHelpOrVersion) {
478
+ } else if (!isHelpOrVersion && args[0] !== "migrate" && args[0] !== "update") {
479
+ // `migrate` and `update` are exempt because they ARE this step, and letting
480
+ // it run first breaks them both. `migrate --dry-run` promises to change
481
+ // nothing and print what would happen — with the check ahead of it, the home
482
+ // was already migrated by the time the subcommand looked, so it reported
483
+ // "nothing to migrate" on every stale machine it was ever pointed at, which
484
+ // is the one answer a dry run must never give wrongly. Caught by a smoke
485
+ // test on a seeded layout-2 home, not by a unit test: nothing below the CLI
486
+ // entry point can see this ordering.
488
487
  const { checkLayoutForCli } = await import("../src/hooks/fp-reset");
489
488
  const check = await checkLayoutForCli();
490
489
  for (const line of check.lines) console.error(line);
491
490
  if (check.fatal) process.exit(1);
492
- layoutWasReset = check.didReset;
491
+ // `check.didReset` is deliberately not read. It used to force the wizard
492
+ // below; see the note at `shouldOfferFirstRun` for why a migrated machine
493
+ // no longer needs setup re-run, and `didReset` in `fp-reset.ts` for what
494
+ // the field means now.
493
495
  }
494
496
  }
495
497
 
@@ -516,20 +518,25 @@ LINKS
516
518
  }
517
519
 
518
520
  const { shouldOfferFirstRun } = await import("../src/hooks/first-run-gate");
519
- if (shouldOfferFirstRun(args) || layoutWasReset) {
521
+ // `|| layoutWasReset` stood here, with `force: layoutWasReset` below, because a
522
+ // migration used to delete the home's policy config while leaving the agent
523
+ // CLIs' settings files alone — so `isConfigured()` read true off
524
+ // `hasGlobalHooks` and setup was skipped, leaving hooks firing against no
525
+ // policies, silently and permanently.
526
+ //
527
+ // The migration keeps that file now (`HOME_CLASSES` classes it `user-typed`),
528
+ // along with `config.json` and `credentials.json`, so a migrated machine is
529
+ // configured in fact and not merely in appearance. Forcing the wizard here
530
+ // would open an interactive prompt with nothing to answer — and on a fleet box,
531
+ // a CI runner or a headless gateway, nobody to answer it. A home that never
532
+ // finished setup still gets here on its own: `isConfigured()` is false for it.
533
+ // See `didReset` in `fp-reset.ts`.
534
+ if (shouldOfferFirstRun(args)) {
520
535
  try {
521
536
  const { maybeFirstRunConfigure } = await import("../src/hooks/configure-wizard");
522
537
  // `audit` runs its own scan immediately after this returns; firing the
523
538
  // post-setup audit too would scan the whole history twice in a row.
524
- //
525
- // `force` after a reset: the home's policy config is gone, but the agent
526
- // CLIs' settings files were deliberately left alone, so `isConfigured()`
527
- // still reads true off `hasGlobalHooks` and setup would be skipped —
528
- // leaving hooks firing against no policies, silently and permanently.
529
- await maybeFirstRunConfigure(
530
- {},
531
- { postSetupAudit: args[0] !== "audit", force: layoutWasReset },
532
- );
539
+ await maybeFirstRunConfigure({}, { postSetupAudit: args[0] !== "audit" });
533
540
  } catch {
534
541
  // Onboarding is never allowed to block the command the user actually typed.
535
542
  }
@@ -733,6 +740,14 @@ EXAMPLES
733
740
  failproofai harness list
734
741
  failproofai harness remove-path claude work
735
742
 
743
+ One home per person — label them, or both derive the same folder-name label
744
+ and the second is refused:
745
+ failproofai harness add-path openclaw user1=/srv/.openclaw-user1
746
+ failproofai harness add-path openclaw user2=/srv/.openclaw-user2
747
+
748
+ Containers: FAILPROOFAI_<HARNESS>_EXTRA_PATHS replaces the file's entries.
749
+ FAILPROOFAI_OPENCLAW_EXTRA_PATHS="user1=/srv/.openclaw-user1,user2=/srv/.openclaw-user2"
750
+
736
751
  `.trimStart());
737
752
  process.exit(0);
738
753
  }
@@ -762,6 +777,211 @@ EXAMPLES
762
777
  // disables policies; this removes the product — hook entries across every
763
778
  // agent CLI plus the root-owned daemon service — and the two must not be one
764
779
  // keystroke apart.
780
+ if (args[0] === "migrate") {
781
+ const subArgs = args.slice(1);
782
+ if (subArgs.includes("--help") || subArgs.includes("-h")) {
783
+ console.log(`
784
+ failproofai migrate — bring ~/.failproofai up to the layout this version speaks
785
+
786
+ USAGE
787
+ failproofai migrate [--dry-run]
788
+
789
+ WHY
790
+ npm cannot update an installed package on its own, so a machine can sit on an
791
+ old version for months and then jump several layouts at once. This runs the
792
+ steps for that jump in order, keyed on the LAYOUT recorded in
793
+ ~/.failproofai/VERSION rather than on the npm version — so skipping thirty
794
+ releases with no layout change runs nothing at all.
795
+
796
+ It normally happens by itself, on the first command after an upgrade. This is
797
+ for running it deliberately, and for seeing what it would do first.
798
+
799
+ Your settings, cloud enrolment, policy selection, your own policy files,
800
+ decision history and undelivered events are carried across, not removed. The
801
+ irreplaceable files are copied to migrations/backup-layout<n>/ before anything
802
+ runs, and every step is recorded in migrations/applied.json.
803
+
804
+ OPTIONS
805
+ --dry-run Print the steps and the files that would be saved. Change nothing.
806
+ `);
807
+ process.exit(0);
808
+ }
809
+
810
+ const KNOWN = new Set(["--dry-run"]);
811
+ const unknown = subArgs.find((a) => a.startsWith("-") && !KNOWN.has(a));
812
+ if (unknown) {
813
+ throw new CliError(
814
+ `Unexpected argument: ${unknown}\nRun \`failproofai migrate --help\` for usage.`,
815
+ );
816
+ }
817
+
818
+ lastSubcommand = "migrate";
819
+ const { detectLayout } = await import("../src/hooks/fp-config");
820
+ const { LAYOUT_VERSION } = await import("../src/hooks/fp-home");
821
+ const { describePlan, runMigrations } = await import("../src/hooks/migrations");
822
+ const state = detectLayout();
823
+
824
+ // A NEWER home is refused here exactly as `checkLayoutForCli` refuses it: the
825
+ // data is fine and an upgrade would read it, so migrating "forward" from it
826
+ // is not a thing that exists.
827
+ if (state.kind === "future") {
828
+ console.error(
829
+ `This machine's failproofai directory was written by a newer version (layout ${state.found};`,
830
+ );
831
+ console.error(`this build speaks ${LAYOUT_VERSION}). Upgrade rather than migrate:`);
832
+ console.error(` npm install -g failproofai@latest`);
833
+ await track("cli_migrate", { ok: false, reason: "future_layout" });
834
+ lastSubcommand = null;
835
+ await exitAfterFlush(1);
836
+ return;
837
+ }
838
+
839
+ const from = state.kind === "stale" ? state.found : LAYOUT_VERSION;
840
+ if (subArgs.includes("--dry-run")) {
841
+ for (const line of describePlan(from)) console.log(line);
842
+ await track("cli_migrate", { ok: true, dry_run: true, from });
843
+ lastSubcommand = null;
844
+ await exitAfterFlush(0);
845
+ return;
846
+ }
847
+
848
+ if (state.kind !== "stale") {
849
+ console.log(`Already at layout ${LAYOUT_VERSION}. Nothing to migrate.`);
850
+ await track("cli_migrate", { ok: true, from, steps: 0 });
851
+ lastSubcommand = null;
852
+ await exitAfterFlush(0);
853
+ return;
854
+ }
855
+
856
+ const run = runMigrations(from);
857
+ for (const step of run.steps) {
858
+ console.log(`${step.ok ? "migrated" : "FAILED "} layout ${step.from} → ${step.to}`);
859
+ }
860
+ if (run.backedUp.length > 0) {
861
+ console.log(`Saved first: ${run.backedUp.join(", ")}`);
862
+ }
863
+ if (run.failed) {
864
+ console.error(`Step ${run.failed.from} → ${run.failed.to} did not finish: ${run.failed.error}`);
865
+ console.error(`The home is still marked layout ${from} and will be retried.`);
866
+ }
867
+ await track("cli_migrate", {
868
+ ok: !run.failed,
869
+ from,
870
+ steps: run.steps.length,
871
+ removed: run.outcome.removed.length,
872
+ });
873
+ lastSubcommand = null;
874
+ await exitAfterFlush(run.failed ? 1 : 0);
875
+ return;
876
+ }
877
+
878
+ if (args[0] === "update") {
879
+ const subArgs = args.slice(1);
880
+ if (subArgs.includes("--help") || subArgs.includes("-h")) {
881
+ console.log(`
882
+ failproofai update — finish an upgrade: migrate the home, match the daemon
883
+
884
+ USAGE
885
+ npm install -g failproofai@latest && failproofai update [--no-daemon]
886
+
887
+ WHY
888
+ npm replaces the CLI and nothing else. The daemon binary lives at
889
+ ~/.failproofai/bin/failproofaid-<version> and stays exactly where it was, so
890
+ after an npm upgrade the two halves are different versions — and failproofaid
891
+ refuses to start against a layout it does not speak, which is the loud version
892
+ of that problem rather than the silent one.
893
+
894
+ This does the rest of the upgrade: runs any pending layout migrations, puts the
895
+ matching daemon binary in place, and restarts the service.
896
+
897
+ OPTIONS
898
+ --no-daemon Migrate the home only. Leaves a version-skewed daemon in place,
899
+ so prefer letting it run.
900
+ `);
901
+ process.exit(0);
902
+ }
903
+
904
+ const KNOWN = new Set(["--no-daemon"]);
905
+ const unknown = subArgs.find((a) => a.startsWith("-") && !KNOWN.has(a));
906
+ if (unknown) {
907
+ throw new CliError(
908
+ `Unexpected argument: ${unknown}\nRun \`failproofai update --help\` for usage.`,
909
+ );
910
+ }
911
+
912
+ lastSubcommand = "update";
913
+ // Runs the migration itself rather than leaning on the check at the top of
914
+ // this file, which this command is exempt from. Reading the ledger and
915
+ // inferring "the top-level check must have done it" was the first version, and
916
+ // it is the kind of indirection that reads fine and reports the wrong thing
917
+ // the moment either half moves.
918
+ const { detectLayout } = await import("../src/hooks/fp-config");
919
+ const { LAYOUT_VERSION } = await import("../src/hooks/fp-home");
920
+ const { runMigrations } = await import("../src/hooks/migrations");
921
+ const state = detectLayout();
922
+
923
+ if (state.kind === "future") {
924
+ console.error(
925
+ `This machine's failproofai directory was written by a NEWER version (layout ${state.found};`,
926
+ );
927
+ console.error(`this build speaks ${LAYOUT_VERSION}). This CLI is the stale half:`);
928
+ console.error(` npm install -g failproofai@latest`);
929
+ await track("cli_update", { ok: false, reason: "future_layout" });
930
+ lastSubcommand = null;
931
+ await exitAfterFlush(1);
932
+ return;
933
+ }
934
+
935
+ let migrationsRan = 0;
936
+ let migrationFailed = false;
937
+ if (state.kind === "stale") {
938
+ const run = runMigrations(state.found);
939
+ migrationsRan = run.steps.length;
940
+ migrationFailed = Boolean(run.failed);
941
+ for (const step of run.steps) {
942
+ console.log(`${step.ok ? "migrated" : "FAILED "} layout ${step.from} → ${step.to}`);
943
+ }
944
+ if (run.backedUp.length > 0) console.log(`Saved first: ${run.backedUp.join(", ")}`);
945
+ if (run.failed) {
946
+ console.error(
947
+ `Step ${run.failed.from} → ${run.failed.to} did not finish: ${run.failed.error}`,
948
+ );
949
+ console.error(`The home is still marked layout ${state.found} and will be retried.`);
950
+ }
951
+ } else {
952
+ console.log(`Home is at layout ${LAYOUT_VERSION}; no migration was needed.`);
953
+ }
954
+
955
+ // The daemon is refreshed even when a step failed, and deliberately: the
956
+ // binary and the layout are independent halves, and leaving a version-skewed
957
+ // daemon behind on top of a failed migration is strictly worse than fixing
958
+ // the half that can be fixed. The exit code still reports the failure.
959
+ let daemonOk = true;
960
+ if (subArgs.includes("--no-daemon")) {
961
+ console.log("Skipped the daemon (--no-daemon). Its version may not match this CLI.");
962
+ } else {
963
+ const svc = await import("../src/hooks/daemon-service");
964
+ if (!svc.isDaemonSupportedPlatform()) {
965
+ console.log(`failproofaid does not run on ${process.platform}; nothing to update.`);
966
+ } else {
967
+ // `refreshDaemonToCliVersion` answers "is there a service at all" itself,
968
+ // so there is no separate installed check to get out of step with it.
969
+ const result = await svc.refreshDaemonToCliVersion();
970
+ for (const line of result.lines) console.log(line);
971
+ daemonOk = result.ok;
972
+ }
973
+ }
974
+
975
+ await track("cli_update", {
976
+ ok: daemonOk && !migrationFailed,
977
+ migrations: migrationsRan,
978
+ migration_failed: migrationFailed,
979
+ });
980
+ lastSubcommand = null;
981
+ await exitAfterFlush(daemonOk && !migrationFailed ? 0 : 1);
982
+ return;
983
+ }
984
+
765
985
  if (args[0] === "uninstall") {
766
986
  const subArgs = args.slice(1);
767
987
  if (subArgs.includes("--help") || subArgs.includes("-h")) {
@@ -11,10 +11,10 @@
11
11
  * keep alive itself. This shim exists only for a user (or script)
12
12
  * invoking `failproofaid` by hand.
13
13
  *
14
- * The npm package deliberately ships no binary: one tarball serves every
15
- * platform, and the four cross-compiled binaries live on the GitHub
16
- * Release for this version (see `src/hooks/daemon-download.ts`).
17
- * `failproofai config` is what fetches one. So "not installed" here is a
14
+ * The root npm tarball contains no native binary. A matching optional platform
15
+ * package normally supplies it; the GitHub Release for this version is the
16
+ * verified fallback (see `src/hooks/daemon-download.ts`). `failproofai config`
17
+ * installs either source into `~/.failproofai/bin`. So "not installed" here is a
18
18
  * normal state rather than a broken install, and it degrades with a
19
19
  * one-line message and a non-zero exit — never a stack trace — including
20
20
  * on a platform that has no binary at all (Windows). The daemon-connect