failproofai 0.0.6-beta.2 → 0.0.6-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +7 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +17 -17
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +17 -17
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +16 -16
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +16 -16
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +11 -11
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g72weg._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_0z7w.hh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__092s1ta._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__09icjsf._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g.lg8b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h..k-e._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0okos0k._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0i5kvry._.js → [root-of-the-server]__0om-5pe._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0w6l33k._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__05akje6._.js → [root-of-the-server]__111.vxi._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11pa2ra._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__12t-wym._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_10lm7or._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_0xerkr6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_0q-m0y-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mebn66._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +9 -9
- package/.next/standalone/.next/static/chunks/{05j1px0r8yzh6.js → 02dqjyv6_9mhq.js} +2 -2
- package/.next/standalone/.next/static/chunks/{14cl9poem30dq.js → 070orfsl6.xal.js} +1 -1
- package/.next/standalone/.next/static/chunks/0mir9jdxn35~s.css +1 -0
- package/.next/standalone/.next/static/chunks/{00j0rr7rh8ef8.js → 0o547jv-k_k35.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0ijk_kek9_wyx.js → 0pk2h2.mjxy.m.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0xpl.oscrakvx.js → 0rcwkbh24w38b.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1052sguyd-.ka.js → 140xx_tfr~lm_.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0npb~873.wvg3.js → 169_e4dq~1~b6.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0badv41uxa56..js → 17ne4p.1sw1jy.js} +1 -1
- package/.next/standalone/next.config.ts +6 -0
- package/.next/standalone/package.json +2 -2
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +91 -4
- package/dist/cli.mjs +1155 -54
- package/package.json +2 -2
- package/scripts/prune-standalone.mjs +128 -0
- package/src/auth/login.ts +104 -0
- package/src/auth/logout.ts +50 -0
- package/src/auth/token-store.ts +64 -0
- package/src/hooks/builtin-policies.ts +22 -20
- package/src/hooks/handler.ts +35 -15
- package/src/relay/daemon.ts +362 -0
- package/src/relay/pid.ts +76 -0
- package/src/relay/queue.ts +225 -0
- package/.next/standalone/.claude/settings.json +0 -316
- package/.next/standalone/.failproofai/policies/review-policies.mjs +0 -113
- package/.next/standalone/.failproofai/policies/workflow-policies.mjs +0 -63
- package/.next/standalone/.failproofai/policies-config.json +0 -39
- package/.next/standalone/.next/static/chunks/0gu_a.a80ritd.css +0 -1
- package/.next/standalone/AGENTS.md +0 -80
- package/.next/standalone/CHANGELOG.md +0 -151
- package/.next/standalone/CLAUDE.md +0 -165
- package/.next/standalone/CONTRIBUTING.md +0 -76
- package/.next/standalone/Dockerfile.docs +0 -12
- package/.next/standalone/LICENSE +0 -42
- package/.next/standalone/README.md +0 -301
- package/.next/standalone/bin/failproofai.mjs +0 -352
- package/.next/standalone/bun.lock +0 -1119
- package/.next/standalone/components.json +0 -23
- package/.next/standalone/dist/cli.mjs +0 -3595
- package/.next/standalone/dist/index.js +0 -80
- package/.next/standalone/docs/ar/architecture.mdx +0 -334
- package/.next/standalone/docs/ar/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/ar/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/ar/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/ar/cli/hook.mdx +0 -31
- package/.next/standalone/docs/ar/cli/install-policies.mdx +0 -48
- package/.next/standalone/docs/ar/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/ar/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/ar/cli/version.mdx +0 -13
- package/.next/standalone/docs/ar/configuration.mdx +0 -223
- package/.next/standalone/docs/ar/custom-policies.mdx +0 -354
- package/.next/standalone/docs/ar/dashboard.mdx +0 -142
- package/.next/standalone/docs/ar/examples.mdx +0 -307
- package/.next/standalone/docs/ar/for-agents.mdx +0 -39
- package/.next/standalone/docs/ar/getting-started.mdx +0 -187
- package/.next/standalone/docs/ar/introduction.mdx +0 -58
- package/.next/standalone/docs/ar/package-aliases.mdx +0 -82
- package/.next/standalone/docs/ar/testing.mdx +0 -261
- package/.next/standalone/docs/architecture.mdx +0 -332
- package/.next/standalone/docs/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/cli/hook.mdx +0 -30
- package/.next/standalone/docs/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/cli/version.mdx +0 -12
- package/.next/standalone/docs/configuration.mdx +0 -222
- package/.next/standalone/docs/custom-policies.mdx +0 -353
- package/.next/standalone/docs/dashboard.mdx +0 -142
- package/.next/standalone/docs/de/architecture.mdx +0 -332
- package/.next/standalone/docs/de/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/de/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/de/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/de/cli/hook.mdx +0 -30
- package/.next/standalone/docs/de/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/de/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/de/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/de/cli/version.mdx +0 -12
- package/.next/standalone/docs/de/configuration.mdx +0 -222
- package/.next/standalone/docs/de/custom-policies.mdx +0 -353
- package/.next/standalone/docs/de/dashboard.mdx +0 -142
- package/.next/standalone/docs/de/examples.mdx +0 -307
- package/.next/standalone/docs/de/for-agents.mdx +0 -38
- package/.next/standalone/docs/de/getting-started.mdx +0 -186
- package/.next/standalone/docs/de/introduction.mdx +0 -57
- package/.next/standalone/docs/de/package-aliases.mdx +0 -82
- package/.next/standalone/docs/de/testing.mdx +0 -260
- package/.next/standalone/docs/docs.json +0 -1002
- package/.next/standalone/docs/es/architecture.mdx +0 -332
- package/.next/standalone/docs/es/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/es/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/es/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/es/cli/hook.mdx +0 -30
- package/.next/standalone/docs/es/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/es/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/es/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/es/cli/version.mdx +0 -12
- package/.next/standalone/docs/es/configuration.mdx +0 -222
- package/.next/standalone/docs/es/custom-policies.mdx +0 -353
- package/.next/standalone/docs/es/dashboard.mdx +0 -142
- package/.next/standalone/docs/es/examples.mdx +0 -307
- package/.next/standalone/docs/es/for-agents.mdx +0 -38
- package/.next/standalone/docs/es/getting-started.mdx +0 -186
- package/.next/standalone/docs/es/introduction.mdx +0 -57
- package/.next/standalone/docs/es/package-aliases.mdx +0 -82
- package/.next/standalone/docs/es/testing.mdx +0 -260
- package/.next/standalone/docs/examples.mdx +0 -307
- package/.next/standalone/docs/favicon.ico +0 -0
- package/.next/standalone/docs/for-agents.mdx +0 -38
- package/.next/standalone/docs/fr/architecture.mdx +0 -332
- package/.next/standalone/docs/fr/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/fr/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/fr/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/fr/cli/hook.mdx +0 -30
- package/.next/standalone/docs/fr/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/fr/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/fr/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/fr/cli/version.mdx +0 -12
- package/.next/standalone/docs/fr/configuration.mdx +0 -222
- package/.next/standalone/docs/fr/custom-policies.mdx +0 -353
- package/.next/standalone/docs/fr/dashboard.mdx +0 -142
- package/.next/standalone/docs/fr/examples.mdx +0 -307
- package/.next/standalone/docs/fr/for-agents.mdx +0 -38
- package/.next/standalone/docs/fr/getting-started.mdx +0 -186
- package/.next/standalone/docs/fr/introduction.mdx +0 -57
- package/.next/standalone/docs/fr/package-aliases.mdx +0 -82
- package/.next/standalone/docs/fr/testing.mdx +0 -260
- package/.next/standalone/docs/getting-started.mdx +0 -186
- package/.next/standalone/docs/he/architecture.mdx +0 -333
- package/.next/standalone/docs/he/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/he/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/he/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/he/cli/hook.mdx +0 -30
- package/.next/standalone/docs/he/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/he/cli/list-policies.mdx +0 -32
- package/.next/standalone/docs/he/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/he/cli/version.mdx +0 -12
- package/.next/standalone/docs/he/configuration.mdx +0 -223
- package/.next/standalone/docs/he/custom-policies.mdx +0 -353
- package/.next/standalone/docs/he/dashboard.mdx +0 -142
- package/.next/standalone/docs/he/examples.mdx +0 -307
- package/.next/standalone/docs/he/for-agents.mdx +0 -38
- package/.next/standalone/docs/he/getting-started.mdx +0 -186
- package/.next/standalone/docs/he/introduction.mdx +0 -57
- package/.next/standalone/docs/he/package-aliases.mdx +0 -82
- package/.next/standalone/docs/he/testing.mdx +0 -260
- package/.next/standalone/docs/hi/architecture.mdx +0 -334
- package/.next/standalone/docs/hi/built-in-policies.mdx +0 -576
- package/.next/standalone/docs/hi/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/hi/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/hi/cli/hook.mdx +0 -30
- package/.next/standalone/docs/hi/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/hi/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/hi/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/hi/cli/version.mdx +0 -12
- package/.next/standalone/docs/hi/configuration.mdx +0 -222
- package/.next/standalone/docs/hi/custom-policies.mdx +0 -354
- package/.next/standalone/docs/hi/dashboard.mdx +0 -142
- package/.next/standalone/docs/hi/examples.mdx +0 -309
- package/.next/standalone/docs/hi/for-agents.mdx +0 -38
- package/.next/standalone/docs/hi/getting-started.mdx +0 -187
- package/.next/standalone/docs/hi/introduction.mdx +0 -57
- package/.next/standalone/docs/hi/package-aliases.mdx +0 -82
- package/.next/standalone/docs/hi/testing.mdx +0 -260
- package/.next/standalone/docs/i18n/README.ar.md +0 -312
- package/.next/standalone/docs/i18n/README.de.md +0 -307
- package/.next/standalone/docs/i18n/README.es.md +0 -307
- package/.next/standalone/docs/i18n/README.fr.md +0 -307
- package/.next/standalone/docs/i18n/README.he.md +0 -312
- package/.next/standalone/docs/i18n/README.hi.md +0 -307
- package/.next/standalone/docs/i18n/README.it.md +0 -307
- package/.next/standalone/docs/i18n/README.ja.md +0 -307
- package/.next/standalone/docs/i18n/README.ko.md +0 -307
- package/.next/standalone/docs/i18n/README.pt-br.md +0 -307
- package/.next/standalone/docs/i18n/README.ru.md +0 -308
- package/.next/standalone/docs/i18n/README.tr.md +0 -307
- package/.next/standalone/docs/i18n/README.vi.md +0 -307
- package/.next/standalone/docs/i18n/README.zh.md +0 -307
- package/.next/standalone/docs/introduction.mdx +0 -57
- package/.next/standalone/docs/it/architecture.mdx +0 -334
- package/.next/standalone/docs/it/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/it/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/it/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/it/cli/hook.mdx +0 -30
- package/.next/standalone/docs/it/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/it/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/it/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/it/cli/version.mdx +0 -12
- package/.next/standalone/docs/it/configuration.mdx +0 -222
- package/.next/standalone/docs/it/custom-policies.mdx +0 -353
- package/.next/standalone/docs/it/dashboard.mdx +0 -142
- package/.next/standalone/docs/it/examples.mdx +0 -307
- package/.next/standalone/docs/it/for-agents.mdx +0 -38
- package/.next/standalone/docs/it/getting-started.mdx +0 -186
- package/.next/standalone/docs/it/introduction.mdx +0 -57
- package/.next/standalone/docs/it/package-aliases.mdx +0 -82
- package/.next/standalone/docs/it/testing.mdx +0 -260
- package/.next/standalone/docs/ja/architecture.mdx +0 -332
- package/.next/standalone/docs/ja/built-in-policies.mdx +0 -572
- package/.next/standalone/docs/ja/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/ja/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/ja/cli/hook.mdx +0 -30
- package/.next/standalone/docs/ja/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/ja/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/ja/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/ja/cli/version.mdx +0 -12
- package/.next/standalone/docs/ja/configuration.mdx +0 -222
- package/.next/standalone/docs/ja/custom-policies.mdx +0 -353
- package/.next/standalone/docs/ja/dashboard.mdx +0 -142
- package/.next/standalone/docs/ja/examples.mdx +0 -307
- package/.next/standalone/docs/ja/for-agents.mdx +0 -38
- package/.next/standalone/docs/ja/getting-started.mdx +0 -186
- package/.next/standalone/docs/ja/introduction.mdx +0 -57
- package/.next/standalone/docs/ja/package-aliases.mdx +0 -82
- package/.next/standalone/docs/ja/testing.mdx +0 -260
- package/.next/standalone/docs/ko/architecture.mdx +0 -332
- package/.next/standalone/docs/ko/built-in-policies.mdx +0 -572
- package/.next/standalone/docs/ko/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/ko/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/ko/cli/hook.mdx +0 -30
- package/.next/standalone/docs/ko/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/ko/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/ko/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/ko/cli/version.mdx +0 -12
- package/.next/standalone/docs/ko/configuration.mdx +0 -222
- package/.next/standalone/docs/ko/custom-policies.mdx +0 -353
- package/.next/standalone/docs/ko/dashboard.mdx +0 -142
- package/.next/standalone/docs/ko/examples.mdx +0 -307
- package/.next/standalone/docs/ko/for-agents.mdx +0 -38
- package/.next/standalone/docs/ko/getting-started.mdx +0 -186
- package/.next/standalone/docs/ko/introduction.mdx +0 -57
- package/.next/standalone/docs/ko/package-aliases.mdx +0 -82
- package/.next/standalone/docs/ko/testing.mdx +0 -260
- package/.next/standalone/docs/logo/dark.svg +0 -21
- package/.next/standalone/docs/logo/exosphere-dark.png +0 -0
- package/.next/standalone/docs/logo/exosphere-light.png +0 -0
- package/.next/standalone/docs/logo/light.svg +0 -21
- package/.next/standalone/docs/package-aliases.mdx +0 -82
- package/.next/standalone/docs/pt-br/architecture.mdx +0 -332
- package/.next/standalone/docs/pt-br/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/pt-br/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/pt-br/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/pt-br/cli/hook.mdx +0 -30
- package/.next/standalone/docs/pt-br/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/pt-br/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/pt-br/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/pt-br/cli/version.mdx +0 -12
- package/.next/standalone/docs/pt-br/configuration.mdx +0 -222
- package/.next/standalone/docs/pt-br/custom-policies.mdx +0 -353
- package/.next/standalone/docs/pt-br/dashboard.mdx +0 -142
- package/.next/standalone/docs/pt-br/examples.mdx +0 -307
- package/.next/standalone/docs/pt-br/for-agents.mdx +0 -38
- package/.next/standalone/docs/pt-br/getting-started.mdx +0 -186
- package/.next/standalone/docs/pt-br/introduction.mdx +0 -57
- package/.next/standalone/docs/pt-br/package-aliases.mdx +0 -82
- package/.next/standalone/docs/pt-br/testing.mdx +0 -260
- package/.next/standalone/docs/ru/architecture.mdx +0 -333
- package/.next/standalone/docs/ru/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/ru/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/ru/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/ru/cli/hook.mdx +0 -30
- package/.next/standalone/docs/ru/cli/install-policies.mdx +0 -48
- package/.next/standalone/docs/ru/cli/list-policies.mdx +0 -32
- package/.next/standalone/docs/ru/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/ru/cli/version.mdx +0 -12
- package/.next/standalone/docs/ru/configuration.mdx +0 -222
- package/.next/standalone/docs/ru/custom-policies.mdx +0 -354
- package/.next/standalone/docs/ru/dashboard.mdx +0 -142
- package/.next/standalone/docs/ru/examples.mdx +0 -309
- package/.next/standalone/docs/ru/for-agents.mdx +0 -38
- package/.next/standalone/docs/ru/getting-started.mdx +0 -186
- package/.next/standalone/docs/ru/introduction.mdx +0 -57
- package/.next/standalone/docs/ru/package-aliases.mdx +0 -82
- package/.next/standalone/docs/ru/testing.mdx +0 -260
- package/.next/standalone/docs/testing.mdx +0 -260
- package/.next/standalone/docs/tr/architecture.mdx +0 -333
- package/.next/standalone/docs/tr/built-in-policies.mdx +0 -574
- package/.next/standalone/docs/tr/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/tr/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/tr/cli/hook.mdx +0 -30
- package/.next/standalone/docs/tr/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/tr/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/tr/cli/remove-policies.mdx +0 -44
- package/.next/standalone/docs/tr/cli/version.mdx +0 -12
- package/.next/standalone/docs/tr/configuration.mdx +0 -222
- package/.next/standalone/docs/tr/custom-policies.mdx +0 -353
- package/.next/standalone/docs/tr/dashboard.mdx +0 -142
- package/.next/standalone/docs/tr/examples.mdx +0 -308
- package/.next/standalone/docs/tr/for-agents.mdx +0 -38
- package/.next/standalone/docs/tr/getting-started.mdx +0 -186
- package/.next/standalone/docs/tr/introduction.mdx +0 -57
- package/.next/standalone/docs/tr/package-aliases.mdx +0 -82
- package/.next/standalone/docs/tr/testing.mdx +0 -260
- package/.next/standalone/docs/vi/architecture.mdx +0 -334
- package/.next/standalone/docs/vi/built-in-policies.mdx +0 -575
- package/.next/standalone/docs/vi/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/vi/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/vi/cli/hook.mdx +0 -30
- package/.next/standalone/docs/vi/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/vi/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/vi/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/vi/cli/version.mdx +0 -13
- package/.next/standalone/docs/vi/configuration.mdx +0 -222
- package/.next/standalone/docs/vi/custom-policies.mdx +0 -353
- package/.next/standalone/docs/vi/dashboard.mdx +0 -142
- package/.next/standalone/docs/vi/examples.mdx +0 -308
- package/.next/standalone/docs/vi/for-agents.mdx +0 -38
- package/.next/standalone/docs/vi/getting-started.mdx +0 -186
- package/.next/standalone/docs/vi/introduction.mdx +0 -57
- package/.next/standalone/docs/vi/package-aliases.mdx +0 -82
- package/.next/standalone/docs/vi/testing.mdx +0 -260
- package/.next/standalone/docs/zh/architecture.mdx +0 -332
- package/.next/standalone/docs/zh/built-in-policies.mdx +0 -572
- package/.next/standalone/docs/zh/cli/dashboard.mdx +0 -28
- package/.next/standalone/docs/zh/cli/environment-variables.mdx +0 -34
- package/.next/standalone/docs/zh/cli/hook.mdx +0 -30
- package/.next/standalone/docs/zh/cli/install-policies.mdx +0 -47
- package/.next/standalone/docs/zh/cli/list-policies.mdx +0 -31
- package/.next/standalone/docs/zh/cli/remove-policies.mdx +0 -43
- package/.next/standalone/docs/zh/cli/version.mdx +0 -12
- package/.next/standalone/docs/zh/configuration.mdx +0 -222
- package/.next/standalone/docs/zh/custom-policies.mdx +0 -353
- package/.next/standalone/docs/zh/dashboard.mdx +0 -142
- package/.next/standalone/docs/zh/examples.mdx +0 -307
- package/.next/standalone/docs/zh/for-agents.mdx +0 -38
- package/.next/standalone/docs/zh/getting-started.mdx +0 -186
- package/.next/standalone/docs/zh/introduction.mdx +0 -57
- package/.next/standalone/docs/zh/package-aliases.mdx +0 -82
- package/.next/standalone/docs/zh/testing.mdx +0 -260
- package/.next/standalone/eslint.config.mjs +0 -15
- package/.next/standalone/examples/convention-policies/security-policies.mjs +0 -40
- package/.next/standalone/examples/convention-policies/workflow-policies.mjs +0 -41
- package/.next/standalone/examples/policies-advanced/index.js +0 -103
- package/.next/standalone/examples/policies-advanced/utils.js +0 -35
- package/.next/standalone/examples/policies-basic.js +0 -77
- package/.next/standalone/examples/policies-notification.js +0 -104
- package/.next/standalone/node_modules/@img/colour/color.cjs +0 -1594
- package/.next/standalone/node_modules/@img/colour/index.cjs +0 -1
- package/.next/standalone/node_modules/@img/colour/package.json +0 -45
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/README.md +0 -46
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/glib-2.0/include/glibconfig.h +0 -221
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/index.js +0 -1
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/lib/libvips-cpp.so.8.17.3 +0 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/package.json +0 -42
- package/.next/standalone/node_modules/@img/sharp-libvips-linux-x64/versions.json +0 -30
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/README.md +0 -46
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/glib-2.0/include/glibconfig.h +0 -221
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/index.js +0 -1
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/lib/libvips-cpp.so.8.17.3 +0 -0
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/package.json +0 -42
- package/.next/standalone/node_modules/@img/sharp-libvips-linuxmusl-x64/versions.json +0 -30
- package/.next/standalone/node_modules/@img/sharp-linux-x64/lib/sharp-linux-x64.node +0 -0
- package/.next/standalone/node_modules/@img/sharp-linux-x64/package.json +0 -46
- package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/lib/sharp-linuxmusl-x64.node +0 -0
- package/.next/standalone/node_modules/@img/sharp-linuxmusl-x64/package.json +0 -46
- package/.next/standalone/node_modules/detect-libc/lib/detect-libc.js +0 -313
- package/.next/standalone/node_modules/detect-libc/lib/elf.js +0 -39
- package/.next/standalone/node_modules/detect-libc/lib/filesystem.js +0 -51
- package/.next/standalone/node_modules/detect-libc/lib/process.js +0 -24
- package/.next/standalone/node_modules/detect-libc/package.json +0 -44
- package/.next/standalone/node_modules/sharp/lib/channel.js +0 -177
- package/.next/standalone/node_modules/sharp/lib/colour.js +0 -195
- package/.next/standalone/node_modules/sharp/lib/composite.js +0 -212
- package/.next/standalone/node_modules/sharp/lib/constructor.js +0 -499
- package/.next/standalone/node_modules/sharp/lib/index.js +0 -16
- package/.next/standalone/node_modules/sharp/lib/input.js +0 -809
- package/.next/standalone/node_modules/sharp/lib/is.js +0 -143
- package/.next/standalone/node_modules/sharp/lib/libvips.js +0 -207
- package/.next/standalone/node_modules/sharp/lib/operation.js +0 -1016
- package/.next/standalone/node_modules/sharp/lib/output.js +0 -1666
- package/.next/standalone/node_modules/sharp/lib/resize.js +0 -595
- package/.next/standalone/node_modules/sharp/lib/sharp.js +0 -121
- package/.next/standalone/node_modules/sharp/lib/utility.js +0 -291
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/comparator.js +0 -143
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/range.js +0 -557
- package/.next/standalone/node_modules/sharp/node_modules/semver/classes/semver.js +0 -333
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/cmp.js +0 -54
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/coerce.js +0 -62
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/compare.js +0 -7
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/eq.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gt.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/gte.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lt.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/lte.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/neq.js +0 -5
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/parse.js +0 -18
- package/.next/standalone/node_modules/sharp/node_modules/semver/functions/satisfies.js +0 -12
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/constants.js +0 -37
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/debug.js +0 -11
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/identifiers.js +0 -29
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/lrucache.js +0 -42
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/parse-options.js +0 -17
- package/.next/standalone/node_modules/sharp/node_modules/semver/internal/re.js +0 -223
- package/.next/standalone/node_modules/sharp/node_modules/semver/package.json +0 -78
- package/.next/standalone/node_modules/sharp/package.json +0 -202
- package/.next/standalone/scripts/alias-proxy.js +0 -18
- package/.next/standalone/scripts/dev.ts +0 -3
- package/.next/standalone/scripts/install-telemetry.mjs +0 -108
- package/.next/standalone/scripts/launch.ts +0 -83
- package/.next/standalone/scripts/parse-script-args.ts +0 -87
- package/.next/standalone/scripts/postinstall.mjs +0 -121
- package/.next/standalone/scripts/preuninstall.mjs +0 -131
- package/.next/standalone/scripts/publish-aliases.mjs +0 -87
- package/.next/standalone/scripts/start.ts +0 -3
- package/.next/standalone/scripts/sync-hook-events-prompt.md +0 -60
- package/.next/standalone/scripts/translate-docs/cache.ts +0 -62
- package/.next/standalone/scripts/translate-docs/cli.ts +0 -357
- package/.next/standalone/scripts/translate-docs/config.ts +0 -248
- package/.next/standalone/scripts/translate-docs/mdx-translator.ts +0 -153
- package/.next/standalone/scripts/translate-docs/mintlify-nav.ts +0 -107
- package/.next/standalone/scripts/translate-docs/readme-translator.ts +0 -154
- package/.next/standalone/scripts/translate-docs/translator.ts +0 -68
- package/.next/standalone/scripts/translate-docs/types.ts +0 -43
- package/.next/standalone/src/cli-error.ts +0 -18
- package/.next/standalone/src/hooks/builtin-policies.ts +0 -1613
- package/.next/standalone/src/hooks/custom-hooks-loader.ts +0 -205
- package/.next/standalone/src/hooks/custom-hooks-registry.ts +0 -30
- package/.next/standalone/src/hooks/handler.ts +0 -202
- package/.next/standalone/src/hooks/hook-activity-store.ts +0 -349
- package/.next/standalone/src/hooks/hook-logger.ts +0 -133
- package/.next/standalone/src/hooks/hook-telemetry.ts +0 -43
- package/.next/standalone/src/hooks/hooks-config.ts +0 -166
- package/.next/standalone/src/hooks/install-prompt.ts +0 -357
- package/.next/standalone/src/hooks/llm-client.ts +0 -90
- package/.next/standalone/src/hooks/loader-utils.ts +0 -178
- package/.next/standalone/src/hooks/manager.ts +0 -692
- package/.next/standalone/src/hooks/policy-evaluator.ts +0 -224
- package/.next/standalone/src/hooks/policy-helpers.ts +0 -16
- package/.next/standalone/src/hooks/policy-registry.ts +0 -90
- package/.next/standalone/src/hooks/policy-types.ts +0 -77
- package/.next/standalone/src/hooks/types.ts +0 -63
- package/.next/standalone/src/index.ts +0 -19
- package/.next/standalone/src/posthog-key.ts +0 -5
- package/.next/standalone/tailwind.config.ts +0 -11
- package/.next/standalone/tsconfig.json +0 -42
- package/.next/standalone/vitest.config.e2e.mts +0 -24
- package/.next/standalone/vitest.config.mts +0 -23
- /package/.next/standalone/.next/static/{A9pNTZdoYJTVyPAYwQMx5 → wOkJXoch1UmRAmyIuKZWc}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{A9pNTZdoYJTVyPAYwQMx5 → wOkJXoch1UmRAmyIuKZWc}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{A9pNTZdoYJTVyPAYwQMx5 → wOkJXoch1UmRAmyIuKZWc}/_ssgManifest.js +0 -0
|
@@ -1,692 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Install/remove/list failproofai hooks in Claude Code's settings.
|
|
3
|
-
*/
|
|
4
|
-
import { execSync } from "node:child_process";
|
|
5
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
6
|
-
import { resolve, dirname, basename } from "node:path";
|
|
7
|
-
import { homedir, platform, arch, release, hostname } from "node:os";
|
|
8
|
-
import {
|
|
9
|
-
HOOK_EVENT_TYPES,
|
|
10
|
-
HOOK_SCOPES,
|
|
11
|
-
FAILPROOFAI_HOOK_MARKER,
|
|
12
|
-
type HookScope,
|
|
13
|
-
type ClaudeHookEntry,
|
|
14
|
-
type ClaudeHookMatcher,
|
|
15
|
-
type ClaudeSettings,
|
|
16
|
-
} from "./types";
|
|
17
|
-
import { promptPolicySelection } from "./install-prompt";
|
|
18
|
-
import { readMergedHooksConfig, readScopedHooksConfig, writeScopedHooksConfig } from "./hooks-config";
|
|
19
|
-
import type { HooksConfig } from "./policy-types";
|
|
20
|
-
import { BUILTIN_POLICIES } from "./builtin-policies";
|
|
21
|
-
import { loadCustomHooks, discoverPolicyFiles } from "./custom-hooks-loader";
|
|
22
|
-
import { trackHookEvent } from "./hook-telemetry";
|
|
23
|
-
import { getInstanceId, hashToId } from "../../lib/telemetry-id";
|
|
24
|
-
import { CliError } from "../cli-error";
|
|
25
|
-
|
|
26
|
-
const VALID_POLICY_NAMES = new Set(BUILTIN_POLICIES.map((p) => p.name));
|
|
27
|
-
|
|
28
|
-
export function getSettingsPath(scope: HookScope, cwd?: string): string {
|
|
29
|
-
const base = cwd ? resolve(cwd) : process.cwd();
|
|
30
|
-
switch (scope) {
|
|
31
|
-
case "user":
|
|
32
|
-
return resolve(homedir(), ".claude", "settings.json");
|
|
33
|
-
case "project":
|
|
34
|
-
return resolve(base, ".claude", "settings.json");
|
|
35
|
-
case "local":
|
|
36
|
-
return resolve(base, ".claude", "settings.local.json");
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function scopeLabel(scope: HookScope): string {
|
|
41
|
-
switch (scope) {
|
|
42
|
-
case "user":
|
|
43
|
-
return `~/.claude/settings.json`;
|
|
44
|
-
case "project":
|
|
45
|
-
return `{cwd}/.claude/settings.json`;
|
|
46
|
-
case "local":
|
|
47
|
-
return `{cwd}/.claude/settings.local.json`;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function readSettings(settingsPath: string): ClaudeSettings {
|
|
52
|
-
if (!existsSync(settingsPath)) {
|
|
53
|
-
return {};
|
|
54
|
-
}
|
|
55
|
-
const raw = readFileSync(settingsPath, "utf8");
|
|
56
|
-
return JSON.parse(raw) as ClaudeSettings;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function writeSettings(settingsPath: string, settings: ClaudeSettings): void {
|
|
60
|
-
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
61
|
-
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf8");
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function resolveFailproofaiBinary(): string {
|
|
65
|
-
try {
|
|
66
|
-
const cmd = process.platform === "win32" ? "where failproofai" : "which failproofai";
|
|
67
|
-
const result = execSync(cmd, { encoding: "utf8" }).trim();
|
|
68
|
-
// `where` on Windows may return multiple lines; take the first
|
|
69
|
-
return result.split("\n")[0].trim();
|
|
70
|
-
} catch {
|
|
71
|
-
throw new CliError(
|
|
72
|
-
"failproofai binary not found in PATH.\n" +
|
|
73
|
-
"Install it globally first: npm install -g failproofai"
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function isFailproofaiHook(hook: Record<string, unknown>): boolean {
|
|
79
|
-
if (hook[FAILPROOFAI_HOOK_MARKER] === true) return true;
|
|
80
|
-
// Fallback for legacy installs that predate the marker
|
|
81
|
-
const cmd = typeof hook.command === "string" ? hook.command : "";
|
|
82
|
-
return cmd.includes("failproofai") && cmd.includes("--hook");
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function validatePolicyNames(names: string[]): void {
|
|
86
|
-
const invalid = names.filter((n) => !VALID_POLICY_NAMES.has(n));
|
|
87
|
-
if (invalid.length > 0) {
|
|
88
|
-
const validList = [...VALID_POLICY_NAMES].join(", ");
|
|
89
|
-
throw new CliError(
|
|
90
|
-
`Unknown policy name(s): ${invalid.join(", ")}\n` +
|
|
91
|
-
`Valid policies: ${validList}`
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** Return only scopes whose settings paths are unique (first wins). */
|
|
97
|
-
function deduplicateScopes(scopes: readonly HookScope[], cwd?: string): HookScope[] {
|
|
98
|
-
const seen = new Set<string>();
|
|
99
|
-
return scopes.filter((s) => {
|
|
100
|
-
const p = getSettingsPath(s, cwd);
|
|
101
|
-
if (seen.has(p)) return false;
|
|
102
|
-
seen.add(p);
|
|
103
|
-
return true;
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function hooksInstalledInSettings(scope: HookScope, cwd?: string): boolean {
|
|
108
|
-
const settingsPath = getSettingsPath(scope, cwd);
|
|
109
|
-
if (!existsSync(settingsPath)) return false;
|
|
110
|
-
try {
|
|
111
|
-
const settings = readSettings(settingsPath);
|
|
112
|
-
if (!settings.hooks) return false;
|
|
113
|
-
for (const matchers of Object.values(settings.hooks)) {
|
|
114
|
-
if (!Array.isArray(matchers)) continue;
|
|
115
|
-
for (const matcher of matchers) {
|
|
116
|
-
if (!matcher.hooks) continue;
|
|
117
|
-
if (matcher.hooks.some((h) => isFailproofaiHook(h as Record<string, unknown>))) {
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} catch {
|
|
123
|
-
// Corrupted settings — treat as not installed
|
|
124
|
-
}
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
function removeHooksFromSettingsFile(settingsPath: string): number {
|
|
130
|
-
const settings = readSettings(settingsPath);
|
|
131
|
-
|
|
132
|
-
if (!settings.hooks) return 0;
|
|
133
|
-
|
|
134
|
-
let removed = 0;
|
|
135
|
-
|
|
136
|
-
for (const eventType of Object.keys(settings.hooks)) {
|
|
137
|
-
const matchers = settings.hooks[eventType];
|
|
138
|
-
if (!Array.isArray(matchers)) continue;
|
|
139
|
-
|
|
140
|
-
for (let i = matchers.length - 1; i >= 0; i--) {
|
|
141
|
-
const matcher = matchers[i];
|
|
142
|
-
if (!matcher.hooks) continue;
|
|
143
|
-
|
|
144
|
-
const before = matcher.hooks.length;
|
|
145
|
-
matcher.hooks = matcher.hooks.filter(
|
|
146
|
-
(h) => !isFailproofaiHook(h as Record<string, unknown>)
|
|
147
|
-
);
|
|
148
|
-
removed += before - matcher.hooks.length;
|
|
149
|
-
|
|
150
|
-
// Remove empty matchers
|
|
151
|
-
if (matcher.hooks.length === 0) {
|
|
152
|
-
matchers.splice(i, 1);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Remove empty event type arrays
|
|
157
|
-
if (matchers.length === 0) {
|
|
158
|
-
delete settings.hooks[eventType];
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Remove empty hooks object
|
|
163
|
-
if (Object.keys(settings.hooks).length === 0) {
|
|
164
|
-
delete settings.hooks;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
writeSettings(settingsPath, settings);
|
|
168
|
-
return removed;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Install hooks into Claude Code settings.
|
|
173
|
-
*
|
|
174
|
-
* @param policyNames — if provided, skip interactive prompt:
|
|
175
|
-
* - `["all"]` → enable all policies
|
|
176
|
-
* - `["block-sudo", "block-rm-rf"]` → enable specific policies
|
|
177
|
-
* - `undefined` → interactive prompt (pre-loads current config if exists)
|
|
178
|
-
* @param scope — settings scope to write to (default: "user")
|
|
179
|
-
*/
|
|
180
|
-
export async function installHooks(
|
|
181
|
-
policyNames?: string[],
|
|
182
|
-
scope: HookScope = "user",
|
|
183
|
-
cwd?: string,
|
|
184
|
-
includeBeta = false,
|
|
185
|
-
source?: string,
|
|
186
|
-
customPoliciesPath?: string,
|
|
187
|
-
removeCustomHooks = false,
|
|
188
|
-
): Promise<void> {
|
|
189
|
-
// Validate user input first before any system checks
|
|
190
|
-
if (policyNames !== undefined && policyNames.length > 0) {
|
|
191
|
-
const nonAllNames = policyNames.filter((n) => n !== "all");
|
|
192
|
-
// Check unknown names first (most actionable error for the user)
|
|
193
|
-
if (nonAllNames.length > 0) validatePolicyNames(nonAllNames);
|
|
194
|
-
// Then check if "all" is mixed with valid specific names
|
|
195
|
-
if (policyNames.includes("all") && nonAllNames.length > 0) {
|
|
196
|
-
throw new CliError(
|
|
197
|
-
`"all" cannot be combined with specific policy names.\n` +
|
|
198
|
-
`Use either: --install all or --install block-sudo sanitize-jwt ...`
|
|
199
|
-
);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
const binaryPath = resolveFailproofaiBinary();
|
|
204
|
-
|
|
205
|
-
// Capture existing config before overwriting (used for telemetry diff)
|
|
206
|
-
const previousConfig = readScopedHooksConfig(scope, cwd);
|
|
207
|
-
const previousEnabled = new Set(previousConfig.enabledPolicies);
|
|
208
|
-
|
|
209
|
-
let selectedPolicies: string[];
|
|
210
|
-
|
|
211
|
-
if (policyNames !== undefined) {
|
|
212
|
-
// Non-interactive path: explicit array was provided (may be empty)
|
|
213
|
-
let incoming: string[];
|
|
214
|
-
if (policyNames.length === 1 && policyNames[0] === "all") {
|
|
215
|
-
incoming = BUILTIN_POLICIES
|
|
216
|
-
.filter((p) => includeBeta || !p.beta)
|
|
217
|
-
.map((p) => p.name);
|
|
218
|
-
} else {
|
|
219
|
-
incoming = policyNames;
|
|
220
|
-
}
|
|
221
|
-
// Additive: union with whatever was already enabled, deduplicated.
|
|
222
|
-
selectedPolicies = [...new Set([...previousConfig.enabledPolicies, ...incoming])];
|
|
223
|
-
} else {
|
|
224
|
-
// Interactive — pre-load current config if it exists
|
|
225
|
-
const preSelected = previousConfig.enabledPolicies.length > 0 ? previousConfig.enabledPolicies : undefined;
|
|
226
|
-
selectedPolicies = await promptPolicySelection(preSelected, { includeBeta });
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Preserve existing config fields (policyParams, customPoliciesPath, llm) when updating
|
|
230
|
-
const configToWrite = { ...previousConfig, enabledPolicies: selectedPolicies };
|
|
231
|
-
if (removeCustomHooks) {
|
|
232
|
-
delete configToWrite.customPoliciesPath;
|
|
233
|
-
} else if (customPoliciesPath) {
|
|
234
|
-
configToWrite.customPoliciesPath = resolve(customPoliciesPath);
|
|
235
|
-
// Validate the file before committing it to config
|
|
236
|
-
let validatedHooks: Awaited<ReturnType<typeof loadCustomHooks>> = [];
|
|
237
|
-
try {
|
|
238
|
-
validatedHooks = await loadCustomHooks(configToWrite.customPoliciesPath, { strict: true });
|
|
239
|
-
} catch (err) {
|
|
240
|
-
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
241
|
-
process.exit(1);
|
|
242
|
-
}
|
|
243
|
-
if (validatedHooks.length === 0) {
|
|
244
|
-
console.error(
|
|
245
|
-
`Error: no hooks registered in ${customPoliciesPath}. ` +
|
|
246
|
-
`Make sure your file calls customPolicies.add(...) at least once.`,
|
|
247
|
-
);
|
|
248
|
-
process.exit(1);
|
|
249
|
-
}
|
|
250
|
-
console.log(
|
|
251
|
-
`\nValidated ${validatedHooks.length} custom hook(s): ${validatedHooks.map((h) => h.name).join(", ")}`,
|
|
252
|
-
);
|
|
253
|
-
}
|
|
254
|
-
writeScopedHooksConfig(configToWrite, scope, cwd);
|
|
255
|
-
console.log(`\nEnabled ${selectedPolicies.length} policy(ies): ${selectedPolicies.join(", ")}`);
|
|
256
|
-
if (removeCustomHooks) {
|
|
257
|
-
console.log("Custom hooks path cleared.");
|
|
258
|
-
} else if (configToWrite.customPoliciesPath) {
|
|
259
|
-
console.log(`Custom hooks path: ${configToWrite.customPoliciesPath}`);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const settingsPath = getSettingsPath(scope, cwd);
|
|
263
|
-
const settings = readSettings(settingsPath);
|
|
264
|
-
|
|
265
|
-
if (!settings.hooks) {
|
|
266
|
-
settings.hooks = {};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
for (const eventType of HOOK_EVENT_TYPES) {
|
|
270
|
-
const command = scope === "project"
|
|
271
|
-
? `npx -y failproofai --hook ${eventType}`
|
|
272
|
-
: `"${binaryPath}" --hook ${eventType}`;
|
|
273
|
-
const hookEntry: ClaudeHookEntry = {
|
|
274
|
-
type: "command",
|
|
275
|
-
command,
|
|
276
|
-
timeout: 60_000,
|
|
277
|
-
[FAILPROOFAI_HOOK_MARKER]: true,
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
if (!settings.hooks[eventType]) {
|
|
281
|
-
settings.hooks[eventType] = [];
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const matchers: ClaudeHookMatcher[] = settings.hooks[eventType];
|
|
285
|
-
|
|
286
|
-
// Find existing failproofai matcher
|
|
287
|
-
let found = false;
|
|
288
|
-
for (const matcher of matchers) {
|
|
289
|
-
if (!matcher.hooks) continue;
|
|
290
|
-
const failproofaiIdx = matcher.hooks.findIndex((h: ClaudeHookEntry | Record<string, unknown>) =>
|
|
291
|
-
isFailproofaiHook(h as Record<string, unknown>)
|
|
292
|
-
);
|
|
293
|
-
if (failproofaiIdx >= 0) {
|
|
294
|
-
matcher.hooks[failproofaiIdx] = hookEntry;
|
|
295
|
-
found = true;
|
|
296
|
-
break;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
if (!found) {
|
|
301
|
-
// Append a new matcher with the failproofai hook
|
|
302
|
-
matchers.push({ hooks: [hookEntry] });
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
writeSettings(settingsPath, settings);
|
|
307
|
-
|
|
308
|
-
// Telemetry: track successful hook installation (with diff vs previous config)
|
|
309
|
-
try {
|
|
310
|
-
const newSet = new Set(selectedPolicies);
|
|
311
|
-
const policiesAdded = selectedPolicies.filter((p) => !previousEnabled.has(p));
|
|
312
|
-
const policiesRemoved = [...previousEnabled].filter((p) => !newSet.has(p));
|
|
313
|
-
const distinctId = getInstanceId();
|
|
314
|
-
await trackHookEvent(distinctId, "hooks_installed", {
|
|
315
|
-
scope,
|
|
316
|
-
policies: selectedPolicies,
|
|
317
|
-
policy_count: selectedPolicies.length,
|
|
318
|
-
policies_added: policiesAdded,
|
|
319
|
-
policies_removed: policiesRemoved,
|
|
320
|
-
...(source ? { source } : {}),
|
|
321
|
-
platform: platform(),
|
|
322
|
-
arch: arch(),
|
|
323
|
-
os_release: release(),
|
|
324
|
-
hostname_hash: hashToId(hostname()),
|
|
325
|
-
has_custom_hooks_path: !!(configToWrite.customPoliciesPath),
|
|
326
|
-
has_policy_params: !!(configToWrite.policyParams && Object.keys(configToWrite.policyParams).length > 0),
|
|
327
|
-
param_policy_names: configToWrite.policyParams ? Object.keys(configToWrite.policyParams) : [],
|
|
328
|
-
command_format: scope === "project" ? "npx" : "absolute",
|
|
329
|
-
});
|
|
330
|
-
} catch {
|
|
331
|
-
// Telemetry is best-effort — never block the operation
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
console.log(`Failproof AI hooks installed for all ${HOOK_EVENT_TYPES.length} event types (scope: ${scope}).`);
|
|
335
|
-
console.log(`Settings: ${settingsPath}`);
|
|
336
|
-
if (scope === "project") {
|
|
337
|
-
console.log(`Command: npx -y failproofai`);
|
|
338
|
-
console.log(`\nThis file can be committed to git — no machine-specific paths.`);
|
|
339
|
-
} else {
|
|
340
|
-
console.log(`Binary: ${binaryPath}`);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// Warn about duplicate-scope installations
|
|
344
|
-
const otherScopes = deduplicateScopes(HOOK_SCOPES, cwd).filter((s) => s !== scope);
|
|
345
|
-
const duplicates = otherScopes.filter((s) => hooksInstalledInSettings(s, cwd));
|
|
346
|
-
if (duplicates.length > 0) {
|
|
347
|
-
const scopeList = duplicates.map((s) => `${s} (${scopeLabel(s)})`).join(", ");
|
|
348
|
-
console.log();
|
|
349
|
-
console.log(`\x1B[33mWarning: Failproof AI hooks are also installed at ${scopeList}.\x1B[0m`);
|
|
350
|
-
console.log(`Having hooks in multiple scopes may cause duplicate policy evaluation.`);
|
|
351
|
-
console.log(`Use \`failproofai policies --uninstall --scope ${duplicates[0]}\` to remove the other installation,`);
|
|
352
|
-
console.log(`or \`failproofai policies\` to see all scopes.`);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Remove hooks from Claude Code settings.
|
|
358
|
-
*
|
|
359
|
-
* @param policyNames — if provided:
|
|
360
|
-
* - `undefined` or `["all"]` → remove all failproofai hooks from settings (original behavior)
|
|
361
|
-
* - `["block-sudo"]` → disable specific policies in config, keep hooks installed
|
|
362
|
-
* @param scope — settings scope to remove from (default: "user"), or "all" to remove from all scopes
|
|
363
|
-
* @param opts.betaOnly — set to true when removing only beta policies (adds beta_only flag to telemetry)
|
|
364
|
-
*/
|
|
365
|
-
export async function removeHooks(policyNames?: string[], scope: HookScope | "all" = "user", cwd?: string, opts?: { betaOnly?: boolean; source?: string; removeCustomHooks?: boolean }): Promise<void> {
|
|
366
|
-
// Resolve the effective config scope ("all" falls back to "user" for config reads/writes)
|
|
367
|
-
const configScope: HookScope = scope === "all" ? "user" : scope;
|
|
368
|
-
|
|
369
|
-
// Clear custom hooks path if requested
|
|
370
|
-
if (opts?.removeCustomHooks) {
|
|
371
|
-
const config = readScopedHooksConfig(configScope, cwd);
|
|
372
|
-
delete config.customPoliciesPath;
|
|
373
|
-
writeScopedHooksConfig(config, configScope, cwd);
|
|
374
|
-
console.log("Custom hooks path cleared.");
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// Remove specific policies from config (keep hooks installed)
|
|
378
|
-
if (policyNames && policyNames.length > 0 && !(policyNames.length === 1 && policyNames[0] === "all")) {
|
|
379
|
-
validatePolicyNames(policyNames);
|
|
380
|
-
const config = readScopedHooksConfig(configScope, cwd);
|
|
381
|
-
const removeSet = new Set(policyNames);
|
|
382
|
-
const remaining = config.enabledPolicies.filter((p) => !removeSet.has(p));
|
|
383
|
-
const notEnabled = policyNames.filter((p) => !config.enabledPolicies.includes(p));
|
|
384
|
-
if (notEnabled.length > 0) {
|
|
385
|
-
console.log(`Warning: policy(ies) not currently enabled: ${notEnabled.join(", ")}`);
|
|
386
|
-
}
|
|
387
|
-
const { policyParams: existingParams, ...baseConfig } = config;
|
|
388
|
-
const filteredParams = existingParams
|
|
389
|
-
? Object.fromEntries(Object.entries(existingParams).filter(([k]) => !removeSet.has(k)))
|
|
390
|
-
: null;
|
|
391
|
-
const updatedConfig: HooksConfig = {
|
|
392
|
-
...baseConfig,
|
|
393
|
-
enabledPolicies: remaining,
|
|
394
|
-
...(filteredParams && Object.keys(filteredParams).length > 0 ? { policyParams: filteredParams } : {}),
|
|
395
|
-
};
|
|
396
|
-
writeScopedHooksConfig(updatedConfig, configScope, cwd);
|
|
397
|
-
|
|
398
|
-
// Telemetry: track policy-only removal from config
|
|
399
|
-
try {
|
|
400
|
-
const distinctId = getInstanceId();
|
|
401
|
-
const actuallyRemoved = policyNames.filter((p) => config.enabledPolicies.includes(p));
|
|
402
|
-
await trackHookEvent(distinctId, "hooks_removed", {
|
|
403
|
-
scope,
|
|
404
|
-
removal_mode: opts?.betaOnly ? "beta_policies" : "policies",
|
|
405
|
-
beta_only: opts?.betaOnly ?? false,
|
|
406
|
-
policies_removed: actuallyRemoved,
|
|
407
|
-
removed_count: actuallyRemoved.length,
|
|
408
|
-
...(opts?.source ? { source: opts.source } : {}),
|
|
409
|
-
platform: platform(),
|
|
410
|
-
arch: arch(),
|
|
411
|
-
os_release: release(),
|
|
412
|
-
hostname_hash: hashToId(hostname()),
|
|
413
|
-
});
|
|
414
|
-
} catch {
|
|
415
|
-
// Telemetry is best-effort — never block the operation
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
console.log(`Disabled ${policyNames.length - notEnabled.length} policy(ies).`);
|
|
419
|
-
console.log(`Remaining: ${remaining.length > 0 ? remaining.join(", ") : "(none)"}`);
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// Capture enabled policies before clearing (used for accurate telemetry below)
|
|
424
|
-
const configBeforeRemoval = readScopedHooksConfig(configScope, cwd);
|
|
425
|
-
|
|
426
|
-
// Remove all failproofai hooks from Claude Code settings
|
|
427
|
-
const scopesToRemove: HookScope[] = scope === "all" ? [...HOOK_SCOPES] : [scope];
|
|
428
|
-
let totalRemoved = 0;
|
|
429
|
-
|
|
430
|
-
for (const s of scopesToRemove) {
|
|
431
|
-
const settingsPath = getSettingsPath(s, cwd);
|
|
432
|
-
|
|
433
|
-
if (!existsSync(settingsPath)) {
|
|
434
|
-
if (scope !== "all") {
|
|
435
|
-
console.log("No settings file found. Nothing to remove.");
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
continue;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
const settings = readSettings(settingsPath);
|
|
442
|
-
|
|
443
|
-
if (!settings.hooks) {
|
|
444
|
-
if (scope !== "all") {
|
|
445
|
-
console.log("No hooks found in settings. Nothing to remove.");
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
continue;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
const removed = removeHooksFromSettingsFile(settingsPath);
|
|
452
|
-
totalRemoved += removed;
|
|
453
|
-
|
|
454
|
-
if (scope !== "all") {
|
|
455
|
-
console.log(`Removed ${removed} failproofai hook(s) from settings.`);
|
|
456
|
-
console.log(`Settings: ${settingsPath}`);
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
if (scope === "all") {
|
|
461
|
-
console.log(`Removed ${totalRemoved} failproofai hook(s) from all scopes.`);
|
|
462
|
-
for (const s of scopesToRemove) {
|
|
463
|
-
console.log(` ${s}: ${getSettingsPath(s, cwd)}`);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Telemetry: track full hook removal from settings
|
|
468
|
-
try {
|
|
469
|
-
const distinctId = getInstanceId();
|
|
470
|
-
await trackHookEvent(distinctId, "hooks_removed", {
|
|
471
|
-
scope,
|
|
472
|
-
removal_mode: "hooks",
|
|
473
|
-
policies_removed: configBeforeRemoval.enabledPolicies,
|
|
474
|
-
removed_count: totalRemoved,
|
|
475
|
-
...(opts?.source ? { source: opts.source } : {}),
|
|
476
|
-
platform: platform(),
|
|
477
|
-
arch: arch(),
|
|
478
|
-
os_release: release(),
|
|
479
|
-
hostname_hash: hashToId(hostname()),
|
|
480
|
-
});
|
|
481
|
-
} catch {
|
|
482
|
-
// Telemetry is best-effort — never block the operation
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
// Clear policy config when removing from all scopes, or when no hooks remain in any scope
|
|
486
|
-
if (scope === "all") {
|
|
487
|
-
// Clear config across all three scopes
|
|
488
|
-
for (const s of HOOK_SCOPES) {
|
|
489
|
-
const existing = readScopedHooksConfig(s, cwd);
|
|
490
|
-
if (existing.enabledPolicies.length > 0 || existing.customPoliciesPath || existing.policyParams) {
|
|
491
|
-
const { customPoliciesPath: _drop, policyParams: _dropParams, ...rest } = existing;
|
|
492
|
-
writeScopedHooksConfig({ ...rest, enabledPolicies: [] }, s, cwd);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
} else if (!HOOK_SCOPES.some((s) => hooksInstalledInSettings(s, cwd))) {
|
|
496
|
-
const existing = readScopedHooksConfig(configScope, cwd);
|
|
497
|
-
const { customPoliciesPath: _drop, policyParams: _dropParams, ...rest } = existing;
|
|
498
|
-
writeScopedHooksConfig({ ...rest, enabledPolicies: [] }, configScope, cwd);
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
/**
|
|
503
|
-
* List all available policies with their per-scope enabled status.
|
|
504
|
-
* Layout adapts to the number of installed scopes:
|
|
505
|
-
* 0 scopes: compact "not installed" summary
|
|
506
|
-
* 1 scope: table with header + checkmarks, beta policies in a separate section
|
|
507
|
-
* 2+ scopes: column table with per-scope status, beta policies in a separate section
|
|
508
|
-
*
|
|
509
|
-
* Also shows:
|
|
510
|
-
* - Configured policyParams values beneath each policy
|
|
511
|
-
* - Warnings for unknown policyParams keys
|
|
512
|
-
* - Custom Hooks section if customPoliciesPath is set
|
|
513
|
-
*/
|
|
514
|
-
export async function listHooks(cwd?: string): Promise<void> {
|
|
515
|
-
const config = readMergedHooksConfig(cwd);
|
|
516
|
-
const enabledSet = new Set(config.enabledPolicies);
|
|
517
|
-
|
|
518
|
-
// Determine which scopes have hooks installed (deduplicate when paths overlap, e.g. cwd === home)
|
|
519
|
-
const uniqueScopes = deduplicateScopes(HOOK_SCOPES, cwd);
|
|
520
|
-
const installedScopes = uniqueScopes.filter((s) => hooksInstalledInSettings(s, cwd));
|
|
521
|
-
|
|
522
|
-
// Separate beta from regular policies
|
|
523
|
-
const regularPolicies = BUILTIN_POLICIES.filter((p) => !p.beta);
|
|
524
|
-
const betaPolicies = BUILTIN_POLICIES.filter((p) => p.beta);
|
|
525
|
-
|
|
526
|
-
// Dynamic name column width based on longest policy name
|
|
527
|
-
const nameColWidth = Math.max(...BUILTIN_POLICIES.map((p) => p.name.length)) + 2;
|
|
528
|
-
|
|
529
|
-
// All known builtin policy names (for unknown policyParams key detection)
|
|
530
|
-
const builtinPolicyNames = new Set(BUILTIN_POLICIES.map((p) => p.name));
|
|
531
|
-
|
|
532
|
-
// Helper: print params summary lines beneath a policy row
|
|
533
|
-
const printParamsSummary = (policyName: string, indent: string) => {
|
|
534
|
-
const params = config.policyParams?.[policyName];
|
|
535
|
-
if (!params) return;
|
|
536
|
-
for (const [key, val] of Object.entries(params)) {
|
|
537
|
-
console.log(`${indent} ${key}: ${JSON.stringify(val)}`);
|
|
538
|
-
}
|
|
539
|
-
};
|
|
540
|
-
|
|
541
|
-
const statusCol = 8;
|
|
542
|
-
const printSimpleRow = (policy: { name: string; description: string }) => {
|
|
543
|
-
const mark = enabledSet.has(policy.name) ? `\x1B[32m\u2713\x1B[0m` : " ";
|
|
544
|
-
console.log(` ${mark}${" ".repeat(statusCol - 1)}${policy.name.padEnd(nameColWidth)}${policy.description}`);
|
|
545
|
-
printParamsSummary(policy.name, ` ${" ".repeat(statusCol)}`);
|
|
546
|
-
};
|
|
547
|
-
const printBetaSection = (printRow: (p: { name: string; description: string }) => void) => {
|
|
548
|
-
if (betaPolicies.length > 0) {
|
|
549
|
-
console.log(`\n \x1B[2m\u2500\u2500 Beta \u2500\u2500\x1B[0m`);
|
|
550
|
-
for (const policy of betaPolicies) printRow(policy);
|
|
551
|
-
}
|
|
552
|
-
};
|
|
553
|
-
|
|
554
|
-
if (installedScopes.length === 0) {
|
|
555
|
-
// State A: No hooks installed — show table with configured state + descriptions
|
|
556
|
-
console.log("\nFailproof AI Policies \u2014 not installed\n");
|
|
557
|
-
|
|
558
|
-
console.log(` ${"Status".padEnd(statusCol)}${"Name".padEnd(nameColWidth)}Description`);
|
|
559
|
-
console.log(` ${"\u2500".repeat(6)} ${"\u2500".repeat(nameColWidth - 2)} ${"\u2500".repeat(38)}`);
|
|
560
|
-
|
|
561
|
-
for (const policy of regularPolicies) printSimpleRow(policy);
|
|
562
|
-
printBetaSection(printSimpleRow);
|
|
563
|
-
|
|
564
|
-
if (config.enabledPolicies.length > 0) {
|
|
565
|
-
console.log("\n Policies not installed. Run `failproofai policies --install` to activate.");
|
|
566
|
-
} else {
|
|
567
|
-
console.log("\n Run `failproofai policies --install` to get started.");
|
|
568
|
-
}
|
|
569
|
-
console.log(" Config: ~/.failproofai/policies-config.json\n");
|
|
570
|
-
} else if (installedScopes.length === 1) {
|
|
571
|
-
// State B: Single scope — table with header row
|
|
572
|
-
const scope = installedScopes[0];
|
|
573
|
-
console.log(`\nFailproof AI Hook Policies (${scope})\n`);
|
|
574
|
-
|
|
575
|
-
console.log(` ${"Status".padEnd(statusCol)}${"Name".padEnd(nameColWidth)}Description`);
|
|
576
|
-
console.log(` ${"\u2500".repeat(6)} ${"\u2500".repeat(nameColWidth - 2)} ${"\u2500".repeat(38)}`);
|
|
577
|
-
|
|
578
|
-
for (const policy of regularPolicies) printSimpleRow(policy);
|
|
579
|
-
printBetaSection(printSimpleRow);
|
|
580
|
-
|
|
581
|
-
console.log("\n Config: ~/.failproofai/policies-config.json\n");
|
|
582
|
-
} else {
|
|
583
|
-
// State C: Multiple scopes — column table
|
|
584
|
-
const COL = 9;
|
|
585
|
-
const scopeLabelMap: Record<HookScope, string> = {
|
|
586
|
-
user: "User",
|
|
587
|
-
project: "Project",
|
|
588
|
-
local: "Local",
|
|
589
|
-
};
|
|
590
|
-
|
|
591
|
-
console.log("\nFailproof AI Hook Policies\n");
|
|
592
|
-
|
|
593
|
-
// Header with only installed scope columns + separator
|
|
594
|
-
const buildScopePrefix = () => {
|
|
595
|
-
let s = " ";
|
|
596
|
-
for (const sc of installedScopes) s += scopeLabelMap[sc].padEnd(COL);
|
|
597
|
-
return s;
|
|
598
|
-
};
|
|
599
|
-
const scopeHeaderWidth = installedScopes.length * COL;
|
|
600
|
-
console.log(`${buildScopePrefix()}${"Name".padEnd(nameColWidth)}Description`);
|
|
601
|
-
console.log(` ${"\u2500".repeat(scopeHeaderWidth)}${"\u2500".repeat(nameColWidth)}${"\u2500".repeat(38)}`);
|
|
602
|
-
|
|
603
|
-
const printMultiScopeRow = (policy: { name: string; description: string }) => {
|
|
604
|
-
const enabled = enabledSet.has(policy.name);
|
|
605
|
-
let row = " ";
|
|
606
|
-
for (const _scope of installedScopes) {
|
|
607
|
-
if (enabled) {
|
|
608
|
-
row += `\x1B[32m\u2713 ON\x1B[0m` + " ".repeat(COL - 4);
|
|
609
|
-
} else {
|
|
610
|
-
row += " OFF" + " ".repeat(COL - 5);
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
row += policy.name.padEnd(nameColWidth) + policy.description;
|
|
614
|
-
console.log(row);
|
|
615
|
-
printParamsSummary(policy.name, ` ${" ".repeat(scopeHeaderWidth)}`);
|
|
616
|
-
};
|
|
617
|
-
|
|
618
|
-
for (const policy of regularPolicies) printMultiScopeRow(policy);
|
|
619
|
-
|
|
620
|
-
if (betaPolicies.length > 0) {
|
|
621
|
-
console.log(`\n \x1B[2m\u2500\u2500 Beta \u2500\u2500\x1B[0m`);
|
|
622
|
-
for (const policy of betaPolicies) printMultiScopeRow(policy);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
console.log("\n Config: ~/.failproofai/policies-config.json");
|
|
626
|
-
|
|
627
|
-
// Multi-scope warning
|
|
628
|
-
const scopeNames = installedScopes.join(", ");
|
|
629
|
-
console.log();
|
|
630
|
-
console.log(`\x1B[33m\u26A0 Hooks in multiple scopes (${scopeNames}).\x1B[0m`);
|
|
631
|
-
console.log(" Consider keeping one. Remove with: failproofai policies --uninstall --scope <scope>\n");
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
// Warn about unknown policyParams keys
|
|
635
|
-
if (config.policyParams) {
|
|
636
|
-
for (const key of Object.keys(config.policyParams)) {
|
|
637
|
-
if (!builtinPolicyNames.has(key)) {
|
|
638
|
-
console.log(` \x1B[33mWarning: unknown policyParams key "${key}" — possible typo\x1B[0m`);
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
// Custom Policies section
|
|
644
|
-
if (config.customPoliciesPath) {
|
|
645
|
-
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`);
|
|
646
|
-
if (!existsSync(config.customPoliciesPath)) {
|
|
647
|
-
console.log(` \x1B[31m\u2717 File not found: ${config.customPoliciesPath}\x1B[0m`);
|
|
648
|
-
} else {
|
|
649
|
-
const hooks = await loadCustomHooks(config.customPoliciesPath);
|
|
650
|
-
if (hooks.length === 0) {
|
|
651
|
-
console.log(` \x1B[31m\u2717 ERR failed to load (check ~/.failproofai/logs/hooks.log)\x1B[0m`);
|
|
652
|
-
} else {
|
|
653
|
-
const descColWidth = nameColWidth;
|
|
654
|
-
for (const hook of hooks) {
|
|
655
|
-
console.log(` \x1B[32m\u2713\x1B[0m ${hook.name.padEnd(descColWidth)}${hook.description ?? ""}`);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
console.log();
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
// Convention Policies section (.failproofai/policies/*policies.{js,mjs,ts})
|
|
663
|
-
const base = cwd ? resolve(cwd) : process.cwd();
|
|
664
|
-
const conventionDirs: { label: string; dir: string }[] = [
|
|
665
|
-
{ label: "Project", dir: resolve(base, ".failproofai", "policies") },
|
|
666
|
-
{ label: "User", dir: resolve(homedir(), ".failproofai", "policies") },
|
|
667
|
-
];
|
|
668
|
-
|
|
669
|
-
for (const { label, dir } of conventionDirs) {
|
|
670
|
-
const files = discoverPolicyFiles(dir);
|
|
671
|
-
if (files.length === 0) continue;
|
|
672
|
-
|
|
673
|
-
console.log(`\n \u2500\u2500 Convention Policies \u2014 ${label} (${dir}) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
674
|
-
for (const file of files) {
|
|
675
|
-
try {
|
|
676
|
-
const hooks = await loadCustomHooks(file);
|
|
677
|
-
if (hooks.length === 0) {
|
|
678
|
-
const filename = basename(file);
|
|
679
|
-
console.log(` \x1B[31m\u2717\x1B[0m ${filename.padEnd(nameColWidth)}\x1B[31mfailed to load\x1B[0m`);
|
|
680
|
-
} else {
|
|
681
|
-
const filename = basename(file);
|
|
682
|
-
const hookSummary = hooks.map((h) => h.name).join(", ");
|
|
683
|
-
console.log(` \x1B[32m\u2713\x1B[0m ${filename.padEnd(nameColWidth)}${hooks.length} hook(s): ${hookSummary}`);
|
|
684
|
-
}
|
|
685
|
-
} catch {
|
|
686
|
-
const filename = basename(file);
|
|
687
|
-
console.log(` \x1B[31m\u2717\x1B[0m ${filename.padEnd(nameColWidth)}\x1B[31merror\x1B[0m`);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
console.log();
|
|
691
|
-
}
|
|
692
|
-
}
|