failproofai 1.0.4-beta.7 → 1.0.4

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 (221) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +5 -5
  3. package/.next/standalone/.next/prerender-manifest.json +4 -4
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
  6. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
  8. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  9. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
  13. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  14. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
  16. package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page.js +2 -2
  18. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  21. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  22. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
  24. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  26. package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
  27. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  32. package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
  33. package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
  34. package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
  35. package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +4 -37
  36. package/.next/standalone/.next/server/app/audit/page.js +2 -2
  37. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/index.html +1 -1
  40. package/.next/standalone/.next/server/app/index.rsc +14 -14
  41. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
  42. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  43. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  44. package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
  45. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  46. package/.next/standalone/.next/server/app/page.js +2 -2
  47. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
  50. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
  51. package/.next/standalone/.next/server/app/policies/page.js +4 -4
  52. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  53. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  54. package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
  55. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  56. package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
  57. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  58. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  59. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
  60. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  61. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  62. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +4 -4
  63. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  64. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  65. package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
  66. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  67. package/.next/standalone/.next/server/app/projects/page.js +3 -3
  68. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  69. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  70. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
  71. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -15
  72. package/.next/standalone/.next/server/app/settings/page.js +4 -4
  73. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
  74. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  75. package/.next/standalone/.next/server/chunks/{[externals]__0v1hz15._.js → [externals]__0-9ti7z._.js} +1 -1
  76. package/.next/standalone/.next/server/chunks/{[externals]__1nb206a._.js → [externals]__0u3wrvq._.js} +1 -1
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p-qi2t._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
  83. package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/{_0otft92._.js → _1-akg6w._.js} +2 -2
  85. package/.next/standalone/.next/server/chunks/_1ek68ln._.js +10 -10
  86. package/.next/standalone/.next/server/chunks/_1vslkoe._.js +1 -1
  87. package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  89. package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
  90. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1fvfw59._.js → [root-of-the-server]__00-s7h8._.js} +1 -1
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +4 -0
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +4 -0
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +4 -0
  94. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__12hbpha._.js → [root-of-the-server]__09flfsx._.js} +2 -2
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +4 -0
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +4 -0
  97. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0kokc8z._.js → [root-of-the-server]__0n_lxhg._.js} +1 -1
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +4 -0
  100. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +6 -0
  101. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0dxf928._.js → [root-of-the-server]__190won8._.js} +1 -1
  102. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0n2txhk._.js → [root-of-the-server]__1ctpynv._.js} +1 -1
  103. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +4 -0
  104. package/.next/standalone/.next/server/chunks/ssr/_02yoeej._.js +3 -0
  105. package/.next/standalone/.next/server/chunks/ssr/{_0a0zlpr._.js → _04rbnaq._.js} +2 -2
  106. package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/{_0s-77v5._.js → _0h_douw._.js} +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/_1_ozgif._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/_1ddpc5g._.js +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +14 -51
  111. package/.next/standalone/.next/server/chunks/ssr/{_07t3jol._.js → _1u8-lu2._.js} +2 -2
  112. package/.next/standalone/.next/server/chunks/ssr/_1ylae7o._.js +3 -0
  113. package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +3 -0
  114. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
  115. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +69 -1
  116. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  117. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  118. package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
  119. package/.next/standalone/.next/server/chunks/ssr/node_modules_13n822a._.js +1 -1
  120. package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +3 -0
  121. package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
  122. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +1 -1
  123. package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
  124. package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
  125. package/.next/standalone/.next/server/pages/404.html +1 -1
  126. package/.next/standalone/.next/server/pages/500.html +1 -1
  127. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  128. package/.next/standalone/.next/server/server-reference-manifest.json +21 -65
  129. package/.next/standalone/.next/static/chunks/{0f1pznnc7zlub.js → 0-tyrpwuc3lla.js} +1 -1
  130. package/.next/standalone/.next/static/chunks/0ca7octhod0g2.js +69 -0
  131. package/.next/standalone/.next/static/chunks/0u64yey446k4f.css +1 -0
  132. package/.next/standalone/.next/static/chunks/{1csubx9gwhsf6.js → 1j6o9min_6qa9.js} +1 -1
  133. package/.next/standalone/.next/static/chunks/27cl8h-c2w7cd.js +1 -0
  134. package/.next/standalone/.next/static/chunks/{0jpd8dv2vk930.css → 29-iqnp9v_axt.css} +1 -1
  135. package/.next/standalone/.next/static/chunks/{3uyhmm01g64k4.css → 2k9f4tyv04809.css} +0 -1
  136. package/.next/standalone/.next/static/chunks/{0t6ea7d3bkmdv.js → 2lwipmv5etc8m.js} +1 -1
  137. package/.next/standalone/.next/static/chunks/2pd16tn5qmx13.js +1 -0
  138. package/.next/standalone/.next/static/chunks/{0ntdfr2552x-h.js → 2u8vh73tpw28_.js} +1 -1
  139. package/.next/standalone/.next/static/chunks/{15uon66hpwbgg.js → 31u94yukw9fz-.js} +1 -1
  140. package/.next/standalone/.next/static/chunks/{2pwfrn6_mw-1u.js → 3p9_8x5ezce-9.js} +1 -1
  141. package/.next/standalone/.next/static/chunks/3qfoeqhy5l10x.js +1 -0
  142. package/.next/standalone/.next/static/chunks/{083fk73jtv9a0.js → 3tjji451hrgc0.js} +1 -1
  143. package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +1 -0
  144. package/.next/standalone/.next/static/chunks/{turbopack-3s3c-u_u_l0u9.js → turbopack-3p73obe0xmrxm.js} +1 -1
  145. package/.next/standalone/.opencode/plugins/failproofai.mjs +27 -51
  146. package/.next/standalone/app/actions/get-scheduled-audit.ts +0 -5
  147. package/.next/standalone/app/actions/update-scheduled-audit.ts +57 -18
  148. package/.next/standalone/app/api/auth/status/route.ts +2 -3
  149. package/.next/standalone/app/audit/_components/audit-dashboard.tsx +34 -140
  150. package/.next/standalone/app/audit/_components/audit-poster.tsx +10 -29
  151. package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -6
  152. package/.next/standalone/app/audit/_components/empty-state.tsx +1 -4
  153. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +5 -19
  154. package/.next/standalone/app/audit/_components/share-templates.ts +44 -110
  155. package/.next/standalone/app/audit/audit-styles.css +1 -132
  156. package/.next/standalone/app/settings/page.tsx +1 -1
  157. package/.next/standalone/app/settings/settings-client.tsx +45 -50
  158. package/.next/standalone/lib/auth/api-server-client.ts +5 -33
  159. package/.next/standalone/lib/claude-sessions.ts +27 -101
  160. package/.next/standalone/lib/codex-sessions.ts +4 -20
  161. package/.next/standalone/lib/copilot-sessions.ts +1 -32
  162. package/.next/standalone/lib/cursor-sessions.ts +5 -62
  163. package/.next/standalone/lib/sqlite-reader.ts +1 -78
  164. package/.next/standalone/package.json +9 -9
  165. package/.next/standalone/server.js +1 -1
  166. package/bin/failproofai.mjs +1 -1
  167. package/dist/cli.mjs +500 -1762
  168. package/dist/worker.mjs +16 -138
  169. package/lib/auth/api-server-client.ts +5 -33
  170. package/lib/claude-sessions.ts +27 -101
  171. package/lib/codex-sessions.ts +4 -20
  172. package/lib/copilot-sessions.ts +1 -32
  173. package/lib/cursor-sessions.ts +5 -62
  174. package/lib/sqlite-reader.ts +1 -78
  175. package/package.json +9 -9
  176. package/pi-extension/index.ts +5 -50
  177. package/src/audit/cache.ts +0 -6
  178. package/src/audit/cli-adapters/claude.ts +0 -13
  179. package/src/audit/cli-login.ts +1 -4
  180. package/src/audit/cli.ts +7 -157
  181. package/src/audit/harm-report.ts +4 -111
  182. package/src/audit/index.ts +15 -286
  183. package/src/audit/machine-store.ts +9 -8
  184. package/src/audit/redact-example.ts +15 -324
  185. package/src/audit/report-harm.ts +37 -33
  186. package/src/audit/report.ts +3 -6
  187. package/src/audit/schedule-cli.ts +33 -54
  188. package/src/audit/scoring.ts +0 -49
  189. package/src/audit/types.ts +0 -52
  190. package/src/hooks/builtin-policies.ts +2 -67
  191. package/src/hooks/configure-wizard.ts +0 -55
  192. package/src/hooks/fp-config.ts +48 -83
  193. package/src/hooks/fp-home.ts +0 -27
  194. package/src/hooks/integrations.ts +14 -51
  195. package/src/hooks/uninstall-cli.ts +2 -17
  196. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-4ja6q._.js +0 -4
  197. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00cr3xu._.js +0 -4
  198. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04px77e._.js +0 -4
  199. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0egr5s1._.js +0 -6
  200. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0i0l1di._.js +0 -4
  201. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0r3c1_0._.js +0 -4
  202. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17xnxlx._.js +0 -4
  203. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ckpmkk._.js +0 -4
  204. package/.next/standalone/.next/server/chunks/ssr/_04ng_6x._.js +0 -3
  205. package/.next/standalone/.next/server/chunks/ssr/_0l2hi_d._.js +0 -3
  206. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_rerun-button_tsx_0blihgw._.js +0 -3
  207. package/.next/standalone/.next/static/chunks/0divvxng208xo.js +0 -1
  208. package/.next/standalone/.next/static/chunks/27du9n7ssja7l.js +0 -1
  209. package/.next/standalone/.next/static/chunks/2h_pcb1y8_jde.js +0 -1
  210. package/.next/standalone/app/actions/get-leaks.ts +0 -104
  211. package/.next/standalone/app/audit/_components/leak-section.tsx +0 -192
  212. package/src/audit/desktop-notify.ts +0 -420
  213. package/src/audit/leak-fingerprint.ts +0 -198
  214. package/src/audit/leak-record.ts +0 -248
  215. package/src/audit/leak-scan.ts +0 -268
  216. package/src/audit/leak-store.ts +0 -220
  217. package/src/audit/macos-notifier.ts +0 -298
  218. package/src/hooks/notice.ts +0 -24
  219. /package/.next/standalone/.next/static/{YiPsVpjrc-pEQoN7XvhZ0 → dg8VQ7Ejlo0Qsh_x92oIt}/_buildManifest.js +0 -0
  220. /package/.next/standalone/.next/static/{YiPsVpjrc-pEQoN7XvhZ0 → dg8VQ7Ejlo0Qsh_x92oIt}/_clientMiddlewareManifest.js +0 -0
  221. /package/.next/standalone/.next/static/{YiPsVpjrc-pEQoN7XvhZ0 → dg8VQ7Ejlo0Qsh_x92oIt}/_ssgManifest.js +0 -0
