failproofai 1.0.11 → 1.0.12-beta.1
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 +23 -23
- package/.next/standalone/.next/prerender-manifest.json +4 -4
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js +2 -2
- 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 +2 -2
- 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 +2 -2
- 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 -3
- 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 +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +5 -6
- 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 +24 -24
- 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 +2 -2
- 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 +4 -5
- 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 +6 -7
- 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 +6 -7
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +5 -6
- 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 +2 -2
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js +4 -4
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +7 -7
- 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 +7 -7
- 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 +8 -8
- 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 +3 -3
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/settings/page.js +10 -10
- 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]__0qkp92tjfvw8r._.js → [externals]__0vt9i6fqinjne._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[externals]__1x24dzcbbq6-g._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__02vous7mpi2xm._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__03i5o4a840guz._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0__a_je8fsn65._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_hsnj_a2mvl_._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1izwqj_ij_9x_._.js → [root-of-the-server]__0f_4g-vazrvxv._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-oi4gdtmlo5._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0swiyzbmvja2d._.js → [root-of-the-server]__0t9ufnv5hi2hq._.js} +5 -5
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wg9dk8x8bnau._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__12kq3x-h7t7i1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1a5zkndjwlc13._.js +3 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1r7kbfkiw2xmu._.js → [root-of-the-server]__1aaw59g-5uty7._.js} +12 -12
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1hqpg6vgmfexv._.js +3 -0
- package/.next/standalone/.next/server/chunks/_09dz7xva4ce_2._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0hf5q4xzyg40j._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q0miud6._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3ycqv17cl._.js +1 -1
- package/.next/standalone/.next/server/chunks/_19011-u44143j._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68lnh2daur._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1vslkoe35wok6._.js +1 -1
- package/.next/standalone/.next/server/chunks/{_1ixl-kxq_ctsa._.js → _1y590mjzpkbos._.js} +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4vkpxxu7._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_0_em82s16zfym._.js +5 -0
- package/.next/standalone/.next/server/chunks/src_hooks_builtin-policies_ts_1yq5ybgx1v98e._.js +3 -0
- package/.next/standalone/.next/server/chunks/src_hooks_custom-hooks-loader_ts_0lnb3n3h94wnn._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_daemon-client_ts_0il_yu1zc0291._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn_4twyh._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01j58mdcdw0vn._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0588st-tpiuia._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__08ch3staq3ejw._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_a8z2ldp2v3n._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0vcyntk4snf0f._.js → [root-of-the-server]__0b78b0j8iyv6l._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0bigvy9xmv2ka._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ffu2-38y03ic._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0g8b0kyorya-t._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0h86bl2qf0k_o._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1_xbg2kx30wp-._.js → [root-of-the-server]__0naevg4bcoh54._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0pia5h3p8re4c._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__075uro8t92s0_._.js → [root-of-the-server]__0pwj2h2efe5f-._.js} +3 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0zn1d4blhd3bu._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1-ey9fgesfbc0._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__15usvs-ms-0hf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gb3_92zvk5x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17r4zrwanhp6r._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1avi2kypusyb_._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1lnfv02ucky7m._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mc9-zlnh656_._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1r7drlqli-ado._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1s2-ck3k3rsoo._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1l1qgu5mfapkh._.js → [root-of-the-server]__1vx7o8ukefudh._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0eoura3_9gjb-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0pedwblqdoh58._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_128ebxr83nk6g._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1_ozgifqv1ssi._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1gb0ifpkowwub._.js → _1a3tubds7s7ow._.js} +10 -9
- package/.next/standalone/.next/server/chunks/ssr/_1djqs9i27e4kg._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo5_vm5f.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_actions_get-scheduled-audit_ts_0ei9snixb5fd-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47q0xq5w._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x33jqb6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpcz0uxur._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_02tf1h47jmhhd._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_1f_ymmaonkksc.js → node_modules_html-to-image_es_index_1i8oid1gc7s1f.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/package_json_[json]_cjs_013tntikdft59._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_06kzv9ddabn3_._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_0agdmptetetdt._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_0mdwgjisv4fub._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1cv9_c4l1tzrm._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_daemon-client_ts_0k41_i7jg6ndv._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_pack-cli_ts_0t7me658zqmh_._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +23 -23
- 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/preview-props.json +3 -3
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +23 -23
- package/.next/standalone/.next/static/chunks/{0frxv4_m-m2u5.js → 063al_q720fkj.js} +1 -1
- package/.next/standalone/.next/static/chunks/0_zfad4co-t2z.js +1 -0
- package/.next/standalone/.next/static/chunks/0jutamwqz8pg5.js +1 -0
- package/.next/standalone/.next/static/chunks/114hbolvrv94e.js +1 -0
- package/.next/standalone/.next/static/chunks/{37stoe-_yd852.js → 18433qz-8njv3.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1kwj8uqxuv85t.js → 1b32-afqacaen.js} +1 -1
- package/.next/standalone/.next/static/chunks/{44a7k2_62qc-9.js → 1p-hsi58i-6h0.js} +2 -2
- package/.next/standalone/.next/static/chunks/{302llgh97ce6w.js → 2-tf6_7u623kd.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1_c0dc7zqj1n7.js → 24w3x2da9sk49.js} +1 -1
- package/.next/standalone/.next/static/chunks/2tjfp9dirxnku.js +1 -0
- package/.next/standalone/.next/static/chunks/{16z6_d7sp61jm.js → 3-pku9qwv1yfu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{15rm15u5a6dua.js → 42e8zab314654.js} +1 -1
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +41 -0
- package/.next/standalone/fp-cloud-cli/README.md +42 -1
- package/.next/standalone/fp-cloud-cli/fp_cli/client.py +117 -12
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/fleet_cmds.py +285 -19
- package/.next/standalone/fp-cloud-cli/fp_cli/commands/policies_cmds.py +84 -18
- package/.next/standalone/fp-cloud-cli/fp_cli/enforcement.py +170 -6
- package/.next/standalone/fp-cloud-cli/fp_cli/models.py +89 -6
- package/.next/standalone/fp-cloud-cli/fp_cli/output.py +259 -21
- package/.next/standalone/fp-cloud-cli/fp_cli/policy_check.py +8 -5
- package/.next/standalone/fp-cloud-cli/skill/SKILL.md +2 -2
- package/.next/standalone/fp-cloud-cli/skill/references/commands.md +17 -9
- package/.next/standalone/fp-cloud-cli/tests/test_cloud_jev.py +692 -0
- package/.next/standalone/fp-cloud-cli/tests/test_enforcement_logic.py +46 -0
- package/.next/standalone/fp-cloud-cli/tests/test_output.py +23 -0
- package/.next/standalone/fp-cloud-cli/uv.lock +6 -6
- package/.next/standalone/hermes-plugin/README.md +6 -4
- package/.next/standalone/hermes-plugin/__init__.py +16 -0
- package/.next/standalone/hermes-plugin/client.py +5 -1
- package/.next/standalone/hermes-plugin/plugin.yaml +1 -1
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/context.js +72 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/diag.js +84 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/metrics.js +50 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/propagation.js +80 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/api/trace.js +70 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/context-helpers.js +52 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/baggage-impl.js +44 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/internal/symbol.js +12 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/baggage/utils.js +41 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/NoopContextManager.js +27 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/context/context.js +52 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/context-api.js +16 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/ComponentLogger.js +47 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/consoleLogger.js +73 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/internal/logLevelLogger.js +34 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag/types.js +33 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/diag-api.js +20 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/index.js +71 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/global-utils.js +60 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/internal/semver.js +111 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/Metric.js +18 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeter.js +118 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics/NoopMeterProvider.js +20 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/metrics-api.js +17 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/NoopTextMapPropagator.js +23 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation/TextMapPropagator.js +36 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/propagation-api.js +17 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NonRecordingSpan.js +58 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracer.js +68 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/NoopTracerProvider.js +21 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracer.js +46 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/ProxyTracerProvider.js +46 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/SamplingResult.js +33 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/context-utils.js +71 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-impl.js +94 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/tracestate-validators.js +35 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/internal/utils.js +16 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/invalid-span-constants.js +25 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/span_kind.js +38 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/spancontext-utils.js +66 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/status.js +29 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace/trace_flags.js +18 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/trace-api.js +17 -0
- package/.next/standalone/node_modules/@opentelemetry/api/build/src/version.js +10 -0
- package/.next/standalone/node_modules/@opentelemetry/api/package.json +96 -0
- 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 +2 -2
- package/.next/standalone/node_modules/next/dist/compiled/next-server/app-page-turbo.runtime.prod.js +2 -2
- 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/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/app-render/async-local-storage.js +1 -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/generate-agent-files.js +3 -3
- package/.next/standalone/node_modules/next/dist/server/lib/router-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/trace/tracer.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/typescript/rules/config.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/use-cache/use-cache-wrapper.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 +11 -11
- package/.next/standalone/sdk/python/CHANGELOG.md +7 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
- package/.next/standalone/sdk/python/pyproject.toml +19 -0
- package/.next/standalone/sdk/python/uv.lock +520 -301
- package/.next/standalone/sdk/typescript/CHANGELOG.md +13 -0
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package-lock.json +4 -13
- package/.next/standalone/sdk/typescript/integration/fixtures/mastra-1/package.json +2 -1
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package-lock.json +4 -13
- package/.next/standalone/sdk/typescript/integration/fixtures/nextjs/package.json +3 -0
- package/.next/standalone/sdk/typescript/package-lock.json +178 -162
- package/.next/standalone/sdk/typescript/package.json +1 -1
- package/.next/standalone/sdk/typescript/src/version.ts +1 -1
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +17 -1
- package/dist/cli.mjs +2866 -1124
- package/dist/worker.mjs +1450 -145
- package/hermes-plugin/README.md +6 -4
- package/hermes-plugin/__init__.py +16 -0
- package/hermes-plugin/client.py +5 -1
- package/hermes-plugin/plugin.yaml +1 -1
- package/package.json +11 -11
- package/src/hooks/agent-roster.ts +172 -0
- package/src/hooks/agent-targets.ts +60 -0
- package/src/hooks/cloud-connection.ts +97 -27
- package/src/hooks/cloud-enrollment-cli.ts +7 -4
- package/src/hooks/cloud-managed-policies.ts +380 -20
- package/src/hooks/cloud-policy-errors.ts +481 -0
- package/src/hooks/config-status.ts +1 -1
- package/src/hooks/custom-hooks-loader.ts +26 -3
- package/src/hooks/daemon-client.ts +9 -4
- package/src/hooks/daemon-service.ts +2 -1
- package/src/hooks/effective-reviewers.ts +22 -1
- package/src/hooks/fp-home.ts +6 -0
- package/src/hooks/handler.ts +235 -18
- package/src/hooks/health-probe.ts +15 -0
- package/src/hooks/integrations.ts +18 -11
- package/src/hooks/jev-cli.ts +197 -0
- package/src/hooks/jev-cloud-connection.ts +92 -0
- package/src/hooks/manager.ts +122 -16
- package/src/hooks/pack-failclosed.ts +2 -0
- package/src/hooks/pack-manifest.ts +8 -1
- package/src/hooks/policy-evaluator.ts +5 -1
- package/src/hooks/policy-registry.ts +3 -2
- package/src/hooks/policy-reviewability.ts +21 -5
- package/src/hooks/semantic/cloud-jev-health.ts +227 -0
- package/src/hooks/semantic/cloud-jev.ts +677 -0
- package/src/hooks/semantic/jev-client.ts +18 -1
- package/src/hooks/semantic/jev-config.ts +173 -3
- package/src/hooks/semantic/jev-review.ts +129 -10
- package/src/hooks/semantic/pack-policies.ts +2 -1
- package/src/hooks/semantic/types.ts +8 -0
- package/src/hooks/session-pause-cli.ts +1 -1
- package/src/hooks/worker-server.ts +5 -1
- package/.next/standalone/.next/server/chunks/[externals]__0hjaw70fchx66._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07l68zv0hqdiu._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0car70pylmvor._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0u3i025_setk_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__10a2f6s636yc7._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qt5u58xrcuk6._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_077n_4ip5__fu._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0mqvvxcn6v0op._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_0pb7ds5g0vzgn._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1gasm5xkeqmm3._.js +0 -3
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_1q1heqmkhh8l4._.js +0 -3
- package/.next/standalone/.next/server/chunks/src_hooks_1aveq0uhs2t1b._.js +0 -5
- package/.next/standalone/.next/server/chunks/src_hooks_1eem5a7cyqlb2._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0888k4s6spfmh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_bflu046ep5j._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_lbstb5x2t15._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0fdwgktjfhedo._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s4deza787asx._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__18qe-hu0gwqm4._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1_p_9xe520fex._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1fmhm8_s9i4re._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1g76awtnmimd1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1pczevlpk5lxh._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0dc-of_bn0cim._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_effective-reviewers_ts_1h4wtvo55j16x._.js +0 -5
- package/.next/standalone/.next/static/chunks/0m-tv1y6ghhtk.js +0 -1
- package/.next/standalone/.next/static/chunks/0ol2gj4ntfn56.js +0 -1
- package/.next/standalone/.next/static/chunks/3hj5_7i3nw4zj.js +0 -1
- package/.next/standalone/.next/static/chunks/3iyoapeoq_hup.js +0 -1
- /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{kEFP3ybXwZdriNEQmWwlH → xq8UgF5yFxty1VWxY2hyn}/_ssgManifest.js +0 -0
|
@@ -12,6 +12,15 @@
|
|
|
12
12
|
* never installed its checks: `jevChecksInstalled` below is the hook path's
|
|
13
13
|
* gate for starting a review at all.
|
|
14
14
|
*
|
|
15
|
+
* ## …and a FailproofAI Cloud `both` policy's own Cloud checks
|
|
16
|
+
*
|
|
17
|
+
* A `both` policy's JS half names its own Jev checks, which run on FailproofAI
|
|
18
|
+
* Cloud and never reach this machine (CONTRACT C10). While Cloud's Jev mode
|
|
19
|
+
* asks (`observe`/`enforce`), those names are reviewers too — but only as
|
|
20
|
+
* `cloud:<policyId>/<name>` (`cloudReviewerName`), which the Cloud review files
|
|
21
|
+
* that policy's own Cloud outcomes under. An installed pack's check of the same
|
|
22
|
+
* name is a different reviewer and can never clear it.
|
|
23
|
+
*
|
|
15
24
|
* The names come from the MANIFEST, which is already where `authority` and
|
|
16
25
|
* `reviewedBy` themselves are read from, so this adds no new trust and imports
|
|
17
26
|
* no semantic module.
|
|
@@ -36,11 +45,14 @@
|
|
|
36
45
|
*/
|
|
37
46
|
import { readInstalledPacks, type ResolvedPack } from "./pack-manifest";
|
|
38
47
|
import { NO_REVIEWERS, SEMANTIC_REVIEWER_NAMES } from "./policy-authority";
|
|
48
|
+
import { cloudReviewerNames, readCloudAuthorityInputs, readCloudJevMode } from "./cloud-managed-policies";
|
|
49
|
+
import type { AgentIdentity } from "./agent-targets";
|
|
39
50
|
|
|
40
51
|
let cached: ReadonlySet<string> | null = null;
|
|
41
52
|
let cachedContested: ReadonlyMap<string, string[]> = new Map();
|
|
42
53
|
/** The agent the current registration pass is for; see {@link forgetEffectiveReviewerNames}. */
|
|
43
54
|
let reviewerCli: string | undefined;
|
|
55
|
+
let reviewerAgent: AgentIdentity | null = null;
|
|
44
56
|
|
|
45
57
|
/**
|
|
46
58
|
* The packs whose Jev checks take part for `cli`, filtered the way the regex
|
|
@@ -180,6 +192,14 @@ export function effectiveReviewerNames(): ReadonlySet<string> {
|
|
|
180
192
|
} catch {
|
|
181
193
|
// See above: an unreadable manifest declares no checks.
|
|
182
194
|
}
|
|
195
|
+
try {
|
|
196
|
+
// Both reads answer "nothing" for a file they cannot use; guarded anyway,
|
|
197
|
+
// because a throw here would cost the registration pass — every policy.
|
|
198
|
+
const cloud = cloudReviewerNames(readCloudAuthorityInputs(reviewerAgent), readCloudJevMode());
|
|
199
|
+
if (cloud.length > 0) names = new Set([...names, ...cloud]);
|
|
200
|
+
} catch {
|
|
201
|
+
// No Cloud reviewers: every `both` policy stays hard.
|
|
202
|
+
}
|
|
183
203
|
cached = names;
|
|
184
204
|
return names;
|
|
185
205
|
}
|
|
@@ -244,7 +264,8 @@ export function reviewerNamesFor(
|
|
|
244
264
|
* runs before it registers anything — so a pack installed under a long-lived
|
|
245
265
|
* warm worker is picked up on the next event rather than at the next restart.
|
|
246
266
|
*/
|
|
247
|
-
export function forgetEffectiveReviewerNames(cli?: string): void {
|
|
267
|
+
export function forgetEffectiveReviewerNames(cli?: string, agent: AgentIdentity | null = null): void {
|
|
248
268
|
cached = null;
|
|
249
269
|
reviewerCli = cli;
|
|
270
|
+
reviewerAgent = agent;
|
|
250
271
|
}
|
package/src/hooks/fp-home.ts
CHANGED
|
@@ -165,6 +165,9 @@ export const credentialsFile = (home?: string) => atHome(home, "credentials.json
|
|
|
165
165
|
*/
|
|
166
166
|
export const jevConfigFile = (home?: string) => atHome(home, "jev.json");
|
|
167
167
|
|
|
168
|
+
/** Owner-only inventory maintained by failproofaid. Paths stay on this machine. */
|
|
169
|
+
export const agentRosterFile = (home?: string) => atHome(home, "agents", "roster.json");
|
|
170
|
+
|
|
168
171
|
// ── Daemon binaries ──────────────────────────────────────────────────────────
|
|
169
172
|
|
|
170
173
|
export const binDir = (home?: string) => atHome(home, "bin");
|
|
@@ -656,6 +659,9 @@ export const HOME_CLASSES: readonly { path: (home?: string) => string; class: Da
|
|
|
656
659
|
// history the user was already told about. Kept OUT of `auditSessionFile`
|
|
657
660
|
// precisely so both survive a sign-out.
|
|
658
661
|
{ path: auditMachineFile, class: "identity" },
|
|
662
|
+
// Profile IDs are stable across restarts and renames. A reset that deleted
|
|
663
|
+
// this file would make Cloud's exact-profile assignments match nobody.
|
|
664
|
+
{ path: agentRosterFile, class: "identity" },
|
|
659
665
|
|
|
660
666
|
// ── May be dropped: rebuilt on demand ──
|
|
661
667
|
// NOTE: `auditDir` itself is deliberately absent. Layout 4 made it MIXED — it
|
package/src/hooks/handler.ts
CHANGED
|
@@ -37,7 +37,7 @@ import type { TwoTierReview } from "./semantic/combine";
|
|
|
37
37
|
import type { JevActivityFields } from "./semantic/combine";
|
|
38
38
|
import type { JevConfig } from "./semantic/jev-config";
|
|
39
39
|
import { clearPolicies, registerPolicy, getPoliciesForEvent } from "./policy-registry";
|
|
40
|
-
import { loadAllCustomHooks } from "./custom-hooks-loader";
|
|
40
|
+
import { loadAllCustomHooks, type LoadAllResult } from "./custom-hooks-loader";
|
|
41
41
|
import { contestedReviewerNames, effectiveReviewerNames, jevChecksInstalled } from "./effective-reviewers";
|
|
42
42
|
import {
|
|
43
43
|
authorityDeclarationFor,
|
|
@@ -56,13 +56,34 @@ import { resolveTranscriptPath } from "./resolve-transcript-path";
|
|
|
56
56
|
import { getInstanceId } from "../../lib/telemetry-id";
|
|
57
57
|
import { hookLogInfo, hookLogWarn } from "./hook-logger";
|
|
58
58
|
import { readStdinPayload } from "./read-stdin";
|
|
59
|
-
import {
|
|
59
|
+
import {
|
|
60
|
+
cloudJevAsks,
|
|
61
|
+
withCloudAuthority,
|
|
62
|
+
readActiveCloudManagedPolicies,
|
|
63
|
+
readCloudJevMode,
|
|
64
|
+
readCloudJevState,
|
|
65
|
+
readCloudAgentScopeRequired,
|
|
66
|
+
type CloudManagedPolicyArtifact,
|
|
67
|
+
type CloudPolicyError,
|
|
68
|
+
} from "./cloud-managed-policies";
|
|
69
|
+
import {
|
|
70
|
+
cloudPolicyErrorsPath,
|
|
71
|
+
collectCloudPolicyErrors,
|
|
72
|
+
installedPackIds,
|
|
73
|
+
jevBudgetPath,
|
|
74
|
+
readJevBudgetDrops,
|
|
75
|
+
writeCloudPolicyErrors,
|
|
76
|
+
recordCloudLoadChecked,
|
|
77
|
+
} from "./cloud-policy-errors";
|
|
60
78
|
import { hasInstalledRegexPacks, readInstalledPacks, type PackError, type ResolvedPack } from "./pack-manifest";
|
|
61
79
|
import { missingGuards, packFailureReason, combinedGuardMatch, guardsCover } from "./pack-failclosed";
|
|
62
80
|
import { readActivePause, type ActivePause } from "./session-pause";
|
|
63
81
|
import { jevConfigFile } from "./fp-home";
|
|
64
82
|
import { layoutWarningForHook } from "./fp-reset";
|
|
65
83
|
import { noteUntracedAgent } from "./untraced-note";
|
|
84
|
+
import { isHealthProbe } from "./health-probe";
|
|
85
|
+
import { readRuntimeAgentIdentity, runtimeAgentSettingsPath } from "./agent-roster";
|
|
86
|
+
import type { AgentIdentity } from "./agent-targets";
|
|
66
87
|
|
|
67
88
|
/**
|
|
68
89
|
* Canonicalize an event name to PascalCase. Codex sends snake_case event names
|
|
@@ -169,6 +190,8 @@ export interface EvaluateHookEventOptions {
|
|
|
169
190
|
* written for.
|
|
170
191
|
*/
|
|
171
192
|
fallbackCwd?: string;
|
|
193
|
+
/** Config selected by the hook process (may differ from the worker's env). */
|
|
194
|
+
agentSettingsPath?: string;
|
|
172
195
|
/**
|
|
173
196
|
* The warm worker's hook into its request queue. Called at most once, and
|
|
174
197
|
* only on the two-tier path, at the point this evaluation stops reading the
|
|
@@ -222,10 +245,20 @@ async function runObserved(
|
|
|
222
245
|
// package ships none: until `failproofai policies add FailproofAI/jev-policies`
|
|
223
246
|
// (or another pack declaring `semantic` checks) Jev is inert — no request, no
|
|
224
247
|
// intent capture — whether the config is BYOK or FailproofAI Cloud's;
|
|
248
|
+
//
|
|
249
|
+
// …or, in place of the first two, FailproofAI Cloud sets this machine's Jev
|
|
250
|
+
// mode to `observe`/`enforce` (`active.json` `jevMode`, CONTRACT C10): then
|
|
251
|
+
// EVERY gated call goes to FailproofAI Cloud on the Cloud Jev credential —
|
|
252
|
+
// `jev.json` is not used — because the checks Cloud deployed to this machine
|
|
253
|
+
// live there and this machine cannot know which apply. Cloud's `off` switches
|
|
254
|
+
// Jev off whatever `jev.json` says. The remaining conditions hold either way:
|
|
225
255
|
// - `FAILPROOFAI_EVALUATOR` is not `legacy` (see "Turning Jev off" below);
|
|
226
|
-
// - this is not the fail-closed `forceDecision` path and no session pause is
|
|
256
|
+
// - this is not the fail-closed `forceDecision` path, and no session pause is
|
|
227
257
|
// active — a pause suspends local policy, and Jev must not become a way to
|
|
228
|
-
// evaluate what the pause switched off
|
|
258
|
+
// evaluate what the pause switched off. FailproofAI Cloud's checks are the
|
|
259
|
+
// exception, as Cloud JS assignments are: under a Cloud mode that asks, a
|
|
260
|
+
// paused session's calls still go to Cloud, with no installed pack's check
|
|
261
|
+
// in them;
|
|
229
262
|
// - the event is a gate (`PreToolUse` / `PermissionRequest`) for a named tool
|
|
230
263
|
// that the AGENT requested (see `isHumanAuthoredGate`).
|
|
231
264
|
//
|
|
@@ -266,6 +299,14 @@ function jevForcedOff(opts: EvaluateHookEventOptions | undefined): boolean {
|
|
|
266
299
|
return process.env.FAILPROOFAI_EVALUATOR === "legacy" || !!opts?.forceDecision;
|
|
267
300
|
}
|
|
268
301
|
|
|
302
|
+
/** How a Cloud-mode review reaches FailproofAI Cloud (`semantic/cloud-jev.ts`). */
|
|
303
|
+
interface CloudJevRoute {
|
|
304
|
+
machineId: string;
|
|
305
|
+
deployment: number | null;
|
|
306
|
+
mode: "observe" | "enforce";
|
|
307
|
+
agent: AgentIdentity | null;
|
|
308
|
+
}
|
|
309
|
+
|
|
269
310
|
/**
|
|
270
311
|
* The BYOK config (with the build's default mode, D2), or null (Jev off). A
|
|
271
312
|
* config that cannot be read is off, never a failure. Logged at info, like
|
|
@@ -283,8 +324,31 @@ function jevForcedOff(opts: EvaluateHookEventOptions | undefined): boolean {
|
|
|
283
324
|
* unreadable directory above it and a path that is not a file are all null
|
|
284
325
|
* there too.
|
|
285
326
|
*/
|
|
286
|
-
async function readJevConfig(
|
|
327
|
+
async function readJevConfig(agent?: AgentIdentity | null): Promise<{
|
|
328
|
+
config: JevConfig;
|
|
329
|
+
defaultMode: TwoTierReview["mode"];
|
|
330
|
+
/** Set when FailproofAI Cloud's mode asks: the review goes to Cloud. */
|
|
331
|
+
cloud?: CloudJevRoute;
|
|
332
|
+
} | null> {
|
|
287
333
|
try {
|
|
334
|
+
// FailproofAI Cloud's mode, when its deployment sets one, decides (CONTRACT
|
|
335
|
+
// C10.2): `off` is no Jev at all, whatever `jev.json` says; `observe` or
|
|
336
|
+
// `enforce` runs Jev on FailproofAI Cloud with the Cloud Jev credential —
|
|
337
|
+
// never `jev.json`'s provider — or not at all, when this machine cannot
|
|
338
|
+
// (`loadJevConfigForCloudMode` says why, for `errors.json`). Read off
|
|
339
|
+
// `active.json`, which is small and read on this path already.
|
|
340
|
+
const cloud = readCloudJevState();
|
|
341
|
+
if (cloud.jevMode === "off") return null;
|
|
342
|
+
if (cloudJevAsks(cloud.jevMode)) {
|
|
343
|
+
const { loadJevConfigForCloudMode, DEFAULT_JEV_MODE } = await import("./semantic/jev-config");
|
|
344
|
+
const resolved = loadJevConfigForCloudMode(cloud.jevMode);
|
|
345
|
+
if (!resolved.config || !resolved.machineId) return null;
|
|
346
|
+
return {
|
|
347
|
+
config: resolved.config,
|
|
348
|
+
defaultMode: DEFAULT_JEV_MODE,
|
|
349
|
+
cloud: { machineId: resolved.machineId, deployment: cloud.deployment, mode: cloud.jevMode, agent: agent ?? null },
|
|
350
|
+
};
|
|
351
|
+
}
|
|
288
352
|
if (!existsSync(jevConfigFile())) return null;
|
|
289
353
|
const { loadJevConfig, DEFAULT_JEV_MODE } = await import("./semantic/jev-config");
|
|
290
354
|
const config = loadJevConfig();
|
|
@@ -300,6 +364,90 @@ async function readJevConfig(): Promise<{ config: JevConfig; defaultMode: TwoTie
|
|
|
300
364
|
}
|
|
301
365
|
}
|
|
302
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Where a Jev decision's check came from, as activity-row fields. A FailproofAI
|
|
369
|
+
* Cloud check's outcome arrives with `origin.cloudPolicyId`/`cloudVersion`,
|
|
370
|
+
* carried pack-shaped through the review (`cloud:<id>` / `<version>`, see
|
|
371
|
+
* `semantic/cloud-jev.ts`), and is filed here under the Cloud attribution pair
|
|
372
|
+
* a Cloud JS policy's decision uses — so the Cloud policy page counts it
|
|
373
|
+
* against the policy that was deployed.
|
|
374
|
+
*/
|
|
375
|
+
function jevAttribution(
|
|
376
|
+
origin: { packId: string; packVersion?: string } | undefined,
|
|
377
|
+
): { packId?: string; packVersion?: string; cloudPolicyId?: string; cloudVersion?: number } {
|
|
378
|
+
if (!origin) return {};
|
|
379
|
+
if (origin.packId.startsWith("cloud:")) {
|
|
380
|
+
const version = Number(origin.packVersion);
|
|
381
|
+
return {
|
|
382
|
+
cloudPolicyId: origin.packId.slice("cloud:".length),
|
|
383
|
+
...(Number.isSafeInteger(version) ? { cloudVersion: version } : {}),
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
return origin;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Compute and write `cloud-policies/errors.json` for this machine's Cloud
|
|
391
|
+
* deployment. A no-op off a Cloud-managed machine (`writeCloudPolicyErrors`
|
|
392
|
+
* skips without an `active.json`) and when nothing changed. Never throws.
|
|
393
|
+
*/
|
|
394
|
+
async function recordCloudPolicyErrors(input: {
|
|
395
|
+
manifestError: string | null;
|
|
396
|
+
jsPolicies: CloudManagedPolicyArtifact[];
|
|
397
|
+
jsFailures: LoadAllResult["cloudFailures"] | undefined;
|
|
398
|
+
agentScopeUnresolved?: boolean;
|
|
399
|
+
}): Promise<void> {
|
|
400
|
+
try {
|
|
401
|
+
const jev = readCloudJevState();
|
|
402
|
+
const managed = input.manifestError !== null || input.jsPolicies.length > 0 || jev.jevMode !== null ||
|
|
403
|
+
jev.errors.length > 0 || input.agentScopeUnresolved === true;
|
|
404
|
+
// An unmanaged machine never reads further. A managed machine whose
|
|
405
|
+
// deployment just emptied still writes, so a stale report is cleared.
|
|
406
|
+
if (!managed && !existsSync(cloudPolicyErrorsPath())) return;
|
|
407
|
+
// Only while Cloud's mode ASKS (CONTRACT C10.2): why this machine cannot
|
|
408
|
+
// send its calls (`transcripts_disabled`, `jev_unconfigured…`), and the
|
|
409
|
+
// installed packs' checks Cloud dropped for the question budget under this
|
|
410
|
+
// deployment. The config answer is kept by its module until an input
|
|
411
|
+
// changes, so the second ask of a gate event reads no file.
|
|
412
|
+
let jevProblem: string | null = null;
|
|
413
|
+
let budgetDrops: CloudPolicyError[] = [];
|
|
414
|
+
let health: CloudPolicyError[] = [];
|
|
415
|
+
if (cloudJevAsks(jev.jevMode)) {
|
|
416
|
+
const { loadJevConfigForCloudMode } = await import("./semantic/jev-config");
|
|
417
|
+
const resolved = loadJevConfigForCloudMode(jev.jevMode);
|
|
418
|
+
jevProblem = resolved.problem;
|
|
419
|
+
if (resolved.machineId) {
|
|
420
|
+
// A drop of a pack uninstalled since is not reported (review m2);
|
|
421
|
+
// `installed.json` is read only when there is a record to filter.
|
|
422
|
+
budgetDrops = existsSync(jevBudgetPath())
|
|
423
|
+
? readJevBudgetDrops({ machineId: resolved.machineId, deployment: jev.deployment, jevMode: jev.jevMode }, installedPackIds())
|
|
424
|
+
: [];
|
|
425
|
+
}
|
|
426
|
+
// Rate-limited or unavailable FailproofAI Cloud Jev, as this process has seen it (review M3).
|
|
427
|
+
const { cloudJevHealthErrors } = await import("./semantic/cloud-jev-health");
|
|
428
|
+
health = cloudJevHealthErrors();
|
|
429
|
+
}
|
|
430
|
+
writeCloudPolicyErrors(
|
|
431
|
+
collectCloudPolicyErrors({
|
|
432
|
+
manifestError: input.manifestError,
|
|
433
|
+
jsPolicies: input.jsPolicies,
|
|
434
|
+
jsFailures: input.jsFailures,
|
|
435
|
+
jev,
|
|
436
|
+
jevProblem,
|
|
437
|
+
budgetDrops,
|
|
438
|
+
health,
|
|
439
|
+
agentScopeUnresolved: input.agentScopeUnresolved,
|
|
440
|
+
}),
|
|
441
|
+
);
|
|
442
|
+
// After the report: what this hook load-checked (N4). A failure is in
|
|
443
|
+
// errors.json first, so the listing never sees a checked policy without
|
|
444
|
+
// its error.
|
|
445
|
+
if (input.jsPolicies.length > 0) recordCloudLoadChecked(input.jsPolicies[0].deployment, input.jsPolicies);
|
|
446
|
+
} catch (err) {
|
|
447
|
+
hookLogInfo(`could not record Cloud policy errors: ${err instanceof Error ? err.message : String(err)}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
303
451
|
/**
|
|
304
452
|
* Start Jev's review of this call — before the regex policies run, so the two
|
|
305
453
|
* proceed in parallel — or return null for the regex-only path.
|
|
@@ -311,15 +459,27 @@ async function startTwoTier(
|
|
|
311
459
|
cli: IntegrationType,
|
|
312
460
|
opts: EvaluateHookEventOptions | undefined,
|
|
313
461
|
activePause: ActivePause | null,
|
|
462
|
+
agent: AgentIdentity | null,
|
|
314
463
|
): Promise<TwoTierReview | null> {
|
|
315
464
|
if (!JEV_GATE_EVENTS.has(canonicalEventType)) return null;
|
|
316
465
|
if (isHumanAuthoredGate(session.rawHookEventName, cli)) return null;
|
|
317
466
|
if (typeof parsed.tool_name !== "string" || parsed.tool_name.length === 0) return null;
|
|
318
|
-
if (jevForcedOff(opts)
|
|
319
|
-
// Read off the reviewer set registration just cached, so it is free.
|
|
320
|
-
|
|
321
|
-
|
|
467
|
+
if (jevForcedOff(opts)) return null;
|
|
468
|
+
// Read off the reviewer set registration just cached, so it is free. Under a
|
|
469
|
+
// Cloud mode that asks, every gated call goes to Cloud whether or not an
|
|
470
|
+
// installed pack declares a check: the Cloud checks are Cloud's to select.
|
|
471
|
+
const cloudAsks = cloudJevAsks(readCloudJevMode());
|
|
472
|
+
// A session pause suspends LOCAL policy only: installed packs' Jev checks
|
|
473
|
+
// with it, FailproofAI Cloud's Jev checks never — the same exemption Cloud
|
|
474
|
+
// JS assignments get below, for the same reason (a locally-issued command
|
|
475
|
+
// must not switch off what the org assigned centrally).
|
|
476
|
+
if (activePause && !cloudAsks) return null;
|
|
477
|
+
if (!cloudAsks && !jevChecksInstalled()) return null;
|
|
478
|
+
const loaded = await readJevConfig(agent);
|
|
322
479
|
if (!loaded) return null;
|
|
480
|
+
// Paused, and the config is not Cloud's after all (read in between): the
|
|
481
|
+
// local path has nothing left to ask.
|
|
482
|
+
if (activePause && !loaded.cloud) return null;
|
|
323
483
|
const cfg = loaded.config;
|
|
324
484
|
try {
|
|
325
485
|
const { startJevReview } = await import("./semantic/jev-review");
|
|
@@ -331,6 +491,9 @@ async function startTwoTier(
|
|
|
331
491
|
permissionMode: session.permissionMode,
|
|
332
492
|
sessionId: session.sessionId,
|
|
333
493
|
cli,
|
|
494
|
+
...(loaded.cloud ? { cloud: loaded.cloud } : {}),
|
|
495
|
+
// Cloud's checks are still asked; the installed packs' are not.
|
|
496
|
+
...(activePause ? { localPaused: true } : {}),
|
|
334
497
|
});
|
|
335
498
|
} catch (err) {
|
|
336
499
|
// Configured but unable to start: that is a fallback, and it is recorded
|
|
@@ -405,7 +568,9 @@ async function captureJevIntent(
|
|
|
405
568
|
): Promise<void> {
|
|
406
569
|
if (canonicalEventType !== "UserPromptSubmit" || jevForcedOff(opts)) return;
|
|
407
570
|
try {
|
|
408
|
-
|
|
571
|
+
// Same gate as `startTwoTier`: a Cloud mode that asks needs what the human
|
|
572
|
+
// typed whatever the installed packs declare.
|
|
573
|
+
if (!cloudJevAsks(readCloudJevMode()) && !jevChecksInstalled()) return;
|
|
409
574
|
if (!(await readJevConfig())) return;
|
|
410
575
|
if (decision === "deny") {
|
|
411
576
|
const { ENFORCEMENT_CAPABILITY } = await import("./enforcement-capability");
|
|
@@ -464,6 +629,12 @@ export async function evaluateHookEvent(
|
|
|
464
629
|
}
|
|
465
630
|
}
|
|
466
631
|
|
|
632
|
+
// The daemon health probe: proof the worker answers, not an agent event.
|
|
633
|
+
// Answered before anything records scope errors or activity (B3).
|
|
634
|
+
if (isHealthProbe(eventType, parsed)) {
|
|
635
|
+
return { exitCode: 0, stdout: "", stderr: "" };
|
|
636
|
+
}
|
|
637
|
+
|
|
467
638
|
normalizeCliPayload(cli, parsed);
|
|
468
639
|
|
|
469
640
|
// Canonicalize event name (Codex sends snake_case; internals expect PascalCase)
|
|
@@ -508,6 +679,9 @@ export async function evaluateHookEvent(
|
|
|
508
679
|
rawHookEventName: eventType,
|
|
509
680
|
cli,
|
|
510
681
|
};
|
|
682
|
+
const runtimeAgent = readRuntimeAgentIdentity(
|
|
683
|
+
cli, opts?.agentSettingsPath ?? runtimeAgentSettingsPath(cli, session.cwd),
|
|
684
|
+
);
|
|
511
685
|
|
|
512
686
|
let config: HooksConfig;
|
|
513
687
|
let customHooksList: CustomHook[] = [];
|
|
@@ -554,7 +728,7 @@ export async function evaluateHookEvent(
|
|
|
554
728
|
} else {
|
|
555
729
|
// Load enabled policies (merge across project/local/global scopes)
|
|
556
730
|
config = readMergedHooksConfig(session.cwd);
|
|
557
|
-
clearPolicies(cli);
|
|
731
|
+
clearPolicies(cli, runtimeAgent);
|
|
558
732
|
|
|
559
733
|
// A session pause suspends LOCAL policy only, for a bounded time. Cloud
|
|
560
734
|
// assignments are exempt below for the same reason `disabledCustomPolicies`
|
|
@@ -616,10 +790,13 @@ export async function evaluateHookEvent(
|
|
|
616
790
|
// than the status quo, which already failed open on five of the twelve —
|
|
617
791
|
// just accidentally, and without saying so.
|
|
618
792
|
let cloudManagedPolicies: CloudManagedPolicyArtifact[] = [];
|
|
793
|
+
/** Why the Cloud JS half did not load at all, for `errors.json`. */
|
|
794
|
+
let cloudManifestError: string | null = null;
|
|
619
795
|
try {
|
|
620
|
-
cloudManagedPolicies = readActiveCloudManagedPolicies();
|
|
796
|
+
cloudManagedPolicies = readActiveCloudManagedPolicies(runtimeAgent);
|
|
621
797
|
} catch (err) {
|
|
622
798
|
const msg = err instanceof Error ? err.message : String(err);
|
|
799
|
+
cloudManifestError = msg;
|
|
623
800
|
hookLogWarn(
|
|
624
801
|
`[failproofai] cloud-managed policies could NOT be loaded and are not being enforced: ${msg}. ` +
|
|
625
802
|
`Local policies are unaffected. Run \`failproofai config --status\` to check this machine's enrolment.`,
|
|
@@ -633,7 +810,9 @@ export async function evaluateHookEvent(
|
|
|
633
810
|
// policy decided this event: "what was deployed here at the time" is a
|
|
634
811
|
// separate question from "what decided", and only the former can tell a
|
|
635
812
|
// rollout that changed nothing from one that never reached the machine.
|
|
636
|
-
|
|
813
|
+
// A machine whose deployment carries only a Jev mode has no JS policy to
|
|
814
|
+
// read it off.
|
|
815
|
+
cloudDeployment = cloudManagedPolicies[0]?.deployment ?? readCloudJevState().deployment ?? undefined;
|
|
637
816
|
// Installed packs. `readInstalledPacks` never throws: a bad manifest or a
|
|
638
817
|
// tampered artifact yields zero packs and a recorded reason, which is
|
|
639
818
|
// sound ONLY because the builtins still ship compiled in and keep
|
|
@@ -661,11 +840,22 @@ export async function evaluateHookEvent(
|
|
|
661
840
|
...installedPacks.map((pack) => pack.path),
|
|
662
841
|
];
|
|
663
842
|
|
|
843
|
+
// A FailproofAI Cloud policy's `reviewedBy` names ITS OWN Cloud Jev
|
|
844
|
+
// checks, which run on FailproofAI Cloud (CONTRACT C10.5). Each is
|
|
845
|
+
// translated here to `cloud:<id>/<name>` — a reviewer only that policy's
|
|
846
|
+
// own Cloud outcomes can satisfy, never an installed pack's check of the
|
|
847
|
+
// same name (C9.4) — and only while Cloud's Jev mode asks. An `observe`
|
|
848
|
+
// assignment, or no mode that asks, is hard, without a warning: that is
|
|
849
|
+
// the org's choice, not a broken policy. Before the loader, so two
|
|
850
|
+
// assignments sharing one artifact merge names that still say whose.
|
|
851
|
+
const cloudJevMode = readCloudJevMode();
|
|
852
|
+
const cloudForLoading = cloudManagedPolicies.map((policy) => withCloudAuthority(policy, cloudJevMode));
|
|
853
|
+
|
|
664
854
|
// Load and register custom hooks (layer 2, after builtins)
|
|
665
855
|
const loadResult = await loadAllCustomHooks(allExplicitPaths, {
|
|
666
856
|
sessionCwd: session.cwd,
|
|
667
857
|
customPoliciesEnabled: config.customPoliciesEnabled,
|
|
668
|
-
...(
|
|
858
|
+
...(cloudForLoading.length > 0 ? { cloudManagedPolicies: cloudForLoading } : {}),
|
|
669
859
|
...(installedPacks.length > 0 ? { packs: installedPacks } : {}),
|
|
670
860
|
});
|
|
671
861
|
customHooksList = loadResult.hooks;
|
|
@@ -812,6 +1002,7 @@ export async function evaluateHookEvent(
|
|
|
812
1002
|
// for the user's own files; anything unclear registers as hard. Said
|
|
813
1003
|
// aloud when a `reviewable` claim is refused and Jev is configured, so
|
|
814
1004
|
// an author is not left wondering why Jev never clears it.
|
|
1005
|
+
// A Cloud record's authority was translated before loading (above).
|
|
815
1006
|
const authority = authorityDeclarationFor(hook, { cloudManaged, pack });
|
|
816
1007
|
// Against the same set `registerPolicy` judges it by, or this warning
|
|
817
1008
|
// describes a different machine than the registry does: a pack that
|
|
@@ -835,6 +1026,17 @@ export async function evaluateHookEvent(
|
|
|
835
1026
|
);
|
|
836
1027
|
}
|
|
837
1028
|
|
|
1029
|
+
// What this machine could not load from its FailproofAI Cloud deployment,
|
|
1030
|
+
// for the daemon to report on its next poll. Only on a managed machine,
|
|
1031
|
+
// written only when it changes, and never able to cost this event its
|
|
1032
|
+
// answer (see `cloud-policy-errors.ts`).
|
|
1033
|
+
await recordCloudPolicyErrors({
|
|
1034
|
+
manifestError: cloudManifestError,
|
|
1035
|
+
jsPolicies: cloudManagedPolicies,
|
|
1036
|
+
jsFailures: loadResult.cloudFailures,
|
|
1037
|
+
agentScopeUnresolved: runtimeAgent === null && readCloudAgentScopeRequired(),
|
|
1038
|
+
});
|
|
1039
|
+
|
|
838
1040
|
// Fail closed on enforcement this machine was told it had and does not.
|
|
839
1041
|
//
|
|
840
1042
|
// Additive, and deliberately NOT a clearPolicies() the way the
|
|
@@ -924,7 +1126,7 @@ export async function evaluateHookEvent(
|
|
|
924
1126
|
// starts HERE, before any regex policy runs, and evaluatePolicies combines
|
|
925
1127
|
// the two (see semantic/combine.ts). Otherwise this is null and the call
|
|
926
1128
|
// below is exactly the regex-only evaluation it always was.
|
|
927
|
-
const twoTier = await startTwoTier(canonicalEventType, parsed, session, cli, opts, activePause);
|
|
1129
|
+
const twoTier = await startTwoTier(canonicalEventType, parsed, session, cli, opts, activePause, runtimeAgent);
|
|
928
1130
|
// On the two-tier path the registry is read for the activity row BEFORE
|
|
929
1131
|
// evaluating, because evaluatePolicies may hand the registry back to the
|
|
930
1132
|
// warm worker's queue (`releaseRegistry`) while it waits on Jev, and the
|
|
@@ -1001,7 +1203,7 @@ export async function evaluateHookEvent(
|
|
|
1001
1203
|
// would be false — so it is attributed to Jev itself. Leaving it out
|
|
1002
1204
|
// instead filed every Jev block under "unattributed" on FailproofAI
|
|
1003
1205
|
// Cloud's policy page, beside rows written before attribution existed.
|
|
1004
|
-
...(result.policyName && result.twoTier?.decidedByJev ? { policySource: "jev" as const, ...jevOrigin } : {}),
|
|
1206
|
+
...(result.policyName && result.twoTier?.decidedByJev ? { policySource: "jev" as const, ...jevAttribution(jevOrigin) } : {}),
|
|
1005
1207
|
...(result.policyName && !result.twoTier?.decidedByJev
|
|
1006
1208
|
? (() => {
|
|
1007
1209
|
const attribution = policyAttribution.get(result.policyName);
|
|
@@ -1016,6 +1218,14 @@ export async function evaluateHookEvent(
|
|
|
1016
1218
|
};
|
|
1017
1219
|
})()
|
|
1018
1220
|
: {}),
|
|
1221
|
+
// Observe mode, nothing else decided: the Jev check that would have is
|
|
1222
|
+
// named on the row, with its Cloud policy (B12). Before, the row read
|
|
1223
|
+
// policyName/cloudPolicyId null, so "would have" never reached a policy.
|
|
1224
|
+
// No `policySource`: nothing decided this call, and the policy page
|
|
1225
|
+
// counts a source as a decision; `observed` carries the "would have".
|
|
1226
|
+
...(!result.policyName && observeVerdict
|
|
1227
|
+
? { policyName: observeVerdict.policyName, ...jevAttribution(result.twoTier?.jevOrigin) }
|
|
1228
|
+
: {}),
|
|
1019
1229
|
...(cloudDeployment !== undefined ? { cloudDeployment } : {}),
|
|
1020
1230
|
// The point of observe mode is this record. Without it the rollout is
|
|
1021
1231
|
// unmeasurable and the row is indistinguishable from one where the policy
|
|
@@ -1116,7 +1326,11 @@ export async function evaluateHookEvent(
|
|
|
1116
1326
|
* kept unchanged so nothing about the one-shot (non-daemon) path regresses.
|
|
1117
1327
|
* Internally now just a thin wrapper around `evaluateHookEvent`.
|
|
1118
1328
|
*/
|
|
1119
|
-
export async function handleHookEvent(
|
|
1329
|
+
export async function handleHookEvent(
|
|
1330
|
+
eventType: string,
|
|
1331
|
+
cli: IntegrationType = "claude",
|
|
1332
|
+
agentSettingsPath?: string,
|
|
1333
|
+
): Promise<number> {
|
|
1120
1334
|
const MAX_STDIN_BYTES = 1_048_576; // 1 MB
|
|
1121
1335
|
const stdinRead = await readStdinPayload(MAX_STDIN_BYTES);
|
|
1122
1336
|
if (stdinRead.readError) {
|
|
@@ -1148,7 +1362,10 @@ export async function handleHookEvent(eventType: string, cli: IntegrationType =
|
|
|
1148
1362
|
});
|
|
1149
1363
|
}
|
|
1150
1364
|
|
|
1151
|
-
const result = await evaluateHookEvent(
|
|
1365
|
+
const result = await evaluateHookEvent(
|
|
1366
|
+
eventType, cli, stdinRead.payload,
|
|
1367
|
+
agentSettingsPath === undefined ? undefined : { agentSettingsPath },
|
|
1368
|
+
);
|
|
1152
1369
|
|
|
1153
1370
|
// Say it out loud, once a session, when the collector is holding batches the
|
|
1154
1371
|
// server definitively refused.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The daemon health probe's marker (`probeDaemon` in `daemon-service.ts`).
|
|
3
|
+
*
|
|
4
|
+
* The probe is a SessionStart sent through the daemon to the warm worker, so a
|
|
5
|
+
* reply proves the whole path answers. It is not an agent's session: the
|
|
6
|
+
* handler answers it before any scope, policy or activity logic, or every
|
|
7
|
+
* probe recorded `agent_scope_unresolved` in `errors.json` (it carries no cwd
|
|
8
|
+
* and no `--agent-scope`) and wrote a fake SessionStart activity row.
|
|
9
|
+
*/
|
|
10
|
+
export const HEALTH_PROBE_SOURCE = "failproofai-health-probe";
|
|
11
|
+
|
|
12
|
+
/** Whether a parsed hook payload is the daemon health probe. */
|
|
13
|
+
export function isHealthProbe(eventType: string, parsed: Record<string, unknown>): boolean {
|
|
14
|
+
return eventType === "SessionStart" && parsed.source === HEALTH_PROBE_SOURCE && parsed.session_id === undefined;
|
|
15
|
+
}
|
|
@@ -154,6 +154,12 @@ function isMarkedHook(hook: unknown): boolean {
|
|
|
154
154
|
return cmd.includes("failproofai") && cmd.includes("--hook");
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/** A hook names its installing settings scope, avoiding a cwd-based guess
|
|
158
|
+
* when user and project/local hooks both exist for the same integration. */
|
|
159
|
+
function agentScopeSuffix(scope?: HookScope): string {
|
|
160
|
+
return ` --agent-scope ${scope ?? "user"}`;
|
|
161
|
+
}
|
|
162
|
+
|
|
157
163
|
function stripLegacyVersion(settings: Record<string, unknown>): boolean {
|
|
158
164
|
if ("version" in settings) {
|
|
159
165
|
delete settings.version;
|
|
@@ -285,7 +291,7 @@ export const claudeCode: Integration = {
|
|
|
285
291
|
: `"${binaryPath}" --hook ${eventType}`;
|
|
286
292
|
return {
|
|
287
293
|
type: "command",
|
|
288
|
-
command,
|
|
294
|
+
command: command + agentScopeSuffix(scope),
|
|
289
295
|
// Claude reads `timeout` in SECONDS per https://code.claude.com/docs/en/hooks
|
|
290
296
|
// ("Seconds before canceling. Defaults: 600 for command ...; 60 for agent"),
|
|
291
297
|
// NOT milliseconds. 60 = 60s; the old 60000 meant ~16.7h. (#482-class unit fix)
|
|
@@ -464,7 +470,7 @@ export const codex: Integration = {
|
|
|
464
470
|
// Codex reads `timeout` in SECONDS (the field is literally `timeout`,
|
|
465
471
|
// default 600 per https://developers.openai.com/codex/hooks) — same unit as
|
|
466
472
|
// Claude/Cursor/Copilot. 60 = 60s.
|
|
467
|
-
command,
|
|
473
|
+
command: command + agentScopeSuffix(scope),
|
|
468
474
|
timeout: 60,
|
|
469
475
|
[FAILPROOFAI_HOOK_MARKER]: true,
|
|
470
476
|
};
|
|
@@ -644,8 +650,8 @@ export const copilot: Integration = {
|
|
|
644
650
|
: `"${binaryPath}" --hook ${eventType} --cli copilot`;
|
|
645
651
|
return {
|
|
646
652
|
type: "command",
|
|
647
|
-
bash: cmd,
|
|
648
|
-
powershell: cmd,
|
|
653
|
+
bash: cmd + agentScopeSuffix(scope),
|
|
654
|
+
powershell: cmd + agentScopeSuffix(scope),
|
|
649
655
|
timeoutSec: 60,
|
|
650
656
|
[FAILPROOFAI_HOOK_MARKER]: true,
|
|
651
657
|
};
|
|
@@ -788,7 +794,7 @@ export const cursor: Integration = {
|
|
|
788
794
|
// use 30 and 10), NOT milliseconds. 60 = 60s; the old 60000 meant ~16.7h.
|
|
789
795
|
return {
|
|
790
796
|
type: "command",
|
|
791
|
-
command,
|
|
797
|
+
command: command + agentScopeSuffix(scope),
|
|
792
798
|
timeout: 60,
|
|
793
799
|
[FAILPROOFAI_HOOK_MARKER]: true,
|
|
794
800
|
};
|
|
@@ -981,12 +987,13 @@ function canonicalizeToolInput(canonicalToolName, args) {
|
|
|
981
987
|
|
|
982
988
|
const FAILPROOFAI_BIN = ${escapedBin};
|
|
983
989
|
const USE_NPX = ${useNpx};
|
|
990
|
+
const AGENT_SCOPE = ${JSON.stringify(scope)};
|
|
984
991
|
|
|
985
992
|
function runFailproofai(eventName, payload, directory) {
|
|
986
993
|
const cmd = USE_NPX ? "npx" : FAILPROOFAI_BIN;
|
|
987
994
|
const args = USE_NPX
|
|
988
|
-
? ["-y", "failproofai", "--hook", eventName, "--cli", "opencode"]
|
|
989
|
-
: ["--hook", eventName, "--cli", "opencode"];
|
|
995
|
+
? ["-y", "failproofai", "--hook", eventName, "--cli", "opencode", "--agent-scope", AGENT_SCOPE]
|
|
996
|
+
: ["--hook", eventName, "--cli", "opencode", "--agent-scope", AGENT_SCOPE];
|
|
990
997
|
const r = spawnSync(cmd, args, {
|
|
991
998
|
input: JSON.stringify(payload),
|
|
992
999
|
encoding: "utf8",
|
|
@@ -2460,7 +2467,7 @@ export const factory: Integration = {
|
|
|
2460
2467
|
: `"${binaryPath}" --hook ${eventType} --cli factory`;
|
|
2461
2468
|
return {
|
|
2462
2469
|
type: "command",
|
|
2463
|
-
command,
|
|
2470
|
+
command: command + agentScopeSuffix(scope),
|
|
2464
2471
|
// droid reads `timeout` in SECONDS (verified against droid v0.171.0). 30s.
|
|
2465
2472
|
timeout: 30,
|
|
2466
2473
|
[FAILPROOFAI_HOOK_MARKER]: true,
|
|
@@ -2593,7 +2600,7 @@ export const devin: Integration = {
|
|
|
2593
2600
|
: `"${binaryPath}" --hook ${eventType} --cli devin`;
|
|
2594
2601
|
return {
|
|
2595
2602
|
type: "command",
|
|
2596
|
-
command,
|
|
2603
|
+
command: command + agentScopeSuffix(scope),
|
|
2597
2604
|
// Devin reads `timeout` in SECONDS like Claude. 60 = 60s.
|
|
2598
2605
|
timeout: 60,
|
|
2599
2606
|
[FAILPROOFAI_HOOK_MARKER]: true,
|
|
@@ -2738,7 +2745,7 @@ export const antigravity: Integration = {
|
|
|
2738
2745
|
: `"${binaryPath}" --hook ${eventType} --cli antigravity`;
|
|
2739
2746
|
return {
|
|
2740
2747
|
type: "command",
|
|
2741
|
-
command,
|
|
2748
|
+
command: command + agentScopeSuffix(scope),
|
|
2742
2749
|
// Antigravity reads `timeout` in SECONDS (verified agy v1.1.2). 30s.
|
|
2743
2750
|
timeout: 30,
|
|
2744
2751
|
[FAILPROOFAI_HOOK_MARKER]: true,
|
|
@@ -2926,7 +2933,7 @@ export const goose: Integration = {
|
|
|
2926
2933
|
: `"${binaryPath}" --hook ${eventType} --cli goose`;
|
|
2927
2934
|
// Open Plugins command entry: { type, command } only (Goose applies its own
|
|
2928
2935
|
// timeout; no marker field — see isGooseFailproofaiHook).
|
|
2929
|
-
return { type: "command", command };
|
|
2936
|
+
return { type: "command", command: command + agentScopeSuffix(scope) };
|
|
2930
2937
|
},
|
|
2931
2938
|
|
|
2932
2939
|
isFailproofaiHook: isGooseFailproofaiHook,
|