failproofai 1.0.0-beta.12 → 1.0.0-beta.13
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 +2 -3
- 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 +2 -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 +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +2 -2
- 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.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js +3 -2
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/reminder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js +2 -2
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.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 +2 -3
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +4 -4
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +10 -10
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -3
- 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 +10 -10
- package/.next/standalone/.next/server/app/policies/page.js +2 -3
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +3 -4
- 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 +3 -4
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +3 -4
- 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/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js +2 -3
- 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/{[root-of-the-server]__1a7i2q4._.js → [root-of-the-server]__00ni9za._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08y94xv._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__094p1f1._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0xu5z._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ed01_d._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__1_ps0jw._.js → [root-of-the-server]__0effm9m._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0lk_935._.js → [root-of-the-server]__0ix8gm7._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0ky_n0r._.js → [root-of-the-server]__0ji11a-._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0v2fpxe._.js → [root-of-the-server]__0ojwjxl._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vb5fl2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ibjy5x._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tvn4wf._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1uyc-z4._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__20d06rh._.js +3 -0
- package/.next/standalone/.next/server/chunks/_0lxbzdq._.js +1 -3
- package/.next/standalone/.next/server/chunks/_1zuiiy3._.js +1 -3
- 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]__1rdruw4._.js → [root-of-the-server]__0_1tiya._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0ha3gul._.js → [root-of-the-server]__0eeipso._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0spkm68._.js +3 -3
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1tyf0tc._.js → [root-of-the-server]__17itmx-._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1io8n-9._.js → [root-of-the-server]__1dx-a-c._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1mmefsr._.js +5 -0
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1yw368c._.js → [root-of-the-server]__1n2vcv4._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1rv-sc9._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__1a2hcb_._.js → [root-of-the-server]__1tlvv9a._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0rjgfln._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_1fahg9e._.js → _0vo2qyt._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0uz7o9y._.js → _0xej-0e._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_04mekdy._.js → _10399ge._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_0se484m._.js → _149k9oy._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1vsgpqt._.js → _166jvu8._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/{_0r-dsre._.js → _1_hwp06._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1w8sola._.js → _1mnhi_r._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1w_6p9g._.js → _1ror7k9._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{_1gmzkwj._.js → _1sdgprl._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/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 +15 -15
- package/.next/standalone/.next/static/chunks/{2_h--2ame3r83.js → 01s3vpzky_qew.js} +1 -1
- package/.next/standalone/.next/static/chunks/0km-jn9o5xyqs.css +2 -0
- package/.next/standalone/.next/static/chunks/{23hp7hekegpe5.js → 0zbcd_n8ku2ov.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0cakk77ppmlo7.js → 1erji0ratofla.js} +1 -1
- package/.next/standalone/.next/static/chunks/{40-zk44qsg5y-.js → 23hnlzqx44vbe.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1wb8cnmzx69rz.js → 2cwsiyhc7d2cw.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0_rdbv_k5j51p.js → 2y42ebzynyxdv.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1spk1bub0vd-h.js → 315lncj7dsp9c.js} +1 -1
- package/.next/standalone/.next/static/chunks/{0-zh1umoq6ppc.js → 31_px0dfgdg9j.js} +2 -2
- package/.next/standalone/.next/static/chunks/{2bie7ajv70p9b.js → 3l4-fu3xt75j8.js} +1 -1
- package/.next/standalone/.next/static/chunks/{298v78ypf8edl.js → 3poscoxn69x9g.js} +1 -1
- package/.next/standalone/app/policies/hooks-client.tsx +4 -4
- package/.next/standalone/ino.ujh3/.failproofai/VERSION +4 -0
- package/.next/standalone/ino.ujh3/.failproofai/state/last-version +1 -0
- package/.next/standalone/ino.ujh3/.failproofai/state/telemetry-id +1 -0
- package/.next/standalone/package.json +10 -10
- package/.next/standalone/server.js +1 -1
- package/bin/failproofai.mjs +186 -5
- package/dist/cli.mjs +1130 -1352
- package/dist/worker.mjs +107 -1000
- package/package.json +10 -10
- package/src/hooks/backfill-cli.ts +1 -1
- package/src/hooks/cloud-connection.ts +4 -4
- package/src/hooks/cloud-enrollment-cli.ts +1 -1
- package/src/hooks/cloud-enrollment.ts +3 -3
- package/src/hooks/cloud-managed-policies.ts +60 -22
- package/src/hooks/configure-wizard.ts +124 -53
- package/src/hooks/custom-hooks-loader.ts +57 -8
- package/src/hooks/daemon-service.ts +66 -11
- package/src/hooks/flush-cli.ts +180 -0
- package/src/hooks/fp-config.ts +242 -118
- package/src/hooks/fp-home.ts +138 -22
- package/src/hooks/fp-reset.ts +357 -43
- package/src/hooks/handler.ts +11 -11
- package/src/hooks/harness-cli.ts +309 -0
- package/src/hooks/hook-activity-store.ts +5 -5
- package/src/hooks/manager.ts +35 -0
- package/src/hooks/onboarding-attempt.ts +22 -6
- package/src/hooks/tui.ts +64 -7
- package/src/hooks/uninstall-cli.ts +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__06hexd0._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1iny24d._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tyedjt._.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +0 -5
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1u-wx42._.js +0 -4
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +0 -5
- package/.next/standalone/.next/static/chunks/13vrxdsdihqd_.css +0 -2
- /package/.next/standalone/.next/static/{-3gDrXYxNRTVwrFnqXAWd → ziAsXfNE0cH_S7LHK-Py3}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{-3gDrXYxNRTVwrFnqXAWd → ziAsXfNE0cH_S7LHK-Py3}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{-3gDrXYxNRTVwrFnqXAWd → ziAsXfNE0cH_S7LHK-Py3}/_ssgManifest.js +0 -0
package/bin/failproofai.mjs
CHANGED
|
@@ -271,7 +271,7 @@ if (hookIdx >= 0) {
|
|
|
271
271
|
*/
|
|
272
272
|
async function runCli() {
|
|
273
273
|
// --help / -h (only when not inside a subcommand that handles its own --help)
|
|
274
|
-
const SUBCOMMANDS = ["policies", "policy", "audit", "config", "uninstall", "backfill"];
|
|
274
|
+
const SUBCOMMANDS = ["policies", "policy", "audit", "config", "uninstall", "backfill", "flush", "harness"];
|
|
275
275
|
if ((args.includes("--help") || args.includes("-h")) && !SUBCOMMANDS.includes(args[0])) {
|
|
276
276
|
const extraArgs = args.filter((a) => a !== "--help" && a !== "-h");
|
|
277
277
|
if (extraArgs.length > 0) {
|
|
@@ -286,6 +286,13 @@ USAGE
|
|
|
286
286
|
COMMANDS
|
|
287
287
|
(no args) Launch the policy dashboard
|
|
288
288
|
config Interactive setup — pick scope, agents & policies
|
|
289
|
+
--connect <url> --token <key> Connect to Failproof Cloud non-interactively
|
|
290
|
+
--machine-id <id> Stable id for this machine
|
|
291
|
+
--machine-label <name> Human-readable name in the dashboard
|
|
292
|
+
--no-transcripts Report decisions only, never transcripts
|
|
293
|
+
--disconnect Stop pulling policy and sending activity
|
|
294
|
+
--status Show connection, daemon and pause state
|
|
295
|
+
--pause / --resume Pause or resume enforcement
|
|
289
296
|
|
|
290
297
|
policy add <name> Enable a single policy (see \`policy --help\`)
|
|
291
298
|
policy remove <name> Disable a single policy
|
|
@@ -312,10 +319,30 @@ COMMANDS
|
|
|
312
319
|
|
|
313
320
|
policies --help, -h Show this help for the policies command
|
|
314
321
|
|
|
322
|
+
harness list Show extra capture paths per agent CLI
|
|
323
|
+
harness add-path <h> <path> Also capture sessions from <path> for harness
|
|
324
|
+
<h>. Accepts \`<label>=<path>\`; the label
|
|
325
|
+
namespaces agent ids so two copies of one
|
|
326
|
+
project stay distinct.
|
|
327
|
+
harness remove-path <h> <p> Stop capturing that path
|
|
328
|
+
harness --help, -h Show this help for the harness command
|
|
329
|
+
|
|
315
330
|
audit Audit your agent's behavior, then open the
|
|
316
331
|
dashboard at http://localhost:8020/audit
|
|
317
332
|
audit --help, -h Show this help for the audit command
|
|
318
333
|
|
|
334
|
+
backfill Re-send history the collector already read past
|
|
335
|
+
— after clearing the dashboard, re-enrolling a
|
|
336
|
+
machine, or connecting later than the work
|
|
337
|
+
--since <when> How far back: 30d, 6m, or YYYY-MM-DD
|
|
338
|
+
(default: 30 days)
|
|
339
|
+
--dry-run Report what would be re-read, change nothing
|
|
340
|
+
|
|
341
|
+
flush Deliver everything already spooled, now,
|
|
342
|
+
instead of waiting for the next sweep
|
|
343
|
+
--wait Block until the spool drains (or --timeout)
|
|
344
|
+
--timeout <secs> How long to wait with --wait (default: 60)
|
|
345
|
+
|
|
319
346
|
uninstall Remove failproofai from this machine: hook
|
|
320
347
|
entries from every agent CLI, and the daemon
|
|
321
348
|
service. Run this BEFORE \`npm rm -g failproofai\`
|
|
@@ -355,6 +382,10 @@ EXAMPLES
|
|
|
355
382
|
failproofai policies --uninstall --cli opencode
|
|
356
383
|
failproofai policies --uninstall --cli pi
|
|
357
384
|
failproofai policies --uninstall --custom
|
|
385
|
+
failproofai backfill --since 6m
|
|
386
|
+
failproofai backfill --dry-run
|
|
387
|
+
failproofai flush --wait
|
|
388
|
+
failproofai config --status
|
|
358
389
|
|
|
359
390
|
LINKS
|
|
360
391
|
⭐ Star us: https://github.com/failproofai/failproofai
|
|
@@ -419,8 +450,12 @@ LINKS
|
|
|
419
450
|
const isHelpOrVersion =
|
|
420
451
|
args.includes("--help") || args.includes("-h") || args.includes("--version") || args.includes("-v");
|
|
421
452
|
if (args[0] === "audit" && args.includes("--scheduled")) {
|
|
422
|
-
|
|
423
|
-
|
|
453
|
+
// NOT `layoutWarningForHook` — that one answers the hook's question
|
|
454
|
+
// ("are policies unenforced?") and deliberately stays quiet when the
|
|
455
|
+
// global config is readable. This gate is about the LAYOUT, and must
|
|
456
|
+
// fire whenever completing the run would reset the home.
|
|
457
|
+
const { layoutBlockerForScheduledRun } = await import("../src/hooks/fp-reset");
|
|
458
|
+
const warning = layoutBlockerForScheduledRun();
|
|
424
459
|
if (warning) {
|
|
425
460
|
// Exit 1, not 75: 75 means "another audit holds the lock" and is retried
|
|
426
461
|
// in fifteen minutes, which here would just re-warn four times an hour
|
|
@@ -487,6 +522,72 @@ LINKS
|
|
|
487
522
|
// over. Every precondition a person can get wrong is still checked HERE,
|
|
488
523
|
// synchronously, because reporting success and leaving the real failure in the
|
|
489
524
|
// journal is what already cost twenty minutes on a live machine.
|
|
525
|
+
if (args[0] === "flush") {
|
|
526
|
+
const subArgs = args.slice(1);
|
|
527
|
+
if (subArgs.includes("--help") || subArgs.includes("-h")) {
|
|
528
|
+
console.log(`
|
|
529
|
+
failproofai flush — deliver what is already spooled, now
|
|
530
|
+
|
|
531
|
+
USAGE
|
|
532
|
+
failproofai flush [--wait] [--timeout <secs>]
|
|
533
|
+
|
|
534
|
+
WHY
|
|
535
|
+
The collector is unhurried on purpose: a batch is swept once it is older than
|
|
536
|
+
two minutes, at most 64 per pass, on a 60-second cadence. That pacing keeps a
|
|
537
|
+
backlog from stampeding the server, and it is exactly wrong when you are
|
|
538
|
+
standing at a dashboard waiting to see your own events — "not delivered yet"
|
|
539
|
+
and "not working" look identical from there.
|
|
540
|
+
|
|
541
|
+
This asks the daemon to make a pass right now, with no minimum age and no
|
|
542
|
+
per-pass cap. It re-sends nothing: only batches already spooled and not yet
|
|
543
|
+
delivered. For history the collector has already read past, use \`backfill\`.
|
|
544
|
+
|
|
545
|
+
OPTIONS
|
|
546
|
+
--wait Block until the spool drains, or --timeout elapses.
|
|
547
|
+
--timeout <secs> How long --wait waits. Default: 60.
|
|
548
|
+
`);
|
|
549
|
+
process.exit(0);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const KNOWN = new Set(["--wait", "--timeout"]);
|
|
553
|
+
const unknown = subArgs.find(
|
|
554
|
+
(a, i) => a.startsWith("-") && !KNOWN.has(a) && subArgs[i - 1] !== "--timeout",
|
|
555
|
+
);
|
|
556
|
+
if (unknown) {
|
|
557
|
+
throw new CliError(`Unexpected argument: ${unknown}\nRun \`failproofai flush --help\` for usage.`);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
let timeoutSecs;
|
|
561
|
+
const tIdx = subArgs.indexOf("--timeout");
|
|
562
|
+
if (tIdx >= 0) {
|
|
563
|
+
const raw = subArgs[tIdx + 1];
|
|
564
|
+
if (!raw || raw.startsWith("-")) throw new CliError("Missing value after --timeout.");
|
|
565
|
+
const n = Number(raw);
|
|
566
|
+
// Rejected rather than coerced: NaN would silently become "wait forever
|
|
567
|
+
// or not at all" depending on the comparison, and neither is what was asked.
|
|
568
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
569
|
+
throw new CliError(`Could not read --timeout ${raw}. Give a number of seconds.`);
|
|
570
|
+
}
|
|
571
|
+
timeoutSecs = n;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
lastSubcommand = "flush";
|
|
575
|
+
const { runFlushCommand } = await import("../src/hooks/flush-cli");
|
|
576
|
+
const result = await runFlushCommand({ wait: subArgs.includes("--wait"), timeoutSecs });
|
|
577
|
+
for (const line of result.lines) {
|
|
578
|
+
if (result.exitCode === 0) console.log(line);
|
|
579
|
+
else console.error(line);
|
|
580
|
+
}
|
|
581
|
+
await track("cli_flush", {
|
|
582
|
+
ok: result.exitCode === 0,
|
|
583
|
+
waited: subArgs.includes("--wait"),
|
|
584
|
+
pending: result.pending,
|
|
585
|
+
});
|
|
586
|
+
lastSubcommand = null;
|
|
587
|
+
await exitAfterFlush(result.exitCode);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
|
|
490
591
|
if (args[0] === "backfill") {
|
|
491
592
|
const subArgs = args.slice(1);
|
|
492
593
|
if (subArgs.includes("--help") || subArgs.includes("-h")) {
|
|
@@ -557,6 +658,80 @@ OPTIONS
|
|
|
557
658
|
return;
|
|
558
659
|
}
|
|
559
660
|
|
|
661
|
+
// harness list | add-path | remove-path
|
|
662
|
+
//
|
|
663
|
+
// Extra capture paths per harness. Writes ~/.failproofai/config.toml and
|
|
664
|
+
// nothing else — no root, no daemon call — so it works on a machine whose
|
|
665
|
+
// daemon is stopped, which is when someone is most likely to be fixing what
|
|
666
|
+
// it captures.
|
|
667
|
+
if (args[0] === "harness") {
|
|
668
|
+
const subArgs = args.slice(1);
|
|
669
|
+
if (subArgs.length === 0 || subArgs.includes("--help") || subArgs.includes("-h")) {
|
|
670
|
+
console.log(`
|
|
671
|
+
failproofai harness — capture sessions from more than one location per agent CLI
|
|
672
|
+
|
|
673
|
+
USAGE
|
|
674
|
+
failproofai harness list [<harness>]
|
|
675
|
+
failproofai harness add-path <harness> [<label>=]<path>
|
|
676
|
+
failproofai harness remove-path <harness> <path|label>
|
|
677
|
+
|
|
678
|
+
WHY
|
|
679
|
+
Each agent CLI is watched wherever its own installer put it — ~/.claude/projects,
|
|
680
|
+
~/.hermes/state.db, and so on. That misses every other arrangement: a second
|
|
681
|
+
profile, a mounted team share, a container's home beside the host's, an agent
|
|
682
|
+
an operator moved. Those hold real sessions and nothing collects them.
|
|
683
|
+
|
|
684
|
+
THE LABEL
|
|
685
|
+
An entry is \`<path>\` or \`<label>=<path>\`. The label namespaces agent ids as
|
|
686
|
+
<label>-<agentId>, and it matters: two locations holding the same project
|
|
687
|
+
derive the SAME id (it comes from the cwd inside the transcript, identical in
|
|
688
|
+
both copies), so without a label they merge into one agent whose sessions
|
|
689
|
+
interleave from two machines' worth of history. Omit it and one is derived
|
|
690
|
+
from the folder name.
|
|
691
|
+
|
|
692
|
+
HARNESSES
|
|
693
|
+
claude, codex, copilot, openclaw, pi, factory, antigravity, cursor,
|
|
694
|
+
goose, opencode, devin, hermes
|
|
695
|
+
|
|
696
|
+
\`claude\` covers subagent transcripts too — they live under the same root.
|
|
697
|
+
|
|
698
|
+
NOTES
|
|
699
|
+
• Session collection must be on for any of this to be read; extra paths follow
|
|
700
|
+
[collector] in ~/.failproofai/config.toml like the default ones do.
|
|
701
|
+
• A path overlapping one already captured is REFUSED by the daemon at startup
|
|
702
|
+
rather than collected twice under two ids. It says so in the journal.
|
|
703
|
+
• Takes effect within seconds — the daemon re-reads config.toml on an interval
|
|
704
|
+
and cycles its collector. No restart, no sudo.
|
|
705
|
+
|
|
706
|
+
EXAMPLES
|
|
707
|
+
failproofai harness add-path claude work=/srv/team/.claude/projects
|
|
708
|
+
failproofai harness add-path hermes prod=/srv/hermes-prod/state.db
|
|
709
|
+
failproofai harness add-path codex /mnt/other-home/.codex/sessions
|
|
710
|
+
failproofai harness list
|
|
711
|
+
failproofai harness remove-path claude work
|
|
712
|
+
`.trimStart());
|
|
713
|
+
process.exit(0);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
lastSubcommand = "harness";
|
|
717
|
+
const { runHarnessCommand } = await import("../src/hooks/harness-cli");
|
|
718
|
+
const result = runHarnessCommand(subArgs);
|
|
719
|
+
for (const line of result.lines) {
|
|
720
|
+
if (result.exitCode === 0) console.log(line);
|
|
721
|
+
else console.error(line);
|
|
722
|
+
}
|
|
723
|
+
await track("cli_harness", {
|
|
724
|
+
ok: result.exitCode === 0,
|
|
725
|
+
// The subcommand only — never the harness name, the label or the path.
|
|
726
|
+
// A path is a value the user typed, and `enterprise-docs/product-analytics.md`
|
|
727
|
+
// promises we send shape, never value.
|
|
728
|
+
sub: ["list", "add-path", "remove-path"].includes(subArgs[0]) ? subArgs[0] : "unknown",
|
|
729
|
+
});
|
|
730
|
+
lastSubcommand = null;
|
|
731
|
+
await exitAfterFlush(result.exitCode);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
|
|
560
735
|
// uninstall [--purge] [--dry-run] [--yes|-y]
|
|
561
736
|
//
|
|
562
737
|
// Top-level, and deliberately NOT a flag on `policies`. `policies --uninstall`
|
|
@@ -1115,7 +1290,7 @@ USAGE
|
|
|
1115
1290
|
WHAT IT DOES
|
|
1116
1291
|
Walks you through 4 quick steps and writes everything for you:
|
|
1117
1292
|
1. Where — global (all projects) or just this project
|
|
1118
|
-
2.
|
|
1293
|
+
2. Harnesses — which agent CLIs to protect (Claude, Codex, ...)
|
|
1119
1294
|
3. Policies — presets (combine any), Everything, or a custom pick
|
|
1120
1295
|
4. Review — confirms the exact files it will change, then applies
|
|
1121
1296
|
|
|
@@ -1124,7 +1299,13 @@ FAILPROOF CLOUD
|
|
|
1124
1299
|
Connect this machine to Failproof Cloud
|
|
1125
1300
|
[--no-transcripts] decisions only, no transcripts
|
|
1126
1301
|
failproofai config --disconnect Stop pulling policy and sending activity
|
|
1127
|
-
failproofai config --status Show connection and pause state
|
|
1302
|
+
failproofai config --status Show connection, daemon and pause state
|
|
1303
|
+
failproofai config --pause [--session <id>]
|
|
1304
|
+
Pause enforcement, time-boxed
|
|
1305
|
+
failproofai config --resume [--all]
|
|
1306
|
+
Resume enforcement
|
|
1307
|
+
|
|
1308
|
+
--machine-label <name> Human-readable name in the dashboard
|
|
1128
1309
|
|
|
1129
1310
|
One connection, two capabilities: this machine PULLS centrally-managed
|
|
1130
1311
|
policies and SENDS what its hooks decided, so the dashboard shows the fleet
|