failproofai 0.0.14-beta.0 → 0.0.14-beta.2

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 (219) hide show
  1. package/.next/standalone/.codex/hooks.json +6 -6
  2. package/.next/standalone/.cursor/hooks.json +6 -6
  3. package/.next/standalone/.factory/hooks.json +9 -9
  4. package/.next/standalone/.next/BUILD_ID +1 -1
  5. package/.next/standalone/.next/build-manifest.json +5 -5
  6. package/.next/standalone/.next/prerender-manifest.json +3 -3
  7. package/.next/standalone/.next/required-server-files.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  9. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  10. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  11. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  14. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  15. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  16. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  18. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  20. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  21. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  22. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  23. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  24. package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
  25. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
  26. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  27. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
  28. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  29. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  30. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -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.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  37. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  40. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  41. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  43. package/.next/standalone/.next/server/app/index.html +1 -1
  44. package/.next/standalone/.next/server/app/index.rsc +15 -15
  45. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  46. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  47. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  48. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  49. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  50. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  51. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  52. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  55. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  56. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  57. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  58. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  59. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  60. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  61. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  62. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
  63. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  64. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  65. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  66. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  67. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  68. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  69. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  70. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  71. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0--lkk6._.js +1 -1
  72. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08w4wmd._.js +1 -1
  76. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g6bbuw._.js +1 -1
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +1 -1
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q0qzx1._.js +1 -1
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q2nbsl._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xuaoik._.js +3 -3
  83. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16le-kd._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ffkmds._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
  87. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mrihkj._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
  90. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qb590j._.js +1 -1
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +1 -1
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1shcqgr._.js +1 -1
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xuedea._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +4 -4
  95. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
  96. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
  97. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00cz9as._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__015_i4t._.js +2 -2
  100. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__030k0c6._.js +1 -1
  101. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03lv-pe._.js +2 -2
  102. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__042d3cd._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__05r_17v._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09q1168._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__07qfsfa._.js → [root-of-the-server]__09v9cwb._.js} +2 -2
  106. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e2l3c1._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h12me5._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hci7t3._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hdsupo._.js +2 -2
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p84xee._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qeuy9c._.js +2 -2
  112. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s89hoe._.js +2 -2
  113. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0twi4fj._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ynf7tx._.js +2 -2
  115. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11rtg6s._.js +1 -1
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +1 -1
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +1 -1
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17ai7sy._.js +2 -2
  119. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1dky4g0._.js +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +1 -1
  121. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tkjqka._.js +2 -2
  122. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__212nf49._.js +1 -1
  123. package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
  124. package/.next/standalone/.next/server/chunks/ssr/_1kje4fm._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/app_087bt9w._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/app_1fvisnp._.js +1 -1
  127. package/.next/standalone/.next/server/chunks/ssr/app_209u41o._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  129. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  130. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  131. package/.next/standalone/.next/server/chunks/ssr/lib_0xkhw_v._.js +1 -1
  132. package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_0g5r64e.js → node_modules_html-to-image_es_index_06xsmte.js} +1 -1
  133. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-uvagv.js +1 -1
  134. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03c7gi5.js +1 -1
  135. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_09p-8om.js +1 -1
  136. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0v-kfiu.js +1 -1
  137. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0xrgzyz.js +1 -1
  138. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1806lsc.js +1 -1
  139. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1j6dd-e.js +1 -1
  140. package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1sa65r-.js +1 -1
  141. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
  142. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
  143. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
  144. package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
  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 +10 -10
  149. package/.next/standalone/.next/static/chunks/{13f1kmjea-0md.js → 02jcotghcxrbu.js} +1 -1
  150. package/.next/standalone/.next/static/chunks/{1374x9bv_s_vg.js → 0h-6ymo9v86b0.js} +2 -2
  151. package/.next/standalone/.next/static/chunks/0pndjhcxfu-0t.js +1 -0
  152. package/.next/standalone/.next/static/chunks/1-33f82_l32or.js +1 -0
  153. package/.next/standalone/.next/static/chunks/{003uz088wbmz7.js → 1bg_g3g359c_d.js} +1 -1
  154. package/.next/standalone/.next/static/chunks/{454dyizqik6t9.js → 1gg-8e9q_m__9.js} +2 -2
  155. package/.next/standalone/.next/static/chunks/{2ufuwhv03yvtb.js → 29zkom4s9de2d.js} +1 -1
  156. package/.next/standalone/.next/static/chunks/{17sdztgbcc0fi.js → 2llkdafnaejw_.js} +1 -1
  157. package/.next/standalone/.next/static/chunks/{0iinhn4417nk1.js → 3-ogr79xqbw0h.js} +1 -1
  158. package/.next/standalone/.next/static/chunks/36j05kb2x323i.css +2 -0
  159. package/.next/standalone/.next/static/chunks/{43weu8f59tlix.js → 388hgfqye67xa.js} +1 -1
  160. package/.next/standalone/.next/static/chunks/396764jgd7-9j.js +1 -0
  161. package/.next/standalone/.next/static/chunks/3w7g0n0iwwnbs.js +1 -0
  162. package/.next/standalone/.next/static/chunks/{turbopack-0vavqo2d-tlt3.js → turbopack-10hj8t5pf33tu.js} +1 -1
  163. package/.next/standalone/.opencode/plugins/failproofai.mjs +30 -11
  164. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +11 -2
  165. package/.next/standalone/app/components/copy-button.tsx +22 -6
  166. package/.next/standalone/app/components/global-error-listeners.tsx +27 -0
  167. package/.next/standalone/components/reach-developers.tsx +1 -1
  168. package/.next/standalone/docker-hook-sync/Dockerfile +8 -4
  169. package/.next/standalone/integration-suite/Dockerfile +47 -0
  170. package/.next/standalone/integration-suite/README.md +87 -0
  171. package/.next/standalone/integration-suite/canary-policies.mjs +45 -0
  172. package/.next/standalone/integration-suite/capture-tokens.sh +48 -0
  173. package/.next/standalone/integration-suite/ci-entrypoint.sh +164 -0
  174. package/.next/standalone/integration-suite/inject-tokens.sh +44 -0
  175. package/.next/standalone/integration-suite/install-clis.sh +91 -0
  176. package/.next/standalone/integration-suite/probe-cli.sh +208 -0
  177. package/.next/standalone/integration-suite/report.js +74 -0
  178. package/.next/standalone/integration-suite/run.sh +107 -0
  179. package/.next/standalone/lib/error-origin.ts +67 -0
  180. package/.next/standalone/lib/format-duration.ts +23 -9
  181. package/.next/standalone/lib/install-check.ts +231 -0
  182. package/.next/standalone/package.json +1 -3
  183. package/.next/standalone/server.js +1 -1
  184. package/README.md +1 -17
  185. package/bin/failproofai.mjs +11 -1
  186. package/dist/cli.mjs +818 -320
  187. package/lib/error-origin.ts +67 -0
  188. package/lib/format-duration.ts +23 -9
  189. package/lib/install-check.ts +231 -0
  190. package/package.json +1 -3
  191. package/scripts/dev-hook.mjs +292 -0
  192. package/scripts/install-diagnosis.mjs +5 -8
  193. package/scripts/install-telemetry.mjs +12 -4
  194. package/scripts/translate-docs/cli.ts +53 -1
  195. package/scripts/translate-docs/mdx-translator.ts +158 -18
  196. package/scripts/translate-docs/readme-translator.ts +36 -18
  197. package/scripts/translate-docs/translator.ts +180 -9
  198. package/scripts/translate-docs/types.ts +6 -0
  199. package/scripts/translate-docs/validate-translation.ts +132 -0
  200. package/scripts/validate-mdx.ts +92 -15
  201. package/src/audit/cli.ts +53 -15
  202. package/src/auth/cli.ts +14 -5
  203. package/src/hooks/builtin-policies.ts +168 -50
  204. package/src/hooks/configure-wizard.ts +238 -22
  205. package/src/hooks/custom-hooks-loader.ts +70 -4
  206. package/src/hooks/handler.ts +4 -1
  207. package/src/hooks/policy-types.ts +8 -0
  208. package/src/hooks/tui.ts +96 -29
  209. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ge8e7w._.js +0 -3
  210. package/.next/standalone/.next/static/chunks/0405htbxay9vd.js +0 -1
  211. package/.next/standalone/.next/static/chunks/2m_tbl39fcedn.js +0 -1
  212. package/.next/standalone/.next/static/chunks/2o3ql0n5owqsw.js +0 -1
  213. package/.next/standalone/.next/static/chunks/35-90m9py64d4.js +0 -1
  214. package/.next/standalone/.next/static/chunks/3r--yyjkp9_7b.css +0 -2
  215. package/scripts/postinstall.mjs +0 -242
  216. package/scripts/preuninstall.mjs +0 -131
  217. /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_buildManifest.js +0 -0
  218. /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_clientMiddlewareManifest.js +0 -0
  219. /package/.next/standalone/.next/static/{MNJWFb2jLRrxRKGFNK6Hy → YKxI22hC-F_nHp7MEKfb1}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/0zbxssxh53n-3.js","static/chunks/1__i9af9g78vd.js","static/chunks/13f1kmjea-0md.js","static/chunks/1ua5armwfph8o.js","static/chunks/03fmihek9n986.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=["NEXT_DEPLOYMENT_ID","NEXT_CLIENT_ASSET_SUFFIX"];var o,i=((o=i||{})[o.Runtime=0]="Runtime",o[o.Parent=1]="Parent",o[o.Update=2]="Update",o);let l=new WeakMap;function s(e,t){this.m=e,this.e=t}let u=s.prototype,a=Object.prototype.hasOwnProperty,c="u">typeof Symbol&&Symbol.toStringTag;function f(e,t,r){a.call(e,t)||Object.defineProperty(e,t,r)}function p(e,t){let r=e[t];return r||(r=h(t),e[t]=r),r}function h(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function d(e,t){f(e,"__esModule",{value:!0}),c&&f(e,c,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)f(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?f(e,n,{get:o,set:t[r++],enumerable:!0}):f(e,n,{get:o,enumerable:!0})}Object.seal(e)}function m(e,t){(null!=t?p(this.c,t):this.m).exports=e}u.s=function(e,t){let r,n;null!=t?n=(r=p(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,d(n,e)},u.j=function(e,t){var r,n;let o,i,s;null!=t?i=(o=p(this.c,t)).exports:(o=this.m,i=this.e);let u=(r=o,n=i,(s=l.get(r))||(l.set(r,s=[]),r.exports=r.namespaceObject=new Proxy(n,{get(e,t){if(a.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of s){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of s)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),s);"object"==typeof e&&null!==e&&u.push(e)},u.v=m,u.n=function(e,t){let r;(r=null!=t?p(this.c,t):this.m).exports=r.namespaceObject=e};let b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,y=[null,b({}),b([]),b(b)];function g(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!y.includes(t);t=b(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),d(t,n),t}function O(e){let t=B(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=g(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function w(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}function k(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}u.i=O,u.A=function(e){return this.r(e)(O.bind(this))},u.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},u.r=function(e){return B(e,this.m).exports},u.f=function(e){function t(t){if(t=w(t),a.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=w(t),a.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let j=Symbol("turbopack queues"),U=Symbol("turbopack exports"),v=Symbol("turbopack error");function C(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}u.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:i,reject:l,promise:s}=k(),u=Object.assign(s,{[U]:r.exports,[j]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[U]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(j in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[U]:{},[j]:e=>e(t)};return e.then(e=>{r[U]=e,C(t)},e=>{r[v]=e,C(t)}),r}}return{[U]:e,[j]:()=>{}}}),r=()=>t.map(e=>{if(e[v])throw e[v];return e[U]}),{promise:i,resolve:l}=k(),s=Object.assign(()=>l(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[j](u)),s.queueCount?i:r()},function(e){e?l(u[v]=e):i(u[U]),C(n)}),n&&-1===n.status&&(n.status=0)};let P=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function R(e,t){throw Error(`Invariant: ${t(e)}`)}P.prototype=URL.prototype,u.U=P,u.z=function(e){throw Error("dynamic usage of require is not supported")},u.g=globalThis;let S=s.prototype,$=new Map;u.M=$;let _=new Map,E=new Map;async function T(e,t,r){let n;if("string"==typeof r)return M(e,t,N(r));let o=r.included||[],i=o.map(e=>!!$.has(e)||_.get(e));if(i.length>0&&i.every(e=>e))return void await Promise.all(i);let l=r.moduleChunks||[],s=l.map(e=>E.get(e)).filter(e=>e);if(s.length>0){if(s.length===l.length)return void await Promise.all(s);let r=new Set;for(let e of l)E.has(e)||r.add(e);for(let n of r){let r=M(e,t,N(n));E.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=M(e,t,N(r.path)),l))E.has(o)||E.set(o,n)}for(let e of o)_.has(e)||_.set(e,n);await n}S.l=function(e){return T(i.Parent,this.m.id,e)};let A=Promise.resolve(void 0),x=new WeakMap;function M(t,r,n){let o=e.loadChunkCached(t,n),l=x.get(o);if(void 0===l){let e=x.set.bind(x,o,A);l=o.then(e).catch(e=>{let o;switch(t){case i.Runtime:o=`as a runtime dependency of chunk ${r}`;break;case i.Parent:o=`from module ${r}`;break;case i.Update:o="from an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}let l=Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw l.name="ChunkLoadError",l}),x.set(o,l)}return l}function N(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}${r}`}S.L=function(e){return M(i.Parent,this.m.id,e)},S.R=function(e){let t=this.r(e);return t?.default??t},S.P=function(e){return`/ROOT/${e??""}`},S.q=function(e,t){m.call(this,`${e}${r}`,t)},S.b=function(e,t,o,i){let l="SharedWorker"===e.name,s=[o.map(e=>N(e)).reverse(),r];for(let e of n)s.push(globalThis[e]);let u=new URL(N(t),location.origin),a=JSON.stringify(s);return l?u.searchParams.set("params",a):u.hash="#params="+encodeURIComponent(a),new e(u,i?{...i,type:void 0}:void 0)};let K=/\.js(?:\?[^#]*)?(?:#.*)?$/,q=/\.css(?:\?[^#]*)?(?:#.*)?$/;function L(e){return q.test(e)}u.w=function(t,r,n){return e.loadWebAssembly(i.Parent,this.m.id,t,r,n)},u.u=function(t,r){return e.loadWebAssemblyModule(i.Parent,this.m.id,t,r)};let I={};u.c=I;let B=(e,t)=>{let r=I[e];if(r){if(r.error)throw r.error;return r}return W(e,i.Parent,t.id)};function W(e,t,r){let n=$.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=h(e),i=o.exports;I[e]=o;let l=new s(o,i);try{n(l,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&g(o.exports,o.namespaceObject),o}function F(t){let r,n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let i=e[o];for(let i=r;i<o;i++){let r=e[i],o=t.get(r);if(o){n=o;break}}let l=n??i,s=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(s||(l===i&&Object.defineProperty(i,"name",{value:"module evaluation"}),s=!0),t.set(r,l))}r=o+1}}(t,$)),e.registerChunk(n,r)}let X=new Map;function D(e){let t=X.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},X.set(e,t)}return t}e={async registerChunk(e,r){let n=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(e.src.replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(e);if(D("string"==typeof e?N(e):e.src).resolve(),null!=r){for(let e of r.otherChunks)D(N("string"==typeof e?e:e.path));if(await Promise.all(r.otherChunks.map(e=>T(i.Runtime,n,e))),r.runtimeModuleIds.length>0)for(let e of r.runtimeModuleIds)!function(e,t){let r=I[t];if(r){if(r.error)throw r.error;return}W(t,i.Runtime,e)}(n,e)}},loadChunkCached:(e,t)=>(function(e,t){let r=D(t);if(r.loadingStarted)return r.promise;if(e===i.Runtime)return r.loadingStarted=!0,L(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(L(t));else if(K.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(L(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(K.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let i=fetch(N(r)),{instance:l}=await WebAssembly.instantiateStreaming(i,o);return l.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(N(r));return await WebAssembly.compileStreaming(o)}};let H=globalThis.TURBOPACK;globalThis.TURBOPACK={push:F},H.forEach(F)})();
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/0zbxssxh53n-3.js","static/chunks/1__i9af9g78vd.js","static/chunks/02jcotghcxrbu.js","static/chunks/1ua5armwfph8o.js","static/chunks/03fmihek9n986.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=function(){if(null!=self.TURBOPACK_ASSET_SUFFIX)return self.TURBOPACK_ASSET_SUFFIX;let e=document?.currentScript?.getAttribute?.("src")??"",t=e.indexOf("?");return t>=0?e.slice(t):""}(),n=["NEXT_DEPLOYMENT_ID","NEXT_CLIENT_ASSET_SUFFIX"];var o,i=((o=i||{})[o.Runtime=0]="Runtime",o[o.Parent=1]="Parent",o[o.Update=2]="Update",o);let l=new WeakMap;function s(e,t){this.m=e,this.e=t}let u=s.prototype,a=Object.prototype.hasOwnProperty,c="u">typeof Symbol&&Symbol.toStringTag;function f(e,t,r){a.call(e,t)||Object.defineProperty(e,t,r)}function p(e,t){let r=e[t];return r||(r=h(t),e[t]=r),r}function h(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function d(e,t){f(e,"__esModule",{value:!0}),c&&f(e,c,{value:"Module"});let r=0;for(;r<t.length;){let n=t[r++],o=t[r++];if("number"==typeof o)if(0===o)f(e,n,{value:t[r++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[r]?f(e,n,{get:o,set:t[r++],enumerable:!0}):f(e,n,{get:o,enumerable:!0})}Object.seal(e)}function m(e,t){(null!=t?p(this.c,t):this.m).exports=e}u.s=function(e,t){let r,n;null!=t?n=(r=p(this.c,t)).exports:(r=this.m,n=this.e),r.namespaceObject=n,d(n,e)},u.j=function(e,t){var r,n;let o,i,s;null!=t?i=(o=p(this.c,t)).exports:(o=this.m,i=this.e);let u=(r=o,n=i,(s=l.get(r))||(l.set(r,s=[]),r.exports=r.namespaceObject=new Proxy(n,{get(e,t){if(a.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);for(let e of s){let r=Reflect.get(e,t);if(void 0!==r)return r}},ownKeys(e){let t=Reflect.ownKeys(e);for(let e of s)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t}})),s);"object"==typeof e&&null!==e&&u.push(e)},u.v=m,u.n=function(e,t){let r;(r=null!=t?p(this.c,t):this.m).exports=r.namespaceObject=e};let b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,y=[null,b({}),b([]),b(b)];function g(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!y.includes(t);t=b(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),d(t,n),t}function O(e){let t=B(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=g(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function w(e){let t=e.indexOf("#");-1!==t&&(e=e.substring(0,t));let r=e.indexOf("?");return -1!==r&&(e=e.substring(0,r)),e}function j(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}u.i=O,u.A=function(e){return this.r(e)(O.bind(this))},u.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},u.r=function(e){return B(e,this.m).exports},u.f=function(e){function t(t){if(t=w(t),a.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(t=w(t),a.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let k=Symbol("turbopack queues"),U=Symbol("turbopack exports"),v=Symbol("turbopack error");function C(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}u.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:i,reject:l,promise:s}=j(),u=Object.assign(s,{[U]:r.exports,[k]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[U]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(k in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[U]:{},[k]:e=>e(t)};return e.then(e=>{r[U]=e,C(t)},e=>{r[v]=e,C(t)}),r}}return{[U]:e,[k]:()=>{}}}),r=()=>t.map(e=>{if(e[v])throw e[v];return e[U]}),{promise:i,resolve:l}=j(),s=Object.assign(()=>l(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[k](u)),s.queueCount?i:r()},function(e){e?l(u[v]=e):i(u[U]),C(n)}),n&&-1===n.status&&(n.status=0)};let P=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function R(e,t){throw Error(`Invariant: ${t(e)}`)}P.prototype=URL.prototype,u.U=P,u.z=function(e){throw Error("dynamic usage of require is not supported")},u.g=globalThis;let S=s.prototype,$=new Map;u.M=$;let _=new Map,E=new Map;async function T(e,t,r){let n;if("string"==typeof r)return M(e,t,N(r));let o=r.included||[],i=o.map(e=>!!$.has(e)||_.get(e));if(i.length>0&&i.every(e=>e))return void await Promise.all(i);let l=r.moduleChunks||[],s=l.map(e=>E.get(e)).filter(e=>e);if(s.length>0){if(s.length===l.length)return void await Promise.all(s);let r=new Set;for(let e of l)E.has(e)||r.add(e);for(let n of r){let r=M(e,t,N(n));E.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=M(e,t,N(r.path)),l))E.has(o)||E.set(o,n)}for(let e of o)_.has(e)||_.set(e,n);await n}S.l=function(e){return T(i.Parent,this.m.id,e)};let x=Promise.resolve(void 0),A=new WeakMap;function M(t,r,n){let o=e.loadChunkCached(t,n),l=A.get(o);if(void 0===l){let e=A.set.bind(A,o,x);l=o.then(e).catch(e=>{let o;switch(t){case i.Runtime:o=`as a runtime dependency of chunk ${r}`;break;case i.Parent:o=`from module ${r}`;break;case i.Update:o="from an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}let l=Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw l.name="ChunkLoadError",l}),A.set(o,l)}return l}function N(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}${r}`}S.L=function(e){return M(i.Parent,this.m.id,e)},S.R=function(e){let t=this.r(e);return t?.default??t},S.P=function(e){return`/ROOT/${e??""}`},S.q=function(e,t){m.call(this,`${e}${r}`,t)},S.b=function(e,t,o,i){let l="SharedWorker"===e.name,s=[o.map(e=>N(e)).reverse(),r];for(let e of n)s.push(globalThis[e]);let u=new URL(N(t),location.origin),a=JSON.stringify(s);return l?u.searchParams.set("params",a):u.hash="#params="+encodeURIComponent(a),new e(u,i?{...i,type:void 0}:void 0)};let K=/\.js(?:\?[^#]*)?(?:#.*)?$/,q=/\.css(?:\?[^#]*)?(?:#.*)?$/;function L(e){return q.test(e)}u.w=function(t,r,n){return e.loadWebAssembly(i.Parent,this.m.id,t,r,n)},u.u=function(t,r){return e.loadWebAssemblyModule(i.Parent,this.m.id,t,r)};let I={};u.c=I;let B=(e,t)=>{let r=I[e];if(r){if(r.error)throw r.error;return r}return W(e,i.Parent,t.id)};function W(e,t,r){let n=$.get(e);if("function"!=typeof n)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:R(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=h(e),i=o.exports;I[e]=o;let l=new s(o,i);try{n(l,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&g(o.exports,o.namespaceObject),o}function F(t){let r,n=function(e){if("string"==typeof e)return e;if(e)return{src:e.getAttribute("src")};if("u">typeof TURBOPACK_NEXT_CHUNK_URLS)return{src:TURBOPACK_NEXT_CHUNK_URLS.pop()};throw Error("chunk path empty but not in a worker")}(t[0]);return 2===t.length?r=t[1]:(r=void 0,!function(e,t){let r=1;for(;r<e.length;){let n,o=r+1;for(;o<e.length&&"function"!=typeof e[o];)o++;if(o===e.length)throw Error("malformed chunk format, expected a factory function");let i=e[o];for(let i=r;i<o;i++){let r=e[i],o=t.get(r);if(o){n=o;break}}let l=n??i,s=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(s||(l===i&&Object.defineProperty(i,"name",{value:"module evaluation"}),s=!0),t.set(r,l))}r=o+1}}(t,$)),e.registerChunk(n,r)}let X=new Map;function D(e){let t=X.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},X.set(e,t)}return t}e={async registerChunk(e,r){let n=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(e.src.replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(e);if(D("string"==typeof e?N(e):e.src).resolve(),null!=r){for(let e of r.otherChunks)D(N("string"==typeof e?e:e.path));if(await Promise.all(r.otherChunks.map(e=>T(i.Runtime,n,e))),r.runtimeModuleIds.length>0)for(let e of r.runtimeModuleIds)!function(e,t){let r=I[t];if(r){if(r.error)throw r.error;return}W(t,i.Runtime,e)}(n,e)}},loadChunkCached:(e,t)=>(function(e,t){let r=D(t);if(r.loadingStarted)return r.promise;if(e===i.Runtime)return r.loadingStarted=!0,L(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(L(t));else if(K.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(L(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(K.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let i=fetch(N(r)),{instance:l}=await WebAssembly.instantiateStreaming(i,o);return l.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(N(r));return await WebAssembly.compileStreaming(o)}};let H=globalThis.TURBOPACK;globalThis.TURBOPACK={push:F},H.forEach(F)})();
@@ -1,11 +1,13 @@
1
1
  // AUTO-GENERATED by failproofai. __failproofai_hook__
2
2
  // Re-generate via: failproofai policies --install --cli opencode
3
3
  //
4
- // DEV variant: this repo's contributors run failproofai from source via
5
- // `bun bin/failproofai.mjs ...` instead of `npx -y failproofai`. This file
6
- // is the project-scope shim with that dev path baked in. The production
7
- // shape (npx-based) is generated by `src/hooks/integrations.ts` on install
8
- // for end users see `buildOpenCodePluginShim` there.
4
+ // DEV variant: this repo's contributors run failproofai from source, via
5
+ // the shared `scripts/dev-hook.mjs` resolver rather than `npx -y failproofai`.
6
+ // That resolver locates bun across PATH, $BUN_INSTALL/bin, ~/.bun/bin, Homebrew
7
+ // and every nvm version dir — a bare `spawnSync("bun")` silently fails open the
8
+ // moment bun is off the hook's PATH. The production shape (npx-based) is
9
+ // generated by `src/hooks/integrations.ts` on install for end users — see
10
+ // `buildOpenCodePluginShim` there.
9
11
  //
10
12
  // Do NOT install this repo via `failproofai policies --install --cli
11
13
  // opencode --scope project` — it would overwrite this dev path with the
@@ -17,10 +19,7 @@
17
19
  // When #337 landed, this dev shim drifted and `block-read-outside-cwd`
18
20
  // silently no-op'd on every opencode `read` call inside this repo.
19
21
  import { spawnSync } from "node:child_process";
20
- import { resolve } from "node:path";
21
-
22
- const REPO_ROOT = resolve(import.meta.dirname, "..", "..");
23
- const FAILPROOFAI_DEV_BIN = resolve(REPO_ROOT, "bin", "failproofai.mjs");
22
+ import { resolveDevSpawn } from "../../scripts/dev-hook.mjs";
24
23
 
25
24
  const BUS_EVENT_MAP = {
26
25
  "session.created": "SessionStart",
@@ -72,13 +71,33 @@ function canonicalizeToolInput(canonicalToolName, args) {
72
71
  }
73
72
 
74
73
  function runFailproofai(eventName, payload, directory) {
75
- const r = spawnSync("bun", [FAILPROOFAI_DEV_BIN, "--hook", eventName, "--cli", "opencode"], {
74
+ // Shared with the JSON configs' launcher: locates bun across PATH, ~/.bun/bin,
75
+ // $BUN_INSTALL, Homebrew and every nvm version dir. A bare spawnSync("bun")
76
+ // dies with ENOENT the moment bun is off the hook's PATH.
77
+ const spawn = resolveDevSpawn();
78
+ if (!spawn) {
79
+ process.stderr.write(
80
+ "[failproofai-dev] bun not found — opencode policies are NOT enforcing. " +
81
+ "Install bun: curl -fsSL https://bun.sh/install | bash\n",
82
+ );
83
+ return { exitCode: 0, stdout: "", stderr: "" };
84
+ }
85
+ const r = spawnSync(spawn.cmd, [...spawn.args, "--hook", eventName, "--cli", "opencode"], {
76
86
  input: JSON.stringify(payload),
77
87
  encoding: "utf8",
78
88
  timeout: 60_000,
79
89
  cwd: directory,
80
90
  });
81
- return { exitCode: r.status ?? 0, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
91
+ // `r.status` is null when the spawn never ran (ENOENT) or the child was
92
+ // killed. Coercing that to 0 reports "allowed" for a policy that never got
93
+ // to run, so say so on stderr rather than failing open in silence.
94
+ if (r.status === null) {
95
+ process.stderr.write(
96
+ `[failproofai-dev] ${eventName} hook did not run (${r.error?.code ?? r.signal ?? "unknown"}) — not enforcing\n`,
97
+ );
98
+ return { exitCode: 0, stdout: "", stderr: "" };
99
+ }
100
+ return { exitCode: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
82
101
  }
83
102
 
84
103
  async function applyDecision(result, ctx, eventName) {
@@ -84,10 +84,19 @@ function buildFixes(result: AuditResult): FixRow[] {
84
84
  }));
85
85
  }
86
86
 
87
+ /**
88
+ * The "install all" command.
89
+ *
90
+ * `policy add` and `policies --install` are DIFFERENT commands, not aliases:
91
+ * `policy add` enables exactly one policy and rejects a second name outright
92
+ * ("`policy add` takes exactly one policy name"). This button is almost always
93
+ * multi-policy — listing the gaps is the section's whole job — so it must use
94
+ * the plural form, which is the one that accepts a list. Using `policy add`
95
+ * here handed the user a command that errored on paste.
96
+ */
87
97
  function bulkInstall(fixes: FixRow[]): string {
88
98
  if (fixes.length === 0) return "";
89
- if (fixes.length === 1) return `failproofai policy add ${fixes[0]!.name}`;
90
- return `failproofai policy add ${fixes.map((f) => f.name).join(" ")}`;
99
+ return `failproofai policies --install ${fixes.map((f) => f.name).join(" ")}`;
91
100
  }
92
101
 
93
102
  export function HowToImproveSection({ result, projected, projectedGrade }: Props) {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useState, useCallback } from "react";
3
+ import { useState, useCallback, useEffect, useRef } from "react";
4
4
  import { Copy, Check } from "lucide-react";
5
5
  import { cn } from "@/lib/utils";
6
6
 
@@ -25,6 +25,23 @@ interface CopyButtonProps {
25
25
 
26
26
  export function CopyButton({ text, className }: CopyButtonProps) {
27
27
  const [copied, setCopied] = useState(false);
28
+ const revertTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
29
+
30
+ // Clear any pending revert timer on unmount so `setCopied` never fires
31
+ // after the component is gone.
32
+ useEffect(() => {
33
+ return () => {
34
+ if (revertTimerRef.current) clearTimeout(revertTimerRef.current);
35
+ };
36
+ }, []);
37
+
38
+ const armRevertTimer = useCallback(() => {
39
+ // A re-click resets the 2s window rather than being cut short by the
40
+ // previous (stale) timer.
41
+ if (revertTimerRef.current) clearTimeout(revertTimerRef.current);
42
+ setCopied(true);
43
+ revertTimerRef.current = setTimeout(() => setCopied(false), 2000);
44
+ }, []);
28
45
 
29
46
  const handleCopy = useCallback(async () => {
30
47
  try {
@@ -33,24 +50,23 @@ export function CopyButton({ text, className }: CopyButtonProps) {
33
50
  } else if (!fallbackCopyText(text)) {
34
51
  throw new Error("Both clipboard methods failed");
35
52
  }
36
- setCopied(true);
37
- setTimeout(() => setCopied(false), 2000);
53
+ armRevertTimer();
38
54
  } catch (err) {
39
55
  console.error("Failed to copy to clipboard:", err);
40
56
  // Try fallback if the modern API threw
41
57
  try {
42
58
  if (fallbackCopyText(text)) {
43
- setCopied(true);
44
- setTimeout(() => setCopied(false), 2000);
59
+ armRevertTimer();
45
60
  }
46
61
  } catch {
47
62
  // Both methods failed — do nothing
48
63
  }
49
64
  }
50
- }, [text]);
65
+ }, [text, armRevertTimer]);
51
66
 
52
67
  return (
53
68
  <button
69
+ type="button"
54
70
  onClick={handleCopy}
55
71
  title="Copy to clipboard"
56
72
  className={cn(
@@ -2,10 +2,27 @@
2
2
 
3
3
  import { useEffect } from "react";
4
4
  import { captureClientEvent } from "@/lib/client-telemetry";
5
+ import { isAppError } from "@/lib/error-origin";
5
6
 
7
+ /**
8
+ * Reports uncaught dashboard errors.
9
+ *
10
+ * Both listeners are page-global, so they also see failures from browser
11
+ * extensions injected into the page (MetaMask and friends). Those are filtered
12
+ * out — see lib/error-origin.ts — so this reports only our own failures.
13
+ */
6
14
  export function GlobalErrorListeners() {
7
15
  useEffect(() => {
8
16
  const handleError = (event: ErrorEvent) => {
17
+ if (
18
+ !isAppError({
19
+ stack: event.error?.stack,
20
+ filename: event.filename,
21
+ appOrigin: window.location.origin,
22
+ })
23
+ ) {
24
+ return;
25
+ }
9
26
  captureClientEvent("unhandled_exception", {
10
27
  error_message: event.message,
11
28
  error_name: event.error?.name,
@@ -17,6 +34,16 @@ export function GlobalErrorListeners() {
17
34
 
18
35
  const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
19
36
  const reason = event.reason;
37
+ // A rejection carries no filename, so the stack is the only evidence of
38
+ // where it came from. A non-Error reason has none and stays unattributed.
39
+ if (
40
+ !isAppError({
41
+ stack: reason instanceof Error ? reason.stack : undefined,
42
+ appOrigin: window.location.origin,
43
+ })
44
+ ) {
45
+ return;
46
+ }
20
47
  captureClientEvent("unhandled_rejection", {
21
48
  error_message: reason instanceof Error ? reason.message : String(reason),
22
49
  error_name: reason instanceof Error ? reason.name : undefined,
@@ -25,7 +25,7 @@ const options = [
25
25
  {
26
26
  label: "Join our Discord",
27
27
  icon: MessageCircle,
28
- href: "https://discord.gg/2zjBZP7yQJ",
28
+ href: "https://discord.befailproof.ai/",
29
29
  color: "#5865f2",
30
30
  bg: "rgba(88,101,242,0.08)",
31
31
  },
@@ -5,10 +5,14 @@
5
5
  # harness we integrate with and this repo, and opens ONE auto-PR with the fix.
6
6
  #
7
7
  # Bundles:
8
- # - Node 20 + npm
9
- # - bun (REQUIRED: the cloned repo's .claude/settings.json fires hooks via
10
- # `bun $CLAUDE_PROJECT_DIR/bin/failproofai.mjs --hook <Event>`, so the
11
- # dogfooded require-*-before-stop policies enforce the commit/push/PR)
8
+ # - Node 20 + npm (npm is a fallback bun installer for scripts/dev-hook.mjs;
9
+ # node runs the launcher itself)
10
+ # - bun (STILL REQUIRED: the cloned repo's .claude/settings.json fires hooks via
11
+ # `node "$CLAUDE_PROJECT_DIR/scripts/dev-hook.mjs" --hook <Event>`, and that
12
+ # launcher only *locates* bun — it cannot conjure one. Without this layer the
13
+ # dogfooded require-*-before-stop policies never fire and the auto-PR is
14
+ # never committed/pushed. We install to BUN_INSTALL=/home/appuser/.bun, which
15
+ # the launcher probes explicitly, so enforcement survives a broken PATH.)
12
16
  # - Claude Code CLI (`claude`) — run headless with --effort ultracode
13
17
  # - failproofai@latest on PATH (belt-and-suspenders; the dogfood hooks actually
14
18
  # run the clone's SOURCE via bun, not this global)
@@ -0,0 +1,47 @@
1
+ # failproofai CLI-canary sandbox — base image
2
+ #
3
+ # Design goals (see failproofai-cli-canary-design.md §4):
4
+ # - SAFE: non-root user, NO sudo installed, no host FS mounted at runtime.
5
+ # The canary fires `sudo whoami` / `.env`-read deny-probes; here they
6
+ # are inert BY CONSTRUCTION even on a day enforcement is broken.
7
+ # - LIGHT: ephemeral daily container (`docker run --rm`), not a daemon.
8
+ # Only this image + one named volume persist; zero idle CPU/RAM.
9
+ # - FRESH: CLIs are NOT baked in — they are `@latest`-installed into the
10
+ # persistent HOME volume at run time (the whole point of the canary),
11
+ # so this base image rebuilds rarely.
12
+ #
13
+ # The HOME volume (mounted at /home/canary) holds: npm-global CLIs, every
14
+ # vendor login/token, and per-CLI config — so logins survive across daily runs.
15
+
16
+ FROM node:22-bookworm-slim
17
+
18
+ # bun from the official image — no `curl | bash` needed at build time.
19
+ COPY --from=oven/bun:latest /usr/local/bin/bun /usr/local/bin/bun
20
+
21
+ # Minimal tooling for the various vendor CLI installers. Deliberately NO sudo.
22
+ # Tooling for the various vendor installers. Deliberately NO sudo.
23
+ # bzip2/xz-utils : goose extracts its Rust binary with these
24
+ # libsecret-1-0 : antigravity caches login tokens via libsecret (best-effort)
25
+ RUN apt-get update -qq \
26
+ && apt-get install -y -qq --no-install-recommends \
27
+ git ca-certificates curl unzip bzip2 xz-utils libsecret-1-0 \
28
+ && rm -rf /var/lib/apt/lists/*
29
+
30
+ # Unprivileged user. HOME is the mount point for the persistent named volume;
31
+ # because the image ships a canary-owned /home/canary, an empty named volume
32
+ # mounted here is initialised canary-owned (Docker copies image content+owner).
33
+ # node:22-slim already ships a `node` user at UID 1000, so pin canary to 1001.
34
+ RUN useradd --create-home --uid 1001 --shell /bin/bash canary
35
+ USER canary
36
+ WORKDIR /home/canary
37
+ RUN mkdir -p /home/canary/.npm-global/bin /home/canary/.local/bin
38
+
39
+ # NPM_CONFIG_PREFIX via ENV (not `npm config set`) so it survives the volume
40
+ # mount shadowing /home/canary at runtime. Runtime `npm i -g` lands in the volume.
41
+ ENV NPM_CONFIG_PREFIX=/home/canary/.npm-global
42
+ ENV PATH=/home/canary/.npm-global/bin:/home/canary/.local/bin:/usr/local/bin:/usr/bin:/bin
43
+
44
+ # Sanity: fail the build if bun/node/npm aren't all runnable as the canary user.
45
+ RUN bun --version && node --version && npm --version
46
+
47
+ CMD ["bash"]
@@ -0,0 +1,87 @@
1
+ # Integration suite
2
+
3
+ A daily **live-enforcement integration test** for failproofai. It answers one
4
+ question the unit/e2e suites can't: *does failproofai still enforce against every
5
+ supported agent CLI, at the versions users actually install today?*
6
+
7
+ Every day (`.github/workflows/integration-suite.yml`) it installs all 12 agent
8
+ CLIs **@latest** into an isolated Docker sandbox, drives each one against
9
+ failproofai's own policies (built from this repo's HEAD), and confirms the hook
10
+ log shows a **DENY**. A *silent-allow* — a blocked action that ran with no deny —
11
+ means enforcement broke against that CLI (e.g. a vendor changed their hook schema
12
+ out from under us). The test asserts the deny **positively**, so drift surfaces
13
+ as a red run + a Slack alert instead of going unnoticed until a user hits it.
14
+
15
+ ## Why it's separate from `__tests__/`
16
+
17
+ It drives **real vendor CLIs against real gateway models** — it needs network,
18
+ Docker, credentials, and ~7-10 min, none of which belong in the fast in-process
19
+ vitest suites. So it's a scheduled workflow, not a PR gate.
20
+
21
+ ## How a run works
22
+
23
+ The workflow is a thin trigger; `ci-entrypoint.sh` is the front door and does
24
+ everything below except the Actions cache restore/save.
25
+
26
+ 1. Restore `integration-suite-state.json` from Actions cache (version-gate +
27
+ broke/recovered diff) — *workflow*.
28
+ 2. Build failproofai under test (`dist/index.js` + `dist/cli.mjs`) from this repo.
29
+ 3. Decode the OAuth token secrets, build the sandbox image, create the per-run
30
+ HOME volume, install all 12 CLIs (`install-clis.sh`), inject the credential
31
+ files (`inject-tokens.sh`), assemble the gateway env-file.
32
+ 4. `run.sh` probes each non-gated CLI (`probe-cli.sh`), builds the report
33
+ (`report.js`), and POSTs it to Slack.
34
+ 5. Cleanup (env-file + volume) runs via `trap`, so it happens on failure too.
35
+
36
+ Run it locally the same way CI does — every input is an env var:
37
+
38
+ ```bash
39
+ CANARY_LLM_API_KEY=... CANARY_SKIP_BUILD=1 \
40
+ bash integration-suite/ci-entrypoint.sh
41
+ ```
42
+
43
+ **Version-gate:** a CLI is re-probed only when its binary version **or**
44
+ failproofai's HEAD changed since its last green run — unchanged ⇒ can't have
45
+ drifted ⇒ skip, protecting LLM/vendor quota. `FAIL`/`INCONCLUSIVE`/`ERROR` always
46
+ re-probe until they recover. Dispatch with **force** to probe everything.
47
+
48
+ ## Auth & secrets (the `cli-integration` Environment)
49
+
50
+ > The GitHub **Environment** is still named `cli-integration` — it's configured in
51
+ > repo settings, not in this tree, so it was deliberately left alone when this
52
+ > directory was renamed. Renaming it there means renaming `environment:` in the
53
+ > workflow at the same time, or the job loses access to every secret.
54
+
55
+ Because this repo is public, all credentials live in a scoped **GitHub
56
+ Environment** (`cli-integration`) — only this workflow's job can read them — and
57
+ the workflow triggers on `schedule`/`workflow_dispatch` **only**, so fork PRs can
58
+ never reach them.
59
+
60
+ | Auth | CLIs | Secret(s) |
61
+ |------|------|-----------|
62
+ | Env-var (gateway) | claude, codex, goose, opencode, pi, hermes, openclaw, factory | `CANARY_LLM_API_KEY`, `CANARY_LLM_BASE_URL` |
63
+ | Env-var (PAT) | copilot | `COPILOT_GITHUB_TOKEN` |
64
+ | Injected token file | cursor, devin, antigravity | `CURSOR_/DEVIN_/ANTIGRAVITY_TOKEN_TGZ_B64` |
65
+ | Delivery | — | `SLACK_WEBHOOK_URL` |
66
+
67
+ The injected-token CLIs carry OAuth session tokens captured from a logged-in
68
+ machine (see `capture-tokens.sh`). They authenticate on a fresh runner, but may
69
+ eventually expire — when that happens the test reports `⚠️ ERROR` for that CLI;
70
+ re-login on the capture machine and refresh the secret.
71
+
72
+ > Note: env-var / secret names keep the historical `CANARY_` prefix internally —
73
+ > renaming them across the harness would be churn with no user-visible benefit.
74
+
75
+ ## Files
76
+
77
+ ```
78
+ ci-entrypoint.sh CI front door: build -> sandbox -> install -> probe -> cleanup
79
+ Dockerfile non-root sandbox base image
80
+ install-clis.sh install/upgrade all 12 CLIs @latest (with retries)
81
+ inject-tokens.sh write captured OAuth creds into the fresh volume
82
+ probe-cli.sh live enforcement probe for ONE CLI (the oracle)
83
+ canary-policies.mjs benign-marker custom policies the probe trips
84
+ run.sh orchestrator (gate → probe → report → Slack)
85
+ report.js build the Slack report + diff state (broke/recovered)
86
+ capture-tokens.sh (run on a logged-in machine) refresh the OAuth token secrets
87
+ ```
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Canary custom policies — the DEFINITE probe.
3
+ *
4
+ * The canary probes use BENIGN actions an agent never refuses: `echo`-ing a
5
+ * token, and reading a plain local file. Because there's nothing scary about
6
+ * them, the model reliably issues the tool call — eliminating the self-censorship
7
+ * that made sudo/.env/system-read probes come back INCONCLUSIVE.
8
+ *
9
+ * These policies intercept exactly those benign markers. A deny in the hook log
10
+ * is therefore positive proof that the full enforcement pipeline works against
11
+ * the CLI's REAL tool payload: hook fired → payload normalized (tool_name +
12
+ * tool_input.command / file_path — the drift-prone fields behind the Copilot
13
+ * 1.0.70 silent-allow) → policy evaluated → deny emitted. If normalization ever
14
+ * drifts, ctx.toolInput.command/file_path go empty, no deny fires, the benign
15
+ * command runs, and the probe reports FAIL — never a false alarm, never a miss.
16
+ */
17
+ import { customPolicies, allow, deny } from "failproofai";
18
+
19
+ // Bash-command path: deny a benign shell command carrying the probe token.
20
+ customPolicies.add({
21
+ name: "canary-bash",
22
+ description: "Canary: deny the benign probe shell command (CANARY_PROBE token)",
23
+ match: { events: ["PreToolUse"] },
24
+ fn: async (ctx) => {
25
+ if (ctx.toolName !== "Bash") return allow();
26
+ const cmd = String(ctx.toolInput?.command ?? "");
27
+ if (cmd.includes("CANARY_PROBE")) return deny("canary-bash probe intercepted");
28
+ return allow();
29
+ },
30
+ });
31
+
32
+ // File-path path: deny reading the benign marker file (via Read tool OR `cat`).
33
+ customPolicies.add({
34
+ name: "canary-read",
35
+ description: "Canary: deny reading the benign probe marker file (CANARY_MARKER)",
36
+ match: { events: ["PreToolUse"] },
37
+ fn: async (ctx) => {
38
+ const path = String(ctx.toolInput?.file_path ?? "");
39
+ const cmd = String(ctx.toolInput?.command ?? "");
40
+ if (path.includes("CANARY_MARKER") || cmd.includes("CANARY_MARKER")) {
41
+ return deny("canary-read probe intercepted");
42
+ }
43
+ return allow();
44
+ },
45
+ });
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+ # ─────────────────────────────────────────────────────────────────────────────
3
+ # capture-tokens.sh — run on the OFFICE BOX (has the logged-in canary volume).
4
+ # ./capture-tokens.sh <owner/repo>
5
+ #
6
+ # Captures each OAuth CLI's credential tree from the persistent HOME volume as a
7
+ # base64 gzip-tar rooted at $HOME, and stores it as a GitHub Actions secret on
8
+ # the canary repo. The CI workflow decodes it back onto the ephemeral runner's
9
+ # volume (see sandbox/inject-tokens.sh), so cursor/devin/antigravity authenticate
10
+ # in CI without an interactive login.
11
+ #
12
+ # Re-run this whenever the canary reports ERROR (not-logged-in / 401) for one of
13
+ # these CLIs — i.e. after you re-login on the box — to refresh the secret.
14
+ #
15
+ # NB: these are real credentials for internal@exosphere.host. They live only in
16
+ # GitHub *encrypted secrets*, never in the repo tree.
17
+ # ─────────────────────────────────────────────────────────────────────────────
18
+ set -euo pipefail
19
+ REPO="${1:?usage: capture-tokens.sh <owner/repo>}"
20
+ VOL="${CANARY_VOL:-failproofai-canary-home}"
21
+ IMAGE="${CANARY_IMAGE:-failproofai-canary:base}"
22
+
23
+ # secret-name → $HOME-relative path(s) to tar from the volume
24
+ capture() {
25
+ local secret="$1"; shift
26
+ local paths=("$@")
27
+ echo "── $secret ($(printf '%s ' "${paths[@]}"))"
28
+ # Tar the paths (rooted at $HOME) inside the container, gzip, base64 → host.
29
+ local b64
30
+ b64="$(docker run --rm -v "$VOL:/home/canary" "$IMAGE" bash -c "
31
+ cd \$HOME || exit 1
32
+ miss=1
33
+ for p in ${paths[*]}; do [ -e \"\$p\" ] && miss=0; done
34
+ [ \$miss = 1 ] && { echo 'MISSING' >&2; exit 3; }
35
+ tar -czf - ${paths[*]} 2>/dev/null | base64 -w0
36
+ ")" || { echo " ⚠️ none of the paths exist in the volume — skipping (login first)"; return 0; }
37
+ if [ -z "$b64" ]; then echo " ⚠️ empty capture — skipping"; return 0; fi
38
+ printf '%s' "$b64" | gh secret set "$secret" --repo "$REPO" --body -
39
+ echo " ✓ set $secret (${#b64} b64 chars)"
40
+ }
41
+
42
+ echo "Capturing OAuth credential trees from volume '$VOL' → secrets on $REPO"
43
+ capture CURSOR_TOKEN_TGZ_B64 .config/cursor
44
+ capture DEVIN_TOKEN_TGZ_B64 .local/share/devin/credentials.toml
45
+ # antigravity: capture ONLY the small OAuth token file — the full ~/.gemini tree
46
+ # is ~15 MB (CLI binary + brain/ + logs), far over GitHub's 48 KB secret cap.
47
+ capture ANTIGRAVITY_TOKEN_TGZ_B64 .gemini/antigravity-cli/antigravity-oauth-token
48
+ echo "done."