@@ -4,14 +4,8 @@
4
4
  * Claude stores transcripts at:
5
5
  * <CLAUDE_PROJECTS_PATH>/<encoded-cwd>/<sessionId>.jsonl
6
6
  *
7
- * Subagent transcripts (when a session spawned subagents) live alongside, in two
8
- * shapes — a direct child, and one nested per workflow run:
7
+ * Subagent transcripts (when a session spawned subagents) live alongside:
9
8
  * <CLAUDE_PROJECTS_PATH>/<encoded-cwd>/<sessionId>/subagents/<agentId>.jsonl
10
- * <CLAUDE_PROJECTS_PATH>/<encoded-cwd>/<sessionId>/subagents/workflows/<runId>/<agentId>.jsonl
11
- *
12
- * Everything below `subagents/` is walked to a bounded depth rather than one
13
- * level, because the second shape arrived after this module was written and the
14
- * miss was most of the corpus. See `collectSubagentTranscripts`.
15
9
  *
16
10
  * The parser for these files lives in `lib/log-entries.ts` (`parseLogContent`,
17
11
  * `parseSessionLog`). This module exposes discovery only — the audit pipeline
@@ -76,99 +70,6 @@ export function listClaudeProjects(): ClaudeProjectFolder[] {
76
70
  /** Lists every JSONL transcript under one Claude project folder, including
77
71
  * subagent transcripts under `<sessionId>/subagents/`. Returns [] on missing
78
72
  * or unreadable paths. */
79
- /**
80
- * Depth of nesting allowed below `subagents/`.
81
- *
82
- * The two shapes that exist today need 0 and 2 (`<agent>.jsonl` and
83
- * `workflows/<runId>/<agent>.jsonl`). The cap is here so an unexpected layout —
84
- * or a symlink cycle a future Claude build introduces — costs a bounded walk
85
- * rather than an audit that never returns, and it is deliberately loose enough
86
- * that a third shape lands inside it without another release.
87
- */
88
- const MAX_SUBAGENT_DEPTH = 5;
89
-
90
- /**
91
- * Collect every `.jsonl` beneath a session's `subagents/` directory.
92
- *
93
- * This used to read only the DIRECT children of `subagents/`, which was correct
94
- * for the layout Claude shipped when it was written and silently wrong the day
95
- * workflow runs started nesting their agents one level further down. On a
96
- * machine that uses them the miss is most of the corpus: 1,839 transcripts on
97
- * disk, 1,741 under `subagents/`, and 1,679 of those inside
98
- * `subagents/workflows/<runId>/` — so the audit was walking 160 files, 8.7% of
99
- * the evidence, and reporting the result as though it had read everything.
100
- *
101
- * ## Session ids come from the relative path, not the basename
102
- *
103
- * Every workflow run writes a `journal.jsonl` beside its agents, so basenames
104
- * are NOT unique below this directory — 1,741 files share 1,613 distinct names
105
- * on the machine this was found on. A basename id would collide those 128 files
106
- * onto ~one row each, and `sessionId` is what the cache, the per-session
107
- * detector state and the example attribution are keyed by, so the collision
108
- * would silently merge unrelated sessions rather than fail.
109
- *
110
- * Nor is the path below `subagents/` unique on its own. A workflow run id is
111
- * reused when its session is resumed, so `wf_3d609e92-a38/journal.jsonl` exists
112
- * under two different parent sessions in the same project — found by asserting
113
- * uniqueness over the real corpus, not by reasoning about it.
114
- *
115
- * The id is therefore the PARENT SESSION id followed by the path relative to
116
- * `subagents/`, minus the extension, joined with `__`:
117
- * `<parentUuid>__workflows__wf_123__agent-abc`. That is a filesystem path
118
- * within the project, so it is unique by construction rather than by argument,
119
- * and it names the session the subagent belongs to. `__` is safe as the joiner
120
- * because no id Claude generates contains one — verified against 1,741 real
121
- * files, zero hits. Top-level session ids are untouched.
122
- *
123
- * Symlinks are not followed. Nothing in the layout uses them, and following one
124
- * is how a directory walk turns into an infinite loop.
125
- */
126
- function collectSubagentTranscripts(
127
- dir: string,
128
- relPrefix: string,
129
- project: ClaudeProjectFolder,
130
- out: ClaudeTranscriptFile[],
131
- depth: number,
132
- ): void {
133
- if (depth > MAX_SUBAGENT_DEPTH) return;
134
- let entries: import("node:fs").Dirent[];
135
- try {
136
- entries = readdirSync(dir, { withFileTypes: true });
137
- } catch {
138
- return;
139
- }
140
- for (const entry of entries) {
141
- if (entry.isSymbolicLink()) continue;
142
- if (entry.isDirectory()) {
143
- collectSubagentTranscripts(
144
- join(dir, entry.name),
145
- relPrefix ? `${relPrefix}__${entry.name}` : entry.name,
146
- project,
147
- out,
148
- depth + 1,
149
- );
150
- continue;
151
- }
152
- if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
153
- const stem = entry.name.slice(0, -".jsonl".length);
154
- const transcriptPath = join(dir, entry.name);
155
- try {
156
- const s = statSync(transcriptPath);
157
- out.push({
158
- projectName: project.name,
159
- cwd: project.cwd,
160
- sessionId: relPrefix ? `${relPrefix}__${stem}` : stem,
161
- transcriptPath,
162
- mtimeMs: s.mtimeMs,
163
- sizeBytes: s.size,
164
- isSubagent: true,
165
- });
166
- } catch {
167
- // unreadable — skip
168
- }
169
- }
170
- }
171
-
172
73
  export function listClaudeTranscripts(project: ClaudeProjectFolder): ClaudeTranscriptFile[] {
173
74
  const out: ClaudeTranscriptFile[] = [];
174
75
  let entries: import("node:fs").Dirent[];
@@ -198,9 +99,34 @@ export function listClaudeTranscripts(project: ClaudeProjectFolder): ClaudeTrans
198
99
  // unreadable — skip
199
100
  }
200
101
  } else if (entry.isDirectory() && UUID_RE.test(entry.name)) {
102
+ // Subagent transcripts at <sessionId>/subagents/<agentId>.jsonl
201
103
  const subDir = join(project.path, entry.name, "subagents");
202
104
  if (!existsSync(subDir)) continue;
203
- collectSubagentTranscripts(subDir, entry.name, project, out, 0);
105
+ let subEntries: import("node:fs").Dirent[];
106
+ try {
107
+ subEntries = readdirSync(subDir, { withFileTypes: true });
108
+ } catch {
109
+ continue;
110
+ }
111
+ for (const sub of subEntries) {
112
+ if (!sub.isFile() || !sub.name.endsWith(".jsonl")) continue;
113
+ const agentId = sub.name.slice(0, -".jsonl".length);
114
+ const transcriptPath = join(subDir, sub.name);
115
+ try {
116
+ const s = statSync(transcriptPath);
117
+ out.push({
118
+ projectName: project.name,
119
+ cwd: project.cwd,
120
+ sessionId: agentId,
121
+ transcriptPath,
122
+ mtimeMs: s.mtimeMs,
123
+ sizeBytes: s.size,
124
+ isSubagent: true,
125
+ });
126
+ } catch {
127
+ // unreadable — skip
128
+ }
129
+ }
204
130
  }
