failproofai 0.0.11-beta.7 → 0.0.11-beta.9

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 (233) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
  3. package/.next/standalone/.next/build-manifest.json +6 -6
  4. package/.next/standalone/.next/prerender-manifest.json +3 -3
  5. package/.next/standalone/.next/required-server-files.json +1 -1
  6. package/.next/standalone/.next/routes-manifest.json +6 -0
  7. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
  8. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  10. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  13. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  14. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  15. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  16. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  17. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
  19. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  20. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  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/app-paths-manifest.json +3 -0
  32. package/.next/standalone/.next/server/app/api/audit/invite/route/build-manifest.json +9 -0
  33. package/.next/standalone/.next/server/app/api/audit/invite/route/server-reference-manifest.json +4 -0
  34. package/.next/standalone/.next/server/app/api/audit/invite/route.js +7 -0
  35. package/.next/standalone/.next/server/app/api/audit/invite/route.js.map +5 -0
  36. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -0
  37. package/.next/standalone/.next/server/app/api/audit/invite/route_client-reference-manifest.js +3 -0
  38. package/.next/standalone/.next/server/app/api/audit/run/route.js +1 -1
  39. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/auth/login-request/route.js +1 -1
  41. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  42. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +2 -2
  43. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/api/auth/logout/route.js +2 -2
  45. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/api/auth/reminder/route.js +2 -2
  47. package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/api/auth/status/route.js +2 -2
  49. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  50. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
  52. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
  53. package/.next/standalone/.next/server/app/audit/page.js +2 -2
  54. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  55. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  56. package/.next/standalone/.next/server/app/index.html +1 -1
  57. package/.next/standalone/.next/server/app/index.rsc +15 -15
  58. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  59. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
  60. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  61. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
  62. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  63. package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
  64. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  65. package/.next/standalone/.next/server/app/page.js +2 -2
  66. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  67. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  68. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
  69. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  70. package/.next/standalone/.next/server/app/policies/page.js +2 -2
  71. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  72. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  73. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +3 -3
  74. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  75. package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
  76. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  78. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +3 -3
  79. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  80. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  81. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +3 -3
  82. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  83. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  84. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +3 -3
  85. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  86. package/.next/standalone/.next/server/app/projects/page.js +3 -3
  87. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  88. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  89. package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
  90. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1_mqemn._.js +1 -1
  91. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1r1h8v9._.js +3 -0
  92. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +1 -1
  93. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1uatkiv._.js +3 -0
  94. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1y6gxxb._.js +3 -0
  95. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_invite_route_actions_0-2n5sy.js +3 -0
  96. package/.next/standalone/.next/server/chunks/node_modules_0-tu4ot._.js +3 -0
  97. package/.next/standalone/.next/server/chunks/node_modules_0ttxbz7._.js +3 -0
  98. package/.next/standalone/.next/server/chunks/node_modules_1bnh1y0._.js +3 -0
  99. package/.next/standalone/.next/server/chunks/node_modules_1epycqa._.js +3 -0
  100. package/.next/standalone/.next/server/chunks/node_modules_1wpdcgo._.js +3 -0
  101. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +8 -8
  102. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
  103. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0808sha._.js +4 -0
  106. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1cd25c7._.js → [root-of-the-server]__0e4-6d8._.js} +3 -3
  107. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__08gyb62._.js → [root-of-the-server]__0e446gb._.js} +2 -2
  108. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehe24g._.js +4 -0
  109. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1-scthx._.js → [root-of-the-server]__0f62vu9._.js} +2 -2
  110. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g253ve._.js +4 -0
  111. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0l13qf2._.js → [root-of-the-server]__0k65l27._.js} +2 -2
  112. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0vxf0_g._.js +4 -0
  113. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__08v7sn2._.js → [root-of-the-server]__0wprfyc._.js} +2 -2
  114. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12mcauo._.js +4 -0
  115. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0989_dx._.js → [root-of-the-server]__1e-x7j4._.js} +2 -2
  116. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mt35_w._.js +1 -1
  117. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pcxxwg._.js +2 -2
  118. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1uvfwgr._.js +4 -0
  119. package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/_0il3fl1._.js +3 -0
  121. package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
  122. package/.next/standalone/.next/server/chunks/ssr/_1kje4fm._.js +1 -1
  123. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +21 -21
  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 +2 -2
  126. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0y4a-0q.js +3 -0
  127. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +3 -0
  128. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
  129. package/.next/standalone/.next/server/functions-config-manifest.json +0 -3
  130. package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
  131. package/.next/standalone/.next/server/pages/404.html +1 -1
  132. package/.next/standalone/.next/server/pages/500.html +1 -1
  133. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  134. package/.next/standalone/.next/server/server-reference-manifest.json +10 -10
  135. package/.next/standalone/.next/static/chunks/{0hmxjseydp6as.js → 07_d165p5h5ys.js} +1 -1
  136. package/.next/standalone/.next/static/chunks/0f7d7hnbh4djs.js +1 -0
  137. package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +1 -0
  138. package/.next/standalone/.next/static/chunks/168k-8z6k7e8z.css +1 -0
  139. package/.next/standalone/.next/static/chunks/{3n28elq6kwpy3.js → 1kvadxkgnapyj.js} +1 -1
  140. package/.next/standalone/.next/static/chunks/{0fpw1jzeg66_x.js → 277oc363p56n6.js} +2 -2
  141. package/.next/standalone/.next/static/chunks/28mkxkl_d91-l.js +1 -0
  142. package/.next/standalone/.next/static/chunks/28x7jvo3kxd3u.js +41 -0
  143. package/.next/standalone/.next/static/chunks/29nrs5xs9c4hx.css +2 -0
  144. package/.next/standalone/.next/static/chunks/{41vwoxpkauj1w.js → 29tg7deqmq32l.js} +1 -1
  145. package/.next/standalone/.next/static/chunks/{3w8d8k_dca5rp.js → 2h0dkzyy0vocp.js} +1 -1
  146. package/.next/standalone/.next/static/chunks/{1eq7f419t6ln3.js → 2z42u62k-8-_q.js} +1 -1
  147. package/.next/standalone/.next/static/chunks/{0avgb78edu0i-.js → 3nj6g3xu9uy78.js} +1 -1
  148. package/.next/standalone/.next/static/chunks/{0xkxbaa-oo180.js → 3ty6dhcuogout.js} +1 -1
  149. package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +1 -0
  150. package/.next/standalone/.next/static/chunks/{turbopack-00qy7zfa7m--m.js → turbopack-3lrm4f20fz89b.js} +1 -1
  151. package/.next/standalone/app/api/audit/_state.ts +40 -33
  152. package/.next/standalone/app/api/audit/invite/route.ts +183 -0
  153. package/.next/standalone/app/api/audit/run/route.ts +30 -16
  154. package/.next/standalone/app/api/audit/status/route.ts +1 -0
  155. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +33 -65
  156. package/.next/standalone/app/audit/_components/audit-poster.tsx +322 -0
  157. package/.next/standalone/app/audit/_components/audit-progress-strip.tsx +1 -1
  158. package/.next/standalone/app/audit/_components/auth-dialog.tsx +21 -49
  159. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +316 -0
  160. package/.next/standalone/app/audit/_components/empty-state.tsx +8 -2
  161. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +187 -0
  162. package/.next/standalone/app/audit/_components/invite-dialog.tsx +227 -0
  163. package/.next/standalone/app/audit/_components/quirks-section.tsx +75 -0
  164. package/.next/standalone/app/audit/_components/rerun-button.tsx +43 -14
  165. package/.next/standalone/app/audit/_components/run-progress.tsx +2 -2
  166. package/.next/standalone/app/audit/_components/share-templates.ts +23 -22
  167. package/.next/standalone/app/audit/_components/sigil.tsx +9 -66
  168. package/.next/standalone/app/audit/_components/strengths-section.tsx +20 -32
  169. package/.next/standalone/app/audit/audit-styles.css +781 -1784
  170. package/.next/standalone/app/components/sessions-list.tsx +77 -80
  171. package/.next/standalone/app/globals.css +214 -32
  172. package/.next/standalone/app/layout.tsx +1 -10
  173. package/.next/standalone/app/policies/hooks-client.tsx +12 -4
  174. package/.next/standalone/app/project/[name]/page.tsx +23 -79
  175. package/.next/standalone/app/projects/page.tsx +14 -23
  176. package/.next/standalone/assets/audit/poster-styles.css +1 -1
  177. package/.next/standalone/assets/audit/styles.css +11 -11
  178. package/.next/standalone/components/navbar.tsx +2 -37
  179. package/.next/standalone/lib/auth/api-server-client.ts +25 -0
  180. package/.next/standalone/node_modules/@next/env/package.json +2 -2
  181. package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
  182. package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +1 -1
  183. package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
  184. package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
  185. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
  186. package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
  187. package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
  188. package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
  189. package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
  190. package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
  191. package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
  192. package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
  193. package/.next/standalone/node_modules/next/package.json +15 -15
  194. package/.next/standalone/package.json +18 -15
  195. package/.next/standalone/server.js +1 -1
  196. package/dist/cli.mjs +2 -2
  197. package/lib/auth/api-server-client.ts +25 -0
  198. package/package.json +18 -15
  199. package/src/audit/dashboard-cache.ts +13 -6
  200. package/src/audit/social-proof.ts +34 -0
  201. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07tgnzi._.js +0 -3
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oeun7z._.js +0 -3
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__12pit4m._.js +0 -3
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13ra2jq._.js +0 -3
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1b9z5-i._.js +0 -3
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ixjiy8._.js +0 -3
  207. package/.next/standalone/.next/server/chunks/_1-1804f._.js +0 -3
  208. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00jkjmt._.js +0 -4
  209. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013du6r._.js +0 -4
  210. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e85wxv._.js +0 -4
  211. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0gfxvb1._.js +0 -3
  212. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1hlrq6y._.js +0 -4
  213. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ihxdo5._.js +0 -4
  214. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vvfde2._.js +0 -4
  215. package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_0q4m0_h.js +0 -3
  216. package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_1n-0xws.js +0 -3
  217. package/.next/standalone/.next/static/chunks/09ueq8s1as8xs.css +0 -2
  218. package/.next/standalone/.next/static/chunks/0qassxjx1ef04.js +0 -1
  219. package/.next/standalone/.next/static/chunks/2452blhu4bcdr.js +0 -41
  220. package/.next/standalone/.next/static/chunks/2so39wg7mjbi7.js +0 -1
  221. package/.next/standalone/.next/static/chunks/3gti1qdk5epqn.js +0 -1
  222. package/.next/standalone/.next/static/chunks/3osmt-t2hsrng.js +0 -1
  223. package/.next/standalone/.next/static/chunks/3wycox197ouus.css +0 -1
  224. package/.next/standalone/app/audit/_components/findings-section.tsx +0 -135
  225. package/.next/standalone/app/audit/_components/identity-section.tsx +0 -126
  226. package/.next/standalone/app/audit/_components/policies-section.tsx +0 -194
  227. package/.next/standalone/app/audit/_components/return-section.tsx +0 -416
  228. package/.next/standalone/app/audit/_components/score-section.tsx +0 -179
  229. package/.next/standalone/app/audit/_components/share-dock.tsx +0 -265
  230. package/.next/standalone/app/audit/_components/show-off-cta.tsx +0 -135
  231. /package/.next/standalone/.next/static/{90NFQus9VOnEzD6sP0EyP → NYPiJP6Rv_exQdSFVS8HP}/_buildManifest.js +0 -0
  232. /package/.next/standalone/.next/static/{90NFQus9VOnEzD6sP0EyP → NYPiJP6Rv_exQdSFVS8HP}/_clientMiddlewareManifest.js +0 -0
  233. /package/.next/standalone/.next/static/{90NFQus9VOnEzD6sP0EyP → NYPiJP6Rv_exQdSFVS8HP}/_ssgManifest.js +0 -0
