failproofai 0.0.11-beta.1 → 0.0.11-beta.3
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.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +8 -1
- package/.next/standalone/.next/build-manifest.json +10 -10
- package/.next/standalone/.next/prerender-manifest.json +3 -32
- package/.next/standalone/.next/required-server-files.json +2 -1
- package/.next/standalone/.next/routes-manifest.json +45 -3
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +6 -6
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/_not-found/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js +12 -13
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +16 -16
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +16 -16
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/run/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/audit/run/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/audit/run/route.js +8 -0
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/audit/run/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/audit/status/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/audit/status/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/audit/status/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/audit/status/route.js +6 -0
- package/.next/standalone/.next/server/app/api/audit/status/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/audit/status/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +6 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/login-request/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/login-verify/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/reminder/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/auth/status/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/auth/status/route/build-manifest.json +9 -0
- package/.next/standalone/.next/server/app/api/auth/status/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/auth/status/route.js +7 -0
- package/.next/standalone/.next/server/app/api/auth/status/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/auth/status/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +3 -3
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +18 -0
- package/.next/standalone/.next/server/app/audit/page/next-font-manifest.json +6 -0
- package/.next/standalone/.next/server/app/audit/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +29 -0
- package/.next/standalone/.next/server/app/audit/page.js +17 -0
- package/.next/standalone/.next/server/app/audit/page.js.map +5 -0
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +16 -17
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -17
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -3
- package/.next/standalone/.next/server/app/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +14 -15
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/policies/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js +16 -16
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/project/[name]/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +16 -17
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +19 -20
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +7 -7
- package/.next/standalone/.next/server/app/projects/page/next-font-manifest.json +2 -6
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +15 -16
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +8 -1
- package/.next/standalone/.next/server/chunks/[externals]__14odj07._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[externals]__0z0j--b._.js → [externals]__1nl3dvw._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__0-p9.k~._.js → [externals]__1s61mel._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]_node_os_06ur78j._.js → [externals]_node_os_0by37l-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07tgnzi._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0kjo7d_._.js → [root-of-the-server]__0_0xu5z._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cag8qd._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0z-180.._.js → [root-of-the-server]__0cycwg6._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__08px0ym._.js → [root-of-the-server]__0f7mikp._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0oeun7z._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0g48iv.._.js → [root-of-the-server]__0sb_5m8._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0j8-xkl._.js → [root-of-the-server]__0xuaoik._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12pit4m._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13h8pzr._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__13ra2jq._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0d_ob4n._.js → [root-of-the-server]__1_mqemn._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1b9z5-i._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0vlhtkc._.js → [root-of-the-server]__1hgv_75._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ixjiy8._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0wu7fr7._.js → [root-of-the-server]__1jm9fw6._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0fwb7ao._.js → [root-of-the-server]__1m2_4t0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0yfq1yr._.js → [root-of-the-server]__1mhmdzs._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0zso~62._.js → [root-of-the-server]__1ou2ehh._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0.~nmr9._.js → [root-of-the-server]__1w9zl9-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{_0ebx_lc._.js → _0p53ge1._.js} +2 -2
- package/.next/standalone/.next/server/chunks/_1-1804f._.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_run_route_actions_1qgp9io.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_audit_status_route_actions_1f7pjof.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_login-request_route_actions_1c49co0.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_login-verify_route_actions_1r3slzk.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_logout_route_actions_0regwyr.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_reminder_route_actions_1kjgxf8.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_auth_status_route_actions_1aho9zu.js +3 -0
- package/.next/standalone/.next/server/chunks/{_next-internal_server_app_api_download_[project]_[session]_route_actions_0wb00i-.js → _next-internal_server_app_api_download_[project]_[session]_route_actions_1is7vs7.js} +1 -1
- package/.next/standalone/.next/server/chunks/{lib_logger_ts_047tt9f._.js → lib_logger_ts_07e65t5._.js} +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +23 -0
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +3 -0
- package/.next/standalone/.next/server/chunks/{package_json_[json]_cjs_0z7w.hh._.js → package_json_[json]_cjs_1nxcc4v._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[externals]__12dv.x0._.js → [externals]__1_g_b3t._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[externals]_node_async_hooks_0v0ln8c._.js → [externals]_node_async_hooks_1gjz99j._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00jkjmt._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013du6r._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0989_dx._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e85wxv._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0gfxvb1._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h12me5._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0l13qf2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ywoypf._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-scthx._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__100hdar._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11rtg6s._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1cd25c7._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0t5l7a5._.js → [root-of-the-server]__1d8omgc._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0tcyn68._.js → [root-of-the-server]__1dky4g0._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__098zro9._.js → [root-of-the-server]__1fax1sl._.js} +4 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1hlrq6y._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ihxdo5._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mt35_w._.js +221 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0-wn51s._.js → [root-of-the-server]__1pcxxwg._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1usf8v2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1vvfde2._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__212nf49._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_03d7qyt._.js → _05whahf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_0xb8ngh._.js → _1kje4fm._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0zx~s__._.js → _1p0-leb._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_04qfs8z._.js → app_087bt9w._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_0uosk1e._.js → app_1fvisnp._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_13f0ohr._.js → app_209u41o._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +43 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit_loading_tsx_1j1kc6j._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{app_error_tsx_11t4ysq._.js → app_error_tsx_1zds1ns._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_global-error_tsx_0m9qisk._.js → app_global-error_tsx_113y3za._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +8 -0
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_error_tsx_0.9-fod._.js → app_project_[name]_error_tsx_1v02_5n._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_loading_tsx_03g9xy0._.js → app_project_[name]_loading_tsx_05-l4uf._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_session_[sessionId]_error_tsx_0ler-mr._.js → app_project_[name]_session_[sessionId]_error_tsx_0-lj3nd._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{app_project_[name]_session_[sessionId]_loading_tsx_0c0e3yx._.js → app_project_[name]_session_[sessionId]_loading_tsx_0l4aixs._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_projects_loading_tsx_20-3u8b._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{lib_codex-projects_ts_0eosib~._.js → lib_codex-projects_ts_0pqlw37._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_copilot-projects_ts_0r8xkn8._.js → lib_copilot-projects_ts_19wl7tp._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_cursor-projects_ts_0qt1scg._.js → lib_cursor-projects_ts_18-iwyk._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_gemini-projects_ts_0sl~yqr._.js → lib_gemini-projects_ts_1c7bgx-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_opencode-projects_ts_0op9gyp._.js → lib_opencode-projects_ts_15bjxkm._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_pi-projects_ts_103tsh1._.js → lib_pi-projects_ts_1wikofb._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{lib_utils_ts_068jk73._.js → lib_utils_ts_0az0sfq._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1ynf7el._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_05gja40.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html2canvas_dist_html2canvas_esm_1n-0xws.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_0rd0oc-._.js → node_modules_next_1a1kch7._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_0h9llsw._.js → node_modules_next_dist_0uboya6._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_11dij6w._.js → node_modules_next_dist_1d_onnt._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_client_components_0inhx6q._.js → node_modules_next_dist_client_components_0wpq8j3._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_forbidden_0ghu-f7.js → node_modules_next_dist_client_components_builtin_forbidden_0symwr9.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_client_components_builtin_unauthorized_0cjv-23.js → node_modules_next_dist_client_components_builtin_unauthorized_0l_sp0x.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0-uvagv.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_03c7gi5.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_09p-8om.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0v-kfiu.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0j79~gv.js → node_modules_next_dist_esm_build_templates_app-page_0xrgzyz.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1806lsc.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1j6dd-e.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_1sa65r-.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +5 -0
- package/.next/standalone/.next/server/functions-config-manifest.json +3 -0
- package/.next/standalone/.next/server/instrumentation.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +10 -10
- package/.next/standalone/.next/server/middleware.js +2 -2
- package/.next/standalone/.next/server/next-font-manifest.js +1 -1
- package/.next/standalone/.next/server/next-font-manifest.json +2 -21
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +27 -9
- package/.next/standalone/.next/static/chunks/{07uz2g0_38qia.js → 03fmihek9n986.js} +1 -1
- package/.next/standalone/.next/static/chunks/09ueq8s1as8xs.css +2 -0
- package/.next/standalone/.next/static/chunks/0ehe4dh0grngk.js +41 -0
- package/.next/standalone/.next/static/chunks/{13-bt.3~irg00.js → 0gdm-xaez4l7t.js} +1 -1
- package/.next/standalone/.next/static/chunks/{07kfzzinhsl7e.js → 0kdglk0vtzymo.js} +1 -1
- package/.next/standalone/.next/static/chunks/0qassxjx1ef04.js +1 -0
- package/.next/standalone/.next/static/chunks/0zbxssxh53n-3.js +1 -0
- package/.next/standalone/.next/static/chunks/13f1kmjea-0md.js +2 -0
- package/.next/standalone/.next/static/chunks/1btx2c49fk9xt.css +1 -0
- package/.next/standalone/.next/static/chunks/1fmco3pvq_twz.js +1 -0
- package/.next/standalone/.next/static/chunks/2b1fzuhuk-42n.js +1 -0
- package/.next/standalone/.next/static/chunks/{0_vk1wsgf~q3o.js → 2dtip-mvmihiu.js} +1 -1
- package/.next/standalone/.next/static/chunks/2srzafd1_ha5y.js +1 -0
- package/.next/standalone/.next/static/chunks/{0d3shmwh5_nmn.js → 33u59vf_8xpd-.js} +1 -1
- package/.next/standalone/.next/static/chunks/3gti1qdk5epqn.js +1 -0
- package/.next/standalone/.next/static/chunks/{0wtiofzdt-l2u.js → 3krzy-lhwfrmz.js} +1 -1
- package/.next/standalone/.next/static/chunks/{17mubwtqwijpu.js → 3w8d8k_dca5rp.js} +1 -1
- package/.next/standalone/.next/static/chunks/43lnq0c1rnflb.js +6 -0
- package/.next/standalone/.next/static/chunks/{turbopack-0nh.aopesgj~5.js → turbopack-00qy7zfa7m--m.js} +1 -1
- package/.next/standalone/SECURITY.md +73 -0
- package/.next/standalone/app/actions/get-audit-result.ts +24 -0
- package/.next/standalone/app/api/audit/_state.ts +72 -0
- package/.next/standalone/app/api/audit/run/route.ts +89 -0
- package/.next/standalone/app/api/audit/status/route.ts +23 -0
- package/.next/standalone/app/api/auth/login-request/route.ts +91 -0
- package/.next/standalone/app/api/auth/login-verify/route.ts +98 -0
- package/.next/standalone/app/api/auth/logout/route.ts +48 -0
- package/.next/standalone/app/api/auth/reminder/route.ts +213 -0
- package/.next/standalone/app/api/auth/status/route.ts +42 -0
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +364 -0
- package/.next/standalone/app/audit/_components/auth-dialog.tsx +401 -0
- package/.next/standalone/app/audit/_components/empty-state.tsx +146 -0
- package/.next/standalone/app/audit/_components/findings-section.tsx +135 -0
- package/.next/standalone/app/audit/_components/identity-section.tsx +126 -0
- package/.next/standalone/app/audit/_components/policies-section.tsx +194 -0
- package/.next/standalone/app/audit/_components/report-footer.tsx +35 -0
- package/.next/standalone/app/audit/_components/rerun-button.tsx +81 -0
- package/.next/standalone/app/audit/_components/return-section.tsx +428 -0
- package/.next/standalone/app/audit/_components/run-progress.tsx +120 -0
- package/.next/standalone/app/audit/_components/score-section.tsx +179 -0
- package/.next/standalone/app/audit/_components/share-dock.tsx +265 -0
- package/.next/standalone/app/audit/_components/share-templates.ts +67 -0
- package/.next/standalone/app/audit/_components/show-off-cta.tsx +135 -0
- package/.next/standalone/app/audit/_components/sigil.tsx +93 -0
- package/.next/standalone/app/audit/_components/strengths-section.tsx +57 -0
- package/.next/standalone/app/audit/audit-styles.css +2066 -0
- package/.next/standalone/app/audit/loading.tsx +24 -0
- package/.next/standalone/app/audit/page.tsx +53 -0
- package/.next/standalone/app/globals.css +570 -137
- package/.next/standalone/app/layout.tsx +16 -9
- package/.next/standalone/app/policies/hooks-client.tsx +325 -142
- package/.next/standalone/app/project/[name]/page.tsx +89 -39
- package/.next/standalone/app/projects/loading.tsx +30 -8
- package/.next/standalone/app/projects/page.tsx +76 -18
- package/.next/standalone/assets/audit/Audit Report.html +22 -0
- package/.next/standalone/assets/audit/Show Off Your Agent.html +22 -0
- package/.next/standalone/assets/audit/archetypes.jsx +277 -0
- package/.next/standalone/assets/audit/assets/fonts/bitcount-prop-single.woff2 +0 -0
- package/.next/standalone/assets/audit/audit.jsx +825 -0
- package/.next/standalone/assets/audit/poster-styles.css +424 -0
- package/.next/standalone/assets/audit/poster.jsx +247 -0
- package/.next/standalone/assets/audit/screenshots/poster-optimist.png +0 -0
- package/.next/standalone/assets/audit/screenshots/poster-scrolled.png +0 -0
- package/.next/standalone/assets/audit/styles.css +1225 -0
- package/.next/standalone/assets/audit/tweaks-panel.jsx +425 -0
- package/.next/standalone/assets/logos/company/icon.svg +1 -0
- package/.next/standalone/assets/logos/company/logo.svg +1 -0
- package/.next/standalone/components/navbar.tsx +154 -65
- package/.next/standalone/components/reach-developers.tsx +37 -9
- package/.next/standalone/lib/atomic-write.ts +67 -0
- package/.next/standalone/lib/auth/api-server-client.ts +281 -0
- package/.next/standalone/lib/auth/auth-store.ts +250 -0
- package/.next/standalone/lib/claude-sessions.ts +181 -0
- package/.next/standalone/lib/client-telemetry.ts +2 -0
- package/.next/standalone/lib/fetch-with-timeout.ts +42 -0
- package/.next/standalone/lib/share-card.ts +120 -0
- package/.next/standalone/lib/telemetry.ts +12 -7
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/client/dev/debug-channel.js +102 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +11 -11
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +13 -13
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +2 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/app-render/action-handler.js +18 -8
- package/.next/standalone/node_modules/next/dist/server/config-schema.js +1 -0
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/encode-cache-tag.js +45 -0
- package/.next/standalone/node_modules/next/dist/server/lib/implicit-tags.js +6 -3
- package/.next/standalone/node_modules/next/dist/server/lib/patch-fetch.js +5 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/revalidate.js +4 -3
- package/.next/standalone/node_modules/next/dist/server/web/spec-extension/unstable-cache.js +6 -2
- package/.next/standalone/node_modules/next/dist/shared/lib/errors/canary-only-config-error.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +15 -15
- package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
- package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
- package/.next/standalone/node_modules/react/package.json +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/package.json +2 -2
- package/.next/standalone/osv-scanner.toml +17 -0
- package/.next/standalone/package.json +8 -3
- package/.next/standalone/public/audit/fonts/bitcount-prop-single.woff2 +0 -0
- package/.next/standalone/public/icon.svg +1 -0
- package/.next/standalone/public/logo.svg +1 -0
- package/.next/standalone/server.js +1 -1
- package/.next/standalone/templates/bitcount-font/README.md +42 -0
- package/.next/standalone/templates/bitcount-font/bitcount-prop-single.woff2 +0 -0
- package/.next/standalone/templates/bitcount-font/bitcount.css +49 -0
- package/.next/standalone/templates/bitcount-font/fonts.ts.example +23 -0
- package/README.md +4 -3
- package/bin/failproofai.mjs +248 -70
- package/dist/cli.mjs +1709 -1385
- package/lib/atomic-write.ts +67 -0
- package/lib/auth/api-server-client.ts +281 -0
- package/lib/auth/auth-store.ts +250 -0
- package/lib/claude-sessions.ts +181 -0
- package/lib/client-telemetry.ts +2 -0
- package/lib/fetch-with-timeout.ts +42 -0
- package/lib/share-card.ts +120 -0
- package/lib/telemetry.ts +12 -7
- package/package.json +8 -3
- package/scripts/install-telemetry.mjs +4 -0
- package/scripts/postinstall.mjs +89 -1
- package/src/audit/archetypes.ts +924 -0
- package/src/audit/cache.ts +132 -0
- package/src/audit/cli-adapters/claude.ts +97 -0
- package/src/audit/cli-adapters/codex.ts +56 -0
- package/src/audit/cli-adapters/copilot.ts +51 -0
- package/src/audit/cli-adapters/cursor.ts +51 -0
- package/src/audit/cli-adapters/gemini.ts +51 -0
- package/src/audit/cli-adapters/index.ts +70 -0
- package/src/audit/cli-adapters/opencode.ts +52 -0
- package/src/audit/cli-adapters/pi.ts +51 -0
- package/src/audit/cli-adapters/shared.ts +85 -0
- package/src/audit/dashboard-cache.ts +111 -0
- package/src/audit/detectors/find-from-root.ts +27 -0
- package/src/audit/detectors/git-commit-no-verify.ts +22 -0
- package/src/audit/detectors/index.ts +33 -0
- package/src/audit/detectors/prefer-edit-over-read-cat.ts +31 -0
- package/src/audit/detectors/prefer-edit-over-sed-awk.ts +27 -0
- package/src/audit/detectors/prefer-write-over-heredoc.ts +36 -0
- package/src/audit/detectors/redundant-cd-cwd.ts +28 -0
- package/src/audit/detectors/reread-after-edit.ts +58 -0
- package/src/audit/detectors/sleep-polling-loop.ts +34 -0
- package/src/audit/features.ts +268 -0
- package/src/audit/findings.ts +298 -0
- package/src/audit/index.ts +387 -0
- package/src/audit/replay.ts +147 -0
- package/src/audit/report.ts +349 -0
- package/src/audit/scoring.ts +174 -0
- package/src/audit/strengths.ts +138 -0
- package/src/audit/types.ts +216 -0
- package/src/auth/cli.ts +359 -0
- package/src/hooks/builtin-policies.ts +80 -1
- package/src/hooks/custom-hooks-loader.ts +19 -3
- package/src/hooks/first-run-nudge.ts +146 -0
- package/src/hooks/handler.ts +21 -102
- package/src/hooks/hook-telemetry.ts +2 -2
- package/src/hooks/install-prompt.ts +34 -4
- package/src/hooks/manager.ts +72 -5
- package/src/hooks/policy-evaluator.ts +16 -1
- package/src/hooks/policy-registry.ts +20 -0
- package/src/hooks/policy-types.ts +9 -0
- package/src/hooks/tool-name-canonicalize.ts +65 -0
- package/src/posthog-key.ts +9 -0
- package/.next/standalone/.next/server/app/icon.png/route/app-paths-manifest.json +0 -3
- package/.next/standalone/.next/server/app/icon.png/route.js +0 -7
- package/.next/standalone/.next/server/app/icon.png/route.js.nft.json +0 -1
- package/.next/standalone/.next/server/app/icon.png.body +0 -0
- package/.next/standalone/.next/server/app/icon.png.meta +0 -1
- package/.next/standalone/.next/server/chunks/[externals]_next_dist_0sqmaqd._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06.arfm._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__i0h0._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fe7_q_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fw.e.h._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0pxn0e1._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xv0jh2._.js +0 -3
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_icon_png_route_actions_12.gv.r.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_0bdfoky.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_05pz9._._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0370~qj._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09i-rsi._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09v.ljl._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0agrcb8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0b7hkr~._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ehh6vp._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g8l0tu._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0j4l6hl._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lp08ll._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0yaqw._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0o21f.o._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t8juvy._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uylufv._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ymlddl._.js +0 -223
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0~03grs._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__101v4_7._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12y7xmt._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_0cdqd9w._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +0 -8
- package/.next/standalone/.next/server/chunks/ssr/app_projects_loading_tsx_13veom4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_0ttbz1~._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_06u0kr8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0a_7sdg.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0ef3uwk.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0pbja1x.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0r6o0i2.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_11y81~_.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_12or2kf.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mebn66._.js +0 -3
- package/.next/standalone/.next/static/chunks/03xhjwk6zhi8f.js +0 -1
- package/.next/standalone/.next/static/chunks/0f5p9plm.aqlp.css +0 -2
- package/.next/standalone/.next/static/chunks/0ffvlbgzgnlw7.js +0 -2
- package/.next/standalone/.next/static/chunks/0wq808vlc8l04.js +0 -6
- package/.next/standalone/.next/static/chunks/0zg~cpc5ysg6d.js +0 -1
- package/.next/standalone/.next/static/chunks/12pt~2f.c1sha.js +0 -1
- package/.next/standalone/.next/static/chunks/16vev.do1oho7.js +0 -4
- package/.next/standalone/.next/static/media/4fa387ec64143e14-s.0.qu-9752pffj.woff2 +0 -0
- package/.next/standalone/.next/static/media/5ce348bf30bf5439-s.0ee55_hj9qcer.woff2 +0 -0
- package/.next/standalone/.next/static/media/6306c77e7c8268e4-s.0mao5jbfbduzp.woff2 +0 -0
- package/.next/standalone/.next/static/media/797e433ab948586e-s.p.09zddjkbdep5a.woff2 +0 -0
- package/.next/standalone/.next/static/media/7d817b4c03b0c5f1-s.0uzt.a6d44yda.woff2 +0 -0
- package/.next/standalone/.next/static/media/bbc41e54d2fcbd21-s.0mvwgmnhv29no.woff2 +0 -0
- package/.next/standalone/.next/static/media/icon.0a.gigb3_x5pd.png +0 -0
- package/.next/standalone/app/icon.png +0 -0
- package/src/auth/login.ts +0 -104
- package/src/auth/logout.ts +0 -50
- package/src/auth/token-store.ts +0 -64
- package/src/relay/daemon.ts +0 -362
- package/src/relay/pid.ts +0 -76
- package/src/relay/queue.ts +0 -225
- /package/.next/standalone/.next/server/app/{icon.png → api/audit/run}/route/build-manifest.json +0 -0
- /package/.next/standalone/.next/server/app/{icon.png → api/audit/run}/route.js.map +0 -0
- /package/.next/standalone/.next/static/chunks/{03~yq9q893hmn.js → 0cz1d0mv5g_q7.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0a40sy4tk8ioe.js → 0wwt5o04i4zwh.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0n1n67imq.udf.js → 1__i9af9g78vd.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0w6fzf.07a24u.js → 2so39wg7mjbi7.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0xbo5nl6w4lka.js → 2wbuxnsvux4di.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{0_s0luks5tay-.js → 35fgpd_feci6x.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{15fklyav5py5m.js → 3xpjn3cdgm-7m.js} +0 -0
- /package/.next/standalone/.next/static/chunks/{17.b3suj8zjjj.js → 4448_qq7bd963.js} +0 -0
- /package/.next/standalone/.next/static/{s5Nn6KwDdLpPhjG3l2WNf → wU3ot-EKa5ApKoh785wp8}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{s5Nn6KwDdLpPhjG3l2WNf → wU3ot-EKa5ApKoh785wp8}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{s5Nn6KwDdLpPhjG3l2WNf → wU3ot-EKa5ApKoh785wp8}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Output renderers for `failproofai audit`:
|
|
3
|
+
* • formatText — ANSI table to stdout (GTM-oriented "moment of truth")
|
|
4
|
+
* • formatMarkdown — shareable sectioned report written to a file
|
|
5
|
+
* • formatJson — machine-readable
|
|
6
|
+
*
|
|
7
|
+
* The text renderer is the user's first impression of the audit. It leads
|
|
8
|
+
* with a headline-box, splits findings into "already protected" vs "slipping
|
|
9
|
+
* through" so the conversion ask is obvious, and ends with a copy-pasteable
|
|
10
|
+
* install command + report path + star link.
|
|
11
|
+
*/
|
|
12
|
+
import type { AuditCount, AuditResult, RunAuditOptions } from "./types";
|
|
13
|
+
|
|
14
|
+
const ANSI = {
|
|
15
|
+
reset: "\x1B[0m",
|
|
16
|
+
dim: "\x1B[2m",
|
|
17
|
+
bold: "\x1B[1m",
|
|
18
|
+
red: "\x1B[31m",
|
|
19
|
+
yellow: "\x1B[33m",
|
|
20
|
+
green: "\x1B[32m",
|
|
21
|
+
cyan: "\x1B[36m",
|
|
22
|
+
magenta: "\x1B[35m",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/** Honor https://no-color.org / NO_COLOR=1 and FORCE_COLOR=0 by stripping all
|
|
26
|
+
* ANSI sequences from the final output. Detected once per renderer call. */
|
|
27
|
+
function noColorEnabled(): boolean {
|
|
28
|
+
if (process.env.NO_COLOR && process.env.NO_COLOR !== "") return true;
|
|
29
|
+
if (process.env.FORCE_COLOR === "0") return true;
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function stripAnsi(s: string): string {
|
|
34
|
+
// eslint-disable-next-line no-control-regex
|
|
35
|
+
return s.replace(/\x1B\[[0-9;]*m/g, "");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Human-readable "time ago" — "30m ago", "2h ago", "3d ago", "2w ago".
|
|
39
|
+
* Returns "just now" for <1 minute. */
|
|
40
|
+
function formatTimeAgo(iso: string | undefined): string {
|
|
41
|
+
if (!iso) return "—";
|
|
42
|
+
const ms = Date.now() - new Date(iso).getTime();
|
|
43
|
+
if (Number.isNaN(ms) || ms < 0) return "—";
|
|
44
|
+
const m = Math.floor(ms / 60_000);
|
|
45
|
+
if (m < 1) return "just now";
|
|
46
|
+
if (m < 60) return `${m}m ago`;
|
|
47
|
+
const h = Math.floor(m / 60);
|
|
48
|
+
if (h < 24) return `${h}h ago`;
|
|
49
|
+
const d = Math.floor(h / 24);
|
|
50
|
+
if (d < 14) return `${d}d ago`;
|
|
51
|
+
const w = Math.floor(d / 7);
|
|
52
|
+
if (w < 8) return `${w}w ago`;
|
|
53
|
+
return `${Math.floor(d / 30)}mo ago`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Width of the headline box and section dividers. Adapts to narrow terminals
|
|
57
|
+
* down to a 60-char floor. */
|
|
58
|
+
function getWidth(): number {
|
|
59
|
+
const cols = process.stdout.columns ?? 80;
|
|
60
|
+
return Math.max(60, Math.min(78, cols));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Box-drawing helpers using unicode round-corner glyphs. */
|
|
64
|
+
function topBorder(w: number): string { return `╭${"─".repeat(w - 2)}╮`; }
|
|
65
|
+
function bottomBorder(w: number): string { return `╰${"─".repeat(w - 2)}╯`; }
|
|
66
|
+
function boxLine(text: string, w: number): string {
|
|
67
|
+
const inner = w - 4; // 2 chars of border + 1 char padding each side
|
|
68
|
+
const visible = stripAnsi(text);
|
|
69
|
+
const pad = Math.max(0, inner - visible.length);
|
|
70
|
+
return `│ ${text}${" ".repeat(pad)} │`;
|
|
71
|
+
}
|
|
72
|
+
function divider(w: number): string { return "─".repeat(w); }
|
|
73
|
+
|
|
74
|
+
/** Short, qualified policy slug — `failproofai/foo` → `foo` for display. */
|
|
75
|
+
function shortName(name: string): string {
|
|
76
|
+
const slash = name.indexOf("/");
|
|
77
|
+
return slash >= 0 ? name.slice(slash + 1) : name;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Sum hits across an AuditCount[] subset. */
|
|
81
|
+
function sumHits(rows: AuditCount[]): number {
|
|
82
|
+
return rows.reduce((acc, r) => acc + r.hits, 0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** Render one row in the table-of-findings form:
|
|
86
|
+
* 31× Tried to read files outside your project
|
|
87
|
+
* Stops the agent from peeking at neighboring repos…
|
|
88
|
+
* Last seen 2h ago · 6 projects
|
|
89
|
+
* › Already enforced — failproofai is blocking these in real time.
|
|
90
|
+
* Example: grep -n …
|
|
91
|
+
*/
|
|
92
|
+
function renderRow(r: AuditCount, opts: { showExamples?: boolean }): string[] {
|
|
93
|
+
const out: string[] = [];
|
|
94
|
+
const sev = r.severity;
|
|
95
|
+
const titleColor =
|
|
96
|
+
sev === "deny" ? ANSI.red
|
|
97
|
+
: sev === "warn" ? ANSI.red
|
|
98
|
+
: sev === "info" || sev === "instruct" ? ANSI.yellow
|
|
99
|
+
: ANSI.cyan;
|
|
100
|
+
const countStr = String(r.hits).padStart(4);
|
|
101
|
+
out.push(` ${titleColor}${ANSI.bold}${countStr}×${ANSI.reset} ${r.displayTitle}`);
|
|
102
|
+
if (r.impact) {
|
|
103
|
+
out.push(` ${ANSI.dim}${r.impact}${ANSI.reset}`);
|
|
104
|
+
}
|
|
105
|
+
out.push(
|
|
106
|
+
` ${ANSI.dim}Last seen ${formatTimeAgo(r.lastSeen)} · ${r.projects} project${r.projects === 1 ? "" : "s"}${ANSI.reset}`,
|
|
107
|
+
);
|
|
108
|
+
if (opts.showExamples && r.examples[0]) {
|
|
109
|
+
out.push(` ${ANSI.dim}Example: ${r.examples[0].example}${ANSI.reset}`);
|
|
110
|
+
}
|
|
111
|
+
if (r.installHint) {
|
|
112
|
+
const arrowColor = r.enabledInConfig ? ANSI.green : ANSI.cyan;
|
|
113
|
+
out.push(` ${arrowColor}›${ANSI.reset} ${r.installHint}`);
|
|
114
|
+
}
|
|
115
|
+
out.push("");
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function formatText(result: AuditResult, opts: RunAuditOptions = {}): string {
|
|
120
|
+
const w = getWidth();
|
|
121
|
+
const limit = opts.limit ?? 20;
|
|
122
|
+
const showExamples = !!opts.showExamples;
|
|
123
|
+
|
|
124
|
+
// Split rows by enforcement state.
|
|
125
|
+
const enabledRows = result.results.filter((r) => r.source === "builtin" && r.enabledInConfig);
|
|
126
|
+
const unenabledBuiltinRows = result.results.filter((r) => r.source === "builtin" && !r.enabledInConfig);
|
|
127
|
+
const detectorRows = result.results.filter((r) => r.source === "audit-detector");
|
|
128
|
+
// "Slipping through" combines unenabled-builtins + audit-detectors, ranked by hits.
|
|
129
|
+
const slippingRows = [...unenabledBuiltinRows, ...detectorRows].sort((a, b) => b.hits - a.hits);
|
|
130
|
+
|
|
131
|
+
const totalProtected = sumHits(enabledRows);
|
|
132
|
+
const totalSlipping = sumHits(slippingRows);
|
|
133
|
+
const totalHits = totalProtected + totalSlipping;
|
|
134
|
+
const sinceLabel = result.scope.since ? `the last ${result.scope.since}` : "all time";
|
|
135
|
+
|
|
136
|
+
const lines: string[] = [];
|
|
137
|
+
|
|
138
|
+
// ── Header ──────────────────────────────────────────────────────
|
|
139
|
+
lines.push(`${ANSI.cyan}🛡 failproofai audit${ANSI.reset} ${ANSI.dim}[beta]${ANSI.reset} · ${sinceLabel}`);
|
|
140
|
+
lines.push(
|
|
141
|
+
` ${ANSI.dim}${result.transcripts.scanned} sessions · ${result.totals.projectsWithHits} project${result.totals.projectsWithHits === 1 ? "" : "s"} with hits · scanned in ${(result.transcripts.durationMs / 1000).toFixed(1)}s${ANSI.reset}`,
|
|
142
|
+
);
|
|
143
|
+
lines.push("");
|
|
144
|
+
|
|
145
|
+
// ── Headline box ────────────────────────────────────────────────
|
|
146
|
+
if (totalHits === 0) {
|
|
147
|
+
lines.push(topBorder(w));
|
|
148
|
+
lines.push(boxLine(`${ANSI.green}🎉 Clean run!${ANSI.reset} Nothing matched your policies in this window.`, w));
|
|
149
|
+
lines.push(bottomBorder(w));
|
|
150
|
+
lines.push("");
|
|
151
|
+
return noColorEnabled() ? stripAnsi(lines.join("\n")) : lines.join("\n");
|
|
152
|
+
}
|
|
153
|
+
lines.push(topBorder(w));
|
|
154
|
+
lines.push(boxLine(
|
|
155
|
+
`${ANSI.bold}Your agent did ${totalHits} wasteful or risky things in ${sinceLabel}.${ANSI.reset}`,
|
|
156
|
+
w,
|
|
157
|
+
));
|
|
158
|
+
if (totalSlipping > 0) {
|
|
159
|
+
lines.push(boxLine(
|
|
160
|
+
`${totalSlipping} of those would've been caught if more policies were on.`,
|
|
161
|
+
w,
|
|
162
|
+
));
|
|
163
|
+
}
|
|
164
|
+
lines.push(bottomBorder(w));
|
|
165
|
+
lines.push("");
|
|
166
|
+
|
|
167
|
+
// ── Section: ALREADY PROTECTED ──────────────────────────────────
|
|
168
|
+
if (enabledRows.length > 0) {
|
|
169
|
+
lines.push(
|
|
170
|
+
`${ANSI.green}✓ ALREADY PROTECTED${ANSI.reset} ${ANSI.dim}(${totalProtected} action${totalProtected === 1 ? "" : "s"} stopped by your current policies)${ANSI.reset}`,
|
|
171
|
+
);
|
|
172
|
+
lines.push("");
|
|
173
|
+
for (const row of enabledRows.slice(0, limit)) {
|
|
174
|
+
lines.push(...renderRow(row, { showExamples }));
|
|
175
|
+
}
|
|
176
|
+
if (enabledRows.length > limit) {
|
|
177
|
+
lines.push(` ${ANSI.dim}… ${enabledRows.length - limit} more (use --limit ${enabledRows.length})${ANSI.reset}`);
|
|
178
|
+
lines.push("");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ── Section: SLIPPING THROUGH ───────────────────────────────────
|
|
183
|
+
if (slippingRows.length > 0) {
|
|
184
|
+
lines.push(
|
|
185
|
+
`${ANSI.yellow}○ SLIPPING THROUGH${ANSI.reset} ${ANSI.dim}(${totalSlipping} action${totalSlipping === 1 ? "" : "s"} caught by audit, not blocked in real time)${ANSI.reset}`,
|
|
186
|
+
);
|
|
187
|
+
lines.push("");
|
|
188
|
+
for (const row of slippingRows.slice(0, limit)) {
|
|
189
|
+
lines.push(...renderRow(row, { showExamples }));
|
|
190
|
+
}
|
|
191
|
+
if (slippingRows.length > limit) {
|
|
192
|
+
lines.push(` ${ANSI.dim}… ${slippingRows.length - limit} more (use --limit ${slippingRows.length})${ANSI.reset}`);
|
|
193
|
+
lines.push("");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ── Footer / NEXT step ──────────────────────────────────────────
|
|
198
|
+
lines.push(divider(w));
|
|
199
|
+
if (unenabledBuiltinRows.length > 0) {
|
|
200
|
+
const installNames = unenabledBuiltinRows.map((r) => shortName(r.name));
|
|
201
|
+
lines.push(
|
|
202
|
+
`${ANSI.bold}NEXT${ANSI.reset} Enable the ${installNames.length} unenabled real-time polic${installNames.length === 1 ? "y" : "ies"} in one command:`,
|
|
203
|
+
);
|
|
204
|
+
lines.push("");
|
|
205
|
+
lines.push(` ${ANSI.cyan}failproofai policies --install ${installNames.join(" ")}${ANSI.reset}`);
|
|
206
|
+
lines.push("");
|
|
207
|
+
} else if (slippingRows.length > 0) {
|
|
208
|
+
lines.push(
|
|
209
|
+
`${ANSI.bold}NEXT${ANSI.reset} Everything blockable is already enabled. Audit-only findings will show up in your next ${ANSI.cyan}failproofai audit${ANSI.reset}.`,
|
|
210
|
+
);
|
|
211
|
+
lines.push("");
|
|
212
|
+
} else {
|
|
213
|
+
lines.push(`${ANSI.bold}NEXT${ANSI.reset} ${ANSI.green}You have the relevant policies enabled. failproofai is blocking these in real time.${ANSI.reset}`);
|
|
214
|
+
lines.push("");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Mirror the actual --report path so the printed footer matches what was
|
|
218
|
+
// (or will be) written. Suppressed entirely with --no-report.
|
|
219
|
+
if (!opts.noReport) {
|
|
220
|
+
const reportPath = opts.reportPath ?? "./failproofai-audit.md";
|
|
221
|
+
lines.push(` 📄 Shareable report: ${ANSI.cyan}${reportPath}${ANSI.reset}`);
|
|
222
|
+
}
|
|
223
|
+
lines.push(` ⭐ Star us: ${ANSI.cyan}https://github.com/FailproofAI/failproofai${ANSI.reset}`);
|
|
224
|
+
lines.push("");
|
|
225
|
+
|
|
226
|
+
return noColorEnabled() ? stripAnsi(lines.join("\n")) : lines.join("\n");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function formatJson(result: AuditResult): string {
|
|
230
|
+
return JSON.stringify(result, null, 2);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Escape characters that would break a markdown table row. Pipes split
|
|
234
|
+
* columns; backslashes escape the next char; leading newlines end the row. */
|
|
235
|
+
function escapeTableCell(s: string): string {
|
|
236
|
+
return s.replace(/\\/g, "\\\\").replace(/\|/g, "\\|").replace(/[\r\n]+/g, " ");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function escapeBackticks(s: string): string {
|
|
240
|
+
return s.replace(/`/g, "\\`");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export function formatMarkdown(result: AuditResult): string {
|
|
244
|
+
const out: string[] = [];
|
|
245
|
+
|
|
246
|
+
const enabledRows = result.results.filter((r) => r.source === "builtin" && r.enabledInConfig);
|
|
247
|
+
const unenabledBuiltinRows = result.results.filter((r) => r.source === "builtin" && !r.enabledInConfig);
|
|
248
|
+
const detectorRows = result.results.filter((r) => r.source === "audit-detector");
|
|
249
|
+
const slippingRows = [...unenabledBuiltinRows, ...detectorRows].sort((a, b) => b.hits - a.hits);
|
|
250
|
+
|
|
251
|
+
const totalProtected = sumHits(enabledRows);
|
|
252
|
+
const totalSlipping = sumHits(slippingRows);
|
|
253
|
+
const totalHits = totalProtected + totalSlipping;
|
|
254
|
+
const sinceLabel = result.scope.since ? `last ${result.scope.since}` : "all time";
|
|
255
|
+
|
|
256
|
+
out.push(`# Agent behavior audit · ${sinceLabel}`);
|
|
257
|
+
out.push("");
|
|
258
|
+
out.push("> _Generated by `failproofai audit` (**beta**) — flags and output may change between releases. Going live shortly._");
|
|
259
|
+
out.push("");
|
|
260
|
+
out.push(`*Generated ${result.scannedAt} — scanned ${result.transcripts.scanned} sessions across ${result.totals.projectsWithHits} project(s) in ${(result.transcripts.durationMs / 1000).toFixed(1)}s.*`);
|
|
261
|
+
out.push("");
|
|
262
|
+
|
|
263
|
+
// TL;DR — readable to someone who doesn't know failproofai.
|
|
264
|
+
out.push("## TL;DR");
|
|
265
|
+
out.push("");
|
|
266
|
+
if (totalHits === 0) {
|
|
267
|
+
out.push("Clean run — the AI coding agent didn't do anything `failproofai` catches in this window.");
|
|
268
|
+
} else {
|
|
269
|
+
out.push(
|
|
270
|
+
`Over ${result.transcripts.scanned} sessions, my AI coding agent did **${totalHits} things \`failproofai\` would have stopped**: ` +
|
|
271
|
+
`${totalProtected} were already blocked in real time by my current config; ` +
|
|
272
|
+
`**${totalSlipping} slipped through** (would've been caught if more policies were on).`,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
out.push("");
|
|
276
|
+
out.push("> [failproofai](https://github.com/FailproofAI/failproofai) is a hook-based policy engine for Claude Code, Codex, Copilot, Cursor, OpenCode, Pi, and Gemini CLI. The `audit` command replays past agent sessions through every builtin policy to surface patterns that were (or could've been) stopped.");
|
|
277
|
+
out.push("");
|
|
278
|
+
|
|
279
|
+
if (totalHits === 0) return out.join("\n");
|
|
280
|
+
|
|
281
|
+
// What was blocked
|
|
282
|
+
if (enabledRows.length > 0) {
|
|
283
|
+
out.push(`## ✓ Already protected (${totalProtected} action${totalProtected === 1 ? "" : "s"} stopped)`);
|
|
284
|
+
out.push("");
|
|
285
|
+
out.push("These are real-time policies you have on — `failproofai` blocked the agent before each action took effect.");
|
|
286
|
+
out.push("");
|
|
287
|
+
out.push("| Issue | Hits | Projects | Last seen | Policy |");
|
|
288
|
+
out.push("|---|---:|---:|---|---|");
|
|
289
|
+
for (const r of enabledRows) {
|
|
290
|
+
out.push(
|
|
291
|
+
`| ${escapeTableCell(r.displayTitle)} | ${r.hits} | ${r.projects} | ${formatTimeAgo(r.lastSeen)} | \`${escapeTableCell(shortName(r.name))}\` |`,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
out.push("");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// What's slipping through
|
|
298
|
+
if (slippingRows.length > 0) {
|
|
299
|
+
out.push(`## ○ Slipping through (${totalSlipping} action${totalSlipping === 1 ? "" : "s"} caught by audit, not yet blocked)`);
|
|
300
|
+
out.push("");
|
|
301
|
+
out.push("Patterns the audit detected but real-time enforcement isn't on for. The CTA column shows how to fix each.");
|
|
302
|
+
out.push("");
|
|
303
|
+
out.push("| Issue | Hits | Projects | Last seen | Fix |");
|
|
304
|
+
out.push("|---|---:|---:|---|---|");
|
|
305
|
+
for (const r of slippingRows) {
|
|
306
|
+
const fix = r.source === "builtin"
|
|
307
|
+
? `\`failproofai policies --install ${shortName(r.name)}\``
|
|
308
|
+
: "_audit-only_";
|
|
309
|
+
out.push(
|
|
310
|
+
`| ${escapeTableCell(r.displayTitle)} | ${r.hits} | ${r.projects} | ${formatTimeAgo(r.lastSeen)} | ${fix} |`,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
out.push("");
|
|
314
|
+
|
|
315
|
+
if (unenabledBuiltinRows.length > 0) {
|
|
316
|
+
out.push(`### Enable everything in one command`);
|
|
317
|
+
out.push("");
|
|
318
|
+
out.push("```bash");
|
|
319
|
+
out.push(`failproofai policies --install ${unenabledBuiltinRows.map((r) => shortName(r.name)).join(" ")}`);
|
|
320
|
+
out.push("```");
|
|
321
|
+
out.push("");
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Examples appendix (only if non-trivial)
|
|
326
|
+
const rowsWithExamples = [...enabledRows, ...slippingRows].filter((r) => r.examples.length > 0);
|
|
327
|
+
if (rowsWithExamples.length > 0) {
|
|
328
|
+
out.push("## Examples");
|
|
329
|
+
out.push("");
|
|
330
|
+
for (const r of rowsWithExamples) {
|
|
331
|
+
out.push(`### ${escapeBackticks(r.displayTitle)} (\`${escapeBackticks(shortName(r.name))}\`)`);
|
|
332
|
+
out.push("");
|
|
333
|
+
if (r.impact) {
|
|
334
|
+
out.push(`> ${r.impact}`);
|
|
335
|
+
out.push("");
|
|
336
|
+
}
|
|
337
|
+
for (const e of r.examples) {
|
|
338
|
+
out.push(`- \`${escapeBackticks(e.example)}\` _(${e.cwd || "?"}, ${formatTimeAgo(e.timestamp)})_`);
|
|
339
|
+
}
|
|
340
|
+
out.push("");
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
out.push("---");
|
|
345
|
+
out.push("");
|
|
346
|
+
out.push("⭐ Star failproofai on GitHub: <https://github.com/FailproofAI/failproofai>");
|
|
347
|
+
out.push("");
|
|
348
|
+
return out.join("\n");
|
|
349
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Score derivation for the audit dashboard.
|
|
3
|
+
*
|
|
4
|
+
* Score is on 0-100, mapped to letter grades that anchor the leaderboard
|
|
5
|
+
* + tier prose. The thresholds match the reference design (assets/audit):
|
|
6
|
+
*
|
|
7
|
+
* ≥ 90 S "s tier"
|
|
8
|
+
* ≥ 80 A "a tier"
|
|
9
|
+
* ≥ 71 B "b tier"
|
|
10
|
+
* ≥ 55 C "c tier"
|
|
11
|
+
* ≥ 40 D "d tier"
|
|
12
|
+
* < 40 F "f tier"
|
|
13
|
+
*
|
|
14
|
+
* The "projected score" is the hypothetical score after enabling every
|
|
15
|
+
* recommended unenabled-builtin policy — used by the prescription section
|
|
16
|
+
* to motivate enabling them.
|
|
17
|
+
*/
|
|
18
|
+
import type { AuditResult } from "./types";
|
|
19
|
+
|
|
20
|
+
export type Grade = "S" | "A" | "B" | "C" | "D" | "F";
|
|
21
|
+
|
|
22
|
+
export function gradeFor(score: number): Grade {
|
|
23
|
+
if (score >= 90) return "S";
|
|
24
|
+
if (score >= 80) return "A";
|
|
25
|
+
if (score >= 71) return "B";
|
|
26
|
+
if (score >= 55) return "C";
|
|
27
|
+
if (score >= 40) return "D";
|
|
28
|
+
return "F";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const TIER_NAME: Record<Grade, string> = {
|
|
32
|
+
S: "s tier", A: "a tier", B: "b tier",
|
|
33
|
+
C: "c tier", D: "d tier", F: "f tier",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function tierName(g: Grade): string {
|
|
37
|
+
return TIER_NAME[g];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Heuristic score on 0-100. Three properties make it *dynamic* — distinct
|
|
42
|
+
* inputs (almost) never collide on a fixed threshold the way the old
|
|
43
|
+
* hard-capped scorer did:
|
|
44
|
+
*
|
|
45
|
+
* 1. Rate-normalised. Penalty scales with the *rate* of weighted faults per
|
|
46
|
+
* tool call (× REF_EVENTS), not the absolute count. A 1000-call session
|
|
47
|
+
* with 25 denies scores higher than a 100-call one with 25 denies — and
|
|
48
|
+
* heavy users no longer all pile onto the same cap.
|
|
49
|
+
*
|
|
50
|
+
* 2. Saturating, not clipped. Each severity bucket asymptotes to a cap via
|
|
51
|
+
* `cap·(1 − e^(−p/k))` instead of `min(p, cap)`. One bad area still can't
|
|
52
|
+
* tank the score, but the curve is *strictly monotonic*, so every extra
|
|
53
|
+
* hit still moves the number — no two counts land on the same value.
|
|
54
|
+
*
|
|
55
|
+
* 3. Credited. Up to +5 from the derived strengths, so clean agents spread
|
|
56
|
+
* upward instead of all sitting at 100.
|
|
57
|
+
*
|
|
58
|
+
* Per-hit weights (pre-normalisation): deny 1.2, warn/instruct 0.7,
|
|
59
|
+
* sanitize 0.4, audit detector 0.5. Bucket caps 50 / 28 / 16 / 30 (they sum
|
|
60
|
+
* past 100 so a multi-dimension reckless agent can bottom out at F).
|
|
61
|
+
*
|
|
62
|
+
* Sessions with zero scanned transcripts return 0 (no signal, no grade).
|
|
63
|
+
*/
|
|
64
|
+
import { MIN_EVENTS } from "./features";
|
|
65
|
+
import { deriveStrengths } from "./strengths";
|
|
66
|
+
|
|
67
|
+
/** Reference tool-call volume the rate is normalised against — chosen so a
|
|
68
|
+
* moderate footprint lands around C/B and the demo anchor (~58 → C) holds.
|
|
69
|
+
* Calibrated via __tests__/audit/scoring.test.ts. */
|
|
70
|
+
const REF_EVENTS = 300;
|
|
71
|
+
|
|
72
|
+
/** Concave saturator: → `cap` as `p → ∞`, strictly increasing for all p ≥ 0. */
|
|
73
|
+
function saturate(p: number, cap: number, k: number): number {
|
|
74
|
+
return cap * (1 - Math.exp(-p / k));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Total weighted penalty for a set of rows, rate-normalised against `events`.
|
|
78
|
+
* Shared by `deriveScore` and `projectedScore` so they can't diverge. */
|
|
79
|
+
function penaltyFor(rows: AuditResult["results"], events: number): number {
|
|
80
|
+
const norm = REF_EVENTS / Math.max(events, MIN_EVENTS);
|
|
81
|
+
let deny = 0, instruct = 0, sanitize = 0, detector = 0;
|
|
82
|
+
for (const row of rows) {
|
|
83
|
+
if (row.source === "audit-detector") {
|
|
84
|
+
detector += row.hits * 0.5;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const sev = row.severity;
|
|
88
|
+
if (sev === "deny") deny += row.hits * 1.2;
|
|
89
|
+
else if (sev === "instruct" || sev === "warn") instruct += row.hits * 0.7;
|
|
90
|
+
else sanitize += row.hits * 0.4; // sanitize-* and any other gentle category
|
|
91
|
+
}
|
|
92
|
+
// Per-bucket (cap, k). The cap bounds any single failure mode; k sets how
|
|
93
|
+
// fast it ramps. k is small relative to the cap so penalties bite early and
|
|
94
|
+
// the score uses the full S→F range rather than clustering near 100. Caps
|
|
95
|
+
// sum past 100 on purpose, so a multi-dimension reckless agent can reach F.
|
|
96
|
+
return (
|
|
97
|
+
saturate(deny * norm, 50, 12) +
|
|
98
|
+
saturate(instruct * norm, 28, 10) +
|
|
99
|
+
saturate(sanitize * norm, 16, 8) +
|
|
100
|
+
saturate(detector * norm, 30, 14)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** Positive credit (0-5) from the heuristic strengths. Deliberately small so a
|
|
105
|
+
* reckless agent's "absence" strengths (e.g. "no credential leaks") can't
|
|
106
|
+
* inflate it back into the top tier. */
|
|
107
|
+
function creditFor(result: AuditResult): number {
|
|
108
|
+
return Math.min(deriveStrengths(result).length * 1.0, 5);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Exact (unrounded) score — used by tests to prove strict monotonicity and
|
|
112
|
+
* the absence of threshold collisions. */
|
|
113
|
+
export function deriveScoreExact(result: AuditResult): number {
|
|
114
|
+
if (result.transcripts.scanned === 0) return 0;
|
|
115
|
+
const events = result.eventsScanned ?? 0;
|
|
116
|
+
const score = 100 - penaltyFor(result.results, events) + creditFor(result);
|
|
117
|
+
return Math.max(0, Math.min(100, score));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function deriveScore(result: AuditResult): number {
|
|
121
|
+
return Math.round(deriveScoreExact(result));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Projected score after enabling every unenabled builtin. Doesn't actually
|
|
126
|
+
* re-run the audit — instead it credits back the hits the user would have
|
|
127
|
+
* blocked by enabling those policies, applying the same weighted penalty
|
|
128
|
+
* scheme used by `deriveScore`.
|
|
129
|
+
*
|
|
130
|
+
* Caps at 92 so the prescription never promises a guaranteed S — the user
|
|
131
|
+
* still has to keep the policies on.
|
|
132
|
+
*/
|
|
133
|
+
export function projectedScore(result: AuditResult, currentScore: number): number {
|
|
134
|
+
const events = result.eventsScanned ?? 0;
|
|
135
|
+
// Penalty as-is vs. penalty with every unenabled builtin's hits removed
|
|
136
|
+
// (enabling those policies would have blocked them). The delta is what the
|
|
137
|
+
// user recovers — computed through the same saturating, rate-normalised
|
|
138
|
+
// curve as `deriveScore`, so the projection is consistent rather than a
|
|
139
|
+
// naive per-hit sum.
|
|
140
|
+
const full = penaltyFor(result.results, events);
|
|
141
|
+
const fixedRows = result.results.filter(
|
|
142
|
+
(r) => !(r.source === "builtin" && !r.enabledInConfig),
|
|
143
|
+
);
|
|
144
|
+
const fixed = penaltyFor(fixedRows, events);
|
|
145
|
+
const recoverable = Math.max(0, full - fixed);
|
|
146
|
+
// Cap at 92 so the prescription never promises a guaranteed S.
|
|
147
|
+
const proj = Math.min(92, currentScore + Math.round(recoverable));
|
|
148
|
+
return Math.max(currentScore, proj);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Approximate global rank in the cohort. We don't have a real leaderboard
|
|
153
|
+
* yet — this is a deterministic synthetic rank derived from the score so
|
|
154
|
+
* the UI doesn't feel jittery as the user re-runs.
|
|
155
|
+
*
|
|
156
|
+
* Distribution roughly matches a bell-shape centered at 60. Cohort size
|
|
157
|
+
* is fixed at 2316 to match the reference design.
|
|
158
|
+
*/
|
|
159
|
+
export const COHORT_SIZE = 2316;
|
|
160
|
+
|
|
161
|
+
export function syntheticRank(score: number): number {
|
|
162
|
+
// Roughly: 100 → top of leaderboard, 0 → bottom. Use a smooth curve so
|
|
163
|
+
// small score changes feel meaningful but not catastrophic.
|
|
164
|
+
const percentile = scoreToPercentile(score);
|
|
165
|
+
return Math.max(1, Math.min(COHORT_SIZE, Math.round((1 - percentile) * COHORT_SIZE)));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function scoreToPercentile(score: number): number {
|
|
169
|
+
// Logistic mapping centered at 58 — agents below 58 fall into the long
|
|
170
|
+
// tail, agents above climb steeply. Anchors the default demo (58 → ~p20).
|
|
171
|
+
const z = (score - 58) / 14;
|
|
172
|
+
const p = 1 / (1 + Math.exp(-z));
|
|
173
|
+
return p;
|
|
174
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive the StrengthsSection rows from a live AuditResult.
|
|
3
|
+
*
|
|
4
|
+
* The reference (assets/audit/audit.jsx) ships 5 hand-curated strengths
|
|
5
|
+
* with placeholder numbers. Here we compute each one off the actual
|
|
6
|
+
* scanned data. Output shape mirrors the original.
|
|
7
|
+
*
|
|
8
|
+
* Most strengths are "absences" — the cleaner the agent, the more
|
|
9
|
+
* strengths we surface (e.g. "0 credential leaks" only counts as a
|
|
10
|
+
* strength when no sanitize-* policies fired).
|
|
11
|
+
*/
|
|
12
|
+
import type { AuditResult } from "./types";
|
|
13
|
+
|
|
14
|
+
export interface Strength {
|
|
15
|
+
metric: string;
|
|
16
|
+
unit: string;
|
|
17
|
+
headline: string;
|
|
18
|
+
detail: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function shortName(name: string): string {
|
|
22
|
+
const slash = name.indexOf("/");
|
|
23
|
+
return slash >= 0 ? name.slice(slash + 1) : name;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function hitsForShort(result: AuditResult, names: string[]): number {
|
|
27
|
+
const set = new Set(names);
|
|
28
|
+
let total = 0;
|
|
29
|
+
for (const r of result.results) {
|
|
30
|
+
if (set.has(shortName(r.name))) total += r.hits;
|
|
31
|
+
}
|
|
32
|
+
return total;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Pick up to 5 derived strengths. Each strength has a true-or-not test —
|
|
36
|
+
* only included when the agent actually demonstrates the behavior. */
|
|
37
|
+
export function deriveStrengths(result: AuditResult): Strength[] {
|
|
38
|
+
const out: Strength[] = [];
|
|
39
|
+
const events = result.eventsScanned ?? 0;
|
|
40
|
+
const totalHits = result.totals.hits;
|
|
41
|
+
const detectorsTriggered = result.results.filter((r) => r.source === "audit-detector").length;
|
|
42
|
+
const cleanRate = events > 0 ? Math.max(0, Math.min(100, Math.round(((events - totalHits) / events) * 100))) : 100;
|
|
43
|
+
|
|
44
|
+
// 1. Always show the "X tool calls, Y detectors triggered" headline.
|
|
45
|
+
if (events > 0) {
|
|
46
|
+
out.push({
|
|
47
|
+
metric: `${cleanRate}%`,
|
|
48
|
+
unit: "clean tool calls",
|
|
49
|
+
headline: `ran ${events.toLocaleString()} tool calls. ${detectorsTriggered} detector${detectorsTriggered === 1 ? "" : "s"} triggered.`,
|
|
50
|
+
detail: `${cleanRate}% of tool calls came back clean before today's audit.`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 2. Zero credential exposure to stdout — only when no sanitize-* and no
|
|
55
|
+
// block-env-files / block-secrets-write / block-read-outside-cwd hits.
|
|
56
|
+
const credentialPolicies = [
|
|
57
|
+
"sanitize-api-keys", "sanitize-jwt", "sanitize-connection-strings",
|
|
58
|
+
"sanitize-private-key-content", "sanitize-bearer-tokens",
|
|
59
|
+
"block-env-files", "block-secrets-write", "block-read-outside-cwd",
|
|
60
|
+
"protect-env-vars",
|
|
61
|
+
];
|
|
62
|
+
if (hitsForShort(result, credentialPolicies) === 0) {
|
|
63
|
+
out.push({
|
|
64
|
+
metric: "0",
|
|
65
|
+
unit: "credential leaks",
|
|
66
|
+
headline: "zero credential exposure to stdout.",
|
|
67
|
+
detail: "no env files, secret writes, or sanitize hits across the audit window.",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 3. Average sessions task length — `events / sessions`. Faster than
|
|
72
|
+
// median (50) is celebrated; slower than it is mentioned in findings.
|
|
73
|
+
if (result.transcripts.scanned > 0 && events > 0) {
|
|
74
|
+
const avgTurns = Math.max(1, Math.round(events / result.transcripts.scanned));
|
|
75
|
+
if (avgTurns < 30) {
|
|
76
|
+
out.push({
|
|
77
|
+
metric: String(avgTurns),
|
|
78
|
+
unit: "avg turns / session",
|
|
79
|
+
headline: `sessions complete in ${avgTurns} turns on average.`,
|
|
80
|
+
detail: avgTurns < 15
|
|
81
|
+
? "faster than the median agent in this cohort."
|
|
82
|
+
: "comfortably within the typical session length envelope.",
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// 4. No retry storms — `warn-repeated-tool-calls` + `sleep-polling-loop`
|
|
88
|
+
// are both quiet.
|
|
89
|
+
const retryHits = hitsForShort(result, ["warn-repeated-tool-calls", "sleep-polling-loop"]);
|
|
90
|
+
if (retryHits === 0) {
|
|
91
|
+
out.push({
|
|
92
|
+
metric: "0",
|
|
93
|
+
unit: "retry storms",
|
|
94
|
+
headline: "no retry storms or polling loops detected.",
|
|
95
|
+
detail: "failed calls were diagnosed or moved on from. no six-times-in-a-row spirals.",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// 5. No production-shape git mistakes.
|
|
100
|
+
const gitHits = hitsForShort(result, [
|
|
101
|
+
"block-push-master", "block-force-push", "block-work-on-main",
|
|
102
|
+
"git-commit-no-verify",
|
|
103
|
+
]);
|
|
104
|
+
if (gitHits === 0) {
|
|
105
|
+
out.push({
|
|
106
|
+
metric: "0",
|
|
107
|
+
unit: "push-to-main attempts",
|
|
108
|
+
headline: "kept changes off main without prompting.",
|
|
109
|
+
detail: "no direct pushes, force pushes, or hook bypasses across every session.",
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 6. No double-writes / re-reads — agent is efficient with edits.
|
|
114
|
+
const wastefulEdits = hitsForShort(result, [
|
|
115
|
+
"reread-after-edit", "prefer-edit-over-sed-awk", "prefer-write-over-heredoc",
|
|
116
|
+
]);
|
|
117
|
+
if (wastefulEdits === 0 && events > 0) {
|
|
118
|
+
out.push({
|
|
119
|
+
metric: "0",
|
|
120
|
+
unit: "double-writes",
|
|
121
|
+
headline: "no double-writes across production projects.",
|
|
122
|
+
detail: "the agent never re-read a file it had just edited, or rewrote via shell.",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Cap to 5. If we somehow have <2 strengths, surface a generic "no
|
|
127
|
+
// findings in this category" so the section never looks empty.
|
|
128
|
+
if (out.length < 2) {
|
|
129
|
+
out.push({
|
|
130
|
+
metric: "—",
|
|
131
|
+
unit: "audit window",
|
|
132
|
+
headline: "audit complete.",
|
|
133
|
+
detail: `${result.transcripts.scanned} session${result.transcripts.scanned === 1 ? "" : "s"} scanned across ${result.totals.projectsWithHits} project${result.totals.projectsWithHits === 1 ? "" : "s"}.`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return out.slice(0, 5);
|
|
138
|
+
}
|