205
131
  }
206
132
 
@@ -158,21 +158,6 @@ function joinTexts(blocks: CodexContentBlock[] | undefined, wantedType: "input_t
158
158
  .join("\n");
159
159
  }
160
160
 
161
- /** Text carried by tool outputs. Newer Codex chronicles use an array of
162
- * `input_text` blocks for `custom_tool_call_output`, while older releases use
163
- * one string for `function_call_output`. */
164
- function toolOutputText(output: unknown): string {
165
- if (typeof output === "string") return output;
166
- if (Array.isArray(output)) {
167
- return output
168
- .filter((block): block is CodexContentBlock => !!block && typeof block === "object")
169
- .map((block) => typeof block.text === "string" ? block.text : "")
170
- .filter(Boolean)
171
- .join("\n");
172
- }
173
- return output === undefined ? "" : JSON.stringify(output);
174
- }
175
-
176
161
  /**
177
162
  * Parse a Codex JSONL transcript into `LogEntry[]` plus the raw lines.
178
163
  * Yields to the event loop every 200 lines so big transcripts don't block.
@@ -265,11 +250,10 @@ export async function parseCodexLog(
265
250
  continue;
266
251
  }
267
252
 
268
- if (subType === "function_call" || subType === "custom_tool_call") {
253
+ if (subType === "function_call") {
269
254
  const callId = payload.call_id as string | undefined;
270
255
  const name = (payload.name as string | undefined) ?? "function_call";
271
- const encodedInput = (payload.arguments ?? payload.input) as string | undefined;
272
- const input = safeJsonParse(encodedInput);
256
+ const input = safeJsonParse(payload.arguments as string | undefined);
273
257
  const toolUse: ToolUseBlock = {
274
258
  type: "tool_use",
275
259
  id: callId ?? `${timestamp}-${name}`,
@@ -289,7 +273,7 @@ export async function parseCodexLog(
289
273
  continue;
290
274
  }
291
275
 
292
- if (subType === "function_call_output" || subType === "custom_tool_call_output") {
276
+ if (subType === "function_call_output") {
293
277
  const callId = payload.call_id as string | undefined;
294
278
  const block = callId ? toolUseById.get(callId) : undefined;
295
279
  if (block) {
@@ -298,7 +282,7 @@ export async function parseCodexLog(
298
282
  block.result = {
299
283
  timestamp,
300
284
  timestampFormatted: formatTimestamp(date),
301
- content: toolOutputText(payload.output),
285
+ content: typeof payload.output === "string" ? (payload.output as string) : JSON.stringify(payload.output),
302
286
  durationMs: duration,
303
287
  durationFormatted: formatDuration(duration),
304
288
  };
@@ -151,11 +151,6 @@ interface CopilotToolResult {
151
151
  detailedContent?: string;
152
152
  }
153
153
 
154
- interface CopilotHookToolResult {
155
- textResultForLlm?: string;
156
- sessionLog?: string;
157
- }
158
-
159
154
  interface CopilotToolTelemetry {
160
155
  metrics?: { commandTimeMs?: number; durationMs?: number };
161
156
  properties?: Record<string, unknown>;
@@ -176,8 +171,6 @@ export async function parseCopilotLog(
176
171
  // toolCallId → tool_use block, so we can attach tool.execution_complete back.
177
172
  const toolUseById = new Map<string, ToolUseBlock>();
178
173
  const toolUseStartMs = new Map<string, number>();
179
- let mostRecentToolUse: ToolUseBlock | undefined;
180
- let mostRecentToolUseStartMs = 0;
181
174
  let cwd: string | undefined;
182
175
  let seenSessionStart = false;
183
176
 
@@ -280,32 +273,9 @@ export async function parseCopilotLog(
280
273
  toolUseById.set(callId, toolUse);
281
274
  toolUseStartMs.set(callId, date.getTime());
282
275
  }
283
- mostRecentToolUse = toolUse;
284
- mostRecentToolUseStartMs = date.getTime();
285
276
  continue;
286
277
  }
287
278
 
288
- // Copilot CLI 1.0.39 can omit the command's real stdout from
289
- // `tool.execution_complete` and expose it only to the PostToolUse hook as
290
- // `input.toolResult.textResultForLlm`. That is the value the model saw and
291
- // the value failproofai must audit. Keep it on the active tool block; the
292
- // later completion record may still contribute timing, but must not replace
293
- // this output with its shorter status-only summary.
294
- if (recType === "hook.start" && data.hookType === "postToolUse" && mostRecentToolUse) {
295
- const input = (data.input as Record<string, unknown> | undefined) ?? {};
296
- const hookResult = (input.toolResult as CopilotHookToolResult | undefined) ?? {};
297
- const hookContent = hookResult.textResultForLlm ?? hookResult.sessionLog;
298
- if (typeof hookContent === "string" && hookContent.length > 0) {
299
- mostRecentToolUse.result = {
300
- timestamp,
301
- timestampFormatted: formatTimestamp(date),
302
- content: hookContent,
303
- durationMs: Math.max(0, date.getTime() - mostRecentToolUseStartMs),
304
- durationFormatted: formatDuration(Math.max(0, date.getTime() - mostRecentToolUseStartMs)),
305
- };
306
- }
307
- }
308
-
309
279
  if (recType === "tool.execution_complete") {
310
280
  const callId = data.toolCallId as string | undefined;
311
281
  const block = callId ? toolUseById.get(callId) : undefined;
@@ -319,8 +289,7 @@ export async function parseCopilotLog(
319
289
  typeof reportedMs === "number" && reportedMs >= 0
320
290
  ? reportedMs
321
291
  : Math.max(0, date.getTime() - startMs);
322
- const completionContent = result.detailedContent ?? result.content ?? "";
323
- const content = block.result?.content || completionContent;
292
+ const content = result.detailedContent ?? result.content ?? "";
324
293
  block.result = {
325
294
  timestamp,
326
295
  timestampFormatted: formatTimestamp(date),
@@ -127,15 +127,7 @@ interface CursorRecord {
127
127
  /** Cursor 2026-04+ transcript shape: `{role, message: {content: [...]}}`. */
