failproofai 0.0.15-beta.0 → 0.0.15

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 (107) 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/audit/page/server-reference-manifest.json +2 -2
  27. package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
  28. package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
  29. package/.next/standalone/.next/server/app/index.html +1 -1
  30. package/.next/standalone/.next/server/app/index.rsc +14 -14
  31. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  32. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
  33. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
  34. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +9 -9
  35. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  36. package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  37. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  39. package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +20 -8
  40. package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
  41. package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
  42. package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  43. package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
  44. package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  45. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  46. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
  47. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
  48. package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  49. package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
  50. package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
  51. package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  52. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +1 -1
  53. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
  54. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1is3glr._.js +1 -1
  55. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
  56. package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +3 -3
  57. package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
  58. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0114ewg._.js +2 -2
  59. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +2 -2
  60. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__04o-kw7._.js → [root-of-the-server]__06b4trb._.js} +2 -2
  61. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +2 -2
  62. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fopait._.js +3 -0
  63. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +2 -2
  64. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +2 -2
  65. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +2 -2
  66. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +10 -10
  67. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ath6v_._.js +2 -2
  68. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +2 -2
  69. package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
  70. package/.next/standalone/.next/server/chunks/ssr/app_audit_loading_tsx_1j1kc6j._.js +1 -1
  71. package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
  72. package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +2 -2
  73. package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_0w82veb.js → node_modules_html-to-image_es_index_0hs_5mh.js} +1 -1
  74. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  75. package/.next/standalone/.next/server/pages/404.html +1 -1
  76. package/.next/standalone/.next/server/pages/500.html +1 -1
  77. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  78. package/.next/standalone/.next/server/server-reference-manifest.json +22 -10
  79. package/.next/standalone/.next/static/chunks/{31c084gsop1bb.js → 0kf9j0pf_j9-0.js} +1 -1
  80. package/.next/standalone/.next/static/chunks/{1qzsbft-jtnf8.js → 1-ng45379-ztb.js} +1 -1
  81. package/.next/standalone/.next/static/chunks/11qhtpk2cvoxv.js +1 -0
  82. package/.next/standalone/.next/static/chunks/{1_20f96f1253b.js → 1_v8b8mxhk25s.js} +1 -1
  83. package/.next/standalone/.next/static/chunks/{312ihvhxeuoi_.js → 2f4mxqkkoa_7d.js} +1 -1
  84. package/.next/standalone/.next/static/chunks/{2xbkqlma_-61k.js → 2geh8s7d3ead-.js} +1 -1
  85. package/.next/standalone/.next/static/chunks/{3q9y67-fobgpc.js → 2h7vw-ojgr9fz.js} +1 -1
  86. package/.next/standalone/.next/static/chunks/33rm-y-i4uzvv.js +6 -0
  87. package/.next/standalone/.next/static/chunks/{1j2xm011_aoae.js → 33u59vf_8xpd-.js} +1 -1
  88. package/.next/standalone/.next/static/chunks/{2y7acsw0--8xf.js → 3m8wmvlhsy1mx.js} +1 -1
  89. package/.next/standalone/app/actions/get-hooks-config.ts +44 -12
  90. package/.next/standalone/app/actions/update-hooks-config.ts +38 -1
  91. package/.next/standalone/app/policies/hooks-client.tsx +38 -14
  92. package/.next/standalone/package.json +1 -1
  93. package/.next/standalone/server.js +1 -1
  94. package/bin/failproofai.mjs +14 -13
  95. package/dist/cli.mjs +172 -97
  96. package/package.json +1 -1
  97. package/src/hooks/custom-hooks-loader.ts +33 -10
  98. package/src/hooks/handler.ts +8 -2
  99. package/src/hooks/hooks-config.ts +31 -5
  100. package/src/hooks/manager.ts +115 -50
  101. package/src/hooks/policy-types.ts +5 -0
  102. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1i21qhv._.js +0 -3
  103. package/.next/standalone/.next/static/chunks/0hn30_j22wpp_.js +0 -6
  104. package/.next/standalone/.next/static/chunks/3060a-0fayz96.js +0 -1
  105. /package/.next/standalone/.next/static/{QFmU1xD4R9N_HVfwccP6A → ePKMmXXfXxThNsxwv1EiF}/_buildManifest.js +0 -0
  106. /package/.next/standalone/.next/static/{QFmU1xD4R9N_HVfwccP6A → ePKMmXXfXxThNsxwv1EiF}/_clientMiddlewareManifest.js +0 -0
  107. /package/.next/standalone/.next/static/{QFmU1xD4R9N_HVfwccP6A → ePKMmXXfXxThNsxwv1EiF}/_ssgManifest.js +0 -0
