prae-cli 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/bin.js +1 -1
- package/lib/{checkpoint-BqJ8xwky.js → checkpoint-BLOGdWFu.js} +1 -1
- package/lib/cli-BlWTUnGJ.js +6 -0
- package/lib/{cli-DPldZ2ND.js → cli-C_6dosaw.js} +399 -37
- package/lib/docs/pilot-claude-code.md +22 -21
- package/lib/{hook-Gll2spTP.js → hook-DxLgNtc4.js} +3 -5
- package/lib/index.js +4 -6
- package/lib/{init-DRd-IRR6.js → init-BPlBJvA-.js} +10 -4
- package/lib/{instructions-DihPiiC2.js → instructions-fCJ4j7ce.js} +2 -2
- package/lib/{mcp-D521EoP6.js → mcp-DdEDvTvR.js} +2 -2
- package/lib/playground.js +713 -109
- package/lib/prae-baseline.prae.json +144 -1
- package/lib/{receipt-check-CUuEjGHL.js → receipt-check-2F4zLEW5.js} +1 -1
- package/lib/{src-wG36kT6K.js → src-2iJy5MZc.js} +1 -1
- package/lib/src-CZYvvEn5.js +1691 -0
- package/lib/{src-DMoYsdfo.js → src-CwBEFhww.js} +1 -1
- package/lib/{test-run-C8dHjIE2.js → test-run-BGsK-inZ.js} +1 -1
- package/lib/{views-CUcixte0.js → views-C7DD-Oif.js} +1 -1
- package/package.json +4 -4
- package/lib/cli-BcAJlB9B.js +0 -8
- package/lib/evaluate-DhoGQw0Z.js +0 -521
- package/lib/frameworks-BgZHGKiH.js +0 -118
- package/lib/pack-h5n43S0F.js +0 -448
- /package/lib/{ocsf-DF9cMiQJ.js → ocsf-BwWyM7hc.js} +0 -0
- /package/lib/{src-BuaOiL2v.js → src-B25SHWcz.js} +0 -0
- /package/lib/{src-BlmsTGdY.js → src-BoBCmiwj.js} +0 -0
- /package/lib/{src-Cy-Acrgj.js → src-CuiWC80o.js} +0 -0
- /package/lib/{src-CDYyZyeU.js → src-XukJfuml.js} +0 -0
package/lib/bin.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
//#region src/bin.ts
|
|
3
3
|
const argv = process.argv.slice(2);
|
|
4
|
-
(argv[0] === "hook" && argv[1] === "claude-code" ? import("./hook-
|
|
4
|
+
(argv[0] === "hook" && argv[1] === "claude-code" ? import("./hook-DxLgNtc4.js").then(({ runHook }) => runHook(argv.slice(2))) : import("./cli-BlWTUnGJ.js").then(({ main }) => main(argv))).catch((error) => {
|
|
5
5
|
console.error(`prae: ${error instanceof Error ? error.message : error}`);
|
|
6
6
|
process.exit(1);
|
|
7
7
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as
|
|
3
|
-
import { t as
|
|
4
|
-
import { a as verifyEntries, b as seal, g as GENESIS, h as verifySignature, l as verifyBytes, n as Ledger, r as readEntries, t as verifyGrowing, u as fingerprint, v as chain } from "./src-Cy-Acrgj.js";
|
|
5
|
-
import { a as renderPacks, c as renderNav, i as renderOverview, l as renderShell, n as renderApprovals, o as CONTROLS, r as renderCompliance, s as esc, t as navFor, u as VERDICT_LABEL$1 } from "./views-CUcixte0.js";
|
|
1
|
+
import { c as withinAny, i as evaluate, n as FRAMEWORKS, o as hostOf, r as cite, t as parsePack } from "./src-CZYvvEn5.js";
|
|
2
|
+
import { a as verifyEntries, b as seal, g as GENESIS, h as verifySignature, l as verifyBytes, n as Ledger, r as readEntries, t as verifyGrowing, u as fingerprint, v as chain } from "./src-CuiWC80o.js";
|
|
3
|
+
import { a as renderPacks, c as renderNav, i as renderOverview, l as renderShell, n as renderApprovals, o as CONTROLS, r as renderCompliance, s as esc, t as navFor, u as VERDICT_LABEL$1 } from "./views-C7DD-Oif.js";
|
|
6
4
|
import { createRequire } from "node:module";
|
|
7
5
|
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, statSync, watch, writeFileSync } from "node:fs";
|
|
8
6
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
@@ -866,6 +864,327 @@ function readRedteam(dir, files) {
|
|
|
866
864
|
};
|
|
867
865
|
}
|
|
868
866
|
|
|
867
|
+
//#endregion
|
|
868
|
+
//#region ../controls/src/inspect.ts
|
|
869
|
+
/**
|
|
870
|
+
* How a rule is evaluated, one label per matcher field it uses. Every one
|
|
871
|
+
* of them runs in the PRAE kernel's deterministic matcher; these are the
|
|
872
|
+
* only engines the rule model has. There is no semantic model and no
|
|
873
|
+
* syntax tree behind any rule: `command` is a lexical decomposition.
|
|
874
|
+
*/
|
|
875
|
+
const ENGINES = {
|
|
876
|
+
tool: "Tool / capability match",
|
|
877
|
+
capability: "Tool / capability match",
|
|
878
|
+
plugin: "Tool / capability match",
|
|
879
|
+
agent: "Agent match",
|
|
880
|
+
path: "Path glob match",
|
|
881
|
+
host: "Host list match",
|
|
882
|
+
arg: "Argument value match",
|
|
883
|
+
count: "Session call count",
|
|
884
|
+
command: "Command decomposition (lexical)",
|
|
885
|
+
secrets: "Content inspection (regex + entropy)"
|
|
886
|
+
};
|
|
887
|
+
function enginesOf(rule) {
|
|
888
|
+
const keys = Object.keys(rule.when);
|
|
889
|
+
if (keys.length === 0) return ["Every call (no matcher)"];
|
|
890
|
+
return [...new Set(keys.map((k) => ENGINES[k] ?? `Unknown matcher: ${k}`))];
|
|
891
|
+
}
|
|
892
|
+
const list = (v) => v === void 0 ? [] : typeof v === "string" ? [v] : v;
|
|
893
|
+
const quoted = (v) => v.map((x) => `\`${String(x)}\``).join(", ");
|
|
894
|
+
/** The plain-language reading, or undefined when it cannot be given reliably. */
|
|
895
|
+
function logicOf(rule) {
|
|
896
|
+
const w = rule.when;
|
|
897
|
+
if (Object.keys(w).some((k) => ENGINES[k] === void 0)) return void 0;
|
|
898
|
+
const subjects = [];
|
|
899
|
+
if (w.capability !== void 0) subjects.push(`calls with capability ${quoted(list(w.capability))}`);
|
|
900
|
+
if (w.tool !== void 0) subjects.push(`calls to ${quoted(list(w.tool))}`);
|
|
901
|
+
if (w.plugin !== void 0) subjects.push(`tools registered by ${quoted(list(w.plugin))}`);
|
|
902
|
+
const evaluates = subjects.length === 0 ? "Every tool call" : `${subjects.join(" that are also ")}`.replace(/^./, (c$1) => c$1.toUpperCase());
|
|
903
|
+
const targets = [];
|
|
904
|
+
if (w.path !== void 0) targets.push(w.path.arg === void 0 ? "the path argument (the first conventional one present)" : `the path in argument \`${w.path.arg}\``);
|
|
905
|
+
if (w.host !== void 0) targets.push(w.host.arg === void 0 ? "the URL argument's host" : `the host of argument \`${w.host.arg}\``);
|
|
906
|
+
if (w.command !== void 0) targets.push("the shell command line, read lexically");
|
|
907
|
+
if (w.arg !== void 0) targets.push(`argument${w.arg.length === 1 ? "" : "s"} ${quoted(w.arg.map((a) => a.name))}`);
|
|
908
|
+
if (w.count !== void 0) targets.push("this session's count of calls with the same capability");
|
|
909
|
+
if (w.secrets !== void 0) targets.push("findings the content inspection attached to the call");
|
|
910
|
+
if (w.agent !== void 0) targets.push("the agent making the call");
|
|
911
|
+
const target = targets.length === 0 ? "The call as a whole" : targets.join("; ");
|
|
912
|
+
const condition = [];
|
|
913
|
+
if (w.agent !== void 0) condition.push(`the agent is ${quoted(list(w.agent))}`);
|
|
914
|
+
if (w.path?.inside !== void 0) condition.push(`the path is under ${quoted(w.path.inside)}`);
|
|
915
|
+
if (w.path?.outside !== void 0) condition.push(`the path is outside all of ${quoted(w.path.outside)}`);
|
|
916
|
+
if (w.host?.in !== void 0) condition.push(`the host is one of ${quoted(w.host.in)}`);
|
|
917
|
+
if (w.host?.notIn !== void 0) condition.push(`the host is not one of ${quoted(w.host.notIn)}`);
|
|
918
|
+
for (const a of w.arg ?? []) {
|
|
919
|
+
if (a.present !== void 0) condition.push(`\`${a.name}\` is ${a.present ? "present" : "absent"}`);
|
|
920
|
+
if (a.above !== void 0) condition.push(`\`${a.name}\` is above ${a.above}`);
|
|
921
|
+
if (a.below !== void 0) condition.push(`\`${a.name}\` is below ${a.below}`);
|
|
922
|
+
if (a.equals !== void 0) condition.push(`\`${a.name}\` equals \`${String(a.equals)}\``);
|
|
923
|
+
if (a.oneOf !== void 0) condition.push(`\`${a.name}\` is one of ${quoted(a.oneOf)}`);
|
|
924
|
+
}
|
|
925
|
+
if (w.count !== void 0) condition.push(`more than ${w.count.above} such calls have already run in this session`);
|
|
926
|
+
if (w.secrets !== void 0) {
|
|
927
|
+
const n = w.secrets.atLeast ?? 1;
|
|
928
|
+
condition.push(`${n === 1 ? "a finding" : `at least ${n} findings`}${w.secrets.types === void 0 ? "" : ` of type ${quoted(w.secrets.types)}`}${w.secrets.minConfidence === void 0 ? "" : ` with confidence ≥ ${w.secrets.minConfidence}`}`);
|
|
929
|
+
}
|
|
930
|
+
const c = w.command;
|
|
931
|
+
if (c !== void 0) {
|
|
932
|
+
if (c.name !== void 0) condition.push(`the program (or a wrapper it runs through) is ${quoted(list(c.name))}`);
|
|
933
|
+
const must = list(c.token).filter((t) => !t.startsWith("!"));
|
|
934
|
+
const never = list(c.token).filter((t) => t.startsWith("!")).map((t) => t.slice(1));
|
|
935
|
+
if (must.length > 0) condition.push(`it carries all of ${quoted(must)}`);
|
|
936
|
+
if (never.length > 0) condition.push(`it carries none of ${quoted(never)}`);
|
|
937
|
+
if (c.anyToken !== void 0) condition.push(`it carries any of ${quoted(list(c.anyToken))}`);
|
|
938
|
+
if (c.pipedTo !== void 0) condition.push(`it pipes into ${quoted(list(c.pipedTo))}`);
|
|
939
|
+
if (c.pipeline !== void 0) condition.push(`its pipeline has the shape ${quoted(list(c.pipeline))}`);
|
|
940
|
+
}
|
|
941
|
+
if (condition.length === 0) condition.push("always: no further condition");
|
|
942
|
+
const e = rule.effect;
|
|
943
|
+
return {
|
|
944
|
+
evaluates,
|
|
945
|
+
target,
|
|
946
|
+
condition,
|
|
947
|
+
action: e.kind === "deny" ? "Refuses the call before it runs." : e.kind === "ask" ? "Holds the call until a person allows or refuses it." : e.kind === "warn" ? "Lets the call run and records a warning." : e.kind === "allow" ? "Allows the call and names this rule in the evidence; an allow never overrides another rule's refusal." : `Rewrites ${quoted(Object.keys(e.set))} before the call runs.`
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
const isEvent = (e) => e.tool.startsWith("prae:") || e.tool === "system-prompt";
|
|
951
|
+
/**
|
|
952
|
+
* Per pack name, every row in which a gate showed it in force — its
|
|
953
|
+
* activation or reload row, or a decision attributed to it — and its
|
|
954
|
+
* removal rows, in ledger order.
|
|
955
|
+
*/
|
|
956
|
+
function packActivity(entries) {
|
|
957
|
+
const out = /* @__PURE__ */ new Map();
|
|
958
|
+
const add = (name, seen) => {
|
|
959
|
+
const list$1 = out.get(name);
|
|
960
|
+
if (list$1 === void 0) out.set(name, [seen]);
|
|
961
|
+
else list$1.push(seen);
|
|
962
|
+
};
|
|
963
|
+
for (const e of entries) if (e.tool === "prae:pack") {
|
|
964
|
+
if (e.rule === "pack.activated" || e.rule === "pack.reloaded") add(e.pack.name, {
|
|
965
|
+
row: e,
|
|
966
|
+
kind: "in-force"
|
|
967
|
+
});
|
|
968
|
+
else if (e.rule === "pack.removed") add(e.pack.name, {
|
|
969
|
+
row: e,
|
|
970
|
+
kind: "removed"
|
|
971
|
+
});
|
|
972
|
+
} else if (!isEvent(e) && e.pack !== void 0) add(e.pack.name, {
|
|
973
|
+
row: e,
|
|
974
|
+
kind: "in-force"
|
|
975
|
+
});
|
|
976
|
+
return out;
|
|
977
|
+
}
|
|
978
|
+
/** Whether a gate confirmed this exact definition of a pack in force. */
|
|
979
|
+
function activityOf(pack, activity, failed) {
|
|
980
|
+
if (failed !== void 0) return {
|
|
981
|
+
state: "failed",
|
|
982
|
+
note: `A gate refused this definition: ${failed.why}`,
|
|
983
|
+
seq: failed.seq,
|
|
984
|
+
at: failed.at,
|
|
985
|
+
sessions: []
|
|
986
|
+
};
|
|
987
|
+
const rows = activity.get(pack.name) ?? [];
|
|
988
|
+
const same = (r) => r.pack.version === pack.version && (pack.sha256 === void 0 || r.pack.sha256 === void 0 || r.pack.sha256 === pack.sha256);
|
|
989
|
+
const last = rows.at(-1);
|
|
990
|
+
if (last?.kind === "removed") return {
|
|
991
|
+
state: "inactive",
|
|
992
|
+
note: `A gate sealed this pack removed (row #${last.row.seq}); its rules no longer apply there.`,
|
|
993
|
+
seq: last.row.seq,
|
|
994
|
+
at: last.row.at,
|
|
995
|
+
sessions: []
|
|
996
|
+
};
|
|
997
|
+
const confirming = rows.filter((s) => s.kind === "in-force" && same(s.row));
|
|
998
|
+
const newest = confirming.at(-1);
|
|
999
|
+
if (newest !== void 0) return {
|
|
1000
|
+
state: "active",
|
|
1001
|
+
note: `A gate showed ${pack.name} ${pack.version} in force at row #${newest.row.seq}. That is the last confirmation; PRAE has no heartbeat that says a gate is running now.`,
|
|
1002
|
+
seq: newest.row.seq,
|
|
1003
|
+
at: newest.row.at,
|
|
1004
|
+
sessions: [...new Set(confirming.flatMap((s) => s.row.session === void 0 ? [] : [s.row.session]))]
|
|
1005
|
+
};
|
|
1006
|
+
const other = rows.at(-1);
|
|
1007
|
+
return {
|
|
1008
|
+
state: "unconfirmed",
|
|
1009
|
+
note: other !== void 0 ? `Verification required: the gate last showed ${pack.name} ${other.row.pack.version} in force (row #${other.row.seq}); this configured definition has not been confirmed by any gate.` : "Verification required: configured, but no gate has sealed this pack in force in this record yet.",
|
|
1010
|
+
sessions: []
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* The rows that can be evidence: every row except the console's own
|
|
1015
|
+
* deployment rows. Placing a pack is an operation, not something the agent
|
|
1016
|
+
* did or a gate decided, so it never counts toward a control — not as a
|
|
1017
|
+
* recorded event, and never as a refusal.
|
|
1018
|
+
*/
|
|
1019
|
+
function evidenceRows(entries) {
|
|
1020
|
+
return entries.filter((e) => e.tool !== "prae:deploy");
|
|
1021
|
+
}
|
|
1022
|
+
/** How long a written pack waits for a gate before it needs verification. */
|
|
1023
|
+
const CONFIRM_WINDOW_MS = 2e4;
|
|
1024
|
+
/**
|
|
1025
|
+
* Each deployment's lifecycle, read from the ledger alone: the console's
|
|
1026
|
+
* `deploy.requested` row, then what a gate sealed after it. ACTIVE only on
|
|
1027
|
+
* a gate's activation or reload row carrying the deployed file's exact
|
|
1028
|
+
* sha256; FAILED on the console's own failure row or a gate refusing the
|
|
1029
|
+
* file; INACTIVE when a gate later sealed it removed. With no gate row,
|
|
1030
|
+
* APPLYING for a short window and then VERIFICATION_REQUIRED — the file is
|
|
1031
|
+
* configured, and nothing has shown it enforced.
|
|
1032
|
+
*/
|
|
1033
|
+
function deploymentsOf(entries, now = Date.now()) {
|
|
1034
|
+
const out = [];
|
|
1035
|
+
const requests = entries.filter((e) => e.tool === "prae:deploy" && e.deploy?.action === "requested");
|
|
1036
|
+
for (const r of requests) {
|
|
1037
|
+
const d = r.deploy;
|
|
1038
|
+
if (d === void 0 || r.pack.sha256 === void 0) continue;
|
|
1039
|
+
const sha = r.pack.sha256;
|
|
1040
|
+
const after = entries.filter((e) => e.seq > r.seq);
|
|
1041
|
+
const base = {
|
|
1042
|
+
operation: d.operation,
|
|
1043
|
+
pack: r.pack.name,
|
|
1044
|
+
version: r.pack.version,
|
|
1045
|
+
sha256: sha,
|
|
1046
|
+
file: d.file,
|
|
1047
|
+
target: d.target,
|
|
1048
|
+
environment: d.environment,
|
|
1049
|
+
rules: d.rules,
|
|
1050
|
+
controls: d.controls,
|
|
1051
|
+
...d.operator === void 0 ? {} : { operator: d.operator },
|
|
1052
|
+
requestedAt: r.at,
|
|
1053
|
+
seq: r.seq
|
|
1054
|
+
};
|
|
1055
|
+
const failedRow = after.find((e) => e.tool === "prae:deploy" && e.deploy?.action === "failed" && e.deploy.operation === d.operation);
|
|
1056
|
+
if (failedRow !== void 0) {
|
|
1057
|
+
out.push({
|
|
1058
|
+
...base,
|
|
1059
|
+
state: "FAILED",
|
|
1060
|
+
failure: "operation",
|
|
1061
|
+
note: `Not deployed: ${failedRow.deploy?.error ?? "the operation failed"}. Nothing was placed where a gate reads, so coverage is unchanged.`,
|
|
1062
|
+
runtime: {
|
|
1063
|
+
seq: failedRow.seq,
|
|
1064
|
+
at: failedRow.at
|
|
1065
|
+
},
|
|
1066
|
+
sessions: []
|
|
1067
|
+
});
|
|
1068
|
+
continue;
|
|
1069
|
+
}
|
|
1070
|
+
const confirms = after.filter((e) => e.tool === "prae:pack" && (e.rule === "pack.activated" || e.rule === "pack.reloaded") && e.pack.sha256 === sha);
|
|
1071
|
+
const refused = after.find((e) => e.tool === "prae:pack" && e.rule === "pack.rejected" && e.subject === d.file);
|
|
1072
|
+
const removed = after.find((e) => e.tool === "prae:pack" && e.rule === "pack.removed" && e.pack.sha256 === sha);
|
|
1073
|
+
const sessions = [...new Set(confirms.flatMap((e) => e.session === void 0 ? [] : [e.session]))];
|
|
1074
|
+
const at = (e) => ({
|
|
1075
|
+
seq: e.seq,
|
|
1076
|
+
at: e.at,
|
|
1077
|
+
...e.session === void 0 ? {} : { session: e.session }
|
|
1078
|
+
});
|
|
1079
|
+
if (refused !== void 0) {
|
|
1080
|
+
out.push({
|
|
1081
|
+
...base,
|
|
1082
|
+
state: "FAILED",
|
|
1083
|
+
failure: "runtime",
|
|
1084
|
+
note: `A gate refused the pack (row #${refused.seq}): ${(refused.reason ?? "").replace(/^pack rejected, not loaded: /, "")}. The gate kept the policy it had; this pack does not count toward coverage.`,
|
|
1085
|
+
runtime: at(refused),
|
|
1086
|
+
sessions
|
|
1087
|
+
});
|
|
1088
|
+
continue;
|
|
1089
|
+
}
|
|
1090
|
+
if (removed !== void 0) {
|
|
1091
|
+
out.push({
|
|
1092
|
+
...base,
|
|
1093
|
+
state: "INACTIVE",
|
|
1094
|
+
note: `A gate sealed the pack removed (row #${removed.seq}); its rules no longer apply there.`,
|
|
1095
|
+
runtime: at(removed),
|
|
1096
|
+
sessions
|
|
1097
|
+
});
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
const first = confirms[0];
|
|
1101
|
+
if (first !== void 0) {
|
|
1102
|
+
out.push({
|
|
1103
|
+
...base,
|
|
1104
|
+
state: "ACTIVE",
|
|
1105
|
+
note: `A gate sealed this exact pack (sha256 ${sha.slice(0, 12)}) in force at row #${first.seq}${sessions.length > 0 ? ` · ${sessions.length} session${sessions.length === 1 ? "" : "s"}` : ""}.`,
|
|
1106
|
+
runtime: at(first),
|
|
1107
|
+
sessions
|
|
1108
|
+
});
|
|
1109
|
+
continue;
|
|
1110
|
+
}
|
|
1111
|
+
const waiting = now - Date.parse(r.at) < CONFIRM_WINDOW_MS;
|
|
1112
|
+
out.push({
|
|
1113
|
+
...base,
|
|
1114
|
+
state: waiting ? "APPLYING" : "VERIFICATION_REQUIRED",
|
|
1115
|
+
note: waiting ? "Written to the workspace pack directory; waiting for a gate to seal it in force." : "Written and configured, but no gate has sealed it in force: no gate watching this workspace is running. A gate mounted with this workspace confirms it when it starts.",
|
|
1116
|
+
sessions
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
return out;
|
|
1120
|
+
}
|
|
1121
|
+
function describeRule(rule) {
|
|
1122
|
+
const logic = logicOf(rule);
|
|
1123
|
+
return {
|
|
1124
|
+
id: rule.id,
|
|
1125
|
+
...rule.title === void 0 ? {} : { title: rule.title },
|
|
1126
|
+
...rule.description === void 0 ? {} : { description: rule.description },
|
|
1127
|
+
effect: rule.effect.kind,
|
|
1128
|
+
because: rule.effect.because,
|
|
1129
|
+
engines: enginesOf(rule),
|
|
1130
|
+
...logic === void 0 ? {} : { logic },
|
|
1131
|
+
definition: JSON.stringify({
|
|
1132
|
+
when: rule.when,
|
|
1133
|
+
effect: rule.effect
|
|
1134
|
+
}, null, 2),
|
|
1135
|
+
cites: Object.entries(rule.frameworks ?? {}).flatMap(([f, cs]) => cs.map((c) => `${f}:${c}`))
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
function ruleViews(pack, origins, entries, admitted, environment, failedPacks = /* @__PURE__ */ new Map()) {
|
|
1139
|
+
const activity = packActivity(entries);
|
|
1140
|
+
const byRule = /* @__PURE__ */ new Map();
|
|
1141
|
+
for (const e of admitted) {
|
|
1142
|
+
if (e.rule === void 0 || isEvent(e)) continue;
|
|
1143
|
+
const rows = byRule.get(e.rule);
|
|
1144
|
+
if (rows === void 0) byRule.set(e.rule, [e]);
|
|
1145
|
+
else rows.push(e);
|
|
1146
|
+
}
|
|
1147
|
+
const out = {};
|
|
1148
|
+
for (const rule of pack?.rules ?? []) {
|
|
1149
|
+
const ref = origins.get(rule.id) ?? {
|
|
1150
|
+
name: pack?.pack ?? "unknown",
|
|
1151
|
+
version: pack?.version ?? ""
|
|
1152
|
+
};
|
|
1153
|
+
const rows = byRule.get(rule.id) ?? [];
|
|
1154
|
+
const last = rows.at(-1);
|
|
1155
|
+
out[rule.id] = {
|
|
1156
|
+
...describeRule(rule),
|
|
1157
|
+
pack: ref,
|
|
1158
|
+
scope: {
|
|
1159
|
+
agents: rule.when.agent === void 0 ? "all" : list(rule.when.agent),
|
|
1160
|
+
environment
|
|
1161
|
+
},
|
|
1162
|
+
active: activityOf(ref, activity, ref.sha256 === void 0 ? void 0 : failedPacks.get(ref.sha256)),
|
|
1163
|
+
evidence: {
|
|
1164
|
+
count: rows.length,
|
|
1165
|
+
...last === void 0 ? {} : { last: {
|
|
1166
|
+
seq: last.seq,
|
|
1167
|
+
at: last.at
|
|
1168
|
+
} }
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
return out;
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Deployed packs a gate refused, by sha256 — the latest deployment of each
|
|
1176
|
+
* definition decides — kept out of coverage: the gate does not enforce them.
|
|
1177
|
+
*/
|
|
1178
|
+
function refusedDeployments(deployments) {
|
|
1179
|
+
const latest = /* @__PURE__ */ new Map();
|
|
1180
|
+
for (const d of deployments) latest.set(d.sha256, d);
|
|
1181
|
+
return new Map([...latest.values()].filter((d) => d.failure === "runtime").map((d) => [d.sha256, {
|
|
1182
|
+
seq: d.runtime?.seq ?? d.seq,
|
|
1183
|
+
at: d.runtime?.at ?? d.requestedAt,
|
|
1184
|
+
why: d.note
|
|
1185
|
+
}]));
|
|
1186
|
+
}
|
|
1187
|
+
|
|
869
1188
|
//#endregion
|
|
870
1189
|
//#region ../controls/src/scope.ts
|
|
871
1190
|
const ROW_LIMIT = 50;
|
|
@@ -943,10 +1262,11 @@ function catalogOf(file) {
|
|
|
943
1262
|
};
|
|
944
1263
|
frameworks.set(framework.id, f);
|
|
945
1264
|
}
|
|
1265
|
+
const name = control.name ?? FRAMEWORKS[framework.id]?.controls[id]?.name;
|
|
946
1266
|
f.controls.push({
|
|
947
1267
|
key,
|
|
948
1268
|
id,
|
|
949
|
-
...
|
|
1269
|
+
...name === void 0 ? {} : { name },
|
|
950
1270
|
asks: control.asks
|
|
951
1271
|
});
|
|
952
1272
|
};
|
|
@@ -1040,6 +1360,11 @@ function inPeriod(at, period, now) {
|
|
|
1040
1360
|
if (period.kind === "days") return t >= now - period.days * 864e5;
|
|
1041
1361
|
return t >= Date.parse(period.from) && t < Date.parse(period.to) + 864e5;
|
|
1042
1362
|
}
|
|
1363
|
+
/** The rows a scope admits: its agents, its sessions, its period. */
|
|
1364
|
+
function admit(entries, scope, agent, now = Date.now()) {
|
|
1365
|
+
const agentOf$1 = (e) => e.agent ?? agent;
|
|
1366
|
+
return entries.filter((e) => (scope.agents === "all" || scope.agents.includes(agentOf$1(e))) && (scope.sessions === "all" || e.session !== void 0 && scope.sessions.includes(e.session)) && inPeriod(e.at, scope.period, now));
|
|
1367
|
+
}
|
|
1043
1368
|
/**
|
|
1044
1369
|
* Assess the scoped controls against the record. The rows are narrowed to
|
|
1045
1370
|
* the scope's agents, sessions and period before any control reads them;
|
|
@@ -1049,7 +1374,7 @@ function inPeriod(at, period, now) {
|
|
|
1049
1374
|
function assess(data, scope, catalog, options) {
|
|
1050
1375
|
const now = options.now ?? Date.now();
|
|
1051
1376
|
const agentOf$1 = (e) => e.agent ?? options.agent;
|
|
1052
|
-
const admitted = data.entries
|
|
1377
|
+
const admitted = admit(data.entries, scope, options.agent, now);
|
|
1053
1378
|
const scoped = {
|
|
1054
1379
|
...data,
|
|
1055
1380
|
entries: admitted
|
|
@@ -1196,17 +1521,39 @@ function agentOf(dir) {
|
|
|
1196
1521
|
} catch {}
|
|
1197
1522
|
return "this agent";
|
|
1198
1523
|
}
|
|
1199
|
-
|
|
1524
|
+
/** What a record's compliance is assessed against: its catalog and scope. */
|
|
1525
|
+
function complianceContext(record) {
|
|
1200
1526
|
const { catalog, catalogError } = catalogFor(record.dir);
|
|
1201
1527
|
return {
|
|
1202
|
-
|
|
1528
|
+
catalog,
|
|
1529
|
+
...catalogError === void 0 ? {} : { catalogError },
|
|
1530
|
+
scope: scopeFor(record.dir, catalog),
|
|
1531
|
+
options: {
|
|
1203
1532
|
agent: agentOf(record.dir),
|
|
1204
1533
|
environment: basename(resolve(record.dir))
|
|
1205
|
-
}
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
function assessCompliance(record, data) {
|
|
1538
|
+
const { catalog, catalogError, scope, options } = complianceContext(record);
|
|
1539
|
+
return {
|
|
1540
|
+
...assess(data, scope, catalog, options),
|
|
1206
1541
|
saved: existsSync(resolve(record.dir, SCOPE_FILE)),
|
|
1207
1542
|
...catalogError === void 0 ? {} : { catalogError }
|
|
1208
1543
|
};
|
|
1209
1544
|
}
|
|
1545
|
+
/**
|
|
1546
|
+
* The Rule Inspector's rules (PRA-195): every rule in force, with where it
|
|
1547
|
+
* came from, how it is evaluated, whether a gate confirmed its pack in
|
|
1548
|
+
* force, and its sealed decisions within the scope. Read-only.
|
|
1549
|
+
*/
|
|
1550
|
+
function inspectorOf(record, data, scope, origins, deployments, refused) {
|
|
1551
|
+
const agent = agentOf(record.dir);
|
|
1552
|
+
return {
|
|
1553
|
+
rules: ruleViews(data.pack, origins, data.entries, admit(data.entries, scope, agent), basename(resolve(record.dir)), refused),
|
|
1554
|
+
deployments
|
|
1555
|
+
};
|
|
1556
|
+
}
|
|
1210
1557
|
|
|
1211
1558
|
//#endregion
|
|
1212
1559
|
//#region src/serve.ts
|
|
@@ -1395,15 +1742,30 @@ function complianceOf(record) {
|
|
|
1395
1742
|
problems: grown.problems
|
|
1396
1743
|
};
|
|
1397
1744
|
const { set } = packSetOf(record);
|
|
1398
|
-
const
|
|
1745
|
+
const deployments = deploymentsOf(entries);
|
|
1746
|
+
const refused = refusedDeployments(deployments);
|
|
1747
|
+
const kept = set.packs.filter((p) => !refused.has(p.sha256));
|
|
1748
|
+
const pack = kept.length === 0 ? void 0 : kept.length === set.packs.length ? set.effective : {
|
|
1749
|
+
...set.effective,
|
|
1750
|
+
rules: kept.flatMap((p) => p.pack.rules)
|
|
1751
|
+
};
|
|
1399
1752
|
const data = {
|
|
1400
1753
|
...pack === void 0 ? {} : { pack },
|
|
1401
|
-
entries,
|
|
1754
|
+
entries: evidenceRows(entries),
|
|
1402
1755
|
verification,
|
|
1403
1756
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1404
1757
|
};
|
|
1758
|
+
const assessment = assessCompliance(record, data);
|
|
1759
|
+
const origins = new Map(set.packs.flatMap((p) => p.pack.rules.map((r) => [r.id, {
|
|
1760
|
+
name: p.pack.pack,
|
|
1761
|
+
version: p.pack.version,
|
|
1762
|
+
sha256: p.sha256,
|
|
1763
|
+
origin: p.origin,
|
|
1764
|
+
file: p.file.split("/").at(-1) ?? p.file
|
|
1765
|
+
}])));
|
|
1405
1766
|
return {
|
|
1406
|
-
assessment
|
|
1767
|
+
assessment,
|
|
1768
|
+
inspector: inspectorOf(record, data, assessment.scope, origins, deployments, refused),
|
|
1407
1769
|
controls: CONTROLS.map((control) => {
|
|
1408
1770
|
const found = Object.entries(FRAMEWORKS).find(([, f]) => control.id.startsWith(`${f.short} · `));
|
|
1409
1771
|
const code = found === void 0 ? void 0 : control.id.split(" · ")[1];
|
|
@@ -1822,7 +2184,7 @@ async function check(path, argv = []) {
|
|
|
1822
2184
|
* from the findings, so there is nothing here to be careful about printing.
|
|
1823
2185
|
*/
|
|
1824
2186
|
async function scanFile(path, packPath, json) {
|
|
1825
|
-
const { scan } = await import("./src-
|
|
2187
|
+
const { scan } = await import("./src-CwBEFhww.js");
|
|
1826
2188
|
let content;
|
|
1827
2189
|
try {
|
|
1828
2190
|
content = await readFile(path, "utf8");
|
|
@@ -1862,13 +2224,13 @@ async function scanFile(path, packPath, json) {
|
|
|
1862
2224
|
* not come up inspecting nothing.
|
|
1863
2225
|
*/
|
|
1864
2226
|
async function mcp(root, packPath, ledgerPath) {
|
|
1865
|
-
const { serveMcp } = await import("./mcp-
|
|
2227
|
+
const { serveMcp } = await import("./mcp-DdEDvTvR.js");
|
|
1866
2228
|
const { resolve: resolve$1 } = await import("node:path");
|
|
1867
2229
|
const bundled = [join(import.meta.dirname, "secret-catcher.prae.json"), join(import.meta.dirname, "..", "..", "..", "examples", "secret-catcher.prae.json")].find((candidate) => existsSync(candidate));
|
|
1868
2230
|
const chosen = packPath ?? bundled;
|
|
1869
2231
|
if (chosen === void 0) return fail("mcp needs --pack <file>; no bundled secret-catcher found");
|
|
1870
2232
|
const pack = await loadPack(chosen);
|
|
1871
|
-
const { Ledger: Ledger$1 } = await import("./src-
|
|
2233
|
+
const { Ledger: Ledger$1 } = await import("./src-2iJy5MZc.js");
|
|
1872
2234
|
const ledger = ledgerPath === void 0 ? void 0 : Ledger$1.open(ledgerPath);
|
|
1873
2235
|
console.error(`prae mcp: serving ${resolve$1(root)} under ${pack.pack} ${pack.version}` + (ledgerPath === void 0 ? " (no ledger)" : ` · ledger ${ledgerPath}`));
|
|
1874
2236
|
await serveMcp({
|
|
@@ -1920,7 +2282,7 @@ async function explain(path, tool, pairs) {
|
|
|
1920
2282
|
* a key that arrived beside it is checked against nothing.
|
|
1921
2283
|
*/
|
|
1922
2284
|
async function keygen(dir) {
|
|
1923
|
-
const { generateKeypair, fingerprint: fingerprint$1 } = await import("./src-
|
|
2285
|
+
const { generateKeypair, fingerprint: fingerprint$1 } = await import("./src-2iJy5MZc.js");
|
|
1924
2286
|
const { writeFileSync: writeFileSync$1 } = await import("node:fs");
|
|
1925
2287
|
const keys = generateKeypair();
|
|
1926
2288
|
const priv = join(dir, "prae-signing.pem");
|
|
@@ -1943,7 +2305,7 @@ async function keygen(dir) {
|
|
|
1943
2305
|
async function keygenSealed(role, dir) {
|
|
1944
2306
|
if (role !== "operator" && role !== "policy" && role !== "ledger") fail("--role is operator, policy or ledger");
|
|
1945
2307
|
const stem = role === "ledger" ? "prae-signing" : role;
|
|
1946
|
-
const { sealedKeypair, fingerprint: fingerprint$1 } = await import("./src-
|
|
2308
|
+
const { sealedKeypair, fingerprint: fingerprint$1 } = await import("./src-2iJy5MZc.js");
|
|
1947
2309
|
const { writeFileSync: writeFileSync$1 } = await import("node:fs");
|
|
1948
2310
|
const keys = sealedKeypair(process.env.PRAE_KEY_PASSPHRASE ?? await askHidden("passphrase: "));
|
|
1949
2311
|
const pub = join(dir, `${stem}.pub.pem`);
|
|
@@ -1956,7 +2318,7 @@ async function keygenSealed(role, dir) {
|
|
|
1956
2318
|
}
|
|
1957
2319
|
/** A detached signature over a pack's bytes (PRA-107). */
|
|
1958
2320
|
async function signPack(packPath, keyPath) {
|
|
1959
|
-
const { signBytes, unsealPrivateKey, fingerprint: fingerprint$1 } = await import("./src-
|
|
2321
|
+
const { signBytes, unsealPrivateKey, fingerprint: fingerprint$1 } = await import("./src-2iJy5MZc.js");
|
|
1960
2322
|
const { createPublicKey: createPublicKey$1 } = await import("node:crypto");
|
|
1961
2323
|
const bytes = readFileSync(packPath);
|
|
1962
2324
|
const parsed$1 = parsePack(bytes.toString("utf8"));
|
|
@@ -2001,7 +2363,7 @@ function askHidden(prompt) {
|
|
|
2001
2363
|
});
|
|
2002
2364
|
}
|
|
2003
2365
|
async function receipt(path, seq, keyPath, out) {
|
|
2004
|
-
const { Ledger: Ledger$1, makeReceipt, fingerprint: fingerprint$1 } = await import("./src-
|
|
2366
|
+
const { Ledger: Ledger$1, makeReceipt, fingerprint: fingerprint$1 } = await import("./src-2iJy5MZc.js");
|
|
2005
2367
|
const { readFileSync: readFileSync$1 } = await import("node:fs");
|
|
2006
2368
|
const { createPublicKey: createPublicKey$1 } = await import("node:crypto");
|
|
2007
2369
|
const privateKey = readFileSync$1(keyPath, "utf8");
|
|
@@ -2031,7 +2393,7 @@ async function receipt(path, seq, keyPath, out) {
|
|
|
2031
2393
|
* file and sets the exit code, so scripts can branch on it.
|
|
2032
2394
|
*/
|
|
2033
2395
|
async function verifyReceiptCmd(path) {
|
|
2034
|
-
const { checkReceipt } = await import("./receipt-check-
|
|
2396
|
+
const { checkReceipt } = await import("./receipt-check-2F4zLEW5.js");
|
|
2035
2397
|
let parsed$1;
|
|
2036
2398
|
try {
|
|
2037
2399
|
parsed$1 = JSON.parse(await readFile(path, "utf8"));
|
|
@@ -2062,7 +2424,7 @@ async function test(suitePath, packOverride, asJson) {
|
|
|
2062
2424
|
} catch (error) {
|
|
2063
2425
|
return fail(`${suitePath} is not valid JSON: ${error instanceof Error ? error.message : error}`);
|
|
2064
2426
|
}
|
|
2065
|
-
const { parseSuite, renderSuite, runSuite } = await import("./test-run-
|
|
2427
|
+
const { parseSuite, renderSuite, runSuite } = await import("./test-run-BGsK-inZ.js");
|
|
2066
2428
|
const suite = parseSuite(parsed$1);
|
|
2067
2429
|
if (!suite.ok) {
|
|
2068
2430
|
console.error(`prae: ${suitePath} is not a valid test suite`);
|
|
@@ -2073,7 +2435,7 @@ async function test(suitePath, packOverride, asJson) {
|
|
|
2073
2435
|
if (chosen === void 0) return fail("test needs a pack: set `pack` in the suite or pass --pack");
|
|
2074
2436
|
const pack = await loadPack(chosen);
|
|
2075
2437
|
const { capabilityForTool } = await import("capmark");
|
|
2076
|
-
const { scan } = await import("./src-
|
|
2438
|
+
const { scan } = await import("./src-CwBEFhww.js");
|
|
2077
2439
|
const inspect = pack.rules.some((rule) => rule.when.secrets !== void 0) ? (path) => {
|
|
2078
2440
|
try {
|
|
2079
2441
|
return scan(readFileSync(path, "utf8"));
|
|
@@ -2102,14 +2464,14 @@ async function verify$1(path, keyPath, checkpointPath) {
|
|
|
2102
2464
|
const last = entries.at(-1);
|
|
2103
2465
|
console.log(`${result.entries} entries · chain intact${last === void 0 ? "" : ` · seal ${seal(last)}`}`);
|
|
2104
2466
|
if (checkpointPath !== void 0) {
|
|
2105
|
-
const { checkCheckpoint } = await import("./checkpoint-
|
|
2467
|
+
const { checkCheckpoint } = await import("./checkpoint-BLOGdWFu.js");
|
|
2106
2468
|
const publicKey = keyPath === void 0 ? void 0 : readFileSync(keyPath, "utf8");
|
|
2107
2469
|
const verdict = checkCheckpoint(entries, JSON.parse(readFileSync(checkpointPath, "utf8")), publicKey);
|
|
2108
2470
|
for (const line of verdict.lines) (verdict.ok ? console.log : console.error)(`checkpoint: ${line}`);
|
|
2109
2471
|
if (!verdict.ok) process.exitCode = 1;
|
|
2110
2472
|
}
|
|
2111
2473
|
if (keyPath !== void 0) {
|
|
2112
|
-
const { verifySignature: verifySignature$1, fingerprint: fingerprint$1 } = await import("./src-
|
|
2474
|
+
const { verifySignature: verifySignature$1, fingerprint: fingerprint$1 } = await import("./src-2iJy5MZc.js");
|
|
2113
2475
|
const { readFileSync: readFileSync$1 } = await import("node:fs");
|
|
2114
2476
|
const publicKey = readFileSync$1(keyPath, "utf8");
|
|
2115
2477
|
let signed = 0;
|
|
@@ -2187,7 +2549,7 @@ async function report(path, out, packPath) {
|
|
|
2187
2549
|
* that step is a proposal a human approves, and it starts from this list.
|
|
2188
2550
|
*/
|
|
2189
2551
|
async function instructions(from, asJson) {
|
|
2190
|
-
const { ingest } = await import("./src-
|
|
2552
|
+
const { ingest } = await import("./src-XukJfuml.js");
|
|
2191
2553
|
const result = ingest(from);
|
|
2192
2554
|
if (asJson) {
|
|
2193
2555
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -2223,7 +2585,7 @@ async function instructions(from, asJson) {
|
|
|
2223
2585
|
* on purpose rather than something that happened to their policy.
|
|
2224
2586
|
*/
|
|
2225
2587
|
async function propose(from, options) {
|
|
2226
|
-
const [{ ingest }, { extract }] = await Promise.all([import("./src-
|
|
2588
|
+
const [{ ingest }, { extract }] = await Promise.all([import("./src-XukJfuml.js"), import("./src-BoBCmiwj.js")]);
|
|
2227
2589
|
const read = ingest(from);
|
|
2228
2590
|
if (read.files.length === 0) {
|
|
2229
2591
|
console.log(`No instruction files found at or above ${from}.`);
|
|
@@ -2283,9 +2645,9 @@ async function consoleOut(path, argv) {
|
|
|
2283
2645
|
const instructionsDir = flag(argv, "instructions");
|
|
2284
2646
|
if (instructionsDir !== void 0) {
|
|
2285
2647
|
const [{ ingest }, { extract }, { renderInstructions }] = await Promise.all([
|
|
2286
|
-
import("./src-
|
|
2287
|
-
import("./src-
|
|
2288
|
-
import("./instructions-
|
|
2648
|
+
import("./src-XukJfuml.js"),
|
|
2649
|
+
import("./src-BoBCmiwj.js"),
|
|
2650
|
+
import("./instructions-fCJ4j7ce.js")
|
|
2289
2651
|
]);
|
|
2290
2652
|
const read = ingest(instructionsDir);
|
|
2291
2653
|
instructionsView = renderInstructions(data, read, extract(read.statements));
|
|
@@ -2333,11 +2695,11 @@ function bundledBaseline() {
|
|
|
2333
2695
|
async function init(argv) {
|
|
2334
2696
|
const packPath = flag(argv, "pack") ?? bundledBaseline();
|
|
2335
2697
|
if (packPath === void 0) fail("init needs --pack <file>; no bundled baseline found");
|
|
2698
|
+
const pack = await loadPack(packPath);
|
|
2336
2699
|
if (flag(argv, "pack") === void 0) {
|
|
2337
|
-
console.log(
|
|
2700
|
+
console.log(`No --pack given; mounting the built-in baseline (${pack.rules.length} rules).`);
|
|
2338
2701
|
console.log(`See it with: prae check ${packPath}\n`);
|
|
2339
2702
|
}
|
|
2340
|
-
const pack = await loadPack(packPath);
|
|
2341
2703
|
const source = await readFile(packPath, "utf8");
|
|
2342
2704
|
const link = argv.includes("--link");
|
|
2343
2705
|
const builtin = link ? { packFile: resolve(packPath) } : { pack: source };
|
|
@@ -2418,7 +2780,7 @@ async function chainMatrix(path, argv) {
|
|
|
2418
2780
|
const catalogue = guardiansPath === void 0 ? [] : JSON.parse(readFileSync(guardiansPath, "utf8")).guardians;
|
|
2419
2781
|
const guardianOf = (rule) => rule === void 0 ? void 0 : catalogue.find((g) => g.rules.includes(rule) || (g.armed ?? []).includes(rule))?.name;
|
|
2420
2782
|
const keyPath = flag(argv, "key");
|
|
2421
|
-
const { verifySignature: verifySignature$1 } = await import("./src-
|
|
2783
|
+
const { verifySignature: verifySignature$1 } = await import("./src-2iJy5MZc.js");
|
|
2422
2784
|
const publicKey = keyPath === void 0 ? void 0 : readFileSync(keyPath, "utf8");
|
|
2423
2785
|
const matrix = integrityMatrix(entries, pack, guardianOf).map((m) => {
|
|
2424
2786
|
const entry = entries.find((e) => e.seq === m.seq);
|
|
@@ -2449,7 +2811,7 @@ async function chainMatrix(path, argv) {
|
|
|
2449
2811
|
if (!chainOk || sigFailed) process.exitCode = 1;
|
|
2450
2812
|
}
|
|
2451
2813
|
async function checkpoint(path, keyPath, out) {
|
|
2452
|
-
const { makeCheckpoint } = await import("./checkpoint-
|
|
2814
|
+
const { makeCheckpoint } = await import("./checkpoint-BLOGdWFu.js");
|
|
2453
2815
|
let ledger;
|
|
2454
2816
|
try {
|
|
2455
2817
|
ledger = Ledger.open(path);
|
|
@@ -2470,7 +2832,7 @@ async function checkpoint(path, keyPath, out) {
|
|
|
2470
2832
|
}
|
|
2471
2833
|
}
|
|
2472
2834
|
async function exportLedger(path, options) {
|
|
2473
|
-
const { toOcsf, ndjson, sendToHec } = await import("./ocsf-
|
|
2835
|
+
const { toOcsf, ndjson, sendToHec } = await import("./ocsf-BwWyM7hc.js");
|
|
2474
2836
|
const { createRequire: createRequire$1 } = await import("node:module");
|
|
2475
2837
|
const { version } = createRequire$1(import.meta.url)("../package.json");
|
|
2476
2838
|
let ledger;
|
|
@@ -2601,7 +2963,7 @@ async function main(argv) {
|
|
|
2601
2963
|
}
|
|
2602
2964
|
case "init":
|
|
2603
2965
|
if (rest[0] === "claude-code") {
|
|
2604
|
-
const { initClaudeCode, stableNode } = await import("./init-
|
|
2966
|
+
const { initClaudeCode, stableNode } = await import("./init-BPlBJvA-.js");
|
|
2605
2967
|
try {
|
|
2606
2968
|
return initClaudeCode(rest.slice(1), {
|
|
2607
2969
|
cwd: process.cwd(),
|
|
@@ -2616,7 +2978,7 @@ async function main(argv) {
|
|
|
2616
2978
|
return init(rest);
|
|
2617
2979
|
case "hook": {
|
|
2618
2980
|
if (rest[0] !== "claude-code") fail("hook takes claude-code");
|
|
2619
|
-
const { runHook } = await import("./hook-
|
|
2981
|
+
const { runHook } = await import("./hook-DxLgNtc4.js");
|
|
2620
2982
|
return runHook(rest.slice(1));
|
|
2621
2983
|
}
|
|
2622
2984
|
case "--help":
|