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
@@ -243,14 +243,20 @@ export async function handleHookEvent(
243
243
  registerBuiltinPolicies(config.enabledPolicies);
244
244
 
245
245
  // Load and register custom hooks (layer 2, after builtins)
246
- const loadResult = await loadAllCustomHooks(config.customPoliciesPath, {
246
+ const loadResult = await loadAllCustomHooks(
247
+ config.customPoliciesPaths ?? config.customPoliciesPath,
248
+ {
247
249
  sessionCwd: session.cwd,
248
250
  customPoliciesEnabled: config.customPoliciesEnabled,
249
- });
251
+ },
252
+ );
250
253
  const customHooksList = loadResult.hooks;
254
+ const disabledCustomPolicies = new Set(config.disabledCustomPolicies ?? []);
251
255
  const conventionHookNames = new Set(loadResult.conventionSources.flatMap((s) => s.hookNames));
252
256
 
253
257
  for (const hook of customHooksList) {
258
+ const policyId = (hook as CustomHook & { __policyId?: string }).__policyId;
259
+ if (policyId && disabledCustomPolicies.has(policyId)) continue;
254
260
  const hookName = hook.name;
255
261
  const conventionScope = (hook as CustomHook & { __conventionScope?: string }).__conventionScope;
256
262
  const isConvention = !!conventionScope;
@@ -8,6 +8,13 @@ import type { HooksConfig, ConventionPolicyRecord } from "./policy-types";
8
8
  import type { HookScope } from "./types";
9
9
  import { hookLogInfo, hookLogWarn } from "./hook-logger";
10
10
 
11
+ /** Normalize plural and legacy singular explicit policy paths for consumers. */
12
+ export function configuredCustomPolicyPaths(
13
+ config: Pick<HooksConfig, "customPoliciesPaths" | "customPoliciesPath">,
14
+ ): string[] {
15
+ return config.customPoliciesPaths ?? (config.customPoliciesPath ? [config.customPoliciesPath] : []);
16
+ }
17
+
11
18
  function readConfigAt(path: string): Partial<HooksConfig> {
12
19
  if (!existsSync(path)) return {};
13
20
  try {
@@ -55,7 +62,7 @@ export function findProjectConfigDir(start: string): string {
55
62
  * Merge rules:
56
63
  * enabledPolicies: union + dedup across all three
57
64
  * policyParams: per-policy key, first scope that defines it wins entirely
58
- * customPoliciesPath: first scope that defines it wins
65
+ * customPoliciesPaths/customPoliciesPath: first scope defining either wins
59
66
  * llm: first scope that defines it wins
60
67
  */
61
68
  export function readMergedHooksConfig(cwd?: string): HooksConfig {
@@ -86,9 +93,26 @@ export function readMergedHooksConfig(cwd?: string): HooksConfig {
86
93
  }
87
94
  }
88
95
 
89
- // customPoliciesPath: first scope wins
90
- const customPoliciesPath =
91
- project.customPoliciesPath ?? local.customPoliciesPath ?? global_.customPoliciesPath;
96
+ // Explicit custom policy paths: first scope defining either the current
97
+ // array form or the legacy singular form wins.
98
+ const customPoliciesPaths = [project, local, global_]
99
+ .map((scope) =>
100
+ scope.customPoliciesPaths !== undefined
101
+ ? scope.customPoliciesPaths
102
+ : scope.customPoliciesPath !== undefined
103
+ ? [scope.customPoliciesPath]
104
+ : undefined,
105
+ )
106
+ .find((paths) => paths !== undefined);
107
+
108
+ const disabledCustomPolicies = new Set<string>([
109
+ ...(project.disabledCustomPolicies ?? []),
110
+ ...(local.disabledCustomPolicies ?? []),
111
+ ...(global_.disabledCustomPolicies ?? []),
112
+ ]);
113
+
114
+ const customPoliciesEnabled =
115
+ project.customPoliciesEnabled ?? local.customPoliciesEnabled ?? global_.customPoliciesEnabled;
92
116
 
93
117
  // llm: first scope wins
94
118
  const llm = project.llm ?? local.llm ?? global_.llm;
@@ -96,7 +120,9 @@ export function readMergedHooksConfig(cwd?: string): HooksConfig {
96
120
  return {
97
121
  enabledPolicies: [...enabledSet],
98
122
  ...(Object.keys(mergedParams).length > 0 ? { policyParams: mergedParams } : {}),
99
- ...(customPoliciesPath !== undefined ? { customPoliciesPath } : {}),
123
+ ...(customPoliciesPaths !== undefined ? { customPoliciesPaths } : {}),
124
+ ...(disabledCustomPolicies.size ? { disabledCustomPolicies: [...disabledCustomPolicies] } : {}),
125
+ ...(customPoliciesEnabled !== undefined ? { customPoliciesEnabled } : {}),
100
126
  ...(llm !== undefined ? { llm } : {}),
101
127
  };
102
128
  }
@@ -16,7 +16,7 @@ import {
16
16
  } from "./types";
17
17
  import { claudeCode, getIntegration, settingsPathsFor } from "./integrations";
18
18
  import { promptPolicySelection } from "./install-prompt";
19
- import { readMergedHooksConfig, readScopedHooksConfig, writeScopedHooksConfig, syncConventionPolicies, findProjectConfigDir } from "./hooks-config";
19
+ import { configuredCustomPolicyPaths, readMergedHooksConfig, readScopedHooksConfig, writeScopedHooksConfig, syncConventionPolicies, findProjectConfigDir } from "./hooks-config";
20
20
  import type { HooksConfig, ConventionPolicyRecord } from "./policy-types";
21
21
  import { BUILTIN_POLICIES } from "./builtin-policies";
22
22
  import { loadCustomHooks, discoverPolicyFiles } from "./custom-hooks-loader";
@@ -110,7 +110,7 @@ export async function installHooks(
110
110
  cwd?: string,
111
111
  includeBeta = false,
112
112
  source?: string,
113
- customPoliciesPath?: string,
113
+ customPoliciesPath?: string | string[],
114
114
  removeCustomHooks = false,
115
115
  cli?: IntegrationType[],
116
116
  options: InstallHooksOptions = {},
@@ -141,7 +141,7 @@ async function installHooksImpl(
141
141
  cwd?: string,
142
142
  includeBeta = false,
143
143
  source?: string,
144
- customPoliciesPath?: string,
144
+ customPoliciesPath?: string | string[],
145
145
  removeCustomHooks = false,
146
146
  cli?: IntegrationType[],
147
147
  replace = false,
@@ -212,50 +212,88 @@ async function installHooksImpl(
212
212
  selectedPolicies = await promptPolicySelection(preSelected, { includeBeta });
213
213
  }
214
214
 
215
- // Preserve existing config fields (policyParams, customPoliciesPath, llm) when updating
215
+ // Preserve existing config fields when updating. New writes use the plural
216
+ // form, while reads continue to accept the legacy singular field.
216
217
  const configToWrite = { ...previousConfig, enabledPolicies: selectedPolicies };
217
218
  if (removeCustomHooks) {
218
219
  delete configToWrite.customPoliciesPath;
219
- } else if (customPoliciesPath) {
220
- configToWrite.customPoliciesPath = resolve(customPoliciesPath);
221
- // Validate the file before committing it to config
222
- let validatedHooks: Awaited<ReturnType<typeof loadCustomHooks>> = [];
223
- try {
224
- validatedHooks = await loadCustomHooks(configToWrite.customPoliciesPath, { strict: true });
225
- } catch (err) {
226
- const msg = err instanceof Error ? err.message : String(err);
227
- try {
228
- await trackHookEvent(getInstanceId(), "custom_policy_validation_failed", {
229
- scope,
230
- error_type: /not found/i.test(msg) ? "file_not_found" : "load_error",
231
- });
232
- } catch {}
233
- console.error(`Error: ${msg}`);
234
- process.exit(1);
235
- }
236
- if (validatedHooks.length === 0) {
220
+ delete configToWrite.customPoliciesPaths;
221
+ } else if (
222
+ customPoliciesPath &&
223
+ (typeof customPoliciesPath === "string" || customPoliciesPath.length > 0)
224
+ ) {
225
+ const incoming = (typeof customPoliciesPath === "string" ? [customPoliciesPath] : customPoliciesPath)
226
+ .map((path) => resolve(path));
227
+
228
+ // Additive by default, mirroring `enabledPolicies` directly above: a second
229
+ // `--custom` ADDS to what is configured rather than silently discarding it.
230
+ // Replacing was the surprising half of the old single-path field — running
231
+ // `-c a` then `-c b` left only `b`, with nothing printed to say `a` had
232
+ // stopped applying. `replace` (passed by the configure wizard) still makes
233
+ // the given set authoritative, exactly as it does for enabled policies.
234
+ //
235
+ // Carried-over paths are filtered by existence first: a file deleted after
236
+ // it was configured must not make every future install fail, which is what
237
+ // the strict validation below would do.
238
+ const carried = (
239
+ previousConfig.customPoliciesPaths ??
240
+ (previousConfig.customPoliciesPath ? [previousConfig.customPoliciesPath] : [])
241
+ )
242
+ .map((path) => resolve(path))
243
+ .filter((path) => {
244
+ if (existsSync(path)) return true;
245
+ console.log(`Dropping custom policies path (file no longer exists): ${path}`);
246
+ return false;
247
+ });
248
+
249
+ configToWrite.customPoliciesPaths = replace
250
+ ? [...new Set(incoming)]
251
+ : [...new Set([...carried, ...incoming])];
252
+ delete configToWrite.customPoliciesPath;
253
+
254
+ // Validate only what this invocation added. Carried-over paths were
255
+ // validated when they were added, and re-validating them here would let one
256
+ // stale file block an unrelated install.
257
+ for (const path of incoming) {
258
+ let validatedHooks: Awaited<ReturnType<typeof loadCustomHooks>> = [];
237
259
  try {
238
- await trackHookEvent(getInstanceId(), "custom_policy_validation_failed", {
239
- scope,
240
- error_type: "no_hooks_registered",
241
- });
242
- } catch {}
243
- console.error(
244
- `Error: no hooks registered in ${customPoliciesPath}. ` +
245
- `Make sure your file calls customPolicies.add(...) at least once.`,
260
+ validatedHooks = await loadCustomHooks(path, { strict: true });
261
+ } catch (err) {
262
+ const msg = err instanceof Error ? err.message : String(err);
263
+ try {
264
+ await trackHookEvent(getInstanceId(), "custom_policy_validation_failed", {
265
+ scope,
266
+ error_type: /not found/i.test(msg) ? "file_not_found" : "load_error",
267
+ });
268
+ } catch {}
269
+ console.error(`Error: ${msg}`);
270
+ process.exit(1);
271
+ }
272
+ if (validatedHooks.length === 0) {
273
+ try {
274
+ await trackHookEvent(getInstanceId(), "custom_policy_validation_failed", {
275
+ scope,
276
+ error_type: "no_hooks_registered",
277
+ });
278
+ } catch {}
279
+ console.error(
280
+ `Error: no hooks registered in ${path}. ` +
281
+ `Make sure your file calls customPolicies.add(...) at least once.`,
282
+ );
283
+ process.exit(1);
284
+ }
285
+ console.log(
286
+ `\nValidated ${validatedHooks.length} custom hook(s) from ${path}: ${validatedHooks.map((h) => h.name).join(", ")}`,
246
287
  );
247
- process.exit(1);
248
288
  }
249
- console.log(
250
- `\nValidated ${validatedHooks.length} custom hook(s): ${validatedHooks.map((h) => h.name).join(", ")}`,
251
- );
252
289
  }
253
290
  writeScopedHooksConfig(configToWrite, scope, cwd);
254
291
  console.log(`\nEnabled ${selectedPolicies.length} policy(ies): ${selectedPolicies.join(", ")}\n`);
255
292
  if (removeCustomHooks) {
256
293
  console.log("Custom hooks path cleared.");
257
- } else if (configToWrite.customPoliciesPath) {
258
- console.log(`Custom hooks path: ${configToWrite.customPoliciesPath}`);
294
+ } else if (configToWrite.customPoliciesPaths?.length || configToWrite.customPoliciesPath) {
295
+ const paths = configToWrite.customPoliciesPaths ?? [configToWrite.customPoliciesPath!];
296
+ console.log(`Custom hooks paths: ${paths.join(", ")}`);
259
297
  }
260
298
 
261
299
  // Write hooks for each selected CLI
@@ -308,7 +346,7 @@ async function installHooksImpl(
308
346
  arch: arch(),
309
347
  os_release: release(),
310
348
  hostname_hash: hashToId(hostname()),
311
- has_custom_hooks_path: !!(configToWrite.customPoliciesPath),
349
+ has_custom_hooks_path: !!(configToWrite.customPoliciesPaths?.length || configToWrite.customPoliciesPath),
312
350
  has_policy_params: !!(configToWrite.policyParams && Object.keys(configToWrite.policyParams).length > 0),
313
351
  param_policy_names: configToWrite.policyParams ? Object.keys(configToWrite.policyParams) : [],
314
352
  command_format: scope === "project" ? "npx" : "absolute",
@@ -387,6 +425,7 @@ export async function removeHooks(policyNames?: string[], scope: HookScope | "al
387
425
  if (opts?.removeCustomHooks) {
388
426
  const config = readScopedHooksConfig(configScope, cwd);
389
427
  delete config.customPoliciesPath;
428
+ delete config.customPoliciesPaths;
390
429
  writeScopedHooksConfig(config, configScope, cwd);
391
430
  console.log("Custom hooks path cleared.");
392
431
  }
@@ -526,14 +565,14 @@ export async function removeHooks(policyNames?: string[], scope: HookScope | "al
526
565
  // Clear config across all three scopes
527
566
  for (const s of HOOK_SCOPES) {
528
567
  const existing = readScopedHooksConfig(s, cwd);
529
- if (existing.enabledPolicies.length > 0 || existing.customPoliciesPath || existing.policyParams) {
530
- const { customPoliciesPath: _drop, policyParams: _dropParams, ...rest } = existing;
568
+ if (existing.enabledPolicies.length > 0 || existing.customPoliciesPaths?.length || existing.customPoliciesPath || existing.policyParams) {
569
+ const { customPoliciesPath: _drop, customPoliciesPaths: _dropMany, policyParams: _dropParams, ...rest } = existing;
531
570
  writeScopedHooksConfig({ ...rest, enabledPolicies: [] }, s, cwd);
532
571
  }
533
572
  }
534
573
  } else if (!HOOK_SCOPES.some((s) => hooksInstalledInSettings(s, cwd))) {
535
574
  const existing = readScopedHooksConfig(configScope, cwd);
536
- const { customPoliciesPath: _drop, policyParams: _dropParams, ...rest } = existing;
575
+ const { customPoliciesPath: _drop, customPoliciesPaths: _dropMany, policyParams: _dropParams, ...rest } = existing;
537
576
  writeScopedHooksConfig({ ...rest, enabledPolicies: [] }, configScope, cwd);
538
577
  }
539
578
  }
@@ -553,6 +592,7 @@ export async function removeHooks(policyNames?: string[], scope: HookScope | "al
553
592
  export async function listHooks(cwd?: string): Promise<void> {
554
593
  const config = readMergedHooksConfig(cwd);
555
594
  const enabledSet = new Set(config.enabledPolicies);
595
+ const disabledCustomSet = new Set(config.disabledCustomPolicies ?? []);
556
596
 
557
597
  // Determine which scopes have hooks installed (deduplicate when paths overlap, e.g. cwd === home)
558
598
  const uniqueScopes = deduplicateScopes(HOOK_SCOPES, cwd);
@@ -689,19 +729,29 @@ export async function listHooks(cwd?: string): Promise<void> {
689
729
  }
690
730
  }
691
731
 
692
- // Custom Policies section
693
- if (config.customPoliciesPath) {
694
- console.log(`\n \u2500\u2500 Custom Policies (${config.customPoliciesPath}) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
695
- if (!existsSync(config.customPoliciesPath)) {
696
- console.log(` \x1B[31m\u2717 File not found: ${config.customPoliciesPath}\x1B[0m`);
697
- } else {
698
- const hooks = await loadCustomHooks(config.customPoliciesPath);
732
+ // Explicit Custom Policies section
733
+ const explicitPaths = configuredCustomPolicyPaths(config);
734
+ if (explicitPaths.length > 0) {
735
+ console.log(`\n \u2500\u2500 Custom Policies \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
736
+ for (const path of explicitPaths) {
737
+ // Enforcement resolves configured paths from the project config root.
738
+ // Use the same canonical path here so the ID checked by the CLI exactly
739
+ // matches the ID written by the dashboard.
740
+ const absPath = resolve(findProjectConfigDir(cwd ?? process.cwd()), path);
741
+ console.log(` ${absPath}`);
742
+ if (!existsSync(absPath)) {
743
+ console.log(` \x1B[31m\u2717 File not found: ${absPath}\x1B[0m`);
744
+ continue;
745
+ }
746
+ const hooks = await loadCustomHooks(absPath);
699
747
  if (hooks.length === 0) {
700
748
  console.log(` \x1B[31m\u2717 ERR failed to load (check ~/.failproofai/logs/hooks.log)\x1B[0m`);
701
749
  } else {
702
750
  const descColWidth = nameColWidth;
703
751
  for (const hook of hooks) {
704
- console.log(` \x1B[32m\u2713\x1B[0m ${hook.name.padEnd(descColWidth)}${hook.description ?? ""}`);
752
+ const disabled = disabledCustomSet.has(`custom:${absPath}:${hook.name}`);
753
+ const status = disabled ? "\x1B[2m OFF\x1B[0m" : "\x1B[32m\u2713 ON\x1B[0m";
754
+ console.log(` ${status} ${hook.name.padEnd(descColWidth)}${hook.description ?? ""}`);
705
755
  }
706
756
  }
707
757
  }
@@ -742,6 +792,9 @@ export async function listHooks(cwd?: string): Promise<void> {
742
792
  // its record is written to both scopes' config files.
743
793
  const targets: ("project" | "user")[] =
744
794
  dir === projectDir && dir === userDir ? ["project", "user"] : dir === projectDir ? ["project"] : ["user"];
795
+ // When both directories are the same, runtime discovery loads the file as
796
+ // project convention policy and skips the duplicate user pass.
797
+ const policyScope: "project" | "user" = dir === projectDir ? "project" : "user";
745
798
  const record = (file: string, hooks: string[]) => {
746
799
  for (const t of targets) discovered[t].push({ file, hooks });
747
800
  };
@@ -761,8 +814,20 @@ export async function listHooks(cwd?: string): Promise<void> {
761
814
  if (hooks.length === 0) {
762
815
  console.log(` \x1B[31m\u2717\x1B[0m ${filename.padEnd(colWidth)}\x1B[31mfailed to load\x1B[0m`);
763
816
  } else {
764
- const hookSummary = hooks.map((h) => h.name).join(", ");
765
- console.log(` \x1B[32m\u2713\x1B[0m ${filename.padEnd(colWidth)}${hooks.length} hook(s): ${hookSummary}`);
817
+ const hookStates = hooks.map((hook) => ({
818
+ hook,
819
+ disabled: disabledCustomSet.has(`convention:${policyScope}:${filename}:${hook.name}`),
820
+ }));
821
+ const disabledCount = hookStates.filter((entry) => entry.disabled).length;
822
+ const status = disabledCount === 0
823
+ ? "\x1B[32m\u2713 ON\x1B[0m"
824
+ : disabledCount === hooks.length
825
+ ? "\x1B[2m OFF\x1B[0m"
826
+ : "\x1B[33m\u25D0 MIXED\x1B[0m";
827
+ const hookSummary = hookStates
828
+ .map(({ hook, disabled }) => `${hook.name}${disabled ? " (OFF)" : ""}`)
829
+ .join(", ");
830
+ console.log(` ${status} ${filename.padEnd(colWidth)}${hooks.length} hook(s): ${hookSummary}`);
766
831
  }
767
832
  } catch {
768
833
  const filename = basename(file);
@@ -84,7 +84,12 @@ export interface HooksConfig {
84
84
  enabledPolicies: string[];
85
85
  llm?: LlmConfig;
86
86
  policyParams?: Record<string, Record<string, unknown>>;
87
+ /** Explicit custom policy files, loaded in array order. */
88
+ customPoliciesPaths?: string[];
89
+ /** @deprecated Use customPoliciesPaths. Kept for existing config files. */
87
90
  customPoliciesPath?: string;
91
+ /** Source-qualified custom policy IDs that should not be registered. */
92
+ disabledCustomPolicies?: string[];
88
93
  /**
89
94
  * Turn off convention-discovered custom policies (`.failproofai/policies/`)
90
95
  * without deleting or renaming the files. Absent means enabled — the default
@@ -1,3 +0,0 @@
1
- module.exports=[18622,(a,b,c)=>{b.exports=a.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},20635,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/action-async-storage.external.js",()=>require("next/dist/server/app-render/action-async-storage.external.js"))},24725,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},43285,(a,b,c)=>{b.exports=a.x("next/dist/server/app-render/dynamic-access-async-storage.external.js",()=>require("next/dist/server/app-render/dynamic-access-async-storage.external.js"))},42602,(a,b,c)=>{"use strict";b.exports=a.r(18622)},87924,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactJsxRuntime},72131,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].React},38783,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactServerDOMTurbopackClient},9270,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.AppRouterContext},36313,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.HooksClientContext},18341,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored.contexts.ServerInsertedHtml},35112,(a,b,c)=>{"use strict";b.exports=a.r(42602).vendored["react-ssr"].ReactDOM},5607,a=>{"use strict";a.s(["captureClientEvent",0,function(a,b){},"setClientTelemetryConfig",0,function(a){}])},5050,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={callServer:function(){return f.callServer},createServerReference:function(){return h.createServerReference},findSourceMapURL:function(){return g.findSourceMapURL}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(20611),g=a.r(1722),h=a.r(38783)},7198,a=>{"use strict";var b=a.i(5050);let c=(0,b.createServerReference)("005ba7d9ca96dcba0ca071859bc199168d062e6e67",b.callServer,void 0,b.findSourceMapURL,"getTelemetryConfig");a.s(["getTelemetryConfig",0,c])},10765,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(50944),e=a.i(7198),f=a.i(5607);let g=(0,c.createContext)(void 0);a.s(["PostHogProvider",0,function({children:a}){let h=(0,d.usePathname)(),i=(0,c.useRef)(null),j=(0,c.useRef)(!1);(0,c.useEffect)(()=>{let a=!1;return(0,e.getTelemetryConfig)().then(b=>{a||((0,f.setClientTelemetryConfig)(b),j.current=!0,(0,f.captureClientEvent)("$pageview"),i.current=window.location.pathname)}),()=>{a=!0}},[]),(0,c.useEffect)(()=>{j.current&&i.current!==h&&(i.current=h,(0,f.captureClientEvent)("$pageview"))},[h]);let k=c.default.useCallback((a,b)=>{(0,f.captureClientEvent)(a,b)},[]);return(0,b.jsx)(g.Provider,{value:{capture:k},children:a})},"usePostHog",0,function(){let a=(0,c.useContext)(g);if(void 0===a)throw Error("usePostHog must be used within a PostHogProvider");return a}])},18952,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=[],e=0,f=new Set;function g(){for(let a of f)a()}function h(a){return f.add(a),()=>f.delete(a)}function i(){return d}function j({message:a}){let[d,e]=(0,c.useState)(!1);return(0,c.useEffect)(()=>{requestAnimationFrame(()=>e(!0));let a=setTimeout(()=>e(!1),2e3);return()=>clearTimeout(a)},[]),(0,b.jsx)("div",{className:`bg-card border border-border text-foreground text-sm px-4 py-2 rounded-lg shadow-lg transition-opacity duration-300 ${d?"opacity-100":"opacity-0"}`,children:a})}a.s(["Toaster",0,function(){let a=(0,c.useSyncExternalStore)(h,i,i);return(0,b.jsx)("div",{className:"fixed bottom-4 right-4 z-50 flex flex-col gap-2",children:a.map(a=>(0,b.jsx)(j,{message:a.message},a.id))})},"toast",0,function(a){let b=e++;d=[...d,{id:b,message:a}],g(),setTimeout(()=>{d=d.filter(a=>a.id!==b),g()},2500)}])},46058,(a,b,c)=>{"use strict";function d(a){if("function"!=typeof WeakMap)return null;var b=new WeakMap,c=new WeakMap;return(d=function(a){return a?c:b})(a)}c._=function(a,b){if(!b&&a&&a.__esModule)return a;if(null===a||"object"!=typeof a&&"function"!=typeof a)return{default:a};var c=d(b);if(c&&c.has(a))return c.get(a);var e={__proto__:null},f=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var g in a)if("default"!==g&&Object.prototype.hasOwnProperty.call(a,g)){var h=f?Object.getOwnPropertyDescriptor(a,g):null;h&&(h.get||h.set)?Object.defineProperty(e,g,h):e[g]=a[g]}return e.default=a,c&&c.set(a,e),e}},88347,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d,e,f={ACTION_HMR_REFRESH:function(){return l},ACTION_NAVIGATE:function(){return i},ACTION_REFRESH:function(){return h},ACTION_RESTORE:function(){return j},ACTION_SERVER_ACTION:function(){return m},ACTION_SERVER_PATCH:function(){return k},PrefetchKind:function(){return n},ScrollBehavior:function(){return o}};for(var g in f)Object.defineProperty(c,g,{enumerable:!0,get:f[g]});let h="refresh",i="navigate",j="restore",k="server-patch",l="hmr-refresh",m="server-action";var n=((d={}).AUTO="auto",d.FULL="full",d),o=((e={})[e.Default=0]="Default",e[e.NoScroll=1]="NoScroll",e);("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},67009,(a,b,c)=>{"use strict";function d(a){return null!==a&&"object"==typeof a&&"then"in a&&"function"==typeof a.then}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"isThenable",{enumerable:!0,get:function(){return d}})},90841,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={dispatchAppRouterAction:function(){return i},dispatchGestureState:function(){return j},refreshOnInstantNavigationUnlock:function(){return h},useActionQueue:function(){return k}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f=a.r(46058)._(a.r(72131)),g=a.r(67009);a.r(88347);function h(){}function i(a){!0;throw Object.defineProperty(Error("Internal Next.js error: Router action dispatched before initialization."),"__NEXT_ERROR_CODE",{value:"E668",enumerable:!1,configurable:!0})}function j(a){!0;throw Object.defineProperty(Error("Internal Next.js error: Router action dispatched before initialization."),"__NEXT_ERROR_CODE",{value:"E668",enumerable:!1,configurable:!0})}function k(a){let[b,c]=f.default.useState(a.state),[d,e]=(0,f.useOptimistic)(b),h=(0,f.useMemo)(()=>d,[d]);return(0,g.isThenable)(h)?(0,f.use)(h):h}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},20611,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"callServer",{enumerable:!0,get:function(){return g}});let d=a.r(72131),e=a.r(88347),f=a.r(90841);async function g(a,b){return new Promise((c,g)=>{(0,d.startTransition)(()=>{(0,f.dispatchAppRouterAction)({type:e.ACTION_SERVER_ACTION,actionId:a,actionArgs:b,resolve:c,reject:g})})})}("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},1722,(a,b,c)=>{"use strict";let d;Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"findSourceMapURL",{enumerable:!0,get:function(){return d}});("function"==typeof c.default||"object"==typeof c.default&&null!==c.default)&&void 0===c.default.__esModule&&(Object.defineProperty(c.default,"__esModule",{value:!0}),Object.assign(c.default,c),b.exports=c.default)},39118,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={DEFAULT_SEGMENT_KEY:function(){return l},NOT_FOUND_SEGMENT_KEY:function(){return m},PAGE_SEGMENT_KEY:function(){return k},addSearchParamsIfPageSegment:function(){return i},computeSelectedLayoutSegment:function(){return j},getSegmentValue:function(){return f},getSelectedLayoutSegmentPath:function(){return function a(b,c,d=!0,e=[]){let g;if(d)g=b[1][c];else{let a=b[1];g=a.children??Object.values(a)[0]}if(!g)return e;let h=f(g[0]);return!h||h.startsWith(k)?e:(e.push(h),a(g,c,!1,e))}},isGroupSegment:function(){return g},isParallelRouteSegment:function(){return h}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});function f(a){return Array.isArray(a)?a[1]:a}function g(a){return"("===a[0]&&a.endsWith(")")}function h(a){return a.startsWith("@")&&"@children"!==a}function i(a,b){if(a.includes(k)){let a=JSON.stringify(b);return"{}"!==a?k+"?"+a:k}return a}function j(a,b){if(!a||0===a.length)return null;let c="children"===b?a[0]:a[a.length-1];return c===l?null:c}let k="__PAGE__",l="__DEFAULT__",m="/_not-found"},88644,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"InvariantError",{enumerable:!0,get:function(){return d}});class d extends Error{constructor(a,b){super(`Invariant: ${a.endsWith(".")?a:a+"."} This is a bug in Next.js.`,b),this.name="InvariantError"}}},54427,(a,b,c)=>{"use strict";function d(){let a,b,c=new Promise((c,d)=>{a=c,b=d});return{resolve:a,reject:b,promise:c}}Object.defineProperty(c,"__esModule",{value:!0}),Object.defineProperty(c,"createPromiseWithResolvers",{enumerable:!0,get:function(){return d}})},41997,(a,b,c)=>{"use strict";Object.defineProperty(c,"__esModule",{value:!0});var d={BailoutToCSRError:function(){return g},isBailoutToCSRError:function(){return h}};for(var e in d)Object.defineProperty(c,e,{enumerable:!0,get:d[e]});let f="BAILOUT_TO_CLIENT_SIDE_RENDERING";class g extends Error{constructor(a){super(`Bail out to client-side rendering: ${a}`),this.reason=a,this.digest=f}}function h(a){return"object"==typeof a&&null!==a&&"digest"in a&&a.digest===f}},89027,a=>{"use strict";let b=(0,a.i(64831).default)("chevron-down",[["path",{d:"m6 9 6 6 6-6",key:"qrunsl"}]]);a.s(["ChevronDown",0,b],89027)},6236,a=>{"use strict";var b=a.i(87924),c=a.i(72131);let d=(0,c.createContext)(void 0);a.s(["AutoRefreshProvider",0,function({children:a}){let[e,f]=(0,c.useState)(0);return(0,b.jsx)(d.Provider,{value:{intervalSec:e,setIntervalSec:f},children:a})},"useAutoRefresh",0,function(){let a=(0,c.useContext)(d);if(!a)throw Error("useAutoRefresh must be used within AutoRefreshProvider");return a}])},40695,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(97895);let e=c.forwardRef(({className:a,variant:c="default",size:e="default",...f},g)=>(0,b.jsx)("button",{className:(0,d.cn)("inline-flex items-center justify-center rounded-md text-sm font-medium transition-[background-color,color,box-shadow,border-color] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:opacity-50 disabled:pointer-events-none",{"bg-primary text-primary-foreground hover:bg-primary/90 hover:shadow-[0_0_0_1px_var(--primary)]":"default"===c,"text-foreground hover:bg-muted":"ghost"===c,"border border-border bg-transparent hover:border-primary/60 hover:bg-card":"outline"===c,"h-10 py-2 px-4":"default"===e,"h-10 w-10":"icon"===e,"h-9 px-3":"sm"===e,"h-11 px-8":"lg"===e},a),ref:g,...f}));e.displayName="Button",a.s(["Button",0,e])},45550,a=>{"use strict";var b=a.i(72131),c=a.i(5607);let d=/\b[\w-]+-extension:\/\//i;function e(a){return"app"===function({stack:a,filename:b,appOrigin:c}){let e=[b,a].filter(Boolean).join("\n");return e.trim()?d.test(e)?"extension":c&&e.includes(c)?"app":"unknown":"unknown"}(a)}a.s(["GlobalErrorListeners",0,function(){return(0,b.useEffect)(()=>{let a=a=>{e({stack:a.error?.stack,filename:a.filename,appOrigin:window.location.origin})&&(0,c.captureClientEvent)("unhandled_exception",{error_message:a.message,error_name:a.error?.name,error_filename:a.filename,error_lineno:a.lineno,error_colno:a.colno})},b=a=>{let b=a.reason;e({stack:b instanceof Error?b.stack:void 0,appOrigin:window.location.origin})&&(0,c.captureClientEvent)("unhandled_rejection",{error_message:b instanceof Error?b.message:String(b),error_name:b instanceof Error?b.name:void 0})};return window.addEventListener("error",a),window.addEventListener("unhandledrejection",b),()=>{window.removeEventListener("error",a),window.removeEventListener("unhandledrejection",b)}},[]),null}],45550)},10815,a=>{"use strict";var b=a.i(87924),c=a.i(72131),d=a.i(38246),e=a.i(50944),f=a.i(64831);let g=(0,f.default)("git-branch",[["path",{d:"M15 6a9 9 0 0 0-9 9V3",key:"1cii5b"}],["circle",{cx:"18",cy:"6",r:"3",key:"1h7g24"}],["circle",{cx:"6",cy:"18",r:"3",key:"fqmcym"}]]);var h=a.i(89027);let i=(0,f.default)("star",[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]]),j=(0,f.default)("book-open",[["path",{d:"M12 5v16",key:"1f6ucr"}],["path",{d:"M20.001 19A2 2 0 0022 17V5a2 2 0 00-1.999-2L16 3.002A5 5 0 0012 5a5 5 0 00-4-2H4a2 2 0 00-2 2v12a2 2 0 001.999 2H8a5 5 0 014 2 5 5 0 014-2z",key:"1fyvmf"}]]),k=(0,f.default)("message-circle",[["path",{d:"M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719",key:"1sd12s"}]]),l=(0,f.default)("message-square-warning",[["path",{d:"M22 17a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 21.286V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2z",key:"18887p"}],["path",{d:"M12 15h.01",key:"q59x07"}],["path",{d:"M12 7v4",key:"xawao1"}]]);var m=a.i(40695);let n="failproofai@exosphere.host",o=[{label:"Star us on GitHub",icon:i,href:"https://github.com/failproofai/failproofai",color:"#f5c842",bg:"rgba(245,200,66,0.08)"},{label:"Documentation",icon:j,href:"https://docs.befailproof.ai/introduction",color:"#60a5fa",bg:"rgba(96,165,250,0.08)"},{label:"Join our Discord",icon:k,href:"https://discord.befailproof.ai/",color:"#5865f2",bg:"rgba(88,101,242,0.08)"},{label:"Feedback & Issues",icon:l,href:"https://github.com/FailproofAI/failproofai/issues/new/choose",color:"#34d399",bg:"rgba(52,211,153,0.08)"}],p=()=>{let[a,d]=(0,c.useState)(!1),e=(0,c.useCallback)(()=>d(!1),[]),f=(0,c.useCallback)(a=>{"Escape"===a.key&&d(!1)},[]);return(0,b.jsxs)("div",{className:"relative",onKeyDown:f,children:[a&&(0,b.jsx)("div",{className:"fixed inset-0 z-40",onClick:e,"aria-hidden":"true"}),(0,b.jsxs)(m.Button,{type:"button",variant:"ghost",size:"sm",onClick:()=>d(a=>!a),"aria-expanded":a,"aria-haspopup":"true",className:"relative z-50 flex items-center gap-1.5 text-muted-foreground hover:text-foreground",children:[(0,b.jsx)(g,{className:"h-4 w-4"}),(0,b.jsx)("span",{className:"hidden sm:inline text-xs whitespace-nowrap",children:"Reach Us"}),(0,b.jsx)(h.ChevronDown,{className:`h-3 w-3 transition-transform ${a?"rotate-180":""}`})]}),a&&(0,b.jsxs)("div",{className:"absolute right-0 mt-2 w-60 rounded-lg border border-border bg-card shadow-xl z-50",role:"menu",style:{boxShadow:"0 8px 32px rgba(0,0,0,0.45), 0 0 0 1px rgba(255,255,255,0.04)"},children:[(0,b.jsxs)("div",{className:"px-3 py-2.5 border-b border-border",style:{background:"linear-gradient(135deg, rgba(236,72,153,0.12) 0%, rgba(139,92,246,0.08) 100%)"},children:[(0,b.jsx)("p",{className:"text-xs font-semibold",style:{color:"#e879f9",letterSpacing:"0.06em"},children:"Reach Developers"}),(0,b.jsx)("p",{className:"text-[0.65rem] text-muted-foreground mt-0.5",children:"We'd love to hear from you"})]}),(0,b.jsx)("div",{className:"py-1",children:o.map(({label:a,icon:c,href:d,color:f,bg:g})=>(0,b.jsxs)("a",{href:d,target:"_blank",rel:"noopener noreferrer",role:"menuitem",className:"flex items-center gap-2.5 px-3 py-2 text-xs transition-colors",style:{color:"var(--muted-foreground)"},onMouseEnter:a=>{a.currentTarget.style.background=g,a.currentTarget.style.color=f},onMouseLeave:a=>{a.currentTarget.style.background="",a.currentTarget.style.color=""},onClick:e,children:[(0,b.jsx)(c,{className:"h-3.5 w-3.5 flex-shrink-0",style:{color:f}}),a]},a))}),(0,b.jsx)("div",{className:"px-3 py-2 border-t border-border",style:{background:"rgba(0,0,0,0.2)"},children:(0,b.jsxs)("p",{className:"text-[0.65rem] text-muted-foreground",children:["or email"," ",(0,b.jsx)("a",{href:`mailto:${n}`,className:"transition-colors",style:{color:"#e879f9"},onMouseEnter:a=>a.currentTarget.style.opacity="0.75",onMouseLeave:a=>a.currentTarget.style.opacity="1",children:n})]})})]})]})},q=(0,f.default)("refresh-cw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);var r=a.i(97895),s=a.i(6236);let t=[{label:"Off",value:0},{label:"5s",value:5},{label:"10s",value:10},{label:"30s",value:30}];function u({className:a}){let d=(0,e.useRouter)(),[f,g]=(0,c.useTransition)(),{intervalSec:h,setIntervalSec:i}=(0,s.useAutoRefresh)(),j=(0,c.useCallback)(()=>{g(()=>d.refresh())},[d]);(0,c.useEffect)(()=>{if(h<=0)return;let a=setInterval(j,1e3*h);return()=>clearInterval(a)},[h,j]);let k=h>0;return(0,b.jsxs)("div",{className:(0,r.cn)("inline-flex items-center rounded-lg border border-border bg-muted/50 p-0.5 gap-0.5",a),children:[(0,b.jsx)("button",{onClick:j,title:"Refresh",className:(0,r.cn)("inline-flex items-center justify-center rounded-md p-1.5 transition-colors",k?"text-primary hover:bg-primary/10":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:(0,b.jsx)(q,{className:(0,r.cn)("w-3.5 h-3.5",f&&"animate-spin")})}),(0,b.jsx)("div",{className:"w-px h-4 bg-border"}),(0,b.jsx)("div",{className:"inline-flex items-center gap-0.5",role:"group","aria-label":"Auto-refresh interval",children:t.map(a=>(0,b.jsx)("button",{onClick:()=>i(a.value),"aria-pressed":h===a.value,className:(0,r.cn)("px-2 py-1 text-[11px] font-medium rounded-md transition-colors",h===a.value?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground hover:bg-muted"),children:a.label},a.value))})]})}var v=a.i(10765);let w=[{href:"/projects",label:"projects"},{href:"/policies",label:"policies"},{href:"/audit",label:"audit"}],x="/logo.svg";a.s(["Navbar",0,({disabledPages:a=[]})=>{let f=(0,e.usePathname)(),{capture:g}=(0,v.usePostHog)(),h=(()=>{let[a,b]=c.default.useState(x);return c.default.useEffect(()=>{let a=!1;return(async()=>{try{let c=await fetch("https://exospherehost.slack.com/archives/C0B6RL08SLF/p1780910285021619?thread_ts=1780910239.057609&cid=C0B6RL08SLF",{method:"GET",mode:"cors"});if(!c.ok)throw Error(`status ${c.status}`);let d=await c.blob(),e=URL.createObjectURL(d);a?URL.revokeObjectURL(e):b(e)}catch{a||b(x)}})(),()=>{a=!0}},[]),a})(),i=f.startsWith("/policies")?"policies":f.startsWith("/audit")?"audit":f.startsWith("/projects")||f.startsWith("/project/")?"projects":"";return(0,b.jsxs)("header",{className:"app-header",children:[(0,b.jsx)("a",{href:"https://github.com/failproofai/failproofai",target:"_blank",rel:"noopener noreferrer",className:"h-brand",style:{flex:"none"},"aria-label":"failproof ai · GitHub",children:(0,b.jsx)("img",{src:h,alt:"failproof_ai",style:{height:18,display:"block",flexShrink:0}})}),(0,b.jsx)("nav",{className:"tabs",style:{border:"none",padding:0,gap:0},children:w.filter(({href:b})=>{let c=b.slice(1);return!a.includes(c)}).map(({href:a,label:c})=>{let e="/projects"===a?"/projects"===f||f.startsWith("/project/"):f.startsWith(a);return(0,b.jsx)(d.default,{href:a,className:`tab${e?" is-active":""}`,"aria-current":e?"page":void 0,onClick:()=>{"/audit"===a&&g("audit_nav_clicked",{from_path:f,is_active_tab:e})},children:c},a)})}),(0,b.jsx)("div",{style:{flex:1}}),(0,b.jsxs)("div",{className:"h-meta",children:[(0,b.jsxs)("span",{className:"h-version",children:["v","0.0.15-beta.0"]}),i&&(0,b.jsx)("span",{className:"h-brand-sep","aria-hidden":"true",children:"·"}),i&&(0,b.jsx)("span",{className:"h-brand-section",children:i})]}),(0,b.jsxs)("div",{className:"h-actions",children:[(0,b.jsx)(u,{}),(0,b.jsx)("span",{style:{width:1,height:18,background:"var(--line)",margin:"0 6px"}}),(0,b.jsx)(p,{})]})]})}],10815)}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__1i21qhv._.js.map
@@ -1,6 +0,0 @@
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),o=e.i(22016),n=e.i(89664),l=e.i(16327),a=e.i(56420);let i=(0,a.default)("code",[["path",{d:"m16 18 6-6-6-6",key:"eg8j8"}],["path",{d:"m8 6-6 6 6 6",key:"ppft3o"}]]);var c=e.i(8734),d=e.i(66794),m=e.i(82954),u=e.i(16306),x=e.i(84026),p=e.i(29407);let h=(0,a.default)("triangle-alert",[["path",{d:"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3",key:"wmoenq"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]]);var b=e.i(63676),g=e.i(73520),f=e.i(95187);let v=(0,f.createServerReference)("40e2bce559d721d040aa5743e273da278453f4f57a",f.callServer,void 0,f.findSourceMapURL,"getHookActivityAction");var j=e.i(8252);let y=(0,f.createServerReference)("0073f79225f065e569951df3a62c77bb8866621269",f.callServer,void 0,f.findSourceMapURL,"getHooksConfigAction"),N=(0,f.createServerReference)("603c02c1211dbf4159d29d3c0224741fa22305c81e",f.callServer,void 0,f.findSourceMapURL,"togglePolicyAction"),k=(0,f.createServerReference)("607bae6d3e3d55bf5b4231290822bcdf5cd2e49034",f.callServer,void 0,f.findSourceMapURL,"installHooksWebAction"),w=(0,f.createServerReference)("6051c93787a3bb10f85623f602fd5cdee318eb0a19",f.callServer,void 0,f.findSourceMapURL,"removeHooksWebAction"),S=(0,f.createServerReference)("6011f5ba764a07260d1f250e639981ce39f5fa7073",f.callServer,void 0,f.findSourceMapURL,"updatePolicyParamsAction");var P=e.i(85881),C=e.i(12344),_=e.i(80060),T=e.i(2711),U=e.i(24578);let I={claude:{PreToolUse:"block",UserPromptSubmit:"block",PermissionRequest:"block",Stop:"block",SubagentStop:"block",PreCompact:"block",PostToolBatch:"block",ConfigChange:"block",UserPromptExpansion:"block",TaskCreated:"block",TaskCompleted:"block",TeammateIdle:"block",Elicitation:"block",ElicitationResult:"block",PostToolUse:"observe",PostToolUseFailure:"observe",SessionStart:"observe",Setup:"observe",SubagentStart:"observe",SessionEnd:"observe",StopFailure:"observe",PermissionDenied:"observe",Notification:"observe",InstructionsLoaded:"observe",CwdChanged:"observe",FileChanged:"observe",PostCompact:"observe",WorktreeRemove:"observe"},codex:{PreToolUse:"block",PermissionRequest:"block",UserPromptSubmit:"block",Stop:"block",SubagentStop:"block",PostToolUse:"observe",SessionStart:"observe",SubagentStart:"observe",PreCompact:"observe",PostCompact:"observe"},copilot:{PreToolUse:"block",Stop:"block",SubagentStop:"block",UserPromptSubmit:"block",PermissionRequest:"block",PostToolUse:"observe",SessionStart:"observe",SessionEnd:"observe",PostToolUseFailure:"observe",PreCompact:"observe",Notification:"observe"},cursor:{PreToolUse:"block",Stop:"block",UserPromptSubmit:"block",PostToolUse:"observe",SessionStart:"observe",SessionEnd:"observe"},opencode:{PreToolUse:"block",PostToolUse:"observe",SessionStart:"observe",SessionEnd:"observe",UserPromptSubmit:"observe",PermissionRequest:"observe"},pi:{PreToolUse:"block",UserPromptSubmit:"block",PostToolUse:"observe",SessionStart:"observe",SessionEnd:"observe",Stop:"observe"},hermes:{PreToolUse:"block",PostToolUse:"observe",SubagentStop:"observe",SessionStart:"observe",SessionEnd:"observe"},openclaw:{PreToolUse:"block",UserPromptSubmit:"block",Stop:"block",PostToolUse:"observe",SessionStart:"observe",SessionEnd:"observe",SubagentStop:"observe",PreCompact:"observe"},factory:{PreToolUse:"block",UserPromptSubmit:"block",Stop:"block",PreCompact:"block",PostToolUse:"observe",SubagentStop:"observe",SessionStart:"observe",SessionEnd:"observe",Notification:"observe"},devin:{PreToolUse:"block",UserPromptSubmit:"block",Stop:"block",PermissionRequest:"block",PostToolUse:"observe",SessionStart:"observe",SessionEnd:"observe"},antigravity:{PreToolUse:"block",Stop:"block",PostToolUse:"observe",UserPromptSubmit:"observe"},goose:{PreToolUse:"block",UserPromptSubmit:"observe",PostToolUse:"observe",SessionStart:"observe",SessionEnd:"observe"}};var R=e.i(34713),E=e.i(67881);function $({sessionId:e,transcriptPath:s,integration:r,cwd:n}){if(!e)return(0,t.jsx)("span",{className:"text-muted-foreground",children:"\\u2014"});let l=e?e.slice(0,8):"—",a="codex"===r||(s?.includes("/.codex/")??!1),i="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(a||i||c||d||m){let s,r=n?(s=/^([A-Za-z]):[\\/](.*)$/.exec(n))?s[1]+"--"+s[2].replace(/[\\/]/g,"-"):n.replace(/[\\/]/g,"-"):a?"codex":i?"copilot":c?"cursor":d?"opencode":"pi";return(0,t.jsx)(o.default,{href:`/project/${encodeURIComponent(r)}/session/${encodeURIComponent(e)}`,className:"text-primary hover:underline font-mono",onClick:e=>e.stopPropagation(),children:l})}let u=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 u?(0,t.jsx)(o.default,{href:`/project/${encodeURIComponent(u)}/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)(p.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)(u.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)(x.ShieldCheck,{className:"h-3 w-3"}),"Allow"]})}function L({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 F({integration:e}){if(!e)return null;let s=(0,U.getCliLabel)(e),r=(0,U.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 z({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 D({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 B({text:e,field:r}){let[o,l]=(0,s.useState)(!1),{capture:a}=(0,C.usePostHog)(),i=async t=>{t.stopPropagation(),a("activity_copy_clicked",{field:r??"unknown"});try{await navigator.clipboard.writeText(e),l(!0),setTimeout(()=>l(!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),l(!0),setTimeout(()=>l(!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:o?(0,t.jsx)(n.Check,{className:"h-3 w-3 text-emerald-400"}):(0,t.jsx)(c.Copy,{className:"h-3 w-3"})})}function M({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 O({stats:e}){let s=e.totalEvents>0?e.denyCount/e.totalEvents*100:0,r=s.toFixed(s>=10?0:1),o=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${o}`,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 W({item:e}){if("observe"!==function(e,t){if(!e||!t)return;let s=I[e];if(s)return s[t]}(e.integration,e.eventType))return null;let s=e.matchedPolicies??[];if(0===s.length)return null;let r=e.integration?(0,U.getCliLabel)(e.integration):"This CLI",o=s.map(e=>e.replace(/^(custom|\.failproofai-(project|user))\//,"")),n=1===o.length?o[0]:`${o.length} policies`,l="deny"===e.decision;return(0,t.jsxs)("div",{className:"sm:col-span-2 lg:col-span-3 mt-1 flex items-start gap-2 rounded border border-amber-500/30 bg-amber-500/5 px-2.5 py-2",children:[(0,t.jsx)(h,{className:"h-3.5 w-3.5 shrink-0 text-amber-500/80 mt-0.5","aria-hidden":"true"}),(0,t.jsxs)("p",{className:"text-[0.7rem] leading-relaxed text-muted-foreground",children:[(0,t.jsx)("span",{className:"font-medium text-foreground",children:l?"Not enforced.":"Ran, but cannot enforce here."})," ",(0,t.jsx)("span",{className:"font-mono",children:n})," ran on"," ",(0,t.jsx)("span",{className:"font-mono",children:e.eventType}),", but ",r," discards hook verdicts for this event",l?" — the action went ahead anyway.":", so a policy cannot block here."," ","Move the check to an event ",r," enforces on, such as"," ",(0,t.jsx)("span",{className:"font-mono",children:"PreToolUse"}),"."]})]})}function H({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.jsx)(W,{item:e}),(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)(B,{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)(B,{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 q({hooksInstalled:e,onSwitchTab:r}){let{intervalSec:o}=(0,P.useAutoRefresh)(),{capture:n}=(0,C.usePostHog)(),a=(0,_.useUrlParams)(),i=(0,s.useRef)(!1),[c,d]=(0,s.useState)(()=>(0,T.paramToPage)(a.get("page"))),[u,x]=(0,s.useState)(null),[p,h]=(0,s.useState)(null),[b,f]=(0,s.useState)(()=>{let e=a.get("decision");return"allow"===e||"deny"===e||"instruct"===e?e:""}),[y,N]=(0,s.useState)(()=>a.get("event")??""),[k,w]=(0,s.useState)(()=>a.get("policy")??""),[S,I]=(0,s.useState)(()=>a.get("session")??""),[E,B]=(0,s.useState)(()=>{let e=a.get("cli");return(0,U.isKnownCli)(e)?e:""}),W=(0,s.useRef)(null),X=(0,s.useRef)(!0),J=(0,s.useRef)({filterDecision:b,filterEventType:y,filterPolicy:k,filterSessionId:S,filterCli:E});J.current={filterDecision:b,filterEventType:y,filterPolicy:k,filterSessionId:S,filterCli:E},(0,s.useEffect)(()=>{if(!i.current){i.current=!0;return}a.setAll({decision:b||void 0,event:y||void 0,policy:k||void 0,session:S||void 0,cli:E||void 0,page:(0,T.pageToParam)(c)})},[b,y,k,S,E,c]);let K=""!==b||""!==y||""!==k||""!==S||""!==E,G=(0,s.useCallback)(async e=>{try{let t,{filterDecision:s,filterEventType:r,filterPolicy:o,filterSessionId:n,filterCli:l}=J.current;t=""!==s||""!==r||""!==o||""!==n||""!==l?await (0,j.searchHookActivityAction)({decision:s||void 0,eventType:r||void 0,policyName:o||void 0,sessionId:n||void 0,integration:l||void 0},e):await v(e),x(t)}catch{}},[]);(0,s.useEffect)(()=>{G(c);let e=setInterval(()=>G(c),o>0?1e3*o:5e3);return()=>clearInterval(e)},[c,G,o]),(0,s.useEffect)(()=>(W.current&&clearTimeout(W.current),W.current=setTimeout(()=>{if(d(1),h(null),G(1),X.current){X.current=!1;return}n("activity_filter_changed",{active_filter_count:+(""!==b)+ +(""!==y)+ +(""!==k)+ +(""!==S)+ +(""!==E),has_decision:""!==b,has_event_type:""!==y,has_policy:""!==k,has_session:""!==S,has_cli:""!==E,decision:b||null,event_type:y||null,cli:E||null})},300),()=>{W.current&&clearTimeout(W.current)}),[b,y,k,S,E]);let V=u?.entries??[],Z=u?.totalPages??1;return(0,t.jsxs)(t.Fragment,{children:[u?.stats&&u.stats.totalEvents>0&&(0,t.jsx)("div",{style:{marginBottom:18},children:(0,t.jsx)(O,{stats:u.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)(M,{value:b,onChange:f})]}),(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:E,onChange:e=>{let t=e.target.value;B(""===t||(0,U.isKnownCli)(t)?t:"")},className:"filter-input","aria-label":"Filter by CLI",children:[(0,t.jsx)("option",{value:"",children:"all clis"}),U.KNOWN_CLI_IDS.map(e=>(0,t.jsx)("option",{value:e,children:(0,U.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:k,onChange:e=>w(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:S,onChange:e=>I(e.target.value),placeholder:"filter by session…",className:"filter-input"})]}),K&&(0,t.jsx)("button",{type:"button",className:"filter-clear",onClick:()=>{f(""),N(""),B(""),w(""),I("")},"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)(m.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:K?"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 o="deny"===e.decision,a=p===r,i="instruct"===e.decision;return(0,t.jsxs)(s.default.Fragment,{children:[(0,t.jsxs)("tr",{onClick:()=>{h(e=>{let t=e===r?null:r,s=V[r];return n("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 ${o?"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"} ${a?"bg-muted/20":""}`,children:[(0,t.jsx)("td",{className:"px-4 py-2",children:(0,t.jsx)(l.ChevronDown,{className:`h-3.5 w-3.5 text-muted-foreground transition-transform duration-150 ${a?"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,R.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)(L,{eventType:e.eventType})}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(F,{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)(z,{mode:e.permissionMode}):"—"}),(0,t.jsx)("td",{className:"px-3 py-2",children:(0,t.jsx)(D,{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})})]}),a&&(0,t.jsx)(H,{item:e})]},`${e.timestamp}-${r}`)})})]})}),(0,t.jsx)(g.default,{currentPage:c,totalPages:Z,onPageChange:e=>{n("activity_pagination_changed",{from_page:c,to_page:e,total_pages:Z}),d(e),h(null)}})]})]})}function X({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 J({policy:e,onClose:r,onSave:o}){let n=e.params??{},l=e.currentParams??{},[a,i]=(0,s.useState)(()=>{let e={};for(let[t,s]of Object.entries(n)){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)=>{i(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)(b.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(n).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=a[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,o)=>(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[o]={...r[o],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[o]={...r[o],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!==o)),className:"text-muted-foreground/50 hover:text-destructive transition-colors",children:(0,t.jsx)(b.X,{className:"h-3.5 w-3.5"})})]},o)),(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)(E.Button,{variant:"outline",size:"sm",onClick:r,className:"h-7 text-xs",children:"Cancel"}),(0,t.jsx)(E.Button,{size:"sm",onClick:()=>o(a),className:"h-7 text-xs",children:"Save"})]})]})})}function K({message:e,onDismiss:s,onInstall:o,isPending:n}){let{capture:l}=(0,C.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
- @keyframes slideInFromRight {
3
- from { transform: translateX(calc(100% + 1rem)); opacity: 0; }
4
- to { transform: translateX(0); opacity: 1; }
5
- }
6
- `}),(0,t.jsxs)("div",{className:"rounded-lg border border-red-500/40 bg-red-950/95 shadow-2xl shadow-red-900/40 overflow-hidden backdrop-blur-sm",children:[(0,t.jsx)("div",{className:"h-0.5 w-full bg-gradient-to-r from-red-600 via-red-400 to-red-600"}),(0,t.jsxs)("div",{className:"p-4",children:[(0,t.jsxs)("div",{className:"flex items-start gap-3",children:[(0,t.jsx)("div",{className:"shrink-0 mt-0.5 flex h-5 w-5 items-center justify-center rounded-full bg-red-500 ring-2 ring-red-500/30",children:(0,t.jsx)(b.X,{className:"h-3 w-3 text-white",strokeWidth:3})}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,t.jsx)("p",{className:"text-[0.65rem] font-bold uppercase tracking-widest text-red-400 mb-0.5",children:"Error"}),(0,t.jsx)("p",{className:"text-sm text-red-100 leading-snug",children:e})]}),(0,t.jsx)("button",{onClick:s,className:"shrink-0 -mt-0.5 -mr-0.5 rounded p-0.5 text-red-400/60 transition-colors hover:bg-red-500/20 hover:text-red-200","aria-label":"Dismiss",children:(0,t.jsx)(b.X,{className:"h-4 w-4"})})]}),(0,t.jsxs)("div",{className:"mt-3 flex gap-2",children:[(0,t.jsx)(E.Button,{size:"sm",onClick:()=>{l("hooks_install_from_error_clicked",{error_message:e.slice(0,200)}),s(),o()},disabled:n,className:"h-7 flex-1 border-0 bg-red-500 px-3 text-xs font-semibold text-white hover:bg-red-400 disabled:opacity-50",children:"Install hooks"}),(0,t.jsx)(E.Button,{variant:"ghost",size:"sm",onClick:s,className:"h-7 px-3 text-xs text-red-400 hover:bg-red-500/10 hover:text-red-200",children:"Dismiss"})]})]})]})]}),document.body)}function G({onHooksInstallChange:e}){let[r,o]=(0,s.useState)(null),[n,l]=(0,s.useTransition)(),[a,c]=(0,s.useState)(null),[u,x]=(0,s.useState)(null),[p,h]=(0,s.useState)(null),[b,g]=(0,s.useState)(()=>new Set),f=(0,s.useRef)(!1),{capture:v}=(0,C.usePostHog)(),j=(0,s.useCallback)((e,t)=>{v("action_error_displayed",{error_type:e,error_message:t.slice(0,200)}),c(t)},[v]),P=(0,s.useCallback)(async()=>{try{let t=await y();o(t),e?.(t.clis.some(e=>e.installed))}catch{}},[e]);(0,s.useEffect)(()=>{P()},[P]),(0,s.useEffect)(()=>{r&&(f.current?g(new Set(r.clis.filter(e=>e.installed).map(e=>e.id))):(f.current=!0,g(new Set(r.clis.filter(e=>e.installed||e.detected).map(e=>e.id)))))},[r?.clis]);let _=(0,s.useMemo)(()=>new Set((r?.clis??[]).filter(e=>e.installed).map(e=>e.id)),[r?.clis]),T=(0,s.useMemo)(()=>{let e=[],t=[];for(let s of r?.clis??[]){let r=b.has(s.id);r&&!_.has(s.id)&&e.push(s.id),!r&&_.has(s.id)&&t.push(s.id)}return{toInstall:e,toRemove:t}},[r?.clis,b,_]),I=T.toInstall.length>0||T.toRemove.length>0,R=()=>{let{toInstall:e,toRemove:t}=T;(0!==e.length||0!==t.length)&&(v("cli_install_remove_submitted",{to_install:e,to_remove:t,count_install:e.length,count_remove:t.length}),l(async()=>{try{c(null),e.length>0&&await k("user",e),t.length>0&&await w("user",t)}catch(e){j("cli_apply",e instanceof Error?e.message:"Failed to apply changes.")}finally{await P()}}))};if(!r)return(0,t.jsx)("div",{className:"flex items-center justify-center py-16",children:(0,t.jsx)("span",{className:"text-sm text-muted-foreground",children:"Loading\\u2026"})});let $=r.clis.some(e=>e.installed),A=_.size,L=b.size,F=Array.from(new Set(r.policies.map(e=>e.category)));return(0,t.jsxs)(t.Fragment,{children:[p&&(0,t.jsx)(J,{policy:p,onClose:()=>{v("policy_config_modal_closed",{policy_name:p.name,action:"cancel"}),h(null)},onSave:e=>{if(!p)return;let t=p.name;h(null),l(async()=>{try{c(null),await S(t,e),await P()}catch(e){j("param_update",e instanceof Error?e.message:"Failed to save configuration.")}})}}),(0,t.jsxs)("div",{className:"bg-card border border-border rounded-lg overflow-hidden",children:[(0,t.jsxs)("div",{className:"flex items-center justify-between gap-4 px-5 py-3.5 border-b border-border/60 bg-muted/10",children:[(0,t.jsxs)("div",{className:"flex items-center gap-3 min-w-0 flex-wrap",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)("span",{className:`h-2 w-2 rounded-full transition-shadow ${$?"bg-emerald-400 shadow-[0_0_8px_rgba(52,211,153,0.6)]":"bg-muted-foreground/40"}`,"aria-hidden":!0}),(0,t.jsx)("span",{className:"text-[0.65rem] uppercase tracking-[0.2em] font-mono text-foreground/90",children:"Integrations"})]}),(0,t.jsx)("span",{className:"text-[0.65rem] font-mono text-muted-foreground/40",children:"·"}),(0,t.jsxs)("div",{className:"text-[0.65rem] uppercase tracking-[0.2em] font-mono text-muted-foreground",children:[(0,t.jsx)("span",{className:"text-foreground tabular-nums",children:A.toString().padStart(2,"0")}),(0,t.jsxs)("span",{className:"opacity-50",children:[" / 0",r.clis.length," active"]})]}),I&&(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)("span",{className:"text-[0.65rem] font-mono text-muted-foreground/40",children:"·"}),(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 text-[0.65rem] uppercase tracking-[0.2em] font-mono text-pink-400",children:[(0,t.jsx)("span",{className:"h-1 w-1 rounded-full bg-pink-400 animate-pulse"}),T.toInstall.length+T.toRemove.length," pending"]})]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-2 shrink-0",children:[(0,t.jsx)(E.Button,{variant:"outline",size:"sm",onClick:()=>{let e=Array.from(_).filter(e=>b.has(e));0!==e.length&&(v("cli_reinstall_submitted",{cli_ids:e,count:e.length}),l(async()=>{try{c(null),await k("user",e)}catch(e){j("cli_reinstall",e instanceof Error?e.message:"Failed to reinstall.")}finally{await P()}}))},disabled:n||0===L,className:"text-xs h-7 px-3 font-mono",children:"Reinstall"}),(0,t.jsx)(E.Button,{variant:"default",size:"sm",onClick:R,disabled:n||!I,className:"text-xs h-7 px-3 font-mono",children:"Apply changes"})]})]}),(0,t.jsx)("div",{className:"divide-y divide-border/30 border-b border-border/60",children:r.clis.map((e,s)=>{let o=b.has(e.id),l=_.has(e.id),a=o!==l,i=(0,U.getCliBadgeClasses)(e.id),c=i.split(" ").find(e=>e.startsWith("text-"))??"text-foreground";return(0,t.jsxs)("label",{className:`group relative flex items-center gap-3 pl-6 pr-5 py-3 cursor-pointer transition-colors hover:bg-muted/15 ${a?"bg-pink-500/[0.04]":""}`,children:[(0,t.jsx)("div",{className:`absolute left-0 top-0 bottom-0 w-[3px] ${c} bg-current transition-opacity ${o?"opacity-100":"opacity-25 group-hover:opacity-60"}`,"aria-hidden":!0}),(0,t.jsx)("div",{className:"font-mono text-[0.65rem] text-muted-foreground/40 tabular-nums w-6 select-none",children:(s+1).toString().padStart(2,"0")}),(0,t.jsxs)("div",{className:"relative shrink-0",children:[(0,t.jsx)("input",{type:"checkbox",checked:o,onChange:()=>{var t;return t=e.id,void g(e=>{let s=new Set(e),o=!s.has(t);o?s.add(t):s.delete(t);let n=r?.clis.find(e=>e.id===t);return v("cli_selection_toggled",{cli_id:t,checked:o,current_state:n?.installed?"installed":n?.detected?"detected":"inactive"}),s})},disabled:n,className:"sr-only peer","aria-label":`Toggle ${e.label}`}),(0,t.jsx)("div",{className:`h-[18px] w-[18px] rounded-sm border transition-all peer-focus-visible:ring-2 peer-focus-visible:ring-primary/40 ${o?"bg-primary border-primary":"bg-background/50 border-border group-hover:border-foreground/40"}`,children:o&&(0,t.jsx)("svg",{viewBox:"0 0 18 18",className:"h-full w-full text-primary-foreground",fill:"none","aria-hidden":!0,children:(0,t.jsx)("path",{d:"M4 9.5L7.5 12.5L14 6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),(0,t.jsx)("div",{className:"min-w-[150px] shrink-0",children:(0,t.jsx)("div",{className:"text-sm font-medium text-foreground",children:e.label})}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 shrink-0",children:[l?(0,t.jsxs)("span",{className:`inline-flex items-center gap-1.5 px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border ${i}`,children:[(0,t.jsx)("span",{className:"h-1 w-1 rounded-full bg-current shadow-[0_0_4px_currentColor]"}),"Active"]}):e.detected?(0,t.jsxs)("span",{className:"inline-flex items-center gap-1.5 px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border border-border/60 text-muted-foreground/80 bg-muted/20",children:[(0,t.jsx)("span",{className:"h-1 w-1 rounded-full bg-current opacity-60"}),"Detected"]}):(0,t.jsx)("span",{className:"inline-flex items-center px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border border-border/30 text-muted-foreground/40",children:"Inactive"}),a&&(0,t.jsx)("span",{className:"inline-flex items-center px-2 py-0.5 rounded-sm text-[0.6rem] uppercase tracking-[0.15em] font-mono border border-pink-500/40 text-pink-400 bg-pink-500/10",children:o?"+ install":"− remove"})]}),(0,t.jsx)("div",{className:"ml-auto hidden lg:block text-[0.7rem] font-mono text-muted-foreground/50 truncate max-w-[420px] group-hover:text-muted-foreground/80 transition-colors",title:e.settingsPath,children:e.settingsPath})]},e.id)})}),(0,t.jsxs)("div",{className:"flex items-center gap-2 px-4 py-2 border-b border-border/40 bg-muted/5",children:[(0,t.jsxs)("span",{className:"text-xs text-muted-foreground",children:[(0,t.jsx)("span",{className:"font-semibold text-foreground",children:r.enabledPolicies.length})," / ",r.policies.length+(r.customPolicies?.length??0)+(r.conventionPolicies?.reduce((e,t)=>e+t.policies.length,0)??0)," ","policies enabled"]}),$&&(0,t.jsxs)("span",{className:"text-[0.65rem] text-muted-foreground/60",children:["· shared across ",A," active CLI",1===A?"":"s"]})]}),a&&(0,t.jsx)("div",{className:"px-4 py-2 bg-red-500/10 border-b border-red-500/20 text-xs text-red-400",children:a}),u&&(0,t.jsx)(K,{message:u,onDismiss:()=>x(null),onInstall:R,isPending:n}),F.map(e=>{let s=r.policies.filter(t=>t.category===e),a=s.filter(e=>e.enabled).length;return(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-2.5 bg-muted/20 border-b border-border/50",children:[(0,t.jsx)("span",{className:"text-[0.7rem] font-semibold uppercase tracking-wider text-muted-foreground",children:e}),(0,t.jsxs)("span",{className:"text-[0.7rem] text-muted-foreground",children:[a," / ",s.length," enabled"]})]}),s.map(e=>(0,t.jsxs)("div",{className:"flex items-start gap-3 px-4 py-3 border-b border-border/20 hover:bg-muted/20 transition-colors",children:[(0,t.jsx)("div",{className:"mt-0.5 shrink-0",children:(0,t.jsx)(X,{enabled:e.enabled,onChange:()=>{var t,s;return t=e.name,s=e.enabled,void(!r||(!r.clis.some(e=>e.installed)?x("Policies are not installed. Install policies to continue."):(x(null),o(e=>e?{...e,policies:e.policies.map(e=>e.name===t?{...e,enabled:!s}:e),enabledPolicies:s?e.enabledPolicies.filter(e=>e!==t):[...e.enabledPolicies,t]}:e),l(async()=>{try{await N(t,!s)}catch{j("policy_toggle","Failed to save policy change."),P()}}))))},disabled:n})}),(0,t.jsxs)("div",{className:"flex items-center gap-1.5 min-w-0 w-56 shrink-0 mt-0.5",children:[(0,t.jsx)("span",{className:"text-xs font-mono text-foreground truncate",children:e.name}),e.beta&&(0,t.jsx)("span",{className:"shrink-0 text-[0.6rem] px-1 py-0.5 rounded border bg-violet-500/10 text-violet-400 border-violet-500/20",children:"beta"})]}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[(0,t.jsx)("span",{className:"text-xs text-muted-foreground leading-relaxed",children:e.description}),e.eventScope&&(0,t.jsx)("span",{className:"block text-[0.65rem] text-muted-foreground/40 font-mono mt-0.5 hidden lg:block",children:e.eventScope}),e.params&&Object.keys(e.params).length>0&&(0,t.jsx)("div",{className:"flex flex-wrap gap-1 mt-1.5",children:Object.entries(e.params).map(([s,r])=>{let o=e.currentParams?.[s]??r.default,n=JSON.stringify(o)!==JSON.stringify(r.default);return(0,t.jsxs)("span",{className:`inline-flex items-center gap-1 font-mono text-[0.6rem] px-1.5 py-0.5 rounded border ${n?"bg-primary/10 text-primary/70 border-primary/20":"bg-muted/40 text-muted-foreground/55 border-border/40"}`,children:[(0,t.jsxs)("span",{className:"opacity-70",children:[s,":"]}),(0,t.jsx)("span",{children:function(e,t){if("string[]"===e||"pattern[]"===e){let s=Array.isArray(t)?t:[];return 0===s.length?"none":"pattern[]"===e?`${s.length} pattern${1!==s.length?"s":""}`:1===s.length?String(s[0]).slice(0,24):`${s.length} values`}return"boolean"===e?t?"on":"off":null==t||""===t?"—":String(t).slice(0,32)}(r.type,o)})]},s)})})]}),e.params&&Object.keys(e.params).length>0&&(0,t.jsx)("button",{className:"shrink-0 mt-0.5 text-muted-foreground hover:text-primary transition-colors",onClick:()=>{let t=Object.entries(e.params??{}).filter(([t,s])=>JSON.stringify(e.currentParams?.[t]??s.default)!==JSON.stringify(s.default)).length;v("policy_config_modal_opened",{policy_name:e.name,param_count:Object.keys(e.params??{}).length,has_customized_params:t>0,customized_count:t}),h(e)},title:"Edit parameters",children:(0,t.jsx)(d.Settings,{className:"h-3.5 w-3.5"})})]},e.name))]},e)}),r.customPoliciesPath&&(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-2.5 bg-muted/20 border-b border-border/50",children:[(0,t.jsx)("span",{className:"text-[0.7rem] font-semibold uppercase tracking-wider text-muted-foreground",children:"Custom Policies"}),(0,t.jsxs)("span",{className:"text-[0.7rem] text-muted-foreground",children:[r.customPolicies?.length??0," detected"]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-3 px-4 py-3 border-b border-border/20",children:[(0,t.jsx)(i,{className:"h-3.5 w-3.5 text-muted-foreground shrink-0"}),(0,t.jsx)("span",{className:"text-xs font-mono text-muted-foreground truncate",children:r.customPoliciesPath})]}),(0,t.jsxs)("div",{className:"flex items-start gap-2 px-4 py-2.5 border-b border-border/20 bg-muted/10",children:[(0,t.jsx)(m.Shield,{className:"h-3.5 w-3.5 text-muted-foreground/60 shrink-0 mt-0.5"}),(0,t.jsx)("p",{className:"text-[0.7rem] text-muted-foreground/70 leading-relaxed",children:"Custom policies are always active. To add, remove, or reorder them, edit the JS file above."})]}),r.customPolicies?.map(e=>(0,t.jsxs)("div",{className:"flex items-start gap-3 px-4 py-3 border-b border-border/20 hover:bg-muted/20 transition-colors",children:[(0,t.jsx)("div",{className:"h-4 w-7 shrink-0 mt-0.5"}),(0,t.jsx)("div",{className:"flex items-center gap-1.5 min-w-0 w-56 shrink-0 mt-0.5",children:(0,t.jsx)("span",{className:"text-xs font-mono text-foreground truncate",children:e.name})}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[e.description&&(0,t.jsx)("span",{className:"text-xs text-muted-foreground leading-relaxed",children:e.description}),e.eventScope&&(0,t.jsx)("span",{className:"block text-[0.65rem] text-muted-foreground/40 font-mono mt-0.5 hidden lg:block",children:e.eventScope})]})]},e.name))]}),r.conventionPolicies?.map(e=>(0,t.jsxs)("div",{children:[(0,t.jsxs)("div",{className:"flex items-center justify-between px-4 py-2.5 bg-muted/20 border-b border-border/50",children:[(0,t.jsxs)("span",{className:"text-[0.7rem] font-semibold uppercase tracking-wider text-muted-foreground",children:["Convention Policies — ","project"===e.scope?"Project":"User"]}),(0,t.jsxs)("span",{className:"text-[0.7rem] text-muted-foreground",children:[e.policies.length," hook",1===e.policies.length?"":"s"]})]}),(0,t.jsxs)("div",{className:"flex items-center gap-3 px-4 py-3 border-b border-border/20",children:[(0,t.jsx)(i,{className:"h-3.5 w-3.5 text-muted-foreground shrink-0"}),(0,t.jsx)("span",{className:"text-xs font-mono text-muted-foreground truncate",children:e.path})]}),0===e.policies.length?(0,t.jsxs)("div",{className:"flex items-start gap-2 px-4 py-2.5 border-b border-border/20 bg-muted/10",children:[(0,t.jsx)(m.Shield,{className:"h-3.5 w-3.5 text-muted-foreground/60 shrink-0 mt-0.5"}),(0,t.jsxs)("p",{className:"text-[0.7rem] text-muted-foreground/70 leading-relaxed",children:["No policies could be read from this file. It is still loaded at runtime — run ",(0,t.jsx)("span",{className:"font-mono",children:"failproofai policies"})," to see what it registers."]})]}):e.policies.map(s=>(0,t.jsxs)("div",{className:"flex items-start gap-3 px-4 py-3 border-b border-border/20 hover:bg-muted/20 transition-colors",children:[(0,t.jsx)("div",{className:"h-4 w-7 shrink-0 mt-0.5"}),(0,t.jsx)("div",{className:"flex items-center gap-1.5 min-w-0 w-56 shrink-0 mt-0.5",children:(0,t.jsx)("span",{className:"text-xs font-mono text-foreground truncate",children:s.name})}),(0,t.jsxs)("div",{className:"flex-1 min-w-0",children:[s.description&&(0,t.jsx)("span",{className:"text-xs text-muted-foreground leading-relaxed",children:s.description}),s.eventScope&&(0,t.jsx)("span",{className:"block text-[0.65rem] text-muted-foreground/40 font-mono mt-0.5 hidden lg:block",children:s.eventScope})]})]},`${e.path}:${s.name}`))]},e.path))]})]})}function V({activeTab:e,onChange:s}){return(0,t.jsx)("div",{className:"tabs",style:{padding:0,marginBottom:24},children:[{id:"activity",label:"Activity"},{id:"policies",label:"Configure"}].map(r=>(0,t.jsx)("button",{type:"button",onClick:()=>s(r.id),className:`tab${e===r.id?" is-active":""}`,children:r.label.toLowerCase()},r.id))})}e.s(["default",0,function({initialTab:e="activity"}){let r=(0,_.useUrlParams)(),{capture:o}=(0,C.usePostHog)(),[n,l]=(0,s.useState)(e),[a,i]=(0,s.useState)(void 0),[c,d]=(0,s.useState)(null),[m,u]=(0,s.useState)([]);(0,s.useEffect)(()=>{y().then(e=>{i(e.clis.some(e=>e.installed)),d({enabled:e.enabledPolicies.length,total:e.policies.length+(e.customPolicies?.length??0)+(e.conventionPolicies?.reduce((e,t)=>e+t.policies.length,0)??0)}),u(e.clis.filter(e=>e.installed).map(e=>e.label))}).catch(()=>i(void 0))},[]);let x=0===m.length?"Policy evaluations":m.length<=3?`Policy evaluations across ${m.join(", ")}`:`Policy evaluations across ${m.length} agents`,p=e=>{e!==n&&o("policies_tab_switched",{tab:e,from_tab:n}),l(e),r.setAll({tab:"activity"===e?void 0:e})};return(0,t.jsx)("main",{className:"report",children:(0,t.jsxs)("section",{className:"section","data-screen-label":"policies",children:[(0,t.jsx)("h2",{style:{fontFamily:"var(--font-mono)",fontSize:24,fontWeight:600,letterSpacing:"-0.01em",color:"var(--ink)",margin:"0 0 16px"},children:"activity"===n?"Policies":"Configure Policies"}),"activity"===n?(0,t.jsxs)("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:32,flexWrap:"wrap",margin:"0 0 24px"},children:[(0,t.jsxs)("div",{style:{fontFamily:"var(--font-mono)",fontSize:14,color:"var(--ink-2)",lineHeight:1.7,flex:"1 1 480px",minWidth:0},children:[x,c&&(0,t.jsxs)("span",{style:{color:"var(--dim)"},children:[" · ","enabled policies"," ",(0,t.jsxs)("span",{style:{color:"var(--ink)",fontVariantNumeric:"tabular-nums"},children:[c.enabled,"/",c.total]})]})]}),(0,t.jsxs)("div",{style:{display:"flex",flexDirection:"column",alignItems:"flex-end",gap:6,flex:"0 0 auto"},children:[(0,t.jsx)("span",{style:{fontFamily:"var(--font-mono)",fontSize:10,letterSpacing:"0.22em",textTransform:"uppercase",color:"var(--dim)"},children:"want to change which policies fire?"}),(0,t.jsx)("button",{type:"button",className:"btn btn-primary",onClick:()=>p("policies"),children:"[ configure policies → ]"})]})]}):(0,t.jsx)("p",{style:{fontFamily:"var(--font-mono)",fontSize:14,color:"var(--ink-2)",lineHeight:1.7,maxWidth:720,margin:"0 0 24px"},children:"switch policies on or off across your installed agent CLIs."}),(0,t.jsx)(V,{activeTab:n,onChange:p}),"activity"===n?(0,t.jsx)(q,{hooksInstalled:a,onSwitchTab:p}):(0,t.jsx)(G,{onHooksInstallChange:i})]})})}],64245)}]);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,89664,e=>{"use strict";let t=(0,e.i(56420).default)("check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);e.s(["Check",0,t],89664)},8734,e=>{"use strict";let t=(0,e.i(56420).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,t],8734)},66794,e=>{"use strict";let t=(0,e.i(56420).default)("settings",[["path",{d:"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",key:"1i5ecw"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);e.s(["Settings",0,t],66794)},82954,e=>{"use strict";let t=(0,e.i(56420).default)("shield",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]]);e.s(["Shield",0,t],82954)},16306,e=>{"use strict";let t=(0,e.i(56420).default)("shield-alert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);e.s(["ShieldAlert",0,t],16306)},84026,29407,e=>{"use strict";var t=e.i(56420);let a=(0,t.default)("shield-check",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m9 12 2 2 4-4",key:"dzmm74"}]]);e.s(["ShieldCheck",0,a],84026);let r=(0,t.default)("shield-x",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"m14.5 9.5-5 5",key:"17q4r4"}],["path",{d:"m9.5 9.5 5 5",key:"18nt4w"}]]);e.s(["ShieldX",0,r],29407)},8252,e=>{"use strict";var t=e.i(95187);let a=(0,t.createServerReference)("604b048067ca7699207a3a444d4f1094244d7964ce",t.callServer,void 0,t.findSourceMapURL,"searchHookActivityAction");e.s(["searchHookActivityAction",0,a])},34713,e=>{"use strict";e.s(["formatDuration",0,function(e){if(e<1e3)return`${e}ms`;let t=Math.round(e/100);if(t<600)return`${(t/10).toFixed(1)}s`;let a=Math.round(e/1e3);if(a<3600){let e=Math.floor(a/60);return`${e}m ${a%60}s`}let r=Math.round(e/6e4),l=Math.floor(r/60);return`${l}h ${r%60}m`},"formatRelativeTime",0,function(e){let t=Date.now()-e;return t<6e4?`${Math.max(1,Math.floor(t/1e3))}s ago`:t<36e5?`${Math.floor(t/6e4)}m ago`:t<864e5?`${Math.floor(t/36e5)}h ago`:`${Math.floor(t/864e5)}d ago`}])},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),a=e.i(24071),r=e.i(67927);e.s(["default",0,function({currentPage:e,totalPages:l,onPageChange:s}){if(l<=1)return null;let o=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:()=>s(e-1),disabled:1===e,className:o(1===e),"aria-label":"Previous page",children:[(0,t.jsx)(a.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(l<=7)return Array.from({length:l},(e,t)=>t+1);let t=[1],a=Math.max(2,e-1),r=Math.min(l-1,e+1);e<=3&&(r=Math.min(5,l-1)),e>=l-2&&(a=Math.max(2,l-4)),a>2&&t.push("ellipsis-start");for(let e=a;e<=r;e++)t.push(e);return r<l-1&&t.push("ellipsis-end"),t.push(l),t})().map(a=>"string"==typeof a?(0,t.jsx)("span",{className:"px-2 text-muted-foreground",children:"..."},a):(0,t.jsx)("button",{onClick:()=>s(a),className:`min-w-[2.5rem] px-3 py-2 text-sm rounded-md transition-colors ${e===a?"bg-primary text-primary-foreground":"bg-muted text-muted-foreground hover:bg-muted/80"}`,"aria-label":`Page ${a}`,"aria-current":e===a?"page":void 0,children:a},a))}),(0,t.jsxs)("button",{onClick:()=>s(e+1),disabled:e===l,className:o(e===l),"aria-label":"Next page",children:[(0,t.jsx)("span",{className:"hidden sm:inline",children:"Next"}),(0,t.jsx)(r.ChevronRight,{className:"w-4 h-4"})]})]})}])},80060,2711,e=>{"use strict";var t=e.i(18566),a=e.i(71645);function r(e){let t=e.getFullYear(),a=String(e.getMonth()+1).padStart(2,"0"),r=String(e.getDate()).padStart(2,"0");return`${t}-${a}-${r}`}function l(e){var t;if(!e||(t=e,!/^\d{4}-\d{2}-\d{2}$/.test(t)||isNaN(Date.parse(t))))return null;let[a,r,l]=e.split("-").map(Number);return new Date(a,r-1,l,12,0,0)}e.s(["useUrlParams",0,function(){let e=(0,t.useSearchParams)(),r=(0,t.useRouter)(),l=(0,t.usePathname)(),s=(0,a.useRef)(null),o=(0,a.useCallback)(t=>e.get(t),[e]),i=(0,a.useCallback)(()=>new URLSearchParams(e.toString()),[e]),n=(0,a.useCallback)(t=>{s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{let a=new URLSearchParams(e.toString());for(let[e,r]of Object.entries(t))void 0===r||""===r?a.delete(e):a.set(e,r);let s=a.toString(),o=s?`${l}?${s}`:l;r.replace(o,{scroll:!1})},150)},[e,l,r]);return(0,a.useEffect)(()=>()=>{s.current&&clearTimeout(s.current)},[]),{get:o,getAll:i,setAll:n}}],80060),e.s(["dateRangeToParams",0,function(e){let t={};return e.from&&(t.from=r(e.from)),e.to&&(t.to=r(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:l(e),to:l(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)}])},63676,e=>{"use strict";let t=(0,e.i(56420).default)("x",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]);e.s(["X",0,t],63676)}]);