failproofai 1.0.4-beta.8 → 1.0.5-beta.0

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 (246) 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 -2
  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 +6 -6
  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/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  16. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  18. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  21. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  22. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
  27. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
  34. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  35. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  36. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +4 -37
  37. package/.next/standalone/.next/server/app/audit/page.js +2 -2
  38. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  39. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  40. package/.next/standalone/.next/server/app/index.html +1 -1
  41. package/.next/standalone/.next/server/app/index.rsc +14 -14
  42. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  43. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  44. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  45. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  46. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  47. package/.next/standalone/.next/server/app/page.js +2 -2
  48. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  51. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  52. package/.next/standalone/.next/server/app/policies/page.js +4 -4
  53. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  54. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  55. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  56. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  57. package/.next/standalone/.next/server/app/project/[name]/page.js +4 -4
  58. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
  61. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  62. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  63. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +5 -5
  64. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  65. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  66. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  67. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  68. package/.next/standalone/.next/server/app/projects/page.js +3 -3
  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/app/settings/page/build-manifest.json +2 -2
  72. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -15
  73. package/.next/standalone/.next/server/app/settings/page.js +4 -4
  74. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  75. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  76. package/.next/standalone/.next/server/chunks/{[externals]__0hmcwgg._.js → [externals]__0-9ti7z._.js} +1 -1
  77. package/.next/standalone/.next/server/chunks/{[externals]__14b7cc6._.js → [externals]__0u3wrvq._.js} +1 -1
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +3 -0
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +3 -0
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +3 -0
  85. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p-qi2t._.js +5 -0
  87. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/{_1_eakl4._.js → _1-akg6w._.js} +2 -2
  90. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +10 -10
  91. package/.next/standalone/.next/server/chunks/_1vslkoe._.js +1 -1
  92. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
  93. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
  95. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__187jks6._.js → [root-of-the-server]__00-s7h8._.js} +1 -1
  96. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__04px77e._.js → [root-of-the-server]__013jr2b._.js} +3 -3
  97. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0i0l1di._.js → [root-of-the-server]__01wy8d-._.js} +3 -3
  98. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0r3c1_0._.js → [root-of-the-server]__02npjtd._.js} +3 -3
  99. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1ckpmkk._.js → [root-of-the-server]__0da85px._.js} +3 -3
  100. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__17xnxlx._.js → [root-of-the-server]__0ftmoxc._.js} +3 -3
  101. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0kokc8z._.js → [root-of-the-server]__0n_lxhg._.js} +1 -1
  102. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0-4ja6q._.js → [root-of-the-server]__0p-5p8u._.js} +3 -3
  104. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0egr5s1._.js → [root-of-the-server]__0s740oi._.js} +3 -3
  105. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1fa1jd9._.js → [root-of-the-server]__0x1aj1_._.js} +2 -2
  106. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1kpd1za._.js → [root-of-the-server]__190won8._.js} +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +3 -0
  108. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +3 -0
  109. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__00cr3xu._.js → [root-of-the-server]__1p2otjt._.js} +3 -3
  110. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__00y9ww2._.js → [root-of-the-server]__1sc84bb._.js} +2 -21
  111. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  112. package/.next/standalone/.next/server/chunks/ssr/{_0s-77v5._.js → _0h_douw._.js} +1 -1
  113. package/.next/standalone/.next/server/chunks/ssr/{_00bqkhj._.js → _0u3xxgc._.js} +2 -2
  114. package/.next/standalone/.next/server/chunks/ssr/_0zs_4uu._.js +3 -0
  115. package/.next/standalone/.next/server/chunks/ssr/_1_ozgif._.js +1 -1
  116. package/.next/standalone/.next/server/chunks/ssr/_1ddpc5g._.js +1 -1
  117. package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +14 -51
  118. package/.next/standalone/.next/server/chunks/ssr/{_14c6q09._.js → _1if9ixi._.js} +2 -21
  119. package/.next/standalone/.next/server/chunks/ssr/{_07t3jol._.js → _1u8-lu2._.js} +2 -2
  120. package/.next/standalone/.next/server/chunks/ssr/_1ylae7o._.js +3 -0
  121. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +3 -0
  122. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  123. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +69 -1
  124. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  125. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  126. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  127. package/.next/standalone/.next/server/chunks/ssr/lib_openclaw-projects_ts_0qxq3bp._.js +1 -1
  128. package/.next/standalone/.next/server/chunks/ssr/node_modules_13n822a._.js +1 -1
  129. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +3 -0
  130. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  131. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +1 -1
  132. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
  133. package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
  134. package/.next/standalone/.next/server/pages/404.html +1 -1
  135. package/.next/standalone/.next/server/pages/500.html +1 -1
  136. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  137. package/.next/standalone/.next/server/server-reference-manifest.json +21 -65
  138. package/.next/standalone/.next/static/chunks/0hw6-c206lsma.js +1 -0
  139. package/.next/standalone/.next/static/chunks/{2mizt96igig1y.js → 0m9sx3khjrl1q.js} +1 -1
  140. package/.next/standalone/.next/static/chunks/{1302duobnz07l.js → 0oos8qpc1ugos.js} +1 -1
  141. package/.next/standalone/.next/static/chunks/0u64yey446k4f.css +1 -0
  142. package/.next/standalone/.next/static/chunks/{2ukucf6g-kbs5.js → 0unrx9g_x0u7j.js} +1 -1
  143. package/.next/standalone/.next/static/chunks/{0jpd8dv2vk930.css → 29-iqnp9v_axt.css} +1 -1
  144. package/.next/standalone/.next/static/chunks/{3uyhmm01g64k4.css → 2k9f4tyv04809.css} +0 -1
  145. package/.next/standalone/.next/static/chunks/{0vm4wdx3w-2_w.js → 2qjn-leir0x_s.js} +1 -1
  146. package/.next/standalone/.next/static/chunks/{1chm9piluggc-.js → 2xbxkaszi1xnw.js} +1 -1
  147. package/.next/standalone/.next/static/chunks/{2n85g-crgcx5j.js → 33umhy-x204qj.js} +2 -2
  148. package/.next/standalone/.next/static/chunks/3nux7kkrc3eps.js +69 -0
  149. package/.next/standalone/.next/static/chunks/3qfoeqhy5l10x.js +1 -0
  150. package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +1 -0
  151. package/.next/standalone/.next/static/chunks/{3a4gth64hwtwf.js → 40tpgs4fjct5p.js} +1 -1
  152. package/.next/standalone/.next/static/chunks/{1_x7pqemw5n_w.js → 40uih96wnkowy.js} +1 -1
  153. package/.next/standalone/.next/static/chunks/{turbopack-3s3c-u_u_l0u9.js → turbopack-3p73obe0xmrxm.js} +1 -1
  154. package/.next/standalone/.opencode/plugins/failproofai.mjs +27 -51
  155. package/.next/standalone/app/actions/get-scheduled-audit.ts +0 -5
  156. package/.next/standalone/app/actions/update-scheduled-audit.ts +57 -18
  157. package/.next/standalone/app/api/auth/status/route.ts +2 -3
  158. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +34 -140
  159. package/.next/standalone/app/audit/_components/audit-poster.tsx +10 -29
  160. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -6
  161. package/.next/standalone/app/audit/_components/empty-state.tsx +1 -4
  162. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +5 -19
  163. package/.next/standalone/app/audit/_components/share-templates.ts +44 -110
  164. package/.next/standalone/app/audit/audit-styles.css +1 -132
  165. package/.next/standalone/app/settings/page.tsx +1 -1
  166. package/.next/standalone/app/settings/settings-client.tsx +45 -50
  167. package/.next/standalone/lib/auth/api-server-client.ts +5 -33
  168. package/.next/standalone/lib/claude-sessions.ts +27 -101
  169. package/.next/standalone/lib/codex-sessions.ts +4 -20
  170. package/.next/standalone/lib/copilot-sessions.ts +1 -32
  171. package/.next/standalone/lib/cursor-sessions.ts +5 -62
  172. package/.next/standalone/lib/download-session.ts +13 -58
  173. package/.next/standalone/lib/openclaw-projects.ts +18 -54
  174. package/.next/standalone/lib/openclaw-sessions.ts +17 -75
  175. package/.next/standalone/lib/sqlite-reader.ts +1 -78
  176. package/.next/standalone/package.json +9 -9
  177. package/.next/standalone/sdk/python/CHANGELOG.md +32 -9
  178. package/.next/standalone/sdk/python/failproofai_sdk/_events.py +20 -0
  179. package/.next/standalone/sdk/python/failproofai_sdk/_redact.py +233 -0
  180. package/.next/standalone/sdk/python/failproofai_sdk/_writer.py +4 -1
  181. package/.next/standalone/sdk/python/failproofai_sdk/integrations/llama_index.py +5 -5
  182. package/.next/standalone/sdk/python/tests/integrations/test_llama_index.py +2 -2
  183. package/.next/standalone/sdk/python/tests/test_redaction.py +140 -0
  184. package/.next/standalone/sdk/python/tests/test_sdk.py +87 -0
  185. package/.next/standalone/sdk/python/tests/test_server_contract.py +60 -0
  186. package/.next/standalone/sdk/python/tests/test_site_docs.py +2 -2
  187. package/.next/standalone/server.js +1 -1
  188. package/bin/failproofai.mjs +1 -1
  189. package/dist/cli.mjs +664 -2121
  190. package/dist/worker.mjs +105 -422
  191. package/lib/auth/api-server-client.ts +5 -33
  192. package/lib/claude-sessions.ts +27 -101
  193. package/lib/codex-sessions.ts +4 -20
  194. package/lib/copilot-sessions.ts +1 -32
  195. package/lib/cursor-sessions.ts +5 -62
  196. package/lib/download-session.ts +13 -58
  197. package/lib/openclaw-projects.ts +18 -54
  198. package/lib/openclaw-sessions.ts +17 -75
  199. package/lib/sqlite-reader.ts +1 -78
  200. package/package.json +9 -9
  201. package/pi-extension/index.ts +5 -50
  202. package/src/audit/cache.ts +0 -6
  203. package/src/audit/cli-adapters/claude.ts +0 -13
  204. package/src/audit/cli-login.ts +1 -4
  205. package/src/audit/cli.ts +7 -157
  206. package/src/audit/harm-report.ts +4 -111
  207. package/src/audit/index.ts +15 -286
  208. package/src/audit/machine-store.ts +9 -8
  209. package/src/audit/redact-example.ts +15 -324
  210. package/src/audit/report-harm.ts +37 -33
  211. package/src/audit/report.ts +3 -6
  212. package/src/audit/schedule-cli.ts +33 -54
  213. package/src/audit/scoring.ts +0 -49
  214. package/src/audit/types.ts +0 -52
  215. package/src/hooks/builtin-policies.ts +2 -67
  216. package/src/hooks/configure-wizard.ts +0 -55
  217. package/src/hooks/fp-config.ts +48 -83
  218. package/src/hooks/fp-home.ts +0 -27
  219. package/src/hooks/integrations.ts +14 -51
  220. package/src/hooks/uninstall-cli.ts +2 -17
  221. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0faqz9x._.js +0 -22
  222. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zyc_nm._.js +0 -3
  223. package/.next/standalone/.next/server/chunks/[root-of-the-server]__112b4go._.js +0 -24
  224. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1l71g3y._.js +0 -22
  225. package/.next/standalone/.next/server/chunks/lib_openclaw-projects_ts_0gc-p24._.js +0 -3
  226. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n2txhk._.js +0 -3
  227. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1kaotix._.js +0 -22
  228. package/.next/standalone/.next/server/chunks/ssr/_04ng_6x._.js +0 -3
  229. package/.next/standalone/.next/server/chunks/ssr/_0l2hi_d._.js +0 -3
  230. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_rerun-button_tsx_0blihgw._.js +0 -3
  231. package/.next/standalone/.next/static/chunks/0igq884ziuv-8.js +0 -1
  232. package/.next/standalone/.next/static/chunks/349jkb79v5g6z.js +0 -1
  233. package/.next/standalone/app/actions/get-leaks.ts +0 -104
  234. package/.next/standalone/app/audit/_components/leak-section.tsx +0 -192
  235. package/.next/standalone/lib/openclaw-db.ts +0 -271
  236. package/lib/openclaw-db.ts +0 -271
  237. package/src/audit/desktop-notify.ts +0 -420
  238. package/src/audit/leak-fingerprint.ts +0 -198
  239. package/src/audit/leak-record.ts +0 -248
  240. package/src/audit/leak-scan.ts +0 -268
  241. package/src/audit/leak-store.ts +0 -220
  242. package/src/audit/macos-notifier.ts +0 -298
  243. package/src/hooks/notice.ts +0 -24
  244. /package/.next/standalone/.next/static/{DNhaAH8iPGH0tIuxee5_2 → 4_QeL7mSPYsuiSVJmBOTj}/_buildManifest.js +0 -0
  245. /package/.next/standalone/.next/static/{DNhaAH8iPGH0tIuxee5_2 → 4_QeL7mSPYsuiSVJmBOTj}/_clientMiddlewareManifest.js +0 -0
  246. /package/.next/standalone/.next/static/{DNhaAH8iPGH0tIuxee5_2 → 4_QeL7mSPYsuiSVJmBOTj}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/1c6aptmytnu6q.js","static/chunks/2yuzx8716maf0.js","static/chunks/2zafgs90r_leq.js","static/chunks/3i8rg2fv9nd6e.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;var t,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=((t=n||{})[t.Runtime=0]="Runtime",t[t.Parent=1]="Parent",t[t.Update=2]="Update",t);let o=new WeakMap;function l(e,t){this.m=e,this.e=t}let i=l.prototype,u=Object.prototype.hasOwnProperty,s="u">typeof Symbol&&Symbol.toStringTag;function c(e,t,r){u.call(e,t)||Object.defineProperty(e,t,r)}function a(e,t){let r=e[t];return r||(r=f(t),e[t]=r),r}function f(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function p(e,t,r){c(e,"__esModule",{value:!0}),s&&c(e,s,{value:"Module"});let n=0;for(;n<t.length;){let r=t[n++],o=t[n++];if("number"==typeof o)if(0===o)c(e,r,{value:t[n++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[n]?c(e,r,{get:o,set:t[n++],enumerable:!0}):c(e,r,{get:o,enumerable:!0})}r||Object.seal(e)}function h(e,t){(null!=t?a(this.c,t):this.m).exports=e}i.s=function(e,t,r){let n,o;null!=t?o=(n=a(this.c,t)).exports:(n=this.m,o=this.e),n.namespaceObject=o,p(o,e,r)},i.j=function(e,t){let r,n;null!=t?n=(r=a(this.c,t)).exports:(r=this.m,n=this.e);let l=function(e,t){let r=o.get(e);if(!r){o.set(e,r=[]);let n=e=>{if("default"!==e){for(let t of r)if(u.call(t,e))return t}};e.exports=e.namespaceObject=new Proxy(t,{get(e,t){if(u.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);let r=n(t);return r&&Reflect.get(r,t)},set:()=>!1,defineProperty:()=>!1,deleteProperty:()=>!1,has:(e,t)=>!!Reflect.has(e,t)||"default"!==t&&"__esModule"!==t&&void 0!==n(t),ownKeys(e){let t=Reflect.ownKeys(e);for(let e of r)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t},getOwnPropertyDescriptor(e,t){let r=Reflect.getOwnPropertyDescriptor(e,t);if(r||"default"===t||"__esModule"===t)return r;let o=n(t);if(o)return{enumerable:!0,configurable:!0,get:()=>Reflect.get(o,t)}}})}return r}(r,n);"object"==typeof e&&null!==e&&l.push(e)},i.v=h,i.n=function(e,t){let r;(r=null!=t?a(this.c,t):this.m).exports=r.namespaceObject=e};let d=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,m=[null,d({}),d([]),d(d)];function y(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!m.includes(t);t=d(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)),p(t,n),t}function g(e){let t=K(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=y(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function b(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}i.i=g,i.A=function(e){return this.r(e)(g.bind(this))},i.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},i.r=function(e){return K(e,this.m).exports},i.f=function(e){function t(t){if(t=b(t),u.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=b(t),u.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 O=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 w(e,t){throw Error(`Invariant: ${t(e)}`)}O.prototype=URL.prototype,i.U=O,i.z=function(e){throw Error("dynamic usage of require is not supported")},i.g=globalThis;let R=l.prototype,k="string"==typeof TURBOPACK_CHUNK_BASE_PATH?TURBOPACK_CHUNK_BASE_PATH:"/_next/",U=new Map;i.M=U;let _=new Map,v=new Map,P=new Map;async function C(e,t,r){let n;if("string"==typeof r)return function(e,t,r){return A(e,t,r)}(e,t,E(r));let o=r.included||[],l=o.map(e=>!!U.has(e)||_.get(e));if(l.length>0&&l.every(e=>e))return void await Promise.all(l);for(let l of(n=A(e,t,E(r.path)),o))_.has(l)||_.set(l,n);await n}R.l=function(e){return C(n.Parent,this.m.id,e)};let j=Promise.resolve(void 0),$=new WeakMap;function A(t,r,o){let l=e.loadChunkCached(t,o),i=$.get(l);if(void 0===i){let e=$.set.bind($,l,j);i=l.then(e).catch(e=>{let l;switch(t){case n.Runtime:l=`as a runtime dependency of chunk ${r}`;break;case n.Parent:l=`from module ${r}`;break;case n.Update:l="from an HMR update";break;default:w(t,e=>`Unknown source type: ${e}`)}let i=Error(`Failed to load chunk ${o} ${l}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw i.name="ChunkLoadError",i}),$.set(l,i)}return i}R.L=function(e){var t,r;return t=n.Parent,r=this.m.id,A(t,r,e)};R.R=function(e){let t=this.r(e);return t?.default??t},R.P=function(e){return`/ROOT/${e??""}`},R.F=function(e){return e?`file:///ROOT/${e.split("/").map(encodeURIComponent).join("/")}`:"file:///ROOT/"},R.q=function(e,t){h.call(this,`${e}${r}`,t)};let T=/[^A-Za-z0-9\-_.!~*'()/]/;function E(e,t=k){let n=T.test(e)?e.split("/").map(encodeURIComponent).join("/"):e;return`${t}${n}${r}`}function S(e,t){let r,n=e.indexOf("?");if(-1!==n)r=n;else{let t=e.indexOf("#");r=-1!==t?t:e.length}return r>=t.length&&e.startsWith(t,r-t.length)}R.b=k,R.X=r,R.h=E;function M(e){return S(e,".css")}let x={};i.c=x;let K=(e,t)=>{let r=x[e];if(r){if(r.error)throw r.error;return r}return N(e,n.Parent,t.id)};function N(e,t,r){let n=U.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:w(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=f(e),i=o.exports;x[e]=o;let u=new l(o,i);try{n(u,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&y(o.exports,o.namespaceObject),o}function B(t){let r;if(!Array.isArray(t))return e.registerChunk(void 0,t);let 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 l=e[o];for(let l=r;l<o;l++){let r=e[l],o=t.get(r);if(o){n=o;break}}let i=n??l,u=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(u||(i===l&&Object.defineProperty(l,"name",{value:"module evaluation"}),u=!0),t.set(r,i))}r=o+1}}(t,U)),e.registerChunk(n,r)}let L=new Map;function q(e){let t=L.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,retryAttempts:0,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},L.set(e,t)}return t}function I(e,t,r,n,o){!(null==n||n instanceof DOMException&&"NetworkError"===n.name)||r.retryAttempts>=1||L.get(t)!==r?(L.get(t)===r&&L.delete(t),r.reject(n)):(r.retryAttempts++,setTimeout(()=>{r.resolved||L.get(t)!==r||(o?o():(r.loadingStarted=!1,H(e,t)))},200+Math.floor(401*Math.random())))}function H(e,t){let r=q(t);if(r.loadingStarted)return r.promise;if(e===n.Runtime)return r.loadingStarted=!0,M(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(M(t));else if(S(t,".js")){self.TURBOPACK_NEXT_CHUNK_URLS.push(t);try{importScripts(t)}catch(n){I(e,t,r,n)}}else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let n=decodeURI(t);if(M(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${n}"],link[rel=stylesheet][href^="${n}?"]`).length>0)r.resolve();else{let n=()=>{let o=document.createElement("link");return o.rel="stylesheet",o.crossOrigin=null,o.href=t,o.onerror=()=>{let l=document.createComment("");o.replaceWith(l),I(e,t,r,void 0,()=>l.replaceWith(n()))},o.onload=()=>{r.resolve()},o};document.head.appendChild(n())}else if(S(t,".js")){let o=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${n}"],script[src^="${n}?"]`);if(o.length>0)for(let n of Array.from(o))n.addEventListener("error",()=>{n.remove(),I(e,t,r)},{once:!0});else{let n=document.createElement("script");n.crossOrigin=null,n.src=t,n.onerror=()=>{n.remove(),I(e,t,r)},document.head.appendChild(n)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise}e={async registerChunk(e,t){let r;if(null!=e&&(r=function(e){if("string"==typeof e)return e;let t=decodeURIComponent(e.src.replace(/[?#].*$/,""));return t.startsWith(k)?t.slice(k.length):t}(e),q("string"==typeof e?E(e):e.src).resolve()),null!=t){for(let e of t.otherChunks)q(E("string"==typeof e?e:e.path));if(await Promise.all(t.otherChunks.map(e=>{var t;return t=r,C(n.Runtime,t,e)})),t.runtimeModuleIds.length>0)for(let e of t.runtimeModuleIds)!function(e,t){let r=x[t];if(r){if(r.error)throw r.error;return}N(t,n.Runtime,e)}(r,e)}},loadChunkCached:(e,t)=>H(e,t)};var F=globalThis.TURBOPACK;globalThis.TURBOPACK={push:B},F.forEach(B)})();
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/1c6aptmytnu6q.js","static/chunks/2yuzx8716maf0.js","static/chunks/3i8rg2fv9nd6e.js","static/chunks/2zafgs90r_leq.js"],runtimeModuleIds:[94553]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;var t,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=((t=n||{})[t.Runtime=0]="Runtime",t[t.Parent=1]="Parent",t[t.Update=2]="Update",t);let o=new WeakMap;function l(e,t){this.m=e,this.e=t}let i=l.prototype,u=Object.prototype.hasOwnProperty,s="u">typeof Symbol&&Symbol.toStringTag;function c(e,t,r){u.call(e,t)||Object.defineProperty(e,t,r)}function a(e,t){let r=e[t];return r||(r=f(t),e[t]=r),r}function f(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function p(e,t,r){c(e,"__esModule",{value:!0}),s&&c(e,s,{value:"Module"});let n=0;for(;n<t.length;){let r=t[n++],o=t[n++];if("number"==typeof o)if(0===o)c(e,r,{value:t[n++],enumerable:!0,writable:!1});else throw Error(`unexpected tag: ${o}`);else"function"==typeof t[n]?c(e,r,{get:o,set:t[n++],enumerable:!0}):c(e,r,{get:o,enumerable:!0})}r||Object.seal(e)}function h(e,t){(null!=t?a(this.c,t):this.m).exports=e}i.s=function(e,t,r){let n,o;null!=t?o=(n=a(this.c,t)).exports:(n=this.m,o=this.e),n.namespaceObject=o,p(o,e,r)},i.j=function(e,t){let r,n;null!=t?n=(r=a(this.c,t)).exports:(r=this.m,n=this.e);let l=function(e,t){let r=o.get(e);if(!r){o.set(e,r=[]);let n=e=>{if("default"!==e){for(let t of r)if(u.call(t,e))return t}};e.exports=e.namespaceObject=new Proxy(t,{get(e,t){if(u.call(e,t)||"default"===t||"__esModule"===t)return Reflect.get(e,t);let r=n(t);return r&&Reflect.get(r,t)},set:()=>!1,defineProperty:()=>!1,deleteProperty:()=>!1,has:(e,t)=>!!Reflect.has(e,t)||"default"!==t&&"__esModule"!==t&&void 0!==n(t),ownKeys(e){let t=Reflect.ownKeys(e);for(let e of r)for(let r of Reflect.ownKeys(e))"default"===r||t.includes(r)||t.push(r);return t},getOwnPropertyDescriptor(e,t){let r=Reflect.getOwnPropertyDescriptor(e,t);if(r||"default"===t||"__esModule"===t)return r;let o=n(t);if(o)return{enumerable:!0,configurable:!0,get:()=>Reflect.get(o,t)}}})}return r}(r,n);"object"==typeof e&&null!==e&&l.push(e)},i.v=h,i.n=function(e,t){let r;(r=null!=t?a(this.c,t):this.m).exports=r.namespaceObject=e};let d=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,m=[null,d({}),d([]),d(d)];function y(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!m.includes(t);t=d(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)),p(t,n),t}function g(e){let t=K(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=y(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function b(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}i.i=g,i.A=function(e){return this.r(e)(g.bind(this))},i.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},i.r=function(e){return K(e,this.m).exports},i.f=function(e){function t(t){if(t=b(t),u.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=b(t),u.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 O=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 w(e,t){throw Error(`Invariant: ${t(e)}`)}O.prototype=URL.prototype,i.U=O,i.z=function(e){throw Error("dynamic usage of require is not supported")},i.g=globalThis;let R=l.prototype,k="string"==typeof TURBOPACK_CHUNK_BASE_PATH?TURBOPACK_CHUNK_BASE_PATH:"/_next/",U=new Map;i.M=U;let _=new Map,v=new Map,P=new Map;async function C(e,t,r){let n;if("string"==typeof r)return function(e,t,r){return A(e,t,r)}(e,t,E(r));let o=r.included||[],l=o.map(e=>!!U.has(e)||_.get(e));if(l.length>0&&l.every(e=>e))return void await Promise.all(l);for(let l of(n=A(e,t,E(r.path)),o))_.has(l)||_.set(l,n);await n}R.l=function(e){return C(n.Parent,this.m.id,e)};let j=Promise.resolve(void 0),$=new WeakMap;function A(t,r,o){let l=e.loadChunkCached(t,o),i=$.get(l);if(void 0===i){let e=$.set.bind($,l,j);i=l.then(e).catch(e=>{let l;switch(t){case n.Runtime:l=`as a runtime dependency of chunk ${r}`;break;case n.Parent:l=`from module ${r}`;break;case n.Update:l="from an HMR update";break;default:w(t,e=>`Unknown source type: ${e}`)}let i=Error(`Failed to load chunk ${o} ${l}${e?`: ${e}`:""}`,e?{cause:e}:void 0);throw i.name="ChunkLoadError",i}),$.set(l,i)}return i}R.L=function(e){var t,r;return t=n.Parent,r=this.m.id,A(t,r,e)};R.R=function(e){let t=this.r(e);return t?.default??t},R.P=function(e){return`/ROOT/${e??""}`},R.F=function(e){return e?`file:///ROOT/${e.split("/").map(encodeURIComponent).join("/")}`:"file:///ROOT/"},R.q=function(e,t){h.call(this,`${e}${r}`,t)};let T=/[^A-Za-z0-9\-_.!~*'()/]/;function E(e,t=k){let n=T.test(e)?e.split("/").map(encodeURIComponent).join("/"):e;return`${t}${n}${r}`}function S(e,t){let r,n=e.indexOf("?");if(-1!==n)r=n;else{let t=e.indexOf("#");r=-1!==t?t:e.length}return r>=t.length&&e.startsWith(t,r-t.length)}R.b=k,R.X=r,R.h=E;function M(e){return S(e,".css")}let x={};i.c=x;let K=(e,t)=>{let r=x[e];if(r){if(r.error)throw r.error;return r}return N(e,n.Parent,t.id)};function N(e,t,r){let n=U.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:w(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let o=f(e),i=o.exports;x[e]=o;let u=new l(o,i);try{n(u,o,i)}catch(e){throw o.error=e,e}return o.namespaceObject&&o.exports!==o.namespaceObject&&y(o.exports,o.namespaceObject),o}function B(t){let r;if(!Array.isArray(t))return e.registerChunk(void 0,t);let 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 l=e[o];for(let l=r;l<o;l++){let r=e[l],o=t.get(r);if(o){n=o;break}}let i=n??l,u=!1;for(let n=r;n<o;n++){let r=e[n];t.has(r)||(u||(i===l&&Object.defineProperty(l,"name",{value:"module evaluation"}),u=!0),t.set(r,i))}r=o+1}}(t,U)),e.registerChunk(n,r)}let L=new Map;function q(e){let t=L.get(e);if(!t){let r,n;t={resolved:!1,loadingStarted:!1,retryAttempts:0,promise:new Promise((e,t)=>{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},L.set(e,t)}return t}function I(e,t,r,n,o){!(null==n||n instanceof DOMException&&"NetworkError"===n.name)||r.retryAttempts>=1||L.get(t)!==r?(L.get(t)===r&&L.delete(t),r.reject(n)):(r.retryAttempts++,setTimeout(()=>{r.resolved||L.get(t)!==r||(o?o():(r.loadingStarted=!1,H(e,t)))},200+Math.floor(401*Math.random())))}function H(e,t){let r=q(t);if(r.loadingStarted)return r.promise;if(e===n.Runtime)return r.loadingStarted=!0,M(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(M(t));else if(S(t,".js")){self.TURBOPACK_NEXT_CHUNK_URLS.push(t);try{importScripts(t)}catch(n){I(e,t,r,n)}}else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let n=decodeURI(t);if(M(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${n}"],link[rel=stylesheet][href^="${n}?"]`).length>0)r.resolve();else{let n=()=>{let o=document.createElement("link");return o.rel="stylesheet",o.crossOrigin=null,o.href=t,o.onerror=()=>{let l=document.createComment("");o.replaceWith(l),I(e,t,r,void 0,()=>l.replaceWith(n()))},o.onload=()=>{r.resolve()},o};document.head.appendChild(n())}else if(S(t,".js")){let o=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${n}"],script[src^="${n}?"]`);if(o.length>0)for(let n of Array.from(o))n.addEventListener("error",()=>{n.remove(),I(e,t,r)},{once:!0});else{let n=document.createElement("script");n.crossOrigin=null,n.src=t,n.onerror=()=>{n.remove(),I(e,t,r)},document.head.appendChild(n)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise}e={async registerChunk(e,t){let r;if(null!=e&&(r=function(e){if("string"==typeof e)return e;let t=decodeURIComponent(e.src.replace(/[?#].*$/,""));return t.startsWith(k)?t.slice(k.length):t}(e),q("string"==typeof e?E(e):e.src).resolve()),null!=t){for(let e of t.otherChunks)q(E("string"==typeof e?e:e.path));if(await Promise.all(t.otherChunks.map(e=>{var t;return t=r,C(n.Runtime,t,e)})),t.runtimeModuleIds.length>0)for(let e of t.runtimeModuleIds)!function(e,t){let r=x[t];if(r){if(r.error)throw r.error;return}N(t,n.Runtime,e)}(r,e)}},loadChunkCached:(e,t)=>H(e,t)};var F=globalThis.TURBOPACK;globalThis.TURBOPACK={push:B},F.forEach(B)})();
@@ -18,7 +18,7 @@
18
18
  // • src/hooks/integrations.ts (buildOpenCodePluginShim production template)
19
19
  // When #337 landed, this dev shim drifted and `block-read-outside-cwd`
20
20
  // silently no-op'd on every opencode `read` call inside this repo.
21
- import { spawn } from "node:child_process";
21
+ import { spawnSync } from "node:child_process";
22
22
  import { resolveDevSpawn } from "../../scripts/dev-hook.mjs";
23
23
 
24
24
  const BUS_EVENT_MAP = {
@@ -70,58 +70,34 @@ function canonicalizeToolInput(canonicalToolName, args) {
70
70
  return out;
71
71
  }
72
72
 
73
- /**
74
- * Run failproofai for one event WITHOUT blocking opencode's event loop.
75
- *
76
- * This was `spawnSync`, and opencode loads the plugin in-process in the TUI —
77
- * so every hook froze rendering and input for the subprocess's full duration,
78
- * with a 60s ceiling. The verdicts are unchanged: every caller already `await`s
79
- * `applyDecision`, so the deny still lands before the tool runs. What changes
80
- * is that the wait is now a promise rather than a blocked thread, and the TUI
81
- * keeps painting while it happens.
82
- *
83
- * Fail-open on spawn error, and on the timeout — a policy that never ran must
84
- * not read as a deny.
85
- */
86
- async function runFailproofai(eventName, payload, directory) {
87
- const resolved = resolveDevSpawn();
88
- if (!resolved) {
73
+ function runFailproofai(eventName, payload, directory) {
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) {
89
79
  process.stderr.write(
90
80
  "[failproofai-dev] bun not found — opencode policies are NOT enforcing. " +
91
81
  "Install bun: curl -fsSL https://bun.sh/install | bash\n",
92
82
  );
93
83
  return { exitCode: 0, stdout: "", stderr: "" };
94
84
  }
95
- const cmd = resolved.cmd;
96
- const args = [...resolved.args, "--hook", eventName, "--cli", "opencode"];
97
- return await new Promise((resolveRun) => {
98
- let child;
99
- try {
100
- child = spawn(cmd, args, { cwd: directory });
101
- } catch {
102
- resolveRun({ exitCode: 0, stdout: "", stderr: "" });
103
- return;
104
- }
105
- let stdout = "";
106
- let stderr = "";
107
- let settled = false;
108
- const finish = (exitCode) => {
109
- if (settled) return;
110
- settled = true;
111
- clearTimeout(timer);
112
- resolveRun({ exitCode, stdout, stderr });
113
- };
114
- const timer = setTimeout(() => {
115
- try { child.kill("SIGKILL"); } catch { /* already gone */ }
116
- finish(0);
117
- }, 60_000);
118
- child.stdout.on("data", (d) => { stdout += d; });
119
- child.stderr.on("data", (d) => { stderr += d; });
120
- child.on("error", () => finish(0));
121
- child.on("close", (code) => finish(code ?? 0));
122
- child.stdin.on("error", () => {});
123
- child.stdin.end(JSON.stringify(payload));
85
+ const r = spawnSync(spawn.cmd, [...spawn.args, "--hook", eventName, "--cli", "opencode"], {
86
+ input: JSON.stringify(payload),
87
+ encoding: "utf8",
88
+ timeout: 60_000,
89
+ cwd: directory,
124
90
  });
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 ?? "" };
125
101
  }
126
102
 
127
103
  async function applyDecision(result, ctx, eventName) {
@@ -174,7 +150,7 @@ export default async function failproofaiPlugin({ client, directory }) {
174
150
  }
175
151
  }
176
152
  if (!prompt) prompt = (info.text || info.content || props.text || "").toString();
177
- const r = await runFailproofai("UserPromptSubmit", {
153
+ const r = runFailproofai("UserPromptSubmit", {
178
154
  session_id: sessionID, cwd: directory, hook_event_name: "UserPromptSubmit", prompt,
179
155
  }, directory);
180
156
  await applyDecision(r, { client, sessionID }, "UserPromptSubmit");
@@ -184,7 +160,7 @@ export default async function failproofaiPlugin({ client, directory }) {
184
160
  if (!claudeEvent) return;
185
161
  const props = event.properties || {};
186
162
  const sessionID = props.sessionID || (props.session && props.session.id) || props.id;
187
- const r = await runFailproofai(claudeEvent, {
163
+ const r = runFailproofai(claudeEvent, {
188
164
  session_id: sessionID, cwd: directory, hook_event_name: claudeEvent,
189
165
  }, directory);
190
166
  await applyDecision(r, { client, sessionID }, claudeEvent);
@@ -192,7 +168,7 @@ export default async function failproofaiPlugin({ client, directory }) {
192
168
 
193
169
  "tool.execute.before": async (input, output) => {
194
170
  const canonicalTool = canonicalizeTool(input.tool);
195
- const r = await runFailproofai("PreToolUse", {
171
+ const r = runFailproofai("PreToolUse", {
196
172
  session_id: input.sessionID,
197
173
  cwd: directory,
198
174
  tool_name: canonicalTool,
@@ -204,7 +180,7 @@ export default async function failproofaiPlugin({ client, directory }) {
204
180
 
205
181
  "tool.execute.after": async (input, output) => {
206
182
  const canonicalTool = canonicalizeTool(input.tool);
207
- const r = await runFailproofai("PostToolUse", {
183
+ const r = runFailproofai("PostToolUse", {
208
184
  session_id: input.sessionID,
209
185
  cwd: directory,
210
186
  tool_name: canonicalTool,
@@ -217,7 +193,7 @@ export default async function failproofaiPlugin({ client, directory }) {
217
193
 
218
194
  "permission.ask": async (input, output) => {
219
195
  const canonicalTool = canonicalizeTool(input.tool);
220
- const r = await runFailproofai("PermissionRequest", {
196
+ const r = runFailproofai("PermissionRequest", {
221
197
  session_id: input.sessionID,
222
198
  cwd: directory,
223
199
  tool_name: canonicalTool || input.command || "permission",
@@ -11,8 +11,6 @@
11
11
  * - `auto` ⟷ `config.json [audit] auto` (readConfig / updateConfig —
12
12
  * the same call `failproofai audit --schedule` makes, so
13
13
  * the two cannot diverge)
14
- * - `notify` ⟷ `config.json [audit] notify` (the same value changed by
15
- * `failproofai audit --notify` / `--no-notify`)
16
14
  * - `intervalDays` ⟷ `config.json [audit] interval_days` (readConfig owns the
17
15
  * 1..90 clamp — see fp-config.readIntervalDays)
18
16
  * - `daemon` ⟷ `systemctl status failproofaid@<user>` (daemonServiceStatus)
@@ -60,8 +58,6 @@ export interface ScheduledAuditLastScan {
60
58
  export interface ScheduledAuditView {
61
59
  /** `[audit] auto` — whether the daemon scans on a timer. */
62
60
  auto: boolean;
63
- /** `[audit] notify` — whether scheduled findings raise an OS notification. */
64
- notify: boolean;
65
61
  /** `[audit] interval_days`, already clamped to 1..90 by readConfig. */
66
62
  intervalDays: number;
67
63
  /**
@@ -104,7 +100,6 @@ export async function getScheduledAuditAction(): Promise<ScheduledAuditView> {
104
100
 
105
101
  return {
106
102
  auto: config.audit.auto,
107
- notify: config.audit.notify,
108
103
  intervalDays: config.audit.intervalDays,
109
104
  signedInAs: auth ? { id: auth.user.id, email: auth.user.email } : null,
110
105
  daemon,
@@ -8,10 +8,9 @@
8
8
  *
9
9
  * ## CLI ⟷ dashboard parity
10
10
  * - `setAutoAuditAction(enabled)` ⟷ `[audit] auto`
11
- * - `setAuditNotifyAction(enabled)` ⟷ `[audit] notify`
12
11
  * - `setAuditIntervalAction(days)` ⟷ `[audit] interval_days`
13
12
  *
14
- * All go through the same `updateConfig` the CLI uses — `failproofai audit
13
+ * Both go through the same `updateConfig` the CLI uses — `failproofai audit
15
14
  * --schedule` / `--no-schedule` call it too — so a value set on either side is
16
15
  * byte-identical. That is the whole mechanism behind "the two
17
16
  * surfaces are always in sync": there is one file, one writer function, and no
@@ -19,6 +18,7 @@
19
18
  */
20
19
 
21
20
  import { readConfig, updateConfig } from "@/src/hooks/fp-config";
21
+ import { readAuth, whoAmI } from "@/lib/auth/auth-store";
22
22
 
23
23
  /**
24
24
  * The outcome of trying to turn scheduling on.
@@ -34,34 +34,73 @@ import { readConfig, updateConfig } from "@/src/hooks/fp-config";
34
34
  * A returned discriminant survives the boundary, so the caller can open the
35
35
  * sign-in dialog for the one failure that has an obvious next step.
36
36
  */
37
- export type SetAutoAuditResult = { ok: true; auto: boolean };
37
+ export type SetAutoAuditResult =
38
+ | { ok: true; auto: boolean }
39
+ | { ok: false; reason: "signed-out" }
40
+ /**
41
+ * The session is intact locally and the api-server could not be reached.
42
+ *
43
+ * Separated from `signed-out` because `whoAmI()` collapses them: it returns
44
+ * null for a 401 AND for every transport failure, so an offline machine, a
45
+ * proxy that blocks the host, and a genuinely expired token were one answer.
46
+ * The user was told "that sign-in expired" and handed a code prompt that
47
+ * cannot succeed either — the failure it names is not the failure they have,
48
+ * and following its advice costs them a real, working session.
49
+ */
50
+ | { ok: false; reason: "unreachable" };
38
51
 
39
52
  /**
40
53
  * Turn the scheduled scan on or off.
41
54
  *
42
- * Scheduling is local and independent of authentication. A signed-in identity
43
- * adds email delivery; without one the scan and desktop notification continue.
55
+ * Turning it ON is refused without a session. Scheduling and mailing are ONE
56
+ * decision — the reason to put a scan on a timer is to be told what it found —
57
+ * so a machine with the timer set and nobody to tell is a switch that reads as
58
+ * on and produces nothing, discoverable only by noticing that no digest ever
59
+ * arrives. The caller signs the user in first and retries.
60
+ *
61
+ * `whoAmI()` asks the SERVER, so this refuses in a case the page cannot see: a
62
+ * session file that exists locally but whose refresh token the api-server has
63
+ * rejected. The local file is what the page reads to show "reports go to …", so
64
+ * the two disagree exactly when a session has expired or was minted against a
65
+ * different server — and that disagreement is the common case, not an edge one.
66
+ *
67
+ * Turning it OFF never checks. An expired session must not be able to trap
68
+ * somebody into keeping a feature they are trying to disable.
69
+ *
70
+ * Note this gates SETTING UP the timer, not the machine's ongoing work: a
71
+ * session that later expires leaves the timer running and the local scan
72
+ * working, and only the digest stops. See `report-harm.ts`.
44
73
  *
45
74
  * Returns the value actually stored (re-read), so an optimistic UI can confirm
46
75
  * against the source of truth rather than assume its own guess landed.
47
76
  */
48
77
  export async function setAutoAuditAction(enabled: boolean): Promise<SetAutoAuditResult> {
49
- const next = updateConfig({ audit: { auto: enabled } });
78
+ if (enabled) {
79
+ const who = await whoAmI();
80
+ if (!who) {
81
+ // `whoAmI()` deletes the session on a 401 and leaves it alone on a
82
+ // transport failure, so what is left ON DISK is the one thing that tells
83
+ // the two apart — no extra request, and nothing new that can fail.
84
+ const local = readAuth();
85
+ const stillWithinWindow = local && local.refresh_expires_at * 1000 > Date.now();
86
+ return { ok: false, reason: stillWithinWindow ? "unreachable" : "signed-out" };
87
+ }
88
+ }
89
+ // Enabling stamps consent in the same write, because the `whoAmI()` above is
90
+ // exactly what makes this a consent record rather than a guess: a person was
91
+ // present, signed in, and looking at the panel that enumerates what gets
92
+ // sent. `reportHarm` gates sending on the stamp, not on `auto`, so a machine
93
+ // that inherited `auto` from a release where it meant "scan locally on a
94
+ // timer" mails nothing until somebody passes through here or the CLI.
95
+ //
96
+ // Disabling leaves the stamp alone. It is a record of something that did
97
+ // happen, and it grants nothing on its own — sending needs `auto` too.
98
+ const next = updateConfig({
99
+ audit: enabled ? { auto: true, reportsConsentedAt: Date.now() } : { auto: false },
100
+ });
50
101
  return { ok: true, auto: next.audit.auto };
51
102
  }
52
103
 
53
- /**
54
- * Turn OS notifications for scheduled credential findings on or off.
55
- *
56
- * This does not change the timer or email delivery. It writes the same setting
57
- * as `failproofai audit --notify` / `--no-notify` and returns the value re-read
58
- * from the shared config so the dashboard never maintains a second truth.
59
- */
60
- export async function setAuditNotifyAction(enabled: boolean): Promise<{ notify: boolean }> {
61
- const next = updateConfig({ audit: { notify: enabled } });
62
- return { notify: next.audit.notify };
63
- }
64
-
65
104
  /**
66
105
  * Set the days between scheduled scans.
67
106
  *
@@ -7,9 +7,8 @@
7
7
  * This keeps the dashboard UI and the CLI consistent regardless of whether
8
8
  * the api-server is reachable.
9
9
  *
10
- * Reminders are gone: the machine now audits itself on a timer and can mail an
11
- * alert when it finds a credential leak, so there is nothing to nudge anyone
12
- * about. The
10
+ * Reminders are gone: the machine now audits itself on a timer and mails a
11
+ * digest when it finds harm, so there is nothing to nudge anyone about. The
13
12
  * scheduled-scan state lives in `getScheduledAuditAction`, which reads it from
14
13
  * the config and the daemon rather than from here.
15
14
  */
@@ -3,8 +3,8 @@
3
3
  /**
4
4
  * Top-level client wrapper for /audit.
5
5
  *
6
- * The old five-section personality report is SWITCHED OFF and being rebuilt
7
- * bottom-up around leak detection. What it used to compose:
6
+ * Composes the calm personality report: classify the agent into one of
7
+ * 8 archetypes, derive a score, and render the 5-section flow:
8
8
  *
9
9
  * 01 AuditPoster — single-screen shareable poster
10
10
  * 02 StrengthsSection — what it's great at
@@ -12,36 +12,23 @@
12
12
  * 04 HowToImproveSection — install / configure
13
13
  * 05 ComeBackBetterSection — spread the audit (invite)
14
14
  *
15
- * Every one of those components, and the score / persona / strengths / findings
16
- * modules behind them, is intact and still unit-tested — only the renders and
17
- * the imports here are commented out, so restoring any of it is deleting a pair
18
- * of comment markers. See the header of `src/audit/scoring.ts` for why.
19
- *
20
- * What this page renders now is `AuditReportPlaceholder`: the scan's own
21
- * numbers. The scan, the 12-CLI transcript reader and the emailed digest all
22
- * still run.
23
- *
24
15
  * Empty / running states fall back to EmptyState and RunProgress.
25
16
  */
26
17
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
27
18
  import { getAuditResultAction } from "@/app/actions/get-audit-result";
28
19
  import type { AuditResult, RunAuditOptions } from "@/src/audit/types";
29
- // import { classifyAgent } from "@/src/audit/archetypes";
30
- // Score switched off — see the header of `src/audit/scoring.ts`.
31
- // import { deriveScore, gradeFor, projectedScore } from "@/src/audit/scoring";
32
- // import { deriveStrengths } from "@/src/audit/strengths";
33
- // import { deriveFindings } from "@/src/audit/findings";
20
+ import { classifyAgent } from "@/src/audit/archetypes";
21
+ import { deriveScore, gradeFor, projectedScore } from "@/src/audit/scoring";
22
+ import { deriveStrengths } from "@/src/audit/strengths";
23
+ import { deriveFindings } from "@/src/audit/findings";
34
24
  import { usePostHog } from "@/contexts/PostHogContext";
35
25
 
36
- // The old report's five sections — switched off, not deleted. Each component
37
- // file and its tests are untouched; only this render is commented out.
38
- // import { AuditPoster } from "./audit-poster";
39
- // import { StrengthsSection } from "./strengths-section";
40
- // import { QuirksSection } from "./quirks-section";
41
- // import { HowToImproveSection } from "./how-to-improve-section";
42
- // import { ComeBackBetterSection } from "./come-back-better-section";
26
+ import { AuditPoster } from "./audit-poster";
27
+ import { StrengthsSection } from "./strengths-section";
28
+ import { QuirksSection } from "./quirks-section";
29
+ import { HowToImproveSection } from "./how-to-improve-section";
30
+ import { ComeBackBetterSection } from "./come-back-better-section";
43
31
  import { ReportFooter } from "./report-footer";
44
- import { LeakSection } from "./leak-section";
45
32
  import { EmptyState } from "./empty-state";
46
33
  import { RunProgress } from "./run-progress";
47
34
  import { AuditProgressStrip, type RerunStatus } from "./audit-progress-strip";
@@ -59,9 +46,7 @@ type Initial =
59
46
  /** Tag passed to the shared `startRerun()` handler so PostHog can tell
60
47
  * whether the click came from the bottom return-section button or the
61
48
  * empty-state CTA. */
62
- // `scan_header` is the button in section 01 — the only re-scan control the
63
- // page has now that the old report's sections are switched off.
64
- export type RerunSource = "return_section" | "empty_state" | "scan_header";
49
+ export type RerunSource = "return_section" | "empty_state";
65
50
 
66
51
  interface Props {
67
52
  initial: Initial;
@@ -74,9 +59,6 @@ interface Props {
74
59
  totalCatalogSize: number;
75
60
  }
76
61
 
77
- /* Switched off with the persona layer — this named the project that seeded the
78
- archetype classifier and the leaderboard row. Restore alongside
79
- `classifyAgent` in this file.
80
62
  function inferProjectName(result: AuditResult, override?: string): string {
81
63
  if (override && override.trim()) return override;
82
64
  // Pick the cwd that appears in the most examples — proxy for "your
@@ -99,7 +81,6 @@ function inferProjectName(result: AuditResult, override?: string): string {
99
81
  if (segs.length >= 2) return `${segs[segs.length - 2]} / ${segs[segs.length - 1]}`;
100
82
  return segs[segs.length - 1] ?? "your agent";
101
83
  }
102
- */
103
84
 
104
85
  export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Props) {
105
86
  const [cache, setCache] = useState<Initial>(initial);
@@ -298,22 +279,16 @@ function MainReport({
298
279
  onDismissRerun,
299
280
  }: MainReportProps) {
300
281
  const { capture } = usePostHog();
301
- // Only fed the persona classifier, which is switched off with it.
302
- // const project = useMemo(() => inferProjectName(result, projectFromUrl), [result, projectFromUrl]);
282
+ const project = useMemo(() => inferProjectName(result, projectFromUrl), [result, projectFromUrl]);
303
283
  // Seed classification with the project name so the behaviour fingerprint
304
284
  // (used for tie-breaks + copy variants) is stable per project.
305
- // Persona classification is switched off with the rest of the old report. Its
306
- // last live use was two telemetry properties describing a persona the product
307
- // no longer shows anyone.
308
- // const classification = useMemo(() => classifyAgent(result, project), [result, project]);
309
- // Score switched off — see the header of `src/audit/scoring.ts`. The four
310
- // functions are intact and still unit-tested; nothing calls them.
311
- // const score = useMemo(() => deriveScore(result), [result]);
312
- // const projected = useMemo(() => projectedScore(result, score), [result, score]);
313
- // const grade = gradeFor(score);
314
- // const projectedGrade = gradeFor(projected);
315
- // const strengths = useMemo(() => deriveStrengths(result), [result]);
316
- // const findings = useMemo(() => deriveFindings(result), [result]);
285
+ const classification = useMemo(() => classifyAgent(result, project), [result, project]);
286
+ const score = useMemo(() => deriveScore(result), [result]);
287
+ const projected = useMemo(() => projectedScore(result, score), [result, score]);
288
+ const grade = gradeFor(score);
289
+ const projectedGrade = gradeFor(projected);
290
+ const strengths = useMemo(() => deriveStrengths(result), [result]);
291
+ const findings = useMemo(() => deriveFindings(result), [result]);
317
292
 
318
293
  // One pass over result.results: detectors triggered + missing prescribed
319
294
  // policies. Both feed PostHog instrumentation; `missing` also feeds the
@@ -335,13 +310,10 @@ function MainReport({
335
310
  if (dashboardViewedRef.current) return;
336
311
  dashboardViewedRef.current = true;
337
312
  capture("audit_dashboard_viewed", {
338
- // Score switched off — see `src/audit/scoring.ts`. `missing` is the
339
- // prescription's denominator and is unaffected, so the copy→install
340
- // funnel keeps both of its ends.
341
- // score,
342
- // grade,
343
- // archetype: classification.archetype,
344
- // secondary: classification.secondary ?? null,
313
+ score,
314
+ grade,
315
+ archetype: classification.archetype,
316
+ secondary: classification.secondary ?? null,
345
317
  missing,
346
318
  transcripts_scanned: result.transcripts.scanned,
347
319
  results_count: result.results.length,
@@ -349,6 +321,10 @@ function MainReport({
349
321
  });
350
322
  }, [
351
323
  capture,
324
+ score,
325
+ grade,
326
+ classification.archetype,
327
+ classification.secondary,
352
328
  missing,
353
329
  result.transcripts.scanned,
354
330
  result.results.length,
@@ -356,43 +332,19 @@ function MainReport({
356
332
  ]);
357
333
 
358
334
  /** Poster ref — captured to PNG by the poster's share buttons. */
359
- // const posterRef = useRef<HTMLDivElement>(null);
335
+ const posterRef = useRef<HTMLDivElement>(null);
360
336
 
361
337
  return (
362
338
  <div className="app">
363
339
  <AuditProgressStrip status={rerunStatus} onDismiss={onDismissRerun} />
364
340
  <div className="app-shell">
365
341
  <div className="report">
366
- <AuditReportPlaceholder
367
- transcripts={result.transcripts.scanned}
368
- events={result.eventsScanned ?? 0}
369
- projects={result.projectsScanned?.length ?? 0}
370
- isRunning={isRunning || rerunStatus.kind === "running"}
371
- onRerun={() => onRerun("scan_header")}
372
- />
373
- {/* The rebuilt report. It reads the leak record rather than this
374
- scan's result, deliberately: a credential found last month and
375
- not touched by today's transcripts is still a credential to
376
- rotate, and a report that showed only the current scan's findings
377
- would go quiet on exactly those. */}
378
- <LeakSection />
379
- {/* The whole old report is switched off — the persona poster, the
380
- strengths and quirks sections, the punch-list with its install-all
381
- funnel, and the invite section. It is being rebuilt bottom-up
382
- around leak detection; see the header of `src/audit/scoring.ts`
383
- for the reasoning and `~/Desktop/failproofai-leak-detection-
384
- verdict-2026-09-07.md` for the measurements behind it.
385
-
386
- Every component below is intact and still unit-tested — only the
387
- render is commented — so restoring any one of them is deleting a
388
- pair of comment markers.
389
-
390
342
  <AuditPoster
391
343
  ref={posterRef}
392
344
  archetypeKey={classification.archetype}
393
345
  seed={classification.variantSeed}
394
- // score={score}
395
- // grade={grade}
346
+ score={score}
347
+ grade={grade}
396
348
  missing={missing}
397
349
  auditedAt={cachedAt ?? new Date().toISOString()}
398
350
  />
@@ -400,11 +352,10 @@ function MainReport({
400
352
  <QuirksSection findings={findings} />
401
353
  <HowToImproveSection
402
354
  result={result}
403
- // projected={projected}
404
- // projectedGrade={projectedGrade}
355
+ projected={projected}
356
+ projectedGrade={projectedGrade}
405
357
  />
406
- <ComeBackBetterSection />
407
- */}
358
+ <ComeBackBetterSection score={score} />
408
359
  </div>
409
360
  <ReportFooter cachedAt={cachedAt} />
410
361
  </div>
@@ -412,63 +363,6 @@ function MainReport({
412
363
  );
413
364
  }
414
365
 
415
- /**
416
- * What `/audit` shows while the report is being rebuilt.
417
- *
418
- * Deliberately states the scan's own numbers rather than nothing at all: the
419
- * scan still runs, still walks every transcript across all 12 CLIs, and still
420
- * feeds the emailed digest. Saying so is the difference between "this page is
421
- * under construction" and "this product is broken".
422
- */
423
- function AuditReportPlaceholder(
424
- {
425
- transcripts,
426
- events,
427
- projects,
428
- isRunning,
429
- onRerun,
430
- }: {
431
- transcripts: number;
432
- events: number;
433
- projects: number;
434
- isRunning: boolean;
435
- onRerun: () => void;
436
- },
437
- ) {
438
- const n = (x: number) => x.toLocaleString();
439
- return (
440
- <section className="audit-sec" data-screen-label="01 Scan">
441
- <div className="audit-sec-head">
442
- <span className="audit-sec-eyebrow">
443
- <span className="ix">01</span>{"// scan"}
444
- </span>
445
- {/* The re-scan control. It lived in the old report's sections and went
446
- dormant when they were commented out, which left the page with no way
447
- to run an audit again at all — you had to go back to the terminal. */}
448
- <button
449
- type="button"
450
- className="scan-rerun"
451
- onClick={onRerun}
452
- disabled={isRunning}
453
- >
454
- {isRunning ? "scanning…" : "run again"}
455
- </button>
456
- </div>
457
- <h2 className="audit-sec-title">scan complete</h2>
458
- <div className="audit-sec-sub">
459
- {n(events)} tool call{events === 1 ? "" : "s"} across {n(transcripts)}{" "}
460
- transcript{transcripts === 1 ? "" : "s"}
461
- {projects > 0 ? ` · ${n(projects)} project${projects === 1 ? "" : "s"}` : ""}
462
- </div>
463
- <div className="audit-sec-sub">
464
- {"// the report is being rebuilt around leak detection. the scan, the"}
465
- <br />
466
- {"// 12-CLI transcript reader and the emailed digest are unaffected."}
467
- </div>
468
- </section>
469
- );
470
- }
471
-
472
366
  interface ShellEmptyProps {
473
367
  running: boolean;
474
368
  mode?: "no-cache" | "zero-sessions";