@@ -3,30 +3,31 @@
3
3
  /**
4
4
  * Top-level client wrapper for /audit.
5
5
  *
6
- * Composes the personality report: classify the agent into one of 8
7
- * archetypes, derive a score + tier, render the IdentitySection +
8
- * ShowOff + Strengths + Score (with leaderboard) + Findings + Policies
9
- * + Return-loop CTA.
6
+ * Composes the calm personality report: classify the agent into one of
7
+ * 8 archetypes, derive a score, and render the 5-section flow:
10
8
  *
11
- * Empty / running states fall back to the existing EmptyState and
12
- * RunProgress components.
9
+ * 01 AuditPoster single-screen shareable poster
10
+ * 02 StrengthsSection — what it's great at
11
+ * 03 QuirksSection — what slipped through
12
+ * 04 HowToImproveSection — install / configure
13
+ * 05 ComeBackBetterSection — reminder + perks
14
+ *
15
+ * Empty / running states fall back to EmptyState and RunProgress.
13
16
  */
14
17
  import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
15
18
  import { getAuditResultAction } from "@/app/actions/get-audit-result";
16
19
  import type { AuditResult, RunAuditOptions } from "@/src/audit/types";
17
20
  import { classifyAgent } from "@/src/audit/archetypes";
18
- import { COHORT_SIZE, deriveScore, gradeFor, projectedScore, type Grade } from "@/src/audit/scoring";
21
+ import { deriveScore, gradeFor, projectedScore } from "@/src/audit/scoring";
19
22
  import { deriveStrengths } from "@/src/audit/strengths";