128
128
  role?: "user" | "assistant" | "system" | string;
129
129
  message?: {
130
- content?: Array<{
131
- type?: string;
132
- text?: string;
133
- id?: string;
134
- name?: string;
135
- input?: Record<string, unknown>;
136
- tool_use_id?: string;
137
- content?: unknown;
138
- }>;
130
+ content?: Array<{ type?: string; text?: string }>;
139
131
  };
140
132
  }
141
133
 
@@ -191,36 +183,11 @@ export async function parseCursorLog(
191
183
  if (!raw.type && raw.role && raw.message?.content) {
192
184
  const synthDate = new Date(SYNTH_T0 + i);
193
185
  const synthTs = synthDate.toISOString();
194
- const messageContent = raw.message.content;
195
- const textParts = messageContent
186
+ const textParts = raw.message.content
196
187
  .filter((c) => c?.type === "text" && typeof c.text === "string")
197
188
  .map((c) => c.text!)
198
189
  .join("");
199
190
  if (raw.role === "user") {
200
- // Some Cursor builds emit Claude-style tool_result blocks in the next
201
- // user record. Pair them before treating any remaining text as a user
202
- // turn so command output is available to the credential scanner.
203
- let attachedResult = false;
204
- for (const block of messageContent) {
205
- if (block?.type !== "tool_result") continue;
206
- const callId = typeof block.tool_use_id === "string" ? block.tool_use_id : undefined;
207
- const toolUse = callId ? toolUseById.get(callId) : undefined;
208
- if (!toolUse) continue;
209
- const durationMs = Math.max(
210
- 0,
211
- synthDate.getTime() - (toolUseStartMs.get(callId!) ?? synthDate.getTime()),
212
- );
213
- toolUse.result = {
214
- timestamp: synthTs,
215
- timestampFormatted: formatTimestamp(synthDate),
216
- content: typeof block.content === "string"
217
- ? block.content
218
- : block.content == null ? "" : JSON.stringify(block.content),
219
- durationMs,
220
- durationFormatted: formatDuration(durationMs),
221
- };
222
- attachedResult = true;
223
- }
224
191
  // Strip the synthesized `<timestamp>...</timestamp>\n<user_query>...\n</user_query>`
225
192
  // wrapper Cursor adds for context — keep just the user_query body.
226
193
  const queryMatch = /<user_query>\s*([\s\S]*?)\s*<\/user_query>/.exec(textParts);
@@ -231,37 +198,13 @@ export async function parseCursorLog(
231
198
  ...baseEntry(rawCopy, synthTs, synthDate, source),
232
199
  message: { role: "user", content: text },
233
200
  } satisfies UserEntry);
234
- } else if (!attachedResult) {
235
- entries.push({
236
- type: "system",
237
- ...baseEntry(rawCopy, synthTs, synthDate, source),
238
- raw: rawCopy,
239
- } satisfies GenericEntry);
240
201
  }
241
202
  continue;
242
203
  }