@@ -10,7 +10,7 @@ import type { HookActivityPayload } from "@/app/actions/get-hook-activity";
10
10
  import { getHooksConfigAction } from "@/app/actions/get-hooks-config";
11
11
  import type { HooksConfigPayload, PolicyInfo, CustomPolicyInfo } from "@/app/actions/get-hooks-config";
12
12
  import type { IntegrationType } from "@/src/hooks/types";
13
- import { togglePolicyAction } from "@/app/actions/update-hooks-config";
13
+ import { toggleCustomPolicyAction, togglePolicyAction } from "@/app/actions/update-hooks-config";
14
14
  import { installHooksWebAction, removeHooksWebAction } from "@/app/actions/install-hooks-web";
15
15
  import { updatePolicyParamsAction } from "@/app/actions/update-policy-params";
16
16
  import { useAutoRefresh } from "@/contexts/AutoRefreshContext";
@@ -382,7 +382,7 @@ function DetailPanel({
382
382
  <td colSpan={11} className="px-0 py-0">
383
383
  <div className="activity-detail animate-expand text-xs">
384
384
  <span className="activity-detail-eyebrow">
385
- <span aria-hidden="true">\u25be</span>
385
+ <span aria-hidden="true">{"\u25BE"}</span>
386
386
  event detail
387
387
  </span>
388
388
  <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-2">
@@ -1214,6 +1214,26 @@ function PoliciesTab({ onHooksInstallChange }: { onHooksInstallChange?: (install
1214
1214
  });
1215
1215
  };
1216
1216
 
1217
+ const handleCustomToggle = (id: string, currentlyEnabled: boolean) => {
1218
+ if (!config) return;
1219
+ setConfig((prev) => prev ? {
1220
+ ...prev,
1221
+ customPolicies: prev.customPolicies?.map((p) => p.id === id ? { ...p, enabled: !currentlyEnabled } : p),
1222
+ conventionPolicies: prev.conventionPolicies.map((entry) => ({
1223
+ ...entry,
1224
+ policies: entry.policies.map((p) => p.id === id ? { ...p, enabled: !currentlyEnabled } : p),
1225
+ })),
1226
+ } : prev);
1227
+ startTransition(async () => {
1228
+ try {
1229
+ await toggleCustomPolicyAction(id, !currentlyEnabled);
1230
+ } catch {
1231
+ fireActionError("custom_policy_toggle", "Failed to save custom policy change.");
1232
+ reload();
1233
+ }
1234
+ });
1235
+ };
1236
+
1217
1237
  const handleApply = () => {
1218
1238
  const { toInstall, toRemove } = pendingChanges;
1219
1239
  if (toInstall.length === 0 && toRemove.length === 0) return;
@@ -1276,7 +1296,7 @@ function PoliciesTab({ onHooksInstallChange }: { onHooksInstallChange?: (install
1276
1296
  if (!config) {
1277
1297
  return (
1278
1298
  <div className="flex items-center justify-center py-16">
1279
- <span className="text-sm text-muted-foreground">Loading\u2026</span>
1299
+ <span className="text-sm text-muted-foreground">Loading{"\u2026"}</span>
1280
1300
  </div>
1281
1301
  );
1282
1302
  }
@@ -1589,7 +1609,7 @@ function PoliciesTab({ onHooksInstallChange }: { onHooksInstallChange?: (install
1589
1609
  })}
1590
1610
 
1591
1611
  {/* Custom policies section */}
1592
- {config.customPoliciesPath && (
1612
+ {(config.customPoliciesPaths?.length || config.customPoliciesPath) && (
1593
1613
  <div>
1594
1614
  {/* Section header — matches category header style */}
1595
1615
  <div className="flex items-center justify-between px-4 py-2.5 bg-muted/20 border-b border-border/50">
@@ -1600,26 +1620,28 @@ function PoliciesTab({ onHooksInstallChange }: { onHooksInstallChange?: (install
1600
1620
  {config.customPolicies?.length ?? 0} detected
1601
1621
  </span>
1602
1622
  </div>
1603
- {/* File path row */}
1604
- <div className="flex items-center gap-3 px-4 py-3 border-b border-border/20">
1605
- <Code className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
1606
- <span className="text-xs font-mono text-muted-foreground truncate">{config.customPoliciesPath}</span>
1607
- </div>
1623
+ {(config.customPoliciesPaths ?? [config.customPoliciesPath!]).map((path) => (
1624
+ <div key={path} className="flex items-center gap-3 px-4 py-3 border-b border-border/20">
1625
+ <Code className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
1626
+ <span className="text-xs font-mono text-muted-foreground truncate">{path}</span>
1627
+ </div>
1628
+ ))}
1608
1629
  {/* Reconfigure notice */}
1609
1630
  <div className="flex items-start gap-2 px-4 py-2.5 border-b border-border/20 bg-muted/10">
1610
1631
  <Shield className="h-3.5 w-3.5 text-muted-foreground/60 shrink-0 mt-0.5" />
1611
1632
  <p className="text-[0.7rem] text-muted-foreground/70 leading-relaxed">
1612
- Custom policies are always active. To add, remove, or reorder them, edit the JS file above.
1633
+ Re-run the install command to add, remove, or reorder files.
1613
1634
  </p>
1614
1635
  </div>
1615
1636
  {/* Rich policy rows — mirrors built-in layout without toggle */}
1616
1637
  {config.customPolicies?.map((policy) => (
1617
1638
  <div
1618
- key={policy.name}
1639
+ key={policy.id}
1619
1640
  className="flex items-start gap-3 px-4 py-3 border-b border-border/20 hover:bg-muted/20 transition-colors"
1620
1641
  >
1621
- {/* Invisible spacer matching PolicyToggle dimensions (h-4 w-7) */}
1622
- <div className="h-4 w-7 shrink-0 mt-0.5" />
1642
+ <div className="mt-0.5 shrink-0">
1643
+ <PolicyToggle enabled={policy.enabled} onChange={() => handleCustomToggle(policy.id, policy.enabled)} disabled={isPending} />
1644
+ </div>
1623
1645
  <div className="flex items-center gap-1.5 min-w-0 w-56 shrink-0 mt-0.5">
1624
1646
  <span className="text-xs font-mono text-foreground truncate">{policy.name}</span>
1625
1647
  </div>
@@ -1670,7 +1692,9 @@ function PoliciesTab({ onHooksInstallChange }: { onHooksInstallChange?: (install
1670
1692
  key={`${entry.path}:${policy.name}`}
1671
1693
  className="flex items-start gap-3 px-4 py-3 border-b border-border/20 hover:bg-muted/20 transition-colors"
1672
1694
  >
1673
- <div className="h-4 w-7 shrink-0 mt-0.5" />
1695
+ <div className="mt-0.5 shrink-0">
1696
+ <PolicyToggle enabled={policy.enabled} onChange={() => handleCustomToggle(policy.id, policy.enabled)} disabled={isPending} />
1697
+ </div>
1674
1698
  <div className="flex items-center gap-1.5 min-w-0 w-56 shrink-0 mt-0.5">
1675
1699
  <span className="text-xs font-mono text-foreground truncate">{policy.name}</span>
1676
1700
  </div>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "failproofai",
3
- "version": "0.0.15-beta.0",
3
+ "version": "0.0.15",
4
4
  "description": "The easiest way to manage policies that keep your AI agents reliable, on-task, and running autonomously — for Claude Code & the Agents SDK",
5
5
  "bin": {
6
6
  "failproofai": "./dist/cli.mjs"
@@ -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":"0.0.15-beta.0"},"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"],"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","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":false,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"partialFallbacks":false,"dynamicOnHover":false,"varyParams":false,"prefetchInlining":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":false,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"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":false,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","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"],"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"},"distDirRoot":".next"}
12
+ const nextConfig = {"env":{"NEXT_PUBLIC_APP_VERSION":"0.0.15"},"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"],"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","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":false,"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"cachedNavigations":false,"partialFallbacks":false,"dynamicOnHover":false,"varyParams":false,"prefetchInlining":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"strictRouteTypes":false,"useTypeScriptCli":false,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":true,"serverComponentsHmrCache":true,"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":false,"turbopackInferModuleSideEffects":true,"turbopackPluginRuntimeStrategy":"childProcesses","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"],"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"},"distDirRoot":".next"}
13
13
 
14
14
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
15
15
 
@@ -164,7 +164,7 @@ COMMANDS
164
164
  --scope user|project|local Config scope to write to (default: user)
165
165
  (Codex / Copilot / Cursor / OpenCode / Pi support user|project only)
166
166
  --beta Include beta policies
167
- --custom, -c <path> Path to a JS file of custom policies
167
+ --custom, -c <path> Custom policy file (repeat for multiple files)
168
168
 
169
169
  policies --uninstall, -u Disable policies or remove hooks
170
170
  [names...] Specific policy names to disable
@@ -172,7 +172,7 @@ COMMANDS
172
172
  Agent CLI(s) to uninstall from
173
173
  --scope user|project|local|all Config scope to remove from (default: user)
174
174
  --beta Remove only beta policies
175
- --custom, -c Clear the customPoliciesPath from config
175
+ --custom, -c Clear all explicit custom policy paths
176
176
 
177
177
  policies --help, -h Show this help for the policies command
178
178
 
@@ -261,7 +261,7 @@ OPTIONS (install)
261
261
  --scope user|project|local Config scope to write to (default: user)
262
262
  (Codex / Copilot / Cursor / OpenCode / Pi support user|project only)
263
263
  --beta Include beta policies
264
- --custom, -c <path> Path to a JS file of custom policies
264
+ --custom, -c <path> Custom policy file (repeat for multiple files)
265
265
  (skips interactive prompt; validates file first)
266
266
 
267
267
  OPTIONS (uninstall)
@@ -270,7 +270,7 @@ OPTIONS (uninstall)
270
270
  Agent CLI(s) to uninstall from
271
271
  --scope user|project|local|all Config scope to remove from (default: user)
272
272
  --beta Remove only beta policies
273
- --custom, -c Clear the customPoliciesPath from config
273
+ --custom, -c Clear all explicit custom policy paths
274
274
 
275
275
  EXAMPLES
276
276
  failproofai policies
@@ -285,6 +285,7 @@ EXAMPLES
285
285
  failproofai policies --install --cli devin --scope project
286
286
  failproofai policies --install --cli claude codex copilot cursor opencode pi hermes openclaw factory devin antigravity goose
287
287
  failproofai policies --install --custom ./my-policies.js
288
+ failproofai policies --install --custom ./security.js --custom ./workflow.js
288
289
  failproofai policies -i -c ./my-policies.js
289
290
  failproofai policies --uninstall block-sudo
290
291
  failproofai policies --uninstall --cli codex
@@ -312,11 +313,11 @@ EXAMPLES
312
313
  throw new CliError(`Invalid scope: ${scope}. Valid values: user, project, local`);
313
314
  }
314
315
 
315
- const customIdx = subArgs.includes("--custom") ? subArgs.indexOf("--custom")
316
- : subArgs.includes("-c") ? subArgs.indexOf("-c")
317
- : -1;
318
- const customPoliciesPath = customIdx >= 0 ? subArgs[customIdx + 1] : undefined;
319
- if (customIdx >= 0 && (!customPoliciesPath || customPoliciesPath.startsWith("-"))) {
316
+ const customIdxs = subArgs
317
+ .map((arg, index) => (arg === "--custom" || arg === "-c" ? index : -1))
318
+ .filter((index) => index >= 0);
319
+ const customPoliciesPaths = customIdxs.map((index) => subArgs[index + 1]);
320
+ if (customPoliciesPaths.some((path) => !path || path.startsWith("-"))) {
320
321
  throw new CliError("Missing path after --custom/-c\nUsage: --custom <path> (e.g. --custom ./my-policies.js)");
321
322
  }
322
323
 
@@ -352,7 +353,7 @@ EXAMPLES
352
353
  // so a policy named "user" isn't incorrectly dropped by the default scope).
353
354
  const consumedIdxs = new Set();
354
355
  if (scopeIdx >= 0) consumedIdxs.add(scopeIdx + 1);
355
- if (customIdx >= 0) consumedIdxs.add(customIdx + 1);
356
+ for (const customIdx of customIdxs) consumedIdxs.add(customIdx + 1);
356
357
  for (const i of cliConsumedIdxs) consumedIdxs.add(i);
357
358
  const flags = new Set(["--install", "-i", "--scope", "--beta", "--custom", "-c", "--cli"]);
358
359
  const unknownInstallFlag = subArgs.find((a) => a.startsWith("-") && !flags.has(a));
@@ -369,7 +370,7 @@ EXAMPLES
369
370
  // prompt — validation of the custom file happens inside installHooks.
370
371
  const policyNames =
371
372
  explicitPolicyNames.length > 0 ? explicitPolicyNames
372
- : customPoliciesPath !== undefined ? []
373
+ : customPoliciesPaths.length > 0 ? []
373
374
  : undefined;
374
375
 
375
376
  const cli = await resolveTargetClis(
@@ -383,7 +384,7 @@ EXAMPLES
383
384
  undefined,
384
385
  includeBeta,
385
386
  undefined,
386
- customPoliciesPath,
387
+ customPoliciesPaths.length > 0 ? customPoliciesPaths : undefined,
387
388
  false,
388
389
  cli,
389
390
  );
@@ -393,7 +394,7 @@ EXAMPLES
393
394
  cli_count: cli.length,
394
395
  explicit_policies: explicitPolicyNames.length > 0,
395
396
  include_beta: includeBeta,
396
- has_custom_path: !!customPoliciesPath,
397
+ has_custom_path: customPoliciesPaths.length > 0,
397
398
  });
398
399
  process.exit(0);
399
400
  }