finitemonkey 0.1.0-next.16 → 0.1.0-next.17
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/README.es.md +1 -0
- package/README.md +1 -0
- package/README.pt-BR.md +1 -0
- package/dist/finitemonkey.mjs +851 -389
- package/package.json +1 -1
package/dist/finitemonkey.mjs
CHANGED
|
@@ -69,7 +69,7 @@ var resolveWindowsCommand = (command, env, exists) => {
|
|
|
69
69
|
}
|
|
70
70
|
return { command, shell: false };
|
|
71
71
|
};
|
|
72
|
-
var windowsCommandLine = (resolved,
|
|
72
|
+
var windowsCommandLine = (resolved, args2) => [quoteForCmd(resolved.command), ...args2.map(quoteForCmd)].join(" ");
|
|
73
73
|
|
|
74
74
|
// src/core/node-exec.ts
|
|
75
75
|
var SHELL_NOT_FOUND = /* @__PURE__ */ new Set([127, 9009]);
|
|
@@ -117,9 +117,9 @@ var nodeAppendText = (path, content) => {
|
|
|
117
117
|
return reject(error instanceof Error ? error.message : String(error));
|
|
118
118
|
}
|
|
119
119
|
};
|
|
120
|
-
var nodeSpawnSelf = (selfPath) => (
|
|
120
|
+
var nodeSpawnSelf = (selfPath) => (args2, cwd) => {
|
|
121
121
|
try {
|
|
122
|
-
const child2 = spawn(process.execPath, [selfPath, ...
|
|
122
|
+
const child2 = spawn(process.execPath, [selfPath, ...args2], {
|
|
123
123
|
cwd,
|
|
124
124
|
detached: true,
|
|
125
125
|
stdio: "ignore",
|
|
@@ -290,8 +290,8 @@ import { createInterface } from "node:readline";
|
|
|
290
290
|
var MAX_BUFFER2 = 256 * 1024 * 1024;
|
|
291
291
|
var GIT_ENV = { ...process.env, GIT_PAGER: "cat", GIT_TERMINAL_PROMPT: "0", LC_ALL: "C" };
|
|
292
292
|
var notFound = (error) => error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
293
|
-
var nodeGit = (
|
|
294
|
-
const result = spawnSync2("git", [...
|
|
293
|
+
var nodeGit = (args2, cwd) => {
|
|
294
|
+
const result = spawnSync2("git", [...args2], {
|
|
295
295
|
cwd,
|
|
296
296
|
encoding: "utf8",
|
|
297
297
|
maxBuffer: MAX_BUFFER2,
|
|
@@ -305,8 +305,8 @@ var nodeGit = (args, cwd) => {
|
|
|
305
305
|
stdout: typeof stdout === "string" ? stdout : ""
|
|
306
306
|
};
|
|
307
307
|
};
|
|
308
|
-
var nodeGitLines = (
|
|
309
|
-
const child2 = spawn2("git", [...
|
|
308
|
+
var nodeGitLines = (args2, cwd, onLine) => new Promise((resolve2) => {
|
|
309
|
+
const child2 = spawn2("git", [...args2], {
|
|
310
310
|
cwd,
|
|
311
311
|
windowsHide: true,
|
|
312
312
|
env: GIT_ENV,
|
|
@@ -323,8 +323,8 @@ var nodeGitLines = (args, cwd, onLine) => new Promise((resolve2) => {
|
|
|
323
323
|
});
|
|
324
324
|
});
|
|
325
325
|
var textOf = (value) => typeof value === "string" ? value : "";
|
|
326
|
-
var nodeGitWith = (
|
|
327
|
-
const result = spawnSync2("git", [...
|
|
326
|
+
var nodeGitWith = (args2, cwd, options) => {
|
|
327
|
+
const result = spawnSync2("git", [...args2], {
|
|
328
328
|
cwd,
|
|
329
329
|
encoding: "utf8",
|
|
330
330
|
maxBuffer: MAX_BUFFER2,
|
|
@@ -350,15 +350,15 @@ var errnoCode2 = (error) => {
|
|
|
350
350
|
if (!(error instanceof Error) || !("code" in error)) return void 0;
|
|
351
351
|
return typeof error.code === "string" ? error.code : void 0;
|
|
352
352
|
};
|
|
353
|
-
var spawnProbe = (command,
|
|
353
|
+
var spawnProbe = (command, args2, timeout) => {
|
|
354
354
|
const options = { encoding: "utf8", timeout, windowsHide: true };
|
|
355
|
-
return process.platform === "win32" ? spawnSync3([command, ...
|
|
355
|
+
return process.platform === "win32" ? spawnSync3([command, ...args2].join(" "), { ...options, shell: true }) : spawnSync3(command, [...args2], options);
|
|
356
356
|
};
|
|
357
|
-
var nodeProbe = (command,
|
|
358
|
-
if (![command, ...
|
|
357
|
+
var nodeProbe = (command, args2, timeoutMs) => {
|
|
358
|
+
if (![command, ...args2].every((token) => SAFE_TOKEN.test(token))) {
|
|
359
359
|
return { found: false, ok: false, stdout: "", timedOut: false };
|
|
360
360
|
}
|
|
361
|
-
const result = spawnProbe(command,
|
|
361
|
+
const result = spawnProbe(command, args2, timeoutMs);
|
|
362
362
|
const code = errnoCode2(result.error);
|
|
363
363
|
const stdout = result.stdout;
|
|
364
364
|
return {
|
|
@@ -409,14 +409,155 @@ var nodeRuntime = () => ({
|
|
|
409
409
|
exec: nodeExec,
|
|
410
410
|
appendText: nodeAppendText,
|
|
411
411
|
spawnSelf: nodeSpawnSelf(SELF_PATH),
|
|
412
|
+
execSelf: (args2, cwd, timeoutMs) => nodeExec({ command: process.execPath, args: [SELF_PATH, ...args2], cwd, timeoutMs }),
|
|
412
413
|
gitWith: nodeGitWith,
|
|
413
414
|
realpath: nodeRealpath,
|
|
414
415
|
homeDir: homedir,
|
|
415
416
|
systemLocale: () => Intl.DateTimeFormat().resolvedOptions().locale
|
|
416
417
|
});
|
|
417
418
|
|
|
418
|
-
// src/
|
|
419
|
-
import {
|
|
419
|
+
// src/app/node-process.ts
|
|
420
|
+
import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
|
|
421
|
+
import { connect } from "node:net";
|
|
422
|
+
var MAX_OUTPUT = 64 * 1024;
|
|
423
|
+
var POLL_MS = 150;
|
|
424
|
+
var STOP_GRACE_MS = 3e3;
|
|
425
|
+
var sleep = (ms) => new Promise((resolve2) => {
|
|
426
|
+
setTimeout(resolve2, ms);
|
|
427
|
+
});
|
|
428
|
+
var portOpen = (host, port) => new Promise((resolve2) => {
|
|
429
|
+
const socket = connect({ host, port });
|
|
430
|
+
const done = (open) => {
|
|
431
|
+
socket.destroy();
|
|
432
|
+
resolve2(open);
|
|
433
|
+
};
|
|
434
|
+
socket.setTimeout(1e3, () => {
|
|
435
|
+
done(false);
|
|
436
|
+
});
|
|
437
|
+
socket.once("connect", () => {
|
|
438
|
+
done(true);
|
|
439
|
+
});
|
|
440
|
+
socket.once("error", () => {
|
|
441
|
+
done(false);
|
|
442
|
+
});
|
|
443
|
+
});
|
|
444
|
+
var startApp = (command, cwd, port) => {
|
|
445
|
+
const child2 = spawn3(command, {
|
|
446
|
+
cwd,
|
|
447
|
+
shell: true,
|
|
448
|
+
detached: process.platform !== "win32",
|
|
449
|
+
windowsHide: true,
|
|
450
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
451
|
+
env: { ...process.env, PORT: String(port) }
|
|
452
|
+
});
|
|
453
|
+
let output = "";
|
|
454
|
+
let exit;
|
|
455
|
+
const collect4 = (chunk) => {
|
|
456
|
+
output = `${output}${chunk.toString("utf8")}`.slice(-MAX_OUTPUT);
|
|
457
|
+
};
|
|
458
|
+
child2.stdout.on("data", collect4);
|
|
459
|
+
child2.stderr.on("data", collect4);
|
|
460
|
+
child2.once("error", (error) => {
|
|
461
|
+
output = `${output}${error.message}`;
|
|
462
|
+
exit = { code: null };
|
|
463
|
+
});
|
|
464
|
+
child2.once("exit", (code) => {
|
|
465
|
+
exit = { code };
|
|
466
|
+
});
|
|
467
|
+
return { child: child2, output: () => output, exited: () => exit };
|
|
468
|
+
};
|
|
469
|
+
var waitForPort = async (app, host, port, deadline) => {
|
|
470
|
+
while (Date.now() < deadline) {
|
|
471
|
+
if (await portOpen(host, port)) return "open";
|
|
472
|
+
if (app.exited() !== void 0) return "exited";
|
|
473
|
+
await sleep(POLL_MS);
|
|
474
|
+
}
|
|
475
|
+
return "timeout";
|
|
476
|
+
};
|
|
477
|
+
var signalGroup = (pid, signal) => {
|
|
478
|
+
try {
|
|
479
|
+
process.kill(-pid, signal);
|
|
480
|
+
} catch {
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
var alive = (pid) => {
|
|
485
|
+
try {
|
|
486
|
+
process.kill(-pid, 0);
|
|
487
|
+
return true;
|
|
488
|
+
} catch {
|
|
489
|
+
return false;
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
var stopApp = async (app) => {
|
|
493
|
+
const pid = app.child.pid;
|
|
494
|
+
if (pid === void 0) return true;
|
|
495
|
+
if (process.platform === "win32") {
|
|
496
|
+
spawnSync4("taskkill", ["/pid", String(pid), "/T", "/F"], { windowsHide: true, stdio: "ignore" });
|
|
497
|
+
return true;
|
|
498
|
+
}
|
|
499
|
+
signalGroup(pid, "SIGTERM");
|
|
500
|
+
const deadline = Date.now() + STOP_GRACE_MS;
|
|
501
|
+
while (alive(pid) && Date.now() < deadline) await sleep(POLL_MS);
|
|
502
|
+
if (alive(pid)) signalGroup(pid, "SIGKILL");
|
|
503
|
+
return !alive(pid);
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// src/app/node-probe.ts
|
|
507
|
+
var BODY_EXCERPT = 200;
|
|
508
|
+
var MAX_BODY = 256 * 1024;
|
|
509
|
+
var url = (request) => {
|
|
510
|
+
const host = request.host.includes(":") ? `[${request.host}]` : request.host;
|
|
511
|
+
return `http://${host}:${String(request.port)}${request.route.startsWith("/") ? "" : "/"}${request.route}`;
|
|
512
|
+
};
|
|
513
|
+
var ask = async (request, deadline) => {
|
|
514
|
+
try {
|
|
515
|
+
const response = await fetch(url(request), {
|
|
516
|
+
redirect: "manual",
|
|
517
|
+
signal: AbortSignal.timeout(Math.max(1e3, deadline - Date.now()))
|
|
518
|
+
});
|
|
519
|
+
const body2 = (await response.text()).slice(0, MAX_BODY);
|
|
520
|
+
const excerpt = body2.slice(0, BODY_EXCERPT);
|
|
521
|
+
if (response.status !== request.status)
|
|
522
|
+
return { kind: "wrong_status", status: response.status, bodyExcerpt: excerpt };
|
|
523
|
+
if (request.body !== void 0 && !body2.includes(request.body)) {
|
|
524
|
+
return { kind: "body_mismatch", status: response.status, bodyExcerpt: excerpt };
|
|
525
|
+
}
|
|
526
|
+
return { kind: "ok", status: response.status };
|
|
527
|
+
} catch (error) {
|
|
528
|
+
return { kind: "request_failed", bodyExcerpt: error instanceof Error ? error.message : String(error) };
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
var finish = async (app, answer, started) => {
|
|
532
|
+
const stopped = app === void 0 ? true : await stopApp(app);
|
|
533
|
+
return {
|
|
534
|
+
...answer,
|
|
535
|
+
reused: app === void 0,
|
|
536
|
+
output: app?.output() ?? "",
|
|
537
|
+
stopped,
|
|
538
|
+
durationMs: Date.now() - started
|
|
539
|
+
};
|
|
540
|
+
};
|
|
541
|
+
var probeApp = async (request) => {
|
|
542
|
+
const started = Date.now();
|
|
543
|
+
const deadline = started + request.timeoutMs;
|
|
544
|
+
if (await portOpen(request.host, request.port)) return finish(void 0, await ask(request, deadline), started);
|
|
545
|
+
if (request.start === void 0) return finish(void 0, { kind: "no_start" }, started);
|
|
546
|
+
const app = startApp(request.start, request.cwd, request.port);
|
|
547
|
+
const port = await waitForPort(app, request.host, request.port, deadline);
|
|
548
|
+
if (port === "exited") return finish(app, { kind: "crashed", exitCode: app.exited()?.code ?? null }, started);
|
|
549
|
+
if (port === "timeout") return finish(app, { kind: "no_port" }, started);
|
|
550
|
+
return finish(app, await ask(request, deadline), started);
|
|
551
|
+
};
|
|
552
|
+
|
|
553
|
+
// src/app/types.ts
|
|
554
|
+
var DEFAULT_HOST = "127.0.0.1";
|
|
555
|
+
var DEFAULT_ROUTE = "/";
|
|
556
|
+
var DEFAULT_STATUS = 200;
|
|
557
|
+
var DEFAULT_APP_TIMEOUT_S = 60;
|
|
558
|
+
|
|
559
|
+
// src/core/args.ts
|
|
560
|
+
import { parseArgs } from "node:util";
|
|
420
561
|
|
|
421
562
|
// src/exit-codes.ts
|
|
422
563
|
var ExitCode = {
|
|
@@ -444,6 +585,89 @@ var exitCodeDocs = {
|
|
|
444
585
|
5: "exit.internal"
|
|
445
586
|
};
|
|
446
587
|
|
|
588
|
+
// src/core/problem.ts
|
|
589
|
+
var usageProblem = (code, messageKey, fix, params2 = {}) => ({
|
|
590
|
+
code,
|
|
591
|
+
messageKey,
|
|
592
|
+
params: params2,
|
|
593
|
+
fix,
|
|
594
|
+
exitCode: ExitCode.Usage
|
|
595
|
+
});
|
|
596
|
+
var needsPersonProblem = (messageKey, fix, params2 = {}) => ({
|
|
597
|
+
code: "needs_confirmation",
|
|
598
|
+
messageKey,
|
|
599
|
+
params: params2,
|
|
600
|
+
fix,
|
|
601
|
+
exitCode: ExitCode.NeedsPerson
|
|
602
|
+
});
|
|
603
|
+
var FmError = class extends Error {
|
|
604
|
+
problem;
|
|
605
|
+
constructor(problem4) {
|
|
606
|
+
super(problem4.code);
|
|
607
|
+
this.name = "FmError";
|
|
608
|
+
this.problem = problem4;
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
// src/core/args.ts
|
|
613
|
+
var GLOBAL_OPTIONS = {
|
|
614
|
+
json: { type: "boolean" },
|
|
615
|
+
lang: { type: "string" },
|
|
616
|
+
yes: { type: "boolean", short: "y" },
|
|
617
|
+
"dry-run": { type: "boolean" },
|
|
618
|
+
version: { type: "boolean", short: "v" },
|
|
619
|
+
help: { type: "boolean", short: "h" }
|
|
620
|
+
};
|
|
621
|
+
var flag = (values, name) => values[name] === true;
|
|
622
|
+
var looseArgs = (argv) => {
|
|
623
|
+
const { values, positionals } = parseArgs({
|
|
624
|
+
args: [...argv],
|
|
625
|
+
options: GLOBAL_OPTIONS,
|
|
626
|
+
strict: false,
|
|
627
|
+
allowPositionals: true
|
|
628
|
+
});
|
|
629
|
+
const lang = values.lang;
|
|
630
|
+
return {
|
|
631
|
+
positionals,
|
|
632
|
+
json: flag(values, "json"),
|
|
633
|
+
yes: flag(values, "yes"),
|
|
634
|
+
dryRun: flag(values, "dry-run"),
|
|
635
|
+
version: flag(values, "version"),
|
|
636
|
+
help: flag(values, "help"),
|
|
637
|
+
lang: typeof lang === "string" ? lang : void 0
|
|
638
|
+
};
|
|
639
|
+
};
|
|
640
|
+
var resolveCommand = (registry, positionals) => registry.filter((spec2) => spec2.path.every((part2, index) => positionals[index] === part2)).reduce(
|
|
641
|
+
(best, spec2) => best === void 0 || spec2.path.length > best.consumed ? { spec: spec2, consumed: spec2.path.length } : best,
|
|
642
|
+
void 0
|
|
643
|
+
);
|
|
644
|
+
var strictArgs = (argv, spec2) => {
|
|
645
|
+
const fix = `finitemonkey help ${spec2.path.join(" ")}`;
|
|
646
|
+
let parsed;
|
|
647
|
+
try {
|
|
648
|
+
parsed = parseArgs({
|
|
649
|
+
args: [...argv],
|
|
650
|
+
options: { ...GLOBAL_OPTIONS, ...spec2.options },
|
|
651
|
+
strict: true,
|
|
652
|
+
allowPositionals: true
|
|
653
|
+
});
|
|
654
|
+
} catch (error) {
|
|
655
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
656
|
+
return reject(usageProblem("invalid_arguments", "error.invalid_arguments", fix, { detail }));
|
|
657
|
+
}
|
|
658
|
+
const rest = parsed.positionals.slice(spec2.path.length);
|
|
659
|
+
const max = spec2.maxPositionals ?? 0;
|
|
660
|
+
const extra = rest[max];
|
|
661
|
+
if (extra !== void 0) {
|
|
662
|
+
return reject(usageProblem("unexpected_argument", "error.unexpected_argument", fix, { argument: extra }));
|
|
663
|
+
}
|
|
664
|
+
return accept({ values: parsed.values, positionals: rest });
|
|
665
|
+
};
|
|
666
|
+
var stringOption = (values, name) => {
|
|
667
|
+
const value = values[name];
|
|
668
|
+
return typeof value === "string" ? value : void 0;
|
|
669
|
+
};
|
|
670
|
+
|
|
447
671
|
// src/core/result.ts
|
|
448
672
|
var SCHEMA_VERSION = 1;
|
|
449
673
|
var success = (data, human2 = []) => ({
|
|
@@ -468,6 +692,87 @@ var toEnvelope = (command, result) => ({
|
|
|
468
692
|
...result.next === void 0 ? {} : { next: result.next }
|
|
469
693
|
});
|
|
470
694
|
|
|
695
|
+
// src/commands/app-check.ts
|
|
696
|
+
var APP_CHECK_SCHEMA = "finitemonkey/app-check@1";
|
|
697
|
+
var positive = (raw, fallback) => {
|
|
698
|
+
if (raw === void 0) return fallback;
|
|
699
|
+
const value = Number(raw);
|
|
700
|
+
return Number.isInteger(value) && value > 0 ? value : void 0;
|
|
701
|
+
};
|
|
702
|
+
var requestFrom = (ctx, values) => {
|
|
703
|
+
const port = positive(stringOption(values, "port"), 0);
|
|
704
|
+
const status = positive(stringOption(values, "status"), DEFAULT_STATUS);
|
|
705
|
+
const timeout = positive(stringOption(values, "timeout"), DEFAULT_APP_TIMEOUT_S);
|
|
706
|
+
if (port === void 0 || port === 0 || port > 65535 || status === void 0 || timeout === void 0)
|
|
707
|
+
return void 0;
|
|
708
|
+
return {
|
|
709
|
+
host: stringOption(values, "host") ?? DEFAULT_HOST,
|
|
710
|
+
port,
|
|
711
|
+
route: stringOption(values, "route") ?? DEFAULT_ROUTE,
|
|
712
|
+
status,
|
|
713
|
+
body: stringOption(values, "body"),
|
|
714
|
+
start: stringOption(values, "start"),
|
|
715
|
+
cwd: ctx.cwd,
|
|
716
|
+
timeoutMs: timeout * 1e3
|
|
717
|
+
};
|
|
718
|
+
};
|
|
719
|
+
var humanLine = (ctx, data) => ctx.t(`app.check.${data.kind}`, {
|
|
720
|
+
url: data.url,
|
|
721
|
+
status: data.status ?? 0,
|
|
722
|
+
code: data.exitCode ?? -1
|
|
723
|
+
});
|
|
724
|
+
var toResult = (ctx, request, data) => {
|
|
725
|
+
const human2 = [humanLine(ctx, data)];
|
|
726
|
+
if (data.kind === "ok") return success(data, human2);
|
|
727
|
+
return {
|
|
728
|
+
ok: false,
|
|
729
|
+
exitCode: ExitCode.CheckFailed,
|
|
730
|
+
data,
|
|
731
|
+
human: human2,
|
|
732
|
+
error: {
|
|
733
|
+
code: "app_check_failed",
|
|
734
|
+
message: human2.join(" "),
|
|
735
|
+
fix: `finitemonkey app check --port ${String(request.port)}`
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
};
|
|
739
|
+
var appCheckCommand = {
|
|
740
|
+
path: ["app", "check"],
|
|
741
|
+
summaryKey: "command.app_check.summary",
|
|
742
|
+
usage: "finitemonkey app check --port <n> [--start <command>] [--route <path>] [--status <code>] [--body <text>] [--timeout <seconds>] [--host <host>]",
|
|
743
|
+
status: "ready",
|
|
744
|
+
options: {
|
|
745
|
+
port: { type: "string" },
|
|
746
|
+
start: { type: "string" },
|
|
747
|
+
route: { type: "string" },
|
|
748
|
+
status: { type: "string" },
|
|
749
|
+
body: { type: "string" },
|
|
750
|
+
timeout: { type: "string" },
|
|
751
|
+
host: { type: "string" }
|
|
752
|
+
},
|
|
753
|
+
run: async (ctx, args2) => {
|
|
754
|
+
const request = requestFrom(ctx, args2.values);
|
|
755
|
+
if (request === void 0) {
|
|
756
|
+
return {
|
|
757
|
+
ok: false,
|
|
758
|
+
exitCode: ExitCode.Usage,
|
|
759
|
+
human: [ctx.t("app.check.usage")],
|
|
760
|
+
error: {
|
|
761
|
+
code: "app_check_failed",
|
|
762
|
+
message: ctx.t("app.check.usage"),
|
|
763
|
+
fix: "finitemonkey app check --port 3000"
|
|
764
|
+
}
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
const result = await probeApp(request);
|
|
768
|
+
const url2 = `http://${request.host}:${String(request.port)}${request.route}`;
|
|
769
|
+
return toResult(ctx, request, { schema: APP_CHECK_SCHEMA, url: url2, ...result });
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
|
|
773
|
+
// src/commands/doctor.ts
|
|
774
|
+
import { dirname as dirname7 } from "node:path";
|
|
775
|
+
|
|
471
776
|
// src/install/apply.ts
|
|
472
777
|
import { dirname as dirname3 } from "node:path";
|
|
473
778
|
|
|
@@ -512,12 +817,12 @@ var parseAdded = (value) => {
|
|
|
512
817
|
const deny2 = strings(value["deny"]);
|
|
513
818
|
const { schema, attribution } = value;
|
|
514
819
|
if (deny2 === void 0 || typeof schema !== "boolean" || typeof attribution !== "boolean") return void 0;
|
|
515
|
-
const
|
|
820
|
+
const ask2 = strings(value["ask"]) ?? [];
|
|
516
821
|
const blockReads = value["blockReads"] === true;
|
|
517
822
|
const marketplace = value["marketplace"] === true;
|
|
518
823
|
const plugin = value["plugin"] === true;
|
|
519
824
|
const language = value["language"];
|
|
520
|
-
const added = { schema, attribution, deny: deny2, ask, blockReads, marketplace, plugin };
|
|
825
|
+
const added = { schema, attribution, deny: deny2, ask: ask2, blockReads, marketplace, plugin };
|
|
521
826
|
return typeof language === "string" ? { ...added, language } : added;
|
|
522
827
|
};
|
|
523
828
|
var parseEntry = (value) => {
|
|
@@ -837,8 +1142,8 @@ var execForm = (runner, event) => {
|
|
|
837
1142
|
};
|
|
838
1143
|
var hookHandler = (runner, spec2, failClosedSupported) => {
|
|
839
1144
|
const failure4 = spec2.guard && failClosedSupported ? { onFailure: "block" } : {};
|
|
840
|
-
const { command, args } = execForm(runner, spec2.event);
|
|
841
|
-
return { type: "command", command, args, timeout: spec2.timeout, ...failure4 };
|
|
1145
|
+
const { command, args: args2 } = execForm(runner, spec2.event);
|
|
1146
|
+
return { type: "command", command, args: args2, timeout: spec2.timeout, ...failure4 };
|
|
842
1147
|
};
|
|
843
1148
|
var OWN_SHELL = /(^|[\s/"'])finitemonkey(@[^\s"]+|\.mjs|\.cmd|\.exe)?"?\s+hook\s/;
|
|
844
1149
|
var OWN_SCRIPT = /finitemonkey(\.mjs|\.cmd|\.exe)?$/;
|
|
@@ -847,19 +1152,19 @@ var isOwnHandler = (handler) => {
|
|
|
847
1152
|
if (!isRecord(handler)) return false;
|
|
848
1153
|
const command = handler["command"];
|
|
849
1154
|
if (typeof command !== "string") return false;
|
|
850
|
-
const
|
|
851
|
-
if (
|
|
852
|
-
const hookAt =
|
|
1155
|
+
const args2 = stringsOf(handler["args"]);
|
|
1156
|
+
if (args2.length === 0) return OWN_SHELL.test(`${command} `);
|
|
1157
|
+
const hookAt = args2.indexOf("hook");
|
|
853
1158
|
if (hookAt < 0) return false;
|
|
854
|
-
const target = hookAt === 0 ? command :
|
|
1159
|
+
const target = hookAt === 0 ? command : args2[hookAt - 1] ?? "";
|
|
855
1160
|
return OWN_SCRIPT.test(target);
|
|
856
1161
|
};
|
|
857
1162
|
|
|
858
1163
|
// src/install/skill-template.ts
|
|
859
|
-
var cliCommand = (runner,
|
|
860
|
-
if (runner.kind === "local") return `node ${LOCAL_BIN} ${
|
|
861
|
-
if (runner.kind === "vendored") return `node ${VENDOR_BIN} ${
|
|
862
|
-
return isScript(runner.path) ? `node "${runner.path}" ${
|
|
1164
|
+
var cliCommand = (runner, args2) => {
|
|
1165
|
+
if (runner.kind === "local") return `node ${LOCAL_BIN} ${args2}`;
|
|
1166
|
+
if (runner.kind === "vendored") return `node ${VENDOR_BIN} ${args2}`;
|
|
1167
|
+
return isScript(runner.path) ? `node "${runner.path}" ${args2}` : `"${runner.path}" ${args2}`;
|
|
863
1168
|
};
|
|
864
1169
|
var verifySkillTemplate = (runner, lang) => {
|
|
865
1170
|
const skill = TEMPLATES[lang].verifySkill;
|
|
@@ -1258,7 +1563,7 @@ var mergeSettings = (current2, wanted, recorded) => {
|
|
|
1258
1563
|
const existingDeny = asList(permissions["deny"]);
|
|
1259
1564
|
const existingAsk = asList(permissions["ask"]);
|
|
1260
1565
|
const deny2 = missing(wanted.deny, existingDeny);
|
|
1261
|
-
const
|
|
1566
|
+
const ask2 = missing(wanted.ask, existingAsk);
|
|
1262
1567
|
const blockReads = !(BLOCK_READS in permissions);
|
|
1263
1568
|
const attribution = wanted.attributionOff && !("attribution" in base);
|
|
1264
1569
|
const marketplace = wanted.marketplace && !hasEntry(base, "extraKnownMarketplaces", MARKETPLACE_KEY);
|
|
@@ -1266,14 +1571,14 @@ var mergeSettings = (current2, wanted, recorded) => {
|
|
|
1266
1571
|
const language = "language" in base ? void 0 : wanted.language;
|
|
1267
1572
|
let settings = withPermissions(withHooks(base, hooks), {
|
|
1268
1573
|
deny: [...existingDeny, ...deny2],
|
|
1269
|
-
ask: [...existingAsk, ...
|
|
1574
|
+
ask: [...existingAsk, ...ask2],
|
|
1270
1575
|
blockReads: blockReads ? true : permissions[BLOCK_READS]
|
|
1271
1576
|
});
|
|
1272
1577
|
if (attribution) settings = { ...settings, attribution: ATTRIBUTION_OFF };
|
|
1273
1578
|
if (marketplace) settings = withEntry(settings, "extraKnownMarketplaces", MARKETPLACE_KEY, MARKETPLACE_ENTRY);
|
|
1274
1579
|
if (plugin) settings = withEntry(settings, "enabledPlugins", PLUGIN_ID, true);
|
|
1275
1580
|
if (language !== void 0) settings = { ...settings, language };
|
|
1276
|
-
const added = { schema, deny: deny2, ask, blockReads, attribution, marketplace, plugin };
|
|
1581
|
+
const added = { schema, deny: deny2, ask: ask2, blockReads, attribution, marketplace, plugin };
|
|
1277
1582
|
return { settings, added: language === void 0 ? added : { ...added, language } };
|
|
1278
1583
|
};
|
|
1279
1584
|
var sameAttribution = (value) => JSON.stringify(value) === JSON.stringify(ATTRIBUTION_OFF);
|
|
@@ -2192,8 +2497,8 @@ var fmPaths = (root) => {
|
|
|
2192
2497
|
var HOOK_FAILURE_EVENT = "hook.failed";
|
|
2193
2498
|
var FAILURES = ["failed_open", "failed_closed", "stop_released"];
|
|
2194
2499
|
var MAX_DETAIL = 500;
|
|
2195
|
-
var logHookFailure = (ctx, event,
|
|
2196
|
-
if (!FAILURES.includes(
|
|
2500
|
+
var logHookFailure = (ctx, event, outcome2) => {
|
|
2501
|
+
if (!FAILURES.includes(outcome2.verdict)) return;
|
|
2197
2502
|
const fromEnv = ctx.env["CLAUDE_PROJECT_DIR"];
|
|
2198
2503
|
const root = fromEnv === void 0 ? findGitRoot(ctx.cwd, ctx.runtime) : toAbsolutePath(fromEnv);
|
|
2199
2504
|
if (root === void 0) return;
|
|
@@ -2201,8 +2506,8 @@ var logHookFailure = (ctx, event, outcome) => {
|
|
|
2201
2506
|
if (ctx.runtime.stat(paths.dir)?.kind !== "dir") return;
|
|
2202
2507
|
logEvent(ctx.runtime, paths, HOOK_FAILURE_EVENT, {
|
|
2203
2508
|
hook: event,
|
|
2204
|
-
verdict:
|
|
2205
|
-
detail: maskText(
|
|
2509
|
+
verdict: outcome2.verdict,
|
|
2510
|
+
detail: maskText(outcome2.stderr.trim()).slice(0, MAX_DETAIL)
|
|
2206
2511
|
});
|
|
2207
2512
|
};
|
|
2208
2513
|
|
|
@@ -2615,7 +2920,7 @@ var checkSandbox = (env) => {
|
|
|
2615
2920
|
}
|
|
2616
2921
|
if (os === "macos") return [finding("sandbox", "ok", "doctor.sandbox.ok")];
|
|
2617
2922
|
if (os === "other") return [];
|
|
2618
|
-
const missing2 = SANDBOX_TOOLS.filter(({ command, args }) => !env.runtime.probe(command,
|
|
2923
|
+
const missing2 = SANDBOX_TOOLS.filter(({ command, args: args2 }) => !env.runtime.probe(command, args2, PROBE_MS2).found).map(
|
|
2619
2924
|
({ command }) => command
|
|
2620
2925
|
);
|
|
2621
2926
|
if (missing2.length === 0) return [finding("sandbox", "ok", "doctor.sandbox.ok")];
|
|
@@ -3336,10 +3641,10 @@ var withAssignments = (stage) => {
|
|
|
3336
3641
|
}
|
|
3337
3642
|
return { ...stage, argv: stage.argv.slice(index), env };
|
|
3338
3643
|
};
|
|
3339
|
-
var skipOptions = (
|
|
3644
|
+
var skipOptions = (args2, wrapper) => {
|
|
3340
3645
|
let index = 0;
|
|
3341
|
-
while (index <
|
|
3342
|
-
const arg =
|
|
3646
|
+
while (index < args2.length) {
|
|
3647
|
+
const arg = args2[index] ?? "";
|
|
3343
3648
|
if (arg === "--") return index + 1 + wrapper.positionals;
|
|
3344
3649
|
if (!arg.startsWith("-") || arg === "-") break;
|
|
3345
3650
|
if (wrapper.queries.has(arg)) return void 0;
|
|
@@ -3369,33 +3674,33 @@ var envCommand = (stage) => {
|
|
|
3369
3674
|
return printsEnvironment ? { kind: "command", stage, extra: [] } : shift(stage, index, "env");
|
|
3370
3675
|
};
|
|
3371
3676
|
var shellScript = (stage, name, stdin) => {
|
|
3372
|
-
const
|
|
3677
|
+
const args2 = stage.argv.slice(1);
|
|
3373
3678
|
let index = 0;
|
|
3374
3679
|
let command = false;
|
|
3375
|
-
while (index <
|
|
3376
|
-
const arg =
|
|
3680
|
+
while (index < args2.length && /^[-+]/.test(args2[index] ?? "")) {
|
|
3681
|
+
const arg = args2[index] ?? "";
|
|
3377
3682
|
if (/^-[A-Za-z]*c[A-Za-z]*$/.test(arg)) command = true;
|
|
3378
3683
|
index += SHELL_WITH_VALUE.has(arg) ? 2 : 1;
|
|
3379
3684
|
}
|
|
3380
|
-
const script =
|
|
3685
|
+
const script = args2[index];
|
|
3381
3686
|
if (command && script !== void 0) return { kind: "script", script, dialect: "bash", stage: shift(stage, 0, name) };
|
|
3382
3687
|
if (script === void 0 && stdin !== void 0) return { kind: "script", script: stdin, dialect: "bash", stage };
|
|
3383
3688
|
return void 0;
|
|
3384
3689
|
};
|
|
3385
3690
|
var decodeEncoded = (value) => Buffer.from(value, "base64").toString("utf16le");
|
|
3386
3691
|
var powershellScript = (stage, name) => {
|
|
3387
|
-
const
|
|
3388
|
-
const at =
|
|
3389
|
-
const encoded =
|
|
3692
|
+
const args2 = stage.argv.slice(1);
|
|
3693
|
+
const at = args2.findIndex((arg) => /^[-/](?:c|co|com|comm|comma|comman|command)$/i.test(arg));
|
|
3694
|
+
const encoded = args2.findIndex((arg) => /^[-/](?:e|ec|enc|encodedcommand)$/i.test(arg));
|
|
3390
3695
|
if (at >= 0) {
|
|
3391
3696
|
return {
|
|
3392
3697
|
kind: "script",
|
|
3393
|
-
script:
|
|
3698
|
+
script: args2.slice(at + 1).join(" "),
|
|
3394
3699
|
dialect: "powershell",
|
|
3395
3700
|
stage: shift(stage, 0, name)
|
|
3396
3701
|
};
|
|
3397
3702
|
}
|
|
3398
|
-
const value = encoded >= 0 ?
|
|
3703
|
+
const value = encoded >= 0 ? args2[encoded + 1] : void 0;
|
|
3399
3704
|
if (value !== void 0) {
|
|
3400
3705
|
return { kind: "script", script: decodeEncoded(value), dialect: "powershell", stage: shift(stage, 0, name) };
|
|
3401
3706
|
}
|
|
@@ -3574,20 +3879,20 @@ var envFindings = (command) => {
|
|
|
3574
3879
|
const exported = command.argv[0] === "export" ? command.argv.slice(1).map((arg) => arg.split("=", 2)) : [];
|
|
3575
3880
|
return [...pairs2, ...exported].filter(([name = ""]) => HOOK_ENV.test(name)).map(([name = "", value = ""]) => ({ kind: "hook_env", detail: `${name}=${value}` }));
|
|
3576
3881
|
};
|
|
3577
|
-
var splitGit = (
|
|
3882
|
+
var splitGit = (args2) => {
|
|
3578
3883
|
let index = 0;
|
|
3579
3884
|
const globals = [];
|
|
3580
|
-
while (index <
|
|
3581
|
-
const arg =
|
|
3885
|
+
while (index < args2.length && (args2[index] ?? "").startsWith("-")) {
|
|
3886
|
+
const arg = args2[index] ?? "";
|
|
3582
3887
|
globals.push(arg);
|
|
3583
|
-
if (GIT_VALUE_OPTIONS.has(arg)) globals.push(
|
|
3888
|
+
if (GIT_VALUE_OPTIONS.has(arg)) globals.push(args2[index + 1] ?? "");
|
|
3584
3889
|
index += GIT_VALUE_OPTIONS.has(arg) ? 2 : 1;
|
|
3585
3890
|
}
|
|
3586
|
-
return { globals, rest:
|
|
3891
|
+
return { globals, rest: args2.slice(index) };
|
|
3587
3892
|
};
|
|
3588
|
-
var commitHasShortN = (
|
|
3589
|
-
for (let index = 0; index <
|
|
3590
|
-
const arg =
|
|
3893
|
+
var commitHasShortN = (args2) => {
|
|
3894
|
+
for (let index = 0; index < args2.length; index += 1) {
|
|
3895
|
+
const arg = args2[index] ?? "";
|
|
3591
3896
|
if (arg === "--") return false;
|
|
3592
3897
|
if (!/^-[A-Za-z]/.test(arg)) continue;
|
|
3593
3898
|
for (const char of arg.slice(1)) {
|
|
@@ -3600,8 +3905,8 @@ var commitHasShortN = (args) => {
|
|
|
3600
3905
|
}
|
|
3601
3906
|
return false;
|
|
3602
3907
|
};
|
|
3603
|
-
var gitFindings = (
|
|
3604
|
-
const { globals, rest } = splitGit(
|
|
3908
|
+
var gitFindings = (args2) => {
|
|
3909
|
+
const { globals, rest } = splitGit(args2);
|
|
3605
3910
|
const found = [];
|
|
3606
3911
|
globals.forEach((arg, index) => {
|
|
3607
3912
|
if (arg === "-c" && isHooksPath(globals[index + 1] ?? "") || /^--config-env=core\.hookspath/i.test(arg)) {
|
|
@@ -3678,16 +3983,16 @@ var GIT_WRITERS = /* @__PURE__ */ new Set(["checkout", "restore", "rm", "mv", "c
|
|
|
3678
3983
|
var FM_NAMES2 = /* @__PURE__ */ new Set(["finitemonkey", "fm"]);
|
|
3679
3984
|
var inline = (argv) => argv.some((arg) => arg === "-e" || arg === "-c" || arg === "--eval");
|
|
3680
3985
|
var writtenPaths = (command) => {
|
|
3681
|
-
const [name = "", ...
|
|
3682
|
-
const operands2 =
|
|
3683
|
-
const ddTargets =
|
|
3986
|
+
const [name = "", ...args2] = command.argv;
|
|
3987
|
+
const operands2 = args2.filter((arg) => !arg.startsWith("-"));
|
|
3988
|
+
const ddTargets = args2.filter((arg) => arg.startsWith("of=")).map((arg) => arg.slice(3));
|
|
3684
3989
|
if (FM_NAMES2.has(name)) return command.redirects;
|
|
3685
3990
|
if (COPIERS.has(name)) return [...command.redirects, ...operands2.slice(-1)];
|
|
3686
3991
|
if (WRITERS.has(name)) return [...command.redirects, ...operands2, ...ddTargets];
|
|
3687
|
-
if (IN_PLACE.has(name) &&
|
|
3992
|
+
if (IN_PLACE.has(name) && args2.some((arg) => /^-[a-zA-Z]*i/.test(arg) || arg.startsWith("--in-place"))) {
|
|
3688
3993
|
return [...command.redirects, ...operands2];
|
|
3689
3994
|
}
|
|
3690
|
-
if (INTERPRETERS.has(name) && inline(
|
|
3995
|
+
if (INTERPRETERS.has(name) && inline(args2)) return [...command.redirects, ...args2];
|
|
3691
3996
|
if (name === "git" && GIT_WRITERS.has(operands2[0] ?? "")) return [...command.redirects, ...operands2.slice(1)];
|
|
3692
3997
|
return command.redirects;
|
|
3693
3998
|
};
|
|
@@ -3706,14 +4011,14 @@ var bashSelfTargets = (root, commandLine) => parseShell(commandLine).flatMap(
|
|
|
3706
4011
|
// src/guards/self/hook.ts
|
|
3707
4012
|
var targets = (input) => {
|
|
3708
4013
|
const tool = toolName(input.payload.raw);
|
|
3709
|
-
const
|
|
4014
|
+
const args2 = toolInput(input.payload.raw);
|
|
3710
4015
|
const root = guardRoot(input);
|
|
3711
4016
|
if (FILE_TOOLS.has(tool)) {
|
|
3712
|
-
const path = textField(
|
|
4017
|
+
const path = textField(args2, "file_path", "notebook_path") ?? "";
|
|
3713
4018
|
const kind = path === "" ? void 0 : selfTarget(root, path);
|
|
3714
4019
|
return kind === void 0 ? [] : [{ kind, path }];
|
|
3715
4020
|
}
|
|
3716
|
-
return SHELL_TOOLS.has(tool) ? bashSelfTargets(root, textField(
|
|
4021
|
+
return SHELL_TOOLS.has(tool) ? bashSelfTargets(root, textField(args2, "command") ?? "") : [];
|
|
3717
4022
|
};
|
|
3718
4023
|
var selfGuard = (input) => {
|
|
3719
4024
|
const found = targets(input);
|
|
@@ -3897,19 +4202,19 @@ var read = (input, path) => {
|
|
|
3897
4202
|
const text6 = input.runtime.readText(path);
|
|
3898
4203
|
return text6.ok ? text6.value : void 0;
|
|
3899
4204
|
};
|
|
3900
|
-
var proposed = (tool,
|
|
3901
|
-
if (tool === "Write") return textField(
|
|
3902
|
-
return before === void 0 ? void 0 : applyEdits(before, editsOf(
|
|
4205
|
+
var proposed = (tool, args2, before) => {
|
|
4206
|
+
if (tool === "Write") return textField(args2, "content") ?? "";
|
|
4207
|
+
return before === void 0 ? void 0 : applyEdits(before, editsOf(args2));
|
|
3903
4208
|
};
|
|
3904
4209
|
var fileViolations = (input, root) => {
|
|
3905
4210
|
const tool = toolName(input.payload.raw);
|
|
3906
|
-
const
|
|
3907
|
-
const file = textField(
|
|
4211
|
+
const args2 = toolInput(input.payload.raw);
|
|
4212
|
+
const file = textField(args2, "file_path") ?? "";
|
|
3908
4213
|
if (tool === "NotebookEdit" || file === "") return [];
|
|
3909
4214
|
const local = localPath(root, file);
|
|
3910
4215
|
if (!isTestFile(local) && !isProtectedConfig(local)) return [];
|
|
3911
4216
|
const before = read(input, toAbsolutePath(file, root));
|
|
3912
|
-
const after = proposed(tool,
|
|
4217
|
+
const after = proposed(tool, args2, before);
|
|
3913
4218
|
if (after === void 0) return [];
|
|
3914
4219
|
const accepted2 = readTrust(input.runtime, fmPaths(root)).configs[local];
|
|
3915
4220
|
if (before === void 0) return compareNewTestFile(local, after);
|
|
@@ -4426,7 +4731,7 @@ var str = (record3, key, at, issues, required) => {
|
|
|
4426
4731
|
}
|
|
4427
4732
|
return value;
|
|
4428
4733
|
};
|
|
4429
|
-
var
|
|
4734
|
+
var positive2 = (record3, key, at, issues) => {
|
|
4430
4735
|
const value = record3[key];
|
|
4431
4736
|
if (value === void 0 || value === null) return void 0;
|
|
4432
4737
|
if (typeof value === "number" && Number.isInteger(value) && value > 0) return value;
|
|
@@ -4446,11 +4751,26 @@ var gitRequire = (value, at, issues) => {
|
|
|
4446
4751
|
if (known2.some((item) => item === void 0)) issues.push(`${at}: use ${GIT_REQUIREMENTS.join(", ")}`);
|
|
4447
4752
|
return known2.filter((item) => item !== void 0);
|
|
4448
4753
|
};
|
|
4754
|
+
var appFields = (record3, kind, at, issues) => {
|
|
4755
|
+
const port = positive2(record3, "port", at, issues);
|
|
4756
|
+
if (kind === "runtime" && port === void 0) issues.push(`${at}port: required`);
|
|
4757
|
+
if (port !== void 0 && port > 65535) issues.push(`${at}port: must be at most 65535`);
|
|
4758
|
+
const status = positive2(record3, "status", at, issues);
|
|
4759
|
+
const route = str(record3, "route", at, issues, false);
|
|
4760
|
+
const body2 = str(record3, "body", at, issues, false);
|
|
4761
|
+
return {
|
|
4762
|
+
...port === void 0 ? {} : { port },
|
|
4763
|
+
...route === void 0 ? {} : { route },
|
|
4764
|
+
...status === void 0 ? {} : { status },
|
|
4765
|
+
...body2 === void 0 ? {} : { body: body2 }
|
|
4766
|
+
};
|
|
4767
|
+
};
|
|
4449
4768
|
var checkFields = (record3, kind, at, issues) => {
|
|
4450
4769
|
const run4 = str(record3, "run", at, issues, kind === "command");
|
|
4451
|
-
const timeoutS =
|
|
4770
|
+
const timeoutS = positive2(record3, "timeout_s", at, issues);
|
|
4452
4771
|
const description = str(record3, "description", at, issues, kind === "manual");
|
|
4453
4772
|
const require2 = kind === "git" ? gitRequire(record3["require"] ?? ["committed"], `${at}require`, issues) : void 0;
|
|
4773
|
+
const app = appFields(record3, kind, at, issues);
|
|
4454
4774
|
const open = record3["require_open"];
|
|
4455
4775
|
if (open !== void 0 && typeof open !== "boolean") issues.push(`${at}require_open: must be true or false`);
|
|
4456
4776
|
return {
|
|
@@ -4458,7 +4778,8 @@ var checkFields = (record3, kind, at, issues) => {
|
|
|
4458
4778
|
...timeoutS === void 0 ? {} : { timeoutS },
|
|
4459
4779
|
...description === void 0 ? {} : { description },
|
|
4460
4780
|
...require2 === void 0 ? {} : { require: require2 },
|
|
4461
|
-
...typeof open === "boolean" ? { requireOpen: open } : {}
|
|
4781
|
+
...typeof open === "boolean" ? { requireOpen: open } : {},
|
|
4782
|
+
...app
|
|
4462
4783
|
};
|
|
4463
4784
|
};
|
|
4464
4785
|
var acceptanceItem = (value, index, issues) => {
|
|
@@ -4496,8 +4817,8 @@ var scope = (value, issues) => {
|
|
|
4496
4817
|
...files === void 0 ? {} : { files },
|
|
4497
4818
|
...lines3 === void 0 ? {} : { lines: lines3 }
|
|
4498
4819
|
}))({
|
|
4499
|
-
files:
|
|
4500
|
-
lines:
|
|
4820
|
+
files: positive2(budget, "files", "scope.diff_budget.", issues),
|
|
4821
|
+
lines: positive2(budget, "lines", "scope.diff_budget.", issues)
|
|
4501
4822
|
}) : void 0;
|
|
4502
4823
|
if (budget !== void 0 && budget !== null && !isRecord(budget)) issues.push("scope.diff_budget: must be a mapping");
|
|
4503
4824
|
const protectedValue = value["tests_protected"];
|
|
@@ -4622,12 +4943,12 @@ var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
|
4622
4943
|
var GIT_TIMEOUT_MS = 15e3;
|
|
4623
4944
|
var EXCLUDE_FM = `:(exclude)${FM_DIR}`;
|
|
4624
4945
|
var gitAt = (runtime, cwd) => {
|
|
4625
|
-
const run4 = (
|
|
4946
|
+
const run4 = (args2) => runtime.exec({ command: "git", args: ["-c", "core.quotepath=off", ...args2], cwd, timeoutMs: GIT_TIMEOUT_MS });
|
|
4626
4947
|
return {
|
|
4627
4948
|
cwd,
|
|
4628
4949
|
run: run4,
|
|
4629
|
-
out: (
|
|
4630
|
-
const result = run4(
|
|
4950
|
+
out: (args2) => {
|
|
4951
|
+
const result = run4(args2);
|
|
4631
4952
|
return result.found && result.exitCode === 0 ? result.stdout : void 0;
|
|
4632
4953
|
}
|
|
4633
4954
|
};
|
|
@@ -4774,7 +5095,7 @@ var parseMergeTreeConflicts = (stdout) => {
|
|
|
4774
5095
|
var PR_FIELDS = "number,url,state,mergeable,mergeStateStatus,baseRefName,headRefOid,statusCheckRollup";
|
|
4775
5096
|
var PR_CACHE_TTL_MS = 6e4;
|
|
4776
5097
|
var GH_TIMEOUT_MS = 8e3;
|
|
4777
|
-
var gh = (runtime, cwd,
|
|
5098
|
+
var gh = (runtime, cwd, args2, timeoutMs = GH_TIMEOUT_MS) => runtime.exec({ command: "gh", args: args2, cwd, timeoutMs });
|
|
4778
5099
|
var ghAuthenticated = (runtime, cwd, timeoutMs = 4e3) => {
|
|
4779
5100
|
const result = gh(runtime, cwd, ["auth", "status"], timeoutMs);
|
|
4780
5101
|
if (result.timedOut) return "timeout";
|
|
@@ -5787,7 +6108,28 @@ var en_default = {
|
|
|
5787
6108
|
"gate.callers.warning": "warning only: {percent}% of callers findings were released with callers_ignore ({released} of {total}), above the 5% ceiling",
|
|
5788
6109
|
"command.policy_false_positive.summary": "Record a false positive of a guard in shadow so it is not promoted",
|
|
5789
6110
|
"policy.error.person_only": "Only the person can record a false positive, and this does not look like their terminal (no TTY, or running inside Claude Code)",
|
|
5790
|
-
"policy.false_positive.recorded": "Recorded for {guard}: {count, plural, one {# false positive} other {# false positives}}; it stays in shadow until you set it in .finitemonkey/policy.yml."
|
|
6111
|
+
"policy.false_positive.recorded": "Recorded for {guard}: {count, plural, one {# false positive} other {# false positives}}; it stays in shadow until you set it in .finitemonkey/policy.yml.",
|
|
6112
|
+
"command.app_check.summary": "Start the app or reuse the running one, call one route and check the answer",
|
|
6113
|
+
"app.check.ok": "{url} answered {status}",
|
|
6114
|
+
"app.check.crashed": "the app exited with code {code} before opening the port",
|
|
6115
|
+
"app.check.no_port": "the port of {url} did not open before the timeout",
|
|
6116
|
+
"app.check.no_start": "nothing listens on {url} and no start command was given",
|
|
6117
|
+
"app.check.wrong_status": "{url} answered {status}",
|
|
6118
|
+
"app.check.body_mismatch": "{url} answered {status} without the expected text",
|
|
6119
|
+
"app.check.request_failed": "the request to {url} failed",
|
|
6120
|
+
"app.check.usage": "give --port as a number from 1 to 65535; --status and --timeout must be positive numbers",
|
|
6121
|
+
"gate.require.runtime": "the app starts and `{command}` answers as declared",
|
|
6122
|
+
"gate.runtime.ok": "started, {route} answered {status}, stopped",
|
|
6123
|
+
"gate.runtime.reused": "reused the running app, {route} answered {status}",
|
|
6124
|
+
"gate.runtime.crashed": "the app exited with code {code} before opening its port",
|
|
6125
|
+
"gate.runtime.no_port": "port {port} did not open before the timeout",
|
|
6126
|
+
"gate.runtime.no_start": "nothing listens on port {port} and the check has no `run` to start the app",
|
|
6127
|
+
"gate.runtime.no_port_declared": "the runtime check needs a `port`",
|
|
6128
|
+
"gate.runtime.wrong_status": "{route} answered {status}, expected {expected}",
|
|
6129
|
+
"gate.runtime.body_mismatch": '{route} did not contain "{body}"',
|
|
6130
|
+
"gate.runtime.request_failed": "the request to {route} failed: {detail}",
|
|
6131
|
+
"gate.runtime.orphan": "the app on port {port} could not be stopped",
|
|
6132
|
+
"gate.runtime.probe_failed": "the app check did not report a result: {line}"
|
|
5791
6133
|
};
|
|
5792
6134
|
|
|
5793
6135
|
// src/i18n/es.json
|
|
@@ -6319,7 +6661,28 @@ var es_default = {
|
|
|
6319
6661
|
"gate.callers.warning": "solo aviso: {percent}% de los hallazgos de callers se liberaron con callers_ignore ({released} de {total}), por encima del techo de 5%",
|
|
6320
6662
|
"command.policy_false_positive.summary": "Registra un falso positivo de un guard en shadow para que no se promueva",
|
|
6321
6663
|
"policy.error.person_only": "Solo la persona puede registrar un falso positivo, y esto no parece su terminal (sin TTY, o dentro de Claude Code)",
|
|
6322
|
-
"policy.false_positive.recorded": "Registrado para {guard}: {count, plural, one {# falso positivo} other {# falsos positivos}}; se queda en shadow hasta que fijes el modo en .finitemonkey/policy.yml."
|
|
6664
|
+
"policy.false_positive.recorded": "Registrado para {guard}: {count, plural, one {# falso positivo} other {# falsos positivos}}; se queda en shadow hasta que fijes el modo en .finitemonkey/policy.yml.",
|
|
6665
|
+
"command.app_check.summary": "Arranca la app o reutiliza la que ya corre, llama a una ruta y comprueba la respuesta",
|
|
6666
|
+
"app.check.ok": "{url} respondió {status}",
|
|
6667
|
+
"app.check.crashed": "la app salió con código {code} antes de abrir el puerto",
|
|
6668
|
+
"app.check.no_port": "el puerto de {url} no se abrió antes del tiempo límite",
|
|
6669
|
+
"app.check.no_start": "nada escucha en {url} y no se indicó comando de arranque",
|
|
6670
|
+
"app.check.wrong_status": "{url} respondió {status}",
|
|
6671
|
+
"app.check.body_mismatch": "{url} respondió {status} sin el texto esperado",
|
|
6672
|
+
"app.check.request_failed": "la petición a {url} falló",
|
|
6673
|
+
"app.check.usage": "indica --port como número de 1 a 65535; --status y --timeout deben ser números positivos",
|
|
6674
|
+
"gate.require.runtime": "la app arranca y `{command}` responde como se declaró",
|
|
6675
|
+
"gate.runtime.ok": "arrancó, {route} respondió {status}, detenida",
|
|
6676
|
+
"gate.runtime.reused": "reutilizó la app en marcha, {route} respondió {status}",
|
|
6677
|
+
"gate.runtime.crashed": "la app salió con código {code} antes de abrir su puerto",
|
|
6678
|
+
"gate.runtime.no_port": "el puerto {port} no se abrió antes del tiempo límite",
|
|
6679
|
+
"gate.runtime.no_start": "nada escucha en el puerto {port} y la comprobación no tiene `run` para arrancar la app",
|
|
6680
|
+
"gate.runtime.no_port_declared": "la comprobación runtime necesita `port`",
|
|
6681
|
+
"gate.runtime.wrong_status": "{route} respondió {status}, se esperaba {expected}",
|
|
6682
|
+
"gate.runtime.body_mismatch": '{route} no contenía "{body}"',
|
|
6683
|
+
"gate.runtime.request_failed": "la petición a {route} falló: {detail}",
|
|
6684
|
+
"gate.runtime.orphan": "no se pudo detener la app del puerto {port}",
|
|
6685
|
+
"gate.runtime.probe_failed": "la comprobación de la app no devolvió resultado: {line}"
|
|
6323
6686
|
};
|
|
6324
6687
|
|
|
6325
6688
|
// src/i18n/pt-BR.json
|
|
@@ -6851,7 +7214,28 @@ var pt_BR_default = {
|
|
|
6851
7214
|
"gate.callers.warning": "só aviso: {percent}% dos achados de callers foram liberados com callers_ignore ({released} de {total}), acima do teto de 5%",
|
|
6852
7215
|
"command.policy_false_positive.summary": "Registra um falso positivo de um guard em shadow para ele não ser promovido",
|
|
6853
7216
|
"policy.error.person_only": "Só a pessoa pode registrar um falso positivo, e isto não parece o terminal dela (sem TTY, ou rodando dentro do Claude Code)",
|
|
6854
|
-
"policy.false_positive.recorded": "Registrado para {guard}: {count, plural, one {# falso positivo} other {# falsos positivos}}; ele fica em shadow até você definir o modo em .finitemonkey/policy.yml."
|
|
7217
|
+
"policy.false_positive.recorded": "Registrado para {guard}: {count, plural, one {# falso positivo} other {# falsos positivos}}; ele fica em shadow até você definir o modo em .finitemonkey/policy.yml.",
|
|
7218
|
+
"command.app_check.summary": "Sobe o app ou reaproveita o que está rodando, chama uma rota e confere a resposta",
|
|
7219
|
+
"app.check.ok": "{url} respondeu {status}",
|
|
7220
|
+
"app.check.crashed": "o app saiu com código {code} antes de abrir a porta",
|
|
7221
|
+
"app.check.no_port": "a porta de {url} não abriu antes do tempo limite",
|
|
7222
|
+
"app.check.no_start": "nada escuta em {url} e nenhum comando de início foi dado",
|
|
7223
|
+
"app.check.wrong_status": "{url} respondeu {status}",
|
|
7224
|
+
"app.check.body_mismatch": "{url} respondeu {status} sem o texto esperado",
|
|
7225
|
+
"app.check.request_failed": "a requisição para {url} falhou",
|
|
7226
|
+
"app.check.usage": "passe --port como número de 1 a 65535; --status e --timeout precisam ser números positivos",
|
|
7227
|
+
"gate.require.runtime": "o app sobe e `{command}` responde como declarado",
|
|
7228
|
+
"gate.runtime.ok": "subiu, {route} respondeu {status}, parado",
|
|
7229
|
+
"gate.runtime.reused": "reaproveitou o app rodando, {route} respondeu {status}",
|
|
7230
|
+
"gate.runtime.crashed": "o app saiu com código {code} antes de abrir a porta",
|
|
7231
|
+
"gate.runtime.no_port": "a porta {port} não abriu antes do tempo limite",
|
|
7232
|
+
"gate.runtime.no_start": "nada escuta na porta {port} e a checagem não tem `run` para subir o app",
|
|
7233
|
+
"gate.runtime.no_port_declared": "a checagem runtime precisa de `port`",
|
|
7234
|
+
"gate.runtime.wrong_status": "{route} respondeu {status}, esperado {expected}",
|
|
7235
|
+
"gate.runtime.body_mismatch": '{route} não continha "{body}"',
|
|
7236
|
+
"gate.runtime.request_failed": "a requisição para {route} falhou: {detail}",
|
|
7237
|
+
"gate.runtime.orphan": "o app na porta {port} não pôde ser parado",
|
|
7238
|
+
"gate.runtime.probe_failed": "a checagem do app não devolveu resultado: {line}"
|
|
6855
7239
|
};
|
|
6856
7240
|
|
|
6857
7241
|
// src/i18n/review.json
|
|
@@ -7384,7 +7768,28 @@ var review_default = {
|
|
|
7384
7768
|
"gate.callers.warning": "machine",
|
|
7385
7769
|
"command.policy_false_positive.summary": "machine",
|
|
7386
7770
|
"policy.error.person_only": "machine",
|
|
7387
|
-
"policy.false_positive.recorded": "machine"
|
|
7771
|
+
"policy.false_positive.recorded": "machine",
|
|
7772
|
+
"command.app_check.summary": "machine",
|
|
7773
|
+
"app.check.ok": "machine",
|
|
7774
|
+
"app.check.crashed": "machine",
|
|
7775
|
+
"app.check.no_port": "machine",
|
|
7776
|
+
"app.check.no_start": "machine",
|
|
7777
|
+
"app.check.wrong_status": "machine",
|
|
7778
|
+
"app.check.body_mismatch": "machine",
|
|
7779
|
+
"app.check.request_failed": "machine",
|
|
7780
|
+
"app.check.usage": "machine",
|
|
7781
|
+
"gate.require.runtime": "machine",
|
|
7782
|
+
"gate.runtime.ok": "machine",
|
|
7783
|
+
"gate.runtime.reused": "machine",
|
|
7784
|
+
"gate.runtime.crashed": "machine",
|
|
7785
|
+
"gate.runtime.no_port": "machine",
|
|
7786
|
+
"gate.runtime.no_start": "machine",
|
|
7787
|
+
"gate.runtime.no_port_declared": "machine",
|
|
7788
|
+
"gate.runtime.wrong_status": "machine",
|
|
7789
|
+
"gate.runtime.body_mismatch": "machine",
|
|
7790
|
+
"gate.runtime.request_failed": "machine",
|
|
7791
|
+
"gate.runtime.orphan": "machine",
|
|
7792
|
+
"gate.runtime.probe_failed": "machine"
|
|
7388
7793
|
},
|
|
7389
7794
|
es: {
|
|
7390
7795
|
"command.init.summary": "machine",
|
|
@@ -7914,7 +8319,28 @@ var review_default = {
|
|
|
7914
8319
|
"gate.callers.warning": "machine",
|
|
7915
8320
|
"command.policy_false_positive.summary": "machine",
|
|
7916
8321
|
"policy.error.person_only": "machine",
|
|
7917
|
-
"policy.false_positive.recorded": "machine"
|
|
8322
|
+
"policy.false_positive.recorded": "machine",
|
|
8323
|
+
"command.app_check.summary": "machine",
|
|
8324
|
+
"app.check.ok": "machine",
|
|
8325
|
+
"app.check.crashed": "machine",
|
|
8326
|
+
"app.check.no_port": "machine",
|
|
8327
|
+
"app.check.no_start": "machine",
|
|
8328
|
+
"app.check.wrong_status": "machine",
|
|
8329
|
+
"app.check.body_mismatch": "machine",
|
|
8330
|
+
"app.check.request_failed": "machine",
|
|
8331
|
+
"app.check.usage": "machine",
|
|
8332
|
+
"gate.require.runtime": "machine",
|
|
8333
|
+
"gate.runtime.ok": "machine",
|
|
8334
|
+
"gate.runtime.reused": "machine",
|
|
8335
|
+
"gate.runtime.crashed": "machine",
|
|
8336
|
+
"gate.runtime.no_port": "machine",
|
|
8337
|
+
"gate.runtime.no_start": "machine",
|
|
8338
|
+
"gate.runtime.no_port_declared": "machine",
|
|
8339
|
+
"gate.runtime.wrong_status": "machine",
|
|
8340
|
+
"gate.runtime.body_mismatch": "machine",
|
|
8341
|
+
"gate.runtime.request_failed": "machine",
|
|
8342
|
+
"gate.runtime.orphan": "machine",
|
|
8343
|
+
"gate.runtime.probe_failed": "machine"
|
|
7918
8344
|
}
|
|
7919
8345
|
};
|
|
7920
8346
|
|
|
@@ -9294,9 +9720,9 @@ var isFlagged = (report2) => report2.spans.length > 0;
|
|
|
9294
9720
|
var MARKDOWN = /\.(?:md|markdown|mdx)$/i;
|
|
9295
9721
|
var RECORD_FILE = /(?:^|\/)(?:CHANGELOG|RELEASE[-_]?NOTES|HISTORY)[^/]*$/i;
|
|
9296
9722
|
var contextOf = (file) => RECORD_FILE.test(toPosixPath(file)) ? "record" : "docs";
|
|
9297
|
-
var listed = (runtime, root,
|
|
9298
|
-
const result = runtime.git(
|
|
9299
|
-
if (!result.ok) return reject(`git ${
|
|
9723
|
+
var listed = (runtime, root, args2) => {
|
|
9724
|
+
const result = runtime.git(args2, root);
|
|
9725
|
+
if (!result.ok) return reject(`git ${args2.join(" ")} failed`);
|
|
9300
9726
|
return accept(result.stdout.split("\0").map(toPosixPath));
|
|
9301
9727
|
};
|
|
9302
9728
|
var changedMarkdown = (runtime, root) => {
|
|
@@ -9376,6 +9802,121 @@ var reviewCheck = (check2, ctx) => {
|
|
|
9376
9802
|
return failed([...sizeNotes(ctx), note("gate.review.missing", { check: check2.id })]);
|
|
9377
9803
|
};
|
|
9378
9804
|
|
|
9805
|
+
// src/app/parse.ts
|
|
9806
|
+
var KINDS2 = [
|
|
9807
|
+
"ok",
|
|
9808
|
+
"crashed",
|
|
9809
|
+
"no_port",
|
|
9810
|
+
"wrong_status",
|
|
9811
|
+
"body_mismatch",
|
|
9812
|
+
"request_failed",
|
|
9813
|
+
"no_start"
|
|
9814
|
+
];
|
|
9815
|
+
var optionalNumber = (value) => typeof value === "number" ? value : void 0;
|
|
9816
|
+
var parseAppCheck = (stdout) => {
|
|
9817
|
+
const envelope = parseJsonObject(stdout.trim());
|
|
9818
|
+
if (!envelope.ok) return void 0;
|
|
9819
|
+
const data = envelope.value["data"];
|
|
9820
|
+
if (!isRecord(data)) return void 0;
|
|
9821
|
+
const kind = KINDS2.find((item) => item === data["kind"]);
|
|
9822
|
+
const { output, reused, stopped, durationMs, exitCode, bodyExcerpt } = data;
|
|
9823
|
+
if (kind === void 0 || typeof output !== "string" || typeof reused !== "boolean" || typeof stopped !== "boolean")
|
|
9824
|
+
return void 0;
|
|
9825
|
+
const status = optionalNumber(data["status"]);
|
|
9826
|
+
return {
|
|
9827
|
+
kind,
|
|
9828
|
+
output,
|
|
9829
|
+
reused,
|
|
9830
|
+
stopped,
|
|
9831
|
+
durationMs: optionalNumber(durationMs) ?? 0,
|
|
9832
|
+
...status === void 0 ? {} : { status },
|
|
9833
|
+
...typeof exitCode === "number" || exitCode === null ? { exitCode } : {},
|
|
9834
|
+
...typeof bodyExcerpt === "string" ? { bodyExcerpt } : {}
|
|
9835
|
+
};
|
|
9836
|
+
};
|
|
9837
|
+
|
|
9838
|
+
// src/gate/checks/runtime.ts
|
|
9839
|
+
var PROBE_MARGIN_MS = 15e3;
|
|
9840
|
+
var MIN_REMAINING_MS2 = 5e3;
|
|
9841
|
+
var TAIL2 = 160;
|
|
9842
|
+
var lastLine = (text6) => {
|
|
9843
|
+
const rows = text6.split(/\r?\n/).filter((row) => row.trim() !== "" && !/^\s*at\s|^Node\.js v\d/.test(row));
|
|
9844
|
+
const line2 = (rows.findLast((row) => /error/i.test(row)) ?? rows.at(-1))?.trim() ?? "";
|
|
9845
|
+
return line2.length > TAIL2 ? `${line2.slice(0, TAIL2)}…` : line2;
|
|
9846
|
+
};
|
|
9847
|
+
var args = (check2, timeoutS) => [
|
|
9848
|
+
"app",
|
|
9849
|
+
"check",
|
|
9850
|
+
"--json",
|
|
9851
|
+
"--port",
|
|
9852
|
+
String(check2.port ?? 0),
|
|
9853
|
+
"--route",
|
|
9854
|
+
check2.route ?? DEFAULT_ROUTE,
|
|
9855
|
+
"--status",
|
|
9856
|
+
String(check2.status ?? DEFAULT_STATUS),
|
|
9857
|
+
"--timeout",
|
|
9858
|
+
String(timeoutS),
|
|
9859
|
+
...check2.run === void 0 ? [] : ["--start", check2.run],
|
|
9860
|
+
...check2.body === void 0 ? [] : ["--body", check2.body]
|
|
9861
|
+
];
|
|
9862
|
+
var resultNotes = (check2, result, ctx) => {
|
|
9863
|
+
const route = check2.route ?? DEFAULT_ROUTE;
|
|
9864
|
+
const line2 = ctx.mask(lastLine(result.output));
|
|
9865
|
+
const output = line2 === "" ? [] : [note("gate.note.output", { line: line2 })];
|
|
9866
|
+
switch (result.kind) {
|
|
9867
|
+
case "ok":
|
|
9868
|
+
return [note(result.reused ? "gate.runtime.reused" : "gate.runtime.ok", { route, status: result.status ?? 0 })];
|
|
9869
|
+
case "crashed":
|
|
9870
|
+
return [note("gate.runtime.crashed", { code: result.exitCode ?? -1 }), ...output];
|
|
9871
|
+
case "no_port":
|
|
9872
|
+
return [note("gate.runtime.no_port", { port: check2.port ?? 0 }), ...output];
|
|
9873
|
+
case "no_start":
|
|
9874
|
+
return [note("gate.runtime.no_start", { port: check2.port ?? 0 })];
|
|
9875
|
+
case "wrong_status":
|
|
9876
|
+
return [
|
|
9877
|
+
note("gate.runtime.wrong_status", {
|
|
9878
|
+
route,
|
|
9879
|
+
status: result.status ?? 0,
|
|
9880
|
+
expected: check2.status ?? DEFAULT_STATUS
|
|
9881
|
+
})
|
|
9882
|
+
];
|
|
9883
|
+
case "body_mismatch":
|
|
9884
|
+
return [note("gate.runtime.body_mismatch", { route, body: ctx.mask(check2.body ?? "") })];
|
|
9885
|
+
case "request_failed":
|
|
9886
|
+
return [note("gate.runtime.request_failed", { route, detail: ctx.mask(result.bodyExcerpt ?? "") })];
|
|
9887
|
+
}
|
|
9888
|
+
};
|
|
9889
|
+
var outcome = (check2, result, ctx) => {
|
|
9890
|
+
const notes2 = [
|
|
9891
|
+
...resultNotes(check2, result, ctx),
|
|
9892
|
+
...result.stopped ? [] : [note("gate.runtime.orphan", { port: check2.port ?? 0 })]
|
|
9893
|
+
];
|
|
9894
|
+
const base = result.kind === "ok" && result.stopped ? passed(notes2) : failed(notes2);
|
|
9895
|
+
return {
|
|
9896
|
+
...base,
|
|
9897
|
+
...check2.run === void 0 ? {} : { command: check2.run },
|
|
9898
|
+
exitCode: result.exitCode ?? (result.kind === "ok" ? 0 : null),
|
|
9899
|
+
stdoutSha256: sha256Hex(result.output),
|
|
9900
|
+
durationMs: result.durationMs
|
|
9901
|
+
};
|
|
9902
|
+
};
|
|
9903
|
+
var runtimeCheck = (check2, ctx) => {
|
|
9904
|
+
if (check2.port === void 0) return failed([note("gate.runtime.no_port_declared")]);
|
|
9905
|
+
if (check2.run !== void 0 && !ctx.trusted)
|
|
9906
|
+
return { ...unverified("untrusted", [note("gate.note.untrusted", { task: ctx.contract.id })]), command: check2.run };
|
|
9907
|
+
const remaining = ctx.deadline - nowMs(ctx.runtime) - PROBE_MARGIN_MS;
|
|
9908
|
+
if (remaining < MIN_REMAINING_MS2) return unverified("budget", [note("gate.note.budget")]);
|
|
9909
|
+
const timeoutS = Math.max(1, Math.min(check2.timeoutS ?? DEFAULT_APP_TIMEOUT_S, Math.floor(remaining / 1e3)));
|
|
9910
|
+
const run4 = ctx.runtime.execSelf(args(check2, timeoutS), ctx.paths.root, timeoutS * 1e3 + PROBE_MARGIN_MS);
|
|
9911
|
+
if (run4.timedOut) return unverified("timeout", [note("gate.note.timeout", { seconds: timeoutS })]);
|
|
9912
|
+
const result = parseAppCheck(run4.stdout);
|
|
9913
|
+
if (result === void 0) {
|
|
9914
|
+
return failed([note("gate.runtime.probe_failed", { line: ctx.mask(lastLine(`${run4.stdout}
|
|
9915
|
+
${run4.stderr}`)) })]);
|
|
9916
|
+
}
|
|
9917
|
+
return outcome(check2, result, ctx);
|
|
9918
|
+
};
|
|
9919
|
+
|
|
9379
9920
|
// src/secrets/baseline.ts
|
|
9380
9921
|
import { join as join18 } from "node:path";
|
|
9381
9922
|
var BASELINE_FILE2 = ".finitemonkey/findings/baseline.json";
|
|
@@ -9670,15 +10211,15 @@ var diffFindings = (diff) => {
|
|
|
9670
10211
|
return scanner.end().filter((finding3) => !SKIPPED.test(finding3.file));
|
|
9671
10212
|
};
|
|
9672
10213
|
var scanStaged = (runtime, root, includeUnstaged = false) => {
|
|
9673
|
-
const
|
|
9674
|
-
const git = runtime.git(
|
|
10214
|
+
const args2 = includeUnstaged ? ["diff", "HEAD", ...DIFF_FLAGS] : ["diff", "--cached", ...DIFF_FLAGS];
|
|
10215
|
+
const git = runtime.git(args2, root);
|
|
9675
10216
|
if (!git.ok) return reject(git.found ? "git diff failed" : "git not found");
|
|
9676
10217
|
return accept(diffFindings(git.stdout));
|
|
9677
10218
|
};
|
|
9678
10219
|
var scanHistory = async (runtime, root) => {
|
|
9679
10220
|
const scanner = diffScanner();
|
|
9680
|
-
const
|
|
9681
|
-
const git = await runtime.gitLines(
|
|
10221
|
+
const args2 = ["log", "-p", "--all", "--format=commit %H", ...DIFF_FLAGS];
|
|
10222
|
+
const git = await runtime.gitLines(args2, root, scanner.push);
|
|
9682
10223
|
if (!git.ok) return reject(git.found ? "git log failed" : "git not found");
|
|
9683
10224
|
return accept(scanner.end().filter((finding3) => !SKIPPED.test(finding3.file)));
|
|
9684
10225
|
};
|
|
@@ -9694,11 +10235,11 @@ var secretsGateStatus = (runtime, root, since) => {
|
|
|
9694
10235
|
if (!changed.ok) return changed;
|
|
9695
10236
|
const baseline = loadBaseline(runtime, root);
|
|
9696
10237
|
if (!baseline.ok) return baseline;
|
|
9697
|
-
const
|
|
10238
|
+
const outcome2 = ratchet([...changed.value, ...untracked2(runtime, root)], baseline.value, runtime.now(), void 0);
|
|
9698
10239
|
const openIncidents = listIncidents(runtime, root).filter(
|
|
9699
10240
|
(incident) => incident.createdAt >= since && incident.state !== "rotacionado" && incident.state !== "fechado"
|
|
9700
10241
|
);
|
|
9701
|
-
return accept({ findings: [...
|
|
10242
|
+
return accept({ findings: [...outcome2.fresh, ...outcome2.expired], openIncidents });
|
|
9702
10243
|
};
|
|
9703
10244
|
|
|
9704
10245
|
// src/gate/checks/secrets.ts
|
|
@@ -9770,8 +10311,8 @@ var testsCheck = (check2, ctx) => {
|
|
|
9770
10311
|
const released2 = grant === void 0 ? {} : { releasedBy: `person@${grant.grantedAt}` };
|
|
9771
10312
|
const releaseNotes = grant === void 0 ? [] : [...notes2, note("gate.note.released", { guard: "tests", reason: grant.reason })];
|
|
9772
10313
|
if (check2.run === void 0) return { ...passed([note("gate.tests.clean"), ...releaseNotes]), ...released2 };
|
|
9773
|
-
const
|
|
9774
|
-
return { ...
|
|
10314
|
+
const outcome2 = runShellCheck(check2, check2.run, ctx);
|
|
10315
|
+
return { ...outcome2, notes: [...outcome2.notes, ...releaseNotes], ...released2 };
|
|
9775
10316
|
};
|
|
9776
10317
|
|
|
9777
10318
|
// src/git/tree.ts
|
|
@@ -9797,13 +10338,13 @@ var IDENTITY_ENV = {
|
|
|
9797
10338
|
GIT_COMMITTER_EMAIL: "finitemonkey@localhost"
|
|
9798
10339
|
};
|
|
9799
10340
|
var failure = (step3, result) => result.timedOut ? `${step3}: timed out` : `${step3}: ${result.stderr.trim() || "git failed"}`;
|
|
9800
|
-
var run = (runtime, repo,
|
|
9801
|
-
const result = runtime.gitWith(
|
|
10341
|
+
var run = (runtime, repo, args2, env, options, input) => {
|
|
10342
|
+
const result = runtime.gitWith(args2, repo.root, {
|
|
9802
10343
|
env,
|
|
9803
10344
|
timeoutMs: options.timeoutMs,
|
|
9804
10345
|
...input === void 0 ? {} : { input }
|
|
9805
10346
|
});
|
|
9806
|
-
return result.ok ? accept(result.stdout.trim()) : reject(failure(
|
|
10347
|
+
return result.ok ? accept(result.stdout.trim()) : reject(failure(args2[0] ?? "git", result));
|
|
9807
10348
|
};
|
|
9808
10349
|
var dropSensitive = (runtime, repo, env, options) => {
|
|
9809
10350
|
const listed4 = run(runtime, repo, ["ls-files", "-z"], env, options);
|
|
@@ -9866,7 +10407,7 @@ var flushHunk = (draft) => {
|
|
|
9866
10407
|
if (draft.current !== void 0) draft.hunks.push(draft.current);
|
|
9867
10408
|
draft.current = void 0;
|
|
9868
10409
|
};
|
|
9869
|
-
var
|
|
10410
|
+
var finish2 = (draft, out) => {
|
|
9870
10411
|
if (draft === void 0) return;
|
|
9871
10412
|
flushHunk(draft);
|
|
9872
10413
|
out.push({
|
|
@@ -9926,7 +10467,7 @@ var parseUnifiedDiff = (text6) => {
|
|
|
9926
10467
|
const line2 = withoutCarriageReturn(raw);
|
|
9927
10468
|
const start = DIFF_GIT.exec(line2);
|
|
9928
10469
|
if (start !== null) {
|
|
9929
|
-
|
|
10470
|
+
finish2(draft, out);
|
|
9930
10471
|
draft = {
|
|
9931
10472
|
oldPath: start[1],
|
|
9932
10473
|
newPath: start[2],
|
|
@@ -9937,7 +10478,7 @@ var parseUnifiedDiff = (text6) => {
|
|
|
9937
10478
|
};
|
|
9938
10479
|
} else if (draft !== void 0) bodyLine(draft, line2);
|
|
9939
10480
|
}
|
|
9940
|
-
|
|
10481
|
+
finish2(draft, out);
|
|
9941
10482
|
return out;
|
|
9942
10483
|
};
|
|
9943
10484
|
var DIFF_ARGS = [
|
|
@@ -10654,8 +11195,8 @@ var openRepo = (runtime, dir) => {
|
|
|
10654
11195
|
};
|
|
10655
11196
|
var globRegex2 = (pattern) => new RegExp(`^${pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`);
|
|
10656
11197
|
var matchesBranch = (branch, patterns) => patterns.some((pattern) => globRegex2(pattern).test(branch));
|
|
10657
|
-
var line = (runtime, root,
|
|
10658
|
-
const result = runtime.git(
|
|
11198
|
+
var line = (runtime, root, args2) => {
|
|
11199
|
+
const result = runtime.git(args2, root);
|
|
10659
11200
|
const value = result.stdout.trim();
|
|
10660
11201
|
return result.ok && value !== "" ? value : void 0;
|
|
10661
11202
|
};
|
|
@@ -10781,20 +11322,21 @@ var DEFAULT_CHECKS = {
|
|
|
10781
11322
|
worktree: worktreeCheck,
|
|
10782
11323
|
merge: mergeCheck,
|
|
10783
11324
|
review: reviewCheck,
|
|
10784
|
-
callers: callersCheck
|
|
11325
|
+
callers: callersCheck,
|
|
11326
|
+
runtime: runtimeCheck
|
|
10785
11327
|
};
|
|
10786
11328
|
|
|
10787
11329
|
// src/gate/run.ts
|
|
10788
11330
|
var FAST_PATH_MS = 10 * 6e4;
|
|
10789
|
-
var toEvidence = (ctx, check2,
|
|
11331
|
+
var toEvidence = (ctx, check2, outcome2) => ({
|
|
10790
11332
|
schema: EVIDENCE_SCHEMA,
|
|
10791
11333
|
task: ctx.contract.id,
|
|
10792
11334
|
check: check2.id,
|
|
10793
11335
|
kind: check2.kind,
|
|
10794
11336
|
treeHash: ctx.treeHash,
|
|
10795
11337
|
at: ctx.runtime.now(),
|
|
10796
|
-
...
|
|
10797
|
-
...check2.run === void 0 ||
|
|
11338
|
+
...outcome2,
|
|
11339
|
+
...check2.run === void 0 || outcome2.command !== void 0 ? {} : { command: check2.run }
|
|
10798
11340
|
});
|
|
10799
11341
|
var reusable = (ledger, ctx, check2) => {
|
|
10800
11342
|
if (!REUSABLE_KINDS.includes(check2.kind)) return false;
|
|
@@ -10990,7 +11532,8 @@ var KNOWN_KINDS = /* @__PURE__ */ new Set([
|
|
|
10990
11532
|
"worktree",
|
|
10991
11533
|
"merge",
|
|
10992
11534
|
"review",
|
|
10993
|
-
"callers"
|
|
11535
|
+
"callers",
|
|
11536
|
+
"runtime"
|
|
10994
11537
|
]);
|
|
10995
11538
|
var requirementText = (t, check2) => {
|
|
10996
11539
|
const key = `gate.require.${check2.kind}`;
|
|
@@ -11183,10 +11726,10 @@ var HELM_READ = /* @__PURE__ */ new Set([
|
|
|
11183
11726
|
"env"
|
|
11184
11727
|
]);
|
|
11185
11728
|
var CURL_WRITE = /^(?:-X|--request|-d|--data.*|-F|--form|-T|--upload-file|-o|--output|-O|--remote-name)$/;
|
|
11186
|
-
var firstPositional = (
|
|
11729
|
+
var firstPositional = (args2, valueFlags = /* @__PURE__ */ new Set()) => {
|
|
11187
11730
|
const out = [];
|
|
11188
|
-
for (let index = 0; index <
|
|
11189
|
-
const arg =
|
|
11731
|
+
for (let index = 0; index < args2.length; index += 1) {
|
|
11732
|
+
const arg = args2[index] ?? "";
|
|
11190
11733
|
if (arg.startsWith("-")) {
|
|
11191
11734
|
if (valueFlags.has(arg)) index += 1;
|
|
11192
11735
|
} else out.push(arg);
|
|
@@ -11221,16 +11764,16 @@ var KUBE_VALUE_FLAGS = /* @__PURE__ */ new Set([
|
|
|
11221
11764
|
"--container",
|
|
11222
11765
|
"--kube-context"
|
|
11223
11766
|
]);
|
|
11224
|
-
var dockerReadOnly = (
|
|
11225
|
-
const words = firstPositional(
|
|
11767
|
+
var dockerReadOnly = (args2) => {
|
|
11768
|
+
const words = firstPositional(args2, DOCKER_VALUE_FLAGS);
|
|
11226
11769
|
const [first, second] = words;
|
|
11227
11770
|
if (first === void 0) return true;
|
|
11228
11771
|
if (DOCKER_GROUPS.has(first))
|
|
11229
11772
|
return second === void 0 || DOCKER_READ.has(second) || first === "compose" && second === "top";
|
|
11230
11773
|
return DOCKER_READ.has(first);
|
|
11231
11774
|
};
|
|
11232
|
-
var kubectlReadOnly = (program,
|
|
11233
|
-
const [verb, object] = firstPositional(
|
|
11775
|
+
var kubectlReadOnly = (program, args2) => {
|
|
11776
|
+
const [verb, object] = firstPositional(args2, KUBE_VALUE_FLAGS);
|
|
11234
11777
|
if (verb === void 0) return true;
|
|
11235
11778
|
if (program === "helm") return HELM_READ.has(verb);
|
|
11236
11779
|
if (verb === "config") return object === "view" || object === "get-contexts" || object === "current-context";
|
|
@@ -11240,24 +11783,24 @@ var kubectlReadOnly = (program, args) => {
|
|
|
11240
11783
|
var writesFile = (command) => command.redirects.some(
|
|
11241
11784
|
(redirect) => (redirect.op === ">" || redirect.op === ">>" || redirect.op === ">|") && !/^(?:\/dev\/null|&?\d)$/.test(redirect.target) && !redirect.op.startsWith("<")
|
|
11242
11785
|
);
|
|
11243
|
-
var gitReadOnly = (
|
|
11244
|
-
const [verb, ...rest] = firstPositional(
|
|
11786
|
+
var gitReadOnly = (args2) => {
|
|
11787
|
+
const [verb, ...rest] = firstPositional(args2, /* @__PURE__ */ new Set(["-C", "-c"]));
|
|
11245
11788
|
if (verb === void 0) return true;
|
|
11246
11789
|
if (GIT_READ.has(verb)) return true;
|
|
11247
11790
|
return GIT_LIST.has(verb) && (rest.length === 0 || verb === "stash" && rest[0] === "list");
|
|
11248
11791
|
};
|
|
11249
11792
|
var programReadOnly = (command) => {
|
|
11250
|
-
const { program, args } = command;
|
|
11251
|
-
if (program === "git") return gitReadOnly(
|
|
11793
|
+
const { program, args: args2 } = command;
|
|
11794
|
+
if (program === "git") return gitReadOnly(args2);
|
|
11252
11795
|
if (program === "docker" || program === "docker-compose")
|
|
11253
|
-
return dockerReadOnly(program === "docker-compose" ? ["compose", ...
|
|
11254
|
-
if (program === "systemctl") return SYSTEMCTL_READ.has(firstPositional(
|
|
11255
|
-
if (program === "kubectl" || program === "helm") return kubectlReadOnly(program,
|
|
11256
|
-
if (program === "curl") return !
|
|
11796
|
+
return dockerReadOnly(program === "docker-compose" ? ["compose", ...args2] : args2);
|
|
11797
|
+
if (program === "systemctl") return SYSTEMCTL_READ.has(firstPositional(args2)[0] ?? "status");
|
|
11798
|
+
if (program === "kubectl" || program === "helm") return kubectlReadOnly(program, args2);
|
|
11799
|
+
if (program === "curl") return !args2.some((arg) => CURL_WRITE.test(arg));
|
|
11257
11800
|
if (program === "find")
|
|
11258
|
-
return !
|
|
11259
|
-
if (program === "sed") return !
|
|
11260
|
-
if (program === "awk") return !
|
|
11801
|
+
return !args2.some((arg) => arg === "-delete" || arg.startsWith("-exec") || arg.startsWith("-ok"));
|
|
11802
|
+
if (program === "sed") return !args2.some((arg) => arg.startsWith("-i") || arg === "--in-place");
|
|
11803
|
+
if (program === "awk") return !args2.some((arg) => arg.includes("system(") || arg.includes(">"));
|
|
11261
11804
|
return READ_PROGRAMS.has(program);
|
|
11262
11805
|
};
|
|
11263
11806
|
var readOnlyCommand = (command) => !writesFile(command) && programReadOnly(command);
|
|
@@ -11317,11 +11860,11 @@ var RSYNC_LONG_VALUE = /* @__PURE__ */ new Set([
|
|
|
11317
11860
|
"--files-from"
|
|
11318
11861
|
]);
|
|
11319
11862
|
var parseSsh = (command) => {
|
|
11320
|
-
const { args } = command;
|
|
11863
|
+
const { args: args2 } = command;
|
|
11321
11864
|
let index = 0;
|
|
11322
11865
|
let noCommand = false;
|
|
11323
|
-
while (index <
|
|
11324
|
-
const arg =
|
|
11866
|
+
while (index < args2.length && (args2[index] ?? "").startsWith("-")) {
|
|
11867
|
+
const arg = args2[index] ?? "";
|
|
11325
11868
|
if (arg === "--") {
|
|
11326
11869
|
index += 1;
|
|
11327
11870
|
break;
|
|
@@ -11330,17 +11873,17 @@ var parseSsh = (command) => {
|
|
|
11330
11873
|
const last = arg.charAt(arg.length - 1);
|
|
11331
11874
|
index += arg.length === 2 && SSH_VALUE.includes(last) ? 2 : 1;
|
|
11332
11875
|
}
|
|
11333
|
-
const destination =
|
|
11876
|
+
const destination = args2[index];
|
|
11334
11877
|
if (destination === void 0) return void 0;
|
|
11335
|
-
return { destination: destination.replace(/^ssh:\/\//, ""), remote:
|
|
11878
|
+
return { destination: destination.replace(/^ssh:\/\//, ""), remote: args2.slice(index + 1), noCommand };
|
|
11336
11879
|
};
|
|
11337
11880
|
var REMOTE_PATH = /^(?:(?:scp|rsync|sftp):\/\/)?(?:[^@/:\s]+@)?(\[[^\]]+\]|[A-Za-z0-9][A-Za-z0-9.-]*)(?::|::|\/)/;
|
|
11338
11881
|
var remoteHostOf = (operand) => {
|
|
11339
11882
|
if (/^[A-Za-z]:[\\/]/.test(operand) || operand.startsWith("/") || operand.startsWith(".")) return void 0;
|
|
11340
|
-
const
|
|
11883
|
+
const url2 = /^(?:scp|rsync|sftp):\/\//.test(operand);
|
|
11341
11884
|
const match = REMOTE_PATH.exec(operand);
|
|
11342
11885
|
if (match === null) return void 0;
|
|
11343
|
-
if (!
|
|
11886
|
+
if (!url2 && !operand.slice(match[0].length - 1).startsWith(":")) return void 0;
|
|
11344
11887
|
return (match[1] ?? "").replace(/^\[|\]$/g, "");
|
|
11345
11888
|
};
|
|
11346
11889
|
var copyOperands = (command, shortValue) => {
|
|
@@ -11445,12 +11988,12 @@ var copyHit = (command, isProd) => {
|
|
|
11445
11988
|
const source = call.sources.map(remoteHostOf).find((host) => host !== void 0 && isProd(host));
|
|
11446
11989
|
return source === void 0 ? void 0 : hit2("read", hostKey(source), command.program);
|
|
11447
11990
|
};
|
|
11448
|
-
var valueAfter = (
|
|
11449
|
-
for (let index = 0; index <
|
|
11450
|
-
const arg =
|
|
11991
|
+
var valueAfter = (args2, ...names) => {
|
|
11992
|
+
for (let index = 0; index < args2.length; index += 1) {
|
|
11993
|
+
const arg = args2[index] ?? "";
|
|
11451
11994
|
const equals = names.find((name) => arg.startsWith(`${name}=`));
|
|
11452
11995
|
if (equals !== void 0) return arg.slice(equals.length + 1);
|
|
11453
|
-
if (names.includes(arg)) return
|
|
11996
|
+
if (names.includes(arg)) return args2[index + 1];
|
|
11454
11997
|
}
|
|
11455
11998
|
return void 0;
|
|
11456
11999
|
};
|
|
@@ -11492,8 +12035,8 @@ var DUMPS = /* @__PURE__ */ new Set(["pg_dump", "mysqldump"]);
|
|
|
11492
12035
|
var databaseHost = (command) => {
|
|
11493
12036
|
const flag2 = valueAfter(command.args, "-h", "--host");
|
|
11494
12037
|
if (flag2 !== void 0) return flag2;
|
|
11495
|
-
const
|
|
11496
|
-
return
|
|
12038
|
+
const url2 = [...command.args, command.env["DATABASE_URL"] ?? ""].map((arg) => URL_HOST.exec(arg)?.[1]).find((host) => host !== void 0);
|
|
12039
|
+
return url2 ?? command.env["PGHOST"];
|
|
11497
12040
|
};
|
|
11498
12041
|
var databaseReadOnly = (command) => {
|
|
11499
12042
|
if (DUMPS.has(command.program)) return true;
|
|
@@ -11667,14 +12210,14 @@ var globalOption = (globals, name, value) => {
|
|
|
11667
12210
|
var gitInvocation = (command) => {
|
|
11668
12211
|
if (command.program !== "git") return void 0;
|
|
11669
12212
|
const globals = { dirs: [], config: {} };
|
|
11670
|
-
const { args } = command;
|
|
12213
|
+
const { args: args2 } = command;
|
|
11671
12214
|
let index = 0;
|
|
11672
|
-
while (index <
|
|
11673
|
-
const arg =
|
|
12215
|
+
while (index < args2.length && (args2[index] ?? "").startsWith("-")) {
|
|
12216
|
+
const arg = args2[index] ?? "";
|
|
11674
12217
|
const equals = arg.indexOf("=");
|
|
11675
12218
|
const name = equals > 2 && arg.startsWith("--") ? arg.slice(0, equals) : arg;
|
|
11676
12219
|
if (WITH_VALUE.has(name) && equals < 0) {
|
|
11677
|
-
globalOption(globals, name,
|
|
12220
|
+
globalOption(globals, name, args2[index + 1] ?? "");
|
|
11678
12221
|
index += 2;
|
|
11679
12222
|
} else {
|
|
11680
12223
|
if (equals > 0) globalOption(globals, name, arg.slice(equals + 1));
|
|
@@ -11684,8 +12227,8 @@ var gitInvocation = (command) => {
|
|
|
11684
12227
|
return {
|
|
11685
12228
|
dirs: globals.dirs,
|
|
11686
12229
|
config: globals.config,
|
|
11687
|
-
subcommand:
|
|
11688
|
-
args:
|
|
12230
|
+
subcommand: args2[index] ?? "",
|
|
12231
|
+
args: args2.slice(index + 1),
|
|
11689
12232
|
command
|
|
11690
12233
|
};
|
|
11691
12234
|
};
|
|
@@ -11819,14 +12362,14 @@ var shortCluster = (building, arg, next2, spec2) => {
|
|
|
11819
12362
|
}
|
|
11820
12363
|
return 1;
|
|
11821
12364
|
};
|
|
11822
|
-
var parseOptions = (
|
|
12365
|
+
var parseOptions = (args2, spec2) => {
|
|
11823
12366
|
const building = { flags: /* @__PURE__ */ new Set(), values: /* @__PURE__ */ new Map(), positionals: [] };
|
|
11824
12367
|
let index = 0;
|
|
11825
|
-
while (index <
|
|
11826
|
-
const arg =
|
|
11827
|
-
const next2 =
|
|
12368
|
+
while (index < args2.length) {
|
|
12369
|
+
const arg = args2[index] ?? "";
|
|
12370
|
+
const next2 = args2[index + 1];
|
|
11828
12371
|
if (arg === "--") {
|
|
11829
|
-
return { ...building, paths:
|
|
12372
|
+
return { ...building, paths: args2.slice(index + 1), dashdash: true };
|
|
11830
12373
|
}
|
|
11831
12374
|
if (arg.startsWith("--")) index += longOption(building, arg, next2, spec2);
|
|
11832
12375
|
else if (arg.startsWith("-") && arg.length > 1 && !/^-\d+$/.test(arg)) {
|
|
@@ -12264,9 +12807,9 @@ var gitVerdict = (invocation, facts) => {
|
|
|
12264
12807
|
|
|
12265
12808
|
// src/git/switch-target.ts
|
|
12266
12809
|
var CREATES = /* @__PURE__ */ new Set(["-c", "-C", "-b", "-B", "--create", "--force-create", "--orphan"]);
|
|
12267
|
-
var operands = (
|
|
12268
|
-
if (
|
|
12269
|
-
return
|
|
12810
|
+
var operands = (args2) => {
|
|
12811
|
+
if (args2.includes("--")) return void 0;
|
|
12812
|
+
return args2.filter((arg) => !arg.startsWith("-"));
|
|
12270
12813
|
};
|
|
12271
12814
|
var switchTarget = (invocation, facts) => {
|
|
12272
12815
|
if (invocation.subcommand !== "switch" && invocation.subcommand !== "checkout") return void 0;
|
|
@@ -12460,8 +13003,8 @@ var BACKUP_PREFIX = "refs/finitemonkey/backup/";
|
|
|
12460
13003
|
var DEFAULT_SNAPSHOT_TIMEOUT_MS = 2500;
|
|
12461
13004
|
var stampOf = (iso) => iso.replace(/[:.]/g, "-");
|
|
12462
13005
|
var slug = (op) => op.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "manual";
|
|
12463
|
-
var optionalLine = (runtime, repo,
|
|
12464
|
-
const result = runtime.git(
|
|
13006
|
+
var optionalLine = (runtime, repo, args2) => {
|
|
13007
|
+
const result = runtime.git(args2, repo.root);
|
|
12465
13008
|
const value = result.stdout.trim();
|
|
12466
13009
|
return result.ok && value !== "" ? value : void 0;
|
|
12467
13010
|
};
|
|
@@ -12566,17 +13109,17 @@ var fileList = (items) => {
|
|
|
12566
13109
|
return items.length > MAX_FILES2 ? `${head} (+${String(items.length - MAX_FILES2)})` : head;
|
|
12567
13110
|
};
|
|
12568
13111
|
var foreignLabel = (t, file) => t(file.reason === "before-session" ? "git.foreign.before" : "git.foreign.other", { path: file.path });
|
|
12569
|
-
var outcomeMessage = (t,
|
|
12570
|
-
switch (
|
|
13112
|
+
var outcomeMessage = (t, outcome2) => {
|
|
13113
|
+
switch (outcome2.kind) {
|
|
12571
13114
|
case "block":
|
|
12572
|
-
return ruleMessage(t,
|
|
13115
|
+
return ruleMessage(t, outcome2.rule, outcome2.command, outcome2.subject);
|
|
12573
13116
|
case "foreign":
|
|
12574
13117
|
return t("git.block.foreign", {
|
|
12575
|
-
command:
|
|
12576
|
-
files: fileList(
|
|
13118
|
+
command: outcome2.command,
|
|
13119
|
+
files: fileList(outcome2.files.map((file) => foreignLabel(t, file)))
|
|
12577
13120
|
});
|
|
12578
13121
|
case "unknown":
|
|
12579
|
-
return t("git.block.unknown", { command:
|
|
13122
|
+
return t("git.block.unknown", { command: outcome2.command });
|
|
12580
13123
|
case "pass":
|
|
12581
13124
|
case "snapshot":
|
|
12582
13125
|
return void 0;
|
|
@@ -12620,10 +13163,10 @@ var review = (input, commands, owner) => {
|
|
|
12620
13163
|
const decision = PROD_PROGRAMS.has(command.program) ? prod().decide(command) : void 0;
|
|
12621
13164
|
if (decision?.kind === "block") return { blocked: decision.reason, snapshots, reads };
|
|
12622
13165
|
if (decision !== void 0) reads.push(decision);
|
|
12623
|
-
for (const
|
|
12624
|
-
const message = outcomeMessage(input.t,
|
|
13166
|
+
for (const outcome2 of guardGitCommand({ runtime: input.runtime, cwd: input.cwd, owner, chain }, command)) {
|
|
13167
|
+
const message = outcomeMessage(input.t, outcome2);
|
|
12625
13168
|
if (message !== void 0) return { blocked: message, snapshots, reads };
|
|
12626
|
-
if (
|
|
13169
|
+
if (outcome2.kind === "snapshot") snapshots.push(outcome2);
|
|
12627
13170
|
}
|
|
12628
13171
|
}
|
|
12629
13172
|
return { blocked: void 0, snapshots, reads };
|
|
@@ -12869,7 +13412,7 @@ var addsMarker = (input, tool, inputs, file) => {
|
|
|
12869
13412
|
return false;
|
|
12870
13413
|
}
|
|
12871
13414
|
};
|
|
12872
|
-
var isReadOnly = (program,
|
|
13415
|
+
var isReadOnly = (program, args2) => READ_ONLY.has(program) || program === "git" && GIT_READ_ONLY.has(args2[0] ?? "");
|
|
12873
13416
|
var shellAddsMarker = (command) => markerCount(command) > 0 && shellWords(command).segments.some((segment) => !isReadOnly(segment.program, segment.args));
|
|
12874
13417
|
var shown2 = (cwd, file) => {
|
|
12875
13418
|
const rel = toPosixPath(relative6(cwd, file));
|
|
@@ -12907,17 +13450,17 @@ var GIT_FLAGS = { title: [], body: ["-m", "--message"], file: ["-F", "--file"] }
|
|
|
12907
13450
|
var GH_FLAGS = { title: ["-t", "--title"], body: ["-b", "--body"], file: ["-F", "--body-file"] };
|
|
12908
13451
|
var GIT_GLOBAL_WITH_VALUE = /* @__PURE__ */ new Set(["-C", "-c", "--git-dir", "--work-tree", "--namespace"]);
|
|
12909
13452
|
var CLUSTER_WITH_MESSAGE = /^-[a-zA-Z]*m$/;
|
|
12910
|
-
var flagValues = (
|
|
13453
|
+
var flagValues = (args2, spec2) => {
|
|
12911
13454
|
const known2 = [...spec2.title, ...spec2.body, ...spec2.file];
|
|
12912
13455
|
const out = [];
|
|
12913
|
-
for (let index = 0; index <
|
|
12914
|
-
const arg =
|
|
13456
|
+
for (let index = 0; index < args2.length; index += 1) {
|
|
13457
|
+
const arg = args2[index] ?? "";
|
|
12915
13458
|
const equals = arg.indexOf("=");
|
|
12916
13459
|
const name = arg.startsWith("--") && equals > 0 ? arg.slice(0, equals) : arg;
|
|
12917
13460
|
if (name !== arg && known2.includes(name)) {
|
|
12918
13461
|
out.push({ flag: name, value: arg.slice(equals + 1) });
|
|
12919
13462
|
} else if (known2.includes(arg) || spec2 === GIT_FLAGS && CLUSTER_WITH_MESSAGE.test(arg)) {
|
|
12920
|
-
out.push({ flag: known2.includes(arg) ? arg : "-m", value:
|
|
13463
|
+
out.push({ flag: known2.includes(arg) ? arg : "-m", value: args2[index + 1] ?? "" });
|
|
12921
13464
|
index += 1;
|
|
12922
13465
|
}
|
|
12923
13466
|
}
|
|
@@ -12931,17 +13474,17 @@ var sourceOf = (value, isFile, segment, heredocs) => {
|
|
|
12931
13474
|
const piped = segment.args.map((arg) => heredocIn(arg, heredocs)).find((text6) => text6 !== void 0);
|
|
12932
13475
|
return { kind: "inline", text: piped ?? "" };
|
|
12933
13476
|
};
|
|
12934
|
-
var collect3 = (target, segment,
|
|
12935
|
-
const values = flagValues(
|
|
13477
|
+
var collect3 = (target, segment, args2, spec2, heredocs) => {
|
|
13478
|
+
const values = flagValues(args2, spec2);
|
|
12936
13479
|
if (values.length === 0) return void 0;
|
|
12937
13480
|
const title = values.find((item) => spec2.title.includes(item.flag));
|
|
12938
13481
|
const bodies = values.filter((item) => !spec2.title.includes(item.flag)).map((item) => sourceOf(item.value, spec2.file.includes(item.flag), segment, heredocs));
|
|
12939
13482
|
return { target, title: title === void 0 ? void 0 : sourceOf(title.value, false, segment, heredocs), bodies };
|
|
12940
13483
|
};
|
|
12941
|
-
var gitSubcommand = (
|
|
13484
|
+
var gitSubcommand = (args2) => {
|
|
12942
13485
|
let index = 0;
|
|
12943
|
-
while (index <
|
|
12944
|
-
index += GIT_GLOBAL_WITH_VALUE.has(
|
|
13486
|
+
while (index < args2.length && (args2[index] ?? "").startsWith("-")) {
|
|
13487
|
+
index += GIT_GLOBAL_WITH_VALUE.has(args2[index] ?? "") ? 2 : 1;
|
|
12945
13488
|
}
|
|
12946
13489
|
return index;
|
|
12947
13490
|
};
|
|
@@ -13157,7 +13700,7 @@ var READERS = /* @__PURE__ */ new Set([
|
|
|
13157
13700
|
var SECRET_NAME = /(?:KEY|SECRET|TOKEN|PASSWORD|PASSWD|PASS|PWD|CREDENTIAL)/i;
|
|
13158
13701
|
var PERSON_ONLY = /\b(?:finitemonkey|fm)(?:\.mjs)?\s+secrets\s+(?:accept\b|incident\s+(?:rotated|close)\b)/;
|
|
13159
13702
|
var LISTS_ENV = /* @__PURE__ */ new Set(["get-childitem", "gci", "dir", "ls"]);
|
|
13160
|
-
var onlyFlags = (
|
|
13703
|
+
var onlyFlags = (args2) => args2.every((arg) => arg.startsWith("-"));
|
|
13161
13704
|
var readTarget = (segment) => {
|
|
13162
13705
|
const redirected = segment.redirectedFrom.find(isSensitivePath);
|
|
13163
13706
|
if (redirected !== void 0) return redirected;
|
|
@@ -13291,17 +13834,17 @@ var secretsPreToolUse = (input) => {
|
|
|
13291
13834
|
// src/secrets/remotes.ts
|
|
13292
13835
|
var USER_AND_SECRET = /^[a-z][a-z0-9+.-]*:\/\/[^\s/@:]+:[^\s/@]+@/i;
|
|
13293
13836
|
var USERINFO = /^[a-z][a-z0-9+.-]*:\/\/(?<user>[^\s/@]+)@/i;
|
|
13294
|
-
var hasCredential = (
|
|
13295
|
-
if (USER_AND_SECRET.test(
|
|
13296
|
-
const user = USERINFO.exec(
|
|
13837
|
+
var hasCredential = (url2) => {
|
|
13838
|
+
if (USER_AND_SECRET.test(url2)) return true;
|
|
13839
|
+
const user = USERINFO.exec(url2)?.groups?.["user"];
|
|
13297
13840
|
return user !== void 0 && scanText(user, { rules: CREDENTIAL_RULES }).length > 0;
|
|
13298
13841
|
};
|
|
13299
13842
|
var parseRemotes = (output) => {
|
|
13300
13843
|
const remotes = /* @__PURE__ */ new Map();
|
|
13301
13844
|
for (const line2 of output.split(/\r?\n/)) {
|
|
13302
|
-
const [name,
|
|
13303
|
-
if (name === void 0 ||
|
|
13304
|
-
remotes.set(name, [...remotes.get(name) ?? [],
|
|
13845
|
+
const [name, url2] = line2.trim().split(/\s+/);
|
|
13846
|
+
if (name === void 0 || url2 === void 0 || name === "") continue;
|
|
13847
|
+
remotes.set(name, [...remotes.get(name) ?? [], url2]);
|
|
13305
13848
|
}
|
|
13306
13849
|
return remotes;
|
|
13307
13850
|
};
|
|
@@ -13550,9 +14093,9 @@ var invocationOf = (entry2, vars) => {
|
|
|
13550
14093
|
const seconds = typeof timeout === "number" && timeout > 0 ? timeout : DEFAULT_TIMEOUT_S;
|
|
13551
14094
|
const timeoutMs = Math.min(seconds * 1e3, PROBE_TIMEOUT_MS2);
|
|
13552
14095
|
const command = expand(raw, vars);
|
|
13553
|
-
const
|
|
13554
|
-
const shell =
|
|
13555
|
-
return { command, args, shell, timeoutMs, display: [command, ...
|
|
14096
|
+
const args2 = strings3(entry2.handler["args"]).map((arg) => expand(arg, vars));
|
|
14097
|
+
const shell = args2.length === 0;
|
|
14098
|
+
return { command, args: args2, shell, timeoutMs, display: [command, ...args2].join(" ") };
|
|
13556
14099
|
};
|
|
13557
14100
|
var versionInvocation = (invocation) => {
|
|
13558
14101
|
if (invocation.shell) {
|
|
@@ -13561,8 +14104,8 @@ var versionInvocation = (invocation) => {
|
|
|
13561
14104
|
}
|
|
13562
14105
|
const at = invocation.args.indexOf("hook");
|
|
13563
14106
|
if (at < 0) return void 0;
|
|
13564
|
-
const
|
|
13565
|
-
return { ...invocation, args, display: [invocation.command, ...
|
|
14107
|
+
const args2 = [...invocation.args.slice(0, at), "version", "--json"];
|
|
14108
|
+
return { ...invocation, args: args2, display: [invocation.command, ...args2].join(" ") };
|
|
13566
14109
|
};
|
|
13567
14110
|
var syntheticPayload = (event, cwd) => {
|
|
13568
14111
|
const base = { session_id: "finitemonkey-doctor", transcript_path: "", cwd, hook_event_name: event };
|
|
@@ -13763,10 +14306,10 @@ var handlerProblems = (at, handler, claude) => {
|
|
|
13763
14306
|
const type = handler["type"];
|
|
13764
14307
|
if (typeof type !== "string" || !HANDLER_TYPES.some((known2) => known2 === type)) return [`${at}.type: unknown`];
|
|
13765
14308
|
const problems = [];
|
|
13766
|
-
const { command, args, timeout, onFailure } = handler;
|
|
14309
|
+
const { command, args: args2, timeout, onFailure } = handler;
|
|
13767
14310
|
if (type === "command" && (typeof command !== "string" || command.trim() === ""))
|
|
13768
14311
|
problems.push(`${at}.command: empty`);
|
|
13769
|
-
if (
|
|
14312
|
+
if (args2 !== void 0 && !(Array.isArray(args2) && args2.every((arg) => typeof arg === "string"))) {
|
|
13770
14313
|
problems.push(`${at}.args: not a list of strings`);
|
|
13771
14314
|
}
|
|
13772
14315
|
if (timeout !== void 0 && !(typeof timeout === "number" && timeout > 0))
|
|
@@ -14185,9 +14728,9 @@ var CHECKS = [
|
|
|
14185
14728
|
];
|
|
14186
14729
|
var probeOnce = (probe) => {
|
|
14187
14730
|
const seen = /* @__PURE__ */ new Map();
|
|
14188
|
-
return (command,
|
|
14189
|
-
const key = [command, ...
|
|
14190
|
-
const known2 = seen.get(key) ?? probe(command,
|
|
14731
|
+
return (command, args2, timeoutMs) => {
|
|
14732
|
+
const key = [command, ...args2].join(" ");
|
|
14733
|
+
const known2 = seen.get(key) ?? probe(command, args2, timeoutMs);
|
|
14191
14734
|
seen.set(key, known2);
|
|
14192
14735
|
return known2;
|
|
14193
14736
|
};
|
|
@@ -14298,93 +14841,7 @@ var doctorCommand = {
|
|
|
14298
14841
|
usage: "finitemonkey doctor [--fix] [--report] [--dry-run] [--json]",
|
|
14299
14842
|
status: "ready",
|
|
14300
14843
|
options: { fix: { type: "boolean" }, report: { type: "boolean" } },
|
|
14301
|
-
run: (ctx,
|
|
14302
|
-
};
|
|
14303
|
-
|
|
14304
|
-
// src/core/args.ts
|
|
14305
|
-
import { parseArgs } from "node:util";
|
|
14306
|
-
|
|
14307
|
-
// src/core/problem.ts
|
|
14308
|
-
var usageProblem = (code, messageKey, fix, params2 = {}) => ({
|
|
14309
|
-
code,
|
|
14310
|
-
messageKey,
|
|
14311
|
-
params: params2,
|
|
14312
|
-
fix,
|
|
14313
|
-
exitCode: ExitCode.Usage
|
|
14314
|
-
});
|
|
14315
|
-
var needsPersonProblem = (messageKey, fix, params2 = {}) => ({
|
|
14316
|
-
code: "needs_confirmation",
|
|
14317
|
-
messageKey,
|
|
14318
|
-
params: params2,
|
|
14319
|
-
fix,
|
|
14320
|
-
exitCode: ExitCode.NeedsPerson
|
|
14321
|
-
});
|
|
14322
|
-
var FmError = class extends Error {
|
|
14323
|
-
problem;
|
|
14324
|
-
constructor(problem4) {
|
|
14325
|
-
super(problem4.code);
|
|
14326
|
-
this.name = "FmError";
|
|
14327
|
-
this.problem = problem4;
|
|
14328
|
-
}
|
|
14329
|
-
};
|
|
14330
|
-
|
|
14331
|
-
// src/core/args.ts
|
|
14332
|
-
var GLOBAL_OPTIONS = {
|
|
14333
|
-
json: { type: "boolean" },
|
|
14334
|
-
lang: { type: "string" },
|
|
14335
|
-
yes: { type: "boolean", short: "y" },
|
|
14336
|
-
"dry-run": { type: "boolean" },
|
|
14337
|
-
version: { type: "boolean", short: "v" },
|
|
14338
|
-
help: { type: "boolean", short: "h" }
|
|
14339
|
-
};
|
|
14340
|
-
var flag = (values, name) => values[name] === true;
|
|
14341
|
-
var looseArgs = (argv) => {
|
|
14342
|
-
const { values, positionals } = parseArgs({
|
|
14343
|
-
args: [...argv],
|
|
14344
|
-
options: GLOBAL_OPTIONS,
|
|
14345
|
-
strict: false,
|
|
14346
|
-
allowPositionals: true
|
|
14347
|
-
});
|
|
14348
|
-
const lang = values.lang;
|
|
14349
|
-
return {
|
|
14350
|
-
positionals,
|
|
14351
|
-
json: flag(values, "json"),
|
|
14352
|
-
yes: flag(values, "yes"),
|
|
14353
|
-
dryRun: flag(values, "dry-run"),
|
|
14354
|
-
version: flag(values, "version"),
|
|
14355
|
-
help: flag(values, "help"),
|
|
14356
|
-
lang: typeof lang === "string" ? lang : void 0
|
|
14357
|
-
};
|
|
14358
|
-
};
|
|
14359
|
-
var resolveCommand = (registry, positionals) => registry.filter((spec2) => spec2.path.every((part2, index) => positionals[index] === part2)).reduce(
|
|
14360
|
-
(best, spec2) => best === void 0 || spec2.path.length > best.consumed ? { spec: spec2, consumed: spec2.path.length } : best,
|
|
14361
|
-
void 0
|
|
14362
|
-
);
|
|
14363
|
-
var strictArgs = (argv, spec2) => {
|
|
14364
|
-
const fix = `finitemonkey help ${spec2.path.join(" ")}`;
|
|
14365
|
-
let parsed;
|
|
14366
|
-
try {
|
|
14367
|
-
parsed = parseArgs({
|
|
14368
|
-
args: [...argv],
|
|
14369
|
-
options: { ...GLOBAL_OPTIONS, ...spec2.options },
|
|
14370
|
-
strict: true,
|
|
14371
|
-
allowPositionals: true
|
|
14372
|
-
});
|
|
14373
|
-
} catch (error) {
|
|
14374
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
14375
|
-
return reject(usageProblem("invalid_arguments", "error.invalid_arguments", fix, { detail }));
|
|
14376
|
-
}
|
|
14377
|
-
const rest = parsed.positionals.slice(spec2.path.length);
|
|
14378
|
-
const max = spec2.maxPositionals ?? 0;
|
|
14379
|
-
const extra = rest[max];
|
|
14380
|
-
if (extra !== void 0) {
|
|
14381
|
-
return reject(usageProblem("unexpected_argument", "error.unexpected_argument", fix, { argument: extra }));
|
|
14382
|
-
}
|
|
14383
|
-
return accept({ values: parsed.values, positionals: rest });
|
|
14384
|
-
};
|
|
14385
|
-
var stringOption = (values, name) => {
|
|
14386
|
-
const value = values[name];
|
|
14387
|
-
return typeof value === "string" ? value : void 0;
|
|
14844
|
+
run: (ctx, args2) => Promise.resolve(runDoctor(ctx, args2.values["fix"] === true, args2.values["report"] === true))
|
|
14388
14845
|
};
|
|
14389
14846
|
|
|
14390
14847
|
// src/gate/baseline-run.ts
|
|
@@ -14399,8 +14856,8 @@ var runBaseline = (options) => {
|
|
|
14399
14856
|
if (commands.length === 0) return { kind: "skipped", reason: "no_commands" };
|
|
14400
14857
|
const checks = {};
|
|
14401
14858
|
for (const check2 of commands) {
|
|
14402
|
-
const
|
|
14403
|
-
checks[check2.id] = { exitCode:
|
|
14859
|
+
const outcome2 = runShellCheck(check2, check2.run ?? "", ctx);
|
|
14860
|
+
checks[check2.id] = { exitCode: outcome2.exitCode ?? null, failures: outcome2.failures ?? [] };
|
|
14404
14861
|
}
|
|
14405
14862
|
if (treeHash(gitAt(ctx.runtime, ctx.paths.root)) !== ctx.treeHash) return { kind: "skipped", reason: "tree_moved" };
|
|
14406
14863
|
writeBaseline(ctx.runtime, ctx.paths, ctx.treeHash, checks);
|
|
@@ -14459,19 +14916,19 @@ var gateCommand = {
|
|
|
14459
14916
|
baseline: { type: "boolean" },
|
|
14460
14917
|
prs: { type: "boolean" }
|
|
14461
14918
|
},
|
|
14462
|
-
run: (ctx,
|
|
14463
|
-
const taskId = stringOption(
|
|
14919
|
+
run: (ctx, args2) => {
|
|
14920
|
+
const taskId = stringOption(args2.values, "task");
|
|
14464
14921
|
const options = {
|
|
14465
14922
|
runtime: ctx.runtime,
|
|
14466
14923
|
cwd: ctx.cwd,
|
|
14467
14924
|
env: ctx.env,
|
|
14468
14925
|
sessionId: void 0,
|
|
14469
|
-
budgetMs: budgetMs(stringOption(
|
|
14470
|
-
fast:
|
|
14926
|
+
budgetMs: budgetMs(stringOption(args2.values, "budget")),
|
|
14927
|
+
fast: args2.values["fast"] === true,
|
|
14471
14928
|
...taskId === void 0 ? {} : { taskId }
|
|
14472
14929
|
};
|
|
14473
|
-
if (
|
|
14474
|
-
if (
|
|
14930
|
+
if (args2.values["prs"] === true) return Promise.resolve(prsResult(ctx));
|
|
14931
|
+
if (args2.values["baseline"] === true) {
|
|
14475
14932
|
const baseline = runBaseline(options);
|
|
14476
14933
|
return Promise.resolve(
|
|
14477
14934
|
success(baseline, [
|
|
@@ -14481,7 +14938,7 @@ var gateCommand = {
|
|
|
14481
14938
|
])
|
|
14482
14939
|
);
|
|
14483
14940
|
}
|
|
14484
|
-
return Promise.resolve(runResult(ctx, runGate(options),
|
|
14941
|
+
return Promise.resolve(runResult(ctx, runGate(options), args2.values["strict"] === true));
|
|
14485
14942
|
}
|
|
14486
14943
|
};
|
|
14487
14944
|
|
|
@@ -14562,11 +15019,11 @@ var mergeVerifyCommand = {
|
|
|
14562
15019
|
status: "ready",
|
|
14563
15020
|
options: { since: { type: "string" }, dropped: { type: "string" } },
|
|
14564
15021
|
maxPositionals: 1,
|
|
14565
|
-
run: (ctx,
|
|
15022
|
+
run: (ctx, args2) => {
|
|
14566
15023
|
const repo = repoOf2(ctx);
|
|
14567
15024
|
if (repo === void 0) return Promise.resolve(failureFrom(ctx.t, notRepository(ctx.cwd)));
|
|
14568
|
-
const dropped = stringOption(
|
|
14569
|
-
const targets2 = targetsOf2(ctx, repo,
|
|
15025
|
+
const dropped = stringOption(args2.values, "dropped");
|
|
15026
|
+
const targets2 = targetsOf2(ctx, repo, args2.positionals[0], stringOption(args2.values, "since"));
|
|
14570
15027
|
if (targets2.length === 0) {
|
|
14571
15028
|
const data = { schema: MERGE_VERIFY_RUN_SCHEMA, merges: [] };
|
|
14572
15029
|
return Promise.resolve(success(data, [ctx.t("git.merge.none", { detail: "HEAD" })]));
|
|
@@ -14674,11 +15131,11 @@ var rescueCommand = {
|
|
|
14674
15131
|
usage: "finitemonkey rescue [--restore <sha> --branch <name>] [--json]",
|
|
14675
15132
|
status: "ready",
|
|
14676
15133
|
options: { restore: { type: "string" }, branch: { type: "string" } },
|
|
14677
|
-
run: (ctx,
|
|
15134
|
+
run: (ctx, args2) => {
|
|
14678
15135
|
const repo = repoOf2(ctx);
|
|
14679
15136
|
if (repo === void 0) return Promise.resolve(failureFrom(ctx.t, notRepository(ctx.cwd)));
|
|
14680
|
-
const sha = stringOption(
|
|
14681
|
-
const branch = stringOption(
|
|
15137
|
+
const sha = stringOption(args2.values, "restore");
|
|
15138
|
+
const branch = stringOption(args2.values, "branch");
|
|
14682
15139
|
if (sha === void 0 && branch === void 0) {
|
|
14683
15140
|
const report2 = rescueReport(ctx.runtime, repo);
|
|
14684
15141
|
return Promise.resolve(success({ schema: RESCUE_SCHEMA, action: "list", ...report2 }, listing(ctx.t, report2)));
|
|
@@ -14709,8 +15166,8 @@ var rescueCommand = {
|
|
|
14709
15166
|
// src/git/undo.ts
|
|
14710
15167
|
import { basename as basename3, dirname as dirname8, join as join36 } from "node:path";
|
|
14711
15168
|
var INDEX_SUBJECT = "finitemonkey index:";
|
|
14712
|
-
var gitLine = (runtime, repo,
|
|
14713
|
-
const result = runtime.git(
|
|
15169
|
+
var gitLine = (runtime, repo, args2) => {
|
|
15170
|
+
const result = runtime.git(args2, repo.root);
|
|
14714
15171
|
const value = result.stdout.trim();
|
|
14715
15172
|
return result.ok && value !== "" ? value : void 0;
|
|
14716
15173
|
};
|
|
@@ -14758,9 +15215,9 @@ var intoWorktree = (runtime, repo, view2) => {
|
|
|
14758
15215
|
const added = runtime.gitWith(["worktree", "add", "--detach", path, view2.commit], repo.root, {});
|
|
14759
15216
|
return added.ok ? accept(path) : reject(failure2("worktree add", added));
|
|
14760
15217
|
};
|
|
14761
|
-
var step2 = (runtime, repo,
|
|
14762
|
-
const result = runtime.gitWith(
|
|
14763
|
-
return result.ok ? accept(void 0) : reject(failure2(
|
|
15218
|
+
var step2 = (runtime, repo, args2) => {
|
|
15219
|
+
const result = runtime.gitWith(args2, repo.root, {});
|
|
15220
|
+
return result.ok ? accept(void 0) : reject(failure2(args2.join(" "), result));
|
|
14764
15221
|
};
|
|
14765
15222
|
var inPlace = (runtime, repo, view2) => {
|
|
14766
15223
|
const current2 = gitLine(runtime, repo, ["rev-parse", "--verify", "--quiet", "HEAD"]);
|
|
@@ -14793,10 +15250,10 @@ var snapshotCommand = {
|
|
|
14793
15250
|
usage: "finitemonkey snapshot [--message <text>] [--json]",
|
|
14794
15251
|
status: "ready",
|
|
14795
15252
|
options: { message: { type: "string", short: "m" } },
|
|
14796
|
-
run: (ctx,
|
|
15253
|
+
run: (ctx, args2) => {
|
|
14797
15254
|
const repo = repoOf2(ctx);
|
|
14798
15255
|
if (repo === void 0) return Promise.resolve(failureFrom(ctx.t, notRepository(ctx.cwd)));
|
|
14799
|
-
const message =
|
|
15256
|
+
const message = args2.values["message"];
|
|
14800
15257
|
const op = typeof message === "string" && message.trim() !== "" ? message.trim() : "manual";
|
|
14801
15258
|
const taken = takeSnapshot(ctx.runtime, repo, { op });
|
|
14802
15259
|
if (!taken.ok) {
|
|
@@ -14826,12 +15283,12 @@ var undoCommand = {
|
|
|
14826
15283
|
status: "ready",
|
|
14827
15284
|
options: { list: { type: "boolean" }, "in-place": { type: "boolean" } },
|
|
14828
15285
|
maxPositionals: 1,
|
|
14829
|
-
run: (ctx,
|
|
15286
|
+
run: (ctx, args2) => {
|
|
14830
15287
|
const repo = repoOf2(ctx);
|
|
14831
15288
|
if (repo === void 0) return Promise.resolve(failureFrom(ctx.t, notRepository(ctx.cwd)));
|
|
14832
15289
|
const views = snapshotViews(ctx.runtime, repo);
|
|
14833
|
-
if (
|
|
14834
|
-
const wanted =
|
|
15290
|
+
if (args2.values["list"] === true) return Promise.resolve(listResult(ctx, views));
|
|
15291
|
+
const wanted = args2.positionals[0];
|
|
14835
15292
|
const view2 = findSnapshot(views, wanted);
|
|
14836
15293
|
if (view2 === void 0) {
|
|
14837
15294
|
return Promise.resolve(
|
|
@@ -14844,7 +15301,7 @@ var undoCommand = {
|
|
|
14844
15301
|
})
|
|
14845
15302
|
);
|
|
14846
15303
|
}
|
|
14847
|
-
const inPlace2 =
|
|
15304
|
+
const inPlace2 = args2.values["in-place"] === true;
|
|
14848
15305
|
if (inPlace2 && !(ctx.yes && isPerson(ctx))) {
|
|
14849
15306
|
return Promise.resolve(
|
|
14850
15307
|
failureFrom(ctx.t, needsPersonProblem("git.undo.confirm", `finitemonkey undo ${view2.ref} --in-place --yes`))
|
|
@@ -14933,8 +15390,8 @@ var helpCommand = {
|
|
|
14933
15390
|
usage: "finitemonkey help [command]",
|
|
14934
15391
|
status: "ready",
|
|
14935
15392
|
maxPositionals: 3,
|
|
14936
|
-
run: (ctx,
|
|
14937
|
-
|
|
15393
|
+
run: (ctx, args2, registry) => Promise.resolve(
|
|
15394
|
+
args2.positionals.length === 0 ? overview(ctx, registry) : topicHelp(ctx, registry, args2.positionals)
|
|
14938
15395
|
)
|
|
14939
15396
|
};
|
|
14940
15397
|
|
|
@@ -14946,8 +15403,8 @@ var hookCommand = {
|
|
|
14946
15403
|
status: "ready",
|
|
14947
15404
|
maxPositionals: 1,
|
|
14948
15405
|
options: { via: { type: "string" } },
|
|
14949
|
-
run: async (ctx,
|
|
14950
|
-
const raw =
|
|
15406
|
+
run: async (ctx, args2) => {
|
|
15407
|
+
const raw = args2.positionals[0] ?? "";
|
|
14951
15408
|
const event = parseHookEvent(raw);
|
|
14952
15409
|
if (event === void 0) {
|
|
14953
15410
|
const params2 = { event: raw, events: HOOK_EVENTS.join(", ") };
|
|
@@ -14956,10 +15413,10 @@ var hookCommand = {
|
|
|
14956
15413
|
usageProblem("unknown_hook_event", "error.unknown_hook_event", "finitemonkey help hook", params2)
|
|
14957
15414
|
);
|
|
14958
15415
|
}
|
|
14959
|
-
if (stringOption(
|
|
15416
|
+
if (stringOption(args2.values, "via") === PLUGIN_VIA && projectOwnsHooks(ctx)) {
|
|
14960
15417
|
return { ok: true, exitCode: 0, data: { event, verdict: "allow" }, raw: { stdout: YIELD_STDOUT, stderr: "" } };
|
|
14961
15418
|
}
|
|
14962
|
-
const
|
|
15419
|
+
const outcome2 = await runHook(event, {
|
|
14963
15420
|
stdin: ctx.io.stdin,
|
|
14964
15421
|
deadlineMs: deadlineFor(event, ctx.env["FINITEMONKEY_HOOK_DEADLINE_MS"]),
|
|
14965
15422
|
handlers: DEFAULT_HANDLERS,
|
|
@@ -14969,11 +15426,11 @@ var hookCommand = {
|
|
|
14969
15426
|
runtime: ctx.runtime,
|
|
14970
15427
|
env: ctx.env
|
|
14971
15428
|
});
|
|
14972
|
-
logHookFailure(ctx, event,
|
|
14973
|
-
const data = { event, verdict:
|
|
14974
|
-
const output = { stdout:
|
|
14975
|
-
if (
|
|
14976
|
-
const message =
|
|
15429
|
+
logHookFailure(ctx, event, outcome2);
|
|
15430
|
+
const data = { event, verdict: outcome2.verdict };
|
|
15431
|
+
const output = { stdout: outcome2.stdout, stderr: outcome2.stderr };
|
|
15432
|
+
if (outcome2.exitCode === 0) return { ok: true, exitCode: 0, data, raw: output };
|
|
15433
|
+
const message = outcome2.stderr.trim();
|
|
14977
15434
|
return {
|
|
14978
15435
|
ok: false,
|
|
14979
15436
|
exitCode: 2,
|
|
@@ -15244,8 +15701,8 @@ var i18nCheckCommand = {
|
|
|
15244
15701
|
usage: "finitemonkey i18n check [--dir <path>]",
|
|
15245
15702
|
status: "ready",
|
|
15246
15703
|
options: { dir: { type: "string" } },
|
|
15247
|
-
run: (ctx,
|
|
15248
|
-
const dir = stringOption(
|
|
15704
|
+
run: (ctx, args2) => {
|
|
15705
|
+
const dir = stringOption(args2.values, "dir");
|
|
15249
15706
|
return Promise.resolve(runI18nCheck(ctx, dir === void 0 ? void 0 : toAbsolutePath(dir, ctx.cwd)));
|
|
15250
15707
|
}
|
|
15251
15708
|
};
|
|
@@ -15589,11 +16046,11 @@ var runInstall = (ctx, request, presetFallback) => {
|
|
|
15589
16046
|
if (ctx.dryRun || !ctx.yes || !needsWrite(plan.value)) return presentPlan(ctx, request, plan.value);
|
|
15590
16047
|
return applyAndReport(ctx, request, plan.value);
|
|
15591
16048
|
};
|
|
15592
|
-
var initRequest = (
|
|
16049
|
+
var initRequest = (args2) => ({
|
|
15593
16050
|
mode: "init",
|
|
15594
|
-
preset: stringOption(
|
|
15595
|
-
bin: stringOption(
|
|
15596
|
-
marketplace:
|
|
16051
|
+
preset: stringOption(args2.values, "preset"),
|
|
16052
|
+
bin: stringOption(args2.values, "bin"),
|
|
16053
|
+
marketplace: args2.values["marketplace"] === true,
|
|
15597
16054
|
showDiff: false
|
|
15598
16055
|
});
|
|
15599
16056
|
var withLookBack = (ctx, result) => {
|
|
@@ -15618,9 +16075,9 @@ var initCommand = {
|
|
|
15618
16075
|
marketplace: { type: "boolean" },
|
|
15619
16076
|
"look-back": { type: "boolean" }
|
|
15620
16077
|
},
|
|
15621
|
-
run: (ctx,
|
|
15622
|
-
const result = runInstall(ctx, initRequest(
|
|
15623
|
-
return Promise.resolve(
|
|
16078
|
+
run: (ctx, args2) => {
|
|
16079
|
+
const result = runInstall(ctx, initRequest(args2), "neutral");
|
|
16080
|
+
return Promise.resolve(args2.values["look-back"] === true ? withLookBack(ctx, result) : result);
|
|
15624
16081
|
}
|
|
15625
16082
|
};
|
|
15626
16083
|
|
|
@@ -15647,7 +16104,7 @@ var policyFalsePositiveCommand = {
|
|
|
15647
16104
|
usage: FIX,
|
|
15648
16105
|
status: "ready",
|
|
15649
16106
|
maxPositionals: 1,
|
|
15650
|
-
run: (ctx,
|
|
16107
|
+
run: (ctx, args2) => Promise.resolve(recordFalsePositive(ctx, args2.positionals[0] ?? ""))
|
|
15651
16108
|
};
|
|
15652
16109
|
|
|
15653
16110
|
// src/commands/prose-check.ts
|
|
@@ -15773,10 +16230,10 @@ var proseCheckCommand = {
|
|
|
15773
16230
|
status: "ready",
|
|
15774
16231
|
options: { stdin: { type: "boolean" }, record: { type: "boolean" } },
|
|
15775
16232
|
maxPositionals: 1e3,
|
|
15776
|
-
run: async (ctx,
|
|
16233
|
+
run: async (ctx, args2) => {
|
|
15777
16234
|
const root = projectRoot(ctx);
|
|
15778
|
-
const mode = { stdin:
|
|
15779
|
-
const reports = await reportsOf(ctx, root,
|
|
16235
|
+
const mode = { stdin: args2.values["stdin"] === true, record: args2.values["record"] === true };
|
|
16236
|
+
const reports = await reportsOf(ctx, root, args2.positionals, mode);
|
|
15780
16237
|
if (!reports.ok) return failureFrom(ctx.t, reports.error);
|
|
15781
16238
|
return resultOf2(ctx, reports.value);
|
|
15782
16239
|
}
|
|
@@ -15831,7 +16288,7 @@ var inputProblem = (ctx, id, reason, days) => {
|
|
|
15831
16288
|
}
|
|
15832
16289
|
return void 0;
|
|
15833
16290
|
};
|
|
15834
|
-
var entryOf3 = (ctx, finding3,
|
|
16291
|
+
var entryOf3 = (ctx, finding3, args2) => {
|
|
15835
16292
|
const now = ctx.runtime.now();
|
|
15836
16293
|
return {
|
|
15837
16294
|
id: finding3.id,
|
|
@@ -15839,30 +16296,30 @@ var entryOf3 = (ctx, finding3, args) => {
|
|
|
15839
16296
|
file: finding3.file,
|
|
15840
16297
|
line: finding3.line,
|
|
15841
16298
|
fingerprint: finding3.fingerprint,
|
|
15842
|
-
state:
|
|
16299
|
+
state: args2.falsePositive ? "falso-positivo" : "aceito",
|
|
15843
16300
|
owner: personName(ctx),
|
|
15844
|
-
reason:
|
|
16301
|
+
reason: args2.reason,
|
|
15845
16302
|
acceptedAt: now,
|
|
15846
|
-
expiresAt: plusDays(now,
|
|
16303
|
+
expiresAt: plusDays(now, args2.days)
|
|
15847
16304
|
};
|
|
15848
16305
|
};
|
|
15849
|
-
var acceptEntry = (ctx,
|
|
16306
|
+
var acceptEntry = (ctx, args2) => {
|
|
15850
16307
|
const root = projectRoot(ctx);
|
|
15851
16308
|
const baseline = loadBaseline(ctx.runtime, root);
|
|
15852
16309
|
if (!baseline.ok) {
|
|
15853
16310
|
return failure3(ctx, baselineInvalid(baseline.error));
|
|
15854
16311
|
}
|
|
15855
16312
|
const scanned = scanPath(ctx.runtime, root, ".");
|
|
15856
|
-
const finding3 = scanned.ok ? scanned.value.find((item) => item.id ===
|
|
16313
|
+
const finding3 = scanned.ok ? scanned.value.find((item) => item.id === args2.id) : void 0;
|
|
15857
16314
|
if (finding3 === void 0) {
|
|
15858
16315
|
return failure3(
|
|
15859
16316
|
ctx,
|
|
15860
16317
|
usageProblem("secrets_finding_not_found", "secrets.error.finding_not_found", "finitemonkey secrets scan", {
|
|
15861
|
-
id:
|
|
16318
|
+
id: args2.id
|
|
15862
16319
|
})
|
|
15863
16320
|
);
|
|
15864
16321
|
}
|
|
15865
|
-
const entry2 = entryOf3(ctx, finding3,
|
|
16322
|
+
const entry2 = entryOf3(ctx, finding3, args2);
|
|
15866
16323
|
const entries = [...baseline.value.entries.filter((item) => item.id !== entry2.id), entry2];
|
|
15867
16324
|
const saved = saveBaseline(ctx.runtime, root, { schema: baseline.value.schema, entries });
|
|
15868
16325
|
if (!saved.ok) {
|
|
@@ -15885,10 +16342,10 @@ var secretsAcceptCommand = {
|
|
|
15885
16342
|
status: "ready",
|
|
15886
16343
|
maxPositionals: 1,
|
|
15887
16344
|
options: { reason: { type: "string" }, days: { type: "string" }, "false-positive": { type: "boolean" } },
|
|
15888
|
-
run: (ctx,
|
|
15889
|
-
const id =
|
|
15890
|
-
const reason = stringOption(
|
|
15891
|
-
const days = daysOf(
|
|
16345
|
+
run: (ctx, args2) => {
|
|
16346
|
+
const id = args2.positionals[0] ?? "";
|
|
16347
|
+
const reason = stringOption(args2.values, "reason");
|
|
16348
|
+
const days = daysOf(args2.values);
|
|
15892
16349
|
const problem4 = inputProblem(ctx, id, reason, days);
|
|
15893
16350
|
if (problem4 !== void 0 || reason === void 0 || days === void 0) {
|
|
15894
16351
|
return Promise.resolve(
|
|
@@ -15899,7 +16356,7 @@ var secretsAcceptCommand = {
|
|
|
15899
16356
|
);
|
|
15900
16357
|
}
|
|
15901
16358
|
return Promise.resolve(
|
|
15902
|
-
acceptEntry(ctx, { id, reason, days, falsePositive:
|
|
16359
|
+
acceptEntry(ctx, { id, reason, days, falsePositive: args2.values["false-positive"] === true })
|
|
15903
16360
|
);
|
|
15904
16361
|
}
|
|
15905
16362
|
};
|
|
@@ -15980,18 +16437,18 @@ var secretsIncidentCommand = {
|
|
|
15980
16437
|
usage: USAGE,
|
|
15981
16438
|
status: "ready",
|
|
15982
16439
|
maxPositionals: 2,
|
|
15983
|
-
run: (ctx,
|
|
15984
|
-
const action = actionOf(
|
|
16440
|
+
run: (ctx, args2) => {
|
|
16441
|
+
const action = actionOf(args2.positionals[0]);
|
|
15985
16442
|
const root = projectRoot(ctx);
|
|
15986
16443
|
if (action === void 0)
|
|
15987
16444
|
return Promise.resolve(
|
|
15988
16445
|
fail2(
|
|
15989
16446
|
ctx,
|
|
15990
|
-
usageProblem("invalid_arguments", "error.invalid_arguments", USAGE, { detail:
|
|
16447
|
+
usageProblem("invalid_arguments", "error.invalid_arguments", USAGE, { detail: args2.positionals[0] ?? "" })
|
|
15991
16448
|
)
|
|
15992
16449
|
);
|
|
15993
16450
|
if (action === "list") return Promise.resolve(list2(ctx, root));
|
|
15994
|
-
const id =
|
|
16451
|
+
const id = args2.positionals[1] ?? "";
|
|
15995
16452
|
const incident = readIncident(ctx.runtime, root, id);
|
|
15996
16453
|
if (!incident.ok) return Promise.resolve(notFound2(ctx, id));
|
|
15997
16454
|
return Promise.resolve(action === "purge" ? purge(ctx, incident.value) : move(ctx, root, incident.value, action));
|
|
@@ -16041,25 +16498,25 @@ var historyIncidents = (ctx, root, fresh3) => fresh3.flatMap((finding3) => {
|
|
|
16041
16498
|
const saved = recordIncident(ctx.runtime, root, draft, HOOK_ACTOR);
|
|
16042
16499
|
return saved.ok ? [saved.value.id] : [];
|
|
16043
16500
|
});
|
|
16044
|
-
var dataOf = (mode,
|
|
16501
|
+
var dataOf = (mode, outcome2, incidents) => {
|
|
16045
16502
|
const findings = [
|
|
16046
|
-
...
|
|
16047
|
-
...
|
|
16048
|
-
...
|
|
16503
|
+
...outcome2.fresh.map((finding3) => view(finding3, "new")),
|
|
16504
|
+
...outcome2.known.map((finding3) => view(finding3, "known")),
|
|
16505
|
+
...outcome2.expired.map((finding3) => view(finding3, "expired"))
|
|
16049
16506
|
];
|
|
16050
16507
|
return {
|
|
16051
16508
|
schema: SECRETS_SCAN_SCHEMA,
|
|
16052
16509
|
mode,
|
|
16053
16510
|
baseline: BASELINE_FILE2,
|
|
16054
16511
|
findings,
|
|
16055
|
-
fixed:
|
|
16512
|
+
fixed: outcome2.fixed.map((entry2) => entry2.id),
|
|
16056
16513
|
incidents,
|
|
16057
16514
|
summary: {
|
|
16058
16515
|
total: findings.length,
|
|
16059
|
-
new:
|
|
16060
|
-
known:
|
|
16061
|
-
expired:
|
|
16062
|
-
fixed:
|
|
16516
|
+
new: outcome2.fresh.length,
|
|
16517
|
+
known: outcome2.known.length,
|
|
16518
|
+
expired: outcome2.expired.length,
|
|
16519
|
+
fixed: outcome2.fixed.length
|
|
16063
16520
|
}
|
|
16064
16521
|
};
|
|
16065
16522
|
};
|
|
@@ -16093,8 +16550,8 @@ var resultOf3 = (ctx, data) => {
|
|
|
16093
16550
|
human2
|
|
16094
16551
|
);
|
|
16095
16552
|
};
|
|
16096
|
-
var prune = (ctx, root, baseline,
|
|
16097
|
-
if (
|
|
16553
|
+
var prune = (ctx, root, baseline, outcome2) => {
|
|
16554
|
+
if (outcome2.fixed.length > 0) saveBaseline(ctx.runtime, root, withoutFixed(baseline, outcome2.fixed));
|
|
16098
16555
|
};
|
|
16099
16556
|
var secretsScanCommand = {
|
|
16100
16557
|
path: ["secrets", "scan"],
|
|
@@ -16102,25 +16559,25 @@ var secretsScanCommand = {
|
|
|
16102
16559
|
usage: "finitemonkey secrets scan [--staged | --history | --path <dir>] [--json]",
|
|
16103
16560
|
status: "ready",
|
|
16104
16561
|
options: { staged: { type: "boolean" }, history: { type: "boolean" }, path: { type: "string" } },
|
|
16105
|
-
run: async (ctx,
|
|
16106
|
-
const mode = modeOf3(
|
|
16562
|
+
run: async (ctx, args2) => {
|
|
16563
|
+
const mode = modeOf3(args2.values);
|
|
16107
16564
|
const fix = "finitemonkey help secrets scan";
|
|
16108
16565
|
if (mode === void 0) return failureFrom(ctx.t, usageProblem("invalid_arguments", "secrets.error.one_mode", fix));
|
|
16109
16566
|
const root = projectRoot(ctx);
|
|
16110
|
-
const target = stringOption(
|
|
16567
|
+
const target = stringOption(args2.values, "path") ?? ".";
|
|
16111
16568
|
const scanned = await runScan(ctx, root, mode, target);
|
|
16112
16569
|
if (!scanned.ok) return failureFrom(ctx.t, gitUnavailable(scanned.error));
|
|
16113
16570
|
const baseline = loadBaseline(ctx.runtime, root);
|
|
16114
16571
|
if (!baseline.ok) return failureFrom(ctx.t, baselineInvalid(baseline.error));
|
|
16115
|
-
const
|
|
16572
|
+
const outcome2 = ratchet(
|
|
16116
16573
|
scanned.value,
|
|
16117
16574
|
baseline.value,
|
|
16118
16575
|
ctx.runtime.now(),
|
|
16119
16576
|
mode === "path" ? scopeOf(target) : void 0
|
|
16120
16577
|
);
|
|
16121
|
-
if (mode === "path") prune(ctx, root, baseline.value,
|
|
16122
|
-
const incidents = mode === "history" ? historyIncidents(ctx, root,
|
|
16123
|
-
return resultOf3(ctx, dataOf(mode,
|
|
16578
|
+
if (mode === "path") prune(ctx, root, baseline.value, outcome2);
|
|
16579
|
+
const incidents = mode === "history" ? historyIncidents(ctx, root, outcome2.fresh) : [];
|
|
16580
|
+
return resultOf3(ctx, dataOf(mode, outcome2, incidents));
|
|
16124
16581
|
}
|
|
16125
16582
|
};
|
|
16126
16583
|
|
|
@@ -16171,7 +16628,11 @@ var checkYaml = (check2) => ({
|
|
|
16171
16628
|
...check2.timeoutS === void 0 ? {} : { timeout_s: check2.timeoutS },
|
|
16172
16629
|
...check2.require === void 0 ? {} : { require: [...check2.require] },
|
|
16173
16630
|
...check2.requireOpen === void 0 ? {} : { require_open: check2.requireOpen },
|
|
16174
|
-
...check2.description === void 0 ? {} : { description: check2.description }
|
|
16631
|
+
...check2.description === void 0 ? {} : { description: check2.description },
|
|
16632
|
+
...check2.port === void 0 ? {} : { port: check2.port },
|
|
16633
|
+
...check2.route === void 0 ? {} : { route: check2.route },
|
|
16634
|
+
...check2.status === void 0 ? {} : { status: check2.status },
|
|
16635
|
+
...check2.body === void 0 ? {} : { body: check2.body }
|
|
16175
16636
|
});
|
|
16176
16637
|
var contractYaml = (contract) => ({
|
|
16177
16638
|
id: contract.id,
|
|
@@ -16287,13 +16748,13 @@ var list3 = (values, name) => {
|
|
|
16287
16748
|
return raw.filter((item) => typeof item === "string" && item.trim() !== "");
|
|
16288
16749
|
};
|
|
16289
16750
|
var csv = (values, name) => list3(values, name).flatMap((item) => item.split(",").map((part2) => part2.trim())).filter((part2) => part2 !== "");
|
|
16290
|
-
var
|
|
16751
|
+
var positive3 = (values, name) => {
|
|
16291
16752
|
const parsed = Number.parseInt(stringOption(values, name) ?? "", 10);
|
|
16292
16753
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
16293
16754
|
};
|
|
16294
16755
|
var draftFrom = (ctx, paths, id, values) => {
|
|
16295
|
-
const files =
|
|
16296
|
-
const lines3 =
|
|
16756
|
+
const files = positive3(values, "budget-files");
|
|
16757
|
+
const lines3 = positive3(values, "budget-lines");
|
|
16297
16758
|
const size = SIZES.find((item) => item === stringOption(values, "size")) ?? "S";
|
|
16298
16759
|
return {
|
|
16299
16760
|
id,
|
|
@@ -16396,7 +16857,7 @@ var taskNewCommand = {
|
|
|
16396
16857
|
status: "ready",
|
|
16397
16858
|
options: TASK_OPTIONS,
|
|
16398
16859
|
maxPositionals: 1,
|
|
16399
|
-
run: (ctx,
|
|
16860
|
+
run: (ctx, args2) => Promise.resolve(newTask(ctx, args2.positionals[0], args2.values))
|
|
16400
16861
|
};
|
|
16401
16862
|
var taskShowCommand = {
|
|
16402
16863
|
path: ["task", "show"],
|
|
@@ -16404,7 +16865,7 @@ var taskShowCommand = {
|
|
|
16404
16865
|
usage: "finitemonkey task show [<id>]",
|
|
16405
16866
|
status: "ready",
|
|
16406
16867
|
maxPositionals: 1,
|
|
16407
|
-
run: (ctx,
|
|
16868
|
+
run: (ctx, args2) => Promise.resolve(showTask(ctx, args2.positionals[0]))
|
|
16408
16869
|
};
|
|
16409
16870
|
var taskDoneCommand = {
|
|
16410
16871
|
path: ["task", "done"],
|
|
@@ -16412,7 +16873,7 @@ var taskDoneCommand = {
|
|
|
16412
16873
|
usage: "finitemonkey task done [<id>]",
|
|
16413
16874
|
status: "ready",
|
|
16414
16875
|
maxPositionals: 1,
|
|
16415
|
-
run: (ctx,
|
|
16876
|
+
run: (ctx, args2) => Promise.resolve(doneTask(ctx, args2.positionals[0]))
|
|
16416
16877
|
};
|
|
16417
16878
|
|
|
16418
16879
|
// src/install/uninstall.ts
|
|
@@ -16462,7 +16923,7 @@ var isEmptyDir = (project, relative9) => {
|
|
|
16462
16923
|
const listed4 = project.runtime.listDir(project.abs(relative9));
|
|
16463
16924
|
return listed4.ok && listed4.value.length === 0;
|
|
16464
16925
|
};
|
|
16465
|
-
var
|
|
16926
|
+
var finish3 = (project, plan) => {
|
|
16466
16927
|
const target = plan.purge ? STATE_DIR : LOCK_FILE;
|
|
16467
16928
|
const removed = project.runtime.remove(project.abs(target));
|
|
16468
16929
|
if (!removed.ok) return reject({ path: target, detail: removed.error });
|
|
@@ -16477,7 +16938,7 @@ var applyRemoval = (project, plan) => {
|
|
|
16477
16938
|
}
|
|
16478
16939
|
return accept(void 0);
|
|
16479
16940
|
});
|
|
16480
|
-
return changed.ok ?
|
|
16941
|
+
return changed.ok ? finish3(project, plan) : changed;
|
|
16481
16942
|
};
|
|
16482
16943
|
|
|
16483
16944
|
// src/commands/uninstall.ts
|
|
@@ -16508,22 +16969,22 @@ var linesOf2 = (ctx, data) => [
|
|
|
16508
16969
|
ctx.t("install.uninstall.outside"),
|
|
16509
16970
|
...OUTSIDE.map(({ key, command }) => ` ${ctx.t(key, { command })}`)
|
|
16510
16971
|
];
|
|
16511
|
-
var fixFor = (
|
|
16972
|
+
var fixFor = (args2) => [
|
|
16512
16973
|
"finitemonkey uninstall --yes",
|
|
16513
|
-
...
|
|
16514
|
-
...
|
|
16974
|
+
...args2.values["purge"] === true ? ["--purge"] : [],
|
|
16975
|
+
...args2.values["keep-generated"] === true ? ["--keep-generated"] : []
|
|
16515
16976
|
].join(" ");
|
|
16516
|
-
var runUninstall = (ctx,
|
|
16977
|
+
var runUninstall = (ctx, args2) => {
|
|
16517
16978
|
const { project } = openProject(ctx);
|
|
16518
16979
|
const lock = readPreviousLock(project);
|
|
16519
16980
|
if (!lock.ok) return failureFrom(ctx.t, planProblem(lock.error));
|
|
16520
16981
|
if (lock.value === void 0) return failureFrom(ctx.t, notInstalled());
|
|
16521
|
-
const options = { purge:
|
|
16982
|
+
const options = { purge: args2.values["purge"] === true, keepGenerated: args2.values["keep-generated"] === true };
|
|
16522
16983
|
const plan = planRemoval(project, lock.value, options);
|
|
16523
16984
|
const preview = dataOf2(project.root, plan, false);
|
|
16524
16985
|
if (ctx.dryRun) return success(preview, [...linesOf2(ctx, preview), ctx.t("install.dry_run")]);
|
|
16525
16986
|
if (!ctx.yes) {
|
|
16526
|
-
const next2 = fixFor(
|
|
16987
|
+
const next2 = fixFor(args2);
|
|
16527
16988
|
const problem4 = confirmProblem("uninstall", ctx.t("install.uninstall.question"), next2);
|
|
16528
16989
|
return { ...failureFrom(ctx.t, { ...problem4, data: preview }, linesOf2(ctx, preview)), next: next2 };
|
|
16529
16990
|
}
|
|
@@ -16538,7 +16999,7 @@ var uninstallCommand = {
|
|
|
16538
16999
|
usage: "finitemonkey uninstall [--purge] [--keep-generated] [--dry-run] [--yes]",
|
|
16539
17000
|
status: "ready",
|
|
16540
17001
|
options: { purge: { type: "boolean" }, "keep-generated": { type: "boolean" } },
|
|
16541
|
-
run: (ctx,
|
|
17002
|
+
run: (ctx, args2) => Promise.resolve(runUninstall(ctx, args2))
|
|
16542
17003
|
};
|
|
16543
17004
|
|
|
16544
17005
|
// src/commands/update.ts
|
|
@@ -16561,14 +17022,14 @@ var check = (ctx, bin) => {
|
|
|
16561
17022
|
error: { code: "install_outdated", message: ctx.t("error.install_outdated"), fix: "finitemonkey update --yes" }
|
|
16562
17023
|
};
|
|
16563
17024
|
};
|
|
16564
|
-
var runUpdate = (ctx,
|
|
16565
|
-
const bin = stringOption(
|
|
16566
|
-
if (
|
|
17025
|
+
var runUpdate = (ctx, args2) => {
|
|
17026
|
+
const bin = stringOption(args2.values, "bin");
|
|
17027
|
+
if (args2.values["check"] === true) return check(ctx, bin);
|
|
16567
17028
|
const { project } = openProject(ctx);
|
|
16568
17029
|
const previous = readPreviousLock(project);
|
|
16569
17030
|
if (!previous.ok) return failureFrom(ctx.t, planProblem(previous.error));
|
|
16570
17031
|
if (previous.value === void 0) return failureFrom(ctx.t, notInstalled());
|
|
16571
|
-
const preset = stringOption(
|
|
17032
|
+
const preset = stringOption(args2.values, "preset");
|
|
16572
17033
|
const request = { mode: "update", preset, bin, marketplace: false, showDiff: true };
|
|
16573
17034
|
return runInstall(ctx, request, previous.value.preset);
|
|
16574
17035
|
};
|
|
@@ -16578,7 +17039,7 @@ var updateCommand = {
|
|
|
16578
17039
|
usage: "finitemonkey update [--check] [--preset neutral|gabriel] [--bin <path>] [--yes]",
|
|
16579
17040
|
status: "ready",
|
|
16580
17041
|
options: { check: { type: "boolean" }, preset: { type: "string" }, bin: { type: "string" } },
|
|
16581
|
-
run: (ctx,
|
|
17042
|
+
run: (ctx, args2) => Promise.resolve(runUpdate(ctx, args2))
|
|
16582
17043
|
};
|
|
16583
17044
|
|
|
16584
17045
|
// src/commands/version.ts
|
|
@@ -16614,6 +17075,7 @@ var REGISTRY = [
|
|
|
16614
17075
|
undoCommand,
|
|
16615
17076
|
rescueCommand,
|
|
16616
17077
|
mergeVerifyCommand,
|
|
17078
|
+
appCheckCommand,
|
|
16617
17079
|
versionCommand,
|
|
16618
17080
|
helpCommand
|
|
16619
17081
|
];
|
|
@@ -16692,9 +17154,9 @@ var failWith = (ctx, name, problem4) => ({
|
|
|
16692
17154
|
});
|
|
16693
17155
|
var invoke = (ctx, argv, spec2, registry) => {
|
|
16694
17156
|
const name = commandName(spec2);
|
|
16695
|
-
const
|
|
16696
|
-
if (!
|
|
16697
|
-
return { name, execute: () => spec2.run(ctx,
|
|
17157
|
+
const args2 = strictArgs(argv, spec2);
|
|
17158
|
+
if (!args2.ok) return failWith(ctx, name, args2.error);
|
|
17159
|
+
return { name, execute: () => spec2.run(ctx, args2.value, registry) };
|
|
16698
17160
|
};
|
|
16699
17161
|
var builtin = (registry, name) => registry.find((spec2) => commandName(spec2) === name);
|
|
16700
17162
|
var dispatch = (ctx, argv, loose, registry) => {
|