failproofai 1.0.0-beta.2 → 1.0.0-beta.21
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/app-path-routes-manifest.json +2 -1
- package/.next/standalone/.next/build-manifest.json +6 -6
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/routes-manifest.json +6 -0
- 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 +3 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/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 +3 -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/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +3 -2
- 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 -3
- 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 +3 -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-verify/route.js +3 -2
- 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 -2
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js +3 -2
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +3 -2
- 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 +5 -3
- 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 +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- 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 +3 -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 +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +30 -18
- package/.next/standalone/.next/server/app/policies/page.js +5 -3
- 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 +4 -2
- 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 +6 -4
- 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 +4 -2
- 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/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +18 -0
- package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +6 -0
- package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +53 -0
- package/.next/standalone/.next/server/app/settings/page.js +18 -0
- package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app-paths-manifest.json +2 -1
- package/.next/standalone/.next/server/chunks/[externals]__0h9_83k._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[externals]__1nl3dvw._.js → [externals]__0r-zamh._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[externals]__1ifpkx-._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0l4vuqm._.js → [root-of-the-server]__00ni9za._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08y94xv._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0-dh5jy._.js → [root-of-the-server]__0effm9m._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g0vcwt._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__18d-9oi._.js → [root-of-the-server]__0ix8gm7._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0h3lfmp._.js → [root-of-the-server]__0ji11a-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__10oa-v9._.js → [root-of-the-server]__0ojwjxl._.js} +2 -2
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__16le-kd._.js → [root-of-the-server]__0pbp9fe._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q-v9z2._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vb5fl2._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0sb_5m8._.js → [root-of-the-server]__131ebum._.js} +4 -4
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__20d06rh._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +5 -5
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[externals]__1aq139v._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0-wfhrp._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__06bp_fg._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__074qmkp._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1apb7k_._.js → [root-of-the-server]__0_1tiya._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__170799-._.js → [root-of-the-server]__0spkm68._.js} +11 -11
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0t281d4._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17itmx-._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__01od0m6._.js → [root-of-the-server]__1n2vcv4._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qapotl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tlvv9a._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1v185mo._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0vo2qyt._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0xej-0e._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_10399ge._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_11_p9y8._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_149k9oy._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1_hwp06._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1ctse6u._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1e19atl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1mnhi_r._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1ror7k9._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1sdgprl._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +2 -2
- 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 +2 -2
- package/.next/standalone/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0dwo94s.js +4 -0
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +4 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +6 -6
- package/.next/standalone/.next/server/middleware.js +2 -2
- 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 +74 -20
- package/.next/standalone/.next/static/chunks/{03fmihek9n986.js → 06zgzyh3wv1ig.js} +1 -1
- package/.next/standalone/.next/static/chunks/0km-jn9o5xyqs.css +2 -0
- package/.next/standalone/.next/static/chunks/{1hdhteui932bq.js → 0qmo2t50kpb30.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2sbelanzvxvv0.js → 113g8wtal6_c4.js} +22 -22
- package/.next/standalone/.next/static/chunks/16p68cybetr31.js +1 -0
- package/.next/standalone/.next/static/chunks/18wqn0_3mzylf.js +1 -0
- package/.next/standalone/.next/static/chunks/1v1gqvpjk62jm.js +1 -0
- package/.next/standalone/.next/static/chunks/{0fi645si-uiiq.js → 1xq1m8h14tnlj.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3hp8ulqknybil.js → 1y3vwogqb88dx.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3vs4ay36tjds_.js → 1zmh-b0ulrqu7.js} +1 -1
- package/.next/standalone/.next/static/chunks/23kev26by1e4f.js +1 -0
- package/.next/standalone/.next/static/chunks/299lhw60e8gr6.js +1 -0
- package/.next/standalone/.next/static/chunks/{18rvdw5v72364.js → 2adbpdaxp5ygq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2j94uwkb4s3qr.js → 2kbqcw-6swmav.js} +1 -1
- package/.next/standalone/.next/static/chunks/2n9n5m0963pdg.js +6 -0
- package/.next/standalone/.next/static/chunks/2uvhw57mf9lg_.css +2 -0
- package/.next/standalone/.next/static/chunks/{31feojxhjyjpl.js → 30nrrpwymht5m.js} +1 -1
- package/.next/standalone/.next/static/chunks/31coz11ia5vc4.js +1 -0
- package/.next/standalone/.next/static/chunks/{turbopack-1lsv92x7klwrn.js → turbopack-3diub4ctvn1n0.js} +1 -1
- package/.next/standalone/SECURITY.md +8 -2
- package/.next/standalone/app/actions/get-active-pauses.ts +16 -0
- package/.next/standalone/app/actions/get-hooks-config.ts +2 -2
- package/.next/standalone/app/actions/get-scheduled-audit.ts +70 -0
- package/.next/standalone/app/actions/update-scheduled-audit.ts +44 -0
- package/.next/standalone/app/api/audit/run/route.ts +28 -0
- package/.next/standalone/app/api/audit/status/route.ts +13 -1
- package/.next/standalone/app/api/auth/status/route.ts +1 -1
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +1 -3
- package/.next/standalone/app/audit/_components/audit-progress-strip.tsx +1 -1
- package/.next/standalone/app/audit/_components/auth-dialog.css +159 -0
- package/.next/standalone/app/audit/_components/auth-dialog.tsx +3 -0
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +1 -1
- package/.next/standalone/app/audit/_components/empty-state.tsx +0 -1
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +1 -1
- package/.next/standalone/app/audit/_components/quirks-section.tsx +0 -1
- package/.next/standalone/app/audit/_components/report-footer.tsx +0 -2
- package/.next/standalone/app/audit/_components/run-progress.tsx +1 -1
- package/.next/standalone/app/audit/_components/strengths-section.tsx +0 -1
- package/.next/standalone/app/audit/audit-styles.css +6 -149
- package/.next/standalone/app/components/pause-notices.tsx +111 -0
- package/.next/standalone/app/components/raw-log-viewer.tsx +1 -1
- package/.next/standalone/app/components/toast.tsx +1 -1
- package/.next/standalone/app/policies/hooks-client.tsx +84 -8
- package/.next/standalone/app/settings/page.tsx +31 -0
- package/.next/standalone/app/settings/settings-client.tsx +487 -0
- package/.next/standalone/components/navbar.tsx +2 -0
- package/.next/standalone/lib/auth/api-server-client.ts +2 -3
- package/.next/standalone/lib/auth/auth-store.ts +4 -5
- package/.next/standalone/lib/codex-sessions.ts +2 -1
- package/.next/standalone/lib/dashboard-host.ts +101 -0
- package/.next/standalone/lib/install-check.ts +22 -7
- package/.next/standalone/lib/pi-sessions.ts +99 -14
- package/.next/standalone/lib/telemetry-enabled.ts +54 -0
- package/.next/standalone/lib/telemetry-id.ts +52 -1
- package/.next/standalone/lib/telemetry.ts +8 -4
- package/.next/standalone/node_modules/react/cjs/react.development.js +1 -1
- package/.next/standalone/node_modules/react/cjs/react.production.js +1 -1
- package/.next/standalone/node_modules/react/package.json +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.browser.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server-legacy.node.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.browser.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.edge.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom-server.node.production.js +3 -3
- package/.next/standalone/node_modules/react-dom/cjs/react-dom.production.js +1 -1
- package/.next/standalone/node_modules/react-dom/package.json +4 -4
- package/.next/standalone/package.json +23 -12
- package/.next/standalone/proxy.ts +111 -1
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai-worker.mjs +1 -1
- package/bin/failproofai.mjs +1041 -81
- package/bin/failproofaid-shim.mjs +4 -4
- package/dist/cli.mjs +18513 -10474
- package/dist/worker.mjs +1223 -299
- package/lib/auth/api-server-client.ts +2 -3
- package/lib/auth/auth-store.ts +4 -5
- package/lib/codex-sessions.ts +2 -1
- package/lib/dashboard-host.ts +101 -0
- package/lib/install-check.ts +22 -7
- package/lib/pi-sessions.ts +99 -14
- package/lib/telemetry-enabled.ts +54 -0
- package/lib/telemetry-id.ts +52 -1
- package/lib/telemetry.ts +8 -4
- package/package.json +23 -12
- package/scripts/build-daemon-packages.mjs +247 -0
- package/scripts/daemon-platforms.mjs +42 -0
- package/scripts/dev-hook.mjs +46 -5
- package/scripts/install-telemetry.mjs +8 -1
- package/scripts/launch.ts +25 -3
- package/scripts/parse-script-args.ts +27 -1
- package/scripts/prune-standalone.mjs +26 -0
- package/scripts/publish-aliases.mjs +62 -41
- package/scripts/repro-npm-install.sh +155 -0
- package/scripts/translate-docs/cache.ts +1 -1
- package/scripts/translate-docs/cli.ts +2 -2
- package/scripts/translate-docs/mintlify-nav.ts +1 -1
- package/scripts/translate-docs/readme-translator.ts +163 -4
- package/scripts/validate-mdx.ts +153 -13
- package/src/audit/audit-lock.ts +285 -0
- package/src/audit/audit-schedule.ts +111 -0
- package/src/audit/cache.ts +18 -5
- package/src/audit/cli-adapters/goose.ts +2 -1
- package/src/audit/cli-adapters/hermes.ts +28 -10
- package/src/audit/cli.ts +191 -35
- package/src/audit/dashboard-cache.ts +2 -3
- package/src/audit/report.ts +0 -1
- package/src/hooks/backfill-cli.ts +247 -0
- package/src/hooks/builtin-policies.ts +391 -3
- package/src/hooks/cloud-connection.ts +354 -0
- package/src/hooks/cloud-enrollment-cli.ts +439 -0
- package/src/hooks/cloud-enrollment.ts +284 -0
- package/src/hooks/cloud-introspect.ts +147 -0
- package/src/hooks/cloud-managed-policies.ts +206 -0
- package/src/hooks/collector-config.ts +218 -0
- package/src/hooks/configure-wizard.ts +1211 -233
- package/src/hooks/custom-hooks-loader.ts +243 -37
- package/src/hooks/daemon-client.ts +136 -33
- package/src/hooks/daemon-download.ts +264 -31
- package/src/hooks/daemon-service.ts +1124 -76
- package/src/hooks/first-run-gate.ts +50 -0
- package/src/hooks/flush-cli.ts +180 -0
- package/src/hooks/fp-config.ts +835 -0
- package/src/hooks/fp-home.ts +714 -0
- package/src/hooks/fp-reset.ts +1363 -0
- package/src/hooks/handler.ts +185 -6
- package/src/hooks/harness-cli.ts +386 -0
- package/src/hooks/hook-activity-store.ts +171 -24
- package/src/hooks/hook-logger.ts +2 -2
- package/src/hooks/hook-telemetry.ts +5 -1
- package/src/hooks/hooks-config.ts +4 -3
- package/src/hooks/integrations.ts +0 -1
- package/src/hooks/loader-utils.ts +172 -9
- package/src/hooks/manager.ts +41 -5
- package/src/hooks/migrations.ts +450 -0
- package/src/hooks/onboarding-attempt.ts +195 -0
- package/src/hooks/onboarding-lock.ts +118 -0
- package/src/hooks/policy-types.ts +28 -0
- package/src/hooks/session-pause-cli.ts +159 -0
- package/src/hooks/session-pause.ts +267 -0
- package/src/hooks/setup-state.ts +256 -0
- package/src/hooks/tui.ts +209 -9
- package/src/hooks/uninstall-cli.ts +418 -0
- package/src/hooks/worker-server.ts +134 -15
- package/.next/standalone/.next/server/chunks/[externals]__14odj07._.js +0 -3
- package/.next/standalone/.next/server/chunks/[externals]__1s61mel._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0id_xf7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0longh-._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__19120tr._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rhmvod._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[externals]__1_g_b3t._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0114ewg._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02r5bgf._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e8sjqm._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0lkzqax._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0nb0syg._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qucxyj._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0u02miy._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0uno39i._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__14dd6h8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ath6v_._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1psjybo._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zqz4v8._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/_1m_p7pi._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_0oy_-36.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +0 -5
- package/.next/standalone/.next/static/chunks/0h7auy7hzjyhw.js +0 -1
- package/.next/standalone/.next/static/chunks/0zbxssxh53n-3.js +0 -1
- package/.next/standalone/.next/static/chunks/2mazwb1qmur1p.js +0 -1
- package/.next/standalone/.next/static/chunks/2pujpnfx4pws6.css +0 -2
- package/.next/standalone/.next/static/chunks/33u59vf_8xpd-.js +0 -1
- package/.next/standalone/.next/static/chunks/3i27c3hcriawq.css +0 -1
- package/.next/standalone/.next/static/chunks/3s7myk_co0gbh.js +0 -1
- package/.next/standalone/.next/static/chunks/40k1_v4os4cw6.js +0 -6
- package/.next/standalone/Cargo.lock +0 -428
- package/.next/standalone/Cargo.toml +0 -9
- package/.next/standalone/crates/PROTOCOL.md +0 -122
- package/.next/standalone/crates/failproofaid/Cargo.toml +0 -18
- package/.next/standalone/crates/failproofaid/src/lock.rs +0 -81
- package/.next/standalone/crates/failproofaid/src/main.rs +0 -83
- package/.next/standalone/crates/failproofaid/src/paths.rs +0 -172
- package/.next/standalone/crates/failproofaid/src/server.rs +0 -502
- package/.next/standalone/crates/failproofaid/src/worker.rs +0 -400
- package/.next/standalone/crates/failproofaid/tests/daemon_e2e.rs +0 -241
- package/.next/standalone/crates/fpai-ipc/Cargo.toml +0 -16
- package/.next/standalone/crates/fpai-ipc/src/envelope.rs +0 -175
- package/.next/standalone/crates/fpai-ipc/src/framing.rs +0 -177
- package/.next/standalone/crates/fpai-ipc/src/lib.rs +0 -10
- package/.next/standalone/crates/fpai-ipc/src/peer.rs +0 -80
- package/.next/standalone/docker-hook-sync/Dockerfile +0 -79
- package/.next/standalone/docker-hook-sync/entrypoint.sh +0 -109
- package/.next/standalone/integration-suite/Dockerfile +0 -47
- package/.next/standalone/integration-suite/README.md +0 -129
- package/.next/standalone/integration-suite/canary-policies.mjs +0 -45
- package/.next/standalone/integration-suite/capture-tokens.sh +0 -48
- package/.next/standalone/integration-suite/ci-entrypoint.sh +0 -179
- package/.next/standalone/integration-suite/inject-tokens.sh +0 -44
- package/.next/standalone/integration-suite/install-clis.sh +0 -136
- package/.next/standalone/integration-suite/probe-cli.sh +0 -248
- package/.next/standalone/integration-suite/report.js +0 -120
- package/.next/standalone/integration-suite/run.sh +0 -159
- package/.next/standalone/openclaw-plugin/index.js +0 -223
- package/.next/standalone/openclaw-plugin/openclaw.plugin.json +0 -6
- package/.next/standalone/openclaw-plugin/package.json +0 -12
- package/.next/standalone/osv-scanner.toml +0 -17
- package/.next/standalone/pi-extension/index.ts +0 -524
- package/.next/standalone/pi-extension/package.json +0 -12
- package/.next/standalone/postcss.config.mjs +0 -8
- package/.next/standalone/readme-arch-hq.gif +0 -0
- package/.next/standalone/rust-toolchain.toml +0 -4
- package/src/auth/cli.ts +0 -371
- /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{NWAjs0tHFyzk97gRGG09r → VjEdIL6W5uBsvEzknXqV9}/_ssgManifest.js +0 -0
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
# Integration suite
|
|
2
|
-
|
|
3
|
-
A daily **live-enforcement integration test** for failproofai. It answers one
|
|
4
|
-
question the unit/e2e suites can't: *does failproofai still enforce against every
|
|
5
|
-
supported agent CLI, at the versions users actually install today?*
|
|
6
|
-
|
|
7
|
-
Every day (`.github/workflows/integration-suite.yml`) it installs all 12 agent
|
|
8
|
-
CLIs **@latest** into an isolated Docker sandbox, drives each one against
|
|
9
|
-
failproofai's own policies (built from this repo's HEAD), and confirms the hook
|
|
10
|
-
log shows a **DENY**. A *silent-allow* — a blocked action that ran with no deny —
|
|
11
|
-
means enforcement broke against that CLI (e.g. a vendor changed their hook schema
|
|
12
|
-
out from under us). The test asserts the deny **positively**, so drift surfaces
|
|
13
|
-
as a red run + a Slack alert instead of going unnoticed until a user hits it.
|
|
14
|
-
|
|
15
|
-
## Why it's separate from `__tests__/`
|
|
16
|
-
|
|
17
|
-
It drives **real vendor CLIs against real gateway models** — it needs network,
|
|
18
|
-
Docker, credentials, and ~7-10 min, none of which belong in the fast in-process
|
|
19
|
-
vitest suites. So it's a scheduled workflow, not a PR gate.
|
|
20
|
-
|
|
21
|
-
## How a run works
|
|
22
|
-
|
|
23
|
-
The workflow is a thin trigger; `ci-entrypoint.sh` is the front door and does
|
|
24
|
-
everything below except the Actions cache restore/save.
|
|
25
|
-
|
|
26
|
-
1. Restore `integration-suite-state.json` from Actions cache (version-gate +
|
|
27
|
-
broke/recovered diff) — *workflow*.
|
|
28
|
-
2. Build failproofai under test (`dist/index.js` + `dist/cli.mjs`) from this repo.
|
|
29
|
-
3. Decode the OAuth token secrets, build the sandbox image, create the per-run
|
|
30
|
-
HOME volume, install all 12 CLIs (`install-clis.sh`), inject the credential
|
|
31
|
-
files (`inject-tokens.sh`), assemble the gateway env-file.
|
|
32
|
-
4. `run.sh` probes each non-gated CLI (`probe-cli.sh`), builds the report
|
|
33
|
-
(`report.js`), and POSTs it to Slack.
|
|
34
|
-
5. Cleanup (env-file + volume) runs via `trap`, so it happens on failure too.
|
|
35
|
-
|
|
36
|
-
Run it locally the same way CI does — every input is an env var:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
CANARY_LLM_API_KEY=... CANARY_SKIP_BUILD=1 \
|
|
40
|
-
bash integration-suite/ci-entrypoint.sh
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Version-gate:** a CLI is re-probed only when its binary version **or**
|
|
44
|
-
failproofai's HEAD changed since its last green run — unchanged ⇒ can't have
|
|
45
|
-
drifted ⇒ skip, protecting LLM/vendor quota. `FAIL`/`INCONCLUSIVE`/`ERROR` always
|
|
46
|
-
re-probe until they recover. Dispatch with **force** to probe everything.
|
|
47
|
-
|
|
48
|
-
## Two channels: `stable` and `beta`
|
|
49
|
-
|
|
50
|
-
The workflow runs as a **matrix over `CANARY_CHANNEL`**, in two concurrent legs
|
|
51
|
-
answering different questions:
|
|
52
|
-
|
|
53
|
-
| Leg | Installs | Question | On failure |
|
|
54
|
-
|-----|----------|----------|------------|
|
|
55
|
-
| `stable` | what users get, all 12 CLIs | *is enforcement broken now?* | **fails the job** + Slack |
|
|
56
|
-
| `beta` | each vendor's public pre-release ref, 6 CLIs | *is it about to break?* | **advisory only** — never fails |
|
|
57
|
-
|
|
58
|
-
Only six vendors publish something usable ahead of their release, so the beta leg
|
|
59
|
-
skips the rest rather than re-installing a stable build and reporting it as
|
|
60
|
-
pre-release coverage:
|
|
61
|
-
|
|
62
|
-
| CLI | Pre-release ref | Typical lead |
|
|
63
|
-
|-----|-----------------|--------------|
|
|
64
|
-
| codex | npm `alpha` | up to ~12 d (minor bumps only — patches ship blind) |
|
|
65
|
-
| copilot | npm `prerelease` | 0.6–5.8 d |
|
|
66
|
-
| openclaw | npm `beta` | 0.3–11.4 d |
|
|
67
|
-
| cursor | `install?channel=lab` | 2–4 d |
|
|
68
|
-
| goose | `CANARY=true` (rolling tag) | ~1 release cycle |
|
|
69
|
-
| claude | `latest` — **inverted**, see below | ~13 d |
|
|
70
|
-
|
|
71
|
-
**claude runs backwards.** Nothing ships ahead of `latest`, which *is* the
|
|
72
|
-
bleeding edge (~1 release/day); what exists is `stable`, ~13 days behind. So the
|
|
73
|
-
stable leg pins `bash -s stable` — testing what conservative users run, and
|
|
74
|
-
stopping a same-day Anthropic release from red-lighting an unrelated PR — and
|
|
75
|
-
`latest` becomes the early-warning ref. **hermes** is inverted too but has no fix:
|
|
76
|
-
its installer git-clones `main`, which is also what every hermes user gets, so
|
|
77
|
-
there is nothing ahead of us to probe.
|
|
78
|
-
|
|
79
|
-
**Escalation is a cross-leg comparison, not a beta failure.** A CLI red on both
|
|
80
|
-
legs is already broken and belongs to the stable leg's alarm. The early warning is
|
|
81
|
-
`stable green + beta not-green`, held for **two consecutive runs** so a broken
|
|
82
|
-
alpha that gets reverted before release doesn't burn attention. Note the signal is
|
|
83
|
-
usually `INCONCLUSIVE`/`ERROR`, not `FAIL` — a vendor payload change stops the
|
|
84
|
-
model before it ever calls a tool — so a FAIL-only rule would miss it entirely.
|
|
85
|
-
|
|
86
|
-
Each leg has its own Docker volume and Actions cache key: a pre-release install
|
|
87
|
-
overwrites the stable binary in a shared `$HOME`, and a beta result must never be
|
|
88
|
-
able to overwrite the stable leg's gating record.
|
|
89
|
-
|
|
90
|
-
## Auth & secrets (the `cli-integration` Environment)
|
|
91
|
-
|
|
92
|
-
> The GitHub **Environment** is still named `cli-integration` — it's configured in
|
|
93
|
-
> repo settings, not in this tree, so it was deliberately left alone when this
|
|
94
|
-
> directory was renamed. Renaming it there means renaming `environment:` in the
|
|
95
|
-
> workflow at the same time, or the job loses access to every secret.
|
|
96
|
-
|
|
97
|
-
Because this repo is public, all credentials live in a scoped **GitHub
|
|
98
|
-
Environment** (`cli-integration`) — only this workflow's job can read them — and
|
|
99
|
-
the workflow triggers on `schedule`/`workflow_dispatch` **only**, so fork PRs can
|
|
100
|
-
never reach them.
|
|
101
|
-
|
|
102
|
-
| Auth | CLIs | Secret(s) |
|
|
103
|
-
|------|------|-----------|
|
|
104
|
-
| Env-var (gateway) | claude, codex, goose, opencode, pi, hermes, openclaw, factory | `CANARY_LLM_API_KEY`, `CANARY_LLM_BASE_URL` |
|
|
105
|
-
| Env-var (PAT) | copilot | `COPILOT_GITHUB_TOKEN` |
|
|
106
|
-
| Injected token file | cursor, devin, antigravity | `CURSOR_/DEVIN_/ANTIGRAVITY_TOKEN_TGZ_B64` |
|
|
107
|
-
| Delivery | — | `SLACK_WEBHOOK_URL` |
|
|
108
|
-
|
|
109
|
-
The injected-token CLIs carry OAuth session tokens captured from a logged-in
|
|
110
|
-
machine (see `capture-tokens.sh`). They authenticate on a fresh runner, but may
|
|
111
|
-
eventually expire — when that happens the test reports `⚠️ ERROR` for that CLI;
|
|
112
|
-
re-login on the capture machine and refresh the secret.
|
|
113
|
-
|
|
114
|
-
> Note: env-var / secret names keep the historical `CANARY_` prefix internally —
|
|
115
|
-
> renaming them across the harness would be churn with no user-visible benefit.
|
|
116
|
-
|
|
117
|
-
## Files
|
|
118
|
-
|
|
119
|
-
```
|
|
120
|
-
ci-entrypoint.sh CI front door: build -> sandbox -> install -> probe -> cleanup
|
|
121
|
-
Dockerfile non-root sandbox base image
|
|
122
|
-
install-clis.sh install/upgrade the CLIs for $CANARY_CHANNEL (with retries)
|
|
123
|
-
inject-tokens.sh write captured OAuth creds into the fresh volume
|
|
124
|
-
probe-cli.sh live enforcement probe for ONE CLI (the oracle)
|
|
125
|
-
canary-policies.mjs benign-marker custom policies the probe trips
|
|
126
|
-
run.sh orchestrator (gate → probe → report → Slack)
|
|
127
|
-
report.js build the Slack report + diff state (broke/recovered)
|
|
128
|
-
capture-tokens.sh (run on a logged-in machine) refresh the OAuth token secrets
|
|
129
|
-
```
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Canary custom policies — the DEFINITE probe.
|
|
3
|
-
*
|
|
4
|
-
* The canary probes use BENIGN actions an agent never refuses: `echo`-ing a
|
|
5
|
-
* token, and reading a plain local file. Because there's nothing scary about
|
|
6
|
-
* them, the model reliably issues the tool call — eliminating the self-censorship
|
|
7
|
-
* that made sudo/.env/system-read probes come back INCONCLUSIVE.
|
|
8
|
-
*
|
|
9
|
-
* These policies intercept exactly those benign markers. A deny in the hook log
|
|
10
|
-
* is therefore positive proof that the full enforcement pipeline works against
|
|
11
|
-
* the CLI's REAL tool payload: hook fired → payload normalized (tool_name +
|
|
12
|
-
* tool_input.command / file_path — the drift-prone fields behind the Copilot
|
|
13
|
-
* 1.0.70 silent-allow) → policy evaluated → deny emitted. If normalization ever
|
|
14
|
-
* drifts, ctx.toolInput.command/file_path go empty, no deny fires, the benign
|
|
15
|
-
* command runs, and the probe reports FAIL — never a false alarm, never a miss.
|
|
16
|
-
*/
|
|
17
|
-
import { customPolicies, allow, deny } from "failproofai";
|
|
18
|
-
|
|
19
|
-
// Bash-command path: deny a benign shell command carrying the probe token.
|
|
20
|
-
customPolicies.add({
|
|
21
|
-
name: "canary-bash",
|
|
22
|
-
description: "Canary: deny the benign probe shell command (CANARY_PROBE token)",
|
|
23
|
-
match: { events: ["PreToolUse"] },
|
|
24
|
-
fn: async (ctx) => {
|
|
25
|
-
if (ctx.toolName !== "Bash") return allow();
|
|
26
|
-
const cmd = String(ctx.toolInput?.command ?? "");
|
|
27
|
-
if (cmd.includes("CANARY_PROBE")) return deny("canary-bash probe intercepted");
|
|
28
|
-
return allow();
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// File-path path: deny reading the benign marker file (via Read tool OR `cat`).
|
|
33
|
-
customPolicies.add({
|
|
34
|
-
name: "canary-read",
|
|
35
|
-
description: "Canary: deny reading the benign probe marker file (CANARY_MARKER)",
|
|
36
|
-
match: { events: ["PreToolUse"] },
|
|
37
|
-
fn: async (ctx) => {
|
|
38
|
-
const path = String(ctx.toolInput?.file_path ?? "");
|
|
39
|
-
const cmd = String(ctx.toolInput?.command ?? "");
|
|
40
|
-
if (path.includes("CANARY_MARKER") || cmd.includes("CANARY_MARKER")) {
|
|
41
|
-
return deny("canary-read probe intercepted");
|
|
42
|
-
}
|
|
43
|
-
return allow();
|
|
44
|
-
},
|
|
45
|
-
});
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
-
# capture-tokens.sh — run on the OFFICE BOX (has the logged-in canary volume).
|
|
4
|
-
# ./capture-tokens.sh <owner/repo>
|
|
5
|
-
#
|
|
6
|
-
# Captures each OAuth CLI's credential tree from the persistent HOME volume as a
|
|
7
|
-
# base64 gzip-tar rooted at $HOME, and stores it as a GitHub Actions secret on
|
|
8
|
-
# the canary repo. The CI workflow decodes it back onto the ephemeral runner's
|
|
9
|
-
# volume (see sandbox/inject-tokens.sh), so cursor/devin/antigravity authenticate
|
|
10
|
-
# in CI without an interactive login.
|
|
11
|
-
#
|
|
12
|
-
# Re-run this whenever the canary reports ERROR (not-logged-in / 401) for one of
|
|
13
|
-
# these CLIs — i.e. after you re-login on the box — to refresh the secret.
|
|
14
|
-
#
|
|
15
|
-
# NB: these are real credentials for internal@exosphere.host. They live only in
|
|
16
|
-
# GitHub *encrypted secrets*, never in the repo tree.
|
|
17
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
-
set -euo pipefail
|
|
19
|
-
REPO="${1:?usage: capture-tokens.sh <owner/repo>}"
|
|
20
|
-
VOL="${CANARY_VOL:-failproofai-canary-home}"
|
|
21
|
-
IMAGE="${CANARY_IMAGE:-failproofai-canary:base}"
|
|
22
|
-
|
|
23
|
-
# secret-name → $HOME-relative path(s) to tar from the volume
|
|
24
|
-
capture() {
|
|
25
|
-
local secret="$1"; shift
|
|
26
|
-
local paths=("$@")
|
|
27
|
-
echo "── $secret ($(printf '%s ' "${paths[@]}"))"
|
|
28
|
-
# Tar the paths (rooted at $HOME) inside the container, gzip, base64 → host.
|
|
29
|
-
local b64
|
|
30
|
-
b64="$(docker run --rm -v "$VOL:/home/canary" "$IMAGE" bash -c "
|
|
31
|
-
cd \$HOME || exit 1
|
|
32
|
-
miss=1
|
|
33
|
-
for p in ${paths[*]}; do [ -e \"\$p\" ] && miss=0; done
|
|
34
|
-
[ \$miss = 1 ] && { echo 'MISSING' >&2; exit 3; }
|
|
35
|
-
tar -czf - ${paths[*]} 2>/dev/null | base64 -w0
|
|
36
|
-
")" || { echo " ⚠️ none of the paths exist in the volume — skipping (login first)"; return 0; }
|
|
37
|
-
if [ -z "$b64" ]; then echo " ⚠️ empty capture — skipping"; return 0; fi
|
|
38
|
-
printf '%s' "$b64" | gh secret set "$secret" --repo "$REPO" --body -
|
|
39
|
-
echo " ✓ set $secret (${#b64} b64 chars)"
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
echo "Capturing OAuth credential trees from volume '$VOL' → secrets on $REPO"
|
|
43
|
-
capture CURSOR_TOKEN_TGZ_B64 .config/cursor
|
|
44
|
-
capture DEVIN_TOKEN_TGZ_B64 .local/share/devin/credentials.toml
|
|
45
|
-
# antigravity: capture ONLY the small OAuth token file — the full ~/.gemini tree
|
|
46
|
-
# is ~15 MB (CLI binary + brain/ + logs), far over GitHub's 48 KB secret cap.
|
|
47
|
-
capture ANTIGRAVITY_TOKEN_TGZ_B64 .gemini/antigravity-cli/antigravity-oauth-token
|
|
48
|
-
echo "done."
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
-
# failproofai integration suite — CI entrypoint (runs on the GitHub Actions runner).
|
|
4
|
-
#
|
|
5
|
-
# This is the suite's single front door for CI. The workflow
|
|
6
|
-
# (.github/workflows/integration-suite.yml) is a thin trigger: it checks out,
|
|
7
|
-
# installs bun, maps secrets into the environment, and calls this script. Every
|
|
8
|
-
# step that actually *does* something lives here, so the harness can be read —
|
|
9
|
-
# and run — without opening the YAML.
|
|
10
|
-
#
|
|
11
|
-
# Responsibilities, in order:
|
|
12
|
-
# 1. build failproofai under test (dist/index.js + dist/cli.mjs)
|
|
13
|
-
# 2. decode the base64 OAuth-token secrets into $TOKENS_DIR
|
|
14
|
-
# 3. build the sandbox image and create the per-run HOME volume
|
|
15
|
-
# 4. install all 12 CLIs @latest into that volume, then inject the tokens
|
|
16
|
-
# 5. assemble the gateway env-file
|
|
17
|
-
# 6. hand off to run.sh, which does the version-gating, probing and reporting
|
|
18
|
-
#
|
|
19
|
-
# Cleanup (env-file + docker volume) runs via trap, so it happens on failure and
|
|
20
|
-
# on early exit too — not just on the happy path.
|
|
21
|
-
#
|
|
22
|
-
# Inputs are all environment variables, so this is runnable outside GH Actions:
|
|
23
|
-
#
|
|
24
|
-
# GITHUB_WORKSPACE repo checkout (default: this script's parent dir)
|
|
25
|
-
# CANARY_LLM_API_KEY gateway credentials -> written into the env-file
|
|
26
|
-
# CANARY_LLM_BASE_URL (default https://models.aikin.club)
|
|
27
|
-
# CANARY_LLM_MODEL (default deepseek-v4-pro)
|
|
28
|
-
# CANARY_CLAUDE_MODEL (default claude-haiku-4-5)
|
|
29
|
-
# CANARY_PI_MODEL (default claude-haiku-4-5)
|
|
30
|
-
# CANARY_CODEX_MODEL (default gpt-5.1-codex-mini)
|
|
31
|
-
# COPILOT_GITHUB_TOKEN copilot PAT
|
|
32
|
-
# CURSOR_TOKEN_TGZ_B64 } base64 gzip-tars of each OAuth credential tree,
|
|
33
|
-
# DEVIN_TOKEN_TGZ_B64 } rooted at $HOME (see capture-tokens.sh)
|
|
34
|
-
# ANTIGRAVITY_TOKEN_TGZ_B64
|
|
35
|
-
# CANARY_STATE version-gate state file (restored/saved by the workflow cache)
|
|
36
|
-
# CANARY_SLACK_WEBHOOK optional; report is POSTed here when set
|
|
37
|
-
# CANARY_FP_SHA failproofai HEAD, the second version-gate dimension
|
|
38
|
-
# CANARY_VERSION_GATED "all" (default) | comma-sep list | "none" to force-probe
|
|
39
|
-
# CANARY_CLIS space-separated CLI subset (empty = all 12)
|
|
40
|
-
# CANARY_SKIP_BUILD set to 1 to reuse an existing dist/ (local iteration)
|
|
41
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
42
|
-
set -u
|
|
43
|
-
|
|
44
|
-
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
45
|
-
REPO="${GITHUB_WORKSPACE:-$(dirname "$HERE")}"
|
|
46
|
-
|
|
47
|
-
# Each channel gets its OWN volume: installing a pre-release into the same $HOME
|
|
48
|
-
# overwrites the stable binary (npm -g, and the vendor installers all rewrite
|
|
49
|
-
# their own shims), so the two refs cannot coexist in one volume.
|
|
50
|
-
CHANNEL="${CANARY_CHANNEL:-stable}"
|
|
51
|
-
SUFFIX=""; [ "$CHANNEL" != stable ] && SUFFIX="-$CHANNEL"
|
|
52
|
-
VOL="${CANARY_VOL:-integration-suite$SUFFIX}"
|
|
53
|
-
IMAGE="${CANARY_IMAGE:-failproofai-integration-suite:base}"
|
|
54
|
-
ENVFILE="${CANARY_ENVFILE:-$REPO/canary$SUFFIX.env}"
|
|
55
|
-
TOKENS_DIR="${CANARY_TOKENS_DIR:-$REPO/tokens$SUFFIX}"
|
|
56
|
-
STATE="${CANARY_STATE:-$REPO/integration-suite-state$SUFFIX.json}"
|
|
57
|
-
# The stable leg's state, so the beta leg can tell "about to break" from
|
|
58
|
-
# "already broken" (see report.js). Unset on the stable leg.
|
|
59
|
-
PEER_STATE="${CANARY_PEER_STATE:-}"
|
|
60
|
-
[ "$CHANNEL" != stable ] && [ -z "$PEER_STATE" ] && PEER_STATE="$REPO/integration-suite-state.json"
|
|
61
|
-
|
|
62
|
-
step() { echo "── $* ──" >&2; }
|
|
63
|
-
|
|
64
|
-
cleanup() {
|
|
65
|
-
local rc=$?
|
|
66
|
-
step "cleanup"
|
|
67
|
-
rm -f "$ENVFILE"
|
|
68
|
-
rm -rf "$TOKENS_DIR"
|
|
69
|
-
docker volume rm "$VOL" -f >/dev/null 2>&1 || true
|
|
70
|
-
exit "$rc"
|
|
71
|
-
}
|
|
72
|
-
trap cleanup EXIT
|
|
73
|
-
|
|
74
|
-
# ── 0. adopt legacy version-gate state (rename transition) ──────────────────
|
|
75
|
-
# This harness was renamed from `cli-integration`, which took the Actions cache
|
|
76
|
-
# key with it. The workflow restores the legacy cache alongside the new one; if
|
|
77
|
-
# only the legacy file is present, adopt it so the version-gate keeps its
|
|
78
|
-
# baseline instead of re-probing all 12 CLIs and reporting every one as changed.
|
|
79
|
-
# Safe to delete (with the workflow's legacy restore step) once a run has saved
|
|
80
|
-
# state under the new key.
|
|
81
|
-
LEGACY_STATE="${CANARY_LEGACY_STATE:-$REPO/cli-integration-state.json}"
|
|
82
|
-
if [ ! -s "$STATE" ] && [ -s "$LEGACY_STATE" ]; then
|
|
83
|
-
step "adopting legacy version-gate state from $(basename "$LEGACY_STATE")"
|
|
84
|
-
cp "$LEGACY_STATE" "$STATE" || echo " WARN: copy failed — gate starts empty" >&2
|
|
85
|
-
fi
|
|
86
|
-
|
|
87
|
-
# ── 1. build failproofai under test ─────────────────────────────────────────
|
|
88
|
-
if [ "${CANARY_SKIP_BUILD:-0}" = 1 ]; then
|
|
89
|
-
step "skipping build (CANARY_SKIP_BUILD=1)"
|
|
90
|
-
else
|
|
91
|
-
step "building failproofai under test (dist/index.js + dist/cli.mjs — no dashboard)"
|
|
92
|
-
(
|
|
93
|
-
cd "$REPO" || exit 1
|
|
94
|
-
bun install --frozen-lockfile || exit 1
|
|
95
|
-
bun build --target=node --format=cjs --outfile=dist/index.js src/index.ts || exit 1
|
|
96
|
-
bun run build:cli || exit 1
|
|
97
|
-
) || { echo "✗ build failed" >&2; exit 1; }
|
|
98
|
-
fi
|
|
99
|
-
if [ ! -s "$REPO/dist/index.js" ] || [ ! -s "$REPO/dist/cli.mjs" ]; then
|
|
100
|
-
echo "✗ dist/index.js and dist/cli.mjs must both be non-empty" >&2
|
|
101
|
-
exit 1
|
|
102
|
-
fi
|
|
103
|
-
|
|
104
|
-
# ── 2. decode OAuth token secrets ───────────────────────────────────────────
|
|
105
|
-
# Each is a base64 gzip-tar rooted at $HOME. A missing secret is NOT fatal: that
|
|
106
|
-
# CLI simply reports ERROR (can't auth) rather than taking the whole run down.
|
|
107
|
-
step "decoding OAuth token secrets"
|
|
108
|
-
mkdir -p "$TOKENS_DIR"
|
|
109
|
-
chmod 700 "$TOKENS_DIR"
|
|
110
|
-
decode_token() {
|
|
111
|
-
local name="$1" b64="$2"
|
|
112
|
-
if [ -z "$b64" ]; then
|
|
113
|
-
echo " ✗ $name: no secret set (that CLI will report ERROR)"
|
|
114
|
-
return 0
|
|
115
|
-
fi
|
|
116
|
-
if printf '%s' "$b64" | base64 -d > "$TOKENS_DIR/$name.tgz" 2>/dev/null; then
|
|
117
|
-
echo " ✓ $name: $(wc -c < "$TOKENS_DIR/$name.tgz") bytes"
|
|
118
|
-
else
|
|
119
|
-
echo " ✗ $name: base64 decode FAILED (that CLI will report ERROR)"
|
|
120
|
-
rm -f "$TOKENS_DIR/$name.tgz"
|
|
121
|
-
fi
|
|
122
|
-
}
|
|
123
|
-
decode_token cursor "${CURSOR_TOKEN_TGZ_B64:-}"
|
|
124
|
-
decode_token devin "${DEVIN_TOKEN_TGZ_B64:-}"
|
|
125
|
-
decode_token antigravity "${ANTIGRAVITY_TOKEN_TGZ_B64:-}"
|
|
126
|
-
|
|
127
|
-
# ── 3. sandbox image + per-run volume ───────────────────────────────────────
|
|
128
|
-
step "building sandbox image ($IMAGE)"
|
|
129
|
-
docker build -t "$IMAGE" "$HERE/" || { echo "✗ sandbox image build failed" >&2; exit 1; }
|
|
130
|
-
|
|
131
|
-
step "creating per-run HOME volume ($VOL)"
|
|
132
|
-
docker volume rm "$VOL" -f >/dev/null 2>&1 || true
|
|
133
|
-
docker volume create "$VOL" >/dev/null || { echo "✗ volume create failed" >&2; exit 1; }
|
|
134
|
-
|
|
135
|
-
# ── 4. install CLIs @latest, then inject tokens ─────────────────────────────
|
|
136
|
-
step "installing CLIs (channel=$CHANNEL) into the fresh volume"
|
|
137
|
-
docker run --rm -e CANARY_CHANNEL="$CHANNEL" -v "$VOL:/home/canary" -v "$HERE:/opt/canary:ro" \
|
|
138
|
-
"$IMAGE" bash /opt/canary/install-clis.sh \
|
|
139
|
-
|| { echo "✗ CLI install failed" >&2; exit 1; }
|
|
140
|
-
|
|
141
|
-
step "injecting OAuth credential files"
|
|
142
|
-
docker run --rm -v "$VOL:/home/canary" \
|
|
143
|
-
-v "$HERE:/opt/canary:ro" -v "$TOKENS_DIR:/opt/tokens:ro" \
|
|
144
|
-
"$IMAGE" bash /opt/canary/inject-tokens.sh \
|
|
145
|
-
|| { echo "✗ token injection failed" >&2; exit 1; }
|
|
146
|
-
|
|
147
|
-
# ── 5. gateway env-file ─────────────────────────────────────────────────────
|
|
148
|
-
# umask 077 so the file with the gateway key is never group/world readable.
|
|
149
|
-
step "assembling gateway env-file"
|
|
150
|
-
(
|
|
151
|
-
umask 077
|
|
152
|
-
{
|
|
153
|
-
echo "CANARY_LLM_API_KEY=${CANARY_LLM_API_KEY:-}"
|
|
154
|
-
echo "CANARY_LLM_BASE_URL=${CANARY_LLM_BASE_URL:-https://models.aikin.club}"
|
|
155
|
-
echo "CANARY_LLM_MODEL=${CANARY_LLM_MODEL:-deepseek-v4-pro}"
|
|
156
|
-
echo "CANARY_CLAUDE_MODEL=${CANARY_CLAUDE_MODEL:-claude-haiku-4-5}"
|
|
157
|
-
echo "CANARY_PI_MODEL=${CANARY_PI_MODEL:-claude-haiku-4-5}"
|
|
158
|
-
# Without this line probe-cli.sh's CANARY_CODEX_MODEL override was dead plumbing:
|
|
159
|
-
# the var is read inside the container, and only what is written here crosses into it.
|
|
160
|
-
echo "CANARY_CODEX_MODEL=${CANARY_CODEX_MODEL:-gpt-5.1-codex-mini}"
|
|
161
|
-
echo "COPILOT_GITHUB_TOKEN=${COPILOT_GITHUB_TOKEN:-}"
|
|
162
|
-
} > "$ENVFILE"
|
|
163
|
-
)
|
|
164
|
-
|
|
165
|
-
# ── 6. probe + report ───────────────────────────────────────────────────────
|
|
166
|
-
# run.sh word-splits CANARY_CLIS into args; unquoted on purpose. It owns the
|
|
167
|
-
# exit code (non-zero iff a hard FAIL verdict is present), which the trap
|
|
168
|
-
# preserves.
|
|
169
|
-
step "running integration probes + report"
|
|
170
|
-
# shellcheck disable=SC2086
|
|
171
|
-
CANARY_REPO="$REPO" \
|
|
172
|
-
CANARY_SANDBOX="$HERE" \
|
|
173
|
-
CANARY_VOL="$VOL" \
|
|
174
|
-
CANARY_IMAGE="$IMAGE" \
|
|
175
|
-
CANARY_STATE="$STATE" \
|
|
176
|
-
CANARY_ENVFILE="$ENVFILE" \
|
|
177
|
-
CANARY_CHANNEL="$CHANNEL" \
|
|
178
|
-
CANARY_PEER_STATE="$PEER_STATE" \
|
|
179
|
-
bash "$HERE/run.sh" ${CANARY_CLIS:-}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
-
# Token injection — runs INSIDE the sandbox container, against the fresh per-run
|
|
4
|
-
# HOME volume, BEFORE the probes.
|
|
5
|
-
#
|
|
6
|
-
# On the office box the OAuth logins (cursor / devin / antigravity) live in a
|
|
7
|
-
# PERSISTENT volume. GitHub-Actions runners are ephemeral, so instead each of
|
|
8
|
-
# those credential trees is captured once (see capture-tokens.sh) into a GitHub
|
|
9
|
-
# secret as a base64 gzip-tar rooted at $HOME, decoded by the workflow into
|
|
10
|
-
# /opt/tokens/<name>.tgz, and extracted here into the fresh volume's $HOME.
|
|
11
|
-
#
|
|
12
|
-
# Extraction is rooted at $HOME and the tarballs were created with $HOME-relative
|
|
13
|
-
# paths (e.g. `.config/cursor`, `.local/share/devin/credentials.toml`), so each
|
|
14
|
-
# file lands exactly where its CLI expects it. Env-var-auth CLIs (gateway key,
|
|
15
|
-
# copilot PAT, factory BYOK) need NO file here — they authenticate from env.
|
|
16
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
17
|
-
set -u
|
|
18
|
-
TOK="${1:-/opt/tokens}"
|
|
19
|
-
|
|
20
|
-
if [ ! -d "$TOK" ]; then
|
|
21
|
-
echo "inject-tokens: no token dir at $TOK — nothing to inject (env-var CLIs only)"
|
|
22
|
-
exit 0
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
shopt -s nullglob
|
|
26
|
-
found=0
|
|
27
|
-
for t in "$TOK"/*.tgz "$TOK"/*.tar.gz; do
|
|
28
|
-
found=1
|
|
29
|
-
echo "── injecting $(basename "$t") → \$HOME ──"
|
|
30
|
-
if tar -C "$HOME" -xzf "$t"; then
|
|
31
|
-
tar -tzf "$t" 2>/dev/null | sed 's/^/ /' | head -8
|
|
32
|
-
else
|
|
33
|
-
echo " WARN: extract failed for $t (skipping — that CLI will report ERROR)"
|
|
34
|
-
fi
|
|
35
|
-
done
|
|
36
|
-
[ "$found" = 0 ] && echo "inject-tokens: token dir present but empty — env-var CLIs only"
|
|
37
|
-
|
|
38
|
-
echo "── credential files now present in volume ──"
|
|
39
|
-
for f in "$HOME/.config/cursor/auth.json" \
|
|
40
|
-
"$HOME/.local/share/devin/credentials.toml" \
|
|
41
|
-
"$HOME/.gemini/antigravity-cli"; do
|
|
42
|
-
[ -e "$f" ] && echo " ✓ $f" || echo " ✗ $f (absent)"
|
|
43
|
-
done
|
|
44
|
-
exit 0
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
3
|
-
# Tier-0 install probe — runs INSIDE the canary sandbox container.
|
|
4
|
-
#
|
|
5
|
-
# Installs/upgrades the agent CLIs into the persistent HOME volume, then records
|
|
6
|
-
# which resolve to a runnable binary + their version. This is both the daily
|
|
7
|
-
# "fresh upgrade" step AND the Tier-0 canary signal (packaging/binary breaks show
|
|
8
|
-
# up here as a FAIL).
|
|
9
|
-
#
|
|
10
|
-
# CANARY_CHANNEL selects WHICH ref of each CLI to install:
|
|
11
|
-
# stable (default) — what users get. All 12 CLIs.
|
|
12
|
-
# beta — the vendor's public pre-release ref, for early warning.
|
|
13
|
-
# Only the CLIs that actually publish one; the rest are
|
|
14
|
-
# SKIPPED, never silently re-installed at stable (that would
|
|
15
|
-
# be duplicate work reported as coverage).
|
|
16
|
-
#
|
|
17
|
-
# Every beta ref below was verified live against the vendor's registry/CDN on
|
|
18
|
-
# 2026-07-23; see ~/Desktop/failproofai-integration-suite-beta-channels-design.md
|
|
19
|
-
# for the evidence, lead times, and the CLIs that have no pre-release ref at all
|
|
20
|
-
# (factory, antigravity, pi, opencode, devin, hermes).
|
|
21
|
-
#
|
|
22
|
-
# Install methods verified 2026-07-16 (see failproofai-cli-canary-design.md).
|
|
23
|
-
# Vendor installers scatter binaries across several dirs, so we search an
|
|
24
|
-
# expanded PATH and fall back to a bounded `find` under $HOME.
|
|
25
|
-
#
|
|
26
|
-
# Output: a JSON array at $CANARY_RESULTS (default ~/canary-tier0.json) + a
|
|
27
|
-
# human table on stdout. Never `set -e` — one CLI failing must not abort the rest.
|
|
28
|
-
# ─────────────────────────────────────────────────────────────────────────────
|
|
29
|
-
set -u
|
|
30
|
-
|
|
31
|
-
RESULTS="${CANARY_RESULTS:-$HOME/canary-tier0.json}"
|
|
32
|
-
LOGDIR="${CANARY_LOGDIR:-$HOME/canary-logs}"
|
|
33
|
-
CHANNEL="${CANARY_CHANNEL:-stable}"
|
|
34
|
-
mkdir -p "$LOGDIR"
|
|
35
|
-
|
|
36
|
-
# Cover every dir the vendor installers are known to drop binaries into.
|
|
37
|
-
export PATH="$HOME/.npm-global/bin:$HOME/.local/bin:$HOME/.factory/bin:$HOME/.hermes/bin:$HOME/.cursor/bin:$HOME/.codex/bin:$HOME/bin:$PATH"
|
|
38
|
-
|
|
39
|
-
ROWS=()
|
|
40
|
-
|
|
41
|
-
# probe <id> <binary> <--version flag> <stable install cmd> [beta install cmd]
|
|
42
|
-
# Omitting the 5th argument declares "this CLI has no public pre-release ref",
|
|
43
|
-
# which skips it entirely on the beta channel.
|
|
44
|
-
probe() {
|
|
45
|
-
local id="$1" bin="$2" vflag="$3" install="$4" beta="${5:-}"
|
|
46
|
-
if [ "$CHANNEL" != stable ]; then
|
|
47
|
-
if [ -z "$beta" ]; then
|
|
48
|
-
echo "════════════════════ $id ════════════════════"
|
|
49
|
-
echo " skipped — no public pre-release ref for this CLI"
|
|
50
|
-
return 0
|
|
51
|
-
fi
|
|
52
|
-
install="$beta"
|
|
53
|
-
fi
|
|
54
|
-
echo "════════════════════ $id ════════════════════"
|
|
55
|
-
local t0 t1 rc=1; t0=$SECONDS
|
|
56
|
-
# Retry transient install failures. Flaky vendor CDNs / HTTP-2 stream resets are
|
|
57
|
-
# common on ephemeral CI runners (e.g. factory's `curl … | sh` dropping the
|
|
58
|
-
# download mid-stream with `curl: (18)`). Break as soon as the binary resolves;
|
|
59
|
-
# otherwise give it up to 3 attempts so one bad download isn't a false FAIL.
|
|
60
|
-
for attempt in 1 2 3; do
|
|
61
|
-
bash -c "$install" >"$LOGDIR/$id.install.log" 2>&1
|
|
62
|
-
rc=$?
|
|
63
|
-
hash -r 2>/dev/null
|
|
64
|
-
command -v "$bin" >/dev/null 2>&1 && break
|
|
65
|
-
find "$HOME" -maxdepth 5 -name "$bin" -type f -perm -u+x 2>/dev/null | grep -q . && break
|
|
66
|
-
[ "$attempt" -lt 3 ] && { echo " ↻ $id install attempt $attempt failed (rc=$rc) — retrying in 5s"; sleep 5; }
|
|
67
|
-
done
|
|
68
|
-
t1=$SECONDS
|
|
69
|
-
hash -r 2>/dev/null
|
|
70
|
-
|
|
71
|
-
# Resolve the binary: PATH first, then a bounded find under $HOME.
|
|
72
|
-
local resolved; resolved="$(command -v "$bin" 2>/dev/null || true)"
|
|
73
|
-
if [ -z "$resolved" ]; then
|
|
74
|
-
resolved="$(find "$HOME" -maxdepth 5 -name "$bin" -type f -perm -u+x 2>/dev/null | head -1)"
|
|
75
|
-
fi
|
|
76
|
-
|
|
77
|
-
local ver="" status="FAIL"
|
|
78
|
-
if [ -n "$resolved" ]; then
|
|
79
|
-
status="OK"
|
|
80
|
-
ver="$("$resolved" $vflag 2>&1 | head -1 | tr -cd '[:alnum:] ._+:/-')"
|
|
81
|
-
fi
|
|
82
|
-
|
|
83
|
-
printf ' rc=%s time=%ss bin=%s ver=%s => %s\n' \
|
|
84
|
-
"$rc" "$((t1 - t0))" "${resolved:-<none>}" "${ver:-<none>}" "$status"
|
|
85
|
-
[ "$status" = FAIL ] && echo " ↳ last install log lines:" && tail -3 "$LOGDIR/$id.install.log" | sed 's/^/ /'
|
|
86
|
-
|
|
87
|
-
ROWS+=("$(printf '{"cli":"%s","status":"%s","binary":"%s","version":"%s","install_rc":%s,"secs":%s}' \
|
|
88
|
-
"$id" "$status" "${resolved:-}" "${ver:-}" "$rc" "$((t1 - t0))")")
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
# id binary --ver flag stable ref beta ref (omitted = none exists)
|
|
92
|
-
#
|
|
93
|
-
# claude is the one CLI whose channels run BACKWARDS: nothing ships ahead of
|
|
94
|
-
# `latest`, which is the bleeding edge (~1 release/day). What exists is `stable`,
|
|
95
|
-
# ~13 days behind. So the stable leg pins `stable` — both to test what
|
|
96
|
-
# conservative users actually run and to stop a same-day Anthropic release
|
|
97
|
-
# red-lighting an unrelated PR — and `latest` becomes the early-warning ref.
|
|
98
|
-
probe claude claude "--version" 'curl -fsSL https://claude.ai/install.sh | bash -s stable' \
|
|
99
|
-
'curl -fsSL https://claude.ai/install.sh | bash'
|
|
100
|
-
probe codex codex "--version" 'npm install -g @openai/codex@latest' \
|
|
101
|
-
'npm install -g @openai/codex@alpha'
|
|
102
|
-
probe copilot copilot "--version" 'npm install -g @github/copilot@latest' \
|
|
103
|
-
'npm install -g @github/copilot@prerelease'
|
|
104
|
-
# Cursor validates the channel server-side: only prod/lab/static/prod-stable-internal
|
|
105
|
-
# return 200, anything else is a 400. `lab` is Anysphere's own dogfood channel.
|
|
106
|
-
probe cursor cursor-agent "--version" 'curl https://cursor.com/install -fsS | bash' \
|
|
107
|
-
'curl "https://cursor.com/install?channel=lab" -fsS | bash'
|
|
108
|
-
# opencode's beta/dev tags are ~31 branch snapshots a day (0.0.0-<branch>-<ts>),
|
|
109
|
-
# not release candidates — deliberately no beta ref.
|
|
110
|
-
probe opencode opencode "--version" 'npm install -g opencode-ai@latest'
|
|
111
|
-
probe pi pi "--version" 'npm install -g @mariozechner/pi-coding-agent@latest'
|
|
112
|
-
# hermes install.sh git-clones main, which is ALSO what every hermes user gets —
|
|
113
|
-
# its tags are markers nobody installs. So there is nothing ahead of us to probe,
|
|
114
|
-
# and pinning a tag would test something no user runs.
|
|
115
|
-
probe hermes hermes "--version" 'curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash'
|
|
116
|
-
probe openclaw openclaw "--version" 'npm install -g openclaw@latest' \
|
|
117
|
-
'npm install -g openclaw@beta'
|
|
118
|
-
probe factory droid "--version" 'curl -fsSL https://app.factory.ai/cli | sh'
|
|
119
|
-
probe devin devin "--version" 'curl -fsSL https://cli.devin.ai/install.sh | bash'
|
|
120
|
-
probe antigravity agy "--version" 'curl -fsSL https://antigravity.google/cli/install.sh | bash'
|
|
121
|
-
# goose's canary is a ROLLING TAG (prerelease:false), selected by env var — not a
|
|
122
|
-
# GitHub prerelease, so channel detection that scans for prerelease:true misses it.
|
|
123
|
-
probe goose goose "--version" 'curl -fsSL https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh | CONFIGURE=false bash' \
|
|
124
|
-
'curl -fsSL https://github.com/aaif-goose/goose/releases/download/stable/download_cli.sh | CANARY=true CONFIGURE=false bash'
|
|
125
|
-
|
|
126
|
-
# Emit JSON array.
|
|
127
|
-
{ printf '['; IFS=,; printf '%s' "${ROWS[*]}"; printf ']\n'; } > "$RESULTS"
|
|
128
|
-
|
|
129
|
-
echo
|
|
130
|
-
echo "════════════════════ TIER-0 SUMMARY ════════════════════"
|
|
131
|
-
ok=0; fail=0
|
|
132
|
-
for r in "${ROWS[@]}"; do
|
|
133
|
-
case "$r" in *'"status":"OK"'*) ok=$((ok+1));; *) fail=$((fail+1));; esac
|
|
134
|
-
done
|
|
135
|
-
printf 'channel: %s installed OK: %s / %s failed: %s\n' "$CHANNEL" "$ok" "$((ok + fail))" "$fail"
|
|
136
|
-
echo "results JSON: $RESULTS"
|