failproofai 1.0.3 → 1.0.4-beta.2
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 +5 -5
- package/.next/standalone/.next/prerender-manifest.json +5 -5
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- 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 +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 +2 -2
- 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 +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route_client-reference-manifest.js +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/run/route_client-reference-manifest.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/audit/status/route_client-reference-manifest.js +1 -1
- 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-request/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route_client-reference-manifest.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/api/download/[project]/[session]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +37 -4
- package/.next/standalone/.next/server/app/audit/page.js +2 -2
- 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.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +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/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- 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 +2 -2
- 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/build-manifest.json +2 -2
- 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/build-manifest.json +2 -2
- 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/app/settings/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
- 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]__0-9ti7z._.js → [externals]__1lh7m5d._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__0u3wrvq._.js → [externals]__1rqkg_y._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adacul._.js +1 -1
- package/.next/standalone/.next/server/chunks/{_1-akg6w._.js → _08w6xzm._.js} +2 -2
- 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 +4 -4
- 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_01r25oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rgu2r3._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0-oij9d._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0l2hi_d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0oq1dh6._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +47 -13
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -69
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_rerun-button_tsx_0blihgw._.js +3 -0
- 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_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_13n822a._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
- 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 +5 -5
- 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 +54 -21
- package/.next/standalone/.next/static/chunks/010bv1w6j171t.js +1 -0
- package/.next/standalone/.next/static/chunks/04r6ch8uf_n8m.js +1 -0
- package/.next/standalone/.next/static/chunks/{29-iqnp9v_axt.css → 0o-hh5_turzlz.css} +1 -1
- package/.next/standalone/.next/static/chunks/{40nr6ehj4p3cw.css → 0qmsunv04x4na.css} +1 -1
- package/.next/standalone/.next/static/chunks/{0ollg-nnu3t3e.js → 0wz8yftk18ts2.js} +1 -1
- package/.next/standalone/.next/static/chunks/0zebh1n9jkfbt.js +1 -0
- package/.next/standalone/.next/static/chunks/1eyl7fzkmnkf_.js +1 -0
- package/.next/standalone/.next/static/chunks/1pb1oztsbwcss.js +1 -0
- package/.next/standalone/.next/static/chunks/{1-_zkmnm-jwei.js → 2aquitk72k2op.js} +1 -1
- package/.next/standalone/.next/static/chunks/2bi_1y0a_smt7.js +6 -0
- package/.next/standalone/.next/static/chunks/{42yfkhekx440s.js → 2ej3b8gk5ittu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{354-n7p7labpn.js → 2zafgs90r_leq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2xm5mj1d21b4n.js → 32spub4wqjem-.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1a6u7l3giejch.js → 3m4upvybtrexd.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2k9f4tyv04809.css → 3uyhmm01g64k4.css} +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-2x-o099q64i8h.js → turbopack-3s3c-u_u_l0u9.js} +1 -1
- package/.next/standalone/.opencode/plugins/failproofai.mjs +51 -27
- package/.next/standalone/app/actions/get-leaks.ts +100 -0
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +112 -33
- package/.next/standalone/app/audit/_components/audit-poster.tsx +29 -10
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +6 -1
- package/.next/standalone/app/audit/_components/empty-state.tsx +4 -1
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +19 -5
- package/.next/standalone/app/audit/_components/leak-section.tsx +179 -0
- package/.next/standalone/app/audit/_components/share-templates.ts +110 -44
- package/.next/standalone/app/audit/audit-styles.css +114 -1
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +26 -3
- package/.next/standalone/fp-cloud-cli/fp_cli/_click_compat.py +31 -8
- package/.next/standalone/fp-cloud-cli/fp_cli/permissions.py +1 -0
- package/.next/standalone/fp-cloud-cli/pyproject.toml +9 -2
- package/.next/standalone/fp-cloud-cli/tests/test_click_compat.py +54 -0
- package/.next/standalone/fp-cloud-cli/uv.lock +9 -12
- package/.next/standalone/lib/auth/api-server-client.ts +28 -0
- package/.next/standalone/lib/claude-sessions.ts +101 -27
- 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/next-server/app-page-turbo-experimental.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-route-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +5 -5
- package/.next/standalone/node_modules/next/dist/experimental/testmode/fetch.js +10 -2
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/lib/typescript/runTypeScriptCli.js +2 -2
- package/.next/standalone/node_modules/next/dist/lib/verify-typescript-setup.js +3 -1
- 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/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js +17 -4
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/shared/lib/router/utils/escape-path-delimiters.js +1 -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 +11 -11
- package/.next/standalone/package.json +14 -13
- package/.next/standalone/sdk/python/CHANGELOG.md +155 -0
- package/.next/standalone/sdk/python/README.md +8 -0
- package/.next/standalone/sdk/python/examples/evaluator_worker.py +121 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__init__.py +101 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__main__.py +49 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/_sandbox_runner.py +63 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/authoring.py +404 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/client.py +299 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/protocol.py +754 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/runtime.py +936 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/source.py +684 -0
- package/.next/standalone/sdk/python/tests/fixtures/evaluator_v2/README.md +28 -0
- package/.next/standalone/sdk/python/tests/fixtures/evaluator_v2/contract.json +252 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_authoring.py +124 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_client.py +253 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_example.py +35 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_http_e2e.py +636 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_main.py +47 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_protocol.py +246 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_review_fixes.py +164 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_runtime.py +1103 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_source.py +430 -0
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +17 -0
- package/.next/standalone/sdk/python/uv.lock +29 -29
- package/.next/standalone/server.js +1 -1
- package/README.md +13 -58
- package/dist/cli.mjs +5368 -8756
- package/dist/worker.mjs +539 -312
- package/lib/auth/api-server-client.ts +28 -0
- package/lib/claude-sessions.ts +101 -27
- package/package.json +14 -13
- package/pi-extension/index.ts +42 -4
- package/scripts/changelog-open.py +115 -0
- package/src/audit/cli.ts +134 -0
- package/src/audit/desktop-notify.ts +420 -0
- package/src/audit/harm-report.ts +101 -0
- package/src/audit/index.ts +141 -13
- package/src/audit/leak-fingerprint.ts +200 -0
- package/src/audit/leak-notice.ts +161 -0
- package/src/audit/leak-record.ts +232 -0
- package/src/audit/leak-scan.ts +292 -0
- package/src/audit/leak-store.ts +217 -0
- package/src/audit/macos-notifier.ts +310 -0
- package/src/audit/redact-example.ts +266 -14
- package/src/audit/report-harm.ts +12 -1
- package/src/audit/report.ts +6 -3
- package/src/audit/schedule-cli.ts +37 -0
- package/src/audit/scoring.ts +49 -0
- package/src/audit/types.ts +41 -0
- package/src/hooks/builtin-policies.ts +67 -2
- package/src/hooks/configure-wizard.ts +20 -0
- package/src/hooks/fp-config.ts +71 -11
- package/src/hooks/fp-home.ts +27 -0
- package/src/hooks/handler.ts +59 -1
- package/src/hooks/integrations.ts +47 -13
- package/src/hooks/notice.ts +155 -0
- package/src/hooks/uninstall-cli.ts +15 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1b5jzxr._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0j6gd_k._.js +0 -23
- package/.next/standalone/.next/server/chunks/ssr/_0v8eebd._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1ylae7o._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +0 -3
- package/.next/standalone/.next/static/chunks/03slu0c8_71y7.js +0 -1
- package/.next/standalone/.next/static/chunks/0nm11ysn0153h.js +0 -1
- package/.next/standalone/.next/static/chunks/0u64yey446k4f.css +0 -1
- package/.next/standalone/.next/static/chunks/1r9676mkvihto.js +0 -1
- package/.next/standalone/.next/static/chunks/30pct5s734jua.js +0 -6
- package/.next/standalone/.next/static/chunks/3pibxnbhjza7n.js +0 -69
- package/.next/standalone/.next/static/chunks/3qfoeqhy5l10x.js +0 -1
- package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +0 -1
- package/.next/standalone/.next/static/chunks/41b5ptaocvi_l.js +0 -1
- /package/.next/standalone/.next/static/{JBYgkXkA1PS48m9P_hKNw → aKNv4Kmv98Xpwns0Xa-C-}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{JBYgkXkA1PS48m9P_hKNw → aKNv4Kmv98Xpwns0Xa-C-}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{JBYgkXkA1PS48m9P_hKNw → aKNv4Kmv98Xpwns0Xa-C-}/_ssgManifest.js +0 -0
|
@@ -7,20 +7,31 @@
|
|
|
7
7
|
* appends a clipboard paste hint. Pure — no React, no DOM — so it's
|
|
8
8
|
* unit-testable and shared by the client poster component.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* ## The score is switched off (2026-09-07)
|
|
11
|
+
*
|
|
12
|
+
* Every template but one used to interpolate `${score}/100`. The score is
|
|
13
|
+
* commented out across the audit — see the header of `src/audit/scoring.ts` for
|
|
14
|
+
* why — so the copy is archetype-only. Eighteen templates lost a subordinate
|
|
15
|
+
* clause; two whose entire premise WAS the number ("my agent scored X/100,
|
|
16
|
+
* think yours can beat it?") are commented out in place rather than reworded,
|
|
17
|
+
* because there is nothing left of them once the number goes.
|
|
18
|
+
*
|
|
19
|
+
* `ShareCtx.score` is kept and still populated so restoring is re-adding the
|
|
20
|
+
* clause, not re-plumbing the type. The originals are preserved verbatim in the
|
|
21
|
+
* block at the bottom of this file.
|
|
14
22
|
*/
|
|
15
23
|
import type { Grade } from "@/src/audit/scoring";
|
|
16
24
|
|
|
17
25
|
export interface ShareCtx {
|
|
18
|
-
score: number;
|
|
19
26
|
/** Lowercased archetype name, e.g. "the cowboy". */
|
|
20
27
|
arch: string;
|
|
21
|
-
grade: Grade;
|
|
22
28
|
/** Count of unenabled prescribed policies. */
|
|
23
29
|
missing: number;
|
|
30
|
+
/** Optional ONLY because the score is switched off and nothing upstream
|
|
31
|
+
* computes them any more. Restoring the score means making these required
|
|
32
|
+
* again — which the compiler will then walk you through. */
|
|
33
|
+
score?: number;
|
|
34
|
+
grade?: Grade;
|
|
24
35
|
}
|
|
25
36
|
|
|
26
37
|
/** Call-to-action + handle per channel. No URL by design (see file header). */
|
|
@@ -33,52 +44,107 @@ const PASTE_LINE = "[ audit card copied to your clipboard — paste it into the
|
|
|
33
44
|
|
|
34
45
|
/** Short, curiosity-forward — for X / Twitter. Ends on the npx CTA + @failproofai. */
|
|
35
46
|
export const X_TEMPLATES: ((c: ShareCtx) => string)[] = [
|
|
36
|
-
({
|
|
37
|
-
`my agent has a personality and it's ${arch}. did not see that coming.\n\nran a failproof audit,
|
|
38
|
-
({
|
|
39
|
-
`spent 30 seconds auditing my agent. learned more about it than i did all month.\n\nit's ${arch}.
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
({ arch }) =>
|
|
48
|
+
`my agent has a personality and it's ${arch}. did not see that coming.\n\nran a failproof audit, all local. find out what yours is → ${X_CTA}`,
|
|
49
|
+
({ arch }) =>
|
|
50
|
+
`spent 30 seconds auditing my agent. learned more about it than i did all month.\n\nit's ${arch}. → ${X_CTA}`,
|
|
51
|
+
// Score-spined — nothing survives removing the number:
|
|
52
|
+
// ({ score }) =>
|
|
53
|
+
// `my agent scored ${score}/100. think yours can beat it?\n\n30 sec audit, runs locally, gives you a personality too → ${X_CTA}`,
|
|
42
54
|
({ arch }) =>
|
|
43
55
|
`turns out my agent is ${arch} and honestly it explains everything.\n\n→ ${X_CTA}`,
|
|
44
|
-
({
|
|
45
|
-
`ran a failproof audit on my agent. it reads how it actually behaves when things break, not just the happy path.\n\npersonality: ${arch}.
|
|
46
|
-
({
|
|
47
|
-
`got to know my agent today. it's ${arch}
|
|
48
|
-
({
|
|
49
|
-
`your agent has a personality. you just haven't met it.\n\ni met mine today: ${arch}
|
|
50
|
-
({
|
|
51
|
-
`everyone talks about what their agent can build. nobody talks about how it acts when it breaks.\n\nmine's ${arch},
|
|
52
|
-
({
|
|
53
|
-
`every agent builder should run this once.\n\n30 sec, local, gives your agent a personality
|
|
54
|
-
({
|
|
55
|
-
`i'll go first: ${arch}
|
|
56
|
+
({ arch }) =>
|
|
57
|
+
`ran a failproof audit on my agent. it reads how it actually behaves when things break, not just the happy path.\n\npersonality: ${arch}. all local → ${X_CTA}`,
|
|
58
|
+
({ arch }) =>
|
|
59
|
+
`got to know my agent today. it's ${arch}. wow.\n\naudit yours in 30s, nothing leaves your machine → ${X_CTA}`,
|
|
60
|
+
({ arch }) =>
|
|
61
|
+
`your agent has a personality. you just haven't met it.\n\ni met mine today: ${arch}. → ${X_CTA}`,
|
|
62
|
+
({ arch }) =>
|
|
63
|
+
`everyone talks about what their agent can build. nobody talks about how it acts when it breaks.\n\nmine's ${arch}, all local → ${X_CTA}`,
|
|
64
|
+
({ arch }) =>
|
|
65
|
+
`every agent builder should run this once.\n\n30 sec, local, gives your agent a personality. mine: ${arch}.\n\n${X_CTA}`,
|
|
66
|
+
({ arch }) =>
|
|
67
|
+
`i'll go first: ${arch}.\n\nwhat's your agent? 30 sec audit, no signup → ${X_CTA}`,
|
|
56
68
|
];
|
|
57
69
|
|
|
58
70
|
/** Longer, reflective — for LinkedIn. Ends on the npx CTA + @Failproof AI. */
|
|
59
71
|
export const LI_TEMPLATES: ((c: ShareCtx) => string)[] = [
|
|
60
|
-
({
|
|
61
|
-
`I've spent more hours with my agent this month than with most people I know. Today I realized I couldn't tell you a single thing about how it actually behaves.\n\nSo I audited it. Turns out it's ${arch}
|
|
62
|
-
({
|
|
63
|
-
`Took a personality test today. It wasn't for me — it was for my AI agent.\n\nThe result: ${arch}
|
|
64
|
-
({
|
|
65
|
-
`Everyone asks what their AI agent can build. I just found out mine has a temper.\n\nAfter watching how it reacts to a failed command, the audit called it ${arch}
|
|
66
|
-
({
|
|
67
|
-
`My agent does this very specific thing every time a command fails. Today I learned there's basically a name for it.\n\nRan a quick audit and it came back ${arch}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
({ arch }) =>
|
|
73
|
+
`I've spent more hours with my agent this month than with most people I know. Today I realized I couldn't tell you a single thing about how it actually behaves.\n\nSo I audited it. Turns out it's ${arch}.\n\nThe audit reads its real history, including how it handles failures, not just the clean runs. 30 seconds, runs entirely locally.\n\nMeet yours: ${LI_CTA}`,
|
|
74
|
+
({ arch }) =>
|
|
75
|
+
`Took a personality test today. It wasn't for me — it was for my AI agent.\n\nThe result: ${arch}.\n\nIt works by reading the agent's actual run history, so the personality comes from how it really behaves, not a vibe. Took 30 seconds and stayed local.\n\nTry it on yours: ${LI_CTA}`,
|
|
76
|
+
({ arch }) =>
|
|
77
|
+
`Everyone asks what their AI agent can build. I just found out mine has a temper.\n\nAfter watching how it reacts to a failed command, the audit called it ${arch}.\n\nOddly useful to see it written down. 30 seconds, all local: ${LI_CTA}`,
|
|
78
|
+
({ arch }) =>
|
|
79
|
+
`My agent does this very specific thing every time a command fails. Today I learned there's basically a name for it.\n\nRan a quick audit and it came back ${arch}. The whole read is based on how the agent handles things going wrong, which is where its real character shows.\n\n30 seconds, nothing leaves your machine: ${LI_CTA}`,
|
|
80
|
+
// Score-spined — the opening line is the number:
|
|
81
|
+
// ({ score, arch }) =>
|
|
82
|
+
// `My AI agent scored ${score}/100 today. I didn't know you could even measure that.\n\nThe same audit also handed it a personality: ${arch}.\n\nIt reads the agent's real history and tells you where it's solid and where it slips. Took 30 seconds and ran fully locally: ${LI_CTA}`,
|
|
83
|
+
({ arch }) =>
|
|
84
|
+
`I'm usually the first to scroll past "audit your X" tools. This one took 30 seconds and actually told me something.\n\nMy agent is ${arch}.\n\nIt reads the agent's real run history rather than asking me anything, and none of it leaves the machine: ${LI_CTA}`,
|
|
85
|
+
({ arch }) =>
|
|
86
|
+
`What is your agent's personality? I realized today that I had no answer.\n\nSo I checked. Mine is ${arch}, with a clear read on where it shines and where it slips.\n\nIf you work with agents, run it and drop yours in the comments. 30 seconds, fully local: ${LI_CTA}`,
|
|
87
|
+
({ arch }) =>
|
|
88
|
+
`I trusted my agent a little less after this morning, and quite a bit more by the afternoon.\n\nI ran an audit on it. It showed me exactly where it's reliable and where it isn't, and gave it a personality: ${arch}.\n\nKnowing the gaps is what made me trust it more. 30 seconds, all local: ${LI_CTA}`,
|
|
89
|
+
({ arch }) =>
|
|
90
|
+
`I almost skipped this because I assumed it would quietly ship my code off somewhere. It doesn't. Everything runs locally.\n\n30 seconds later I had my agent's personality: ${arch}.\n\nIf privacy is usually what stops you from trying these, this one is different: ${LI_CTA}`,
|
|
91
|
+
({ arch }) =>
|
|
92
|
+
`Found out my AI agent has a personality type. Found out it's ${arch}. Found out that explains a lot.\n\nThe audit reads how the agent handles failures, not just the runs where everything goes fine.\n\n30 seconds, runs locally: ${LI_CTA}`,
|
|
80
93
|
];
|
|
81
94
|
|
|
95
|
+
/* ---------------------------------------------------------------------------
|
|
96
|
+
* THE ORIGINAL SCORE-BEARING COPY, verbatim. To restore: put these two arrays
|
|
97
|
+
* back in place of the two above, and re-enable the score at its source (see
|
|
98
|
+
* `src/audit/scoring.ts`). Nothing else has to change — `ShareCtx` is unchanged
|
|
99
|
+
* and `score` is still populated by `audit-poster.tsx`.
|
|
100
|
+
*
|
|
101
|
+
* export const X_TEMPLATES: ((c: ShareCtx) => string)[] = [
|
|
102
|
+
* ({ score, arch }) =>
|
|
103
|
+
* `my agent has a personality and it's ${arch}. did not see that coming.\n\nran a failproof audit, scored ${score}/100, all local. find out what yours is → ${X_CTA}`,
|
|
104
|
+
* ({ score, arch }) =>
|
|
105
|
+
* `spent 30 seconds auditing my agent. learned more about it than i did all month.\n\nit's ${arch}. scored ${score}/100. → ${X_CTA}`,
|
|
106
|
+
* ({ score }) =>
|
|
107
|
+
* `my agent scored ${score}/100. think yours can beat it?\n\n30 sec audit, runs locally, gives you a personality too → ${X_CTA}`,
|
|
108
|
+
* ({ arch }) =>
|
|
109
|
+
* `turns out my agent is ${arch} and honestly it explains everything.\n\n→ ${X_CTA}`,
|
|
110
|
+
* ({ score, arch }) =>
|
|
111
|
+
* `ran a failproof audit on my agent. it reads how it actually behaves when things break, not just the happy path.\n\npersonality: ${arch}. score: ${score}/100. all local → ${X_CTA}`,
|
|
112
|
+
* ({ score, arch }) =>
|
|
113
|
+
* `got to know my agent today. it's ${arch} and scored ${score}/100. wow.\n\naudit yours in 30s, nothing leaves your machine → ${X_CTA}`,
|
|
114
|
+
* ({ score, arch }) =>
|
|
115
|
+
* `your agent has a personality. you just haven't met it.\n\ni met mine today: ${arch}, ${score}/100. → ${X_CTA}`,
|
|
116
|
+
* ({ score, arch }) =>
|
|
117
|
+
* `everyone talks about what their agent can build. nobody talks about how it acts when it breaks.\n\nmine's ${arch}, scored ${score}/100, all local → ${X_CTA}`,
|
|
118
|
+
* ({ score, arch }) =>
|
|
119
|
+
* `every agent builder should run this once.\n\n30 sec, local, gives your agent a personality and a quality score. mine: ${arch}, ${score}/100.\n\n${X_CTA}`,
|
|
120
|
+
* ({ score, arch }) =>
|
|
121
|
+
* `i'll go first: ${arch}, ${score}/100.\n\nwhat's your agent? 30 sec audit, no signup → ${X_CTA}`,
|
|
122
|
+
* ];
|
|
123
|
+
*
|
|
124
|
+
* export const LI_TEMPLATES: ((c: ShareCtx) => string)[] = [
|
|
125
|
+
* ({ score, arch }) =>
|
|
126
|
+
* `I've spent more hours with my agent this month than with most people I know. Today I realized I couldn't tell you a single thing about how it actually behaves.\n\nSo I audited it. Turns out it's ${arch}, and it scored ${score}/100.\n\nThe audit reads its real history, including how it handles failures, not just the clean runs. 30 seconds, runs entirely locally.\n\nMeet yours: ${LI_CTA}`,
|
|
127
|
+
* ({ score, arch }) =>
|
|
128
|
+
* `Took a personality test today. It wasn't for me — it was for my AI agent.\n\nThe result: ${arch}, with a quality score of ${score}/100.\n\nIt works by reading the agent's actual run history, so the personality comes from how it really behaves, not a vibe. Took 30 seconds and stayed local.\n\nTry it on yours: ${LI_CTA}`,
|
|
129
|
+
* ({ score, arch }) =>
|
|
130
|
+
* `Everyone asks what their AI agent can build. I just found out mine has a temper.\n\nAfter watching how it reacts to a failed command, the audit called it ${arch}. It also scored its quality at ${score}/100.\n\nOddly useful to see it written down. 30 seconds, all local: ${LI_CTA}`,
|
|
131
|
+
* ({ score, arch }) =>
|
|
132
|
+
* `My agent does this very specific thing every time a command fails. Today I learned there's basically a name for it.\n\nRan a quick audit and it came back ${arch}, scored ${score}/100. The whole read is based on how the agent handles things going wrong, which is where its real character shows.\n\n30 seconds, nothing leaves your machine: ${LI_CTA}`,
|
|
133
|
+
* ({ score, arch }) =>
|
|
134
|
+
* `My AI agent scored ${score}/100 today. I didn't know you could even measure that.\n\nThe same audit also handed it a personality: ${arch}.\n\nIt reads the agent's real history and tells you where it's solid and where it slips. Took 30 seconds and ran fully locally: ${LI_CTA}`,
|
|
135
|
+
* ({ score, arch }) =>
|
|
136
|
+
* `I'm usually the first to scroll past "audit your X" tools. This one took 30 seconds and actually told me something.\n\nMy agent is ${arch}, and it scored ${score}/100.\n\nIt reads the agent's real run history rather than asking me anything, and none of it leaves the machine: ${LI_CTA}`,
|
|
137
|
+
* ({ score, arch }) =>
|
|
138
|
+
* `What is your agent's personality? I realized today that I had no answer.\n\nSo I checked. Mine is ${arch}, scored ${score}/100, with a clear read on where it shines and where it slips.\n\nIf you work with agents, run it and drop yours in the comments. 30 seconds, fully local: ${LI_CTA}`,
|
|
139
|
+
* ({ score, arch }) =>
|
|
140
|
+
* `I trusted my agent a little less after this morning, and quite a bit more by the afternoon.\n\nI ran an audit on it. It showed me exactly where it's reliable and where it isn't, gave it a personality (${arch}), and scored it ${score}/100.\n\nKnowing the gaps is what made me trust it more. 30 seconds, all local: ${LI_CTA}`,
|
|
141
|
+
* ({ score, arch }) =>
|
|
142
|
+
* `I almost skipped this because I assumed it would quietly ship my code off somewhere. It doesn't. Everything runs locally.\n\n30 seconds later I had my agent's personality (${arch}) and a quality score (${score}/100).\n\nIf privacy is usually what stops you from trying these, this one is different: ${LI_CTA}`,
|
|
143
|
+
* ({ score, arch }) =>
|
|
144
|
+
* `Found out my AI agent has a personality type. Found out it's ${arch}. Found out that explains a lot.\n\nIt scored ${score}/100 too. The audit reads how the agent handles failures, not just the runs where everything goes fine.\n\n30 seconds, runs locally: ${LI_CTA}`,
|
|
145
|
+
* ];
|
|
146
|
+
* ------------------------------------------------------------------------- */
|
|
147
|
+
|
|
82
148
|
/** djb2 hash — stable per seed so the template choice is deterministic. */
|
|
83
149
|
function hashStr(s: string): number {
|
|
84
150
|
let h = 5381;
|
|
@@ -496,7 +496,13 @@
|
|
|
496
496
|
.poster-meta .of { color: var(--dim); }
|
|
497
497
|
.poster-meta .poster-sep { color: var(--dim); }
|
|
498
498
|
|
|
499
|
-
/* body — vertical centered stack: sigil → persona → score ───
|
|
499
|
+
/* body — vertical centered stack: sigil → persona → score ───
|
|
500
|
+
The score block is switched off (see `src/audit/scoring.ts`), so this stack
|
|
501
|
+
currently renders two children, not three. It is a centered flex column with
|
|
502
|
+
a gap and no fixed track count, so it re-centers on its own. The
|
|
503
|
+
`.poster-score` rules below are kept, dormant, against the score coming
|
|
504
|
+
back — do not tidy them away, or restoring it means rewriting the styles
|
|
505
|
+
too. */
|
|
500
506
|
.poster-body {
|
|
501
507
|
display: flex;
|
|
502
508
|
flex-direction: column;
|
|
@@ -555,6 +561,7 @@
|
|
|
555
561
|
.poster-persona .persona-rarity .pct { color: var(--accent-pink); font-weight: 600; }
|
|
556
562
|
|
|
557
563
|
/* score — score-n + /100, baseline-aligned and centered in the card. */
|
|
564
|
+
/* Dormant while the score is switched off — see `src/audit/scoring.ts`. */
|
|
558
565
|
.poster-score {
|
|
559
566
|
display: flex;
|
|
560
567
|
align-items: baseline;
|
|
@@ -1157,3 +1164,109 @@
|
|
|
1157
1164
|
.share-card {
|
|
1158
1165
|
max-width: 420px;
|
|
1159
1166
|
}
|
|
1167
|
+
|
|
1168
|
+
/* ── Leak report ─────────────────────────────────────────────────────────────
|
|
1169
|
+
One block per distinct credential. Deliberately NOT a table: a table implies
|
|
1170
|
+
columns worth scanning down, and the interesting comparison between two
|
|
1171
|
+
leaked keys is never "which is longer" — it is what each one is and where it
|
|
1172
|
+
went, which reads as a sentence. */
|
|
1173
|
+
|
|
1174
|
+
.leak-notify { margin-left: auto; }
|
|
1175
|
+
|
|
1176
|
+
.leak-list {
|
|
1177
|
+
list-style: none;
|
|
1178
|
+
margin: 20px 0 0;
|
|
1179
|
+
padding: 0;
|
|
1180
|
+
display: flex;
|
|
1181
|
+
flex-direction: column;
|
|
1182
|
+
gap: 10px;
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
.leak-row {
|
|
1186
|
+
border: 1px solid var(--line-2);
|
|
1187
|
+
/* Hard-offset pixel shadow, never a blur — the house rule. Pink is the
|
|
1188
|
+
accent that means "this one is yours to act on". */
|
|
1189
|
+
box-shadow: 4px 4px 0 0 var(--line-2);
|
|
1190
|
+
padding: 14px 16px;
|
|
1191
|
+
display: flex;
|
|
1192
|
+
flex-direction: column;
|
|
1193
|
+
gap: 8px;
|
|
1194
|
+
background: var(--bg);
|
|
1195
|
+
}
|
|
1196
|
+
/* A recognised prefix means a console exists and this is revocable in a
|
|
1197
|
+
minute. That is a real difference in what the reader has to do, so it is the
|
|
1198
|
+
one thing the row's own frame encodes. */
|
|
1199
|
+
.leak-row[data-attributed="true"] { box-shadow: 4px 4px 0 0 var(--accent-pink); }
|
|
1200
|
+
|
|
1201
|
+
.leak-row-top {
|
|
1202
|
+
display: flex;
|
|
1203
|
+
align-items: baseline;
|
|
1204
|
+
gap: 10px;
|
|
1205
|
+
flex-wrap: wrap;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
.leak-key {
|
|
1209
|
+
font-family: var(--font-mono);
|
|
1210
|
+
font-size: 14px;
|
|
1211
|
+
color: var(--ink);
|
|
1212
|
+
letter-spacing: 0.02em;
|
|
1213
|
+
/* The masked value can be long; it must wrap rather than push the row wide. */
|
|
1214
|
+
word-break: break-all;
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
.leak-label {
|
|
1218
|
+
font-family: var(--font-mono);
|
|
1219
|
+
font-size: 11px;
|
|
1220
|
+
color: var(--accent-pink);
|
|
1221
|
+
text-transform: lowercase;
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
.leak-name {
|
|
1225
|
+
font-family: var(--font-mono);
|
|
1226
|
+
font-size: 11px;
|
|
1227
|
+
color: var(--ink-2);
|
|
1228
|
+
border: 1px solid var(--line-2);
|
|
1229
|
+
padding: 1px 5px;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
.leak-dismiss {
|
|
1233
|
+
margin-left: auto;
|
|
1234
|
+
font-family: var(--font-mono);
|
|
1235
|
+
font-size: 10px;
|
|
1236
|
+
color: var(--dim);
|
|
1237
|
+
background: none;
|
|
1238
|
+
border: 1px solid var(--line-2);
|
|
1239
|
+
padding: 3px 8px;
|
|
1240
|
+
cursor: pointer;
|
|
1241
|
+
text-transform: lowercase;
|
|
1242
|
+
}
|
|
1243
|
+
.leak-dismiss:hover:not(:disabled) { color: var(--ink); border-color: var(--ink-2); }
|
|
1244
|
+
.leak-dismiss:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
1245
|
+
.leak-dismiss:focus-visible { outline: 2px solid var(--accent-pink); outline-offset: 2px; }
|
|
1246
|
+
|
|
1247
|
+
.leak-how {
|
|
1248
|
+
font-family: var(--font-mono);
|
|
1249
|
+
font-size: 12px;
|
|
1250
|
+
color: var(--ink-2);
|
|
1251
|
+
line-height: 1.6;
|
|
1252
|
+
}
|
|
1253
|
+
.leak-verb { color: var(--ink); }
|
|
1254
|
+
.leak-where { color: var(--accent-green); }
|
|
1255
|
+
.leak-who { color: var(--ink); }
|
|
1256
|
+
.leak-when { color: var(--dim); }
|
|
1257
|
+
|
|
1258
|
+
.leak-foot {
|
|
1259
|
+
display: flex;
|
|
1260
|
+
gap: 14px;
|
|
1261
|
+
flex-wrap: wrap;
|
|
1262
|
+
font-family: var(--font-mono);
|
|
1263
|
+
font-size: 10px;
|
|
1264
|
+
color: var(--dim);
|
|
1265
|
+
}
|
|
1266
|
+
.leak-fix { color: var(--accent-green); }
|
|
1267
|
+
.leak-dir { color: var(--ink-2); }
|
|
1268
|
+
|
|
1269
|
+
@media (max-width: 640px) {
|
|
1270
|
+
.leak-dismiss { margin-left: 0; }
|
|
1271
|
+
.leak-foot { gap: 6px; flex-direction: column; }
|
|
1272
|
+
}
|
|
@@ -3,9 +3,32 @@
|
|
|
3
3
|
## 0.0.1b2 — 2026-08-25
|
|
4
4
|
|
|
5
5
|
Open for the next release. `0.0.1b1` published on 2026-08-24 and the `bump` job
|
|
6
|
-
moved the version here automatically
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
moved the version here automatically. Add entries as changes merge — this section
|
|
7
|
+
becomes the GitHub Release body when it ships.
|
|
8
|
+
|
|
9
|
+
### Fixes
|
|
10
|
+
|
|
11
|
+
- **Typed errors keep their exit codes under typer 0.27.2.** That release moved
|
|
12
|
+
`Abort` out of its vendored `typer._click.exceptions`, and `_click_compat`
|
|
13
|
+
imported all six of its symbols under a single
|
|
14
|
+
`try: … except ImportError: from click import …`. One missing name was enough
|
|
15
|
+
to send the whole block to the fallback, binding `ClickException`,
|
|
16
|
+
`UsageError`, `BadParameter`, `Command` and `Parameter` to the pip `click`
|
|
17
|
+
distribution — which is *not* the Click Typer runs, and Typer catches only its
|
|
18
|
+
own. So every typed error escaped its handler: `fp alerts show ghost` exited
|
|
19
|
+
**1 with an empty stderr** instead of **6** with `no alert named "ghost"`, and
|
|
20
|
+
likewise for exits 2, 3, 4 and 5. Nothing warned; the CLI imported and every
|
|
21
|
+
happy path passed. The Click is now decided **once**, on whether `typer._click`
|
|
22
|
+
exists at all, and every symbol imported from that decision, so a future move
|
|
23
|
+
fails at import — a CLI that refuses to start — instead of silently flattening
|
|
24
|
+
the exit-code contract. `Abort` is resolved from `typer.Abort`, which is by
|
|
25
|
+
construction the class `typer.prompt` raises and typer's own `_main` catches on
|
|
26
|
+
every version in range. Suite verified green against typer 0.25.1, 0.27.0,
|
|
27
|
+
0.27.1 and 0.27.2 (#771)
|
|
28
|
+
|
|
29
|
+
### Dependencies
|
|
30
|
+
|
|
31
|
+
- typer 0.27.1 → 0.27.2, click 8.4.2 → 8.5.0, posthog 7.42.0 → 7.44.2 (#771)
|
|
9
32
|
|
|
10
33
|
## 0.0.1b1 — 2026-08-24
|
|
11
34
|
|
|
@@ -11,9 +11,10 @@ compiles, and every happy path still passes:
|
|
|
11
11
|
should print ``✗ …`` and exit 5 exits **1 with an empty stderr**, and the
|
|
12
12
|
``rich_format_error`` hook in ``app.py`` (reached only *after* that catch) never
|
|
13
13
|
runs. Same for the ``UsageError``/``BadParameter`` we raise by hand.
|
|
14
|
-
* ``Abort`` — ``typer.prompt`` raises
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
* ``Abort`` — ``typer.prompt`` raises the ``Abort`` **typer** exports on closed stdin
|
|
15
|
+
(0.27.2 moved that class out of the vendored Click entirely), so a pip-Click
|
|
16
|
+
``except click.Abort`` stops matching and the clean "no TTY, pass a slug" usage error
|
|
17
|
+
becomes a bare abort.
|
|
17
18
|
* Options — Typer 0.26+ has no ``Option`` class in its vendored Click *at all*: every
|
|
18
19
|
option in a Typer-built tree is a ``typer.core.TyperOption``, subclassing
|
|
19
20
|
``Parameter`` directly. ``isinstance(param, click.Option)`` is then quietly always
|
|
@@ -27,14 +28,36 @@ again, and that our errors are still the class Typer catches.
|
|
|
27
28
|
|
|
28
29
|
from __future__ import annotations
|
|
29
30
|
|
|
31
|
+
# `Abort` is resolved from `typer` itself rather than from either Click, because it is
|
|
32
|
+
# the one symbol here that is not stably a Click class: typer 0.27.2 moved it out of the
|
|
33
|
+
# vendored `typer._click.exceptions` into a plain `typer.exceptions.Abort(RuntimeError)`.
|
|
34
|
+
# `typer.Abort` tracks that move — it is `click.Abort` before 0.26, the vendored class
|
|
35
|
+
# through 0.27.1, the RuntimeError from 0.27.2 — and it is by construction the class
|
|
36
|
+
# `typer.prompt` raises and typer's own `_main` catches, which is the only property
|
|
37
|
+
# `select.py`'s `except click.Abort` needs.
|
|
38
|
+
from typer import Abort as Abort
|
|
39
|
+
|
|
40
|
+
# Pick the Click ONCE, on whether typer vendors one at all, then import every symbol
|
|
41
|
+
# from that choice. Deciding per symbol — a single `try` around the whole vendored
|
|
42
|
+
# import block, falling back to pip `click` on any ImportError — is what shipped
|
|
43
|
+
# through 0.27.1 and it failed exactly as silently as this module exists to prevent:
|
|
44
|
+
# 0.27.2 removing `typer._click.exceptions.Abort` made that one missing name rebind ALL
|
|
45
|
+
# SIX symbols to pip Click, so every typed error escaped Typer's handler as exit 1 with
|
|
46
|
+
# an empty stderr. A name that goes missing inside the chosen Click must raise here, at
|
|
47
|
+
# import, where it is a CLI that refuses to start rather than one that silently stops
|
|
48
|
+
# reporting errors.
|
|
30
49
|
try:
|
|
31
|
-
# typer >= 0.26
|
|
32
|
-
# Click in play, so binding to it here would reintroduce the whole class of bug.
|
|
33
|
-
from typer._click import ClickException, Command, Parameter
|
|
34
|
-
from typer._click.exceptions import Abort, BadParameter, UsageError
|
|
50
|
+
import typer._click as _typer_click # typer >= 0.26 vendors its own Click
|
|
35
51
|
except ImportError: # typer < 0.26 drives the pip `click` distribution directly
|
|
52
|
+
_typer_click = None # type: ignore[assignment]
|
|
53
|
+
|
|
54
|
+
if _typer_click is not None:
|
|
55
|
+
# pip `click` may well still be installed — it is simply not the Click in play, so
|
|
56
|
+
# binding to it here would reintroduce the whole class of bug.
|
|
57
|
+
from typer._click import ClickException, Command, Parameter
|
|
58
|
+
from typer._click.exceptions import BadParameter, UsageError
|
|
59
|
+
else:
|
|
36
60
|
from click import ( # type: ignore[assignment]
|
|
37
|
-
Abort,
|
|
38
61
|
BadParameter,
|
|
39
62
|
ClickException,
|
|
40
63
|
Command,
|
|
@@ -31,7 +31,14 @@ dependencies = [
|
|
|
31
31
|
# through that — which is what makes both sides of the split work. Import Click from
|
|
32
32
|
# there and nowhere else; `tests/test_click_compat.py` enforces it, because every way
|
|
33
33
|
# this breaks is silent (typed errors collapse to exit 1 with an empty stderr, and the
|
|
34
|
-
# telemetry flag catalog empties). Suite verified against 0.25.1
|
|
34
|
+
# telemetry flag catalog empties). Suite verified against 0.25.1, 0.27.0, 0.27.1 and
|
|
35
|
+
# 0.27.2.
|
|
36
|
+
#
|
|
37
|
+
# The split keeps moving INSIDE the vendored tree, so the shim resolves each symbol
|
|
38
|
+
# separately: 0.27.2 moved `Abort` out of `typer._click.exceptions` into
|
|
39
|
+
# `typer.exceptions`, and the one all-or-nothing `try/except ImportError` that used to
|
|
40
|
+
# wrap the vendored import sent every OTHER symbol to pip Click over that single
|
|
41
|
+
# missing name — 105 tests red, every typed error at exit 1.
|
|
35
42
|
#
|
|
36
43
|
# The floor is 0.13, not 0.12, because 0.12 cannot BUILD this app: the global
|
|
37
44
|
# `--insecure/--secure` option in `app.py` is an `Optional[bool]` with a
|
|
@@ -39,7 +46,7 @@ dependencies = [
|
|
|
39
46
|
# rejects with `TypeError: Secondary flag is not valid for non-boolean flag`.
|
|
40
47
|
# That fires while the command tree is constructed, before any parsing, so
|
|
41
48
|
# `fp --version`, `fp --help` and every subcommand die identically — an
|
|
42
|
-
# installed CLI that cannot run one command. `uv.lock` pins 0.27.
|
|
49
|
+
# installed CLI that cannot run one command. `uv.lock` pins 0.27.2, so
|
|
43
50
|
# neither CI nor the publish smoke test ever installed the broken part of the
|
|
44
51
|
# range. Measured across 0.12.0/0.12.3/0.12.5 (all fail) and 0.13.0 upward
|
|
45
52
|
# (all pass).
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
import ast
|
|
12
12
|
import pathlib
|
|
13
13
|
|
|
14
|
+
import pytest
|
|
14
15
|
import typer
|
|
15
16
|
from typer.testing import CliRunner
|
|
16
17
|
|
|
@@ -95,6 +96,59 @@ def test_error_exit_codes_are_distinct_per_class():
|
|
|
95
96
|
assert issubclass(KeyModeUnsupportedError, _click_compat.ClickException)
|
|
96
97
|
|
|
97
98
|
|
|
99
|
+
def test_every_symbol_comes_from_the_click_typer_runs():
|
|
100
|
+
"""No symbol may quietly come from pip Click while Typer is running its own.
|
|
101
|
+
|
|
102
|
+
This is the alarm for a *partial* miss. `_click_compat` used to wrap the whole
|
|
103
|
+
vendored import in one `try: … except ImportError: from click import …`, so a single
|
|
104
|
+
name disappearing from `typer._click` rebound **all six** symbols to pip Click — and
|
|
105
|
+
that is not hypothetical: typer 0.27.2 moved `Abort` out of
|
|
106
|
+
`typer._click.exceptions`, and the fallback fired, and 105 tests went red at once
|
|
107
|
+
with typed errors collapsing to exit 1. Assert the provenance of each symbol
|
|
108
|
+
separately, so the next move is one failure naming one symbol.
|
|
109
|
+
"""
|
|
110
|
+
typer_click = pytest.importorskip(
|
|
111
|
+
"typer._click", reason="typer < 0.26 has no vendored Click; pip click IS the right one"
|
|
112
|
+
)
|
|
113
|
+
wrong = {
|
|
114
|
+
name: obj.__module__
|
|
115
|
+
for name in ("ClickException", "UsageError", "BadParameter", "Command", "Parameter")
|
|
116
|
+
if not (obj := getattr(_click_compat, name)).__module__.startswith(typer_click.__name__)
|
|
117
|
+
}
|
|
118
|
+
assert not wrong, f"these came from pip Click, not the Click Typer runs: {wrong}"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def test_abort_is_the_one_typer_raises():
|
|
122
|
+
"""`Abort` is the exception NOT to pin to a Click — pin it to Typer.
|
|
123
|
+
|
|
124
|
+
It is `click.Abort` before typer 0.26, the vendored class through 0.27.1, and a
|
|
125
|
+
plain `typer.exceptions.Abort(RuntimeError)` from 0.27.2 on. `typer.Abort` is the
|
|
126
|
+
class `typer.prompt` raises and typer's own `_main` catches on every one of those,
|
|
127
|
+
which is the only thing `select.py`'s `except click.Abort` needs to be true.
|
|
128
|
+
"""
|
|
129
|
+
assert _click_compat.Abort is typer.Abort
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_hand_raised_usage_errors_reach_typers_handler():
|
|
133
|
+
"""The other half of the contract: `UsageError`/`BadParameter` we raise ourselves.
|
|
134
|
+
|
|
135
|
+
`test_typed_errors_reach_typers_handler` covers the `ClickException` subclasses in
|
|
136
|
+
`errors.py`; these two are raised directly through the shim (`raise
|
|
137
|
+
click.UsageError(...)`) from a dozen call sites, and bound to the wrong Click they
|
|
138
|
+
escape uncaught the same way — exit 1, empty stderr, instead of a clean exit 2.
|
|
139
|
+
"""
|
|
140
|
+
for exc_class in (_click_compat.UsageError, _click_compat.BadParameter):
|
|
141
|
+
app = typer.Typer()
|
|
142
|
+
|
|
143
|
+
@app.command()
|
|
144
|
+
def boom() -> None:
|
|
145
|
+
raise exc_class("bad input")
|
|
146
|
+
|
|
147
|
+
result = CliRunner().invoke(app, [])
|
|
148
|
+
assert result.exit_code == 2, (exc_class, result.output)
|
|
149
|
+
assert "bad input" in result.output
|
|
150
|
+
|
|
151
|
+
|
|
98
152
|
def test_is_option_recognises_typer_options():
|
|
99
153
|
"""Typer's vendored Click has no `Option` class, so `isinstance` cannot answer this.
|
|
100
154
|
|
|
@@ -208,14 +208,11 @@ wheels = [
|
|
|
208
208
|
|
|
209
209
|
[[package]]
|
|
210
210
|
name = "click"
|
|
211
|
-
version = "8.
|
|
211
|
+
version = "8.5.0"
|
|
212
212
|
source = { registry = "https://pypi.org/simple" }
|
|
213
|
-
|
|
214
|
-
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
215
|
-
]
|
|
216
|
-
sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" }
|
|
213
|
+
sdist = { url = "https://files.pythonhosted.org/packages/c7/0e/7fa0ef50764b67090eca4114772a2abf8b6148198475e54c660b97caeee6/click-8.5.0.tar.gz", hash = "sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34", size = 382235, upload-time = "2026-08-26T13:33:14.56Z" }
|
|
217
214
|
wheels = [
|
|
218
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
215
|
+
{ url = "https://files.pythonhosted.org/packages/58/50/6c0d534c5f134586a8e1ba4e330569e32f057e33372ae556463212fb4cd3/click-8.5.0-py3-none-any.whl", hash = "sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360", size = 125251, upload-time = "2026-08-26T13:33:12.928Z" },
|
|
219
216
|
]
|
|
220
217
|
|
|
221
218
|
[[package]]
|
|
@@ -375,7 +372,7 @@ wheels = [
|
|
|
375
372
|
|
|
376
373
|
[[package]]
|
|
377
374
|
name = "posthog"
|
|
378
|
-
version = "7.
|
|
375
|
+
version = "7.47.0"
|
|
379
376
|
source = { registry = "https://pypi.org/simple" }
|
|
380
377
|
dependencies = [
|
|
381
378
|
{ name = "backoff" },
|
|
@@ -383,9 +380,9 @@ dependencies = [
|
|
|
383
380
|
{ name = "requests" },
|
|
384
381
|
{ name = "typing-extensions" },
|
|
385
382
|
]
|
|
386
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
383
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e4/1b/61eccf2257847def7d01ccae29f9680156cb1cd2b4f00d3e9afaabe236fa/posthog-7.47.0.tar.gz", hash = "sha256:62767af8b0808cb103da37aa3974e728467fed9527e4f201f23e718740debd30", size = 508993, upload-time = "2026-09-04T16:52:31.715Z" }
|
|
387
384
|
wheels = [
|
|
388
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
385
|
+
{ url = "https://files.pythonhosted.org/packages/a6/28/16b9b229b9c2380211249377df5bbb4c33cb8b224b7b27ecd46c89bcedac/posthog-7.47.0-py3-none-any.whl", hash = "sha256:c87daf7830eb5ef779d0ff1ec25b5de6d316926d6bbbcde74b80e055172a0ddc", size = 601509, upload-time = "2026-09-04T16:52:29.935Z" },
|
|
389
386
|
]
|
|
390
387
|
|
|
391
388
|
[[package]]
|
|
@@ -520,7 +517,7 @@ wheels = [
|
|
|
520
517
|
|
|
521
518
|
[[package]]
|
|
522
519
|
name = "typer"
|
|
523
|
-
version = "0.27.
|
|
520
|
+
version = "0.27.2"
|
|
524
521
|
source = { registry = "https://pypi.org/simple" }
|
|
525
522
|
dependencies = [
|
|
526
523
|
{ name = "annotated-doc" },
|
|
@@ -528,9 +525,9 @@ dependencies = [
|
|
|
528
525
|
{ name = "rich" },
|
|
529
526
|
{ name = "shellingham" },
|
|
530
527
|
]
|
|
531
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
528
|
+
sdist = { url = "https://files.pythonhosted.org/packages/16/f7/57713ba479fd405eb76de31404b2c744c289e336b2d999511ebf51e496f7/typer-0.27.2.tar.gz", hash = "sha256:269b7eb9d3c202ca84b4bc9618cb04ebb43d3d4d1e567e4c768607232c05f945", size = 204045, upload-time = "2026-08-28T10:26:55.046Z" }
|
|
532
529
|
wheels = [
|
|
533
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
530
|
+
{ url = "https://files.pythonhosted.org/packages/dc/bf/205d0004930ede8f542fb58f601526fccf4ae7626075ca1e6c4de5d3d652/typer-0.27.2-py3-none-any.whl", hash = "sha256:b3a5fc4342d5fc8fda8fc3010b1cf117e9249aab7fae800c2eff62fd3842d97d", size = 123130, upload-time = "2026-08-28T10:26:53.752Z" },
|
|
534
531
|
]
|
|
535
532
|
|
|
536
533
|
[[package]]
|
|
@@ -253,6 +253,34 @@ export interface AuditReportBody {
|
|
|
253
253
|
last_seen?: string;
|
|
254
254
|
examples: string[];
|
|
255
255
|
}[];
|
|
256
|
+
/**
|
|
257
|
+
* Credentials this machine found in its own transcripts.
|
|
258
|
+
*
|
|
259
|
+
* Optional on the wire, so a CLI newer than the api-server sends a field the
|
|
260
|
+
* server ignores rather than failing the whole digest — the harmful counts
|
|
261
|
+
* are the older half of the contract and must keep arriving either way.
|
|
262
|
+
*
|
|
263
|
+
* Every field here is a mask, a label, a length or a location. There is no
|
|
264
|
+
* shape of this object that carries a secret, because the record it is built
|
|
265
|
+
* from never stores one: `recordLeaks` fingerprints at detection time and
|
|
266
|
+
* keeps only the masked rendering.
|
|
267
|
+
*/
|
|
268
|
+
leaks?: {
|
|
269
|
+
id: string;
|
|
270
|
+
display: string;
|
|
271
|
+
label: string;
|
|
272
|
+
length: number;
|
|
273
|
+
attributed: boolean;
|
|
274
|
+
name: string | null;
|
|
275
|
+
confidence: string;
|
|
276
|
+
first_seen: string;
|
|
277
|
+
last_seen: string;
|
|
278
|
+
occurrences: number;
|
|
279
|
+
cli: string;
|
|
280
|
+
project: string;
|
|
281
|
+
mechanism: string;
|
|
282
|
+
direction: "input" | "result";
|
|
283
|
+
}[];
|
|
256
284
|
}
|
|
257
285
|
|
|
258
286
|
export interface AuditReportResult {
|