failproofai 0.0.14-beta.1 → 0.0.14

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 (174) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/prerender-manifest.json +3 -3
  4. package/.next/standalone/.next/required-server-files.json +1 -1
  5. package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
  6. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  7. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
  10. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  11. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  12. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  13. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  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/server-reference-manifest.json +1 -1
  16. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  17. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  18. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  19. package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
  20. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  21. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  22. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +9 -9
  23. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  24. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  25. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  26. package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
  30. package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
  31. package/.next/standalone/.next/server/app/api/auth/reminder/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/server-reference-manifest.json +2 -2
  35. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  36. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  37. package/.next/standalone/.next/server/app/index.html +1 -1
  38. package/.next/standalone/.next/server/app/index.rsc +14 -14
  39. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  40. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  41. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  42. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +9 -9
  43. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  44. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  45. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  46. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  47. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
  48. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  49. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  50. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  51. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  52. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  53. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  54. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  55. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  56. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  57. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  58. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  59. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  60. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0--lkk6._.js +1 -1
  61. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +1 -1
  62. package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +1 -1
  63. package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +1 -1
  64. package/.next/standalone/.next/server/chunks/[root-of-the-server]__08w4wmd._.js +1 -1
  65. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g6bbuw._.js +1 -1
  66. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +1 -1
  67. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
  68. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q0qzx1._.js +1 -1
  69. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q2nbsl._.js +1 -1
  70. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
  71. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16le-kd._.js +1 -1
  72. package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
  73. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ffkmds._.js +1 -1
  74. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
  75. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
  76. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mrihkj._.js +1 -1
  77. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
  78. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qb590j._.js +1 -1
  79. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +1 -1
  80. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1shcqgr._.js +1 -1
  81. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xuedea._.js +1 -1
  82. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +4 -4
  83. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
  84. package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
  85. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  86. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__015_i4t._.js +2 -2
  87. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__030k0c6._.js +1 -1
  88. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03lv-pe._.js +2 -2
  89. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__05r_17v._.js +1 -1
  90. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e2l3c1._.js +1 -1
  91. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hci7t3._.js +1 -1
  92. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hdsupo._.js +2 -2
  93. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p84xee._.js +1 -1
  94. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qeuy9c._.js +2 -2
  95. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s89hoe._.js +2 -2
  96. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ynf7tx._.js +2 -2
  97. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0brjczq._.js → [root-of-the-server]__0zf8xlq._.js} +2 -2
  98. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +1 -1
  99. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17ai7sy._.js +2 -2
  100. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +1 -1
  101. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0wp9w6i._.js → [root-of-the-server]__1s2b6h0._.js} +2 -2
  102. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tkjqka._.js +2 -2
  103. package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
  104. package/.next/standalone/.next/server/chunks/ssr/_1kje4fm._.js +1 -1
  105. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
  106. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  107. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
  108. package/.next/standalone/.next/server/chunks/ssr/lib_0xkhw_v._.js +1 -1
  109. package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_12rjfea.js → node_modules_html-to-image_es_index_0gkzjaa.js} +1 -1
  110. package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
  111. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
  112. package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
  113. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  114. package/.next/standalone/.next/server/pages/404.html +1 -1
  115. package/.next/standalone/.next/server/pages/500.html +1 -1
  116. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  117. package/.next/standalone/.next/server/server-reference-manifest.json +10 -10
  118. package/.next/standalone/.next/static/chunks/06z_ex1ts3n4s.js +1 -0
  119. package/.next/standalone/.next/static/chunks/0o0ut0ugd0_-s.js +1 -0
  120. package/.next/standalone/.next/static/chunks/0xl97x-874k-u.js +1 -0
  121. package/.next/standalone/.next/static/chunks/19d7hqx8udopz.js +1 -0
  122. package/.next/standalone/.next/static/chunks/{0emg30_6svycu.js → 29o4j32z643_a.js} +1 -1
  123. package/.next/standalone/.next/static/chunks/{1359o5785rmve.js → 2uh_4k4m296z5.js} +2 -2
  124. package/.next/standalone/.next/static/chunks/370sj2lgkw5ey.js +1 -0
  125. package/.next/standalone/.next/static/chunks/{0d5lypu1zs21r.js → 3s8aaig91937v.js} +1 -1
  126. package/.next/standalone/.next/static/chunks/3w7g0n0iwwnbs.js +1 -0
  127. package/.next/standalone/.next/static/chunks/{0o9wpnze1ey8y.js → 42oeva1-w0z2d.js} +1 -1
  128. package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +11 -2
  129. package/.next/standalone/app/components/copy-button.tsx +22 -6
  130. package/.next/standalone/app/components/log-viewer/entry-row.tsx +8 -3
  131. package/.next/standalone/app/components/raw-log-viewer.tsx +33 -15
  132. package/.next/standalone/app/policies/hooks-client.tsx +1 -1
  133. package/.next/standalone/{ci/cli-integration → integration-suite}/README.md +25 -7
  134. package/.next/standalone/integration-suite/ci-entrypoint.sh +164 -0
  135. package/.next/standalone/{ci/cli-integration → integration-suite}/run.sh +4 -4
  136. package/.next/standalone/lib/entry-keys.ts +36 -0
  137. package/.next/standalone/lib/format-duration.ts +23 -9
  138. package/.next/standalone/package.json +5 -4
  139. package/.next/standalone/server.js +1 -1
  140. package/dist/cli.mjs +342 -106
  141. package/lib/entry-keys.ts +36 -0
  142. package/lib/format-duration.ts +23 -9
  143. package/package.json +5 -4
  144. package/scripts/translate-docs/cli.ts +6 -0
  145. package/scripts/translate-docs/mdx-translator.ts +30 -19
  146. package/scripts/translate-docs/readme-translator.ts +31 -21
  147. package/scripts/translate-docs/translator.ts +142 -7
  148. package/scripts/translate-docs/types.ts +6 -0
  149. package/scripts/translate-docs/validate-translation.ts +132 -0
  150. package/scripts/validate-mdx.ts +80 -11
  151. package/src/audit/cli.ts +12 -6
  152. package/src/auth/cli.ts +14 -5
  153. package/src/hooks/builtin-policies.ts +168 -50
  154. package/src/hooks/configure-wizard.ts +238 -22
  155. package/src/hooks/custom-hooks-loader.ts +70 -4
  156. package/src/hooks/handler.ts +4 -1
  157. package/src/hooks/policy-types.ts +8 -0
  158. package/src/hooks/tui.ts +95 -28
  159. package/.next/standalone/.next/static/chunks/20tuctw38jbgw.js +0 -1
  160. package/.next/standalone/.next/static/chunks/2ldhnaweu9ew3.js +0 -1
  161. package/.next/standalone/.next/static/chunks/2vav_x0_336ds.js +0 -1
  162. package/.next/standalone/.next/static/chunks/3cg7x0joi2b98.js +0 -1
  163. package/.next/standalone/.next/static/chunks/3k87p-tijud-4.js +0 -1
  164. package/.next/standalone/.next/static/chunks/3kmaqcp7rldad.js +0 -1
  165. /package/.next/standalone/.next/static/{LkN-JjmhKGmL-WklH7WVi → WQRKgSfFekLcC_pvyzp4S}/_buildManifest.js +0 -0
  166. /package/.next/standalone/.next/static/{LkN-JjmhKGmL-WklH7WVi → WQRKgSfFekLcC_pvyzp4S}/_clientMiddlewareManifest.js +0 -0
  167. /package/.next/standalone/.next/static/{LkN-JjmhKGmL-WklH7WVi → WQRKgSfFekLcC_pvyzp4S}/_ssgManifest.js +0 -0
  168. /package/.next/standalone/{ci/cli-integration → integration-suite}/Dockerfile +0 -0
  169. /package/.next/standalone/{ci/cli-integration → integration-suite}/canary-policies.mjs +0 -0
  170. /package/.next/standalone/{ci/cli-integration → integration-suite}/capture-tokens.sh +0 -0
  171. /package/.next/standalone/{ci/cli-integration → integration-suite}/inject-tokens.sh +0 -0
  172. /package/.next/standalone/{ci/cli-integration → integration-suite}/install-clis.sh +0 -0
  173. /package/.next/standalone/{ci/cli-integration → integration-suite}/probe-cli.sh +0 -0
  174. /package/.next/standalone/{ci/cli-integration → integration-suite}/report.js +0 -0
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,8734,89664,e=>{"use strict";var t=e.i(56420);let s=(0,t.default)("copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);e.s(["Copy",0,s],8734);let a=(0,t.default)("check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);e.s(["Check",0,a],89664)},24380,e=>{"use strict";var t=e.i(43476),s=e.i(71645),a=e.i(8734),r=e.i(89664),l=e.i(47163);function n(e){let t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t);try{return t.select(),document.execCommand("copy")}finally{document.body.removeChild(t)}}e.s(["CopyButton",0,function({text:e,className:i}){let[o,d]=(0,s.useState)(!1),c=(0,s.useRef)(void 0);(0,s.useEffect)(()=>()=>{c.current&&clearTimeout(c.current)},[]);let u=(0,s.useCallback)(()=>{c.current&&clearTimeout(c.current),d(!0),c.current=setTimeout(()=>d(!1),2e3)},[]),m=(0,s.useCallback)(async()=>{try{if(navigator.clipboard?.writeText)await navigator.clipboard.writeText(e);else if(!n(e))throw Error("Both clipboard methods failed");u()}catch(t){console.error("Failed to copy to clipboard:",t);try{n(e)&&u()}catch{}}},[e,u]);return(0,t.jsx)("button",{type:"button",onClick:m,title:"Copy to clipboard",className:(0,l.cn)("inline-flex items-center justify-center rounded p-1 text-muted-foreground hover:text-foreground hover:bg-muted/80 transition-colors",i),children:o?(0,t.jsx)(r.Check,{className:"w-3.5 h-3.5 text-green-500"}):(0,t.jsx)(a.Copy,{className:"w-3.5 h-3.5"})})}])},24071,e=>{"use strict";let t=(0,e.i(56420).default)("chevron-left",[["path",{d:"m15 18-6-6 6-6",key:"1wnfg3"}]]);e.s(["ChevronLeft",0,t],24071)},67927,e=>{"use strict";let t=(0,e.i(56420).default)("chevron-right",[["path",{d:"m9 18 6-6-6-6",key:"mthhwq"}]]);e.s(["ChevronRight",0,t],67927)},73520,e=>{"use strict";var t=e.i(43476),s=e.i(24071),a=e.i(67927);e.s(["default",0,function({currentPage:e,totalPages:r,onPageChange:l}){if(r<=1)return null;let n=e=>`px-3 py-2 text-sm rounded-md transition-colors flex items-center gap-1 bg-muted text-muted-foreground ${e?"opacity-50 cursor-not-allowed":"hover:bg-muted/80"}`;return(0,t.jsxs)("div",{className:"flex items-center justify-center gap-2 py-4",children:[(0,t.jsxs)("button",{onClick:()=>l(e-1),disabled:1===e,className:n(1===e),"aria-label":"Previous page",children:[(0,t.jsx)(s.ChevronLeft,{className:"w-4 h-4"}),(0,t.jsx)("span",{className:"hidden sm:inline",children:"Previous"})]}),(0,t.jsx)("div",{className:"flex items-center gap-1",children:(()=>{if(r<=7)return Array.from({length:r},(e,t)=>t+1);let t=[1],s=Math.max(2,e-1),a=Math.min(r-1,e+1);e<=3&&(a=Math.min(5,r-1)),e>=r-2&&(s=Math.max(2,r-4)),s>2&&t.push("ellipsis-start");for(let e=s;e<=a;e++)t.push(e);return a<r-1&&t.push("ellipsis-end"),t.push(r),t})().map(s=>"string"==typeof s?(0,t.jsx)("span",{className:"px-2 text-muted-foreground",children:"..."},s):(0,t.jsx)("button",{onClick:()=>l(s),className:`min-w-[2.5rem] px-3 py-2 text-sm rounded-md transition-colors ${e===s?"bg-primary text-primary-foreground":"bg-muted text-muted-foreground hover:bg-muted/80"}`,"aria-label":`Page ${s}`,"aria-current":e===s?"page":void 0,children:s},s))}),(0,t.jsxs)("button",{onClick:()=>l(e+1),disabled:e===r,className:n(e===r),"aria-label":"Next page",children:[(0,t.jsx)("span",{className:"hidden sm:inline",children:"Next"}),(0,t.jsx)(a.ChevronRight,{className:"w-4 h-4"})]})]})}])},80060,2711,e=>{"use strict";var t=e.i(18566),s=e.i(71645);function a(e){let t=e.getFullYear(),s=String(e.getMonth()+1).padStart(2,"0"),a=String(e.getDate()).padStart(2,"0");return`${t}-${s}-${a}`}function r(e){var t;if(!e||(t=e,!/^\d{4}-\d{2}-\d{2}$/.test(t)||isNaN(Date.parse(t))))return null;let[s,a,r]=e.split("-").map(Number);return new Date(s,a-1,r,12,0,0)}e.s(["useUrlParams",0,function(){let e=(0,t.useSearchParams)(),a=(0,t.useRouter)(),r=(0,t.usePathname)(),l=(0,s.useRef)(null),n=(0,s.useCallback)(t=>e.get(t),[e]),i=(0,s.useCallback)(()=>new URLSearchParams(e.toString()),[e]),o=(0,s.useCallback)(t=>{l.current&&clearTimeout(l.current),l.current=setTimeout(()=>{let s=new URLSearchParams(e.toString());for(let[e,a]of Object.entries(t))void 0===a||""===a?s.delete(e):s.set(e,a);let l=s.toString(),n=l?`${r}?${l}`:r;a.replace(n,{scroll:!1})},150)},[e,r,a]);return(0,s.useEffect)(()=>()=>{l.current&&clearTimeout(l.current)},[]),{get:n,getAll:i,setAll:o}}],80060),e.s(["dateRangeToParams",0,function(e){let t={};return e.from&&(t.from=a(e.from)),e.to&&(t.to=a(e.to)),t},"keywordsToParam",0,function(e){if(0!==e.length)return e.map(e=>encodeURIComponent(e)).join(",")},"pageToParam",0,function(e){return e<=1?void 0:String(e)},"paramToKeywords",0,function(e){return e?e.split(",").map(e=>decodeURIComponent(e.trim())).filter(e=>e.length>0):[]},"paramToPage",0,function(e){if(!e)return 1;let t=parseInt(e,10);return Number.isFinite(t)&&t>=1?t:1},"paramToPreset",0,function(e){return e&&["all","last-hour","today","last-7-days","last-30-days","custom"].includes(e)?e:"all"},"paramsToDateRange",0,function(e,t){return{from:r(e),to:r(t)}},"presetToParam",0,function(e){return"all"===e?void 0:e}],2711)},24578,e=>{"use strict";let t={claude:{id:"claude",label:"Claude Code",badgeClasses:"bg-orange-500/10 text-orange-400 border-orange-500/20"},codex:{id:"codex",label:"OpenAI Codex",badgeClasses:"bg-purple-500/10 text-purple-400 border-purple-500/20"},copilot:{id:"copilot",label:"GitHub Copilot",badgeClasses:"bg-blue-500/10 text-blue-400 border-blue-500/20"},cursor:{id:"cursor",label:"Cursor Agent",badgeClasses:"bg-emerald-500/10 text-emerald-400 border-emerald-500/20"},opencode:{id:"opencode",label:"OpenCode",badgeClasses:"bg-amber-500/10 text-amber-400 border-amber-500/20"},pi:{id:"pi",label:"Pi",badgeClasses:"bg-pink-500/10 text-pink-400 border-pink-500/20"},hermes:{id:"hermes",label:"Hermes",badgeClasses:"bg-indigo-500/10 text-indigo-400 border-indigo-500/20"},openclaw:{id:"openclaw",label:"OpenClaw",badgeClasses:"bg-teal-500/10 text-teal-400 border-teal-500/20"},factory:{id:"factory",label:"Factory Droid",badgeClasses:"bg-rose-500/10 text-rose-400 border-rose-500/20"},devin:{id:"devin",label:"Devin CLI",badgeClasses:"bg-violet-500/10 text-violet-400 border-violet-500/20"},antigravity:{id:"antigravity",label:"Antigravity CLI",badgeClasses:"bg-cyan-500/10 text-cyan-400 border-cyan-500/20"},goose:{id:"goose",label:"Goose",badgeClasses:"bg-lime-500/10 text-lime-400 border-lime-500/20"}};e.s(["KNOWN_CLI_IDS",0,["claude","codex","copilot","cursor","opencode","pi","hermes","openclaw","factory","devin","antigravity","goose"],"getCliBadgeClasses",0,function(e){return t[e]?.badgeClasses??t.claude.badgeClasses},"getCliLabel",0,function(e){return t[e]?.label??e},"isKnownCli",0,function(e){return"string"==typeof e&&Object.prototype.hasOwnProperty.call(t,e)}])},62706,20087,30005,66595,85898,e=>{"use strict";e.s(["formatDate",0,function(e){return new Intl.DateTimeFormat("en-US",{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit",hour12:!0}).format(e)}],62706),e.s(["FILTER_PRESETS",0,[{value:"all",label:"All"},{value:"last-hour",label:"Last Hour"},{value:"today",label:"Today"},{value:"last-7-days",label:"Last 7 Days"},{value:"last-30-days",label:"Last 30 Days"}],"ITEMS_PER_PAGE",0,25,"filterByDate",0,function(e,t,s){if("all"===t)return e;if("custom"===t){let t,a,r=s.from?((t=new Date(s.from)).setHours(0,0,0,0),t):null,l=s.to?((a=new Date(s.to)).setHours(23,59,59,999),a):null;return e.filter(e=>(!r||!(e.lastModified<r))&&(!l||!(e.lastModified>l)))}let a=function(e){let t=new Date;switch(e){case"last-hour":return new Date(t.getTime()-36e5);case"today":return new Date(t.getFullYear(),t.getMonth(),t.getDate());case"last-7-days":return new Date(t.getTime()-6048e5);case"last-30-days":return new Date(t.getTime()-2592e6);default:return null}}(t);return a?e.filter(e=>e.lastModified>=a):e},"rehydrateDates",0,function(e){return e.map(e=>({...e,lastModified:e.lastModified instanceof Date?e.lastModified:new Date(e.lastModified)}))}],20087);var t=e.i(71645);e.s(["useFilterState",0,function(e=[],s){let[a,r]=(0,t.useState)(s?.filterPreset??"all"),[l,n]=(0,t.useState)(s?.dateRange??{from:null,to:null}),[i,o]=(0,t.useState)(s?.currentPage??1),d=`${a}|${JSON.stringify(l)}|${JSON.stringify(e)}`,[c,u]=(0,t.useState)(d);d!==c&&(u(d),o(1));let m=(0,t.useCallback)(e=>{r(e),"custom"!==e&&n({from:null,to:null})},[]);return{filterPreset:a,dateRange:l,currentPage:i,setCurrentPage:o,handlePresetChange:m,handleDateRangeChange:(0,t.useCallback)((e,t)=>{r("custom"),n(s=>({...s,[e]:t?new Date(t):null}))},[]),clearFilters:(0,t.useCallback)(()=>{r("all"),n({from:null,to:null})},[])}}],30005);var s=e.i(56420);let a=(0,s.default)("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]);e.s(["Search",0,a],66595);var r=e.i(43476);let l=(0,s.default)("calendar",[["path",{d:"M8 2v4",key:"1cmpym"}],["path",{d:"M16 2v4",key:"4m81vk"}],["rect",{width:"18",height:"18",x:"3",y:"4",rx:"2",key:"1hopcy"}],["path",{d:"M3 10h18",key:"8toen8"}]]);e.s(["default",0,function({id:e,value:t,stringValue:s,onChange:a,"aria-label":n}){let i=null!=s?s:t?t.toISOString().split("T")[0]:"";return(0,r.jsxs)("div",{className:"relative group",children:[(0,r.jsx)("input",{type:"date",id:e,value:i,onChange:e=>a(e.target.value),"aria-label":n,className:"date-input px-3 py-2 pr-8 text-sm bg-input border border-border rounded-md text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent transition-all hover:border-primary/50 w-[200px]"}),(0,r.jsx)("label",{htmlFor:e,className:"absolute right-2.5 top-1/2 -translate-y-1/2 cursor-pointer pointer-events-auto z-10 p-1 rounded hover:bg-muted/50 transition-colors",onClick:t=>{t.preventDefault();let s=document.getElementById(e);s&&"function"==typeof s.showPicker?s.showPicker():s?.click()},children:(0,r.jsx)(l,{className:"w-4 h-4 text-primary group-hover:text-primary/80 transition-colors"})})]})}],85898)},43418,e=>{"use strict";var t=e.i(43476),s=e.i(24578);e.s(["CliBadge",0,function({cli:e}){let a=(0,s.getCliLabel)(e),r=(0,s.getCliBadgeClasses)(e);return(0,t.jsx)("span",{className:`inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-mono font-medium uppercase tracking-wider border ${r}`,title:`Agent CLI: ${a}`,children:a})}])},73294,e=>{"use strict";var t=e.i(43476),s=e.i(71645),a=e.i(62706),r=e.i(20087),l=e.i(30005),n=e.i(80060),i=e.i(2711);let o=(0,e.i(56420).default)("file",[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}]]);var d=e.i(66595),c=e.i(22016),u=e.i(73520),m=e.i(85898),h=e.i(24380),p=e.i(43418);e.s(["default",0,function({files:e,projectName:g}){let f=(0,n.useUrlParams)(),b=(0,s.useRef)(!1),[x,y]=(0,s.useState)(()=>f.get("sid")??""),{filterPreset:v,dateRange:C,currentPage:j,setCurrentPage:N,handlePresetChange:w,handleDateRangeChange:T,clearFilters:P}=(0,l.useFilterState)([x],{filterPreset:(0,i.paramToPreset)(f.get("preset")),dateRange:(0,i.paramsToDateRange)(f.get("from"),f.get("to")),currentPage:(0,i.paramToPage)(f.get("page"))});(0,s.useEffect)(()=>{if(!b.current){b.current=!0;return}f.setAll({preset:(0,i.presetToParam)(v),...(0,i.dateRangeToParams)(C),sid:x||void 0,page:(0,i.pageToParam)(j)})},[v,C,x,j]);let k=(0,s.useMemo)(()=>(0,r.rehydrateDates)(e),[e]),S=(0,s.useMemo)(()=>{var e;let t;return(e=(0,r.filterByDate)(k,v,C),!(t=x.trim().toLowerCase())?e:e.filter(e=>e.sessionId?.toLowerCase().includes(t))).sort((e,t)=>t.lastModified.getTime()-e.lastModified.getTime())},[k,x,v,C]),M=Math.max(1,Math.ceil(S.length/r.ITEMS_PER_PAGE));(0,s.useEffect)(()=>{j>M&&N(M)},[j,M,N]);let I=(j-1)*r.ITEMS_PER_PAGE,D=Math.min(I+r.ITEMS_PER_PAGE,S.length),R=S.slice(I,D),E="all"!==v||null!==C.from||null!==C.to||""!==x;return(0,t.jsxs)("div",{className:"sessions-list",children:[(0,t.jsxs)("div",{className:"sessions-filter-bar",children:[(0,t.jsxs)("div",{className:"sessions-filter-row",children:[(0,t.jsx)("span",{className:"sessions-filter-label",children:"filter by"}),r.FILTER_PRESETS.map(e=>(0,t.jsx)("button",{type:"button",onClick:()=>w(e.value),className:`sessions-chip${v===e.value?" on":""}`,children:e.label},e.value))]}),(0,t.jsxs)("div",{className:"sessions-filter-row",children:[(0,t.jsx)("span",{className:"sessions-filter-label",children:"range"}),(0,t.jsx)(m.default,{id:"date-from",value:C.from,onChange:e=>T("from",e),"aria-label":"Filter from date"}),(0,t.jsx)("span",{className:"sessions-range-sep",children:"to"}),(0,t.jsx)(m.default,{id:"date-to",value:C.to,onChange:e=>T("to",e),"aria-label":"Filter to date"})]}),(0,t.jsxs)("div",{className:"sessions-filter-row",children:[(0,t.jsxs)("span",{className:"sessions-filter-label",children:[(0,t.jsx)(d.Search,{className:"sessions-filter-icon","aria-hidden":"true"}),"session id"]}),(0,t.jsx)("input",{type:"text",value:x,onChange:e=>y(e.target.value),placeholder:"paste a session uuid",className:"sessions-input","aria-label":"Filter by session ID"}),E&&(0,t.jsx)("button",{type:"button",onClick:()=>{P(),y("")},className:"sessions-chip",style:{marginLeft:"auto"},children:"clear"})]}),(0,t.jsx)("div",{className:"sessions-results-count",children:0===S.length?(0,t.jsx)(t.Fragment,{children:"// no sessions found"}):(0,t.jsxs)(t.Fragment,{children:["// showing"," ",I+1,"–",D," of ",S.length," sessions",S.length!==k.length&&(0,t.jsxs)("span",{children:[" · filtered from ",k.length]})]})})]}),(0,t.jsxs)("div",{className:"sessions-table-wrap",children:[(0,t.jsxs)("table",{className:"sessions-table",children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{children:[(0,t.jsx)("th",{scope:"col",className:"sessions-th sessions-th-icon",children:(0,t.jsx)("span",{className:"sr-only",children:"Icon"})}),(0,t.jsx)("th",{scope:"col",className:"sessions-th",children:"session id"}),(0,t.jsx)("th",{scope:"col",className:"sessions-th",children:"modified"})]})}),(0,t.jsx)("tbody",{children:0===R.length?(0,t.jsx)("tr",{children:(0,t.jsx)("td",{colSpan:3,className:"sessions-td sessions-empty",children:"// no sessions match the filter."})}):R.map(e=>(0,t.jsxs)("tr",{className:"sessions-row",children:[(0,t.jsx)("td",{className:"sessions-td sessions-td-icon",children:(0,t.jsx)(o,{className:"sessions-file-icon","aria-hidden":"true"})}),(0,t.jsxs)("td",{className:"sessions-td sessions-td-name",children:[e.sessionId?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(c.default,{href:`/project/${encodeURIComponent(g)}/session/${encodeURIComponent(e.sessionId)}`,className:"sessions-link",children:e.name.replace(/\.jsonl$/,"")}),(0,t.jsx)(h.CopyButton,{text:e.sessionId})]}):(0,t.jsx)("span",{className:"sessions-link","aria-disabled":"true",children:e.name.replace(/\.jsonl$/,"")}),e.cli&&(0,t.jsx)(p.CliBadge,{cli:e.cli}),(e.userId||e.channelId)&&(0,t.jsxs)("div",{style:{fontSize:"0.7rem",opacity:.6,marginTop:"0.15rem",display:"flex",gap:"0.6rem",flexWrap:"wrap"},children:[e.userId&&(0,t.jsxs)("span",{title:"Gateway user",children:["user ",e.userId]}),e.channelId&&(0,t.jsxs)("span",{title:"Channel",children:[e.channelType??"channel"," ",e.channelId]})]})]}),(0,t.jsx)("td",{className:"sessions-td sessions-td-date",children:e.lastModifiedFormatted||(0,a.formatDate)(e.lastModified)})]},e.path))})]}),S.length>0&&(0,t.jsx)(u.default,{currentPage:j,totalPages:M,onPageChange:N})]})]})}],73294)}]);
@@ -1,4 +1,4 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,64245,e=>{"use strict";var t=e.i(43476),s=e.i(71645),r=e.i(74080),n=e.i(22016),a=e.i(84026),l=e.i(29407),i=e.i(16306),o=e.i(82954),c=e.i(16327),d=e.i(8734),m=e.i(89664),x=e.i(66794);let u=(0,e.i(56420).default)("code",[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]]);var p=e.i(63676),h=e.i(73520),f=e.i(95187);let g=(0,f.createServerReference)("409ad7684d631c5669dee57c4fc09762741d082266",f.callServer,void 0,f.findSourceMapURL,"getHookActivityAction");var b=e.i(66284);let j=(0,f.createServerReference)("00af902c5457f93374a34ca9347ba3041e9533c888",f.callServer,void 0,f.findSourceMapURL,"getHooksConfigAction"),v=(0,f.createServerReference)("606c0cfc80d877dcb07e643ae78e4a94b79e8450ff",f.callServer,void 0,f.findSourceMapURL,"togglePolicyAction"),y=(0,f.createServerReference)("605d170b304a1f24ab822510ede41f7c7e7ef2b463",f.callServer,void 0,f.findSourceMapURL,"installHooksWebAction"),N=(0,f.createServerReference)("60d784b0820102c61301a64acff41aae8710b9cef7",f.callServer,void 0,f.findSourceMapURL,"removeHooksWebAction"),w=(0,f.createServerReference)("605fb902f62afe95310a2d6cd85e02217920b53fcc",f.callServer,void 0,f.findSourceMapURL,"updatePolicyParamsAction");var k=e.i(85881),S=e.i(12344),C=e.i(80060),_=e.i(2711),P=e.i(24578),I=e.i(34713),T=e.i(67881);function $({sessionId:e,transcriptPath:s,integration:r,cwd:a}){if(!e)return(0,t.jsx)("span",{className:"text-muted-foreground",children:"\\u2014"});let l=e?e.slice(0,8):"—",i="codex"===r||(s?.includes("/.codex/")??!1),o="copilot"===r||(s?.includes("/.copilot/session-state/")??!1),c="cursor"===r||(s?.includes("/.cursor/")??!1),d="opencode"===r||(s?.includes("/.local/share/opencode/")??!1)||(s?.includes("/.opencode/")??!1),m="pi"===r||(s?.includes("/.pi/")??!1);if(i||o||c||d||m){let s,r=a?(s=/^([A-Za-z]):[\\/](.*)$/.exec(a))?s[1]+"--"+s[2].replace(/[\\/]/g,"-"):a.replace(/[\\/]/g,"-"):i?"codex":o?"copilot":c?"cursor":d?"opencode":"pi";return(0,t.jsx)(n.default,{href:`/project/${encodeURIComponent(r)}/session/${encodeURIComponent(e)}`,className:"text-primary hover:underline font-mono",onClick:e=>e.stopPropagation(),children:l})}let x=s?function(e){let t=e.replace(/\\/g,"/").split("/").filter(Boolean);if(t.length<2)return null;let s=t[t.length-2];return!s||s.startsWith(".")?null:s}(s):null;return x?(0,t.jsx)(n.default,{href:`/project/${encodeURIComponent(x)}/session/${encodeURIComponent(e)}`,className:"text-primary hover:underline font-mono",onClick:e=>e.stopPropagation(),children:l}):(0,t.jsx)("span",{className:"text-muted-foreground font-mono",children:l})}function A({decision:e}){return"deny"===e?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-red-500/10 text-red-400 border border-red-500/20",children:[(0,t.jsx)(l.ShieldX,{className:"h-3 w-3"}),"Deny"]}):"instruct"===e?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-amber-500/10 text-amber-400 border border-amber-500/20",children:[(0,t.jsx)(i.ShieldAlert,{className:"h-3 w-3"}),"Instruct"]}):(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-emerald-500/10 text-emerald-400 border border-emerald-500/20",children:[(0,t.jsx)(a.ShieldCheck,{className:"h-3 w-3"}),"Allow"]})}function R({eventType:e}){return(0,t.jsx)("span",{className:"inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium bg-muted text-muted-foreground border border-border/50",children:e})}function L({integration:e}){if(!e)return null;let s=(0,P.getCliLabel)(e),r=(0,P.getCliBadgeClasses)(e);return(0,t.jsx)("span",{className:`inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium border ${r}`,title:`Agent CLI: ${s}`,children:s})}function E({mode:e}){let s="default"===e;return(0,t.jsx)("span",{title:e,className:`inline-block max-w-full truncate rounded px-1.5 py-0.5 align-middle text-[0.6rem] font-medium border ${s?"bg-sky-500/10 text-sky-400 border-sky-500/20":"bg-amber-500/10 text-amber-400 border-amber-500/20"}`,children:e})}function U({ms:e}){return(0,t.jsx)("span",{className:`font-mono text-[0.7rem] ${e>500?"text-red-400":e>100?"text-amber-400":"text-muted-foreground"}`,children:e<1e3?`${e}ms`:`${(e/1e3).toFixed(1)}s`})}function z({text:e,field:r}){let[n,a]=(0,s.useState)(!1),{capture:l}=(0,S.usePostHog)(),i=async t=>{t.stopPropagation(),l("activity_copy_clicked",{field:r??"unknown"});try{await navigator.clipboard.writeText(e),a(!0),setTimeout(()=>a(!1),1500)}catch{let t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t),a(!0),setTimeout(()=>a(!1),1500)}};return(0,t.jsx)("button",{onClick:i,className:"inline-flex items-center justify-center h-5 w-5 rounded hover:bg-muted/50 text-muted-foreground hover:text-foreground transition-colors",title:"Copy",children:n?(0,t.jsx)(m.Check,{className:"h-3 w-3 text-emerald-400"}):(0,t.jsx)(d.Copy,{className:"h-3 w-3"})})}function F({value:e,onChange:s}){return(0,t.jsx)("div",{className:"inline-flex items-center rounded-md border border-border bg-muted/30 p-0.5",children:[{label:"All",value:""},{label:"Allow",value:"allow"},{label:"Instruct",value:"instruct"},{label:"Deny",value:"deny"}].map(r=>(0,t.jsx)("button",{onClick:()=>s(r.value),className:`px-2.5 py-1 text-[0.65rem] font-medium rounded transition-all ${e===r.value?"deny"===r.value?"bg-red-500/15 text-red-400 shadow-sm":"allow"===r.value?"bg-emerald-500/15 text-emerald-400 shadow-sm":"instruct"===r.value?"bg-amber-500/15 text-amber-400 shadow-sm":"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:r.label},r.value))})}function D({stats:e}){let s=e.totalEvents>0?e.denyCount/e.totalEvents*100:0,r=s.toFixed(s>=10?0:1),n=0===e.denyCount?"":s>=5?" is-deny":s>=2?" is-warn":"";return(0,t.jsxs)("div",{className:"stat-bar",role:"group","aria-label":"Activity stats",children:[(0,t.jsxs)("div",{className:"stat-cell",children:[(0,t.jsx)("span",{className:"eyebrow",children:"total events"}),(0,t.jsx)("span",{className:"value",children:e.totalEvents.toLocaleString()}),(0,t.jsx)("span",{className:"meta",children:"across all installed agents"})]}),(0,t.jsxs)("div",{className:"stat-cell",children:[(0,t.jsx)("span",{className:"eyebrow",children:"deny rate"}),(0,t.jsxs)("span",{className:`value${n}`,children:[r,"%"]}),(0,t.jsxs)("span",{className:"meta",children:[e.denyCount.toLocaleString()," of ",e.totalEvents.toLocaleString()," denied"]})]}),(0,t.jsxs)("div",{className:"stat-cell",children:[(0,t.jsx)("span",{className:"eyebrow",children:"top policy"}),(0,t.jsx)("span",{className:"value",style:{fontSize:16,fontWeight:500,color:e.topPolicy?"var(--accent-pink)":"var(--dim)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:e.topPolicy??void 0,children:e.topPolicy??"—"}),(0,t.jsx)("span",{className:"meta",children:"most-evaluated policy in scope"})]})]})}function O({item:e}){return(0,t.jsx)("tr",{children:(0,t.jsx)("td",{colSpan:11,className:"px-0 py-0",children:(0,t.jsxs)("div",{className:"activity-detail animate-expand text-xs",children:[(0,t.jsxs)("span",{className:"activity-detail-eyebrow",children:[(0,t.jsx)("span",{"aria-hidden":"true",children:"\\u25be"}),"event detail"]}),(0,t.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-2",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Session ID: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.sessionId??"—"}),e.sessionId&&(0,t.jsx)(z,{text:e.sessionId,field:"session_id"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"CWD: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.cwd??"—"}),e.cwd&&(0,t.jsx)(z,{text:e.cwd,field:"cwd"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Transcript: "}),(0,t.jsx)("span",{className:"font-mono text-foreground break-all",children:e.transcriptPath??"—"}),e.transcriptPath?.startsWith("opencode-db://")&&(0,t.jsx)("span",{className:"text-muted-foreground ml-1",children:"(stored in opencode DB)"})]})]}),e.policyNames&&e.policyNames.length>1&&(0,t.jsxs)("div",{style:{marginTop:8},children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Policies: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.policyNames.join(", ")})]}),e.reason&&(0,t.jsxs)("div",{style:{marginTop:8},children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Full reason: "}),(0,t.jsx)("span",{className:"text-foreground",children:e.reason})]})]})})})}function B({hooksInstalled:e,onSwitchTab:r}){let{intervalSec:n}=(0,k.useAutoRefresh)(),{capture:a}=(0,S.usePostHog)(),l=(0,C.useUrlParams)(),i=(0,s.useRef)(!1),[d,m]=(0,s.useState)(()=>(0,_.paramToPage)(l.get("page"))),[x,u]=(0,s.useState)(null),[p,f]=(0,s.useState)(null),[j,v]=(0,s.useState)(()=>{let e=l.get("decision");return"allow"===e||"deny"===e||"instruct"===e?e:""}),[y,N]=(0,s.useState)(()=>l.get("event")??""),[w,T]=(0,s.useState)(()=>l.get("policy")??""),[z,W]=(0,s.useState)(()=>l.get("session")??""),[H,M]=(0,s.useState)(()=>{let e=l.get("cli");return(0,P.isKnownCli)(e)?e:""}),X=(0,s.useRef)(null),J=(0,s.useRef)(!0),K=(0,s.useRef)({filterDecision:j,filterEventType:y,filterPolicy:w,filterSessionId:z,filterCli:H});K.current={filterDecision:j,filterEventType:y,filterPolicy:w,filterSessionId:z,filterCli:H},(0,s.useEffect)(()=>{if(!i.current){i.current=!0;return}l.setAll({decision:j||void 0,event:y||void 0,policy:w||void 0,session:z||void 0,cli:H||void 0,page:(0,_.pageToParam)(d)})},[j,y,w,z,H,d]);let q=""!==j||""!==y||""!==w||""!==z||""!==H,G=(0,s.useCallback)(async e=>{try{let t,{filterDecision:s,filterEventType:r,filterPolicy:n,filterSessionId:a,filterCli:l}=K.current;t=""!==s||""!==r||""!==n||""!==a||""!==l?await (0,b.searchHookActivityAction)({decision:s||void 0,eventType:r||void 0,policyName:n||void 0,sessionId:a||void 0,integration:l||void 0},e):await g(e),u(t)}catch{}},[]);(0,s.useEffect)(()=>{G(d);let e=setInterval(()=>G(d),n>0?1e3*n:5e3);return()=>clearInterval(e)},[d,G,n]),(0,s.useEffect)(()=>(X.current&&clearTimeout(X.current),X.current=setTimeout(()=>{if(m(1),f(null),G(1),J.current){J.current=!1;return}a("activity_filter_changed",{active_filter_count:+(""!==j)+ +(""!==y)+ +(""!==w)+ +(""!==z)+ +(""!==H),has_decision:""!==j,has_event_type:""!==y,has_policy:""!==w,has_session:""!==z,has_cli:""!==H,decision:j||null,event_type:y||null,cli:H||null})},300),()=>{X.current&&clearTimeout(X.current)}),[j,y,w,z,H]);let V=x?.entries??[],Z=x?.totalPages??1;return(0,t.jsxs)(t.Fragment,{children:[x?.stats&&x.stats.totalEvents>0&&(0,t.jsx)("div",{style:{marginBottom:18},children:(0,t.jsx)(D,{stats:x.stats})}),(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"filter-bar",children:[(0,t.jsxs)("div",{className:"filter-group",children:[(0,t.jsx)("span",{className:"filter-label",children:"decision"}),(0,t.jsx)(F,{value:j,onChange:v})]}),(0,t.jsxs)("div",{className:"filter-group",children:[(0,t.jsx)("span",{className:"filter-label",children:"event"}),(0,t.jsxs)("select",{value:y,onChange:e=>N(e.target.value),className:"filter-input",children:[(0,t.jsx)("option",{value:"",children:"all events"}),(0,t.jsx)("option",{value:"PreToolUse",children:"PreToolUse"}),(0,t.jsx)("option",{value:"PostToolUse",children:"PostToolUse"}),(0,t.jsx)("option",{value:"SessionStart",children:"SessionStart"}),(0,t.jsx)("option",{value:"SessionEnd",children:"SessionEnd"}),(0,t.jsx)("option",{value:"UserPromptSubmit",children:"UserPromptSubmit"}),(0,t.jsx)("option",{value:"PermissionRequest",children:"PermissionRequest"})]})]}),(0,t.jsxs)("div",{className:"filter-group",children:[(0,t.jsx)("span",{className:"filter-label",children:"cli"}),(0,t.jsxs)("select",{value:H,onChange:e=>{let t=e.target.value;M(""===t||(0,P.isKnownCli)(t)?t:"")},className:"filter-input","aria-label":"Filter by CLI",children:[(0,t.jsx)("option",{value:"",children:"all clis"}),P.KNOWN_CLI_IDS.map(e=>(0,t.jsx)("option",{value:e,children:(0,P.getCliLabel)(e)},e))]})]}),(0,t.jsxs)("div",{className:"filter-group filter-group--grow",children:[(0,t.jsx)("span",{className:"filter-label",children:"policy"}),(0,t.jsx)("input",{type:"text",value:w,onChange:e=>T(e.target.value),placeholder:"filter by policy\\u2026",className:"filter-input"})]}),(0,t.jsxs)("div",{className:"filter-group filter-group--grow",children:[(0,t.jsx)("span",{className:"filter-label",children:"session"}),(0,t.jsx)("input",{type:"text",value:z,onChange:e=>W(e.target.value),placeholder:"filter by session…",className:"filter-input"})]}),q&&(0,t.jsx)("button",{type:"button",className:"filter-clear",onClick:()=>{v(""),N(""),M(""),T(""),W("")},"aria-label":"Clear all filters",children:"[ clear ]"})]}),0===V.length?(0,t.jsxs)("div",{className:"flex flex-col items-center justify-center py-16 px-4 text-center",children:[(0,t.jsx)(o.Shield,{className:"h-12 w-12 text-muted-foreground/30"}),!1===e?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"text-sm text-muted-foreground mt-4 font-medium",children:"Policies are not installed"}),(0,t.jsxs)("p",{className:"text-xs text-muted-foreground mt-1 max-w-sm",children:["Go to the"," ",(0,t.jsx)("button",{className:"underline hover:text-foreground transition-colors",onClick:()=>r?.("policies"),children:"Policies tab"})," ","and click ",(0,t.jsx)("span",{className:"font-mono bg-muted px-1 rounded",children:"Install"})," to enable policy monitoring."]})]}):(0,t.jsx)("p",{className:"text-sm text-muted-foreground mt-4",children:q?"No matching activity.":"Waiting for hook events…"})]}):(0,t.jsx)("div",{className:"overflow-x-auto activity-table-wrap",children:(0,t.jsxs)("table",{className:"w-full text-xs activity-table",style:{tableLayout:"fixed"},children:[(0,t.jsxs)("colgroup",{children:[(0,t.jsx)("col",{style:{width:32}}),(0,t.jsx)("col",{style:{width:"7%"}}),(0,t.jsx)("col",{style:{width:"9%"}}),(0,t.jsx)("col",{style:{width:"12%"}}),(0,t.jsx)("col",{style:{width:"11%"}}),(0,t.jsx)("col",{style:{width:"9%"}}),(0,t.jsx)("col",{style:{width:"13%"}}),(0,t.jsx)("col",{style:{width:"12%"}}),(0,t.jsx)("col",{style:{width:"11%"}}),(0,t.jsx)("col",{style:{width:"8%"}}),(0,t.jsx)("col",{style:{width:"8%"}})]}),(0,t.jsx)("thead",{className:"activity-thead",children:(0,t.jsxs)("tr",{children:[(0,t.jsx)("th",{className:"px-4 py-3"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Time"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Decision"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Event"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"CLI"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Tool"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Policy"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Reason"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Mode"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Duration"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Session"})]})}),(0,t.jsx)("tbody",{className:"divide-y divide-border/30",children:V.map((e,r)=>{let n="deny"===e.decision,l=p===r,i="instruct"===e.decision;return(0,t.jsxs)(s.default.Fragment,{children:[(0,t.jsxs)("tr",{onClick:()=>{f(e=>{let t=e===r?null:r,s=V[r];return a("activity_row_toggled",{expanded:null!==t,decision:s?.decision??null,policy_name:s?.policyName??null,event_type:s?.eventType??null}),t})},className:`activity-data-row cursor-pointer transition-colors ${n?"bg-red-500/[0.03] hover:bg-red-500/[0.07] border-l-2 border-l-red-500/40":i?"bg-amber-500/[0.03] hover:bg-amber-500/[0.07] border-l-2 border-l-amber-500/40":r%2==0?"hover:bg-muted/30":"bg-muted/[0.04] hover:bg-muted/30"} ${l?"bg-muted/20":""}`,children:[(0,t.jsx)("td",{className:"px-4 py-2",children:(0,t.jsx)(c.ChevronDown,{className:`h-3.5 w-3.5 text-muted-foreground transition-transform duration-150 ${l?"rotate-0":"-rotate-90"}`})}),(0,t.jsx)("td",{className:"px-3 py-2 text-muted-foreground whitespace-nowrap",title:new Date(e.timestamp).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"}),children:(0,I.formatRelativeTime)(e.timestamp)}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(A,{decision:e.decision})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(R,{eventType:e.eventType})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(L,{integration:e.integration})}),(0,t.jsx)("td",{className:"px-3 py-2 font-mono text-foreground",children:e.toolName??"—"}),(0,t.jsx)("td",{className:"px-3 py-2 font-mono text-foreground",children:e.policyNames&&e.policyNames.length>1?(0,t.jsxs)("span",{title:e.policyNames.join(", "),children:[e.policyNames[0],(0,t.jsxs)("span",{className:"text-muted-foreground text-[0.6rem]",children:[" +",e.policyNames.length-1]})]}):e.policyName??"—"}),(0,t.jsx)("td",{className:"px-3 py-2 text-muted-foreground truncate",title:e.reason??"",children:e.reason??"—"}),(0,t.jsx)("td",{className:"px-3 py-2",children:e.permissionMode?(0,t.jsx)(E,{mode:e.permissionMode}):"—"}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(U,{ms:e.durationMs})}),(0,t.jsx)("td",{className:"px-3 py-2",title:e.sessionId??"",children:(0,t.jsx)($,{sessionId:e.sessionId,transcriptPath:e.transcriptPath,integration:e.integration,cwd:e.cwd})})]}),l&&(0,t.jsx)(O,{item:e})]},`${e.timestamp}-${r}`)})})]})}),(0,t.jsx)(h.default,{currentPage:d,totalPages:Z,onPageChange:e=>{a("activity_pagination_changed",{from_page:d,to_page:e,total_pages:Z}),m(e),f(null)}})]})]})}function W({enabled:e,onChange:s,disabled:r}){return(0,t.jsx)("button",{onClick:s,disabled:r,className:`relative inline-flex h-4 w-7 shrink-0 items-center rounded-full transition-colors disabled:opacity-40 ${e?"bg-emerald-500":"bg-muted-foreground/30"}`,"aria-label":e?"Disable policy":"Enable policy",children:(0,t.jsx)("span",{className:`inline-block h-3 w-3 rounded-full bg-white shadow transition-transform ${e?"translate-x-3.5":"translate-x-0.5"}`})})}function H({policy:e,onClose:r,onSave:n}){let a=e.params??{},l=e.currentParams??{},[i,o]=(0,s.useState)(()=>{let e={};for(let[t,s]of Object.entries(a)){let r=t in l?l[t]:s.default;e[t]=r}return e});(0,s.useEffect)(()=>{let e=e=>{"Escape"===e.key&&r()};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[r]);let c=(e,t)=>{o(s=>({...s,[e]:t}))};return(0,t.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",onClick:e=>{e.target===e.currentTarget&&r()},children:(0,t.jsxs)("div",{className:"bg-card border border-border rounded-lg shadow-xl w-full max-w-lg mx-4 max-h-[80vh] flex flex-col",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-3 border-b border-border",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{className:"text-sm font-mono font-semibold text-foreground",children:e.name}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground mt-0.5",children:e.description})]}),(0,t.jsx)("button",{onClick:r,className:"text-muted-foreground hover:text-foreground transition-colors",children:(0,t.jsx)(p.X,{className:"h-4 w-4"})})]}),(0,t.jsx)("div",{className:"overflow-y-auto flex-1 px-4 py-4 space-y-4",children:Object.entries(a).map(([e,s])=>(0,t.jsxs)("div",{children:[(0,t.jsx)("label",{className:"block text-xs font-semibold text-foreground mb-1 font-mono",children:e}),(0,t.jsx)("p",{className:"text-[0.65rem] text-muted-foreground mb-1.5",children:s.description}),((e,s)=>{let r=i[e];if("boolean"===s.type)return(0,t.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,t.jsx)("input",{type:"checkbox",checked:!!r,onChange:t=>c(e,t.target.checked),className:"rounded border-border"}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:s.description})]});if("number"===s.type)return(0,t.jsx)("input",{type:"number",value:"number"==typeof r?r:"",onChange:t=>c(e,Number(t.target.value)),className:"w-full h-7 rounded border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40"});if("string[]"===s.type){let s=Array.isArray(r)?r.join("\n"):"";return(0,t.jsx)("textarea",{value:s,onChange:t=>c(e,t.target.value.split("\n").filter(e=>""!==e.trim())),rows:4,placeholder:"One entry per line",className:"w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground font-mono focus:outline-none focus:ring-2 focus:ring-primary/40 resize-y"})}if("pattern[]"===s.type){let s=Array.isArray(r)?r:[];return(0,t.jsxs)("div",{className:"space-y-1.5",children:[s.map((r,n)=>(0,t.jsxs)("div",{className:"flex gap-1.5 items-center",children:[(0,t.jsx)("input",{type:"text",value:r.regex,onChange:t=>{let r=[...s];r[n]={...r[n],regex:t.target.value},c(e,r)},placeholder:"regex",className:"flex-1 h-6 rounded border border-border bg-background px-2 text-xs font-mono focus:outline-none focus:ring-2 focus:ring-primary/40"}),(0,t.jsx)("input",{type:"text",value:r.label,onChange:t=>{let r=[...s];r[n]={...r[n],label:t.target.value},c(e,r)},placeholder:"label",className:"flex-1 h-6 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-2 focus:ring-primary/40"}),(0,t.jsx)("button",{onClick:()=>c(e,s.filter((e,t)=>t!==n)),className:"text-muted-foreground/50 hover:text-destructive transition-colors",children:(0,t.jsx)(p.X,{className:"h-3.5 w-3.5"})})]},n)),(0,t.jsx)("button",{onClick:()=>c(e,[...s,{regex:"",label:""}]),className:"text-xs text-primary hover:underline",children:"+ Add pattern"})]})}return(0,t.jsx)("input",{type:"text",value:"string"==typeof r?r:"",onChange:t=>c(e,t.target.value),className:"w-full h-7 rounded border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40"})})(e,s)]},e))}),(0,t.jsxs)("div",{className:"flex items-center justify-end gap-2 px-4 py-3 border-t border-border",children:[(0,t.jsx)(T.Button,{variant:"outline",size:"sm",onClick:r,className:"h-7 text-xs",children:"Cancel"}),(0,t.jsx)(T.Button,{size:"sm",onClick:()=>n(i),className:"h-7 text-xs",children:"Save"})]})]})})}function M({message:e,onDismiss:s,onInstall:n,isPending:a}){let{capture:l}=(0,S.usePostHog)();return(0,r.createPortal)((0,t.jsxs)("div",{className:"fixed top-4 right-4 z-[9999] w-full max-w-sm",style:{animation:"slideInFromRight 0.25s ease-out"},children:[(0,t.jsx)("style",{children:`
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,64245,e=>{"use strict";var t=e.i(43476),s=e.i(71645),r=e.i(74080),n=e.i(22016),a=e.i(84026),l=e.i(29407),i=e.i(16306),o=e.i(82954),c=e.i(16327),d=e.i(8734),m=e.i(89664),x=e.i(66794);let u=(0,e.i(56420).default)("code",[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]]);var p=e.i(63676),h=e.i(73520),f=e.i(95187);let g=(0,f.createServerReference)("409a8011f18d94f84f5ebf30534677b4a8b6d81578",f.callServer,void 0,f.findSourceMapURL,"getHookActivityAction");var b=e.i(52951);let j=(0,f.createServerReference)("006d7443e613357829b40adaac068a115508df626b",f.callServer,void 0,f.findSourceMapURL,"getHooksConfigAction"),v=(0,f.createServerReference)("60072e86b97598b4347d7bdd6d89d607b1da0ce91b",f.callServer,void 0,f.findSourceMapURL,"togglePolicyAction"),y=(0,f.createServerReference)("60bf2ae748eb1404cd8cbd03c3fa8ece7d62ecdc1e",f.callServer,void 0,f.findSourceMapURL,"installHooksWebAction"),N=(0,f.createServerReference)("604ea829f89db034e3b8d54f85742b44192a13cf9f",f.callServer,void 0,f.findSourceMapURL,"removeHooksWebAction"),w=(0,f.createServerReference)("60cf60cbd7c61987a905fddb52447f5f33a926715f",f.callServer,void 0,f.findSourceMapURL,"updatePolicyParamsAction");var k=e.i(85881),S=e.i(12344),C=e.i(80060),_=e.i(2711),P=e.i(24578),I=e.i(34713),T=e.i(67881);function $({sessionId:e,transcriptPath:s,integration:r,cwd:a}){if(!e)return(0,t.jsx)("span",{className:"text-muted-foreground",children:"\\u2014"});let l=e?e.slice(0,8):"—",i="codex"===r||(s?.includes("/.codex/")??!1),o="copilot"===r||(s?.includes("/.copilot/session-state/")??!1),c="cursor"===r||(s?.includes("/.cursor/")??!1),d="opencode"===r||(s?.includes("/.local/share/opencode/")??!1)||(s?.includes("/.opencode/")??!1),m="pi"===r||(s?.includes("/.pi/")??!1);if(i||o||c||d||m){let s,r=a?(s=/^([A-Za-z]):[\\/](.*)$/.exec(a))?s[1]+"--"+s[2].replace(/[\\/]/g,"-"):a.replace(/[\\/]/g,"-"):i?"codex":o?"copilot":c?"cursor":d?"opencode":"pi";return(0,t.jsx)(n.default,{href:`/project/${encodeURIComponent(r)}/session/${encodeURIComponent(e)}`,className:"text-primary hover:underline font-mono",onClick:e=>e.stopPropagation(),children:l})}let x=s?function(e){let t=e.replace(/\\/g,"/").split("/").filter(Boolean);if(t.length<2)return null;let s=t[t.length-2];return!s||s.startsWith(".")?null:s}(s):null;return x?(0,t.jsx)(n.default,{href:`/project/${encodeURIComponent(x)}/session/${encodeURIComponent(e)}`,className:"text-primary hover:underline font-mono",onClick:e=>e.stopPropagation(),children:l}):(0,t.jsx)("span",{className:"text-muted-foreground font-mono",children:l})}function A({decision:e}){return"deny"===e?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-red-500/10 text-red-400 border border-red-500/20",children:[(0,t.jsx)(l.ShieldX,{className:"h-3 w-3"}),"Deny"]}):"instruct"===e?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-amber-500/10 text-amber-400 border border-amber-500/20",children:[(0,t.jsx)(i.ShieldAlert,{className:"h-3 w-3"}),"Instruct"]}):(0,t.jsxs)("span",{className:"inline-flex items-center gap-1 rounded px-1.5 py-0.5 text-[0.65rem] font-semibold tracking-wide uppercase bg-emerald-500/10 text-emerald-400 border border-emerald-500/20",children:[(0,t.jsx)(a.ShieldCheck,{className:"h-3 w-3"}),"Allow"]})}function R({eventType:e}){return(0,t.jsx)("span",{className:"inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium bg-muted text-muted-foreground border border-border/50",children:e})}function L({integration:e}){if(!e)return null;let s=(0,P.getCliLabel)(e),r=(0,P.getCliBadgeClasses)(e);return(0,t.jsx)("span",{className:`inline-flex items-center rounded px-1.5 py-0.5 text-[0.6rem] font-medium border ${r}`,title:`Agent CLI: ${s}`,children:s})}function E({mode:e}){let s="default"===e;return(0,t.jsx)("span",{title:e,className:`inline-block max-w-full truncate rounded px-1.5 py-0.5 align-middle text-[0.6rem] font-medium border ${s?"bg-sky-500/10 text-sky-400 border-sky-500/20":"bg-amber-500/10 text-amber-400 border-amber-500/20"}`,children:e})}function U({ms:e}){return(0,t.jsx)("span",{className:`font-mono text-[0.7rem] ${e>500?"text-red-400":e>100?"text-amber-400":"text-muted-foreground"}`,children:e<1e3?`${e}ms`:`${(e/1e3).toFixed(1)}s`})}function z({text:e,field:r}){let[n,a]=(0,s.useState)(!1),{capture:l}=(0,S.usePostHog)(),i=async t=>{t.stopPropagation(),l("activity_copy_clicked",{field:r??"unknown"});try{await navigator.clipboard.writeText(e),a(!0),setTimeout(()=>a(!1),1500)}catch{let t=document.createElement("textarea");t.value=e,t.style.position="fixed",t.style.opacity="0",document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t),a(!0),setTimeout(()=>a(!1),1500)}};return(0,t.jsx)("button",{onClick:i,className:"inline-flex items-center justify-center h-5 w-5 rounded hover:bg-muted/50 text-muted-foreground hover:text-foreground transition-colors",title:"Copy",children:n?(0,t.jsx)(m.Check,{className:"h-3 w-3 text-emerald-400"}):(0,t.jsx)(d.Copy,{className:"h-3 w-3"})})}function F({value:e,onChange:s}){return(0,t.jsx)("div",{className:"inline-flex items-center rounded-md border border-border bg-muted/30 p-0.5",children:[{label:"All",value:""},{label:"Allow",value:"allow"},{label:"Instruct",value:"instruct"},{label:"Deny",value:"deny"}].map(r=>(0,t.jsx)("button",{onClick:()=>s(r.value),className:`px-2.5 py-1 text-[0.65rem] font-medium rounded transition-all ${e===r.value?"deny"===r.value?"bg-red-500/15 text-red-400 shadow-sm":"allow"===r.value?"bg-emerald-500/15 text-emerald-400 shadow-sm":"instruct"===r.value?"bg-amber-500/15 text-amber-400 shadow-sm":"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"}`,children:r.label},r.value))})}function D({stats:e}){let s=e.totalEvents>0?e.denyCount/e.totalEvents*100:0,r=s.toFixed(s>=10?0:1),n=0===e.denyCount?"":s>=5?" is-deny":s>=2?" is-warn":"";return(0,t.jsxs)("div",{className:"stat-bar",role:"group","aria-label":"Activity stats",children:[(0,t.jsxs)("div",{className:"stat-cell",children:[(0,t.jsx)("span",{className:"eyebrow",children:"total events"}),(0,t.jsx)("span",{className:"value",children:e.totalEvents.toLocaleString()}),(0,t.jsx)("span",{className:"meta",children:"across all installed agents"})]}),(0,t.jsxs)("div",{className:"stat-cell",children:[(0,t.jsx)("span",{className:"eyebrow",children:"deny rate"}),(0,t.jsxs)("span",{className:`value${n}`,children:[r,"%"]}),(0,t.jsxs)("span",{className:"meta",children:[e.denyCount.toLocaleString()," of ",e.totalEvents.toLocaleString()," denied"]})]}),(0,t.jsxs)("div",{className:"stat-cell",children:[(0,t.jsx)("span",{className:"eyebrow",children:"top policy"}),(0,t.jsx)("span",{className:"value",style:{fontSize:16,fontWeight:500,color:e.topPolicy?"var(--accent-pink)":"var(--dim)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},title:e.topPolicy??void 0,children:e.topPolicy??"—"}),(0,t.jsx)("span",{className:"meta",children:"most-evaluated policy in scope"})]})]})}function O({item:e}){return(0,t.jsx)("tr",{children:(0,t.jsx)("td",{colSpan:11,className:"px-0 py-0",children:(0,t.jsxs)("div",{className:"activity-detail animate-expand text-xs",children:[(0,t.jsxs)("span",{className:"activity-detail-eyebrow",children:[(0,t.jsx)("span",{"aria-hidden":"true",children:"\\u25be"}),"event detail"]}),(0,t.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-2",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Session ID: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.sessionId??"—"}),e.sessionId&&(0,t.jsx)(z,{text:e.sessionId,field:"session_id"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"CWD: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.cwd??"—"}),e.cwd&&(0,t.jsx)(z,{text:e.cwd,field:"cwd"})]}),(0,t.jsxs)("div",{children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Transcript: "}),(0,t.jsx)("span",{className:"font-mono text-foreground break-all",children:e.transcriptPath??"—"}),e.transcriptPath?.startsWith("opencode-db://")&&(0,t.jsx)("span",{className:"text-muted-foreground ml-1",children:"(stored in opencode DB)"})]})]}),e.policyNames&&e.policyNames.length>1&&(0,t.jsxs)("div",{style:{marginTop:8},children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Policies: "}),(0,t.jsx)("span",{className:"font-mono text-foreground",children:e.policyNames.join(", ")})]}),e.reason&&(0,t.jsxs)("div",{style:{marginTop:8},children:[(0,t.jsx)("span",{className:"text-muted-foreground",children:"Full reason: "}),(0,t.jsx)("span",{className:"text-foreground",children:e.reason})]})]})})})}function B({hooksInstalled:e,onSwitchTab:r}){let{intervalSec:n}=(0,k.useAutoRefresh)(),{capture:a}=(0,S.usePostHog)(),l=(0,C.useUrlParams)(),i=(0,s.useRef)(!1),[d,m]=(0,s.useState)(()=>(0,_.paramToPage)(l.get("page"))),[x,u]=(0,s.useState)(null),[p,f]=(0,s.useState)(null),[j,v]=(0,s.useState)(()=>{let e=l.get("decision");return"allow"===e||"deny"===e||"instruct"===e?e:""}),[y,N]=(0,s.useState)(()=>l.get("event")??""),[w,T]=(0,s.useState)(()=>l.get("policy")??""),[z,W]=(0,s.useState)(()=>l.get("session")??""),[H,M]=(0,s.useState)(()=>{let e=l.get("cli");return(0,P.isKnownCli)(e)?e:""}),X=(0,s.useRef)(null),J=(0,s.useRef)(!0),K=(0,s.useRef)({filterDecision:j,filterEventType:y,filterPolicy:w,filterSessionId:z,filterCli:H});K.current={filterDecision:j,filterEventType:y,filterPolicy:w,filterSessionId:z,filterCli:H},(0,s.useEffect)(()=>{if(!i.current){i.current=!0;return}l.setAll({decision:j||void 0,event:y||void 0,policy:w||void 0,session:z||void 0,cli:H||void 0,page:(0,_.pageToParam)(d)})},[j,y,w,z,H,d]);let q=""!==j||""!==y||""!==w||""!==z||""!==H,G=(0,s.useCallback)(async e=>{try{let t,{filterDecision:s,filterEventType:r,filterPolicy:n,filterSessionId:a,filterCli:l}=K.current;t=""!==s||""!==r||""!==n||""!==a||""!==l?await (0,b.searchHookActivityAction)({decision:s||void 0,eventType:r||void 0,policyName:n||void 0,sessionId:a||void 0,integration:l||void 0},e):await g(e),u(t)}catch{}},[]);(0,s.useEffect)(()=>{G(d);let e=setInterval(()=>G(d),n>0?1e3*n:5e3);return()=>clearInterval(e)},[d,G,n]),(0,s.useEffect)(()=>(X.current&&clearTimeout(X.current),X.current=setTimeout(()=>{if(m(1),f(null),G(1),J.current){J.current=!1;return}a("activity_filter_changed",{active_filter_count:+(""!==j)+ +(""!==y)+ +(""!==w)+ +(""!==z)+ +(""!==H),has_decision:""!==j,has_event_type:""!==y,has_policy:""!==w,has_session:""!==z,has_cli:""!==H,decision:j||null,event_type:y||null,cli:H||null})},300),()=>{X.current&&clearTimeout(X.current)}),[j,y,w,z,H]);let V=x?.entries??[],Z=x?.totalPages??1;return(0,t.jsxs)(t.Fragment,{children:[x?.stats&&x.stats.totalEvents>0&&(0,t.jsx)("div",{style:{marginBottom:18},children:(0,t.jsx)(D,{stats:x.stats})}),(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"filter-bar",children:[(0,t.jsxs)("div",{className:"filter-group",children:[(0,t.jsx)("span",{className:"filter-label",children:"decision"}),(0,t.jsx)(F,{value:j,onChange:v})]}),(0,t.jsxs)("div",{className:"filter-group",children:[(0,t.jsx)("span",{className:"filter-label",children:"event"}),(0,t.jsxs)("select",{value:y,onChange:e=>N(e.target.value),className:"filter-input",children:[(0,t.jsx)("option",{value:"",children:"all events"}),(0,t.jsx)("option",{value:"PreToolUse",children:"PreToolUse"}),(0,t.jsx)("option",{value:"PostToolUse",children:"PostToolUse"}),(0,t.jsx)("option",{value:"SessionStart",children:"SessionStart"}),(0,t.jsx)("option",{value:"SessionEnd",children:"SessionEnd"}),(0,t.jsx)("option",{value:"UserPromptSubmit",children:"UserPromptSubmit"}),(0,t.jsx)("option",{value:"PermissionRequest",children:"PermissionRequest"})]})]}),(0,t.jsxs)("div",{className:"filter-group",children:[(0,t.jsx)("span",{className:"filter-label",children:"cli"}),(0,t.jsxs)("select",{value:H,onChange:e=>{let t=e.target.value;M(""===t||(0,P.isKnownCli)(t)?t:"")},className:"filter-input","aria-label":"Filter by CLI",children:[(0,t.jsx)("option",{value:"",children:"all clis"}),P.KNOWN_CLI_IDS.map(e=>(0,t.jsx)("option",{value:e,children:(0,P.getCliLabel)(e)},e))]})]}),(0,t.jsxs)("div",{className:"filter-group filter-group--grow",children:[(0,t.jsx)("span",{className:"filter-label",children:"policy"}),(0,t.jsx)("input",{type:"text",value:w,onChange:e=>T(e.target.value),placeholder:"filter by policy…",className:"filter-input"})]}),(0,t.jsxs)("div",{className:"filter-group filter-group--grow",children:[(0,t.jsx)("span",{className:"filter-label",children:"session"}),(0,t.jsx)("input",{type:"text",value:z,onChange:e=>W(e.target.value),placeholder:"filter by session…",className:"filter-input"})]}),q&&(0,t.jsx)("button",{type:"button",className:"filter-clear",onClick:()=>{v(""),N(""),M(""),T(""),W("")},"aria-label":"Clear all filters",children:"[ clear ]"})]}),0===V.length?(0,t.jsxs)("div",{className:"flex flex-col items-center justify-center py-16 px-4 text-center",children:[(0,t.jsx)(o.Shield,{className:"h-12 w-12 text-muted-foreground/30"}),!1===e?(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("p",{className:"text-sm text-muted-foreground mt-4 font-medium",children:"Policies are not installed"}),(0,t.jsxs)("p",{className:"text-xs text-muted-foreground mt-1 max-w-sm",children:["Go to the"," ",(0,t.jsx)("button",{className:"underline hover:text-foreground transition-colors",onClick:()=>r?.("policies"),children:"Policies tab"})," ","and click ",(0,t.jsx)("span",{className:"font-mono bg-muted px-1 rounded",children:"Install"})," to enable policy monitoring."]})]}):(0,t.jsx)("p",{className:"text-sm text-muted-foreground mt-4",children:q?"No matching activity.":"Waiting for hook events…"})]}):(0,t.jsx)("div",{className:"overflow-x-auto activity-table-wrap",children:(0,t.jsxs)("table",{className:"w-full text-xs activity-table",style:{tableLayout:"fixed"},children:[(0,t.jsxs)("colgroup",{children:[(0,t.jsx)("col",{style:{width:32}}),(0,t.jsx)("col",{style:{width:"7%"}}),(0,t.jsx)("col",{style:{width:"9%"}}),(0,t.jsx)("col",{style:{width:"12%"}}),(0,t.jsx)("col",{style:{width:"11%"}}),(0,t.jsx)("col",{style:{width:"9%"}}),(0,t.jsx)("col",{style:{width:"13%"}}),(0,t.jsx)("col",{style:{width:"12%"}}),(0,t.jsx)("col",{style:{width:"11%"}}),(0,t.jsx)("col",{style:{width:"8%"}}),(0,t.jsx)("col",{style:{width:"8%"}})]}),(0,t.jsx)("thead",{className:"activity-thead",children:(0,t.jsxs)("tr",{children:[(0,t.jsx)("th",{className:"px-4 py-3"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Time"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Decision"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Event"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"CLI"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Tool"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Policy"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Reason"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Mode"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Duration"}),(0,t.jsx)("th",{className:"px-3 py-3 activity-th",children:"Session"})]})}),(0,t.jsx)("tbody",{className:"divide-y divide-border/30",children:V.map((e,r)=>{let n="deny"===e.decision,l=p===r,i="instruct"===e.decision;return(0,t.jsxs)(s.default.Fragment,{children:[(0,t.jsxs)("tr",{onClick:()=>{f(e=>{let t=e===r?null:r,s=V[r];return a("activity_row_toggled",{expanded:null!==t,decision:s?.decision??null,policy_name:s?.policyName??null,event_type:s?.eventType??null}),t})},className:`activity-data-row cursor-pointer transition-colors ${n?"bg-red-500/[0.03] hover:bg-red-500/[0.07] border-l-2 border-l-red-500/40":i?"bg-amber-500/[0.03] hover:bg-amber-500/[0.07] border-l-2 border-l-amber-500/40":r%2==0?"hover:bg-muted/30":"bg-muted/[0.04] hover:bg-muted/30"} ${l?"bg-muted/20":""}`,children:[(0,t.jsx)("td",{className:"px-4 py-2",children:(0,t.jsx)(c.ChevronDown,{className:`h-3.5 w-3.5 text-muted-foreground transition-transform duration-150 ${l?"rotate-0":"-rotate-90"}`})}),(0,t.jsx)("td",{className:"px-3 py-2 text-muted-foreground whitespace-nowrap",title:new Date(e.timestamp).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit"}),children:(0,I.formatRelativeTime)(e.timestamp)}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(A,{decision:e.decision})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(R,{eventType:e.eventType})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(L,{integration:e.integration})}),(0,t.jsx)("td",{className:"px-3 py-2 font-mono text-foreground",children:e.toolName??"—"}),(0,t.jsx)("td",{className:"px-3 py-2 font-mono text-foreground",children:e.policyNames&&e.policyNames.length>1?(0,t.jsxs)("span",{title:e.policyNames.join(", "),children:[e.policyNames[0],(0,t.jsxs)("span",{className:"text-muted-foreground text-[0.6rem]",children:[" +",e.policyNames.length-1]})]}):e.policyName??"—"}),(0,t.jsx)("td",{className:"px-3 py-2 text-muted-foreground truncate",title:e.reason??"",children:e.reason??"—"}),(0,t.jsx)("td",{className:"px-3 py-2",children:e.permissionMode?(0,t.jsx)(E,{mode:e.permissionMode}):"—"}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(U,{ms:e.durationMs})}),(0,t.jsx)("td",{className:"px-3 py-2",title:e.sessionId??"",children:(0,t.jsx)($,{sessionId:e.sessionId,transcriptPath:e.transcriptPath,integration:e.integration,cwd:e.cwd})})]}),l&&(0,t.jsx)(O,{item:e})]},`${e.timestamp}-${r}`)})})]})}),(0,t.jsx)(h.default,{currentPage:d,totalPages:Z,onPageChange:e=>{a("activity_pagination_changed",{from_page:d,to_page:e,total_pages:Z}),m(e),f(null)}})]})]})}function W({enabled:e,onChange:s,disabled:r}){return(0,t.jsx)("button",{onClick:s,disabled:r,className:`relative inline-flex h-4 w-7 shrink-0 items-center rounded-full transition-colors disabled:opacity-40 ${e?"bg-emerald-500":"bg-muted-foreground/30"}`,"aria-label":e?"Disable policy":"Enable policy",children:(0,t.jsx)("span",{className:`inline-block h-3 w-3 rounded-full bg-white shadow transition-transform ${e?"translate-x-3.5":"translate-x-0.5"}`})})}function H({policy:e,onClose:r,onSave:n}){let a=e.params??{},l=e.currentParams??{},[i,o]=(0,s.useState)(()=>{let e={};for(let[t,s]of Object.entries(a)){let r=t in l?l[t]:s.default;e[t]=r}return e});(0,s.useEffect)(()=>{let e=e=>{"Escape"===e.key&&r()};return document.addEventListener("keydown",e),()=>document.removeEventListener("keydown",e)},[r]);let c=(e,t)=>{o(s=>({...s,[e]:t}))};return(0,t.jsx)("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",onClick:e=>{e.target===e.currentTarget&&r()},children:(0,t.jsxs)("div",{className:"bg-card border border-border rounded-lg shadow-xl w-full max-w-lg mx-4 max-h-[80vh] flex flex-col",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-3 border-b border-border",children:[(0,t.jsxs)("div",{children:[(0,t.jsx)("p",{className:"text-sm font-mono font-semibold text-foreground",children:e.name}),(0,t.jsx)("p",{className:"text-xs text-muted-foreground mt-0.5",children:e.description})]}),(0,t.jsx)("button",{onClick:r,className:"text-muted-foreground hover:text-foreground transition-colors",children:(0,t.jsx)(p.X,{className:"h-4 w-4"})})]}),(0,t.jsx)("div",{className:"overflow-y-auto flex-1 px-4 py-4 space-y-4",children:Object.entries(a).map(([e,s])=>(0,t.jsxs)("div",{children:[(0,t.jsx)("label",{className:"block text-xs font-semibold text-foreground mb-1 font-mono",children:e}),(0,t.jsx)("p",{className:"text-[0.65rem] text-muted-foreground mb-1.5",children:s.description}),((e,s)=>{let r=i[e];if("boolean"===s.type)return(0,t.jsxs)("label",{className:"flex items-center gap-2 cursor-pointer",children:[(0,t.jsx)("input",{type:"checkbox",checked:!!r,onChange:t=>c(e,t.target.checked),className:"rounded border-border"}),(0,t.jsx)("span",{className:"text-xs text-muted-foreground",children:s.description})]});if("number"===s.type)return(0,t.jsx)("input",{type:"number",value:"number"==typeof r?r:"",onChange:t=>c(e,Number(t.target.value)),className:"w-full h-7 rounded border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40"});if("string[]"===s.type){let s=Array.isArray(r)?r.join("\n"):"";return(0,t.jsx)("textarea",{value:s,onChange:t=>c(e,t.target.value.split("\n").filter(e=>""!==e.trim())),rows:4,placeholder:"One entry per line",className:"w-full rounded border border-border bg-background px-2 py-1.5 text-xs text-foreground font-mono focus:outline-none focus:ring-2 focus:ring-primary/40 resize-y"})}if("pattern[]"===s.type){let s=Array.isArray(r)?r:[];return(0,t.jsxs)("div",{className:"space-y-1.5",children:[s.map((r,n)=>(0,t.jsxs)("div",{className:"flex gap-1.5 items-center",children:[(0,t.jsx)("input",{type:"text",value:r.regex,onChange:t=>{let r=[...s];r[n]={...r[n],regex:t.target.value},c(e,r)},placeholder:"regex",className:"flex-1 h-6 rounded border border-border bg-background px-2 text-xs font-mono focus:outline-none focus:ring-2 focus:ring-primary/40"}),(0,t.jsx)("input",{type:"text",value:r.label,onChange:t=>{let r=[...s];r[n]={...r[n],label:t.target.value},c(e,r)},placeholder:"label",className:"flex-1 h-6 rounded border border-border bg-background px-2 text-xs focus:outline-none focus:ring-2 focus:ring-primary/40"}),(0,t.jsx)("button",{onClick:()=>c(e,s.filter((e,t)=>t!==n)),className:"text-muted-foreground/50 hover:text-destructive transition-colors",children:(0,t.jsx)(p.X,{className:"h-3.5 w-3.5"})})]},n)),(0,t.jsx)("button",{onClick:()=>c(e,[...s,{regex:"",label:""}]),className:"text-xs text-primary hover:underline",children:"+ Add pattern"})]})}return(0,t.jsx)("input",{type:"text",value:"string"==typeof r?r:"",onChange:t=>c(e,t.target.value),className:"w-full h-7 rounded border border-border bg-background px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-primary/40"})})(e,s)]},e))}),(0,t.jsxs)("div",{className:"flex items-center justify-end gap-2 px-4 py-3 border-t border-border",children:[(0,t.jsx)(T.Button,{variant:"outline",size:"sm",onClick:r,className:"h-7 text-xs",children:"Cancel"}),(0,t.jsx)(T.Button,{size:"sm",onClick:()=>n(i),className:"h-7 text-xs",children:"Save"})]})]})})}function M({message:e,onDismiss:s,onInstall:n,isPending:a}){let{capture:l}=(0,S.usePostHog)();return(0,r.createPortal)((0,t.jsxs)("div",{className:"fixed top-4 right-4 z-[9999] w-full max-w-sm",style:{animation:"slideInFromRight 0.25s ease-out"},children:[(0,t.jsx)("style",{children:`
2
2
  @keyframes slideInFromRight {
3
3
  from { transform: translateX(calc(100% + 1rem)); opacity: 0; }
4
4
  to { transform: translateX(0); opacity: 1; }
@@ -84,10 +84,19 @@ function buildFixes(result: AuditResult): FixRow[] {
84
84
  }));
85
85
  }
86
86
 
87
+ /**
88
+ * The "install all" command.
89
+ *
90
+ * `policy add` and `policies --install` are DIFFERENT commands, not aliases:
91
+ * `policy add` enables exactly one policy and rejects a second name outright
92
+ * ("`policy add` takes exactly one policy name"). This button is almost always
93
+ * multi-policy — listing the gaps is the section's whole job — so it must use
94
+ * the plural form, which is the one that accepts a list. Using `policy add`
95
+ * here handed the user a command that errored on paste.
96
+ */
87
97
  function bulkInstall(fixes: FixRow[]): string {
88
98
  if (fixes.length === 0) return "";
89
- if (fixes.length === 1) return `failproofai policy add ${fixes[0]!.name}`;
90
- return `failproofai policy add ${fixes.map((f) => f.name).join(" ")}`;
99
+ return `failproofai policies --install ${fixes.map((f) => f.name).join(" ")}`;
91
100
  }
92
101
 
93
102
  export function HowToImproveSection({ result, projected, projectedGrade }: Props) {
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
 
3
- import { useState, useCallback } from "react";
3
+ import { useState, useCallback, useEffect, useRef } from "react";
4
4
  import { Copy, Check } from "lucide-react";
5
5
  import { cn } from "@/lib/utils";
6
6
 
@@ -25,6 +25,23 @@ interface CopyButtonProps {
25
25
 
26
26
  export function CopyButton({ text, className }: CopyButtonProps) {
27
27
  const [copied, setCopied] = useState(false);
28
+ const revertTimerRef = useRef<ReturnType<typeof setTimeout>>(undefined);
29
+
30
+ // Clear any pending revert timer on unmount so `setCopied` never fires
31
+ // after the component is gone.
32
+ useEffect(() => {
33
+ return () => {
34
+ if (revertTimerRef.current) clearTimeout(revertTimerRef.current);
35
+ };
36
+ }, []);
37
+
38
+ const armRevertTimer = useCallback(() => {
39
+ // A re-click resets the 2s window rather than being cut short by the
40
+ // previous (stale) timer.
41
+ if (revertTimerRef.current) clearTimeout(revertTimerRef.current);
42
+ setCopied(true);
43
+ revertTimerRef.current = setTimeout(() => setCopied(false), 2000);
44
+ }, []);
28
45
 
29
46
  const handleCopy = useCallback(async () => {
30
47
  try {
@@ -33,24 +50,23 @@ export function CopyButton({ text, className }: CopyButtonProps) {
33
50
  } else if (!fallbackCopyText(text)) {
34
51
  throw new Error("Both clipboard methods failed");
35
52
  }
36
- setCopied(true);
37
- setTimeout(() => setCopied(false), 2000);
53
+ armRevertTimer();
38
54
  } catch (err) {
39
55
  console.error("Failed to copy to clipboard:", err);
40
56
  // Try fallback if the modern API threw
41
57
  try {
42
58
  if (fallbackCopyText(text)) {
43
- setCopied(true);
44
- setTimeout(() => setCopied(false), 2000);
59
+ armRevertTimer();
45
60
  }
46
61
  } catch {
47
62
  // Both methods failed — do nothing
48
63
  }
49
64
  }
50
- }, [text]);
65
+ }, [text, armRevertTimer]);
51
66
 
52
67
  return (
53
68
  <button
69
+ type="button"
54
70
  onClick={handleCopy}
55
71
  title="Copy to clipboard"
56
72
  className={cn(
@@ -1,6 +1,7 @@
1
- import React, { useState, useCallback, useEffect } from "react";
1
+ import React, { useState, useCallback, useEffect, useMemo } from "react";
2
2
  import { Workflow, ChevronRight } from "lucide-react";
3
3
  import type { LogEntry, ToolUseBlock } from "@/lib/log-entries";
4
+ import { buildEntryKeys } from "@/lib/entry-keys";
4
5
  import { cn } from "@/lib/utils";
5
6
  import { ENTRY_BORDER_COLORS } from "./constants";
6
7
  import { TypeBadge } from "./type-badge";
@@ -39,6 +40,10 @@ export function SubagentToolCard({ block, subagentEntries, projectName, sessionI
39
40
 
40
41
  const hasEntries = subagentEntries && subagentEntries.length > 0;
41
42
 
43
+ // Same stable-key treatment as the top-level list — subagent transcripts from
44
+ // uuid-less CLIs collide on timestamp just as readily.
45
+ const subagentKeys = useMemo(() => buildEntryKeys(subagentEntries ?? []), [subagentEntries]);
46
+
42
47
  return (
43
48
  <div className="border border-border/50 rounded-lg p-3 bg-muted/10">
44
49
  {/* Header */}
@@ -94,12 +99,12 @@ export function SubagentToolCard({ block, subagentEntries, projectName, sessionI
94
99
  {subagentEntries && subagentEntries.map((entry) =>
95
100
  entry.type === "queue-operation" ? (
96
101
  <QueueDivider
97
- key={entry.uuid || entry.timestamp}
102
+ key={subagentKeys.get(entry)}
98
103
  entry={entry}
99
104
  />
100
105
  ) : (
101
106
  <EntryRow
102
- key={entry.uuid || entry.timestamp}
107
+ key={subagentKeys.get(entry)}
103
108
  entry={entry}
104
109
  projectName={projectName}
105
110
  sessionId={sessionId}
@@ -9,6 +9,7 @@ import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useSta
9
9
  import { useWindowVirtualizer } from "@tanstack/react-virtual";
10
10
  import { ChevronDown, Wrench } from "lucide-react";
11
11
  import type { LogEntry, ToolUseBlock } from "@/lib/log-entries";
12
+ import { buildEntryKeys } from "@/lib/entry-keys";
12
13
  import { StatsBar } from "@/app/components/log-viewer/stats-bar";
13
14
  import { QueueDivider } from "@/app/components/log-viewer/queue-divider";
14
15
  import { EntryRow } from "@/app/components/log-viewer/entry-row";
@@ -123,8 +124,11 @@ function estimateSize(entry: LogEntry): number {
123
124
 
124
125
  type QueueOperationEntry = Extract<LogEntry, { type: "queue-operation" }>;
125
126
 
126
- function getSegmentId(entry: QueueOperationEntry): string {
127
- return `${entry.uuid}-${entry.timestampMs}`;
127
+ // Segment ids come from the same stable-key map as the rows, so uuid-less
128
+ // transcripts (Codex, Copilot, Cursor, Pi) can't collapse two dividers that
129
+ // happen to share a millisecond into one segment.
130
+ function getSegmentId(entry: QueueOperationEntry, keys: Map<LogEntry, string>): string {
131
+ return keys.get(entry) ?? `${entry.uuid}-${entry.timestampMs}`;
128
132
  }
129
133
 
130
134
  /**
@@ -132,7 +136,7 @@ function getSegmentId(entry: QueueOperationEntry): string {
132
136
  * to the count of non-queue-operation entries in its segment (entries after
133
137
  * it until the next queue-operation or end of list).
134
138
  */
135
- function computeSegments(entries: LogEntry[]): Map<string, number> {
139
+ function computeSegments(entries: LogEntry[], keys: Map<LogEntry, string>): Map<string, number> {
136
140
  const segments = new Map<string, number>();
137
141
  let currentId: string | null = null;
138
142
  let count = 0;
@@ -142,7 +146,7 @@ function computeSegments(entries: LogEntry[]): Map<string, number> {
142
146
  if (currentId !== null) {
143
147
  segments.set(currentId, count);
144
148
  }
145
- currentId = getSegmentId(entry);
149
+ currentId = getSegmentId(entry, keys);
146
150
  count = 0;
147
151
  } else if (currentId !== null) {
148
152
  count++;
@@ -154,11 +158,11 @@ function computeSegments(entries: LogEntry[]): Map<string, number> {
154
158
  return segments;
155
159
  }
156
160
 
157
- function filterVisibleEntries(entries: LogEntry[], collapsedSessions: Set<string>): LogEntry[] {
161
+ function filterVisibleEntries(entries: LogEntry[], collapsedSessions: Set<string>, keys: Map<LogEntry, string>): LogEntry[] {
158
162
  let currentCollapsed = false;
159
163
  return entries.filter((entry) => {
160
164
  if (entry.type === "queue-operation") {
161
- currentCollapsed = collapsedSessions.has(getSegmentId(entry as QueueOperationEntry));
165
+ currentCollapsed = collapsedSessions.has(getSegmentId(entry as QueueOperationEntry, keys));
162
166
  return true; // dividers are always visible
163
167
  }
164
168
  return !currentCollapsed;
@@ -234,11 +238,16 @@ function VirtualizedEntryList({ entries, entriesBySource, projectName, sessionId
234
238
  };
235
239
  }, []);
236
240
 
237
- const segments = useMemo(() => computeSegments(entries), [entries]);
241
+ // One identity per entry, shared by the React key, the segment ids and the
242
+ // virtualizer's measurement cache — all three must agree or rows get
243
+ // measured against the wrong entry.
244
+ const entryKeys = useMemo(() => buildEntryKeys(entries), [entries]);
245
+
246
+ const segments = useMemo(() => computeSegments(entries, entryKeys), [entries, entryKeys]);
238
247
 
239
248
  const visibleEntries = useMemo(
240
- () => filterVisibleEntries(entries, collapsedSessions),
241
- [entries, collapsedSessions],
249
+ () => filterVisibleEntries(entries, collapsedSessions, entryKeys),
250
+ [entries, collapsedSessions, entryKeys],
242
251
  );
243
252
 
244
253
  // UUID-to-index map for visible entries
@@ -303,14 +312,14 @@ function VirtualizedEntryList({ entries, entriesBySource, projectName, sessionId
303
312
  let currentSegmentId: string | null = null;
304
313
  for (const entry of entries) {
305
314
  if (entry.type === "queue-operation") {
306
- currentSegmentId = getSegmentId(entry);
315
+ currentSegmentId = getSegmentId(entry, entryKeys);
307
316
  } else if (entry.uuid === lookupUuid && currentSegmentId) {
308
317
  return currentSegmentId;
309
318
  }
310
319
  }
311
320
  }
312
321
  return null;
313
- }, [highlightedUuid, parentUuidForSubagent, entries, uuidToIndex]);
322
+ }, [highlightedUuid, parentUuidForSubagent, entries, uuidToIndex, entryKeys]);
314
323
 
315
324
  useEffect(() => {
316
325
  if (!segmentToExpand) return;
@@ -337,9 +346,18 @@ function VirtualizedEntryList({ entries, entriesBySource, projectName, sessionId
337
346
  });
338
347
  }, []);
339
348
 
349
+ // getItemKey must match the React key. Without it the virtualizer defaults to
350
+ // keying its size/element caches by index, so collapsing a segment shifts
351
+ // every index and replays one entry's cached height onto a different entry.
352
+ const getItemKey = useCallback(
353
+ (index: number) => entryKeys.get(visibleEntries[index]) ?? index,
354
+ [entryKeys, visibleEntries],
355
+ );
356
+
340
357
  const virtualizer = useWindowVirtualizer({
341
358
  count: visibleEntries.length,
342
359
  estimateSize: (index) => estimateSize(visibleEntries[index]),
360
+ getItemKey,
343
361
  overscan: 5,
344
362
  scrollMargin,
345
363
  });
@@ -370,7 +388,7 @@ function VirtualizedEntryList({ entries, entriesBySource, projectName, sessionId
370
388
  const isTarget = !!highlightedUuid && entry.uuid === (parentUuidForSubagent ?? highlightedUuid);
371
389
  return (
372
390
  <div
373
- key={entry.type === "queue-operation" ? getSegmentId(entry) : (entry.uuid || entry.timestamp)}
391
+ key={virtualRow.key}
374
392
  data-index={virtualRow.index}
375
393
  ref={virtualizer.measureElement}
376
394
  style={{
@@ -384,9 +402,9 @@ function VirtualizedEntryList({ entries, entriesBySource, projectName, sessionId
384
402
  {entry.type === "queue-operation" ? (
385
403
  <QueueDivider
386
404
  entry={entry}
387
- isCollapsed={collapsedSessions.has(getSegmentId(entry))}
388
- entryCount={segments.get(getSegmentId(entry)) ?? 0}
389
- onToggle={() => handleToggleSegment(getSegmentId(entry))}
405
+ isCollapsed={collapsedSessions.has(getSegmentId(entry, entryKeys))}
406
+ entryCount={segments.get(getSegmentId(entry, entryKeys)) ?? 0}
407
+ onToggle={() => handleToggleSegment(getSegmentId(entry, entryKeys))}
390
408
  />
391
409
  ) : (
392
410
  <EntryRow
@@ -575,7 +575,7 @@ function ActivityTab({
575
575
  type="text"
576
576
  value={filterPolicy}
577
577
  onChange={(e) => setFilterPolicy(e.target.value)}
578
- placeholder="filter by policy\u2026"
578
+ placeholder="filter by policy"
579
579
  className="filter-input"
580
580
  />
581
581
  </div>
@@ -1,10 +1,10 @@
1
- # CLI integration tests
1
+ # Integration suite
2
2
 
3
3
  A daily **live-enforcement integration test** for failproofai. It answers one
4
4
  question the unit/e2e suites can't: *does failproofai still enforce against every
5
5
  supported agent CLI, at the versions users actually install today?*
6
6
 
7
- Every day (`.github/workflows/cli-integration.yml`) it installs all 12 agent
7
+ Every day (`.github/workflows/integration-suite.yml`) it installs all 12 agent
8
8
  CLIs **@latest** into an isolated Docker sandbox, drives each one against
9
9
  failproofai's own policies (built from this repo's HEAD), and confirms the hook
10
10
  log shows a **DENY**. A *silent-allow* — a blocked action that ran with no deny —
@@ -20,13 +20,25 @@ vitest suites. So it's a scheduled workflow, not a PR gate.
20
20
 
21
21
  ## How a run works
22
22
 
23
- 1. Build failproofai under test (`dist/index.js` + `dist/cli.mjs`) from this repo.
24
- 2. Restore `cli-integration-state.json` from Actions cache (version-gate +
25
- broke/recovered diff).
26
- 3. Build the sandbox image, install all 12 CLIs (`install-clis.sh`), inject the
27
- OAuth credential files from secrets (`inject-tokens.sh`).
23
+ The workflow is a thin trigger; `ci-entrypoint.sh` is the front door and does
24
+ everything below except the Actions cache restore/save.
25
+
26
+ 1. Restore `integration-suite-state.json` from Actions cache (version-gate +
27
+ broke/recovered diff) *workflow*.
28
+ 2. Build failproofai under test (`dist/index.js` + `dist/cli.mjs`) from this repo.
29
+ 3. Decode the OAuth token secrets, build the sandbox image, create the per-run
30
+ HOME volume, install all 12 CLIs (`install-clis.sh`), inject the credential
31
+ files (`inject-tokens.sh`), assemble the gateway env-file.
28
32
  4. `run.sh` probes each non-gated CLI (`probe-cli.sh`), builds the report
29
33
  (`report.js`), and POSTs it to Slack.
34
+ 5. Cleanup (env-file + volume) runs via `trap`, so it happens on failure too.
35
+
36
+ Run it locally the same way CI does — every input is an env var:
37
+
38
+ ```bash
39
+ CANARY_LLM_API_KEY=... CANARY_SKIP_BUILD=1 \
40
+ bash integration-suite/ci-entrypoint.sh
41
+ ```
30
42
 
31
43
  **Version-gate:** a CLI is re-probed only when its binary version **or**
32
44
  failproofai's HEAD changed since its last green run — unchanged ⇒ can't have
@@ -35,6 +47,11 @@ re-probe until they recover. Dispatch with **force** to probe everything.
35
47
 
36
48
  ## Auth & secrets (the `cli-integration` Environment)
37
49
 
50
+ > The GitHub **Environment** is still named `cli-integration` — it's configured in
51
+ > repo settings, not in this tree, so it was deliberately left alone when this
52
+ > directory was renamed. Renaming it there means renaming `environment:` in the
53
+ > workflow at the same time, or the job loses access to every secret.
54
+
38
55
  Because this repo is public, all credentials live in a scoped **GitHub
39
56
  Environment** (`cli-integration`) — only this workflow's job can read them — and
40
57
  the workflow triggers on `schedule`/`workflow_dispatch` **only**, so fork PRs can
@@ -58,6 +75,7 @@ re-login on the capture machine and refresh the secret.
58
75
  ## Files
59
76
 
60
77
  ```
78
+ ci-entrypoint.sh CI front door: build -> sandbox -> install -> probe -> cleanup
61
79
  Dockerfile non-root sandbox base image
62
80
  install-clis.sh install/upgrade all 12 CLIs @latest (with retries)
63
81
  inject-tokens.sh write captured OAuth creds into the fresh volume