20
23
  import { deriveFindings } from "@/src/audit/findings";
21
24
  import { usePostHog } from "@/contexts/PostHogContext";
22
25
 
23
- import { IdentitySection } from "./identity-section";
24
- import { ShareDock } from "./share-dock";
26
+ import { AuditPoster } from "./audit-poster";
25
27
  import { StrengthsSection } from "./strengths-section";
26
- import { ScoreSection } from "./score-section";
27
- import { FindingsSection } from "./findings-section";
28
- import { PoliciesSection } from "./policies-section";
29
- import { ReturnSection } from "./return-section";
28
+ import { QuirksSection } from "./quirks-section";
29
+ import { HowToImproveSection } from "./how-to-improve-section";
30
+ import { ComeBackBetterSection } from "./come-back-better-section";
30
31
  import { ReportFooter } from "./report-footer";
31
32
  import { EmptyState } from "./empty-state";
32
33
  import { RunProgress } from "./run-progress";
@@ -58,11 +59,6 @@ interface Props {
58
59
  totalCatalogSize: number;
59
60
  }
60
61
 
61
- function inferWindow(params: RunAuditOptions | undefined): string {
62
- if (!params?.since) return "all time";
63
- return params.since;
64
- }
65
-
66
62
  function inferProjectName(result: AuditResult, override?: string): string {
67
63
  if (override && override.trim()) return override;
68
64
  // Pick the cwd that appears in the most examples — proxy for "your
@@ -106,7 +102,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
106
102
  * soft-refreshes the dashboard cache on success — no full page reload. */
107
103
  const startRerun = useCallback(async (source: RerunSource) => {
108
104
  if (running) return;
109
- capture("audit_rerun_clicked", { source, since: "30d" });
105
+ capture("audit_rerun_clicked", { source, since: "all" });
110
106
  setRunning(true);
111
107
  setRerunStatus({ kind: "running", startedAt: Date.now() });
112
108
  try {
@@ -116,7 +112,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
116
112
  // success; the prior cache survives a failed run so the report doesn't vanish.
117
113
  // The empty-state first-run (empty-state.tsx) deliberately stays on the
118
114
  // fast cached path — it's a first scan, not a re-audit.
119
- await triggerRun({ cli: [], since: "30d", noCache: true });
115
+ await triggerRun({ cli: [], since: "all", noCache: true });
120
116
  await refreshFromCache();
121
117
  setRerunStatus({ kind: "idle" });
122
118
  } catch (err) {
@@ -124,7 +120,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
124
120
  capture("audit_rerun_failed", {
125
121
  kind,
126
122
  source,
127
- since: "30d",
123
+ since: "all",
128
124
  cli_filter: "all",
129
125
  });
130
126
  setRerunStatus({ kind: "failed", reason: kind, failedAt: Date.now() });
@@ -249,9 +245,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
249
245
  <MainReport
250
246
  result={result}
251
247
  cachedAt={cachedAt}
252
- params={params}
253
248
  projectFromUrl={projectFromUrl}
254
- totalCatalogSize={totalCatalogSize}
255
249
  isRunning={running}
256
250
  rerunStatus={rerunStatus}
257
251
  onRerun={(source) => startRerun(source)}
@@ -263,9 +257,7 @@ export function AuditDashboard({ initial, projectFromUrl, totalCatalogSize }: Pr
263
257
  interface MainReportProps {
264
258
  result: AuditResult;
265
259
  cachedAt: string | null;
266
- params: RunAuditOptions | undefined;
267
260
  projectFromUrl?: string;
268
- totalCatalogSize: number;
269
261
  isRunning: boolean;
270
262
  rerunStatus: RerunStatus;
271
263
  onRerun: (source: RerunSource) => void;
@@ -275,9 +267,7 @@ interface MainReportProps {
275
267
  function MainReport({
276
268
  result,
277
269
  cachedAt,
278
- params,
279
270
  projectFromUrl,
280
- totalCatalogSize,
281
271
  isRunning,
282
272
  rerunStatus,
283
273
  onRerun,
@@ -294,14 +284,10 @@ function MainReport({
294
284
  const projectedGrade = gradeFor(projected);
295
285
  const strengths = useMemo(() => deriveStrengths(result), [result]);
296
286
  const findings = useMemo(() => deriveFindings(result), [result]);
297
- // Renamed from `window` to avoid shadowing the browser global — any
298
- // future `window.*` reference added inside MainReport would silently
299
- // bind to a string and crash at runtime.
300
- const scopeWindow = inferWindow(params);
301
287
 
302
- // One pass over result.results derives both counts; score-section and
303
- // return-section also need `missing` but they take it from us via props
304
- // / `result` shape, so deduplicate the scan here.
288
+ // One pass over result.results: detectors triggered + missing prescribed
289
+ // policies. Both feed PostHog instrumentation; `missing` also feeds the
290
+ // poster's share-text template.
305
291
  const { detectorsTriggered, missing } = useMemo(() => {
306
292
  let detectorsTriggered = 0;
307
293
  let missing = 0;
@@ -340,54 +326,37 @@ function MainReport({
340
326
  detectorsTriggered,
341
327
  ]);
342
328
 
343
- /** Identity hero ref — captured to PNG by the share buttons. */
344
- const identityFrameRef = useRef<HTMLDivElement>(null);
329
+ /** Poster ref — captured to PNG by the poster's share buttons. */
330
+ const posterRef = useRef<HTMLDivElement>(null);
345
331
 
346
332
  return (
347
333
  <div className="app">
348
334
  <AuditProgressStrip status={rerunStatus} onDismiss={onDismissRerun} />
349
- <div className="scanline-overlay" />
350
335
  <div className="app-shell">
351
336
  <div className="report">
352
- <IdentitySection
353
- ref={identityFrameRef}
337
+ <AuditPoster
338
+ ref={posterRef}
354
339
  archetypeKey={classification.archetype}
355
- secondaryKey={classification.secondary}
356
- toolCalls={result.eventsScanned ?? 0}
357
- sessions={result.transcripts.scanned}
358
- window={scopeWindow}
359
340
  seed={classification.variantSeed}
360
- />
361
- <StrengthsSection
362
- strengths={strengths}
363
- totalDetectorsTriggered={detectorsTriggered}
364
- totalDetectorsAvailable={totalCatalogSize}
365
- />
366
- <ScoreSection
367
- result={result}
368
341
  score={score}
369
342
  grade={grade}
370
- archetypeKey={classification.archetype}
371
- project={project}
343
+ missing={missing}
344
+ auditedAt={cachedAt ?? new Date().toISOString()}
372
345
  />
373
- <ReturnSection
346
+ <StrengthsSection strengths={strengths} />
347
+ <QuirksSection findings={findings} />
348
+ <HowToImproveSection
374
349
  result={result}
350
+ projected={projected}
351
+ projectedGrade={projectedGrade}
352
+ />
353
+ <ComeBackBetterSection
375
354
  isRunning={isRunning}
376
355
  onRerun={() => onRerun("return_section")}
377
356
  />
378
- <FindingsSection findings={findings} />
379
- <PoliciesSection result={result} projected={projected} projectedGrade={projectedGrade} />
380
357
  </div>
381
358
  <ReportFooter cachedAt={cachedAt} />
382
359
  </div>
383
- <ShareDock
384
- frameRef={identityFrameRef}
385
- archetypeKey={classification.archetype}
386
- seed={classification.variantSeed}
387
- score={score}
388
- grade={grade}
389
- missing={missing}
390
- />
391
360
  </div>
392
361
  );
393
362
  }
@@ -408,7 +377,6 @@ function ShellEmpty({ running, mode = "no-cache", rerunStatus, onDismissRerun, o
408
377
  return (
409
378
  <div className="app">
410
379
  <AuditProgressStrip status={rerunStatus} onDismiss={onDismissRerun} />
411
- <div className="scanline-overlay" />
412
380
  <div className="app-shell">
413
381
  <div className="report">
414
382
  {running ? (
@@ -0,0 +1,322 @@
1
+ "use client";
2
+
3
+ /**
4
+ * Section 01 — AUDIT POSTER. The single-screen shareable above-the-fold
5
+ * artifact. Replaces the old IdentitySection + ScoreSection + ShareDock
6
+ * triumvirate.
7
+ *
8
+ * Layout (inside the PNG capture region):
9
+ *
10
+ * ┌─────────────────────────────────────────────────────────────┐
11
+ * │ ▣ failproof_ai · audit № 01 of 08 · audited <date> │
12
+ * ├─────────────────────────────────────────────────────────────┤
13
+ * │ │
14
+ * │ <score>/100 the optimist ▓░▓░▓░▓░ │
15
+ * │ <rank> pace · conviction · forgetful ░▓░▓░▓░▓ │
16
+ * │ // only N% of agents are this archetype │
17
+ * │ │
18
+ * ├─────────────────────────────────────────────────────────────┤
19
+ * │ audit yours → failproof.ai │
20
+ * └─────────────────────────────────────────────────────────────┘
21
+ *
22
+ * Outside the capture region: three share buttons + scroll hint.
23
+ */
24
+ import React, { forwardRef, useMemo, useState } from "react";
25
+ import { pickArchetypeVariant, type ArchetypeKey } from "@/src/audit/archetypes";
26
+ import { type Grade } from "@/src/audit/scoring";
27
+ import { getArchetypeRarityPct, getScoreRank } from "@/src/audit/social-proof";
28
+ import { copyOrDownloadCard, downloadCard, shareCardNative, shareCardToastMessage } from "@/lib/share-card";
29
+ import { toast } from "@/app/components/toast";
30
+ import { usePostHog } from "@/contexts/PostHogContext";
31
+ import { Sigil } from "./sigil";
32
+ import { X_TEMPLATES, LI_TEMPLATES, pickTemplate, type ShareCtx } from "./share-templates";
33
+
34
+ const SITE_URL = "https://befailproof.ai";
35
+ const X_INTENT = (text: string) =>
36
+ `https://x.com/intent/tweet?text=${encodeURIComponent(text)}`;
37
+ const LI_INTENT = (text: string) =>
38
+ `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(SITE_URL)}&summary=${encodeURIComponent(text)}`;
39
+
40
+ interface Props {
41
+ archetypeKey: ArchetypeKey;
42
+ /** Stable seed for variant selection (project name is the natural fit). */
43
+ seed: string;
44
+ score: number;
45
+ grade: Grade;
46
+ /** Count of unenabled prescribed policies — passed to the share-text
47
+ * templates, not rendered on the poster itself. */
48
+ missing: number;
49
+ /** Audit timestamp (ISO string from cache). Rendered as ISO date in the
50
+ * top-right meta. UTC to keep the poster timezone-stable across shares. */
51
+ auditedAt: string;
52
+ }
53
+
54
+ export const AuditPoster = forwardRef<HTMLDivElement, Props>(function AuditPoster(
55
+ { archetypeKey, seed, score, grade, missing, auditedAt }: Props,
56
+ posterRef,
57
+ ) {
58
+ const archetype = useMemo(
59
+ () => pickArchetypeVariant(archetypeKey, seed),
60
+ [archetypeKey, seed],
61
+ );
62
+ const rarityPct = getArchetypeRarityPct(archetypeKey);
63
+ const scoreRank = getScoreRank(score);
64
+ const indexLabel = String(archetype.index).padStart(2, "0");
65
+ const auditedDate = useMemo(() => formatAuditedDate(auditedAt), [auditedAt]);
66
+
67
+ const { capture } = usePostHog();
68
+ const [busy, setBusy] = useState<null | "x" | "linkedin" | "download">(null);
69
+
70
+ const captureCardBlob = async (): Promise<Blob | null> => {
71
+ const node = (posterRef as React.MutableRefObject<HTMLDivElement | null>)?.current;
72
+ if (!node) return null;
73
+ // Capture via html-to-image instead of html2canvas. The former
74
+ // serializes the DOM into an SVG <foreignObject> and rasterizes
75
+ // it through the browser's native rendering engine — so dashed
76
+ // borders, the SVG logo, gradients, and font metrics render
77
+ // exactly as they do on screen. html2canvas reimplements CSS
78
+ // in JS and was producing broken dashes and a stray pink square
79
+ // on the logo's mask.
80
+ if (typeof document !== "undefined" && document.fonts?.ready) await document.fonts.ready;
81
+ await new Promise<void>((r) => requestAnimationFrame(() => r()));
82
+ // Clone the poster into an off-screen container with a fixed width
83
+ // so html-to-image captures a self-contained subtree. The live
84
+ // .poster sits inside a flex column (.poster-section's flex: 1)
85
+ // and uses margin: 0 auto for centering — capturing it directly
86
+ // inherits that parent context, which shifts content within an
87
+ // oversized canvas. The clone has no such context.
88
+ const liveRect = node.getBoundingClientRect();
89
+ const captureWidth = Math.round(liveRect.width);
90
+ const captureHeight = Math.round(liveRect.height);
91
+
92
+ const wrapper = document.createElement("div");
93
+ wrapper.style.cssText = [
94
+ "position: fixed",
95
+ "left: -10000px",
96
+ "top: 0",
97
+ `width: ${captureWidth}px`,
98
+ `height: ${captureHeight}px`,
99
+ "padding: 0",
100
+ "margin: 0",
101
+ "background: var(--bg)",
102
+ "z-index: -1",
103
+ "pointer-events: none",
104
+ ].join(";");
105
+
106
+ const clone = node.cloneNode(true) as HTMLElement;
107
+ clone.style.cssText += [
108
+ "",
109
+ `width: ${captureWidth}px`,
110
+ `height: ${captureHeight}px`,
111
+ "max-width: none",
112
+ "min-width: 0",
113
+ "flex: 0 0 auto",
114
+ "margin: 0",
115
+ ].join(";");
116
+
117
+ wrapper.appendChild(clone);
118
+ document.body.appendChild(wrapper);
119
+
120
+ try {
121
+ const { toBlob } = await import("html-to-image");
122
+ return await toBlob(clone, {
123
+ backgroundColor: "#0e0e11",
124
+ pixelRatio: 2,
125
+ cacheBust: true,
126
+ width: captureWidth,
127
+ height: captureHeight,
128
+ });
129
+ } finally {
130
+ wrapper.remove();
131
+ }
132
+ };
133
+
134
+ const filenameFor = (channel: "x" | "linkedin" | "download") =>
135
+ `failproofai-${channel}-${grade.toLowerCase()}-${score}.png`;
136
+
137
+ const handleShare = async (channel: "x" | "linkedin" | "download") => {
138
+ if (busy) return;
139
+ setBusy(channel);
140
+ capture("audit_card_share_clicked", {
141
+ channel,
142
+ source: "poster",
143
+ score,
144
+ grade,
145
+ missing_policies: missing,
146
+ });
147
+ try {
148
+ const blob = await captureCardBlob().catch(() => null);
149
+ if (!blob) {
150
+ capture("audit_card_capture_completed", {
151
+ trigger: channel === "download" ? "download" : `share_${channel}`,
152
+ status: "error",
153
+ image_method: "failed",
154
+ source: "poster",
155
+ });
156
+ toast(shareCardToastMessage("failed"));
157
+ return;
158
+ }
159
+
160
+ if (channel === "download") {
161
+ const ok = downloadCard(blob, filenameFor(channel));
162
+ const method = ok ? "download" : "failed";
163
+ capture("audit_card_capture_completed", {
164
+ trigger: "download",
165
+ status: ok ? "success" : "error",
166
+ image_method: method,
167
+ source: "poster",
168
+ });
169
+ toast(shareCardToastMessage(method));
170
+ return;
171
+ }
172
+
173
+ const shareCtx: ShareCtx = {
174
+ score,
175
+ arch: archetype.name.toLowerCase(),
176
+ grade,
177
+ missing,
178
+ };
179
+ const shareText = channel === "x"
180
+ ? pickTemplate(X_TEMPLATES, seed, shareCtx)
181
+ : pickTemplate(LI_TEMPLATES, seed, shareCtx);
182
+ const native = await shareCardNative(blob, filenameFor(channel), shareText);
183
+ if (native) {
184
+ capture("audit_card_capture_completed", {
185
+ trigger: `share_${channel}`,
186
+ status: "success",
187
+ image_method: "native",
188
+ source: "poster",
189
+ });
190
+ toast(shareCardToastMessage("native"));
191
+ return;
192
+ }
193
+
194
+ const fallbackMethod = await copyOrDownloadCard(blob, filenameFor(channel));
195
+ capture("audit_card_capture_completed", {
196
+ trigger: `share_${channel}`,
197
+ status: fallbackMethod === "failed" ? "error" : "success",
198
+ image_method: fallbackMethod,
199
+ source: "poster",
200
+ });
201
+ toast(shareCardToastMessage(fallbackMethod));
202
+ const intent = channel === "x" ? X_INTENT(shareText) : LI_INTENT(shareText);
203
+ globalThis.open(intent, "_blank", "noopener,noreferrer");
204
+ } finally {
205
+ setBusy(null);
206
+ }
207
+ };
208
+
209
+ return (
210
+ <section className="poster-section" data-screen-label="01 Poster">
211
+ <div className="poster" ref={posterRef}>
212
+ <header className="poster-head">
213
+ <span className="poster-wordmark">
214
+ <img
215
+ src="/logo.svg"
216
+ alt="failproof_ai"
217
+ className="poster-logo"
218
+ />
219
+ <span className="poster-sep">·</span> audit
220
+ </span>
221
+ <span className="poster-meta">
222
+ <span className="poster-ix">№ {indexLabel}</span>
223
+ <span className="of"> of 08</span>
224
+ <span className="poster-sep"> · </span>
225
+ audited {auditedDate}
226
+ </span>
227
+ </header>
228
+
229
+ <div className="poster-body">
230
+ {/* Sigil — visual anchor at the top of the centered stack */}
231
+ <div className="poster-sigil">
232
+ <Sigil archetypeKey={archetypeKey} />
233
+ </div>
234
+
235
+ {/* Persona block — name + keywords + rarity, centered */}
236
+ <div className="poster-persona">
237
+ <h1 className="persona-name">{archetype.name}</h1>
238
+ <div className="persona-keywords">
239
+ {archetype.keywords.map((k, i) => (
240
+ <React.Fragment key={k}>
241
+ <span className={`kw kw-${i}`}>{k}</span>
242
+ {i < archetype.keywords.length - 1 && (
243
+ <span className="kw-sep">·</span>
244
+ )}
245
+ </React.Fragment>
246
+ ))}
247
+ </div>
248
+ {typeof rarityPct === "number" && (
249
+ <div className="persona-rarity">
250
+ <span className="lbl">{"// only"}</span>{" "}
251
+ <span className="pct">{rarityPct}%</span>{" "}
252
+ <span className="lbl">of agents are this archetype</span>
253
+ </div>
254
+ )}
255
+ </div>
256
+
257
+ {/* Score block — heroic number + rank pill on the same baseline */}
258
+ <div className="poster-score">
259
+ <span className="score-n">{score}</span>
260
+ <span className="score-of">/100</span>
261
+ <span className="score-rank">{scoreRank}</span>
262
+ </div>
263
+ </div>
264
+
265
+ <footer className="poster-foot">
266
+ <span className="poster-cta">
267
+ audit yours <span className="arrow">→</span> failproof.ai
268
+ </span>
269
+ </footer>
270
+ </div>
271
+
272
+ <div className="poster-share-row">
273
+ <button
274
+ type="button"
275
+ className="poster-share-btn"
276
+ onClick={() => handleShare("x")}
277
+ disabled={busy !== null}
278
+ >
279
+ <span className="mark" aria-hidden="true">𝕏</span>
280
+ {busy === "x" ? "rendering…" : "post your archetype"}
281
+ </button>
282
+ <button
283
+ type="button"
284
+ className="poster-share-btn"
285
+ onClick={() => handleShare("linkedin")}
286
+ disabled={busy !== null}
287
+ >
288
+ <span className="mark" aria-hidden="true">in</span>
289
+ {busy === "linkedin" ? "rendering…" : "share on linkedin"}
290
+ </button>
291
+ <button
292
+ type="button"
293
+ className="poster-share-btn"
294
+ onClick={() => handleShare("download")}
295
+ disabled={busy !== null}
296
+ >
297
+ <span className="mark" aria-hidden="true">↓</span>
298
+ {busy === "download" ? "rendering…" : "download poster"}
299
+ </button>
300
+ </div>
301
+
302
+ <div className="poster-scroll-hint" aria-hidden="true">
303
+ scroll for full report <span className="arrow">↓</span>
304
+ </div>
305
+ </section>
306
+ );
307
+ });
308
+
309
+ /** UTC ISO date (YYYY-MM-DD) so the poster's date stays timezone-stable
310
+ * across the geographies it gets shared into. */
311
+ function formatAuditedDate(iso: string): string {
312
+ try {
313
+ const d = new Date(iso);
314
+ if (Number.isNaN(d.getTime())) return iso;
315
+ const y = d.getUTCFullYear();
316
+ const m = String(d.getUTCMonth() + 1).padStart(2, "0");
317
+ const day = String(d.getUTCDate()).padStart(2, "0");
318
+ return `${y}-${m}-${day}`;
319
+ } catch {
320
+ return iso;
321
+ }
322
+ }
@@ -32,7 +32,7 @@ interface Props {
32
32
  const ERROR_COPY: Record<RerunError["kind"], string> = {
33
33
  timeout: "audit took too long — try again",
34
34
  network: "network hiccup — check your connection",
35
- post_failed: "audit failed to start — try again",
35
+ post_failed: "audit failed — try again",
36
36
  };
37
37
 
38
38
  export function formatElapsed(ms: number): string {