failproofai 1.0.10 → 1.0.11-beta.0
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 +6 -6
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
- 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 +4 -4
- 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.meta +8 -0
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +3 -3
- 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 +4 -4
- 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 +1 -1
- package/.next/standalone/.next/server/app/_not-found.meta +8 -0
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +4 -4
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +4 -4
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +3 -3
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -3
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +4 -4
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.meta +8 -0
- package/.next/standalone/.next/server/app/index.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +4 -4
- 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/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +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/build-manifest.json +3 -3
- 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 +5 -5
- 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/build-manifest.json +3 -3
- 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 +5 -5
- 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/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +5 -5
- 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/app/settings/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/settings/page.js +9 -9
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__0qxhecv._.js → [externals]__0d7i9ea._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[externals]__0sg9-3p._.js → [externals]__0hjaw70._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[externals]__1_9ze9b._.js +3 -0
- package/.next/standalone/.next/server/chunks/[externals]__1oenfmn._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ga9hs7._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l3yhx4._.js +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0moxohc._.js +22 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0z2ll-a._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adacul._.js +11 -11
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1autwno._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1v25n-6._.js +3 -0
- package/.next/standalone/.next/server/chunks/_09dz7xv._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +2 -2
- package/.next/standalone/.next/server/chunks/_1fz8m31._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1jrv3hg._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1nx8fim._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1ogwigf._.js +1 -1
- package/.next/standalone/.next/server/chunks/{_1q5i8mb._.js → _1q27azx._.js} +2 -2
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_0el6rg8._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_0ol5pa3._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_04op_ou._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_1rqmk27._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{node_modules_posthog-node_dist_entrypoints_index_node_mjs_0dr20uz._.js → node_modules_posthog-node_dist_entrypoints_index_node_mjs_1w7tiq4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__04usis8._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1-bm5zf._.js → [root-of-the-server]__0502lat._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_gn5iz._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0f765xr._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01bmjsj._.js → [root-of-the-server]__0h38gzz._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hoaz1g._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1ouobn4._.js → [root-of-the-server]__0mxmwtx._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__19evfi8._.js → [root-of-the-server]__0uescqv._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1484zv2._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1mf3zp6._.js → [root-of-the-server]__19dutr7._.js} +4 -4
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0oqrl71._.js → [root-of-the-server]__1_qv8oh._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1u6sn69._.js → [root-of-the-server]__1ab4ifb._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1fbrk56._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pprgri._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1um4yxn._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1wb4yt2._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1y3n3cn._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0bqoto4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_16pa9ht._.js → _0lnpwk8._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0yq5_3a._.js → _15y8myg._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1gb0ifp._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_042cgl1._.js → _1o95rf0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1zopuov._.js → _1thr5rf._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +12 -14
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9sni._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_1hl81y4._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_0nkkbfv._.js +6 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
- package/.next/standalone/.next/server/middleware.js +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- 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 +23 -23
- package/.next/standalone/.next/static/chunks/{03h3b-uomi7_d.js → 0pra9i676pym1.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2kj826h1w9r47.js → 1-lpi0m-hc1kb.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3ob2161ap37ul.js → 17yvyyblr_eb5.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3nkc2jlgyygda.js → 1mylcr99gccyz.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2j92xul6y24_v.js → 1wozchtn2etvh.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3mjfvng11xnoo.js → 23thtelz1a-ur.js} +2 -2
- package/.next/standalone/.next/static/chunks/{1fqukzzowjflt.js → 2bc17tohgs4bs.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3u1s8dsqiean5.js → 2xq-ejo8kti18.js} +1 -1
- package/.next/standalone/.next/static/chunks/3-_pth_c9n938.js +1 -0
- package/.next/standalone/.next/static/chunks/{3i8rg2fv9nd6e.js → 3n46e45atic-m.js} +1 -1
- package/.next/standalone/.next/static/chunks/{078dofaxvjgpd.js → 3q7sndqftqhw9.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0542cuk_va8g1.js → 3sg07wnn969xq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-11dn2pegmg9_9.js → turbopack-1opxka4dtjbc5.js} +1 -1
- package/.next/standalone/app/actions/install-hooks-web.ts +10 -2
- package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/hash.js/sha256/256.js +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/hash.js/sha256/package.json +1 -0
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js +17 -17
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +18 -18
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +3 -3
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +13 -13
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/base-server.js +1 -2
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/image-optimizer.js +265 -53
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js +177 -19
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/index.js +36 -17
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/shared-cache-controls.external.js +14 -6
- package/.next/standalone/node_modules/next/dist/server/lib/match-next-data-pathname.js +3 -1
- package/.next/standalone/node_modules/next/dist/server/lib/node-fs-methods.js +14 -0
- package/.next/standalone/node_modules/next/dist/server/lib/route-cache-key.js +77 -0
- package/.next/standalone/node_modules/next/dist/server/lib/router-utils/block-cross-site-dev.js +9 -11
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/mcp/get-mcp-middleware.js +4 -2
- package/.next/standalone/node_modules/next/dist/server/next-server.js +7 -3
- package/.next/standalone/node_modules/next/dist/server/response-cache/index.js +32 -16
- package/.next/standalone/node_modules/next/dist/server/route-matcher-providers/app-page-route-matcher-provider.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/route-modules/pages/pages-handler.js +6 -1
- package/.next/standalone/node_modules/next/dist/server/route-modules/route-module.js +9 -2
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.js +30 -29
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/app-paths.js +18 -1
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +10 -10
- package/.next/standalone/package.json +14 -11
- package/.next/standalone/sdk/python/README.md +41 -0
- package/.next/standalone/sdk/python/docs/README.md +1 -0
- package/.next/standalone/sdk/python/docs/otel/README.md +36 -0
- package/.next/standalone/sdk/python/docs/otel/examples/agent_trace.py +30 -0
- package/.next/standalone/sdk/python/docs/otel/examples/quickstart.py +22 -0
- package/.next/standalone/sdk/python/failproofai_sdk/__init__.py +8 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/__init__.py +3 -0
- package/.next/standalone/sdk/python/failproofai_sdk/integrations/otel.py +189 -0
- package/.next/standalone/sdk/python/pyproject.toml +2 -1
- package/.next/standalone/sdk/python/tests/test_docs.py +16 -3
- package/.next/standalone/sdk/python/tests/test_integrations.py +1 -1
- package/.next/standalone/sdk/python/tests/test_otel.py +147 -0
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +4 -1
- package/.next/standalone/sdk/python/uv.lock +258 -147
- package/.next/standalone/sdk/typescript/README.md +43 -0
- package/.next/standalone/sdk/typescript/integration/ai.test.ts +9 -2
- package/.next/standalone/sdk/typescript/package-lock.json +57 -5
- package/.next/standalone/sdk/typescript/package.json +2 -0
- package/.next/standalone/sdk/typescript/src/edge/index.ts +9 -0
- package/.next/standalone/sdk/typescript/src/index.ts +2 -0
- package/.next/standalone/sdk/typescript/src/integrations/index.ts +4 -1
- package/.next/standalone/sdk/typescript/src/integrations/otel.ts +204 -0
- package/.next/standalone/sdk/typescript/test/integrations.test.ts +1 -1
- package/.next/standalone/sdk/typescript/test/otel.test.ts +125 -0
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +653 -1077
- package/dist/cli.mjs +8781 -4050
- package/dist/worker.mjs +170 -62
- package/hermes-plugin/plugin.yaml +1 -1
- package/package.json +14 -11
- package/scripts/launch-facts.ts +157 -0
- package/scripts/launch-ready.ts +228 -0
- package/scripts/launch-screen.ts +202 -0
- package/scripts/launch.ts +106 -49
- package/scripts/skew-log-filter.ts +38 -0
- package/src/audit/cli-login.ts +39 -59
- package/src/audit/cli.ts +308 -228
- package/src/audit/index.ts +45 -2
- package/src/audit/schedule-cli.ts +83 -120
- package/src/audit/types.ts +31 -0
- package/src/hooks/agent-selection.ts +155 -0
- package/src/hooks/backfill-cli.ts +151 -137
- package/src/hooks/backfill-request.ts +149 -0
- package/src/hooks/cloud-connection.ts +1 -1
- package/src/hooks/cloud-enrollment-cli.ts +78 -28
- package/src/hooks/cloud-introspect.ts +3 -0
- package/src/hooks/collector-config.ts +10 -1
- package/src/hooks/config-status.ts +717 -0
- package/src/hooks/configure-wizard.ts +967 -988
- package/src/hooks/daemon-service.ts +16 -6
- package/src/hooks/did-you-mean.ts +185 -0
- package/src/hooks/flush-cli.ts +33 -7
- package/src/hooks/fp-config.ts +96 -0
- package/src/hooks/fp-home.ts +11 -0
- package/src/hooks/fp-reset.ts +102 -95
- package/src/hooks/handler.ts +4 -0
- package/src/hooks/harness-cli.ts +87 -138
- package/src/hooks/install-prompt.ts +38 -477
- package/src/hooks/integrations.ts +1 -1
- package/src/hooks/jev-cli.ts +183 -196
- package/src/hooks/manager.ts +554 -358
- package/src/hooks/onboarding-attempt.ts +11 -9
- package/src/hooks/otel-cli.ts +350 -0
- package/src/hooks/otel-output.ts +24 -0
- package/src/hooks/otel-writers.ts +215 -0
- package/src/hooks/pack-cli.ts +219 -204
- package/src/hooks/report-body.ts +50 -0
- package/src/hooks/safe-config-write.ts +4 -2
- package/src/hooks/session-pause-cli.ts +93 -73
- package/src/hooks/tui.ts +849 -389
- package/src/hooks/uninstall-cli.ts +136 -149
- package/src/hooks/untraced-note.ts +52 -0
- package/.next/standalone/.next/server/chunks/[externals]__19_pzeq._.js +0 -3
- package/.next/standalone/.next/server/chunks/[externals]__20kzpkf._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__01eqny5._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__05ja_05._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0igxt32._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0zyc_nm._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ttrwnd._.js +0 -22
- package/.next/standalone/.next/server/chunks/_0bs-v8p._.js +0 -3
- package/.next/standalone/.next/server/chunks/_185gyk9._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__056wjo4._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0n0xg95._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rwtwpm._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0yrsbd_._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__11mayhe._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15578wp._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m_svbe._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1q4p5b8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +0 -6
- package/.next/standalone/.next/static/chunks/1lyg_puttohbc.js +0 -1
- /package/.next/standalone/.next/static/{ECs8__hcNabYV58WfDh-3 → xtcpqBNBdjQVerPMkI2HI}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{ECs8__hcNabYV58WfDh-3 → xtcpqBNBdjQVerPMkI2HI}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{ECs8__hcNabYV58WfDh-3 → xtcpqBNBdjQVerPMkI2HI}/_ssgManifest.js +0 -0
package/src/hooks/pack-cli.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdir
|
|
|
12
12
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
13
13
|
import { INTEGRATION_TYPES } from "./types";
|
|
14
14
|
import { PACK_COMMIT_RE, PACK_VERSION_RE } from "./pack-manifest";
|
|
15
|
-
import { detectInstalledClis } from "./integrations";
|
|
15
|
+
import { detectInstalledClis, getIntegration } from "./integrations";
|
|
16
16
|
import {
|
|
17
17
|
packParamsProblem,
|
|
18
18
|
parsePackIdentity,
|
|
@@ -57,8 +57,10 @@ import {
|
|
|
57
57
|
note,
|
|
58
58
|
nextStep,
|
|
59
59
|
optsFor,
|
|
60
|
+
paint,
|
|
60
61
|
rows as kitRows,
|
|
61
62
|
rule,
|
|
63
|
+
screenKit,
|
|
62
64
|
stack,
|
|
63
65
|
table,
|
|
64
66
|
title,
|
|
@@ -729,25 +731,23 @@ export async function runPolicyPicker(
|
|
|
729
731
|
`\`policies ${action}\` with no name needs a terminal to show you the list.`,
|
|
730
732
|
"From a script, name what you mean:",
|
|
731
733
|
` failproofai policies ${action} <policy-name>`,
|
|
732
|
-
|
|
734
|
+
// Pack-lane remove takes an id and no flags: it uninstalls the whole pack,
|
|
735
|
+
// so advertising add's selection flags here invited exactly that.
|
|
736
|
+
action === "remove"
|
|
737
|
+
? " failproofai policies remove <pack-id>"
|
|
738
|
+
: " failproofai policies add <owner>/<repo> [--policy a,b] [--category x,y] [--all]",
|
|
733
739
|
]);
|
|
734
740
|
}
|
|
735
741
|
|
|
736
742
|
if (packs.length === 0) {
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
opts,
|
|
746
|
-
),
|
|
747
|
-
note("Someone else's: failproofai policies add <owner>/<repo>", opts),
|
|
748
|
-
note("Look first: failproofai policies show <owner>/<repo>", opts),
|
|
749
|
-
),
|
|
750
|
-
);
|
|
743
|
+
// The same three doors the policies screen's empty state offers.
|
|
744
|
+
const kit = screenKit(opts);
|
|
745
|
+
return ok([
|
|
746
|
+
"No policies are installed yet.",
|
|
747
|
+
` Turn on ours: ${kit.cmd("failproofai policies add FailproofAI/policies")}`,
|
|
748
|
+
` Or anyone's: ${kit.cmd("failproofai policies add <owner>/<repo>")}`,
|
|
749
|
+
` Look first: ${kit.cmd("failproofai policies show <owner>/<repo>")}`,
|
|
750
|
+
]);
|
|
751
751
|
}
|
|
752
752
|
|
|
753
753
|
// One row per policy across every pack. The pack id leads the section heading
|
|
@@ -777,10 +777,9 @@ export async function runPolicyPicker(
|
|
|
777
777
|
|
|
778
778
|
const before = new Set(rows.filter((r) => r.checked).map((r) => r.value));
|
|
779
779
|
const picked = await multiSelect<string>({
|
|
780
|
-
message: "
|
|
780
|
+
message: "Choose policies",
|
|
781
781
|
choices: rows,
|
|
782
782
|
summaryNoun: "policies",
|
|
783
|
-
hint: "space toggles · ctrl+a all · ↵ confirm · what is on now is ticked",
|
|
784
783
|
stdin,
|
|
785
784
|
stdout,
|
|
786
785
|
});
|
|
@@ -2244,7 +2243,6 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
2244
2243
|
);
|
|
2245
2244
|
let version =
|
|
2246
2245
|
flag("version") ?? (entry ? inferTaggedVersion(entry, bundledSources) : null) ?? undefined;
|
|
2247
|
-
let versionFromSha = false;
|
|
2248
2246
|
// The id and the repo are usually the same words, and requiring both is asking
|
|
2249
2247
|
// the same question twice. Either one alone answers for the other.
|
|
2250
2248
|
const dryRun = rest.includes("--dry-run") || !repo;
|
|
@@ -2319,7 +2317,6 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
2319
2317
|
const resolved = versionForPublish(provenance);
|
|
2320
2318
|
if ("error" in resolved) return fail(resolved.error);
|
|
2321
2319
|
version = resolved.version;
|
|
2322
|
-
versionFromSha = true;
|
|
2323
2320
|
}
|
|
2324
2321
|
|
|
2325
2322
|
// Check an EXPLICIT tag against the version before anything reaches the
|
|
@@ -2365,16 +2362,18 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
2365
2362
|
// A repository this command creates is made public, so this only ever
|
|
2366
2363
|
// fires on reuse of one that was already private.
|
|
2367
2364
|
if (repoInfo.json?.private === true && !allowPrivate) {
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2365
|
+
// The reason is the install, not the privacy: it fetches over anonymous
|
|
2366
|
+
// HTTPS with no credential to offer, so it 404s even for the author on
|
|
2367
|
+
// another machine, and publishing would only attach three assets
|
|
2368
|
+
// advertising a route nobody can take.
|
|
2369
|
+
return fail(
|
|
2370
|
+
screenKit(optsFor(process.stderr)).notice(
|
|
2371
|
+
"fail",
|
|
2372
|
+
`${repo} is private, so nothing was published: installs fetch over anonymous HTTPS, so every one would 404.\n` +
|
|
2373
|
+
`Make it public and publish again: \`gh repo edit ${repo} --visibility public\`\n` +
|
|
2374
|
+
"Or keep it private and hand the pack over yourself: `--allow-private`",
|
|
2375
|
+
),
|
|
2376
|
+
);
|
|
2378
2377
|
}
|
|
2379
2378
|
}
|
|
2380
2379
|
const tag = flag("tag") ?? version;
|
|
@@ -2528,36 +2527,46 @@ async function publish(rest: string[]): Promise<PackCliResult> {
|
|
|
2528
2527
|
uploaded.push(asset);
|
|
2529
2528
|
}
|
|
2530
2529
|
|
|
2530
|
+
// The design's done screen: one `✓` per thing that happened, then how to
|
|
2531
|
+
// install it. The policy count comes from the build; a pack of Jev checks
|
|
2532
|
+
// alone has no regex policies to count, and says so in its reminder.
|
|
2533
|
+
const kit = screenKit(optsFor(process.stdout));
|
|
2534
|
+
const policies = built.meta?.policies ?? 0;
|
|
2535
|
+
const counted = policies > 0 ? ` with ${policies} ${policies === 1 ? "policy" : "policies"}` : "";
|
|
2536
|
+
// Where it went, only when the id and version do not already say it: `--id`
|
|
2537
|
+
// can differ from the repository, and `--tag v1.2.0` from version 1.2.0.
|
|
2538
|
+
const where = repo === id && tag === version ? "" : ` to ${repo} at tag ${tag}`;
|
|
2531
2539
|
const lines = [
|
|
2540
|
+
kit.header("Publish"),
|
|
2541
|
+
"",
|
|
2532
2542
|
// What was done to the user's own directory, before what was done to
|
|
2533
2543
|
// GitHub. A side effect on somebody's working tree is never silent, even
|
|
2534
2544
|
// when it is the side effect they wanted.
|
|
2535
|
-
...gitLines,
|
|
2536
|
-
...(
|
|
2537
|
-
...bundleNote,
|
|
2538
|
-
...(created ? [`Created ${repo} (public).`] : []),
|
|
2539
|
-
`Published ${id}@${version} to ${repo} at tag ${tag}.` +
|
|
2540
|
-
(versionFromSha ? " That names the commit it was built from." : ""),
|
|
2541
|
-
` ${assets.length} assets attached`,
|
|
2542
|
-
...(built.meta?.semanticOnly ? JEV_ONLY_ROLLBACK_REMINDER : []),
|
|
2543
|
-
"",
|
|
2544
|
-
// The install lines are the whole point of the success message, and on a
|
|
2545
|
-
// private repository they are a lie — `policies add` 404s there. Print the
|
|
2546
|
-
// warning INSTEAD of them, never underneath them: a reader who copies the
|
|
2547
|
-
// first command they see must not be copying one that cannot work.
|
|
2548
|
-
...(isPrivate
|
|
2545
|
+
...gitLines.map((line) => kit.ok(line)),
|
|
2546
|
+
...(discovered.length > 1
|
|
2549
2547
|
? [
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
` gh repo edit ${repo} --visibility public`,
|
|
2548
|
+
kit.ok(
|
|
2549
|
+
`Bundled ${discovered.length} files into one artifact: ` +
|
|
2550
|
+
discovered.map((f) => f.replace(process.cwd() + "/", "")).join(", "),
|
|
2551
|
+
),
|
|
2555
2552
|
]
|
|
2556
|
-
: [
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2553
|
+
: []),
|
|
2554
|
+
...(created ? [kit.ok(`Created ${repo} (public).`)] : []),
|
|
2555
|
+
kit.ok(`Published ${id}@${version}${counted}${where}.`),
|
|
2556
|
+
// The install line is the whole point of the success message, and on a
|
|
2557
|
+
// private repository it is a lie — `policies add` 404s there. Print the
|
|
2558
|
+
// warning INSTEAD of it, never underneath it: a reader who copies the
|
|
2559
|
+
// first command they see must not be copying one that cannot work.
|
|
2560
|
+
...(isPrivate
|
|
2561
|
+
? kit.notice(
|
|
2562
|
+
"caution",
|
|
2563
|
+
`${repo} is private, and installs fetch over anonymous HTTPS, so every install will fail.\n` +
|
|
2564
|
+
`Share the three assets yourself, or make it public: \`gh repo edit ${repo} --visibility public\``,
|
|
2565
|
+
)
|
|
2566
|
+
: [` Anyone can install it: ${kit.cmd(`failproofai policies add ${repo}`)}`]),
|
|
2567
|
+
...(built.meta?.semanticOnly
|
|
2568
|
+
? kit.notice("caution", JEV_ONLY_ROLLBACK_REMINDER.map((line) => line.trim()).join("\n"))
|
|
2569
|
+
: []),
|
|
2561
2570
|
];
|
|
2562
2571
|
return ok(lines);
|
|
2563
2572
|
}
|
|
@@ -2612,7 +2621,7 @@ async function pickClis(
|
|
|
2612
2621
|
): Promise<string[] | null> {
|
|
2613
2622
|
const detected = new Set(detectInstalledClis());
|
|
2614
2623
|
const choices: MultiChoice<string>[] = INTEGRATION_TYPES.map((id) => ({
|
|
2615
|
-
label: id,
|
|
2624
|
+
label: getIntegration(id).displayName,
|
|
2616
2625
|
value: id,
|
|
2617
2626
|
checked: true,
|
|
2618
2627
|
hint: detected.has(id) ? "installed here" : "",
|
|
@@ -2621,8 +2630,9 @@ async function pickClis(
|
|
|
2621
2630
|
message: "Which agents should this pack guard?",
|
|
2622
2631
|
choices,
|
|
2623
2632
|
minSelected: 1,
|
|
2633
|
+
minMessage: "Pick at least one agent.",
|
|
2624
2634
|
summaryNoun: "agents",
|
|
2625
|
-
|
|
2635
|
+
meta: (checked) => `${checked.length} of ${choices.length} selected · ${detected.size} found on this machine`,
|
|
2626
2636
|
stdin: io.stdin,
|
|
2627
2637
|
stdout: io.stdout,
|
|
2628
2638
|
});
|
|
@@ -2710,21 +2720,18 @@ async function pickFromSource(
|
|
|
2710
2720
|
});
|
|
2711
2721
|
}
|
|
2712
2722
|
}
|
|
2713
|
-
const
|
|
2714
|
-
|
|
2715
|
-
//
|
|
2716
|
-
//
|
|
2723
|
+
const kit = screenKit(optsFor(io.stdout));
|
|
2724
|
+
const lead = ["", kit.header(`Add ${preview.id}@${preview.version}`), ""];
|
|
2725
|
+
// Said BEFORE the list because the list cannot say it: Jev checks are not
|
|
2726
|
+
// rows here, and they arrive whole with the pack.
|
|
2717
2727
|
if (preview.semantic.length > 0) {
|
|
2718
|
-
|
|
2719
|
-
`\n This pack also brings ${semanticPhrase(preview.semantic.length)} (not selectable), ` +
|
|
2720
|
-
`${howJevAsksChecks(preview)}.\n See: failproofai policies show ${source}\n\n`,
|
|
2721
|
-
);
|
|
2728
|
+
lead.push(`Also brings ${semanticPhrase(preview.semantic.length)}, ${howJevAsksChecks(preview)}.`, "");
|
|
2722
2729
|
}
|
|
2730
|
+
io.stdout.write(lead.join("\n") + "\n");
|
|
2723
2731
|
const picked = await multiSelect<string>({
|
|
2724
|
-
message:
|
|
2732
|
+
message: "Choose policies",
|
|
2725
2733
|
choices: rows,
|
|
2726
2734
|
summaryNoun: "policies",
|
|
2727
|
-
hint: `space toggles · ctrl+a all · ↵ confirm · ${on} of ${rows.length} are the publisher's defaults`,
|
|
2728
2735
|
stdin: io.stdin,
|
|
2729
2736
|
stdout: io.stdout,
|
|
2730
2737
|
});
|
|
@@ -2798,29 +2805,15 @@ async function add(rest: string[]): Promise<PackCliResult> {
|
|
|
2798
2805
|
|
|
2799
2806
|
try {
|
|
2800
2807
|
const result = await addPack(resolvedSource!, selection);
|
|
2801
|
-
const
|
|
2802
|
-
|
|
2803
|
-
? [
|
|
2804
|
-
// What was OBSERVED, and then the inference — not the inference
|
|
2805
|
-
// stated as fact. Identical artifact bytes are the only evidence
|
|
2806
|
-
// there is, and they cannot tell a renamed pack from a second pack
|
|
2807
|
-
// one repository builds from the same source. Absorbing is the
|
|
2808
|
-
// right default (a publisher renaming a set must not reset everyone
|
|
2809
|
-
// who narrowed it), but the record that goes away is one the user
|
|
2810
|
-
// installed on purpose, so the line has to say what to do when the
|
|
2811
|
-
// guess was wrong instead of asserting it was right.
|
|
2812
|
-
`Replaced ${result.replaced.join(", ")} — same artifact, so it was taken as this pack renamed, and your selection was carried over.`,
|
|
2813
|
-
`If ${result.replaced.length > 1 ? "those are separate packs" : "that is a separate pack"}, re-add ${result.replaced.join(", ")} to restore ${result.replaced.length > 1 ? "them" : "it"}.`,
|
|
2814
|
-
]
|
|
2815
|
-
: []),
|
|
2816
|
-
result.resolvedFromLatest
|
|
2817
|
-
? `Installed ${result.id}@${result.version} from ${result.source} (newest release; pinned to ${result.tag})`
|
|
2818
|
-
: `Installed ${result.id}@${result.version} from ${result.source}`,
|
|
2819
|
-
];
|
|
2808
|
+
const kit = screenKit(optsFor(process.stdout));
|
|
2809
|
+
const ref = `${result.id}@${result.version}`;
|
|
2820
2810
|
const skipped = result.available.filter((n) => !result.enabled.includes(n));
|
|
2811
|
+
const policies = (n: number): string => `${n} ${n === 1 ? "policy" : "policies"}`;
|
|
2821
2812
|
|
|
2822
2813
|
// Say WHY this set is on. Without it, "10 of 39 enabled" reads like
|
|
2823
|
-
// something went wrong rather than like the pack's own recommendation.
|
|
2814
|
+
// something went wrong rather than like the pack's own recommendation. Five
|
|
2815
|
+
// distinct reasons, because a reader who cannot tell them apart cannot tell
|
|
2816
|
+
// whose decision put these policies on their machine.
|
|
2824
2817
|
const why = {
|
|
2825
2818
|
defaults: "the pack's defaults",
|
|
2826
2819
|
selected: "your selection",
|
|
@@ -2831,54 +2824,85 @@ async function add(rest: string[]): Promise<PackCliResult> {
|
|
|
2831
2824
|
added: "what you added, plus what was already on",
|
|
2832
2825
|
all: "everything in the pack",
|
|
2833
2826
|
}[result.selection];
|
|
2834
|
-
//
|
|
2835
|
-
//
|
|
2836
|
-
//
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
// nothing is
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2827
|
+
// "Turned on N" only when this run turned them on. A re-add that carried
|
|
2828
|
+
// the machine's selection turned nothing on, a merge counts what was already
|
|
2829
|
+
// on, and a pack with nothing on — or nothing to turn on, a pack of Jev
|
|
2830
|
+
// checks alone — gets a sentence that says so instead of "Turned on 0".
|
|
2831
|
+
const headline =
|
|
2832
|
+
result.available.length === 0
|
|
2833
|
+
? `Installed ${ref}.`
|
|
2834
|
+
: result.enabled.length === 0
|
|
2835
|
+
? // "enforces nothing" is only true when the pack brought nothing else:
|
|
2836
|
+
// a pack's Jev checks enforce through the semantic tier with no regex
|
|
2837
|
+
// policy on at all.
|
|
2838
|
+
`Installed ${ref} with no policies on (${why})` +
|
|
2839
|
+
(result.semantic > 0 ? "." : ", so it enforces nothing.")
|
|
2840
|
+
: result.selection === "carried"
|
|
2841
|
+
? `Kept ${policies(result.enabled.length)} on from ${ref}: ${why}.`
|
|
2842
|
+
: result.selection === "added"
|
|
2843
|
+
? `${ref} has ${policies(result.enabled.length)} on: ${why}.`
|
|
2844
|
+
: `Turned on ${policies(result.enabled.length)} from ${ref}: ${why}.`;
|
|
2845
|
+
|
|
2846
|
+
// How many of each category are on, read back from what was just recorded:
|
|
2847
|
+
// the result carries category slugs, not which policy is in which.
|
|
2848
|
+
let perCategory = "";
|
|
2849
|
+
try {
|
|
2850
|
+
const recorded = readInstalledPacks().packs.find((p) => p.id === result.id);
|
|
2851
|
+
const on = new Set(result.enabled);
|
|
2852
|
+
const counts = new Map<string, number>();
|
|
2853
|
+
for (const policy of recorded?.policies ?? []) {
|
|
2854
|
+
if (on.has(policy.name)) counts.set(policy.category, (counts.get(policy.category) ?? 0) + 1);
|
|
2855
|
+
}
|
|
2856
|
+
perCategory = [...counts].map(([category, n]) => `${category.toLowerCase()} ${n}`).join(", ");
|
|
2857
|
+
} catch {
|
|
2858
|
+
// A count that cannot be read is left out, never guessed.
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2861
|
+
// The facts only this outcome has, one line each.
|
|
2862
|
+
const facts: string[] = [];
|
|
2863
|
+
if (result.replaced?.length) {
|
|
2864
|
+
// What was OBSERVED, and then the inference — not the inference stated as
|
|
2865
|
+
// fact. Identical artifact bytes are the only evidence there is, and they
|
|
2866
|
+
// cannot tell a renamed pack from a second pack one repository builds from
|
|
2867
|
+
// the same source. Absorbing is the right default (a publisher renaming a
|
|
2868
|
+
// set must not reset everyone who narrowed it), but the record that goes
|
|
2869
|
+
// away is one the user installed on purpose, so the line says what to do
|
|
2870
|
+
// when the guess was wrong instead of asserting it was right.
|
|
2871
|
+
const many = result.replaced.length > 1;
|
|
2872
|
+
facts.push(
|
|
2873
|
+
`Replaced ${result.replaced.join(", ")}, the same artifact under another name, and kept your selection. ` +
|
|
2874
|
+
`If ${many ? "they are separate packs, re-add them" : "it is a separate pack, re-add it"}.`,
|
|
2857
2875
|
);
|
|
2858
2876
|
}
|
|
2877
|
+
// The pin made visible: re-running the same command later can install
|
|
2878
|
+
// something different, and that should not be a silent surprise.
|
|
2879
|
+
if (result.resolvedFromLatest) facts.push(`Pinned to ${result.source}, the newest release.`);
|
|
2880
|
+
// Counted separately, and without an on/off ratio, because there is none: a
|
|
2881
|
+
// pack's Jev checks arrive whole. Silence here was the shape of the original
|
|
2882
|
+
// bug — the manifest's semantic half was fetched, verified and then never
|
|
2883
|
+
// written to `installed.json`, so the half somebody installed did nothing
|
|
2884
|
+
// and nothing said so.
|
|
2885
|
+
if (result.semantic > 0) facts.push(`${semanticPhrase(result.semantic)}, ${howJevAsksChecks(result)}.`);
|
|
2859
2886
|
// Nothing after this screen says it: the record keeps no unreadable minimum.
|
|
2860
|
-
if (result.minCliVersionNote)
|
|
2887
|
+
if (result.minCliVersionNote) facts.push(result.minCliVersionNote);
|
|
2861
2888
|
// Which of its checks the resolver will leave out beside what is already
|
|
2862
2889
|
// installed (the shared question budget, a reserved or contested name).
|
|
2863
2890
|
// Otherwise said only in the hook log, on the first call that asks Jev.
|
|
2864
2891
|
if (result.semantic > 0) {
|
|
2865
|
-
for (const e of jevCheckWarnings(result.id))
|
|
2892
|
+
for (const e of jevCheckWarnings(result.id)) facts.push(kit.caution(e));
|
|
2866
2893
|
}
|
|
2867
2894
|
|
|
2895
|
+
const lines = [
|
|
2896
|
+
kit.header("Policies"),
|
|
2897
|
+
"",
|
|
2898
|
+
kit.ok(headline),
|
|
2899
|
+
...(perCategory ? [` ${perCategory}`] : []),
|
|
2900
|
+
...facts.map((fact) => ` ${fact}`),
|
|
2901
|
+
];
|
|
2902
|
+
// The source as TYPED, never the manifest's id: the id is self-declared and
|
|
2903
|
+
// can name a repository the pack did not come from.
|
|
2868
2904
|
if (skipped.length > 0) {
|
|
2869
|
-
lines.push(`
|
|
2870
|
-
lines.push("");
|
|
2871
|
-
lines.push(` see all: failproofai policies`);
|
|
2872
|
-
// Naming --policy here as well as the coarser two: it is the flag people
|
|
2873
|
-
// reach for first ("just give me that one"), and it was only ever
|
|
2874
|
-
// suggested on the branch that installed our own pack from disk — so
|
|
2875
|
-
// every third-party pack told you about categories and everything, and
|
|
2876
|
-
// never about taking a single policy.
|
|
2877
|
-
lines.push(` one policy: failproofai policies add ${source} --policy ${skipped[0]}`);
|
|
2878
|
-
if (result.categories.length > 0) {
|
|
2879
|
-
lines.push(` by category: failproofai policies add ${source} --category ${result.categories.slice(0, 3).join(",")}`);
|
|
2880
|
-
}
|
|
2881
|
-
lines.push(` everything: failproofai policies add ${source} --all`);
|
|
2905
|
+
lines.push("", `Turn on the other ${skipped.length} with ${kit.cmd(`failproofai policies add ${source} --all`)}`);
|
|
2882
2906
|
}
|
|
2883
2907
|
return ok(lines);
|
|
2884
2908
|
} catch (err) {
|
|
@@ -3001,20 +3025,15 @@ async function listReleases(source: string): Promise<PackCliResult> {
|
|
|
3001
3025
|
return Number.NEGATIVE_INFINITY;
|
|
3002
3026
|
};
|
|
3003
3027
|
const releases = [...raw].sort((a, b) => when(b) - when(a));
|
|
3028
|
+
const kit = screenKit(opts);
|
|
3004
3029
|
if (releases.length === 0) {
|
|
3005
|
-
return ok(
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
cmd: "failproofai publish",
|
|
3013
|
-
},
|
|
3014
|
-
opts,
|
|
3015
|
-
),
|
|
3016
|
-
),
|
|
3017
|
-
);
|
|
3030
|
+
return ok([
|
|
3031
|
+
kit.header(`${spec.owner}/${spec.repo}`),
|
|
3032
|
+
"",
|
|
3033
|
+
kit.head("Releases", "no releases"),
|
|
3034
|
+
"This repository has published no releases, so there is nothing to install.",
|
|
3035
|
+
` Its author publishes one with: ${kit.cmd("failproofai publish")}`,
|
|
3036
|
+
]);
|
|
3018
3037
|
}
|
|
3019
3038
|
|
|
3020
3039
|
// Which of them is on THIS machine — the question somebody runs this to
|
|
@@ -3073,26 +3092,22 @@ async function listReleases(source: string): Promise<PackCliResult> {
|
|
|
3073
3092
|
flags,
|
|
3074
3093
|
]);
|
|
3075
3094
|
}
|
|
3076
|
-
return ok(
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
opts,
|
|
3093
|
-
),
|
|
3094
|
-
),
|
|
3095
|
-
);
|
|
3095
|
+
return ok([
|
|
3096
|
+
kit.header(`${spec.owner}/${spec.repo}`),
|
|
3097
|
+
"",
|
|
3098
|
+
// The id stays in the header: `head` uppercases, and an id is case-sensitive.
|
|
3099
|
+
kit.head("Releases", `${rows.length} release${rows.length === 1 ? "" : "s"}`),
|
|
3100
|
+
// Columns, so it stays a table: the kit's rows are two-column.
|
|
3101
|
+
...table({ head: ["version", "published", "commit", "policies", "default", ""], rows }, opts),
|
|
3102
|
+
// `—` is load-bearing: it means "this release did not say", which is what
|
|
3103
|
+
// a release published before this format did, and what anybody else's
|
|
3104
|
+
// hand-made release does. Filling those in would cost a manifest download
|
|
3105
|
+
// each, and a listing that silently costs a hundred downloads is worse than
|
|
3106
|
+
// one with gaps in it.
|
|
3107
|
+
` ${paint(opts.color).ink3("— means the release did not record it.")}`,
|
|
3108
|
+
"",
|
|
3109
|
+
`Install a particular one with: ${kit.cmd(`failproofai policies add ${spec.owner}/${spec.repo}@${newest ?? "<tag>"}`)}`,
|
|
3110
|
+
]);
|
|
3096
3111
|
}
|
|
3097
3112
|
|
|
3098
3113
|
/** `2 hours ago`, `6 days ago`. Coarse on purpose — the question is "how stale",
|
|
@@ -3237,10 +3252,7 @@ export function jevChecksSection(
|
|
|
3237
3252
|
return [
|
|
3238
3253
|
// The count is on the heading rather than in a row, the way every other
|
|
3239
3254
|
// section on this screen carries its own total.
|
|
3240
|
-
|
|
3241
|
-
`Jev checks — ${pack.semantic.length} · not selectable · only where Jev is configured`,
|
|
3242
|
-
opts,
|
|
3243
|
-
),
|
|
3255
|
+
screenKit(opts).head("Jev checks", `${pack.semantic.length} · not selectable · only where Jev is configured`),
|
|
3244
3256
|
// The reviewers column is the only one allowed to shrink: a mode or a check
|
|
3245
3257
|
// name cut in half is a fact nobody can act on, while a cut reviewer list is
|
|
3246
3258
|
// one that was already abbreviated.
|
|
@@ -3274,52 +3286,55 @@ async function listRemote(source: string): Promise<PackCliResult> {
|
|
|
3274
3286
|
return fail([`Could not read ${source}: ${err instanceof Error ? err.message : String(err)}`]);
|
|
3275
3287
|
}
|
|
3276
3288
|
|
|
3277
|
-
const
|
|
3289
|
+
const kit = screenKit({ ...opts, fit: Boolean(process.stdout.isTTY) });
|
|
3290
|
+
const count = (n: number, one: string, many: string): string => `${n} ${n === 1 ? one : many}`;
|
|
3278
3291
|
const categories = [...new Set(preview.policies.map((p) => p.category))];
|
|
3279
|
-
const rows: Array<string[] | { section: string }> = [];
|
|
3280
|
-
for (const category of categories) {
|
|
3281
|
-
const inCategory = preview.policies.filter((p) => p.category === category);
|
|
3282
|
-
const on = inCategory.filter((p) => p.defaultEnabled).length;
|
|
3283
|
-
rows.push({
|
|
3284
|
-
section: `${category} — ${on}/${inCategory.length} on by default · ${slugifyCategory(category)}`,
|
|
3285
|
-
});
|
|
3286
|
-
for (const policy of inCategory) {
|
|
3287
|
-
// The publisher's DEFAULTS, not a machine's state — this pack is not
|
|
3288
|
-
// installed, so a row claiming ON would be describing nothing.
|
|
3289
|
-
rows.push([
|
|
3290
|
-
policy.defaultEnabled ? "default" : "opt-in",
|
|
3291
|
-
policy.name,
|
|
3292
|
-
policy.description,
|
|
3293
|
-
]);
|
|
3294
|
-
}
|
|
3295
|
-
}
|
|
3296
3292
|
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3293
|
+
// The PUBLISHER is the account the release was actually fetched from — the
|
|
3294
|
+
// owner in `github:<owner>/<repo>@<tag>` — never the id's owner segment,
|
|
3295
|
+
// which is whatever the manifest claims. No release date: knowing one would
|
|
3296
|
+
// take a GitHub API call this path does not make (decision D16).
|
|
3297
|
+
const kvRows: Array<[string, string]> = [["publisher", preview.source.replace(/^github:/i, "").split("/")[0]]];
|
|
3298
|
+
// Optional by design: a pack published from outside a git checkout has none.
|
|
3299
|
+
if (preview.commit) kvRows.push(["commit", preview.commit]);
|
|
3300
|
+
kvRows.push([
|
|
3301
|
+
"policies",
|
|
3302
|
+
preview.policies.length === 0
|
|
3303
|
+
? "none"
|
|
3304
|
+
: `${preview.policies.length} in ${count(categories.length, "category", "categories")} ${kit.selected} on by default`,
|
|
3305
|
+
]);
|
|
3306
|
+
if (preview.effect === "observe") kvRows.push(["effect", "observe, blocks nothing"]);
|
|
3307
|
+
if (preview.minCliVersion) kvRows.push(["requires", `failproofai ${preview.minCliVersion} or newer`]);
|
|
3308
|
+
if (preview.minCliVersionNote) kvRows.push(["requires", preview.minCliVersionNote]);
|
|
3309
|
+
if (preview.semantic.length > 0) kvRows.push(["jev checks", String(preview.semantic.length)]);
|
|
3310
|
+
|
|
3311
|
+
const lines = [kit.header(`${preview.id}@${preview.version}`), "", ...kit.kv(kvRows)];
|
|
3312
|
+
// ■ is the publisher's DEFAULT, not a machine's state: this pack is not
|
|
3313
|
+
// installed, so a row claiming ● on would be describing nothing.
|
|
3314
|
+
const column = Math.max(24, ...preview.policies.map((p) => p.name.length + 4));
|
|
3315
|
+
for (const category of categories) {
|
|
3316
|
+
lines.push(
|
|
3317
|
+
"",
|
|
3318
|
+
kit.head(category),
|
|
3319
|
+
...kit.rows(
|
|
3320
|
+
preview.policies
|
|
3321
|
+
.filter((p) => p.category === category)
|
|
3322
|
+
.map((p): [string, string] => [`${p.defaultEnabled ? kit.selected : kit.unselected} ${p.name}`, p.description]),
|
|
3323
|
+
column,
|
|
3309
3324
|
),
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
);
|
|
3325
|
+
);
|
|
3326
|
+
}
|
|
3327
|
+
// The half the rows above cannot hold: its own section, under the policies
|
|
3328
|
+
// rather than above them, because a check is read against the policies it can
|
|
3329
|
+
// clear and those are the rows just passed.
|
|
3330
|
+
const jev = jevChecksSection(preview, opts);
|
|
3331
|
+
if (jev) lines.push("", ...jev);
|
|
3332
|
+
if (preview.semantic.length > 0) {
|
|
3333
|
+
const warnings = jevCheckWarnings(preview.id, preview);
|
|
3334
|
+
if (warnings.length > 0) lines.push("", ...warnings.map((e) => kit.caution(e)));
|
|
3335
|
+
}
|
|
3336
|
+
lines.push("", `Install with ${kit.cmd(`failproofai policies add ${source}`)}`);
|
|
3337
|
+
return ok(lines);
|
|
3323
3338
|
}
|
|
3324
3339
|
|
|
3325
3340
|
async function list(): Promise<PackCliResult> {
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The body of an action report (`update`, `migrate`, `flush`, `connect`, …),
|
|
3
|
+
* laid out before colour: which line carries the failure's ✕, and how a
|
|
4
|
+
* wrapped line continues. bin/failproofai.mjs's `printReport` paints it.
|
|
5
|
+
*
|
|
6
|
+
* Kept apart from `tui.ts` so it can be tested without driving the binary.
|
|
7
|
+
*/
|
|
8
|
+
import { wrap } from "./tui";
|
|
9
|
+
|
|
10
|
+
/** A line that opens on a state glyph says its own state. */
|
|
11
|
+
const STATE_GLYPH = /^\s*[✓▲✕] /;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Lay out `lines` for a report `width` columns wide.
|
|
15
|
+
*
|
|
16
|
+
* A failed run whose lines carry no state glyph of their own opens with ✕ on
|
|
17
|
+
* the first top-level line, and the top-level lines after it are the fix,
|
|
18
|
+
* indented under it. That guess is only right when the failure comes first.
|
|
19
|
+
* A report that marks its own lines — `update` opening on "no migration was
|
|
20
|
+
* needed" before a daemon's ✕, `migrate` listing its backup before the step
|
|
21
|
+
* that failed — gets no guess at all: a ✕ beside the line that succeeded
|
|
22
|
+
* reads as that step failing, and the real error indented beneath it reads as
|
|
23
|
+
* the remedy.
|
|
24
|
+
*
|
|
25
|
+
* Lines that already carry their own leading space are passed through: those
|
|
26
|
+
* are sub-items a module laid out on purpose.
|
|
27
|
+
*/
|
|
28
|
+
export function reportBody(lines: readonly string[], opts: { ok: boolean; width: number }): string[] {
|
|
29
|
+
const autoLead = !opts.ok && !lines.some((line) => STATE_GLYPH.test(line));
|
|
30
|
+
const width = Math.max(20, opts.width);
|
|
31
|
+
const body: string[] = [];
|
|
32
|
+
let first = true;
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
if (line.trim() === "") {
|
|
35
|
+
body.push("");
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (line.startsWith(" ")) {
|
|
39
|
+
body.push(line);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const glyphed = STATE_GLYPH.test(line);
|
|
43
|
+
const lead = autoLead ? (first ? "✕ " : " ") : "";
|
|
44
|
+
// A glyphed line's continuation sits under its words, not under the glyph.
|
|
45
|
+
const hang = lead || glyphed ? " " : "";
|
|
46
|
+
wrap(line, width - lead.length).forEach((w, i) => body.push(i === 0 ? `${lead}${w}` : `${hang}${w}`));
|
|
47
|
+
first = false;
|
|
48
|
+
}
|
|
49
|
+
return body;
|
|
50
|
+
}
|