243
204
  if (raw.role === "assistant") {
244
- const blocks: ContentBlock[] = [];
245
- if (textParts) blocks.push({ type: "text", text: textParts });
246
- for (let j = 0; j < messageContent.length; j++) {
247
- const contentBlock = messageContent[j];
248
- if (contentBlock?.type !== "tool_use") continue;
249
- const name = typeof contentBlock.name === "string" ? contentBlock.name : "tool";
250
- const id = typeof contentBlock.id === "string" && contentBlock.id
251
- ? contentBlock.id
252
- : `cursor-${i}-${name}-${j}`;
253
- const toolUse: ToolUseBlock = {
254
- type: "tool_use",
255
- id,
256
- name,
257
- input: contentBlock.input && typeof contentBlock.input === "object"
258
- ? contentBlock.input
259
- : {},
260
- };
261
- blocks.push(toolUse);
262
- toolUseById.set(id, toolUse);
263
- toolUseStartMs.set(id, synthDate.getTime());
264
- }
205
+ const blocks: ContentBlock[] = textParts
206
+ ? [{ type: "text", text: textParts }]
207
+ : [];
265
208
  if (blocks.length === 0) {
266
209
  entries.push({
267
210
  type: "system",
@@ -39,42 +39,8 @@ interface NodeSqliteModule {
39
39
  DatabaseSync: new (path: string, options?: { readOnly?: boolean }) => NodeSqliteDb;
40
40
  }
41
41
 
42
- /**
43
- * Swallow Node's "SQLite is an experimental feature" warning, once.
44
- *
45
- * It is not information the user can act on — we chose `node:sqlite`
46
- * deliberately, and the alternative tier is a WASM build that leaks. But it is
47
- * emitted on first use, which lands it in the MIDDLE of whatever is on screen,
48
- * and the audit's progress display redraws itself by moving the cursor up a
49
- * fixed number of lines. Two unexpected lines of stderr push the cursor down
50
- * two rows, so the next redraw repaints the block two rows lower and strands
51
- * the top of the previous frame above it. The user sees every stage twice and
52
- * reasonably concludes the audit ran twice.
53
- *
54
- * Filtered by message rather than silenced wholesale: `process.emitWarning` is
55
- * how deprecations and real problems surface too, and a blanket
56
- * `NODE_NO_WARNINGS` in a tool that installs into other people's machines would
57
- * hide those as well.
58
- */
59
- let warningPatched = false;
60
- function silenceSqliteExperimentalWarning(): void {
61
- if (warningPatched) return;
62
- warningPatched = true;
63
- const original = process.emitWarning.bind(process);
64
- // The overloads differ across Node versions; the shape we care about is the
65
- // first argument, and everything else is passed straight through.
66
- process.emitWarning = ((warning: unknown, ...rest: unknown[]) => {
67
- const text = typeof warning === "string" ? warning : String((warning as Error)?.message ?? "");
68
- if (text.includes("SQLite is an experimental feature")) return;
69
- return (original as (...a: unknown[]) => void)(warning, ...rest);
70
- }) as typeof process.emitWarning;
71
- }
72
-
73
42
  async function tryNodeSqlite(dbPath: string): Promise<SqliteReader | null> {
74
43
  try {
75
- // Before the import, not after: the warning fires on first use of the
76
- // module, which is this line.
77
- silenceSqliteExperimentalWarning();
78
44
  // Dynamic import: on Node < 22.5 this rejects and we fall through to sql.js.
79
45
  const mod = (await import("node:sqlite")) as unknown as NodeSqliteModule;
80
46
  const db = new mod.DatabaseSync(dbPath, { readOnly: true });
@@ -100,53 +66,10 @@ function loadSqlJs(): Promise<SqlJsStatic> {
100
66
  return sqlPromise;
101
67
  }
102
68
 
103
- const SQLITE_MAGIC = "SQLite format 3\0";
104
-
105
- /**
106
- * Clear the WAL flag on OUR OWN in-memory copy of the database image.
107
- *
108
- * Header bytes 18 and 19 are the file-format write and read versions; `2`
109
- * means WAL. sql.js never sees the `-wal` sidecar — it is handed the main
110
- * file's bytes and nothing else, which is exactly the snapshot caveat this
111
- * module already documents — so the flag buys us nothing, and it costs a great
112
- * deal: opening a WAL-flagged image makes SQLite build a wal-index
113
- * shared-memory region that sql.js's MEMFS-backed VFS never reclaims on
114
- * `close()` (close unlinks only the db file it created).
115
- *
116
- * The asm.js build's heap is a FIXED 22,151,168-byte ArrayBuffer with
117
- * ALLOW_MEMORY_GROWTH off, so `emscripten_resize_heap` is compiled to
118
- * `abort("OOM")`. Measured: the 128th WAL-mode open exhausts it — the same
119
- * threshold for a 319 KB database and a 10 MB one, because the leaked region
120
- * is a fixed per-connection allocation rather than data.
121
- *
122
- * And the abort is not confined to that open. `initSqlJs` memoizes one
123
- * process-wide module, so once it aborts every later `openSqliteReadonly`
124
- * silently returns null. A full audit opens ~150 databases — devin, goose and
125
- * opencode each open theirs once per SESSION — so it crossed 128 and then
126
- * dropped whatever it had not yet read, with no error anywhere. The
127
- * `Aborted(OOM)` lines on stderr were the only symptom, and they read as
128
- * harmless because the run still completed.
129
- *
130
- * Only under bun and Node < 22.5: tier 1 is `node:sqlite`, which bun does not
131
- * provide, and `engines.node` allows 20.9. Both fall through to here.
132
- */
133
- function clearWalFlag(bytes: Buffer): Buffer {
134
- // Too short to carry a header, or not a SQLite image at all — hand it back
135
- // untouched and let sql.js produce its own error.
136
- if (bytes.length < 20) return bytes;
137
- if (bytes.toString("latin1", 0, 16) !== SQLITE_MAGIC) return bytes;
138
- if (bytes[18] === 1 && bytes[19] === 1) return bytes; // already rollback-journal
139
- bytes[18] = 1;
140
- bytes[19] = 1;
141
- return bytes;
142
- }
143
-
144
69
  async function trySqlJs(dbPath: string): Promise<SqliteReader | null> {
145
70
  try {
146
71
  const SQL = await loadSqlJs();
147
- // `readFileSync` already returns a private copy, so mutating the two header
148
- // bytes cannot touch the file on disk.
149
- const db = new SQL.Database(clearWalFlag(readFileSync(dbPath)));
72
+ const db = new SQL.Database(readFileSync(dbPath));
150
73
  return {
151
74
  query<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[] {
152
75
  const stmt = db.prepare(sql);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "1.0.4-beta.7",
3
+ "version": "1.0.4",
4
4
  "description": "Observability and enforcement for AI agent harnesses. 39 built-in policies hooked into 12 of them — Claude Code, Codex, Cursor, Hermes, OpenClaw and more — blocking the tool call before it runs. Local dashboard included, no account needed.",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs",
@@ -121,15 +121,15 @@
121
121
  "browserslist": "4.28.8"
122
122
  },
123
123
  "optionalDependencies": {
124
- "@failproofai/failproofaid-linux-x64": "1.0.4-beta.7",
125
- "@failproofai/failproofaid-linux-arm64": "1.0.4-beta.7",
126
- "@failproofai/failproofaid-darwin-x64": "1.0.4-beta.7",
127
- "@failproofai/failproofaid-darwin-arm64": "1.0.4-beta.7"
124
+ "@failproofai/failproofaid-linux-x64": "1.0.4",
125
+ "@failproofai/failproofaid-linux-arm64": "1.0.4",
126
+ "@failproofai/failproofaid-darwin-x64": "1.0.4",
127
+ "@failproofai/failproofaid-darwin-arm64": "1.0.4"
128
128
  },
129
129
  "failproofaidBinaries": {
130
- "linux-x64": "e59735a8f94cd8ac697b2bd67aafdd8d76a8394d53db229876980cc13a18f07e",
131
- "linux-arm64": "b9ce50dd2f79b55f4f7112add265a776a4a6d002c2a56f971e666fbb796f3906",
132
- "darwin-x64": "b46efc8ec33945a5cc26b7bb288fb87cea65b5983bd83094b5e607d53b8eda4c",
133
- "darwin-arm64": "a8cc6112cee5ca8a7d517900e9ce32118855135980f22979fa0ff7aa6f68d954"
130
+ "linux-x64": "cca1d41ff951784ba084bf2d72cfad0fe8d988f8226e0e7a4538b1fb8d76a5bd",
131
+ "linux-arm64": "55e9c1e2864cbf6057fd0c27e4bc573ca8fba2cd35d480a3db3a55d398e7bec0",
132
+ "darwin-x64": "2a46ec77d2cac14a036f35e832f92f16895239814a5f10f02121f3c313e70574",
133
+ "darwin-arm64": "a0e7ccc6fe24e1017592637192ba8a26c9d05ca839c98bc72a983094c863b39b"
134
134
  }
135
135
  }
@@ -9,7 +9,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
9
9
  const hostname = process.env.HOSTNAME || '0.0.0.0'
10
10
 
11
11
  let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
12
- const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.4-beta.7"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"instrumentationClientInject":[],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","enablePrerenderSourceMaps":true,"cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":true,"coldCacheBadge":false,"devValidationWorker":true,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"dynamicOnHover":false,"useOffline":false,"varyParams":true,"optimisticRouting":true,"instrumentationClientRouterTransitionEvents":false,"prefetchInlining":{"maxSize":2048,"maxBundleSize":10240},"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptOperationCache":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"devMemoryThresholdRestart":true,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"requestInsights":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":true,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":true,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"serverComponentsHmrCancellation":false,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":true,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","turbopackMemoryEvictionMode":"auto","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"useCacheTimeout":54,"instantInsights":{"validationLevel":"warning"},"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","outputFileTracingExcludes":{"*":["node_modules/@img/**","node_modules/sharp/**"]},"turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"repoRoot":"/home/runner/work/failproofai/failproofai","distDirRoot":".next"}
12
+ const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"1.0.4"},"typescript":{"ignoreBuildErrors":false},"typedRoutes":false,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"instrumentationClientInject":[],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":true,"customCacheHandler":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{"serverFunctions":true,"browserToTerminal":"warn"},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/failproofai/failproofai","enablePrerenderSourceMaps":true,"cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"appNewScrollHandler":true,"coldCacheBadge":false,"devValidationWorker":true,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"dynamicOnHover":false,"useOffline":false,"varyParams":true,"optimisticRouting":true,"instrumentationClientRouterTransitionEvents":false,"prefetchInlining":{"maxSize":2048,"maxBundleSize":10240},"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptOperationCache":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"devMemoryThresholdRestart":true,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"requestInsights":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":true,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":true,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"serverComponentsHmrCancellation":false,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"gestureTransition":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":"warn","lockDistDir":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":true,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","turbopackMemoryEvictionMode":"auto","optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"useCacheTimeout":54,"instantInsights":{"validationLevel":"warning"},"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","outputFileTracingExcludes":{"*":["node_modules/@img/**","node_modules/sharp/**"]},"turbopack":{"root":"/home/runner/work/failproofai/failproofai"},"repoRoot":"/home/runner/work/failproofai/failproofai","distDirRoot":".next"}
13
13
 
14
14
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
15
15
 
@@ -481,7 +481,7 @@ async function runCli() {
481
481
  label: "see what it caught",
482
482
  entries: [
483
483
  ["(no args)", "Open the policy dashboard on localhost:8020"],
484
- ["audit", "Find credentials your agents leaked, and get told about it"],
484
+ ["audit", "Scan your agents' history, then open the audit view"],
485
485
  ["config --status", "Cloud connection, daemon version, pause state"],
486
486
  ],
487
487
  },