failproofai 0.0.14-beta.1 → 0.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +9 -9
- 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 +1 -1
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +9 -9
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +8 -8
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0--lkk6._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-219ec._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__04_h-a5._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06cuf1y._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08w4wmd._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0g6bbuw._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jnjf2t._.js +1 -1
- 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]__0q0qzx1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0q2nbsl._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rv7m0k._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__16le-kd._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17g9wh7._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ffkmds._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1fwl2mz._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1legmza._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1mrihkj._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1myjm-d._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qb590j._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qxztj-._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1shcqgr._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xuedea._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_17k9e3w.js +4 -4
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +1 -1
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__015_i4t._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__030k0c6._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__03lv-pe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__05r_17v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0e2l3c1._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hci7t3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0hdsupo._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p84xee._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qeuy9c._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s89hoe._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ynf7tx._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0brjczq._.js → [root-of-the-server]__0zf8xlq._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__170799-._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__17ai7sy._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1nq7ivq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0wp9w6i._.js → [root-of-the-server]__1s2b6h0._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1tkjqka._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_05whahf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1kje4fm._.js +1 -1
- 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 +1 -1
- package/.next/standalone/.next/server/chunks/ssr/lib_0xkhw_v._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{node_modules_html-to-image_es_index_12rjfea.js → node_modules_html-to-image_es_index_0gkzjaa.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1ezd2jf._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_1tnuifj._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- 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 +10 -10
- package/.next/standalone/.next/static/chunks/06z_ex1ts3n4s.js +1 -0
- package/.next/standalone/.next/static/chunks/0o0ut0ugd0_-s.js +1 -0
- package/.next/standalone/.next/static/chunks/0xl97x-874k-u.js +1 -0
- package/.next/standalone/.next/static/chunks/19d7hqx8udopz.js +1 -0
- package/.next/standalone/.next/static/chunks/{0emg30_6svycu.js → 29o4j32z643_a.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1359o5785rmve.js → 2uh_4k4m296z5.js} +2 -2
- package/.next/standalone/.next/static/chunks/370sj2lgkw5ey.js +1 -0
- package/.next/standalone/.next/static/chunks/{0d5lypu1zs21r.js → 3s8aaig91937v.js} +1 -1
- package/.next/standalone/.next/static/chunks/3w7g0n0iwwnbs.js +1 -0
- package/.next/standalone/.next/static/chunks/{0o9wpnze1ey8y.js → 42oeva1-w0z2d.js} +1 -1
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +11 -2
- package/.next/standalone/app/components/copy-button.tsx +22 -6
- package/.next/standalone/app/components/log-viewer/entry-row.tsx +8 -3
- package/.next/standalone/app/components/raw-log-viewer.tsx +33 -15
- package/.next/standalone/app/policies/hooks-client.tsx +1 -1
- package/.next/standalone/{ci/cli-integration → integration-suite}/README.md +25 -7
- package/.next/standalone/integration-suite/ci-entrypoint.sh +164 -0
- package/.next/standalone/{ci/cli-integration → integration-suite}/run.sh +4 -4
- package/.next/standalone/lib/entry-keys.ts +36 -0
- package/.next/standalone/lib/format-duration.ts +23 -9
- package/.next/standalone/package.json +5 -4
- package/.next/standalone/server.js +1 -1
- package/dist/cli.mjs +342 -106
- package/lib/entry-keys.ts +36 -0
- package/lib/format-duration.ts +23 -9
- package/package.json +5 -4
- package/scripts/translate-docs/cli.ts +6 -0
- package/scripts/translate-docs/mdx-translator.ts +30 -19
- package/scripts/translate-docs/readme-translator.ts +31 -21
- package/scripts/translate-docs/translator.ts +142 -7
- package/scripts/translate-docs/types.ts +6 -0
- package/scripts/translate-docs/validate-translation.ts +132 -0
- package/scripts/validate-mdx.ts +80 -11
- package/src/audit/cli.ts +12 -6
- package/src/auth/cli.ts +14 -5
- package/src/hooks/builtin-policies.ts +168 -50
- package/src/hooks/configure-wizard.ts +238 -22
- package/src/hooks/custom-hooks-loader.ts +70 -4
- package/src/hooks/handler.ts +4 -1
- package/src/hooks/policy-types.ts +8 -0
- package/src/hooks/tui.ts +95 -28
- package/.next/standalone/.next/static/chunks/20tuctw38jbgw.js +0 -1
- package/.next/standalone/.next/static/chunks/2ldhnaweu9ew3.js +0 -1
- package/.next/standalone/.next/static/chunks/2vav_x0_336ds.js +0 -1
- package/.next/standalone/.next/static/chunks/3cg7x0joi2b98.js +0 -1
- package/.next/standalone/.next/static/chunks/3k87p-tijud-4.js +0 -1
- package/.next/standalone/.next/static/chunks/3kmaqcp7rldad.js +0 -1
- /package/.next/standalone/.next/static/{LkN-JjmhKGmL-WklH7WVi → WQRKgSfFekLcC_pvyzp4S}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{LkN-JjmhKGmL-WklH7WVi → WQRKgSfFekLcC_pvyzp4S}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{LkN-JjmhKGmL-WklH7WVi → WQRKgSfFekLcC_pvyzp4S}/_ssgManifest.js +0 -0
- /package/.next/standalone/{ci/cli-integration → integration-suite}/Dockerfile +0 -0
- /package/.next/standalone/{ci/cli-integration → integration-suite}/canary-policies.mjs +0 -0
- /package/.next/standalone/{ci/cli-integration → integration-suite}/capture-tokens.sh +0 -0
- /package/.next/standalone/{ci/cli-integration → integration-suite}/inject-tokens.sh +0 -0
- /package/.next/standalone/{ci/cli-integration → integration-suite}/install-clis.sh +0 -0
- /package/.next/standalone/{ci/cli-integration → integration-suite}/probe-cli.sh +0 -0
- /package/.next/standalone/{ci/cli-integration → integration-suite}/report.js +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -19,7 +19,7 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
|
19
19
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
20
20
|
|
|
21
21
|
// package.json
|
|
22
|
-
var version2 = "0.0.14
|
|
22
|
+
var version2 = "0.0.14";
|
|
23
23
|
var init_package = () => {};
|
|
24
24
|
|
|
25
25
|
// src/posthog-key.ts
|
|
@@ -727,6 +727,22 @@ function readMergedHooksConfig(cwd) {
|
|
|
727
727
|
...llm !== undefined ? { llm } : {}
|
|
728
728
|
};
|
|
729
729
|
}
|
|
730
|
+
function getConfigPath() {
|
|
731
|
+
return resolve(homedir2(), ".failproofai", "policies-config.json");
|
|
732
|
+
}
|
|
733
|
+
function readHooksConfig() {
|
|
734
|
+
const configPath = getConfigPath();
|
|
735
|
+
if (!existsSync2(configPath)) {
|
|
736
|
+
return { enabledPolicies: [] };
|
|
737
|
+
}
|
|
738
|
+
try {
|
|
739
|
+
const raw = readFileSync(configPath, "utf8");
|
|
740
|
+
return JSON.parse(raw);
|
|
741
|
+
} catch (err) {
|
|
742
|
+
hookLogWarn(`failed to parse config at ${configPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
743
|
+
return { enabledPolicies: [] };
|
|
744
|
+
}
|
|
745
|
+
}
|
|
730
746
|
function getConfigPathForScope(scope, cwd) {
|
|
731
747
|
switch (scope) {
|
|
732
748
|
case "user":
|
|
@@ -1178,28 +1194,73 @@ function blockPushMaster(ctx) {
|
|
|
1178
1194
|
}
|
|
1179
1195
|
return allow();
|
|
1180
1196
|
}
|
|
1181
|
-
function
|
|
1182
|
-
|
|
1197
|
+
function expandHomePrefix(path2) {
|
|
1198
|
+
const m = path2.match(/^(?:~|\$HOME|\$\{HOME\})(?=$|\/)/);
|
|
1199
|
+
return m ? homedir3() + path2.slice(m[0].length) : path2;
|
|
1200
|
+
}
|
|
1201
|
+
function stripTrailingGlob(path2) {
|
|
1202
|
+
return path2.replace(/\/\*$/, "").replace(/\/+$/, "");
|
|
1203
|
+
}
|
|
1204
|
+
function isCatastrophicTarget(token) {
|
|
1205
|
+
const raw = token.replace(/^['"]|['"]$/g, "");
|
|
1206
|
+
if (raw === "")
|
|
1207
|
+
return false;
|
|
1208
|
+
const homePrefix = raw.match(HOME_PREFIX_RE);
|
|
1209
|
+
if (!homePrefix && /^[$`]/.test(raw))
|
|
1210
|
+
return true;
|
|
1211
|
+
const belowRoot = homePrefix ? raw.slice(homePrefix[0].length) : raw.startsWith("/") ? raw : null;
|
|
1212
|
+
if (belowRoot === null)
|
|
1183
1213
|
return false;
|
|
1184
|
-
const segments =
|
|
1185
|
-
if (
|
|
1214
|
+
const segments = stripTrailingGlob(belowRoot).split("/").filter(Boolean);
|
|
1215
|
+
if (!homePrefix && SCRATCH_ROOTS.some((r) => `/${segments.join("/")}`.startsWith(`${r}/`)))
|
|
1186
1216
|
return false;
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
const
|
|
1194
|
-
|
|
1217
|
+
return segments.length <= CATASTROPHIC_DEPTH;
|
|
1218
|
+
}
|
|
1219
|
+
function recursiveDeletionTargets(seg) {
|
|
1220
|
+
const tokens = parseArgvTokens(seg);
|
|
1221
|
+
const findIdx = tokens.findIndex((t) => FIND_CMD_RE.test(t));
|
|
1222
|
+
if (findIdx >= 0) {
|
|
1223
|
+
const expr = tokens.slice(findIdx + 1);
|
|
1224
|
+
const execIdx = expr.findIndex((t) => FIND_EXEC_RE.test(t));
|
|
1225
|
+
const deletes = expr.includes("-delete") || execIdx >= 0 && RM_CMD_RE.test(expr[execIdx + 1] ?? "");
|
|
1226
|
+
if (deletes) {
|
|
1227
|
+
let start = 0;
|
|
1228
|
+
while (start < expr.length && FIND_GLOBAL_OPT_RE.test(expr[start])) {
|
|
1229
|
+
start += expr[start] === "-D" ? 2 : 1;
|
|
1230
|
+
}
|
|
1231
|
+
const rest = expr.slice(start);
|
|
1232
|
+
const end = rest.findIndex((t) => FIND_EXPR_START_RE.test(t));
|
|
1233
|
+
return end < 0 ? rest : rest.slice(0, end);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
const rmIdx = tokens.findIndex((t) => RM_CMD_RE.test(t));
|
|
1237
|
+
if (rmIdx >= 0) {
|
|
1238
|
+
const args = tokens.slice(rmIdx + 1);
|
|
1239
|
+
const shortFlags = args.filter((t) => /^-[^-]/.test(t)).join("");
|
|
1240
|
+
const longFlags = args.filter((t) => /^--/.test(t));
|
|
1241
|
+
const recursive = /r/i.test(shortFlags) || longFlags.some((f) => /^--recursive$/i.test(f));
|
|
1242
|
+
const force = /f/.test(shortFlags) || longFlags.some((f) => /^--force$/i.test(f));
|
|
1243
|
+
if (recursive && force)
|
|
1244
|
+
return args.filter((t) => !t.startsWith("-"));
|
|
1245
|
+
}
|
|
1246
|
+
return null;
|
|
1247
|
+
}
|
|
1248
|
+
function shellSegments(cmd) {
|
|
1249
|
+
return cmd.split(/&&|\|\||[|;\n]/).map((s) => s.trim()).filter((s) => s !== "");
|
|
1250
|
+
}
|
|
1251
|
+
function deletionTargetIsAllowed(cmd, allowPaths) {
|
|
1252
|
+
if (allowPaths.length === 0)
|
|
1253
|
+
return false;
|
|
1254
|
+
const normalizedAllowPaths = allowPaths.map((p) => stripTrailingGlob(expandHomePrefix(p)) || "/");
|
|
1255
|
+
let sawRecursiveDelete = false;
|
|
1256
|
+
for (const seg of shellSegments(cmd)) {
|
|
1257
|
+
const targets = recursiveDeletionTargets(seg);
|
|
1258
|
+
if (targets === null)
|
|
1195
1259
|
continue;
|
|
1196
|
-
|
|
1197
|
-
for (const target of
|
|
1198
|
-
const normalized =
|
|
1199
|
-
const covered =
|
|
1200
|
-
const np = p.replace(/\/+$/, "") || "/";
|
|
1201
|
-
return normalized === np || normalized.startsWith(np + "/");
|
|
1202
|
-
});
|
|
1260
|
+
sawRecursiveDelete = true;
|
|
1261
|
+
for (const target of targets) {
|
|
1262
|
+
const normalized = stripTrailingGlob(expandHomePrefix(target)) || "/";
|
|
1263
|
+
const covered = normalizedAllowPaths.some((np) => normalized === np || normalized.startsWith(np + "/"));
|
|
1203
1264
|
if (!covered) {
|
|
1204
1265
|
const segCovered = allowPaths.some((p) => {
|
|
1205
1266
|
const escaped = p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -1210,35 +1271,22 @@ function rmTargetIsAllowed(cmd, allowPaths) {
|
|
|
1210
1271
|
}
|
|
1211
1272
|
}
|
|
1212
1273
|
}
|
|
1213
|
-
return
|
|
1274
|
+
return sawRecursiveDelete;
|
|
1214
1275
|
}
|
|
1215
1276
|
function blockRmRf(ctx) {
|
|
1216
1277
|
if (ctx.toolName !== "Bash")
|
|
1217
1278
|
return allow();
|
|
1218
1279
|
const cmd = getCommand(ctx);
|
|
1219
|
-
const
|
|
1220
|
-
const
|
|
1221
|
-
return
|
|
1280
|
+
const hasCatastrophicTarget = shellSegments(cmd).some((seg) => {
|
|
1281
|
+
const targets = recursiveDeletionTargets(seg);
|
|
1282
|
+
return targets !== null && targets.some(isCatastrophicTarget);
|
|
1222
1283
|
});
|
|
1223
|
-
if (
|
|
1284
|
+
if (hasCatastrophicTarget) {
|
|
1224
1285
|
const allowPaths = ctx.params?.allowPaths ?? [];
|
|
1225
|
-
if (
|
|
1286
|
+
if (deletionTargetIsAllowed(cmd, allowPaths))
|
|
1226
1287
|
return allow();
|
|
1227
1288
|
return deny("Catastrophic deletion blocked");
|
|
1228
1289
|
}
|
|
1229
|
-
if (hasDestructivePath && /\brm\b/.test(cmd)) {
|
|
1230
|
-
const tokens = parseArgvTokens(cmd);
|
|
1231
|
-
const shortFlags = tokens.filter((t) => /^-[^-]/.test(t)).join("");
|
|
1232
|
-
const longFlags = tokens.filter((t) => /^--/.test(t));
|
|
1233
|
-
const hasRecursive = /r/i.test(shortFlags) || longFlags.some((f) => /^--recursive$/i.test(f));
|
|
1234
|
-
const hasForce = /f/.test(shortFlags) || longFlags.some((f) => /^--force$/i.test(f));
|
|
1235
|
-
if (hasRecursive && hasForce) {
|
|
1236
|
-
const allowPaths = ctx.params?.allowPaths ?? [];
|
|
1237
|
-
if (rmTargetIsAllowed(cmd, allowPaths))
|
|
1238
|
-
return allow();
|
|
1239
|
-
return deny("Catastrophic deletion blocked");
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
1290
|
if (/Remove-Item\s+.*-Recurse.*-Force.*(?:[A-Z]:\\(?:\s|$)|\\\*)/i.test(cmd)) {
|
|
1243
1291
|
return deny("Catastrophic deletion blocked");
|
|
1244
1292
|
}
|
|
@@ -1250,12 +1298,31 @@ function blockRmRf(ctx) {
|
|
|
1250
1298
|
function blockForcePush(ctx) {
|
|
1251
1299
|
if (ctx.toolName !== "Bash")
|
|
1252
1300
|
return allow();
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1301
|
+
for (const segment of extractGitPushArgs(getCommand(ctx))) {
|
|
1302
|
+
let sawEndOfOptions = false;
|
|
1303
|
+
for (const token of segment.split(/\s+/)) {
|
|
1304
|
+
if (token === "--") {
|
|
1305
|
+
sawEndOfOptions = true;
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
if (sawEndOfOptions)
|
|
1309
|
+
continue;
|
|
1310
|
+
if (isForcePushFlag(token)) {
|
|
1311
|
+
return deny("Force-pushing is blocked");
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1256
1314
|
}
|
|
1257
1315
|
return allow();
|
|
1258
1316
|
}
|
|
1317
|
+
function isForcePushFlag(token) {
|
|
1318
|
+
if (token === "--force")
|
|
1319
|
+
return true;
|
|
1320
|
+
if (SAFE_FORCE_PREFIXES.some((prefix) => token.startsWith(prefix)))
|
|
1321
|
+
return false;
|
|
1322
|
+
if (token.startsWith("--force"))
|
|
1323
|
+
return true;
|
|
1324
|
+
return SHORT_FLAG_BUNDLE_RE.test(token);
|
|
1325
|
+
}
|
|
1259
1326
|
function blockSecretsWrite(ctx) {
|
|
1260
1327
|
if (ctx.toolName !== "Write")
|
|
1261
1328
|
return allow();
|
|
@@ -1836,7 +1903,7 @@ function registerBuiltinPolicies(enabledNames) {
|
|
|
1836
1903
|
}
|
|
1837
1904
|
}
|
|
1838
1905
|
}
|
|
1839
|
-
var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE, SUDO_RE, PS_ELEVATION_RE, RUNAS_RE, CURL_PIPE_SH_RE, PS_WEB_PIPE_RE,
|
|
1906
|
+
var isClaudeInternalPath, isClaudeSettingsFile, SHELL_OPERATORS, SHELL_METACHAR_RE, JWT_RE, API_KEY_PATTERNS, CONNECTION_STRING_RE, PRIVATE_KEY_RE, BEARER_TOKEN_RE, SQL_TOOL_RE, DESTRUCTIVE_SQL_RE, DELETE_NO_WHERE_RE, SQL_WHERE_RE, SCHEMA_ALTER_RE, PUBLISH_CMD_RE, ENV_PRINTENV_RE, ECHO_ENV_RE, EXPORT_RE, PS_ENV_VAR_RE, PS_CHILDITEM_ENV_RE, DOTNET_GETENV_RE, CMD_ECHO_ENV_RE, ENV_FILE_PATH_RE, ENV_CMD_RE, SUDO_RE, PS_ELEVATION_RE, RUNAS_RE, CURL_PIPE_SH_RE, PS_WEB_PIPE_RE, SHORT_FLAG_BUNDLE_RE, SAFE_FORCE_PREFIXES, SECRET_FILE_RE, SECRET_FILE_ID_RSA_RE, SECRET_FILE_CREDENTIALS_RE, GIT_COMMIT_MERGE_RE, FAILPROOFAI_CLI_RE, FAILPROOFAI_UNINSTALL_RE, GIT_AMEND_RE, GIT_STASH_DROP_RE, GIT_ADD_ALL_RE, NPM_GLOBAL_RE, YARN_GLOBAL_RE, PNPM_GLOBAL_RE, BUN_GLOBAL_RE, CARGO_INSTALL_RE, PIP_SYSTEM_RE, PKG_MANAGER_DETECTORS, NOHUP_RE, SCREEN_DETACH_RE, TMUX_DETACH_RE, DISOWN_RE, BACKGROUND_AMPERSAND_RE, KUBECTL_RE, TERRAFORM_RE, AWS_CLI_RE, GCLOUD_RE, AZ_CLI_RE, HELM_RE, GH_PIPELINE_RE, gitBranchCache, HOME_PREFIX_RE, RM_CMD_RE, FIND_CMD_RE, FIND_EXEC_RE, FIND_GLOBAL_OPT_RE, FIND_EXPR_START_RE, SCRATCH_ROOTS, CATASTROPHIC_DEPTH = 2, READ_LIKE_CMDS, TOOL_CALL_TRACKER_MAX_BYTES = 65536, SEGMENT_SPLIT_RE, BUILTIN_POLICIES;
|
|
1840
1907
|
var init_builtin_policies = __esm(() => {
|
|
1841
1908
|
init_hook_logger();
|
|
1842
1909
|
isClaudeInternalPath = isAgentInternalPath;
|
|
@@ -1878,7 +1945,8 @@ var init_builtin_policies = __esm(() => {
|
|
|
1878
1945
|
RUNAS_RE = /(?:^|;|&&|\|\|)\s*runas\s/i;
|
|
1879
1946
|
CURL_PIPE_SH_RE = /(?:curl|wget)\s.*\|\s*(?:sh|bash|zsh|dash|ksh|csh|tcsh|fish|ash)\b/;
|
|
1880
1947
|
PS_WEB_PIPE_RE = /(?:Invoke-WebRequest|iwr|Invoke-RestMethod|irm)\s+.*\|\s*(?:Invoke-Expression|iex)/i;
|
|
1881
|
-
|
|
1948
|
+
SHORT_FLAG_BUNDLE_RE = /^-[a-zA-Z]*f[a-zA-Z]*$/;
|
|
1949
|
+
SAFE_FORCE_PREFIXES = ["--force-with-lease", "--force-if-includes"];
|
|
1882
1950
|
SECRET_FILE_RE = /\.(?:pem|key)$/;
|
|
1883
1951
|
SECRET_FILE_ID_RSA_RE = /id_rsa/;
|
|
1884
1952
|
SECRET_FILE_CREDENTIALS_RE = /credentials/;
|
|
@@ -1919,6 +1987,13 @@ var init_builtin_policies = __esm(() => {
|
|
|
1919
1987
|
HELM_RE = /(?:^|[;\n]|&&|\|\|?|&)\s*helm(?:\s|$)/;
|
|
1920
1988
|
GH_PIPELINE_RE = /(?:^|[;\n]|&&|\|\|?|&)\s*gh\s+(?:workflow\s+(?:run|enable|disable)|run\s+(?:rerun|cancel)|pr\s+merge|release\s+(?:create|delete)|cache\s+delete|secret\s+(?:set|delete))\b/;
|
|
1921
1989
|
gitBranchCache = new Map;
|
|
1990
|
+
HOME_PREFIX_RE = /^(?:~[A-Za-z0-9_.-]*|\$HOME|\$\{HOME\})(?=$|\/)/;
|
|
1991
|
+
RM_CMD_RE = /^(?:\/\S*\/)?rm$/;
|
|
1992
|
+
FIND_CMD_RE = /^(?:\/\S*\/)?find$/;
|
|
1993
|
+
FIND_EXEC_RE = /^-(?:exec|execdir|ok|okdir)$/;
|
|
1994
|
+
FIND_GLOBAL_OPT_RE = /^-(?:[HLP]|D|O\d*)$/;
|
|
1995
|
+
FIND_EXPR_START_RE = /^(?:-|\\?[(!])/;
|
|
1996
|
+
SCRATCH_ROOTS = ["/tmp", "/var/tmp"];
|
|
1922
1997
|
READ_LIKE_CMDS = /(?:^|;|&&|\|\||\|)\s*(?:ls|find|cat|head|tail|less|more|wc|file|stat|tree|du)\s/;
|
|
1923
1998
|
SEGMENT_SPLIT_RE = /\s*(?:&&|\|\||\||;)\s*/;
|
|
1924
1999
|
BUILTIN_POLICIES = [
|
|
@@ -3435,6 +3510,15 @@ function discoverPolicyFiles(dir) {
|
|
|
3435
3510
|
return [];
|
|
3436
3511
|
}
|
|
3437
3512
|
}
|
|
3513
|
+
function findSkippedPolicyFiles(dir) {
|
|
3514
|
+
if (!existsSync3(dir))
|
|
3515
|
+
return [];
|
|
3516
|
+
try {
|
|
3517
|
+
return readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && LOADABLE_EXT_RE.test(e.name) && !CONVENTION_FILE_RE.test(e.name) && !e.name.endsWith(".d.ts")).map((e) => e.name).sort((a, b) => a.localeCompare(b));
|
|
3518
|
+
} catch {
|
|
3519
|
+
return [];
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3438
3522
|
async function loadSingleFile(absPath, opts) {
|
|
3439
3523
|
const g = globalThis;
|
|
3440
3524
|
g[LOADING_KEY] = true;
|
|
@@ -3477,10 +3561,18 @@ async function loadCustomHooks(customPoliciesPath, opts) {
|
|
|
3477
3561
|
await loadSingleFile(absPath, opts);
|
|
3478
3562
|
return getCustomHooks();
|
|
3479
3563
|
}
|
|
3564
|
+
function warnSkippedPolicyFiles(dir, scope) {
|
|
3565
|
+
const skipped = findSkippedPolicyFiles(dir);
|
|
3566
|
+
if (skipped.length === 0)
|
|
3567
|
+
return;
|
|
3568
|
+
const suggest = (n) => n.replace(/\.(js|mjs|ts)$/, "-policies.$1");
|
|
3569
|
+
hookLogWarn(`${scope} policies: ${skipped.length} file(s) in ${dir} are NOT loaded — ` + `the convention only loads names ending in "policies.js|mjs|ts". ` + skipped.map((n) => `${n} → rename to ${suggest(n)}`).join("; "));
|
|
3570
|
+
}
|
|
3480
3571
|
async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
3481
3572
|
clearCustomHooks();
|
|
3482
3573
|
const conventionSources = [];
|
|
3483
3574
|
const projectRoot = findProjectConfigDir(opts?.sessionCwd ?? process.cwd());
|
|
3575
|
+
const conventionEnabled = opts?.customPoliciesEnabled !== false;
|
|
3484
3576
|
if (customPoliciesPath) {
|
|
3485
3577
|
const absPath = isAbsolute(customPoliciesPath) ? customPoliciesPath : resolve4(projectRoot, customPoliciesPath);
|
|
3486
3578
|
if (existsSync3(absPath)) {
|
|
@@ -3491,7 +3583,9 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3491
3583
|
}
|
|
3492
3584
|
const hooksBeforeConvention = getCustomHooks().length;
|
|
3493
3585
|
const projectDir = resolve4(projectRoot, ".failproofai", "policies");
|
|
3494
|
-
|
|
3586
|
+
if (conventionEnabled)
|
|
3587
|
+
warnSkippedPolicyFiles(projectDir, "project");
|
|
3588
|
+
const projectFiles = conventionEnabled ? discoverPolicyFiles(projectDir) : [];
|
|
3495
3589
|
for (const file of projectFiles) {
|
|
3496
3590
|
const hooksBefore = getCustomHooks().length;
|
|
3497
3591
|
await loadSingleFile(file, { conventionScope: "project" });
|
|
@@ -3505,7 +3599,9 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3505
3599
|
}
|
|
3506
3600
|
}
|
|
3507
3601
|
const userDir = resolve4(homedir4(), ".failproofai", "policies");
|
|
3508
|
-
|
|
3602
|
+
if (conventionEnabled)
|
|
3603
|
+
warnSkippedPolicyFiles(userDir, "user");
|
|
3604
|
+
const userFiles = conventionEnabled ? discoverPolicyFiles(userDir) : [];
|
|
3509
3605
|
for (const file of userFiles) {
|
|
3510
3606
|
const hooksBefore = getCustomHooks().length;
|
|
3511
3607
|
await loadSingleFile(file, { conventionScope: "user" });
|
|
@@ -3520,7 +3616,9 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3520
3616
|
}
|
|
3521
3617
|
const allHooks = getCustomHooks();
|
|
3522
3618
|
const conventionCount = allHooks.length - hooksBeforeConvention;
|
|
3523
|
-
if (
|
|
3619
|
+
if (!conventionEnabled) {
|
|
3620
|
+
hookLogInfo("convention policies: DISABLED via customPoliciesEnabled:false — " + "no .failproofai/policies/ files loaded");
|
|
3621
|
+
} else if (projectFiles.length > 0 || userFiles.length > 0) {
|
|
3524
3622
|
hookLogInfo(`convention policies: ${projectFiles.length} project file(s), ${userFiles.length} user file(s), ${conventionCount} hook(s)`);
|
|
3525
3623
|
}
|
|
3526
3624
|
const hookNameToScope = new Map;
|
|
@@ -3540,7 +3638,7 @@ async function loadAllCustomHooks(customPoliciesPath, opts) {
|
|
|
3540
3638
|
}
|
|
3541
3639
|
return { hooks: allHooks, conventionSources };
|
|
3542
3640
|
}
|
|
3543
|
-
var LOADING_KEY = "__FAILPROOFAI_LOADING_HOOKS__", CONVENTION_FILE_RE;
|
|
3641
|
+
var LOADING_KEY = "__FAILPROOFAI_LOADING_HOOKS__", CONVENTION_FILE_RE, LOADABLE_EXT_RE;
|
|
3544
3642
|
var init_custom_hooks_loader = __esm(() => {
|
|
3545
3643
|
init_hook_logger();
|
|
3546
3644
|
init_custom_hooks_registry();
|
|
@@ -3549,6 +3647,7 @@ var init_custom_hooks_loader = __esm(() => {
|
|
|
3549
3647
|
init_hook_telemetry2();
|
|
3550
3648
|
init_telemetry_id2();
|
|
3551
3649
|
CONVENTION_FILE_RE = /policies\.(js|mjs|ts)$/;
|
|
3650
|
+
LOADABLE_EXT_RE = /\.(js|mjs|ts)$/;
|
|
3552
3651
|
});
|
|
3553
3652
|
|
|
3554
3653
|
// src/hooks/hook-activity-store.ts
|
|
@@ -4761,17 +4860,20 @@ var init_sqlite_reader = () => {};
|
|
|
4761
4860
|
function formatDuration(ms) {
|
|
4762
4861
|
if (ms < 1000)
|
|
4763
4862
|
return `${ms}ms`;
|
|
4764
|
-
const
|
|
4765
|
-
if (
|
|
4766
|
-
return `${
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
const
|
|
4771
|
-
|
|
4863
|
+
const deciseconds = Math.round(ms / 100);
|
|
4864
|
+
if (deciseconds < 600) {
|
|
4865
|
+
return `${(deciseconds / 10).toFixed(1)}s`;
|
|
4866
|
+
}
|
|
4867
|
+
const totalSeconds = Math.round(ms / 1000);
|
|
4868
|
+
if (totalSeconds < 3600) {
|
|
4869
|
+
const minutes2 = Math.floor(totalSeconds / 60);
|
|
4870
|
+
const seconds = totalSeconds % 60;
|
|
4871
|
+
return `${minutes2}m ${seconds}s`;
|
|
4772
4872
|
}
|
|
4773
|
-
const
|
|
4774
|
-
|
|
4873
|
+
const totalMinutes = Math.round(ms / 60000);
|
|
4874
|
+
const hours = Math.floor(totalMinutes / 60);
|
|
4875
|
+
const minutes = totalMinutes % 60;
|
|
4876
|
+
return `${hours}h ${minutes}m`;
|
|
4775
4877
|
}
|
|
4776
4878
|
|
|
4777
4879
|
// lib/hermes-sessions.ts
|
|
@@ -8191,7 +8293,10 @@ async function handleHookEvent(eventType, cli = "claude") {
|
|
|
8191
8293
|
const config = readMergedHooksConfig(session.cwd);
|
|
8192
8294
|
clearPolicies();
|
|
8193
8295
|
registerBuiltinPolicies(config.enabledPolicies);
|
|
8194
|
-
const loadResult = await loadAllCustomHooks(config.customPoliciesPath, {
|
|
8296
|
+
const loadResult = await loadAllCustomHooks(config.customPoliciesPath, {
|
|
8297
|
+
sessionCwd: session.cwd,
|
|
8298
|
+
customPoliciesEnabled: config.customPoliciesEnabled
|
|
8299
|
+
});
|
|
8195
8300
|
const customHooksList = loadResult.hooks;
|
|
8196
8301
|
const conventionHookNames = new Set(loadResult.conventionSources.flatMap((s) => s.hookNames));
|
|
8197
8302
|
for (const hook of customHooksList) {
|
|
@@ -17162,6 +17267,11 @@ import * as readline from "node:readline";
|
|
|
17162
17267
|
function colorsEnabled(out) {
|
|
17163
17268
|
return !!out.isTTY && !process.env.NO_COLOR;
|
|
17164
17269
|
}
|
|
17270
|
+
function brandAnsi(role) {
|
|
17271
|
+
const h = HUES[role];
|
|
17272
|
+
const code = truecolorEnabled() ? `38;2;${h.rgb.join(";")}` : h.basic;
|
|
17273
|
+
return `${ESC}[${code}m`;
|
|
17274
|
+
}
|
|
17165
17275
|
function truecolorEnabled() {
|
|
17166
17276
|
return /truecolor|24bit/i.test(process.env.COLORTERM || "");
|
|
17167
17277
|
}
|
|
@@ -17458,7 +17568,7 @@ function multiSelect(opts) {
|
|
|
17458
17568
|
const choices = opts.choices;
|
|
17459
17569
|
const minSelected = opts.minSelected ?? 0;
|
|
17460
17570
|
const noun = opts.summaryNoun ?? "selected";
|
|
17461
|
-
const checked = choices.map((ch) => !!ch.checked);
|
|
17571
|
+
const checked = choices.map((ch) => ch.locked ? ch.checked ?? true : !!ch.checked);
|
|
17462
17572
|
if (!stdin.isTTY || !stdout.isTTY) {
|
|
17463
17573
|
return Promise.resolve(choices.filter((_, i) => checked[i]).map((ch) => ch.value));
|
|
17464
17574
|
}
|
|
@@ -17474,7 +17584,7 @@ function multiSelect(opts) {
|
|
|
17474
17584
|
renderRow: (index, active, budget) => {
|
|
17475
17585
|
const choice = choices[index];
|
|
17476
17586
|
const caret = active ? c.pink(CARET) : " ";
|
|
17477
|
-
const box = checked[index] ? c.pink(CHECK_ON) : c.dim(CHECK_OFF);
|
|
17587
|
+
const box = choice.locked ? checked[index] ? c.guide(CHECK_ON) : c.dim(CHECK_OFF) : checked[index] ? c.pink(CHECK_ON) : c.dim(CHECK_OFF);
|
|
17478
17588
|
const rawLabel = choice.label.padEnd(nameCol);
|
|
17479
17589
|
const label = active ? c.pinkBold(rawLabel) : checked[index] ? rawLabel : c.dim(rawLabel);
|
|
17480
17590
|
const hint = choice.hint ? ` ${c.dim(ellipsize(choice.hint, budget))}` : "";
|
|
@@ -17484,19 +17594,23 @@ function multiSelect(opts) {
|
|
|
17484
17594
|
footer: opts.hint ?? "↑/↓ move · space select · ctrl+a all · enter confirm",
|
|
17485
17595
|
onKey: (key, cursor2) => {
|
|
17486
17596
|
if (key.name === "space") {
|
|
17597
|
+
if (choices[cursor2]?.locked)
|
|
17598
|
+
return "redraw";
|
|
17487
17599
|
checked[cursor2] = !checked[cursor2];
|
|
17488
17600
|
warn = false;
|
|
17489
17601
|
return "redraw";
|
|
17490
17602
|
}
|
|
17491
17603
|
if (key.ctrl && key.name === "a") {
|
|
17492
|
-
const allOn =
|
|
17493
|
-
for (let i = 0;i < checked.length; i++)
|
|
17494
|
-
checked[i] = !allOn;
|
|
17604
|
+
const allOn = choices.every((ch, i) => checked[i] || ch.locked);
|
|
17605
|
+
for (let i = 0;i < checked.length; i++) {
|
|
17606
|
+
checked[i] = choices[i]?.locked ? true : !allOn;
|
|
17607
|
+
}
|
|
17495
17608
|
return "redraw";
|
|
17496
17609
|
}
|
|
17497
17610
|
if (key.name === "return") {
|
|
17498
17611
|
const selected = choices.filter((_, i) => checked[i]).map((ch) => ch.value);
|
|
17499
|
-
|
|
17612
|
+
const chosen = choices.filter((ch, i) => checked[i] && !ch.locked).length;
|
|
17613
|
+
if (chosen < minSelected) {
|
|
17500
17614
|
warn = true;
|
|
17501
17615
|
return "redraw";
|
|
17502
17616
|
}
|
|
@@ -17504,10 +17618,10 @@ function multiSelect(opts) {
|
|
|
17504
17618
|
}
|
|
17505
17619
|
return;
|
|
17506
17620
|
},
|
|
17507
|
-
summaryFor: (values) => values === null ? "cancelled" : summarize(choices.filter((ch) => values.includes(ch.value)).map((ch) => ch.label), noun)
|
|
17621
|
+
summaryFor: (values) => values === null ? "cancelled" : summarize(choices.filter((ch) => values.includes(ch.value) && !ch.summaryExclude).map((ch) => ch.label), noun)
|
|
17508
17622
|
});
|
|
17509
17623
|
}
|
|
17510
|
-
var ESC = "\x1B", BAR = "│", BAR_END = "└", STEP_ACTIVE = "◆", STEP_DONE = "◇", RADIO_ON = "●", RADIO_OFF = "○", CHECK_ON = "◼", CHECK_OFF = "◻", CARET = "❯", FLOWER = "❋", HUES, LOGO_MIN_COLS = 22, TAGLINE = "end-to-end failure layer for ai agents", LOGO_GRID, LOGO_TEAL, LOGO_PINK, WINDOW = 8;
|
|
17624
|
+
var ESC = "\x1B", BAR = "│", BAR_END = "└", STEP_ACTIVE = "◆", STEP_DONE = "◇", RADIO_ON = "●", RADIO_OFF = "○", CHECK_ON = "◼", CHECK_OFF = "◻", CARET = "❯", FLOWER = "❋", HUES, ANSI_RESET, ANSI_BOLD, ANSI_DIM, LOGO_MIN_COLS = 22, TAGLINE = "end-to-end failure layer for ai agents", LOGO_GRID, LOGO_TEAL, LOGO_PINK, WINDOW = 8;
|
|
17511
17625
|
var init_tui = __esm(() => {
|
|
17512
17626
|
HUES = {
|
|
17513
17627
|
guide: { rgb: [102, 209, 181], basic: "36" },
|
|
@@ -17516,29 +17630,30 @@ var init_tui = __esm(() => {
|
|
|
17516
17630
|
warn: { rgb: [227, 179, 65], basic: "33" },
|
|
17517
17631
|
dim: { rgb: [107, 118, 132], basic: "2" }
|
|
17518
17632
|
};
|
|
17633
|
+
ANSI_RESET = `${ESC}[0m`;
|
|
17634
|
+
ANSI_BOLD = `${ESC}[1m`;
|
|
17635
|
+
ANSI_DIM = `${ESC}[2m`;
|
|
17519
17636
|
LOGO_GRID = [
|
|
17520
|
-
"...tt
|
|
17521
|
-
"..tttt
|
|
17522
|
-
".tttttt
|
|
17523
|
-
".tttttt
|
|
17524
|
-
"..tttt
|
|
17525
|
-
"...tt
|
|
17526
|
-
"
|
|
17527
|
-
"
|
|
17528
|
-
"..pppp
|
|
17529
|
-
"..pppp
|
|
17530
|
-
"..pppp
|
|
17531
|
-
".pppppp
|
|
17532
|
-
".pppppp
|
|
17533
|
-
".pppppp
|
|
17534
|
-
".pppppp
|
|
17535
|
-
"..pppp
|
|
17536
|
-
"..
|
|
17537
|
-
"..
|
|
17538
|
-
"..
|
|
17539
|
-
"..
|
|
17540
|
-
"..ppppppppppppp.",
|
|
17541
|
-
"..ppppppppppppp."
|
|
17637
|
+
"...tt........",
|
|
17638
|
+
"..tttt.......",
|
|
17639
|
+
".tttttt..pppp",
|
|
17640
|
+
".tttttt..pppp",
|
|
17641
|
+
"..tttt...pppp",
|
|
17642
|
+
"...tt....pppp",
|
|
17643
|
+
".........pppp",
|
|
17644
|
+
".........pppp",
|
|
17645
|
+
"..pppp...pppp",
|
|
17646
|
+
"..pppp...pppp",
|
|
17647
|
+
"..pppp...pppp",
|
|
17648
|
+
".pppppp..pppp",
|
|
17649
|
+
".pppppp..pppp",
|
|
17650
|
+
".pppppp..pppp",
|
|
17651
|
+
".pppppp..pppp",
|
|
17652
|
+
"..pppp...pppp",
|
|
17653
|
+
"..ppppppppppp",
|
|
17654
|
+
"..ppppppppppp",
|
|
17655
|
+
"..ppppppppppp",
|
|
17656
|
+
"..ppppppppppp"
|
|
17542
17657
|
];
|
|
17543
17658
|
LOGO_TEAL = HUES.guide.rgb;
|
|
17544
17659
|
LOGO_PINK = HUES.logoPink.rgb;
|
|
@@ -19259,11 +19374,12 @@ async function runAuthCli(args) {
|
|
|
19259
19374
|
return runLogout();
|
|
19260
19375
|
return runWhoami();
|
|
19261
19376
|
}
|
|
19262
|
-
var HELP, LEGACY_FLAG_TO_SUB, SUBCOMMANDS, DIM
|
|
19377
|
+
var HELP, LEGACY_FLAG_TO_SUB, SUBCOMMANDS, COLOR, DIM, RESET, PINK, GREEN, RED;
|
|
19263
19378
|
var init_cli = __esm(() => {
|
|
19264
19379
|
init_api_server_client();
|
|
19265
19380
|
init_auth_store();
|
|
19266
19381
|
init_cli_error();
|
|
19382
|
+
init_tui();
|
|
19267
19383
|
init_hook_telemetry2();
|
|
19268
19384
|
init_telemetry_id2();
|
|
19269
19385
|
HELP = `
|
|
@@ -19292,6 +19408,12 @@ EXAMPLES
|
|
|
19292
19408
|
"--whoami": "whoami"
|
|
19293
19409
|
};
|
|
19294
19410
|
SUBCOMMANDS = new Set(["login", "logout", "whoami", "help"]);
|
|
19411
|
+
COLOR = colorsEnabled(process.stdout);
|
|
19412
|
+
DIM = COLOR ? ANSI_DIM : "";
|
|
19413
|
+
RESET = COLOR ? ANSI_RESET : "";
|
|
19414
|
+
PINK = COLOR ? brandAnsi("pink") : "";
|
|
19415
|
+
GREEN = COLOR ? brandAnsi("guide") : "";
|
|
19416
|
+
RED = COLOR ? brandAnsi("warn") : "";
|
|
19295
19417
|
});
|
|
19296
19418
|
|
|
19297
19419
|
// lib/claude-sessions.ts
|
|
@@ -21665,7 +21787,7 @@ async function runAuditCli(args) {
|
|
|
21665
21787
|
const { launch: launch2 } = await Promise.resolve().then(() => (init_launch(), exports_launch));
|
|
21666
21788
|
launch2("start");
|
|
21667
21789
|
}
|
|
21668
|
-
var DASHBOARD_PORT = 8020, AUDIT_STAGES, HELP2, RESET2
|
|
21790
|
+
var DASHBOARD_PORT = 8020, AUDIT_STAGES, HELP2, RESET2, DIM2, BOLD, PINK2, GREEN2, CYAN, SPINNER;
|
|
21669
21791
|
var init_cli2 = __esm(() => {
|
|
21670
21792
|
init_audit();
|
|
21671
21793
|
init_dashboard_cache();
|
|
@@ -21673,6 +21795,7 @@ var init_cli2 = __esm(() => {
|
|
|
21673
21795
|
init_telemetry_id2();
|
|
21674
21796
|
init_telemetry_sanitize();
|
|
21675
21797
|
init_open_browser();
|
|
21798
|
+
init_tui();
|
|
21676
21799
|
AUDIT_STAGES = [
|
|
21677
21800
|
{ label: "discovering transcripts", detail: "walking ~/.claude, ~/.codex, ~/.cursor, …" },
|
|
21678
21801
|
{ label: "parsing session logs", detail: "reading JSONL + sqlite session stores" },
|
|
@@ -21696,6 +21819,12 @@ WHAT IT DOES
|
|
|
21696
21819
|
Runs fully offline — no account or network required. Press Ctrl+C to stop the
|
|
21697
21820
|
dashboard server when you're done.
|
|
21698
21821
|
`.trimStart();
|
|
21822
|
+
RESET2 = ANSI_RESET;
|
|
21823
|
+
DIM2 = ANSI_DIM;
|
|
21824
|
+
BOLD = ANSI_BOLD;
|
|
21825
|
+
PINK2 = brandAnsi("pink");
|
|
21826
|
+
GREEN2 = brandAnsi("guide");
|
|
21827
|
+
CYAN = brandAnsi("guide");
|
|
21699
21828
|
SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
21700
21829
|
});
|
|
21701
21830
|
|
|
@@ -22225,7 +22354,7 @@ async function runAuditCli2(args) {
|
|
|
22225
22354
|
const { launch: launch2 } = await Promise.resolve().then(() => (init_launch(), exports_launch));
|
|
22226
22355
|
launch2("start");
|
|
22227
22356
|
}
|
|
22228
|
-
var DASHBOARD_PORT2 = 8020, AUDIT_STAGES2, HELP3, RESET3
|
|
22357
|
+
var DASHBOARD_PORT2 = 8020, AUDIT_STAGES2, HELP3, RESET3, DIM3, BOLD2, PINK3, GREEN3, CYAN2, SPINNER2;
|
|
22229
22358
|
var init_cli3 = __esm(() => {
|
|
22230
22359
|
init_audit();
|
|
22231
22360
|
init_dashboard_cache();
|
|
@@ -22233,6 +22362,7 @@ var init_cli3 = __esm(() => {
|
|
|
22233
22362
|
init_telemetry_id2();
|
|
22234
22363
|
init_telemetry_sanitize();
|
|
22235
22364
|
init_open_browser();
|
|
22365
|
+
init_tui();
|
|
22236
22366
|
AUDIT_STAGES2 = [
|
|
22237
22367
|
{ label: "discovering transcripts", detail: "walking ~/.claude, ~/.codex, ~/.cursor, …" },
|
|
22238
22368
|
{ label: "parsing session logs", detail: "reading JSONL + sqlite session stores" },
|
|
@@ -22256,23 +22386,32 @@ WHAT IT DOES
|
|
|
22256
22386
|
Runs fully offline — no account or network required. Press Ctrl+C to stop the
|
|
22257
22387
|
dashboard server when you're done.
|
|
22258
22388
|
`.trimStart();
|
|
22389
|
+
RESET3 = ANSI_RESET;
|
|
22390
|
+
DIM3 = ANSI_DIM;
|
|
22391
|
+
BOLD2 = ANSI_BOLD;
|
|
22392
|
+
PINK3 = brandAnsi("pink");
|
|
22393
|
+
GREEN3 = brandAnsi("guide");
|
|
22394
|
+
CYAN2 = brandAnsi("guide");
|
|
22259
22395
|
SPINNER2 = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
22260
22396
|
});
|
|
22261
22397
|
|
|
22262
22398
|
// src/hooks/configure-wizard.ts
|
|
22263
22399
|
var exports_configure_wizard = {};
|
|
22264
22400
|
__export(exports_configure_wizard, {
|
|
22401
|
+
setCustomPoliciesEnabled: () => setCustomPoliciesEnabled,
|
|
22265
22402
|
runConfigureWizard: () => runConfigureWizard,
|
|
22266
22403
|
reviewLines: () => reviewLines,
|
|
22267
22404
|
resolvePresetSelection: () => resolvePresetSelection,
|
|
22268
22405
|
maybeFirstRunConfigure: () => maybeFirstRunConfigure,
|
|
22269
22406
|
markLauncherSeen: () => markLauncherSeen,
|
|
22270
22407
|
hasSeenLauncher: () => hasSeenLauncher,
|
|
22408
|
+
describeCustomPolicies: () => describeCustomPolicies,
|
|
22409
|
+
clisSupportingScope: () => clisSupportingScope,
|
|
22271
22410
|
buildScopeChoices: () => buildScopeChoices,
|
|
22272
22411
|
buildPresetChoices: () => buildPresetChoices,
|
|
22273
22412
|
buildAgentChoices: () => buildAgentChoices
|
|
22274
22413
|
});
|
|
22275
|
-
import { existsSync as existsSync19, mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "node:fs";
|
|
22414
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync10, writeFileSync as writeFileSync9, readFileSync as readFileSync16 } from "node:fs";
|
|
22276
22415
|
import { homedir as homedir30 } from "node:os";
|
|
22277
22416
|
import { resolve as resolve16, sep as sep5 } from "node:path";
|
|
22278
22417
|
async function emit(event, props) {
|
|
@@ -22302,6 +22441,9 @@ function buildScopeChoices(cwd) {
|
|
|
22302
22441
|
}
|
|
22303
22442
|
];
|
|
22304
22443
|
}
|
|
22444
|
+
function clisSupportingScope(scope) {
|
|
22445
|
+
return INTEGRATION_TYPES.filter((id) => getIntegration(id).scopes.includes(scope));
|
|
22446
|
+
}
|
|
22305
22447
|
function buildAgentChoices(scope, cwd) {
|
|
22306
22448
|
const detected = new Set(detectInstalledClis());
|
|
22307
22449
|
const ordered = [
|
|
@@ -22311,6 +22453,17 @@ function buildAgentChoices(scope, cwd) {
|
|
|
22311
22453
|
return ordered.map((id) => {
|
|
22312
22454
|
const integration = getIntegration(id);
|
|
22313
22455
|
const isDetected = detected.has(id);
|
|
22456
|
+
const supported = integration.scopes.includes(scope);
|
|
22457
|
+
if (!supported) {
|
|
22458
|
+
return {
|
|
22459
|
+
label: integration.displayName,
|
|
22460
|
+
value: id,
|
|
22461
|
+
checked: false,
|
|
22462
|
+
locked: true,
|
|
22463
|
+
section: "Global only · not configurable per-project",
|
|
22464
|
+
hint: `supports ${integration.scopes.join(", ")} scope — rerun with "Everywhere I code"`
|
|
22465
|
+
};
|
|
22466
|
+
}
|
|
22314
22467
|
let installedHere = false;
|
|
22315
22468
|
try {
|
|
22316
22469
|
installedHere = integration.hooksInstalledInSettings(scope, cwd);
|
|
@@ -22326,28 +22479,102 @@ function buildAgentChoices(scope, cwd) {
|
|
|
22326
22479
|
};
|
|
22327
22480
|
});
|
|
22328
22481
|
}
|
|
22329
|
-
function buildPresetChoices() {
|
|
22330
|
-
const choices = POLICY_PRESETS.map((p) => ({
|
|
22482
|
+
function buildPresetChoices(cwd = process.cwd(), enabled = true) {
|
|
22483
|
+
const choices = POLICY_PRESETS.map((p) => ({
|
|
22484
|
+
label: p.label,
|
|
22485
|
+
value: p.id,
|
|
22486
|
+
hint: p.description
|
|
22487
|
+
}));
|
|
22331
22488
|
choices.push({
|
|
22332
22489
|
label: "Everything",
|
|
22333
22490
|
value: EVERYTHING,
|
|
22334
22491
|
hint: `all ${resolveEverything().length} policies`
|
|
22335
22492
|
});
|
|
22493
|
+
const custom = describeCustomPolicies(cwd);
|
|
22494
|
+
const skipped = custom.warnings.length;
|
|
22495
|
+
const plural = (n) => `${n} file${n === 1 ? "" : "s"}`;
|
|
22496
|
+
const skippedNote = skipped > 0 ? ` · ${skipped} skipped, see next screen` : "";
|
|
22497
|
+
if (custom.fileCount > 0) {
|
|
22498
|
+
choices.push({
|
|
22499
|
+
label: "Custom",
|
|
22500
|
+
value: CUSTOM,
|
|
22501
|
+
checked: enabled,
|
|
22502
|
+
hint: `${plural(custom.fileCount)} in ${custom.scopes.join(" + ")}${skippedNote}`
|
|
22503
|
+
});
|
|
22504
|
+
} else {
|
|
22505
|
+
choices.push({
|
|
22506
|
+
label: "Custom",
|
|
22507
|
+
value: CUSTOM,
|
|
22508
|
+
locked: true,
|
|
22509
|
+
checked: false,
|
|
22510
|
+
summaryExclude: true,
|
|
22511
|
+
hint: skipped > 0 ? `${plural(skipped)} found but NOT loaded — see next screen` : "none yet · drop *-policies.mjs in .failproofai/policies/"
|
|
22512
|
+
});
|
|
22513
|
+
}
|
|
22336
22514
|
return choices;
|
|
22337
22515
|
}
|
|
22338
22516
|
function resolvePresetSelection(values) {
|
|
22339
|
-
|
|
22517
|
+
const selected = values.filter((v) => v !== CUSTOM);
|
|
22518
|
+
if (selected.includes(EVERYTHING))
|
|
22340
22519
|
return resolveEverything();
|
|
22341
|
-
return [...new Set(
|
|
22520
|
+
return [...new Set(selected.flatMap((id) => resolvePreset(id)))];
|
|
22521
|
+
}
|
|
22522
|
+
function setCustomPoliciesEnabled(scope, cwd, enabled) {
|
|
22523
|
+
if (enabled === undefined)
|
|
22524
|
+
return;
|
|
22525
|
+
const path3 = getConfigPathForScope(scope, cwd);
|
|
22526
|
+
let config = {};
|
|
22527
|
+
try {
|
|
22528
|
+
if (existsSync19(path3))
|
|
22529
|
+
config = JSON.parse(readFileSync16(path3, "utf8"));
|
|
22530
|
+
} catch {
|
|
22531
|
+
return;
|
|
22532
|
+
}
|
|
22533
|
+
if (enabled)
|
|
22534
|
+
delete config.customPoliciesEnabled;
|
|
22535
|
+
else
|
|
22536
|
+
config.customPoliciesEnabled = false;
|
|
22537
|
+
try {
|
|
22538
|
+
writeFileSync9(path3, JSON.stringify(config, null, 2) + `
|
|
22539
|
+
`, "utf8");
|
|
22540
|
+
} catch {}
|
|
22541
|
+
}
|
|
22542
|
+
function describeCustomPolicies(cwd) {
|
|
22543
|
+
const active = [];
|
|
22544
|
+
const warnings = [];
|
|
22545
|
+
const scopes = [];
|
|
22546
|
+
let fileCount = 0;
|
|
22547
|
+
const dirs = [
|
|
22548
|
+
{ dir: resolve16(cwd, ".failproofai", "policies"), label: "project" },
|
|
22549
|
+
{ dir: resolve16(homedir30(), ".failproofai", "policies"), label: "global" }
|
|
22550
|
+
];
|
|
22551
|
+
for (const { dir, label } of dirs) {
|
|
22552
|
+
const found = discoverPolicyFiles(dir);
|
|
22553
|
+
if (found.length > 0) {
|
|
22554
|
+
active.push(`${found.length} file${found.length === 1 ? "" : "s"} (${label})`);
|
|
22555
|
+
scopes.push(label);
|
|
22556
|
+
fileCount += found.length;
|
|
22557
|
+
}
|
|
22558
|
+
for (const name of findSkippedPolicyFiles(dir)) {
|
|
22559
|
+
warnings.push(`! ${homeify(resolve16(dir, name))} is NOT loaded — rename to ` + `${name.replace(/\.(js|mjs|ts)$/, "-policies.$1")}`);
|
|
22560
|
+
}
|
|
22561
|
+
}
|
|
22562
|
+
return { active, warnings, fileCount, scopes };
|
|
22342
22563
|
}
|
|
22343
22564
|
function reviewLines(state) {
|
|
22344
|
-
const { scope, clis, policies, cwd } = state;
|
|
22565
|
+
const { scope, clis, policies, cwd, customEnabled } = state;
|
|
22345
22566
|
const where = scope === "project" ? `This project (${homeify(cwd)})` : "Everywhere (global)";
|
|
22346
22567
|
const lines = [];
|
|
22347
22568
|
const assistantNames = clis.map((c3) => getIntegration(c3).displayName);
|
|
22348
22569
|
lines.push(` Where : ${where}`);
|
|
22349
22570
|
lines.push(` Assistants : ${assistantNames.length ? summarize(assistantNames, "assistants") : "(none)"}`);
|
|
22350
22571
|
lines.push(` Policies : ${policies.length} enabled`);
|
|
22572
|
+
const custom = describeCustomPolicies(cwd);
|
|
22573
|
+
if (custom.active.length > 0) {
|
|
22574
|
+
lines.push(` Custom : ${custom.active.join(" · ")} ${customEnabled === false ? "— DISABLED, will not load" : DIM_NOTE}`);
|
|
22575
|
+
}
|
|
22576
|
+
for (const warning of custom.warnings)
|
|
22577
|
+
lines.push(` ${warning}`);
|
|
22351
22578
|
lines.push("");
|
|
22352
22579
|
lines.push(" This will update:");
|
|
22353
22580
|
for (const cli of clis) {
|
|
@@ -22437,7 +22664,8 @@ Use the flag form instead, e.g.:
|
|
|
22437
22664
|
{
|
|
22438
22665
|
label: "Everything available",
|
|
22439
22666
|
value: ALL_CLIS,
|
|
22440
|
-
hint: `protect all ${
|
|
22667
|
+
hint: `protect all ${clisSupportingScope(scope).length} CLIs configurable here`,
|
|
22668
|
+
summaryExclude: true
|
|
22441
22669
|
},
|
|
22442
22670
|
...buildAgentChoices(scope, cwd)
|
|
22443
22671
|
],
|
|
@@ -22449,10 +22677,14 @@ Use the flag form instead, e.g.:
|
|
|
22449
22677
|
});
|
|
22450
22678
|
if (clisSel === null)
|
|
22451
22679
|
return cancel();
|
|
22452
|
-
const
|
|
22680
|
+
const supported = new Set(clisSupportingScope(scope));
|
|
22681
|
+
const clis = (clisSel.includes(ALL_CLIS) ? [...INTEGRATION_TYPES] : clisSel.filter((v) => v !== ALL_CLIS)).filter((id) => supported.has(id));
|
|
22682
|
+
const customEnabledBefore = readHooksConfig().customPoliciesEnabled !== false;
|
|
22683
|
+
const presetChoices = buildPresetChoices(cwd, customEnabledBefore);
|
|
22684
|
+
const hasCustomFiles = describeCustomPolicies(cwd).fileCount > 0;
|
|
22453
22685
|
const presets = await multiSelect({
|
|
22454
22686
|
message: "What should we guard against?",
|
|
22455
|
-
choices:
|
|
22687
|
+
choices: presetChoices,
|
|
22456
22688
|
minSelected: 1,
|
|
22457
22689
|
summaryNoun: "bundles",
|
|
22458
22690
|
hint: "space toggles · combine presets · ↵ confirm",
|
|
@@ -22462,9 +22694,10 @@ Use the flag form instead, e.g.:
|
|
|
22462
22694
|
if (presets === null)
|
|
22463
22695
|
return cancel();
|
|
22464
22696
|
const policies = resolvePresetSelection(presets);
|
|
22697
|
+
const customEnabled = hasCustomFiles ? presets.includes(CUSTOM) : undefined;
|
|
22465
22698
|
const decision = await selectOne({
|
|
22466
22699
|
message: "Ready to apply?",
|
|
22467
|
-
body: reviewLines({ scope, clis, policies, cwd }),
|
|
22700
|
+
body: reviewLines({ scope, clis, policies, cwd, customEnabled }),
|
|
22468
22701
|
choices: [
|
|
22469
22702
|
{ label: "Yes, apply now", value: "apply", hint: "write the config" },
|
|
22470
22703
|
{ label: "Cancel", value: "cancel", hint: "quit, no changes" }
|
|
@@ -22482,13 +22715,15 @@ Use the flag form instead, e.g.:
|
|
|
22482
22715
|
source: presets.join("+")
|
|
22483
22716
|
});
|
|
22484
22717
|
await installHooks2(policies, scope, cwd, false, "configure-wizard", undefined, false, clis, { replace: true, quiet: true });
|
|
22718
|
+
setCustomPoliciesEnabled(scope, cwd, customEnabled);
|
|
22485
22719
|
await applied;
|
|
22486
22720
|
markLauncherSeen();
|
|
22487
|
-
const
|
|
22488
|
-
|
|
22721
|
+
const customNote = customEnabled === true ? " + your custom policies" : customEnabled === false ? " · custom policies DISABLED" : "";
|
|
22722
|
+
const assistants = `${clis.length} assistant${clis.length === 1 ? "" : "s"}`;
|
|
22723
|
+
outro(`Setup complete — ${policies.length} policies${customNote} · ${assistants}`, { ok: true }, stdout);
|
|
22489
22724
|
return { applied: true, scope, clis, policies };
|
|
22490
22725
|
}
|
|
22491
|
-
var EVERYTHING = "__everything__", ALL_CLIS = "__all_clis__";
|
|
22726
|
+
var EVERYTHING = "__everything__", ALL_CLIS = "__all_clis__", CUSTOM = "__custom__", DIM_NOTE = "(auto-loaded)";
|
|
22492
22727
|
var init_configure_wizard = __esm(() => {
|
|
22493
22728
|
init_tui();
|
|
22494
22729
|
init_integrations();
|
|
@@ -22496,6 +22731,7 @@ var init_configure_wizard = __esm(() => {
|
|
|
22496
22731
|
init_manager2();
|
|
22497
22732
|
init_hooks_config();
|
|
22498
22733
|
init_policy_presets();
|
|
22734
|
+
init_custom_hooks_loader();
|
|
22499
22735
|
init_hook_telemetry2();
|
|
22500
22736
|
init_telemetry_id2();
|
|
22501
22737
|
});
|
|
@@ -22621,7 +22857,7 @@ import { realpathSync as realpathSync4 } from "fs";
|
|
|
22621
22857
|
import { dirname as dirname9, resolve as resolve18 } from "path";
|
|
22622
22858
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
22623
22859
|
// package.json
|
|
22624
|
-
var version = "0.0.14
|
|
22860
|
+
var version = "0.0.14";
|
|
22625
22861
|
|
|
22626
22862
|
// bin/failproofai.mjs
|
|
22627
22863
|
if (!process.env.FAILPROOFAI_PACKAGE_ROOT) {
|