@codacy/verity-cli 0.34.1-experimental.affbe54 → 0.34.1-experimental.c910405
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.md +38 -0
- package/bin/verity.js +512 -322
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -13782,9 +13782,9 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
13782
13782
|
PatternStructure: 5
|
|
13783
13783
|
};
|
|
13784
13784
|
var QueryError = class _QueryError extends Error {
|
|
13785
|
-
constructor(
|
|
13786
|
-
super(_QueryError.formatMessage(
|
|
13787
|
-
this.kind =
|
|
13785
|
+
constructor(kind2, info2, index, length) {
|
|
13786
|
+
super(_QueryError.formatMessage(kind2, info2));
|
|
13787
|
+
this.kind = kind2;
|
|
13788
13788
|
this.info = info2;
|
|
13789
13789
|
this.index = index;
|
|
13790
13790
|
this.length = length;
|
|
@@ -13798,8 +13798,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
13798
13798
|
__name(this, "QueryError");
|
|
13799
13799
|
}
|
|
13800
13800
|
/** Formats an error message based on the error kind and info */
|
|
13801
|
-
static formatMessage(
|
|
13802
|
-
switch (
|
|
13801
|
+
static formatMessage(kind2, info2) {
|
|
13802
|
+
switch (kind2) {
|
|
13803
13803
|
case QueryErrorKind.NodeName:
|
|
13804
13804
|
return `Bad node name '${info2.word}'`;
|
|
13805
13805
|
case QueryErrorKind.FieldName:
|
|
@@ -16278,8 +16278,8 @@ async function reportLoginOutcome(out2, opts = {}) {
|
|
|
16278
16278
|
printWarn(" repository will report that account. Remove its line from ~/.verity/credentials");
|
|
16279
16279
|
printWarn(" only if you want this repository on the login you just completed.");
|
|
16280
16280
|
} else {
|
|
16281
|
-
const
|
|
16282
|
-
printWarn(` Note: this repository has a ${
|
|
16281
|
+
const kind2 = rec.userId != null ? "superseded per-repository" : "anonymous project-specific";
|
|
16282
|
+
printWarn(` Note: this repository has a ${kind2} credential that takes`);
|
|
16283
16283
|
printWarn(" precedence here. Remove its line from ~/.verity/credentials to use your login.");
|
|
16284
16284
|
printWarn(' Until then, "verity login" in this repository re-runs the full GitHub flow');
|
|
16285
16285
|
printWarn(" every time.");
|
|
@@ -16851,6 +16851,7 @@ var VERITY_SESSION_END_HOOK = {
|
|
|
16851
16851
|
command: "verity session end"
|
|
16852
16852
|
};
|
|
16853
16853
|
var GUARD_TIMEOUT = 300;
|
|
16854
|
+
var GUARD_TIMEOUT_MS = GUARD_TIMEOUT * 1e3;
|
|
16854
16855
|
function buildGuardHook(on) {
|
|
16855
16856
|
return {
|
|
16856
16857
|
type: "command",
|
|
@@ -17606,9 +17607,9 @@ function pointsAtVerity(src) {
|
|
|
17606
17607
|
}
|
|
17607
17608
|
function describeSource(src) {
|
|
17608
17609
|
if (!src || typeof src !== "object") return "an unrecognised source";
|
|
17609
|
-
const
|
|
17610
|
+
const kind2 = typeof src.source === "string" ? src.source : "unknown";
|
|
17610
17611
|
const target = typeof src.repo === "string" && src.repo || typeof src.url === "string" && src.url || typeof src.path === "string" && src.path || "";
|
|
17611
|
-
return target ? `${
|
|
17612
|
+
return target ? `${kind2} \u2192 ${target}` : kind2;
|
|
17612
17613
|
}
|
|
17613
17614
|
function legacyMarketplaceInstall() {
|
|
17614
17615
|
const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
@@ -18532,8 +18533,8 @@ function slugify(s) {
|
|
|
18532
18533
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
18533
18534
|
}
|
|
18534
18535
|
function orgNodePath(node) {
|
|
18535
|
-
const
|
|
18536
|
-
return `${
|
|
18536
|
+
const kind2 = ORG_KINDS.includes(node.kind) ? node.kind : "domain";
|
|
18537
|
+
return `${kind2}/${slugify(node.title) || "claim"}-${node.tag_id.replace(/-/g, "").slice(0, 8)}.md`;
|
|
18537
18538
|
}
|
|
18538
18539
|
function renderOrgNode(node, orgName) {
|
|
18539
18540
|
const fm = [
|
|
@@ -18622,10 +18623,10 @@ function renderIndex(orgName, nodes) {
|
|
|
18622
18623
|
];
|
|
18623
18624
|
const byKind = /* @__PURE__ */ new Map();
|
|
18624
18625
|
for (const n of nodes) byKind.set(n.kind, [...byKind.get(n.kind) ?? [], n]);
|
|
18625
|
-
for (const
|
|
18626
|
-
const list2 = byKind.get(
|
|
18626
|
+
for (const kind2 of ORG_KINDS) {
|
|
18627
|
+
const list2 = byKind.get(kind2);
|
|
18627
18628
|
if (!list2?.length) continue;
|
|
18628
|
-
lines.push(`## ${
|
|
18629
|
+
lines.push(`## ${kind2}/ (${list2.length})`);
|
|
18629
18630
|
for (const n of list2) lines.push(`- [[${orgNodePath(n).split("/")[1].replace(/\.md$/, "")}]] \u2014 ${n.title} \xB7 ${n.origin}`);
|
|
18630
18631
|
lines.push("");
|
|
18631
18632
|
}
|
|
@@ -18684,8 +18685,8 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
18684
18685
|
const dir = orgMirrorDir(remote);
|
|
18685
18686
|
if (!dir || !(0, import_node_fs14.existsSync)(dir)) return [];
|
|
18686
18687
|
const out2 = [];
|
|
18687
|
-
for (const
|
|
18688
|
-
const kindDir = (0, import_node_path14.join)(dir,
|
|
18688
|
+
for (const kind2 of ORG_KINDS) {
|
|
18689
|
+
const kindDir = (0, import_node_path14.join)(dir, kind2);
|
|
18689
18690
|
if (!(0, import_node_fs14.existsSync)(kindDir)) continue;
|
|
18690
18691
|
let files;
|
|
18691
18692
|
try {
|
|
@@ -18953,16 +18954,16 @@ function relevance(node, ctx) {
|
|
|
18953
18954
|
return { score, via: { glob: globHit, tag: tagScore, text: textScore } };
|
|
18954
18955
|
}
|
|
18955
18956
|
var KIND_POOL_STRENGTH = 20;
|
|
18956
|
-
function priorFor(
|
|
18957
|
-
const base = KIND_PRIOR_MEAN[
|
|
18957
|
+
function priorFor(kind2, pooled) {
|
|
18958
|
+
const base = KIND_PRIOR_MEAN[kind2] ?? DEFAULT_PRIOR_MEAN;
|
|
18958
18959
|
const a = pooled ? Math.max(0, pooled.alpha) : 0;
|
|
18959
18960
|
const b = pooled ? Math.max(0, pooled.beta) : 0;
|
|
18960
|
-
const mean = pooled &&
|
|
18961
|
+
const mean = pooled && kind2 !== "integration" ? (KIND_POOL_STRENGTH * base + a) / (KIND_POOL_STRENGTH + a + b) : base;
|
|
18961
18962
|
return { alpha: mean * PRIOR_STRENGTH, beta: (1 - mean) * PRIOR_STRENGTH };
|
|
18962
18963
|
}
|
|
18963
|
-
function posteriorFor(
|
|
18964
|
-
const p = priorFor(
|
|
18965
|
-
if (!own ||
|
|
18964
|
+
function posteriorFor(kind2, own, pooled) {
|
|
18965
|
+
const p = priorFor(kind2, pooled);
|
|
18966
|
+
if (!own || kind2 === "integration") return p;
|
|
18966
18967
|
return { alpha: p.alpha + Math.max(0, own.alpha), beta: p.beta + Math.max(0, own.beta) };
|
|
18967
18968
|
}
|
|
18968
18969
|
function posteriorMean(p) {
|
|
@@ -20002,7 +20003,7 @@ async function regenerateIndex() {
|
|
|
20002
20003
|
try {
|
|
20003
20004
|
const content = await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8");
|
|
20004
20005
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
20005
|
-
const
|
|
20006
|
+
const kind2 = pickFrontmatter(content, "kind") ?? "-";
|
|
20006
20007
|
const confidence = pickFrontmatter(content, "confidence");
|
|
20007
20008
|
const globs = pickFrontmatterArray(content, "file_globs");
|
|
20008
20009
|
const status = pickFrontmatter(content, "status") ?? "active";
|
|
@@ -20010,7 +20011,7 @@ async function regenerateIndex() {
|
|
|
20010
20011
|
const globPart = globs.length > 0 ? ` \xB7 scope: \`${globs.slice(0, 3).join("`, `")}\`` : "";
|
|
20011
20012
|
const statusPart = status !== "active" ? ` \xB7 *${status}*` : "";
|
|
20012
20013
|
lines.push(`- [[${slug}]] \u2014 **${title}**`);
|
|
20013
|
-
lines.push(` *${
|
|
20014
|
+
lines.push(` *${kind2}*${confPart}${globPart}${statusPart}`);
|
|
20014
20015
|
} catch {
|
|
20015
20016
|
lines.push(`- [[${slug}]]`);
|
|
20016
20017
|
}
|
|
@@ -22053,8 +22054,8 @@ function toRegister(severity) {
|
|
|
22053
22054
|
return "NOTE";
|
|
22054
22055
|
}
|
|
22055
22056
|
}
|
|
22056
|
-
function recordMark(d,
|
|
22057
|
-
appendEvent(d, { k: "mark", kind, from: from ?? null, to: to ?? null });
|
|
22057
|
+
function recordMark(d, kind2, from, to) {
|
|
22058
|
+
appendEvent(d, { k: "mark", kind: kind2, from: from ?? null, to: to ?? null });
|
|
22058
22059
|
}
|
|
22059
22060
|
function recordCapabilities(d, c, known) {
|
|
22060
22061
|
const put = (field, value, tier) => {
|
|
@@ -27257,7 +27258,7 @@ function channelSilence(input) {
|
|
|
27257
27258
|
// src/lib/cli-version.ts
|
|
27258
27259
|
function cliVersion() {
|
|
27259
27260
|
try {
|
|
27260
|
-
return true ? "0.34.1-experimental.
|
|
27261
|
+
return true ? "0.34.1-experimental.c910405" : "dev";
|
|
27261
27262
|
} catch {
|
|
27262
27263
|
return "dev";
|
|
27263
27264
|
}
|
|
@@ -27497,10 +27498,10 @@ var EMPTY_RESULT = {
|
|
|
27497
27498
|
findings: [],
|
|
27498
27499
|
summary: { total_findings: 0, by_severity: {}, tools_run: [] }
|
|
27499
27500
|
};
|
|
27500
|
-
function withFailure(
|
|
27501
|
+
function withFailure(kind2, detail) {
|
|
27501
27502
|
return {
|
|
27502
27503
|
...EMPTY_RESULT,
|
|
27503
|
-
summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
|
|
27504
|
+
summary: { ...EMPTY_RESULT.summary, failure: { kind: kind2, detail: detail.slice(0, 300) } }
|
|
27504
27505
|
};
|
|
27505
27506
|
}
|
|
27506
27507
|
function runCodacyAnalysisIfAvailable(files) {
|
|
@@ -28259,11 +28260,11 @@ var rootCandidateCache = /* @__PURE__ */ new Map();
|
|
|
28259
28260
|
function candidateRoots(repoRoot2) {
|
|
28260
28261
|
const cached2 = rootCandidateCache.get(repoRoot2);
|
|
28261
28262
|
if (cached2) return cached2;
|
|
28262
|
-
const
|
|
28263
|
-
const out2 = [
|
|
28263
|
+
const norm3 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
28264
|
+
const out2 = [norm3];
|
|
28264
28265
|
try {
|
|
28265
|
-
const real = import_node_fs44.realpathSync.native(
|
|
28266
|
-
if (real !==
|
|
28266
|
+
const real = import_node_fs44.realpathSync.native(norm3).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
28267
|
+
if (real !== norm3) out2.push(real);
|
|
28267
28268
|
} catch {
|
|
28268
28269
|
}
|
|
28269
28270
|
for (const r of [...out2]) {
|
|
@@ -29114,39 +29115,39 @@ function extentOf(node) {
|
|
|
29114
29115
|
}
|
|
29115
29116
|
function definitionsIn(root, spec) {
|
|
29116
29117
|
const out2 = [];
|
|
29117
|
-
const add = (name2,
|
|
29118
|
+
const add = (name2, kind2, extent, fn, owner, last = extent) => {
|
|
29118
29119
|
const q = qualifierOf(owner, spec);
|
|
29119
|
-
out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind, extent, last, fn });
|
|
29120
|
+
out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind: kind2, extent, last, fn });
|
|
29120
29121
|
};
|
|
29121
29122
|
const visit = (n) => {
|
|
29122
|
-
const
|
|
29123
|
-
if (
|
|
29123
|
+
const kind2 = spec.definitions[n.type];
|
|
29124
|
+
if (kind2 && n.childForFieldName("body")) {
|
|
29124
29125
|
const nameNode = n.childForFieldName("name");
|
|
29125
29126
|
if (nameNode && nameNode.type !== "computed_property_name") {
|
|
29126
29127
|
const inClass = qualifierOf(n, spec) !== null;
|
|
29127
|
-
const k = spec.id === "python" ? inClass ? "method" : "function" :
|
|
29128
|
+
const k = spec.id === "python" ? inClass ? "method" : "function" : kind2;
|
|
29128
29129
|
add(nameNode.text, k, extentOf(n), n, n, n.parent?.type === "decorated_definition" ? n.parent : n);
|
|
29129
29130
|
}
|
|
29130
29131
|
} else if (spec.functionValues.has(n.type) && n.parent) {
|
|
29131
29132
|
const p = n.parent;
|
|
29132
|
-
const
|
|
29133
|
+
const kind3 = n.type === "arrow_function" ? "arrow" : n.type === "lambda" || n.type === "lambda_expression" ? "lambda" : "function";
|
|
29133
29134
|
const bound = p.childForFieldName("value")?.id === n.id;
|
|
29134
29135
|
if (bound && p.type === "variable_declarator" && p.childForFieldName("name")?.type === "identifier") {
|
|
29135
29136
|
const decl = p.parent && p.parent.namedChildren.filter((c) => c.type === "variable_declarator").length === 1 ? p.parent : p;
|
|
29136
|
-
add(p.childForFieldName("name").text,
|
|
29137
|
+
add(p.childForFieldName("name").text, kind3, decl, n, p);
|
|
29137
29138
|
} else if (bound && (p.type === "public_field_definition" || p.type === "field_definition")) {
|
|
29138
29139
|
const nameNode = p.childForFieldName("name") ?? p.childForFieldName("property");
|
|
29139
|
-
if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text,
|
|
29140
|
+
if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind3, extentOf(p), n, p, p);
|
|
29140
29141
|
} else if (bound && p.type === "pair") {
|
|
29141
29142
|
const key = p.childForFieldName("key");
|
|
29142
|
-
if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text,
|
|
29143
|
+
if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind3, p, n, p);
|
|
29143
29144
|
} else if (p.type === "arguments" && moduleCall(p.parent)) {
|
|
29144
29145
|
const call = p.parent;
|
|
29145
29146
|
const route = p.namedChildren[0];
|
|
29146
29147
|
const quoted = route && route.id !== n.id && route.type === "string" ? unquote2(route.text) : null;
|
|
29147
29148
|
const path = quoted && /^[\w/:.{}*-]{1,60}$/.test(quoted) ? quoted : null;
|
|
29148
29149
|
const callee = call.childForFieldName("function").text;
|
|
29149
|
-
add(path ? `${callee} ${path}` : callee,
|
|
29150
|
+
add(path ? `${callee} ${path}` : callee, kind3, call.parent, n, call);
|
|
29150
29151
|
}
|
|
29151
29152
|
}
|
|
29152
29153
|
for (const c of n.namedChildren) visit(c);
|
|
@@ -29423,15 +29424,15 @@ var STABLE_EXPRESSION = (t) => {
|
|
|
29423
29424
|
const root = t.split(".")[0];
|
|
29424
29425
|
return root === "this" || root === "self" || /^[A-Z]/.test(root);
|
|
29425
29426
|
};
|
|
29426
|
-
function argResource(
|
|
29427
|
-
if (!arg) return { kind, name: null, confidence: "unknown" };
|
|
29427
|
+
function argResource(kind2, arg) {
|
|
29428
|
+
if (!arg) return { kind: kind2, name: null, confidence: "unknown" };
|
|
29428
29429
|
if (arg.literal !== null) {
|
|
29429
29430
|
const n = literalName(arg.literal);
|
|
29430
|
-
return n ? { kind, name: n.name, confidence: n.confidence } : { kind, name: null, confidence: "unknown" };
|
|
29431
|
+
return n ? { kind: kind2, name: n.name, confidence: n.confidence } : { kind: kind2, name: null, confidence: "unknown" };
|
|
29431
29432
|
}
|
|
29432
|
-
if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind, name: arg.text, confidence: "expression" };
|
|
29433
|
+
if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind: kind2, name: arg.text, confidence: "expression" };
|
|
29433
29434
|
const keyed = keyedCall(arg.text);
|
|
29434
|
-
return keyed ? { kind, name: keyed, confidence: "expression" } : { kind, name: null, confidence: "unknown" };
|
|
29435
|
+
return keyed ? { kind: kind2, name: keyed, confidence: "expression" } : { kind: kind2, name: null, confidence: "unknown" };
|
|
29435
29436
|
}
|
|
29436
29437
|
function keyedCall(text) {
|
|
29437
29438
|
const t = text.trim();
|
|
@@ -30940,8 +30941,8 @@ ${m.accessors.map((x) => ` ${x.fn.path}:${x.fn.start.line} ${x.fn.qualified} \u
|
|
|
30940
30941
|
var KINDS = ["table", "cache", "file", "http", "queue", "service", "memory"];
|
|
30941
30942
|
function parseResource(text) {
|
|
30942
30943
|
const colon = text.indexOf(":");
|
|
30943
|
-
const
|
|
30944
|
-
if (KINDS.includes(
|
|
30944
|
+
const kind2 = colon > 0 ? text.slice(0, colon) : "";
|
|
30945
|
+
if (KINDS.includes(kind2)) return { kinds: [kind2], name: text.slice(colon + 1) };
|
|
30945
30946
|
return { kinds: KINDS, name: text };
|
|
30946
30947
|
}
|
|
30947
30948
|
var writersOfTool = async (ctx, args2) => {
|
|
@@ -33434,12 +33435,41 @@ async function runAnalyze(opts, globals) {
|
|
|
33434
33435
|
}
|
|
33435
33436
|
|
|
33436
33437
|
// src/commands/baseline.ts
|
|
33437
|
-
var
|
|
33438
|
-
var
|
|
33438
|
+
var import_node_fs56 = require("node:fs");
|
|
33439
|
+
var import_node_path43 = require("node:path");
|
|
33439
33440
|
|
|
33440
|
-
// src/lib/
|
|
33441
|
+
// src/lib/skew-notice.ts
|
|
33441
33442
|
var import_node_fs54 = require("node:fs");
|
|
33442
33443
|
var import_node_path41 = require("node:path");
|
|
33444
|
+
var MARKER = ".skew-notice.json";
|
|
33445
|
+
function markerPath2() {
|
|
33446
|
+
return (0, import_node_path41.join)(verityHome(), MARKER);
|
|
33447
|
+
}
|
|
33448
|
+
function today(now) {
|
|
33449
|
+
const y = now.getFullYear();
|
|
33450
|
+
const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
33451
|
+
const d = String(now.getDate()).padStart(2, "0");
|
|
33452
|
+
return `${y}-${m}-${d}`;
|
|
33453
|
+
}
|
|
33454
|
+
function skewNoticeDue(skew, now = /* @__PURE__ */ new Date()) {
|
|
33455
|
+
try {
|
|
33456
|
+
const seen = JSON.parse((0, import_node_fs54.readFileSync)(markerPath2(), "utf-8"));
|
|
33457
|
+
return !(seen.global === skew.global && seen.hooks === skew.hooks && seen.day === today(now));
|
|
33458
|
+
} catch {
|
|
33459
|
+
return true;
|
|
33460
|
+
}
|
|
33461
|
+
}
|
|
33462
|
+
function recordSkewNotice(skew, now = /* @__PURE__ */ new Date()) {
|
|
33463
|
+
try {
|
|
33464
|
+
(0, import_node_fs54.mkdirSync)(verityHome(), { recursive: true, mode: 448 });
|
|
33465
|
+
(0, import_node_fs54.writeFileSync)(markerPath2(), JSON.stringify({ global: skew.global, hooks: skew.hooks, day: today(now) }) + "\n");
|
|
33466
|
+
} catch {
|
|
33467
|
+
}
|
|
33468
|
+
}
|
|
33469
|
+
|
|
33470
|
+
// src/lib/project-skills.ts
|
|
33471
|
+
var import_node_fs55 = require("node:fs");
|
|
33472
|
+
var import_node_path42 = require("node:path");
|
|
33443
33473
|
var PROJECT_SKILL_NAMES = [
|
|
33444
33474
|
"verity-setup",
|
|
33445
33475
|
"verity-analyze",
|
|
@@ -33465,14 +33495,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
33465
33495
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
33466
33496
|
function staleProjectSkills() {
|
|
33467
33497
|
const root = projectPath(".claude/skills");
|
|
33468
|
-
if (!(0,
|
|
33469
|
-
return ALL.filter((name2) => (0,
|
|
33498
|
+
if (!(0, import_node_fs55.existsSync)(root)) return [];
|
|
33499
|
+
return ALL.filter((name2) => (0, import_node_fs55.existsSync)((0, import_node_path42.join)(root, name2)));
|
|
33470
33500
|
}
|
|
33471
33501
|
function removeProjectSkills() {
|
|
33472
33502
|
const root = projectPath(".claude/skills");
|
|
33473
33503
|
const removed = [];
|
|
33474
33504
|
for (const name2 of staleProjectSkills()) {
|
|
33475
|
-
(0,
|
|
33505
|
+
(0, import_node_fs55.rmSync)((0, import_node_path42.join)(root, name2), { recursive: true, force: true });
|
|
33476
33506
|
removed.push(name2);
|
|
33477
33507
|
}
|
|
33478
33508
|
return removed;
|
|
@@ -33502,10 +33532,12 @@ function registerBaselineCommands(program2) {
|
|
|
33502
33532
|
const skew = cliVersionSkew();
|
|
33503
33533
|
const why = skew ? `the \`verity\` on PATH is ${skew.global} but the hooks run ${skew.hooks}, so it is not the CLI they use` : verityOnPath() ? "the `verity` on PATH is a separate install whose version could not be read" : "this machine has no `verity` on PATH \u2014 the plugin carries its own copy";
|
|
33504
33534
|
const cliLine = cli ? `Verity CLI: ${why}. When a Verity skill tells you to run \`verity <args>\`, run \`${cli} <args>\` instead. Everything else about the command is identical.` : null;
|
|
33505
|
-
const
|
|
33506
|
-
const
|
|
33535
|
+
const skewLoud = !!skew && skewNoticeDue(skew);
|
|
33536
|
+
const skewMsg = skew && skewLoud ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
|
|
33537
|
+
const loginWarning = "Until they have, do not send them to run `verity login` in a terminal: that runs the global one, which can sign this machine in to a different server.";
|
|
33538
|
+
const skewNote = !skew ? null : skewLoud ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. ${loginWarning}` : `The user's global \`verity\` is ${skew.global} and the hooks run ${skew.hooks}; \`${skew.remedy}\` fixes it. They were already told today, so do not repeat it unprompted \u2014 mention it only where it matters, such as before suggesting a \`verity\` command for their terminal. ${loginWarning}`;
|
|
33507
33539
|
if (!verityConfigured()) {
|
|
33508
|
-
if (isMachineStore((0,
|
|
33540
|
+
if (isMachineStore((0, import_node_path43.join)(repoRoot(), VERITY_DIR))) process.exit(0);
|
|
33509
33541
|
const how = isPluginInvocation() ? "Tell the user to run /verity:init \u2014 they type it; you cannot invoke it." : "Tell the user to run `verity init` in their terminal.";
|
|
33510
33542
|
const lines = [
|
|
33511
33543
|
`Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
|
|
@@ -33532,19 +33564,20 @@ function registerBaselineCommands(program2) {
|
|
|
33532
33564
|
}
|
|
33533
33565
|
}) + "\n"
|
|
33534
33566
|
);
|
|
33567
|
+
if (skew && skewMsg) recordSkewNotice(skew);
|
|
33535
33568
|
process.exit(0);
|
|
33536
33569
|
}
|
|
33537
33570
|
const realStart = source2 === void 0 || source2 === "startup" || source2 === "clear";
|
|
33538
33571
|
let memoryMsg = null;
|
|
33539
33572
|
let memoryAgentLine = null;
|
|
33540
33573
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
33541
|
-
if (realStart && !(0,
|
|
33574
|
+
if (realStart && !(0, import_node_fs56.existsSync)(memoryNotice)) {
|
|
33542
33575
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
33543
33576
|
if (trackedGraph > 0) {
|
|
33544
33577
|
memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
|
|
33545
33578
|
memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
|
|
33546
33579
|
try {
|
|
33547
|
-
(0,
|
|
33580
|
+
(0, import_node_fs56.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
33548
33581
|
} catch {
|
|
33549
33582
|
}
|
|
33550
33583
|
}
|
|
@@ -33572,7 +33605,7 @@ function registerBaselineCommands(program2) {
|
|
|
33572
33605
|
}
|
|
33573
33606
|
}
|
|
33574
33607
|
if (memoryAgentLine) notices.push(memoryAgentLine);
|
|
33575
|
-
if (notices.length > 0) {
|
|
33608
|
+
if (notices.length > 0 || skewMsg) {
|
|
33576
33609
|
process.stdout.write(
|
|
33577
33610
|
JSON.stringify({
|
|
33578
33611
|
...userMsg || skewMsg || memoryMsg ? { systemMessage: [skewMsg, userMsg, memoryMsg].filter(Boolean).join("\n") } : {},
|
|
@@ -33582,6 +33615,7 @@ function registerBaselineCommands(program2) {
|
|
|
33582
33615
|
}
|
|
33583
33616
|
}) + "\n"
|
|
33584
33617
|
);
|
|
33618
|
+
if (skew && skewMsg) recordSkewNotice(skew);
|
|
33585
33619
|
}
|
|
33586
33620
|
} else if (memoryMsg) {
|
|
33587
33621
|
process.stdout.write(
|
|
@@ -33645,7 +33679,7 @@ function hookSource(value) {
|
|
|
33645
33679
|
}
|
|
33646
33680
|
|
|
33647
33681
|
// src/commands/review.ts
|
|
33648
|
-
var
|
|
33682
|
+
var import_node_fs57 = require("node:fs");
|
|
33649
33683
|
function registerReviewCommand(program2) {
|
|
33650
33684
|
program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars); - reads it from stdin, so the words never pass through shell quoting").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
|
|
33651
33685
|
const globals = program2.opts();
|
|
@@ -33668,7 +33702,7 @@ async function runReview(opts, globals) {
|
|
|
33668
33702
|
const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
|
|
33669
33703
|
const analyzable = filterAnalyzable(allFiles);
|
|
33670
33704
|
const securityFiles = filterSecurity(allFiles);
|
|
33671
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
33705
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs57.existsSync)(f) || resolveFile(f) !== null);
|
|
33672
33706
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
33673
33707
|
const codeDelta = collectCodeDelta(allFiles);
|
|
33674
33708
|
const tokenResult = await resolveToken(globals.token);
|
|
@@ -33734,12 +33768,12 @@ async function runReview(opts, globals) {
|
|
|
33734
33768
|
}
|
|
33735
33769
|
|
|
33736
33770
|
// src/commands/guard.ts
|
|
33737
|
-
var
|
|
33738
|
-
var
|
|
33771
|
+
var import_node_fs62 = require("node:fs");
|
|
33772
|
+
var import_node_path49 = require("node:path");
|
|
33739
33773
|
|
|
33740
33774
|
// src/lib/vendored.ts
|
|
33741
|
-
var
|
|
33742
|
-
var
|
|
33775
|
+
var import_node_fs58 = require("node:fs");
|
|
33776
|
+
var import_node_path44 = require("node:path");
|
|
33743
33777
|
var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
|
|
33744
33778
|
function dataDirOrNull() {
|
|
33745
33779
|
try {
|
|
@@ -33754,7 +33788,7 @@ function shippedSkillFile(path, dataDir = dataDirOrNull()) {
|
|
|
33754
33788
|
const [, skill, rel] = m;
|
|
33755
33789
|
if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
|
|
33756
33790
|
try {
|
|
33757
|
-
return (0,
|
|
33791
|
+
return (0, import_node_fs58.readFileSync)((0, import_node_path44.join)(dataDir, "skills", skill, rel), "utf8");
|
|
33758
33792
|
} catch {
|
|
33759
33793
|
return null;
|
|
33760
33794
|
}
|
|
@@ -33864,7 +33898,7 @@ async function runAgentReview(options) {
|
|
|
33864
33898
|
}
|
|
33865
33899
|
|
|
33866
33900
|
// src/lib/prove/auto.ts
|
|
33867
|
-
var
|
|
33901
|
+
var import_node_path48 = require("node:path");
|
|
33868
33902
|
var import_node_crypto19 = require("node:crypto");
|
|
33869
33903
|
|
|
33870
33904
|
// src/lib/prove/signals.ts
|
|
@@ -34906,9 +34940,9 @@ function effectSites(numbered2) {
|
|
|
34906
34940
|
const t = r.text.trim();
|
|
34907
34941
|
if (!t || t.startsWith("//") || t.startsWith("#") || t.startsWith("*")) continue;
|
|
34908
34942
|
const onParam = [...params].some((p) => callsOn(t, p) || callsDirect(t, p));
|
|
34909
|
-
const
|
|
34910
|
-
if (!
|
|
34911
|
-
out2.push(`L${r.n} [${
|
|
34943
|
+
const kind2 = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
|
|
34944
|
+
if (!kind2) continue;
|
|
34945
|
+
out2.push(`L${r.n} [${kind2}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
|
|
34912
34946
|
if (out2.length >= MAX_EFFECT_SITES) break;
|
|
34913
34947
|
}
|
|
34914
34948
|
return out2;
|
|
@@ -35591,18 +35625,18 @@ function renderReplay(model, property, r) {
|
|
|
35591
35625
|
// src/lib/prove/runner.ts
|
|
35592
35626
|
var import_node_child_process15 = require("node:child_process");
|
|
35593
35627
|
var import_node_os8 = require("node:os");
|
|
35594
|
-
var
|
|
35628
|
+
var import_node_fs61 = require("node:fs");
|
|
35595
35629
|
var import_node_os9 = require("node:os");
|
|
35596
|
-
var
|
|
35630
|
+
var import_node_path47 = require("node:path");
|
|
35597
35631
|
|
|
35598
35632
|
// src/lib/prove/scaffold.ts
|
|
35599
|
-
var
|
|
35600
|
-
var
|
|
35633
|
+
var import_node_fs60 = require("node:fs");
|
|
35634
|
+
var import_node_path46 = require("node:path");
|
|
35601
35635
|
|
|
35602
35636
|
// src/lib/prove/safe-write.ts
|
|
35603
|
-
var
|
|
35637
|
+
var import_node_fs59 = require("node:fs");
|
|
35604
35638
|
var import_node_crypto15 = require("node:crypto");
|
|
35605
|
-
var
|
|
35639
|
+
var import_node_path45 = require("node:path");
|
|
35606
35640
|
var SafeWriteError = class extends Error {
|
|
35607
35641
|
constructor(reason, path) {
|
|
35608
35642
|
super(`refusing to write ${path}: ${reason}`);
|
|
@@ -35611,10 +35645,10 @@ var SafeWriteError = class extends Error {
|
|
|
35611
35645
|
this.name = "SafeWriteError";
|
|
35612
35646
|
}
|
|
35613
35647
|
};
|
|
35614
|
-
var FLAGS3 =
|
|
35648
|
+
var FLAGS3 = import_node_fs59.constants;
|
|
35615
35649
|
var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
|
|
35616
35650
|
function assertPlainRelative(rel) {
|
|
35617
|
-
if (!rel || (0,
|
|
35651
|
+
if (!rel || (0, import_node_path45.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
|
|
35618
35652
|
for (const part of rel.split(/[\\/]/)) {
|
|
35619
35653
|
if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
|
|
35620
35654
|
}
|
|
@@ -35623,34 +35657,34 @@ function ensureDirsNoFollow(root, rel) {
|
|
|
35623
35657
|
const parts2 = rel.split(/[\\/]/);
|
|
35624
35658
|
let cur = root;
|
|
35625
35659
|
for (const part of parts2.slice(0, -1)) {
|
|
35626
|
-
cur = (0,
|
|
35660
|
+
cur = (0, import_node_path45.join)(cur, part);
|
|
35627
35661
|
let st;
|
|
35628
35662
|
try {
|
|
35629
|
-
st = (0,
|
|
35663
|
+
st = (0, import_node_fs59.lstatSync)(cur);
|
|
35630
35664
|
} catch {
|
|
35631
|
-
(0,
|
|
35665
|
+
(0, import_node_fs59.mkdirSync)(cur);
|
|
35632
35666
|
continue;
|
|
35633
35667
|
}
|
|
35634
35668
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
|
|
35635
35669
|
if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
|
|
35636
35670
|
}
|
|
35637
|
-
return (0,
|
|
35671
|
+
return (0, import_node_path45.join)(root, rel);
|
|
35638
35672
|
}
|
|
35639
35673
|
function insideRoot(realRoot, realPath) {
|
|
35640
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
35674
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path45.sep) ? realRoot : realRoot + import_node_path45.sep);
|
|
35641
35675
|
}
|
|
35642
35676
|
function removeQuietly(path) {
|
|
35643
35677
|
try {
|
|
35644
|
-
(0,
|
|
35678
|
+
(0, import_node_fs59.unlinkSync)(path);
|
|
35645
35679
|
} catch {
|
|
35646
35680
|
}
|
|
35647
35681
|
}
|
|
35648
35682
|
function writeFileInRootNoFollow(root, rel, content) {
|
|
35649
35683
|
assertPlainRelative(rel);
|
|
35650
35684
|
const dest = ensureDirsNoFollow(root, rel);
|
|
35651
|
-
const dir = (0,
|
|
35685
|
+
const dir = (0, import_node_path45.dirname)(dest);
|
|
35652
35686
|
try {
|
|
35653
|
-
const st = (0,
|
|
35687
|
+
const st = (0, import_node_fs59.lstatSync)(dest);
|
|
35654
35688
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
|
|
35655
35689
|
if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
|
|
35656
35690
|
} catch (err2) {
|
|
@@ -35658,41 +35692,41 @@ function writeFileInRootNoFollow(root, rel, content) {
|
|
|
35658
35692
|
}
|
|
35659
35693
|
let realRoot;
|
|
35660
35694
|
try {
|
|
35661
|
-
realRoot = (0,
|
|
35695
|
+
realRoot = (0, import_node_fs59.realpathSync)(root);
|
|
35662
35696
|
} catch {
|
|
35663
35697
|
throw new SafeWriteError("unwritable", root);
|
|
35664
35698
|
}
|
|
35665
|
-
const tmp = (0,
|
|
35699
|
+
const tmp = (0, import_node_path45.join)(dir, `.${(0, import_node_path45.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
|
|
35666
35700
|
let fd;
|
|
35667
35701
|
try {
|
|
35668
|
-
fd = (0,
|
|
35702
|
+
fd = (0, import_node_fs59.openSync)(tmp, import_node_fs59.constants.O_WRONLY | import_node_fs59.constants.O_CREAT | import_node_fs59.constants.O_EXCL | NOFOLLOW2, 420);
|
|
35669
35703
|
} catch {
|
|
35670
35704
|
throw new SafeWriteError("unwritable", tmp);
|
|
35671
35705
|
}
|
|
35672
35706
|
try {
|
|
35673
|
-
const opened = (0,
|
|
35707
|
+
const opened = (0, import_node_fs59.fstatSync)(fd, { bigint: true });
|
|
35674
35708
|
let realTmp;
|
|
35675
35709
|
try {
|
|
35676
|
-
realTmp = (0,
|
|
35710
|
+
realTmp = (0, import_node_fs59.realpathSync)(tmp);
|
|
35677
35711
|
} catch {
|
|
35678
35712
|
throw new SafeWriteError("escaped", tmp);
|
|
35679
35713
|
}
|
|
35680
|
-
const there = (0,
|
|
35714
|
+
const there = (0, import_node_fs59.lstatSync)(realTmp, { bigint: true });
|
|
35681
35715
|
if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
|
|
35682
35716
|
throw new SafeWriteError("escaped", tmp);
|
|
35683
35717
|
}
|
|
35684
35718
|
const buf = Buffer.from(content, "utf-8");
|
|
35685
35719
|
let off = 0;
|
|
35686
|
-
while (off < buf.length) off += (0,
|
|
35720
|
+
while (off < buf.length) off += (0, import_node_fs59.writeSync)(fd, buf, off, buf.length - off);
|
|
35687
35721
|
} catch (err2) {
|
|
35688
|
-
(0,
|
|
35722
|
+
(0, import_node_fs59.closeSync)(fd);
|
|
35689
35723
|
removeQuietly(tmp);
|
|
35690
35724
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
|
|
35691
35725
|
}
|
|
35692
|
-
(0,
|
|
35726
|
+
(0, import_node_fs59.closeSync)(fd);
|
|
35693
35727
|
try {
|
|
35694
|
-
if (!insideRoot(realRoot, (0,
|
|
35695
|
-
(0,
|
|
35728
|
+
if (!insideRoot(realRoot, (0, import_node_fs59.realpathSync)(dir)) || (0, import_node_fs59.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
|
|
35729
|
+
(0, import_node_fs59.renameSync)(tmp, dest);
|
|
35696
35730
|
} catch (err2) {
|
|
35697
35731
|
removeQuietly(tmp);
|
|
35698
35732
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
|
|
@@ -35706,9 +35740,9 @@ function pathHasNoLink(root, rel) {
|
|
|
35706
35740
|
}
|
|
35707
35741
|
let cur = root;
|
|
35708
35742
|
for (const part of rel.split(/[\\/]/)) {
|
|
35709
|
-
cur = cur +
|
|
35743
|
+
cur = cur + import_node_path45.sep + part;
|
|
35710
35744
|
try {
|
|
35711
|
-
if ((0,
|
|
35745
|
+
if ((0, import_node_fs59.lstatSync)(cur).isSymbolicLink()) return false;
|
|
35712
35746
|
} catch {
|
|
35713
35747
|
return true;
|
|
35714
35748
|
}
|
|
@@ -36018,20 +36052,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
|
|
|
36018
36052
|
never committed; what reaches the team is the bug report and the fix.
|
|
36019
36053
|
`;
|
|
36020
36054
|
function scaffoldProofs(root) {
|
|
36021
|
-
const proofsDir = (0,
|
|
36055
|
+
const proofsDir = (0, import_node_path46.join)(root, PROOFS_DIR);
|
|
36022
36056
|
const written = [];
|
|
36023
36057
|
const kept = [];
|
|
36024
36058
|
for (const stray of ["lakefile.lean"]) {
|
|
36025
36059
|
const rel = `${PROOFS_DIR}/${stray}`;
|
|
36026
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36060
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path46.join)(root, rel));
|
|
36027
36061
|
try {
|
|
36028
|
-
(0,
|
|
36062
|
+
(0, import_node_fs60.rmSync)((0, import_node_path46.join)(root, rel), { force: true });
|
|
36029
36063
|
} catch {
|
|
36030
36064
|
}
|
|
36031
36065
|
}
|
|
36032
36066
|
for (const f of PROOFS_TEMPLATE_FILES) {
|
|
36033
36067
|
const rel = `${PROOFS_DIR}/${f.path}`;
|
|
36034
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36068
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path46.join)(root, rel));
|
|
36035
36069
|
const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
|
|
36036
36070
|
if (current.ok && current.content === f.content) {
|
|
36037
36071
|
kept.push(rel);
|
|
@@ -36044,8 +36078,8 @@ function scaffoldProofs(root) {
|
|
|
36044
36078
|
[`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
|
|
36045
36079
|
[`${MODELS_DIR}/README.md`, MODELS_README]
|
|
36046
36080
|
]) {
|
|
36047
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36048
|
-
if (existsNoFollow((0,
|
|
36081
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path46.join)(root, rel));
|
|
36082
|
+
if (existsNoFollow((0, import_node_path46.join)(root, rel))) {
|
|
36049
36083
|
kept.push(rel);
|
|
36050
36084
|
continue;
|
|
36051
36085
|
}
|
|
@@ -36056,7 +36090,7 @@ function scaffoldProofs(root) {
|
|
|
36056
36090
|
}
|
|
36057
36091
|
function existsNoFollow(abs) {
|
|
36058
36092
|
try {
|
|
36059
|
-
(0,
|
|
36093
|
+
(0, import_node_fs60.lstatSync)(abs);
|
|
36060
36094
|
return true;
|
|
36061
36095
|
} catch {
|
|
36062
36096
|
return false;
|
|
@@ -36135,12 +36169,12 @@ function parseHeader(obj) {
|
|
|
36135
36169
|
function parseProperty(obj) {
|
|
36136
36170
|
const model = ident(obj.model);
|
|
36137
36171
|
const id = ident(obj.id);
|
|
36138
|
-
const
|
|
36172
|
+
const kind2 = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
|
|
36139
36173
|
const result = typeof obj.result === "string" && RESULTS.has(obj.result) ? obj.result : null;
|
|
36140
36174
|
const source2 = obj.source === void 0 ? "" : str2(obj.source, LIMITS.text);
|
|
36141
36175
|
const desc = obj.desc === void 0 ? "" : str2(obj.desc, LIMITS.text);
|
|
36142
|
-
if (!model || !id || !
|
|
36143
|
-
const p = { model, id, kind, source: source2, desc, result };
|
|
36176
|
+
if (!model || !id || !kind2 || !result || source2 === null || desc === null) return null;
|
|
36177
|
+
const p = { model, id, kind: kind2, source: source2, desc, result };
|
|
36144
36178
|
if (obj.bound !== void 0) {
|
|
36145
36179
|
const n = nat(obj.bound);
|
|
36146
36180
|
if (n === null) return null;
|
|
@@ -36314,17 +36348,17 @@ function renderReport(r) {
|
|
|
36314
36348
|
|
|
36315
36349
|
// src/lib/prove/runner.ts
|
|
36316
36350
|
function verityLeanHome(env = process.env) {
|
|
36317
|
-
return env.VERITY_LEAN_HOME ?? (0,
|
|
36351
|
+
return env.VERITY_LEAN_HOME ?? (0, import_node_path47.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
|
|
36318
36352
|
}
|
|
36319
36353
|
function findToolchain(env = process.env) {
|
|
36320
|
-
const managedBin = (0,
|
|
36321
|
-
const elanBin = (0,
|
|
36322
|
-
const elanHas = (0,
|
|
36323
|
-
const userPath = (env.PATH ?? "").split(
|
|
36324
|
-
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(
|
|
36354
|
+
const managedBin = (0, import_node_path47.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
|
|
36355
|
+
const elanBin = (0, import_node_path47.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
|
|
36356
|
+
const elanHas = (0, import_node_fs61.existsSync)((0, import_node_path47.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
|
|
36357
|
+
const userPath = (env.PATH ?? "").split(import_node_path47.delimiter).filter((d) => d && (elanHas || (0, import_node_path47.resolve)(d) !== (0, import_node_path47.resolve)(elanBin)));
|
|
36358
|
+
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path47.delimiter);
|
|
36325
36359
|
const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
|
|
36326
36360
|
const exe = process.platform === "win32" ? "lake.exe" : "lake";
|
|
36327
|
-
const candidates2 = [(0,
|
|
36361
|
+
const candidates2 = [(0, import_node_path47.join)(managedBin, exe), ...elanHas ? [(0, import_node_path47.join)(elanBin, exe)] : [], exe];
|
|
36328
36362
|
for (const candidate of candidates2) {
|
|
36329
36363
|
try {
|
|
36330
36364
|
(0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
|
|
@@ -36403,7 +36437,7 @@ function proofsWorkspaceProblem(root) {
|
|
|
36403
36437
|
for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
|
|
36404
36438
|
let st;
|
|
36405
36439
|
try {
|
|
36406
|
-
st = (0,
|
|
36440
|
+
st = (0, import_node_fs61.lstatSync)((0, import_node_path47.join)(root, rel));
|
|
36407
36441
|
} catch {
|
|
36408
36442
|
break;
|
|
36409
36443
|
}
|
|
@@ -36423,44 +36457,44 @@ function refused(problem) {
|
|
|
36423
36457
|
function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36424
36458
|
const problem = proofsWorkspaceProblem(root);
|
|
36425
36459
|
if (problem) return refused(problem);
|
|
36426
|
-
return run2(tc, (0,
|
|
36460
|
+
return run2(tc, (0, import_node_path47.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36427
36461
|
}
|
|
36428
36462
|
async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36429
36463
|
const problem = proofsWorkspaceProblem(root);
|
|
36430
36464
|
if (problem) return refused(problem);
|
|
36431
|
-
return runAsync(tc, (0,
|
|
36465
|
+
return runAsync(tc, (0, import_node_path47.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36432
36466
|
}
|
|
36433
36467
|
function isModelInRoot(modelsAbs, rel) {
|
|
36434
|
-
if (!rel.endsWith(".lean") || (0,
|
|
36468
|
+
if (!rel.endsWith(".lean") || (0, import_node_path47.isAbsolute)(rel) || rel.startsWith("..")) return false;
|
|
36435
36469
|
return statRegularInRoot(modelsAbs, rel).ok;
|
|
36436
36470
|
}
|
|
36437
36471
|
function resolveModelFile(root, arg) {
|
|
36438
|
-
const modelsAbs = (0,
|
|
36439
|
-
const asPath = (0,
|
|
36472
|
+
const modelsAbs = (0, import_node_path47.join)(root, MODELS_DIR);
|
|
36473
|
+
const asPath = (0, import_node_path47.relative)(modelsAbs, (0, import_node_path47.isAbsolute)(arg) ? arg : (0, import_node_path47.resolve)(root, arg));
|
|
36440
36474
|
const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
|
|
36441
36475
|
for (const rel of candidates2) {
|
|
36442
|
-
if (isModelInRoot(modelsAbs, rel)) return (0,
|
|
36476
|
+
if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path47.join)(modelsAbs, rel);
|
|
36443
36477
|
}
|
|
36444
36478
|
return null;
|
|
36445
36479
|
}
|
|
36446
36480
|
function listModelFiles(root) {
|
|
36447
|
-
const modelsAbs = (0,
|
|
36448
|
-
if (!(0,
|
|
36449
|
-
return (0,
|
|
36481
|
+
const modelsAbs = (0, import_node_path47.join)(root, MODELS_DIR);
|
|
36482
|
+
if (!(0, import_node_fs61.existsSync)(modelsAbs)) return [];
|
|
36483
|
+
return (0, import_node_fs61.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path47.join)(modelsAbs, f));
|
|
36450
36484
|
}
|
|
36451
36485
|
function trimDiagnostics(text) {
|
|
36452
36486
|
return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
|
|
36453
36487
|
}
|
|
36454
36488
|
function checkModel(tc, root, modelFile, opts = {}) {
|
|
36455
|
-
const proofsAbs = (0,
|
|
36456
|
-
const rel = (0,
|
|
36489
|
+
const proofsAbs = (0, import_node_path47.join)(root, PROOFS_DIR);
|
|
36490
|
+
const rel = (0, import_node_path47.relative)(proofsAbs, modelFile);
|
|
36457
36491
|
const problem = proofsWorkspaceProblem(root);
|
|
36458
36492
|
const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36459
36493
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36460
36494
|
}
|
|
36461
36495
|
async function checkModelAsync(tc, root, modelFile, opts = {}) {
|
|
36462
|
-
const proofsAbs = (0,
|
|
36463
|
-
const rel = (0,
|
|
36496
|
+
const proofsAbs = (0, import_node_path47.join)(root, PROOFS_DIR);
|
|
36497
|
+
const rel = (0, import_node_path47.relative)(proofsAbs, modelFile);
|
|
36464
36498
|
const problem = proofsWorkspaceProblem(root);
|
|
36465
36499
|
const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36466
36500
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
@@ -36469,10 +36503,10 @@ function toReport(res, root, modelFile, timeoutMs) {
|
|
|
36469
36503
|
const parsed = parseVerityLines(res.stdout);
|
|
36470
36504
|
const combined = `${res.stdout}
|
|
36471
36505
|
${res.stderr}`;
|
|
36472
|
-
const name2 = parsed.header?.model ?? (0,
|
|
36506
|
+
const name2 = parsed.header?.model ?? (0, import_node_path47.basename)(modelFile, ".lean");
|
|
36473
36507
|
const report = {
|
|
36474
36508
|
model: name2,
|
|
36475
|
-
file: (0,
|
|
36509
|
+
file: (0, import_node_path47.relative)(root, modelFile),
|
|
36476
36510
|
ok: res.ok,
|
|
36477
36511
|
header: parsed.header,
|
|
36478
36512
|
properties: parsed.properties,
|
|
@@ -36519,9 +36553,9 @@ function isCrashTrace(trace) {
|
|
|
36519
36553
|
}
|
|
36520
36554
|
function mergeFormalFindings(response, outcome, pushedFiles) {
|
|
36521
36555
|
if (!outcome) return { blocking: 0 };
|
|
36522
|
-
const
|
|
36523
|
-
const pushed = new Set(pushedFiles.map(
|
|
36524
|
-
const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(
|
|
36556
|
+
const norm3 = (p) => p.replace(/\\/g, "/");
|
|
36557
|
+
const pushed = new Set(pushedFiles.map(norm3));
|
|
36558
|
+
const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm3(f.file)));
|
|
36525
36559
|
if (blocking.length === 0) return { blocking: 0 };
|
|
36526
36560
|
const existing = Array.isArray(response.findings) ? response.findings : [];
|
|
36527
36561
|
response.findings = [
|
|
@@ -36717,15 +36751,15 @@ function nonNegative(v) {
|
|
|
36717
36751
|
return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
|
|
36718
36752
|
}
|
|
36719
36753
|
function readLedger(root) {
|
|
36720
|
-
const
|
|
36721
|
-
const empty = { day:
|
|
36754
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
36755
|
+
const empty = { day: today2, models: 0, costUsd: 0 };
|
|
36722
36756
|
if (!isLocalState(root, AUTO_LEDGER)) return empty;
|
|
36723
36757
|
const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
|
|
36724
36758
|
if (!read2.ok) return empty;
|
|
36725
36759
|
try {
|
|
36726
36760
|
const o = JSON.parse(read2.content);
|
|
36727
|
-
if (o.day !==
|
|
36728
|
-
return { day:
|
|
36761
|
+
if (o.day !== today2 || typeof o.models !== "number") return empty;
|
|
36762
|
+
return { day: today2, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
|
|
36729
36763
|
} catch {
|
|
36730
36764
|
return empty;
|
|
36731
36765
|
}
|
|
@@ -36903,7 +36937,7 @@ async function runFormalPhase(input) {
|
|
|
36903
36937
|
const ranked = await deps.rank(eligible, root, input.changedLines);
|
|
36904
36938
|
if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
|
|
36905
36939
|
if (ranked.ok) spend(ranked);
|
|
36906
|
-
candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
|
|
36940
|
+
candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)), commits: c.commits, fixCommits: c.fixCommits, risk: c.risk }));
|
|
36907
36941
|
if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
|
|
36908
36942
|
const minScore = input.minScore ?? DEFAULT_MIN_SCORE;
|
|
36909
36943
|
let qualified = ranked.ranked.filter((c) => c.ai && c.ai.score >= minScore);
|
|
@@ -37012,7 +37046,7 @@ async function runFormalPhase(input) {
|
|
|
37012
37046
|
const sha2562 = sha256Of(chosen.content);
|
|
37013
37047
|
const chosenContent = chosen.content;
|
|
37014
37048
|
const { lines, numbered: numbered2 } = chosen;
|
|
37015
|
-
const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {} };
|
|
37049
|
+
const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {}, signals: { commits: top.commits, fixCommits: top.fixCommits, risk: top.risk } };
|
|
37016
37050
|
progress.target = target;
|
|
37017
37051
|
if (!REPLAYABLE.test(top.file)) return done({ status: "skipped", skip: "replay-unsupported", detail: `${top.file}: replay supports TS/JS and Python`, target });
|
|
37018
37052
|
if (timeLeft() < GENERATE_RESERVE_MS) return done({ status: "skipped", skip: "not-enough-time", detail: `${Math.round(timeLeft() / 1e3)} s left before generation`, target });
|
|
@@ -37042,7 +37076,7 @@ async function runFormalPhase(input) {
|
|
|
37042
37076
|
modelName = gen.name;
|
|
37043
37077
|
const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
|
|
37044
37078
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
37045
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37079
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path48.join)(root, rel);
|
|
37046
37080
|
progress.model = { name: gen.name, file: rel, rounds: round };
|
|
37047
37081
|
progress.step = "check";
|
|
37048
37082
|
report = await deps.check(root, abs);
|
|
@@ -37164,7 +37198,7 @@ async function runFormalPhase(input) {
|
|
|
37164
37198
|
return done({
|
|
37165
37199
|
status: "checked",
|
|
37166
37200
|
target,
|
|
37167
|
-
model: { name: modelName, file: (0,
|
|
37201
|
+
model: { name: modelName, file: (0, import_node_path48.relative)(root, (0, import_node_path48.join)(root, modelFile)), rounds },
|
|
37168
37202
|
properties: report.properties,
|
|
37169
37203
|
findings
|
|
37170
37204
|
});
|
|
@@ -37197,7 +37231,19 @@ async function generateAndCheck(root, req, opts) {
|
|
|
37197
37231
|
const read2 = readSrc(req.file, 96 * 1024);
|
|
37198
37232
|
if (!read2.ok) return { ok: false, error: `${req.file}: ${read2.reason}`, rounds: 0, costUsd: 0 };
|
|
37199
37233
|
const sha2562 = sha256Of(read2.content);
|
|
37200
|
-
const { lines, numbered: numbered2 } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
|
|
37234
|
+
const { lines, numbered: numbered2, extent } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
|
|
37235
|
+
let warning;
|
|
37236
|
+
if (!lines) {
|
|
37237
|
+
const outline = extent === "fallback:not-found" ? opts.deps.codeMap?.outline(req.file, read2.content) : void 0;
|
|
37238
|
+
if (outline?.source === "tree-sitter") {
|
|
37239
|
+
const names2 = [...new Set(outline.value.filter((f) => f.name && f.kind !== "lambda").map((f) => f.qualified))];
|
|
37240
|
+
const last = (req.symbol.split(/[.#:]/).pop() ?? req.symbol).toLowerCase();
|
|
37241
|
+
const close = names2.filter((n) => n.toLowerCase().includes(last));
|
|
37242
|
+
const shown = (close.length > 0 ? close : names2).slice(0, 12);
|
|
37243
|
+
return { ok: false, error: `no function \`${req.symbol}\` in ${req.file}${shown.length ? ` (it has: ${shown.join(", ")})` : ""}. Name one as ${req.file}#<name>, or pass --lines a-b`, rounds: 0, costUsd: 0 };
|
|
37244
|
+
}
|
|
37245
|
+
warning = `could not find the lines of \`${req.symbol}\` in ${req.file} (${extent}): the model is written from the start of the file, and a replay must copy half of the whole file. Pass --lines a-b to name the code.`;
|
|
37246
|
+
}
|
|
37201
37247
|
const target = {
|
|
37202
37248
|
file: req.file,
|
|
37203
37249
|
symbol: req.symbol,
|
|
@@ -37205,7 +37251,9 @@ async function generateAndCheck(root, req, opts) {
|
|
|
37205
37251
|
sha256: sha2562,
|
|
37206
37252
|
numbered: numbered2,
|
|
37207
37253
|
reasons: req.hint ? [`the user's worry, in their words: ${req.hint.slice(0, 280)}`] : [],
|
|
37208
|
-
properties: []
|
|
37254
|
+
properties: [],
|
|
37255
|
+
// The run row records which extractor answered, as at push.
|
|
37256
|
+
extentSource: extent
|
|
37209
37257
|
};
|
|
37210
37258
|
const context = opts.deps.codeMap && !req.lines ? targetContext({ codeMap: opts.deps.codeMap, codeSource: opts.deps.codeSource, readSource: readSrc, file: req.file, content: read2.content, symbol: req.symbol }) : null;
|
|
37211
37259
|
Object.assign(target, context?.fields ?? {});
|
|
@@ -37227,7 +37275,7 @@ async function generateAndCheck(root, req, opts) {
|
|
|
37227
37275
|
}
|
|
37228
37276
|
const rel = `${dir}/${gen.name}.lean`;
|
|
37229
37277
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
37230
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37278
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path48.join)(root, rel);
|
|
37231
37279
|
const report = await opts.deps.check(root, abs);
|
|
37232
37280
|
const abstracts = report.header?.abstracts ?? [];
|
|
37233
37281
|
const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
|
|
@@ -37241,14 +37289,14 @@ async function generateAndCheck(root, req, opts) {
|
|
|
37241
37289
|
const g = basisOf(p.source, files);
|
|
37242
37290
|
return g.ok ? [] : [`${p.id}: ${g.why}`];
|
|
37243
37291
|
});
|
|
37244
|
-
if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd };
|
|
37292
|
+
if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd, ...warning ? { warning } : {} };
|
|
37245
37293
|
lastError = ungroundedMessage(bad.join("; "));
|
|
37246
37294
|
if (round < maxRounds) {
|
|
37247
37295
|
previous = { source: gen.source, error: lastError };
|
|
37248
37296
|
continue;
|
|
37249
37297
|
}
|
|
37250
37298
|
const grounded = report.properties.filter((p) => basisOf(p.source, files).ok);
|
|
37251
|
-
if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd };
|
|
37299
|
+
if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd, ...warning ? { warning } : {} };
|
|
37252
37300
|
break;
|
|
37253
37301
|
}
|
|
37254
37302
|
lastError = stray ? `the model abstracts ${stray.file}, not ${req.file}` : report.error ?? (report.malformed ? "the model printed malformed VERITY lines" : "the model reported no property");
|
|
@@ -37274,9 +37322,16 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
|
|
|
37274
37322
|
}
|
|
37275
37323
|
const build = await buildLibraryAsync(toolchain, root, 9e4);
|
|
37276
37324
|
if (!build.ok) return { ok: false, skip: "library-build-failed", detail: build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).join(" ").slice(0, 200) };
|
|
37325
|
+
const code = await loadCodeContext(root, env, codeSource);
|
|
37326
|
+
return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...code }), codeSource: code.codeSource } };
|
|
37327
|
+
}
|
|
37328
|
+
async function loadCodeContext(root, env = process.env, codeSource) {
|
|
37277
37329
|
const loaded = await loadCodeMap(env);
|
|
37278
|
-
|
|
37279
|
-
|
|
37330
|
+
return { codeMap: loaded.ok ? loaded.map : null, codeSource: codeSource ?? withoutPaths(worktreeSource(root), isDeniedPath) };
|
|
37331
|
+
}
|
|
37332
|
+
async function onDemandDeps(root, opts) {
|
|
37333
|
+
const code = await loadCodeContext(root, opts.env);
|
|
37334
|
+
return { ...defaultDeps({ ...opts, tier: "deep", ...code }), codeSource: code.codeSource };
|
|
37280
37335
|
}
|
|
37281
37336
|
function changedFunction(codeMap, file, content, changed) {
|
|
37282
37337
|
const outline = codeMap.outline(file, content);
|
|
@@ -37351,13 +37406,138 @@ function describeFormalOutcome(o) {
|
|
|
37351
37406
|
return `formal: ${o.model?.name ?? "?"} on ${o.target?.file ?? "?"}#${o.target?.symbol ?? "?"} (${o.model?.rounds ?? 1} round${o.model?.rounds === 1 ? "" : "s"}) \xB7 ${parts2.join(" \xB7 ")} \xB7 ${Math.round(o.durationMs / 1e3)} s${cost}${cut}`;
|
|
37352
37407
|
}
|
|
37353
37408
|
|
|
37409
|
+
// src/lib/prove/record.ts
|
|
37410
|
+
var RECORD_TIMEOUT_MS = 8e3;
|
|
37411
|
+
var HOOK_EXIT_MARGIN_MS = 5e3;
|
|
37412
|
+
var MIN_RECORD_POST_MS = 1e3;
|
|
37413
|
+
function guardRecordDeadline(hookStartedAt) {
|
|
37414
|
+
return hookStartedAt + GUARD_TIMEOUT_MS - HOOK_EXIT_MARGIN_MS;
|
|
37415
|
+
}
|
|
37416
|
+
function recordPostTimeout(now, deadlineAt, timeoutMs = RECORD_TIMEOUT_MS) {
|
|
37417
|
+
if (deadlineAt === void 0) return timeoutMs;
|
|
37418
|
+
const left = deadlineAt - now;
|
|
37419
|
+
return left < MIN_RECORD_POST_MS ? null : Math.min(timeoutMs, left);
|
|
37420
|
+
}
|
|
37421
|
+
var norm2 = (p) => p.replace(/\\/g, "/");
|
|
37422
|
+
var SAFE_SEGMENT = /^[A-Za-z0-9._@+~$()[\]-]{1,255}$/;
|
|
37423
|
+
function safeRepoPath(p) {
|
|
37424
|
+
const n = norm2(p);
|
|
37425
|
+
if (!n || n.length > 512 || n.startsWith("/") || /^[A-Za-z]:\//.test(n)) return null;
|
|
37426
|
+
return n.split("/").every((s) => s !== "." && s !== ".." && SAFE_SEGMENT.test(s)) ? n : null;
|
|
37427
|
+
}
|
|
37428
|
+
var SYMBOL = /^[A-Za-z_$][\w$]*(?:[.#:][A-Za-z_$][\w$]*)*$/;
|
|
37429
|
+
var IDENT3 = /^[A-Za-z][\w]*$/;
|
|
37430
|
+
var TRACE_STEP = /^[A-Za-z_]\w{0,63}$/;
|
|
37431
|
+
var ELIDED_STEP = "\u2026";
|
|
37432
|
+
function recordBasis(source2) {
|
|
37433
|
+
if (typeof source2 !== "string") return "";
|
|
37434
|
+
if (/^rule:[a-z-]+$/.test(source2)) return source2;
|
|
37435
|
+
const m = /^(?:([^:\s]+):)?L(\d+)(?::|$)/.exec(source2);
|
|
37436
|
+
return m ? m[1] ? `${norm2(m[1])}:L${m[2]}` : `L${m[2]}` : "";
|
|
37437
|
+
}
|
|
37438
|
+
function recordTrace(trace) {
|
|
37439
|
+
return trace.slice(0, 16).map((s) => {
|
|
37440
|
+
const name2 = (s.trim().split(/[\s(]/, 1)[0] ?? "").split(".").pop() ?? "";
|
|
37441
|
+
return TRACE_STEP.test(name2) ? name2 : ELIDED_STEP;
|
|
37442
|
+
});
|
|
37443
|
+
}
|
|
37444
|
+
var ident2 = (s, re, max) => typeof s === "string" && s.length <= max && re.test(s) ? s : null;
|
|
37445
|
+
var kind = (k) => k === "intent" ? "intent" : "structural";
|
|
37446
|
+
var signalsOf = (c) => c && typeof c.commits === "number" && typeof c.fixCommits === "number" ? { commits: c.commits, fix_commits: c.fixCommits, risk: Object.fromEntries(Object.entries(c.risk ?? {}).filter(([, n]) => typeof n === "number" && n > 0).slice(0, 16)) } : null;
|
|
37447
|
+
function buildPhaseRecord(outcome, ctx) {
|
|
37448
|
+
const pushed = new Set(ctx.pushedFiles.map(norm2));
|
|
37449
|
+
const blocks = (f) => ctx.moment === "push" && f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file));
|
|
37450
|
+
const symbol = (s) => ident2(s, SYMBOL, 200);
|
|
37451
|
+
return {
|
|
37452
|
+
moment: ctx.moment,
|
|
37453
|
+
status: outcome.status,
|
|
37454
|
+
skip: outcome.skip ?? null,
|
|
37455
|
+
parent_run_id: ctx.parentRunId,
|
|
37456
|
+
target: outcome.target && symbol(outcome.target.symbol) && safeRepoPath(outcome.target.file) ? {
|
|
37457
|
+
file: safeRepoPath(outcome.target.file),
|
|
37458
|
+
symbol: symbol(outcome.target.symbol),
|
|
37459
|
+
lines: outcome.target.lines ?? null,
|
|
37460
|
+
score: Math.max(0, Math.min(1, outcome.target.score)),
|
|
37461
|
+
extent: ident2(outcome.target.extent, /^[a-z-]+(?::[a-z-]+)?$/, 60),
|
|
37462
|
+
signals: signalsOf(outcome.target.signals)
|
|
37463
|
+
} : null,
|
|
37464
|
+
candidates: (outcome.candidates ?? []).filter((c) => safeRepoPath(c.file)).slice(0, 12).map((c) => ({
|
|
37465
|
+
file: safeRepoPath(c.file),
|
|
37466
|
+
symbol: c.symbol === null ? null : symbol(c.symbol),
|
|
37467
|
+
score: c.score === null ? null : Math.max(0, Math.min(1, c.score)),
|
|
37468
|
+
criteria: c.criteria,
|
|
37469
|
+
reasked: c.reasked,
|
|
37470
|
+
signals: signalsOf(c)
|
|
37471
|
+
})),
|
|
37472
|
+
model: outcome.model && ident2(outcome.model.name, /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)*$/, 120) ? { name: outcome.model.name, rounds: Math.max(0, Math.min(20, outcome.model.rounds)) } : null,
|
|
37473
|
+
properties: (outcome.properties ?? []).filter((p) => ident2(p.id, IDENT3, 120)).slice(0, 16).map((p) => ({
|
|
37474
|
+
id: p.id,
|
|
37475
|
+
kind: kind(p.kind),
|
|
37476
|
+
basis: recordBasis(p.source),
|
|
37477
|
+
result: p.result,
|
|
37478
|
+
bound: p.bound ?? null,
|
|
37479
|
+
states: p.states ?? null
|
|
37480
|
+
})),
|
|
37481
|
+
findings: outcome.findings.filter((f) => ident2(f.property, IDENT3, 120) && symbol(f.symbol) && safeRepoPath(f.file)).slice(0, 8).map((f) => ({
|
|
37482
|
+
property: f.property,
|
|
37483
|
+
kind: kind(f.kind),
|
|
37484
|
+
trace: recordTrace(f.trace),
|
|
37485
|
+
file: safeRepoPath(f.file),
|
|
37486
|
+
symbol: f.symbol,
|
|
37487
|
+
verdict: f.verdict,
|
|
37488
|
+
waived: f.waived === true,
|
|
37489
|
+
blocked: blocks(f)
|
|
37490
|
+
})),
|
|
37491
|
+
grounding: outcome.grounding ? {
|
|
37492
|
+
sent_back: outcome.grounding.sentBack,
|
|
37493
|
+
dropped: outcome.grounding.dropped.filter((id) => ident2(id, IDENT3, 120)).slice(0, 16),
|
|
37494
|
+
trigger_missing: (outcome.grounding.triggerMissing ?? []).filter((id) => ident2(id, IDENT3, 120)).slice(0, 16)
|
|
37495
|
+
} : null,
|
|
37496
|
+
usage: {
|
|
37497
|
+
input_tokens: outcome.usage.inputTokens,
|
|
37498
|
+
output_tokens: outcome.usage.outputTokens,
|
|
37499
|
+
cost_usd: outcome.usage.costUsd,
|
|
37500
|
+
unpriced: outcome.usage.unpriced
|
|
37501
|
+
},
|
|
37502
|
+
duration_ms: Math.round(outcome.durationMs)
|
|
37503
|
+
};
|
|
37504
|
+
}
|
|
37505
|
+
async function postPhaseRecord(outcome, ctx, post) {
|
|
37506
|
+
try {
|
|
37507
|
+
const timeout = recordPostTimeout((post.now ?? Date.now)(), post.deadlineAt, post.timeoutMs ?? RECORD_TIMEOUT_MS);
|
|
37508
|
+
if (timeout === null) {
|
|
37509
|
+
logEvent("formal_record_skipped", { moment: ctx.moment, reason: "hook-deadline" });
|
|
37510
|
+
return null;
|
|
37511
|
+
}
|
|
37512
|
+
const res = await apiRequest({
|
|
37513
|
+
method: "POST",
|
|
37514
|
+
path: "/prove/record",
|
|
37515
|
+
serviceUrl: post.serviceUrl,
|
|
37516
|
+
token: post.token,
|
|
37517
|
+
body: buildPhaseRecord(outcome, ctx),
|
|
37518
|
+
timeout,
|
|
37519
|
+
cmd: "prove-record"
|
|
37520
|
+
});
|
|
37521
|
+
if (!res.ok) {
|
|
37522
|
+
logEvent("formal_record_failed", { moment: ctx.moment, category: res.category ?? "unknown", http_status: res.http_status ?? null });
|
|
37523
|
+
return null;
|
|
37524
|
+
}
|
|
37525
|
+
const runId = typeof res.data?.run_id === "string" ? res.data.run_id : null;
|
|
37526
|
+
logEvent("formal_record", { moment: ctx.moment, run_id: runId });
|
|
37527
|
+
return runId;
|
|
37528
|
+
} catch (err2) {
|
|
37529
|
+
logEvent("formal_record_failed", { moment: ctx.moment, category: "exception", name: err2?.constructor?.name ?? "Error" });
|
|
37530
|
+
return null;
|
|
37531
|
+
}
|
|
37532
|
+
}
|
|
37533
|
+
|
|
37354
37534
|
// src/commands/guard.ts
|
|
37355
37535
|
var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
37356
37536
|
var WRITERS_BUDGET_MS = 1500;
|
|
37357
37537
|
var EXCERPT_MAX_LINES2 = 30;
|
|
37358
37538
|
var VENDORED_READ_MAX_BYTES = 256 * 1024;
|
|
37359
37539
|
var GUARD_BLOCK_CAP = 2;
|
|
37360
|
-
var GUARD_ITER_FILE = (0,
|
|
37540
|
+
var GUARD_ITER_FILE = (0, import_node_path49.join)(VERITY_DIR, ".guard-iteration");
|
|
37361
37541
|
function readPreToolUseStdin() {
|
|
37362
37542
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
37363
37543
|
return new Promise((resolve9) => {
|
|
@@ -37402,7 +37582,7 @@ function readPreToolUseStdin() {
|
|
|
37402
37582
|
}
|
|
37403
37583
|
function readIterMap() {
|
|
37404
37584
|
try {
|
|
37405
|
-
const raw = JSON.parse((0,
|
|
37585
|
+
const raw = JSON.parse((0, import_node_fs62.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
37406
37586
|
if (raw && typeof raw === "object") {
|
|
37407
37587
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
37408
37588
|
return { [raw.moment]: raw.count };
|
|
@@ -37422,10 +37602,10 @@ function readIter(moment) {
|
|
|
37422
37602
|
}
|
|
37423
37603
|
function writeIter(moment, count) {
|
|
37424
37604
|
try {
|
|
37425
|
-
(0,
|
|
37605
|
+
(0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37426
37606
|
const map = readIterMap();
|
|
37427
37607
|
map[moment] = count;
|
|
37428
|
-
(0,
|
|
37608
|
+
(0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37429
37609
|
} catch {
|
|
37430
37610
|
}
|
|
37431
37611
|
}
|
|
@@ -37435,10 +37615,10 @@ function resetIter(moment) {
|
|
|
37435
37615
|
if (!(moment in map)) return;
|
|
37436
37616
|
delete map[moment];
|
|
37437
37617
|
if (Object.keys(map).length === 0) {
|
|
37438
|
-
if ((0,
|
|
37618
|
+
if ((0, import_node_fs62.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs62.unlinkSync)(GUARD_ITER_FILE);
|
|
37439
37619
|
} else {
|
|
37440
|
-
(0,
|
|
37441
|
-
(0,
|
|
37620
|
+
(0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37621
|
+
(0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37442
37622
|
}
|
|
37443
37623
|
} catch {
|
|
37444
37624
|
}
|
|
@@ -37508,7 +37688,7 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
37508
37688
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
37509
37689
|
const analyzable = filterAnalyzable(files);
|
|
37510
37690
|
const securityFiles = filterSecurity(files);
|
|
37511
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
37691
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs62.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
37512
37692
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
37513
37693
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
37514
37694
|
const requestBody = {
|
|
@@ -37925,6 +38105,13 @@ async function runGuard(opts, globals) {
|
|
|
37925
38105
|
const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
|
|
37926
38106
|
mergeFormalFindings(response, formalOutcome, files);
|
|
37927
38107
|
decision = response.gate_decision ?? "(unrecognised)";
|
|
38108
|
+
if (formalOutcome) {
|
|
38109
|
+
await postPhaseRecord(formalOutcome, {
|
|
38110
|
+
moment: "push",
|
|
38111
|
+
parentRunId: typeof response.run_id === "string" ? response.run_id : null,
|
|
38112
|
+
pushedFiles: files
|
|
38113
|
+
}, { serviceUrl: urlResult.data, token: tokenResult.data.token, deadlineAt: guardRecordDeadline(hookStartedAt) });
|
|
38114
|
+
}
|
|
37928
38115
|
if (!result.ok) {
|
|
37929
38116
|
const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
|
|
37930
38117
|
if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
|
|
@@ -38134,7 +38321,7 @@ function registerIgnoreCommand(program2) {
|
|
|
38134
38321
|
|
|
38135
38322
|
// src/commands/waive.ts
|
|
38136
38323
|
var import_node_crypto20 = require("node:crypto");
|
|
38137
|
-
var
|
|
38324
|
+
var import_node_fs63 = require("node:fs");
|
|
38138
38325
|
function registerWaiveCommand(program2) {
|
|
38139
38326
|
program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
|
|
38140
38327
|
const globals = program2.opts();
|
|
@@ -38163,7 +38350,7 @@ function registerWaiveCommand(program2) {
|
|
|
38163
38350
|
if (opts.file) {
|
|
38164
38351
|
body2.file = opts.file;
|
|
38165
38352
|
try {
|
|
38166
|
-
body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0,
|
|
38353
|
+
body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs63.readFileSync)(opts.file)).digest("hex");
|
|
38167
38354
|
} catch {
|
|
38168
38355
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
38169
38356
|
process.exit(1);
|
|
@@ -38188,10 +38375,10 @@ function registerWaiveCommand(program2) {
|
|
|
38188
38375
|
}
|
|
38189
38376
|
|
|
38190
38377
|
// src/commands/init.ts
|
|
38191
|
-
var
|
|
38378
|
+
var import_node_fs68 = require("node:fs");
|
|
38192
38379
|
var import_promises20 = require("node:fs/promises");
|
|
38193
38380
|
var import_yaml6 = __toESM2(require_dist());
|
|
38194
|
-
var
|
|
38381
|
+
var import_node_path53 = require("node:path");
|
|
38195
38382
|
var import_node_os11 = require("node:os");
|
|
38196
38383
|
var import_node_child_process19 = require("node:child_process");
|
|
38197
38384
|
|
|
@@ -38271,7 +38458,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
38271
38458
|
}
|
|
38272
38459
|
|
|
38273
38460
|
// src/commands/doctor.ts
|
|
38274
|
-
var
|
|
38461
|
+
var import_node_fs64 = require("node:fs");
|
|
38275
38462
|
|
|
38276
38463
|
// src/lib/prereqs.ts
|
|
38277
38464
|
var import_node_child_process16 = require("node:child_process");
|
|
@@ -38479,11 +38666,11 @@ async function buildReport() {
|
|
|
38479
38666
|
const hooks = wiring.status;
|
|
38480
38667
|
const provenance = cliProvenance();
|
|
38481
38668
|
const telemetry = await checkTelemetry();
|
|
38482
|
-
const hasConfig = (0,
|
|
38669
|
+
const hasConfig = (0, import_node_fs64.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
38483
38670
|
const artifacts = {
|
|
38484
|
-
standard: (0,
|
|
38671
|
+
standard: (0, import_node_fs64.existsSync)(projectPath(STANDARD_FILE)),
|
|
38485
38672
|
analysisConfig: hasConfig,
|
|
38486
|
-
verityMd: (0,
|
|
38673
|
+
verityMd: (0, import_node_fs64.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
38487
38674
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
38488
38675
|
};
|
|
38489
38676
|
const next = [];
|
|
@@ -38642,8 +38829,8 @@ function registerDoctorCommand(program2) {
|
|
|
38642
38829
|
}
|
|
38643
38830
|
|
|
38644
38831
|
// src/commands/migrate.ts
|
|
38645
|
-
var
|
|
38646
|
-
var
|
|
38832
|
+
var import_node_fs65 = require("node:fs");
|
|
38833
|
+
var import_node_path50 = require("node:path");
|
|
38647
38834
|
var import_node_child_process17 = require("node:child_process");
|
|
38648
38835
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
38649
38836
|
function defaultNpmRemover(pkg) {
|
|
@@ -38680,12 +38867,12 @@ async function runMigration(opts = {}) {
|
|
|
38680
38867
|
return { actions, migrated: actions.length > 0 };
|
|
38681
38868
|
}
|
|
38682
38869
|
function migrateProjectDir(root, actions) {
|
|
38683
|
-
const gateDir = (0,
|
|
38684
|
-
const verityDir = (0,
|
|
38685
|
-
if ((0,
|
|
38870
|
+
const gateDir = (0, import_node_path50.join)(root, ".gate");
|
|
38871
|
+
const verityDir = (0, import_node_path50.join)(root, ".verity");
|
|
38872
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) {
|
|
38686
38873
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
38687
38874
|
}
|
|
38688
|
-
if ((0,
|
|
38875
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
|
|
38689
38876
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
38690
38877
|
}
|
|
38691
38878
|
return false;
|
|
@@ -38706,13 +38893,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
38706
38893
|
}
|
|
38707
38894
|
}
|
|
38708
38895
|
if (moved) {
|
|
38709
|
-
if ((0,
|
|
38896
|
+
if ((0, import_node_fs65.existsSync)(gateDir)) {
|
|
38710
38897
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
38711
38898
|
if (carried > 0) {
|
|
38712
38899
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
38713
38900
|
}
|
|
38714
38901
|
try {
|
|
38715
|
-
(0,
|
|
38902
|
+
(0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
|
|
38716
38903
|
} catch {
|
|
38717
38904
|
}
|
|
38718
38905
|
}
|
|
@@ -38728,18 +38915,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
38728
38915
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
38729
38916
|
}
|
|
38730
38917
|
try {
|
|
38731
|
-
(0,
|
|
38918
|
+
(0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
|
|
38732
38919
|
} catch {
|
|
38733
38920
|
}
|
|
38734
38921
|
return carried > 0;
|
|
38735
38922
|
}
|
|
38736
38923
|
function migrateGlobalCredentials(home, actions) {
|
|
38737
38924
|
if (!home) return;
|
|
38738
|
-
const gateCreds = (0,
|
|
38739
|
-
const verityCreds = (0,
|
|
38740
|
-
if (!(0,
|
|
38741
|
-
if (!(0,
|
|
38742
|
-
(0,
|
|
38925
|
+
const gateCreds = (0, import_node_path50.join)(home, ".gate", "credentials");
|
|
38926
|
+
const verityCreds = (0, import_node_path50.join)(home, ".verity", "credentials");
|
|
38927
|
+
if (!(0, import_node_fs65.existsSync)(gateCreds)) return;
|
|
38928
|
+
if (!(0, import_node_fs65.existsSync)(verityCreds)) {
|
|
38929
|
+
(0, import_node_fs65.mkdirSync)((0, import_node_path50.join)(home, ".verity"), { recursive: true });
|
|
38743
38930
|
moveFile(gateCreds, verityCreds);
|
|
38744
38931
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
38745
38932
|
return;
|
|
@@ -38761,8 +38948,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
38761
38948
|
}
|
|
38762
38949
|
}
|
|
38763
38950
|
async function migrateClaudeMd(root, actions) {
|
|
38764
|
-
const claudeMd = (0,
|
|
38765
|
-
const hadLegacyBlock = (0,
|
|
38951
|
+
const claudeMd = (0, import_node_path50.join)(root, "CLAUDE.md");
|
|
38952
|
+
const hadLegacyBlock = (0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
38766
38953
|
if (!hadLegacyBlock) return;
|
|
38767
38954
|
try {
|
|
38768
38955
|
await ensureClaudeMdPointer(root);
|
|
@@ -38772,9 +38959,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
38772
38959
|
}
|
|
38773
38960
|
}
|
|
38774
38961
|
function migrateStandardFile(root, actions) {
|
|
38775
|
-
const gateMd = (0,
|
|
38776
|
-
const verityMd = (0,
|
|
38777
|
-
if (!(0,
|
|
38962
|
+
const gateMd = (0, import_node_path50.join)(root, "GATE.md");
|
|
38963
|
+
const verityMd = (0, import_node_path50.join)(root, "VERITY.md");
|
|
38964
|
+
if (!(0, import_node_fs65.existsSync)(gateMd) || (0, import_node_fs65.existsSync)(verityMd)) return;
|
|
38778
38965
|
let moved = false;
|
|
38779
38966
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
38780
38967
|
try {
|
|
@@ -38786,12 +38973,12 @@ function migrateStandardFile(root, actions) {
|
|
|
38786
38973
|
if (!moved) moveFile(gateMd, verityMd);
|
|
38787
38974
|
const content = readFileSyncSafe(verityMd);
|
|
38788
38975
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
38789
|
-
if (refreshed !== content) (0,
|
|
38976
|
+
if (refreshed !== content) (0, import_node_fs65.writeFileSync)(verityMd, refreshed);
|
|
38790
38977
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
38791
38978
|
}
|
|
38792
38979
|
async function migrateTelemetryHeaders(root, actions) {
|
|
38793
|
-
const file = (0,
|
|
38794
|
-
if (!(0,
|
|
38980
|
+
const file = (0, import_node_path50.join)(root, ".claude", "settings.local.json");
|
|
38981
|
+
if (!(0, import_node_fs65.existsSync)(file)) return;
|
|
38795
38982
|
let settings;
|
|
38796
38983
|
try {
|
|
38797
38984
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -38839,14 +39026,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
38839
39026
|
}
|
|
38840
39027
|
if (toAppend.length > 0) {
|
|
38841
39028
|
const sep6 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
38842
|
-
(0,
|
|
39029
|
+
(0, import_node_fs65.writeFileSync)(verityCreds, verityContent + sep6 + toAppend.join("\n") + "\n");
|
|
38843
39030
|
}
|
|
38844
|
-
(0,
|
|
39031
|
+
(0, import_node_fs65.rmSync)(gateCreds, { force: true });
|
|
38845
39032
|
return toAppend.length;
|
|
38846
39033
|
}
|
|
38847
39034
|
function readFileSyncSafe(path) {
|
|
38848
39035
|
try {
|
|
38849
|
-
return (0,
|
|
39036
|
+
return (0, import_node_fs65.readFileSync)(path, "utf-8");
|
|
38850
39037
|
} catch {
|
|
38851
39038
|
return "";
|
|
38852
39039
|
}
|
|
@@ -38861,35 +39048,35 @@ function hasStagedChanges(root) {
|
|
|
38861
39048
|
}
|
|
38862
39049
|
function moveDir(from, to) {
|
|
38863
39050
|
try {
|
|
38864
|
-
(0,
|
|
39051
|
+
(0, import_node_fs65.renameSync)(from, to);
|
|
38865
39052
|
} catch (err2) {
|
|
38866
39053
|
if (err2.code !== "EXDEV") throw err2;
|
|
38867
|
-
(0,
|
|
38868
|
-
(0,
|
|
39054
|
+
(0, import_node_fs65.cpSync)(from, to, { recursive: true });
|
|
39055
|
+
(0, import_node_fs65.rmSync)(from, { recursive: true, force: true });
|
|
38869
39056
|
}
|
|
38870
39057
|
}
|
|
38871
39058
|
function moveFile(from, to) {
|
|
38872
39059
|
try {
|
|
38873
|
-
(0,
|
|
39060
|
+
(0, import_node_fs65.renameSync)(from, to);
|
|
38874
39061
|
} catch (err2) {
|
|
38875
39062
|
if (err2.code !== "EXDEV") throw err2;
|
|
38876
|
-
(0,
|
|
38877
|
-
(0,
|
|
39063
|
+
(0, import_node_fs65.cpSync)(from, to);
|
|
39064
|
+
(0, import_node_fs65.rmSync)(from, { force: true });
|
|
38878
39065
|
}
|
|
38879
39066
|
}
|
|
38880
39067
|
function carryLegacyContents(gateDir, verityDir) {
|
|
38881
39068
|
let copied = 0;
|
|
38882
39069
|
const walk2 = (relDir) => {
|
|
38883
|
-
const srcDir = (0,
|
|
38884
|
-
for (const entry of (0,
|
|
38885
|
-
const rel = relDir ? (0,
|
|
38886
|
-
const src = (0,
|
|
38887
|
-
const dest = (0,
|
|
38888
|
-
if ((0,
|
|
39070
|
+
const srcDir = (0, import_node_path50.join)(gateDir, relDir);
|
|
39071
|
+
for (const entry of (0, import_node_fs65.readdirSync)(srcDir)) {
|
|
39072
|
+
const rel = relDir ? (0, import_node_path50.join)(relDir, entry) : entry;
|
|
39073
|
+
const src = (0, import_node_path50.join)(gateDir, rel);
|
|
39074
|
+
const dest = (0, import_node_path50.join)(verityDir, rel);
|
|
39075
|
+
if ((0, import_node_fs65.statSync)(src).isDirectory()) {
|
|
38889
39076
|
walk2(rel);
|
|
38890
|
-
} else if (!(0,
|
|
38891
|
-
(0,
|
|
38892
|
-
(0,
|
|
39077
|
+
} else if (!(0, import_node_fs65.existsSync)(dest)) {
|
|
39078
|
+
(0, import_node_fs65.mkdirSync)((0, import_node_path50.dirname)(dest), { recursive: true });
|
|
39079
|
+
(0, import_node_fs65.cpSync)(src, dest);
|
|
38893
39080
|
copied++;
|
|
38894
39081
|
}
|
|
38895
39082
|
}
|
|
@@ -38898,22 +39085,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
38898
39085
|
return copied;
|
|
38899
39086
|
}
|
|
38900
39087
|
async function needsMigration(root = repoRoot()) {
|
|
38901
|
-
const gateDir = (0,
|
|
38902
|
-
const verityDir = (0,
|
|
38903
|
-
if ((0,
|
|
38904
|
-
if ((0,
|
|
38905
|
-
if ((0,
|
|
39088
|
+
const gateDir = (0, import_node_path50.join)(root, ".gate");
|
|
39089
|
+
const verityDir = (0, import_node_path50.join)(root, ".verity");
|
|
39090
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) return true;
|
|
39091
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
|
|
39092
|
+
if ((0, import_node_fs65.existsSync)((0, import_node_path50.join)(gateDir, "credentials")) && !(0, import_node_fs65.existsSync)((0, import_node_path50.join)(verityDir, "credentials"))) {
|
|
38906
39093
|
return true;
|
|
38907
39094
|
}
|
|
38908
|
-
if ((0,
|
|
39095
|
+
if ((0, import_node_fs65.existsSync)((0, import_node_path50.join)(gateDir, "memory")) && !(0, import_node_fs65.existsSync)((0, import_node_path50.join)(verityDir, "memory"))) {
|
|
38909
39096
|
return true;
|
|
38910
39097
|
}
|
|
38911
39098
|
}
|
|
38912
|
-
const claudeMd = (0,
|
|
38913
|
-
if ((0,
|
|
39099
|
+
const claudeMd = (0, import_node_path50.join)(root, "CLAUDE.md");
|
|
39100
|
+
if ((0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
38914
39101
|
return true;
|
|
38915
39102
|
}
|
|
38916
|
-
if ((0,
|
|
39103
|
+
if ((0, import_node_fs65.existsSync)((0, import_node_path50.join)(root, "GATE.md")) && !(0, import_node_fs65.existsSync)((0, import_node_path50.join)(root, "VERITY.md"))) {
|
|
38917
39104
|
return true;
|
|
38918
39105
|
}
|
|
38919
39106
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -39194,11 +39381,11 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
39194
39381
|
}
|
|
39195
39382
|
|
|
39196
39383
|
// src/lib/prove/lean-install.ts
|
|
39197
|
-
var
|
|
39384
|
+
var import_node_fs66 = require("node:fs");
|
|
39198
39385
|
var import_node_crypto21 = require("node:crypto");
|
|
39199
39386
|
var import_node_child_process18 = require("node:child_process");
|
|
39200
39387
|
var import_node_os10 = require("node:os");
|
|
39201
|
-
var
|
|
39388
|
+
var import_node_path51 = require("node:path");
|
|
39202
39389
|
var import_promises18 = require("node:stream/promises");
|
|
39203
39390
|
var import_node_stream = require("node:stream");
|
|
39204
39391
|
var RELEASES = "https://releases.lean-lang.org/lean4";
|
|
@@ -39209,10 +39396,10 @@ function freeBytes(dir) {
|
|
|
39209
39396
|
let d = dir;
|
|
39210
39397
|
for (let i2 = 0; i2 < 64; i2++) {
|
|
39211
39398
|
try {
|
|
39212
|
-
const st = (0,
|
|
39399
|
+
const st = (0, import_node_fs66.statfsSync)(d);
|
|
39213
39400
|
return Number(st.bavail) * Number(st.bsize);
|
|
39214
39401
|
} catch {
|
|
39215
|
-
const up = (0,
|
|
39402
|
+
const up = (0, import_node_path51.join)(d, "..");
|
|
39216
39403
|
if (up === d) return null;
|
|
39217
39404
|
d = up;
|
|
39218
39405
|
}
|
|
@@ -39234,7 +39421,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
|
|
|
39234
39421
|
function sha256File(path) {
|
|
39235
39422
|
return new Promise((resolve9, reject) => {
|
|
39236
39423
|
const hash = (0, import_node_crypto21.createHash)("sha256");
|
|
39237
|
-
(0,
|
|
39424
|
+
(0, import_node_fs66.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
|
|
39238
39425
|
});
|
|
39239
39426
|
}
|
|
39240
39427
|
async function verifyDownload(zip, asset, version = pinnedVersion()) {
|
|
@@ -39254,7 +39441,7 @@ function leanAssetName(version = pinnedVersion()) {
|
|
|
39254
39441
|
return suffix ? `lean-${v}-${suffix}.zip` : null;
|
|
39255
39442
|
}
|
|
39256
39443
|
function pinnedVersionDir(env = process.env) {
|
|
39257
|
-
return (0,
|
|
39444
|
+
return (0, import_node_path51.join)(verityLeanHome(env), pinnedVersion());
|
|
39258
39445
|
}
|
|
39259
39446
|
function lakeBinary() {
|
|
39260
39447
|
return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
|
|
@@ -39265,12 +39452,12 @@ function unzip(zip, dest) {
|
|
|
39265
39452
|
for (const [cmd, args2] of attempts) {
|
|
39266
39453
|
try {
|
|
39267
39454
|
(0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
|
|
39268
|
-
if ((0,
|
|
39455
|
+
if ((0, import_node_fs66.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
|
|
39269
39456
|
errors.push(`${cmd}: produced nothing`);
|
|
39270
39457
|
} catch (err2) {
|
|
39271
39458
|
errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
|
|
39272
39459
|
try {
|
|
39273
|
-
for (const e of (0,
|
|
39460
|
+
for (const e of (0, import_node_fs66.readdirSync)(dest)) (0, import_node_fs66.rmSync)((0, import_node_path51.join)(dest, e), { recursive: true, force: true });
|
|
39274
39461
|
} catch {
|
|
39275
39462
|
}
|
|
39276
39463
|
}
|
|
@@ -39296,7 +39483,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
|
|
|
39296
39483
|
seen += chunk.length;
|
|
39297
39484
|
onProgress(seen, total);
|
|
39298
39485
|
});
|
|
39299
|
-
await (0, import_promises18.pipeline)(stream, (0,
|
|
39486
|
+
await (0, import_promises18.pipeline)(stream, (0, import_node_fs66.createWriteStream)(dest), { signal: ctrl.signal });
|
|
39300
39487
|
} catch (err2) {
|
|
39301
39488
|
if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
|
|
39302
39489
|
throw err2;
|
|
@@ -39346,10 +39533,10 @@ async function installLean(opts = {}) {
|
|
|
39346
39533
|
const gb = (n) => (n / 1024 ** 3).toFixed(1);
|
|
39347
39534
|
return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
|
|
39348
39535
|
}
|
|
39349
|
-
const tmp = (0,
|
|
39350
|
-
(0,
|
|
39351
|
-
(0,
|
|
39352
|
-
const zip = (0,
|
|
39536
|
+
const tmp = (0, import_node_path51.join)(home, ".tmp");
|
|
39537
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39538
|
+
(0, import_node_fs66.mkdirSync)(tmp, { recursive: true });
|
|
39539
|
+
const zip = (0, import_node_path51.join)(tmp, asset);
|
|
39353
39540
|
say(`downloading ${url}`);
|
|
39354
39541
|
let lastPct = -1;
|
|
39355
39542
|
try {
|
|
@@ -39362,40 +39549,40 @@ async function installLean(opts = {}) {
|
|
|
39362
39549
|
}
|
|
39363
39550
|
});
|
|
39364
39551
|
} catch (err2) {
|
|
39365
|
-
(0,
|
|
39552
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39366
39553
|
return { ok: false, error: err2.message };
|
|
39367
39554
|
}
|
|
39368
39555
|
say("verifying checksum");
|
|
39369
39556
|
const verified = await verifyDownload(zip, asset);
|
|
39370
39557
|
if (!verified.ok) {
|
|
39371
|
-
(0,
|
|
39558
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39372
39559
|
return { ok: false, error: verified.error };
|
|
39373
39560
|
}
|
|
39374
39561
|
say("unpacking (this takes a minute)");
|
|
39375
|
-
const unpack = (0,
|
|
39376
|
-
(0,
|
|
39562
|
+
const unpack = (0, import_node_path51.join)(tmp, "unpack");
|
|
39563
|
+
(0, import_node_fs66.mkdirSync)(unpack);
|
|
39377
39564
|
const unpacked = unzip(zip, unpack);
|
|
39378
39565
|
if (!unpacked.ok) {
|
|
39379
|
-
(0,
|
|
39566
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39380
39567
|
return { ok: false, error: `unpack failed: ${unpacked.error}` };
|
|
39381
39568
|
}
|
|
39382
|
-
const entries = (0,
|
|
39383
|
-
const top = entries.length === 1 && (0,
|
|
39384
|
-
if (!(0,
|
|
39385
|
-
(0,
|
|
39569
|
+
const entries = (0, import_node_fs66.readdirSync)(unpack);
|
|
39570
|
+
const top = entries.length === 1 && (0, import_node_fs66.statSync)((0, import_node_path51.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path51.join)(unpack, entries[0]) : unpack;
|
|
39571
|
+
if (!(0, import_node_fs66.existsSync)((0, import_node_path51.join)(top, "bin", lakeBinary()))) {
|
|
39572
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39386
39573
|
return { ok: false, error: "the archive did not contain bin/lake" };
|
|
39387
39574
|
}
|
|
39388
|
-
(0,
|
|
39389
|
-
(0,
|
|
39390
|
-
(0,
|
|
39391
|
-
(0,
|
|
39575
|
+
(0, import_node_fs66.rmSync)(dir, { recursive: true, force: true });
|
|
39576
|
+
(0, import_node_fs66.mkdirSync)(home, { recursive: true });
|
|
39577
|
+
(0, import_node_fs66.renameSync)(top, dir);
|
|
39578
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39392
39579
|
return { ok: true, dir };
|
|
39393
39580
|
}
|
|
39394
39581
|
|
|
39395
39582
|
// src/lib/remote-config.ts
|
|
39396
|
-
var
|
|
39583
|
+
var import_node_fs67 = require("node:fs");
|
|
39397
39584
|
var import_promises19 = require("node:fs/promises");
|
|
39398
|
-
var
|
|
39585
|
+
var import_node_path52 = require("node:path");
|
|
39399
39586
|
var import_yaml5 = __toESM2(require_dist());
|
|
39400
39587
|
var IGNORE_RIDER = "verityignore";
|
|
39401
39588
|
async function fetchRemoteSetup(opts) {
|
|
@@ -39440,7 +39627,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39440
39627
|
written.push(STANDARD_FILE);
|
|
39441
39628
|
if (rider !== null) {
|
|
39442
39629
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
39443
|
-
if (!(0,
|
|
39630
|
+
if (!(0, import_node_fs67.existsSync)(localIgnore)) {
|
|
39444
39631
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
39445
39632
|
written.push(VERITYIGNORE_FILE);
|
|
39446
39633
|
} else {
|
|
@@ -39473,7 +39660,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39473
39660
|
}
|
|
39474
39661
|
async function writeOut(relative6, body2) {
|
|
39475
39662
|
const target = projectPath(relative6);
|
|
39476
|
-
await (0, import_promises19.mkdir)((0,
|
|
39663
|
+
await (0, import_promises19.mkdir)((0, import_node_path52.dirname)(target), { recursive: true });
|
|
39477
39664
|
await (0, import_promises19.writeFile)(target, body2);
|
|
39478
39665
|
}
|
|
39479
39666
|
function describeRemote(found) {
|
|
@@ -39590,15 +39777,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
39590
39777
|
}
|
|
39591
39778
|
function resolveDataDir2() {
|
|
39592
39779
|
const candidates2 = [
|
|
39593
|
-
(0,
|
|
39780
|
+
(0, import_node_path53.join)(__dirname, "..", "data"),
|
|
39594
39781
|
// installed: node_modules/@codacy/verity-cli/data
|
|
39595
|
-
(0,
|
|
39782
|
+
(0, import_node_path53.join)(__dirname, "..", "..", "data"),
|
|
39596
39783
|
// edge case: nested resolution
|
|
39597
|
-
(0,
|
|
39784
|
+
(0, import_node_path53.join)(process.cwd(), "cli", "data")
|
|
39598
39785
|
// local dev: running from repo root
|
|
39599
39786
|
];
|
|
39600
39787
|
for (const candidate of candidates2) {
|
|
39601
|
-
if ((0,
|
|
39788
|
+
if ((0, import_node_fs68.existsSync)((0, import_node_path53.join)(candidate, "skills"))) {
|
|
39602
39789
|
return candidate;
|
|
39603
39790
|
}
|
|
39604
39791
|
}
|
|
@@ -39614,9 +39801,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
39614
39801
|
const list2 = (dir) => {
|
|
39615
39802
|
const out2 = [];
|
|
39616
39803
|
const walk2 = (d, prefix) => {
|
|
39617
|
-
for (const e of (0,
|
|
39804
|
+
for (const e of (0, import_node_fs68.readdirSync)(d, { withFileTypes: true })) {
|
|
39618
39805
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
39619
|
-
if (e.isDirectory()) walk2((0,
|
|
39806
|
+
if (e.isDirectory()) walk2((0, import_node_path53.join)(d, e.name), rel);
|
|
39620
39807
|
else if (e.isFile()) out2.push(rel);
|
|
39621
39808
|
}
|
|
39622
39809
|
};
|
|
@@ -39627,8 +39814,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
39627
39814
|
const shipped = list2(src);
|
|
39628
39815
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
39629
39816
|
for (const rel of shipped) {
|
|
39630
|
-
const a = await (0, import_promises20.readFile)((0,
|
|
39631
|
-
const b = await (0, import_promises20.readFile)((0,
|
|
39817
|
+
const a = await (0, import_promises20.readFile)((0, import_node_path53.join)(src, rel), "utf-8");
|
|
39818
|
+
const b = await (0, import_promises20.readFile)((0, import_node_path53.join)(dest, rel), "utf-8");
|
|
39632
39819
|
if (a !== b) return false;
|
|
39633
39820
|
}
|
|
39634
39821
|
return true;
|
|
@@ -39831,7 +40018,7 @@ async function synthesizeLocally(opts) {
|
|
|
39831
40018
|
async function healStaleAnalysisConfig(globals) {
|
|
39832
40019
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
39833
40020
|
const standardPath = projectPath(STANDARD_FILE);
|
|
39834
|
-
if (!(0,
|
|
40021
|
+
if (!(0, import_node_fs68.existsSync)(configPath) || !(0, import_node_fs68.existsSync)(standardPath)) return;
|
|
39835
40022
|
const validation = validatePatternIds();
|
|
39836
40023
|
if (validation.status !== "invalid") return;
|
|
39837
40024
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -39928,17 +40115,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
39928
40115
|
async function installSkills(force, step) {
|
|
39929
40116
|
step("Installing skills");
|
|
39930
40117
|
const dataDir = resolveDataDir2();
|
|
39931
|
-
const skillsSource = (0,
|
|
40118
|
+
const skillsSource = (0, import_node_path53.join)(dataDir, "skills");
|
|
39932
40119
|
const skillsDest = ".claude/skills";
|
|
39933
40120
|
let skillsInstalled = 0;
|
|
39934
40121
|
for (const skill of SKILLS) {
|
|
39935
|
-
const src = (0,
|
|
39936
|
-
const dest = (0,
|
|
39937
|
-
if (!(0,
|
|
40122
|
+
const src = (0, import_node_path53.join)(skillsSource, skill);
|
|
40123
|
+
const dest = (0, import_node_path53.join)(skillsDest, skill);
|
|
40124
|
+
if (!(0, import_node_fs68.existsSync)(src)) {
|
|
39938
40125
|
printWarn(` Skill data not found: ${skill}`);
|
|
39939
40126
|
continue;
|
|
39940
40127
|
}
|
|
39941
|
-
if ((0,
|
|
40128
|
+
if ((0, import_node_fs68.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
39942
40129
|
skillsInstalled++;
|
|
39943
40130
|
continue;
|
|
39944
40131
|
}
|
|
@@ -40087,7 +40274,7 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
|
|
|
40087
40274
|
if (!toolchain) {
|
|
40088
40275
|
const dir = pinnedVersionDir();
|
|
40089
40276
|
const home = (0, import_node_os11.homedir)();
|
|
40090
|
-
const shown = dir.startsWith(home +
|
|
40277
|
+
const shown = dir.startsWith(home + import_node_path53.sep) ? `~${dir.slice(home.length)}` : dir;
|
|
40091
40278
|
console.log("");
|
|
40092
40279
|
console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
|
|
40093
40280
|
}
|
|
@@ -40146,7 +40333,7 @@ function registerInitCommand(program2) {
|
|
|
40146
40333
|
const staleMarker = clearStalePluginMarker();
|
|
40147
40334
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
40148
40335
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
40149
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
40336
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs68.existsSync)(m));
|
|
40150
40337
|
if (!isProject) {
|
|
40151
40338
|
printError("No project detected in the current directory.");
|
|
40152
40339
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -40249,7 +40436,7 @@ function registerInitCommand(program2) {
|
|
|
40249
40436
|
untrackMemory: opts.untrackMemory === true,
|
|
40250
40437
|
untrackState: opts.untrackState === true
|
|
40251
40438
|
});
|
|
40252
|
-
const globalVerityDir = (0,
|
|
40439
|
+
const globalVerityDir = (0, import_node_path53.join)(process.env.HOME ?? "", ".verity");
|
|
40253
40440
|
await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
|
|
40254
40441
|
console.log("");
|
|
40255
40442
|
step("Wiring Claude Code hooks");
|
|
@@ -40324,7 +40511,7 @@ function registerInitCommand(program2) {
|
|
|
40324
40511
|
}
|
|
40325
40512
|
step("Your project's Standard");
|
|
40326
40513
|
let haveStandard = false;
|
|
40327
|
-
if ((0,
|
|
40514
|
+
if ((0, import_node_fs68.existsSync)(projectPath(STANDARD_FILE))) {
|
|
40328
40515
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
40329
40516
|
haveStandard = true;
|
|
40330
40517
|
} else {
|
|
@@ -40354,7 +40541,7 @@ function registerInitCommand(program2) {
|
|
|
40354
40541
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
40355
40542
|
init: {
|
|
40356
40543
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40357
|
-
cli_version: true ? "0.34.1-experimental.
|
|
40544
|
+
cli_version: true ? "0.34.1-experimental.c910405" : "dev"
|
|
40358
40545
|
}
|
|
40359
40546
|
});
|
|
40360
40547
|
} catch (err2) {
|
|
@@ -40404,8 +40591,8 @@ function registerInitCommand(program2) {
|
|
|
40404
40591
|
}
|
|
40405
40592
|
|
|
40406
40593
|
// src/commands/uninstall.ts
|
|
40407
|
-
var
|
|
40408
|
-
var
|
|
40594
|
+
var import_node_fs69 = require("node:fs");
|
|
40595
|
+
var import_node_path54 = require("node:path");
|
|
40409
40596
|
function registerUninstallCommand(program2) {
|
|
40410
40597
|
program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
|
|
40411
40598
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -40414,11 +40601,11 @@ function registerUninstallCommand(program2) {
|
|
|
40414
40601
|
const actions = [];
|
|
40415
40602
|
const skillsRoot = projectPath(".claude/skills");
|
|
40416
40603
|
for (const name2 of PROJECT_SKILL_NAMES) {
|
|
40417
|
-
const dir = (0,
|
|
40418
|
-
if ((0,
|
|
40604
|
+
const dir = (0, import_node_path54.join)(skillsRoot, name2);
|
|
40605
|
+
if ((0, import_node_fs69.existsSync)(dir)) {
|
|
40419
40606
|
actions.push({
|
|
40420
40607
|
label: `Remove .claude/skills/${name2}/`,
|
|
40421
|
-
apply: () => (0,
|
|
40608
|
+
apply: () => (0, import_node_fs69.rmSync)(dir, { recursive: true, force: true })
|
|
40422
40609
|
});
|
|
40423
40610
|
}
|
|
40424
40611
|
}
|
|
@@ -40432,24 +40619,24 @@ function registerUninstallCommand(program2) {
|
|
|
40432
40619
|
});
|
|
40433
40620
|
}
|
|
40434
40621
|
const verityDir = projectPath(VERITY_DIR);
|
|
40435
|
-
if ((0,
|
|
40622
|
+
if ((0, import_node_fs69.existsSync)(verityDir)) {
|
|
40436
40623
|
actions.push({
|
|
40437
40624
|
label: `Remove ${VERITY_DIR}/`,
|
|
40438
|
-
apply: () => (0,
|
|
40625
|
+
apply: () => (0, import_node_fs69.rmSync)(verityDir, { recursive: true, force: true })
|
|
40439
40626
|
});
|
|
40440
40627
|
}
|
|
40441
40628
|
if (!keepVerityMd) {
|
|
40442
40629
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
40443
|
-
if ((0,
|
|
40630
|
+
if ((0, import_node_fs69.existsSync)(verityMd)) {
|
|
40444
40631
|
actions.push({
|
|
40445
40632
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
40446
|
-
apply: () => (0,
|
|
40633
|
+
apply: () => (0, import_node_fs69.rmSync)(verityMd, { force: true })
|
|
40447
40634
|
});
|
|
40448
40635
|
}
|
|
40449
40636
|
}
|
|
40450
40637
|
const cleanupEmptyDir = (path) => {
|
|
40451
|
-
if ((0,
|
|
40452
|
-
(0,
|
|
40638
|
+
if ((0, import_node_fs69.existsSync)(path) && (0, import_node_fs69.statSync)(path).isDirectory() && (0, import_node_fs69.readdirSync)(path).length === 0) {
|
|
40639
|
+
(0, import_node_fs69.rmdirSync)(path);
|
|
40453
40640
|
}
|
|
40454
40641
|
};
|
|
40455
40642
|
actions.push({
|
|
@@ -40460,11 +40647,11 @@ function registerUninstallCommand(program2) {
|
|
|
40460
40647
|
}
|
|
40461
40648
|
});
|
|
40462
40649
|
const home = process.env.HOME ?? "";
|
|
40463
|
-
const globalVerityDir = (0,
|
|
40464
|
-
if (purgeGlobal && (0,
|
|
40650
|
+
const globalVerityDir = (0, import_node_path54.join)(home, ".verity");
|
|
40651
|
+
if (purgeGlobal && (0, import_node_fs69.existsSync)(globalVerityDir)) {
|
|
40465
40652
|
actions.push({
|
|
40466
40653
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
40467
|
-
apply: () => (0,
|
|
40654
|
+
apply: () => (0, import_node_fs69.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
40468
40655
|
});
|
|
40469
40656
|
}
|
|
40470
40657
|
if (actions.length === 0) {
|
|
@@ -40658,8 +40845,8 @@ function registerTaskCommands(program2) {
|
|
|
40658
40845
|
}
|
|
40659
40846
|
|
|
40660
40847
|
// src/commands/reset.ts
|
|
40661
|
-
var
|
|
40662
|
-
var
|
|
40848
|
+
var import_node_fs70 = require("node:fs");
|
|
40849
|
+
var import_node_path55 = require("node:path");
|
|
40663
40850
|
function registerResetCommand(program2) {
|
|
40664
40851
|
program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
|
|
40665
40852
|
const globals = program2.opts();
|
|
@@ -40696,11 +40883,11 @@ function registerResetCommand(program2) {
|
|
|
40696
40883
|
}
|
|
40697
40884
|
const cacheDir = projectPath(CACHE_DIR);
|
|
40698
40885
|
let purged = 0;
|
|
40699
|
-
if ((0,
|
|
40700
|
-
for (const entry of (0,
|
|
40886
|
+
if ((0, import_node_fs70.existsSync)(cacheDir)) {
|
|
40887
|
+
for (const entry of (0, import_node_fs70.readdirSync)(cacheDir)) {
|
|
40701
40888
|
if (entry.startsWith("pending-")) {
|
|
40702
40889
|
try {
|
|
40703
|
-
(0,
|
|
40890
|
+
(0, import_node_fs70.unlinkSync)((0, import_node_path55.join)(cacheDir, entry));
|
|
40704
40891
|
purged++;
|
|
40705
40892
|
} catch {
|
|
40706
40893
|
}
|
|
@@ -40715,19 +40902,19 @@ function registerResetCommand(program2) {
|
|
|
40715
40902
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
40716
40903
|
];
|
|
40717
40904
|
for (const file of filesToClear) {
|
|
40718
|
-
if ((0,
|
|
40905
|
+
if ((0, import_node_fs70.existsSync)(file)) {
|
|
40719
40906
|
try {
|
|
40720
|
-
(0,
|
|
40907
|
+
(0, import_node_fs70.writeFileSync)(file, "");
|
|
40721
40908
|
} catch {
|
|
40722
40909
|
}
|
|
40723
40910
|
}
|
|
40724
40911
|
}
|
|
40725
40912
|
if (opts.all) {
|
|
40726
40913
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
40727
|
-
if ((0,
|
|
40728
|
-
for (const entry of (0,
|
|
40914
|
+
if ((0, import_node_fs70.existsSync)(logsDir)) {
|
|
40915
|
+
for (const entry of (0, import_node_fs70.readdirSync)(logsDir)) {
|
|
40729
40916
|
try {
|
|
40730
|
-
(0,
|
|
40917
|
+
(0, import_node_fs70.unlinkSync)((0, import_node_path55.join)(logsDir, entry));
|
|
40731
40918
|
} catch {
|
|
40732
40919
|
}
|
|
40733
40920
|
}
|
|
@@ -40739,7 +40926,7 @@ function registerResetCommand(program2) {
|
|
|
40739
40926
|
}
|
|
40740
40927
|
|
|
40741
40928
|
// src/commands/reflect.ts
|
|
40742
|
-
var
|
|
40929
|
+
var import_node_fs71 = require("node:fs");
|
|
40743
40930
|
|
|
40744
40931
|
// src/lib/reflection-globs.ts
|
|
40745
40932
|
var MAX_GLOBS = 6;
|
|
@@ -40777,7 +40964,7 @@ async function writeNodeToDisk(args2) {
|
|
|
40777
40964
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
40778
40965
|
);
|
|
40779
40966
|
if (written === 0) return false;
|
|
40780
|
-
return (0,
|
|
40967
|
+
return (0, import_node_fs71.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
|
|
40781
40968
|
} catch {
|
|
40782
40969
|
return false;
|
|
40783
40970
|
}
|
|
@@ -40853,7 +41040,7 @@ function registerReflectCommand(program2) {
|
|
|
40853
41040
|
const userInput = input.text;
|
|
40854
41041
|
if (userInput) {
|
|
40855
41042
|
const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
|
|
40856
|
-
const
|
|
41043
|
+
const kind2 = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
|
|
40857
41044
|
const confirmed = opts.confirmed === true;
|
|
40858
41045
|
const source2 = confirmed ? "user" : "agent";
|
|
40859
41046
|
const explicitGlobs = Array.isArray(opts.fileGlobs) ? opts.fileGlobs.map((g) => g.trim()).filter(Boolean) : [];
|
|
@@ -40865,7 +41052,7 @@ function registerReflectCommand(program2) {
|
|
|
40865
41052
|
serviceUrl,
|
|
40866
41053
|
token,
|
|
40867
41054
|
body: {
|
|
40868
|
-
kind,
|
|
41055
|
+
kind: kind2,
|
|
40869
41056
|
title: userInput.slice(0, 200),
|
|
40870
41057
|
body: userInput,
|
|
40871
41058
|
domains: [],
|
|
@@ -41214,9 +41401,9 @@ function registerRunCommand(program2) {
|
|
|
41214
41401
|
}
|
|
41215
41402
|
|
|
41216
41403
|
// src/commands/telemetry.ts
|
|
41217
|
-
var
|
|
41404
|
+
var import_node_fs72 = require("node:fs");
|
|
41218
41405
|
async function recordTelemetryChoice(choice) {
|
|
41219
|
-
if (!(0,
|
|
41406
|
+
if (!(0, import_node_fs72.existsSync)(projectPath(SETUP_STATE_FILE))) return;
|
|
41220
41407
|
try {
|
|
41221
41408
|
if ((await readSetupState())?.telemetry === choice) return;
|
|
41222
41409
|
await writeSetupState({ telemetry: choice });
|
|
@@ -41293,8 +41480,8 @@ function registerTelemetryCommands(program2) {
|
|
|
41293
41480
|
}
|
|
41294
41481
|
|
|
41295
41482
|
// src/commands/prove.ts
|
|
41296
|
-
var
|
|
41297
|
-
var
|
|
41483
|
+
var import_node_fs73 = require("node:fs");
|
|
41484
|
+
var import_node_path56 = require("node:path");
|
|
41298
41485
|
|
|
41299
41486
|
// src/lib/prove/hint-pool.ts
|
|
41300
41487
|
var STOP2 = /* @__PURE__ */ new Set([
|
|
@@ -41436,7 +41623,7 @@ function registerProveCommand(program2) {
|
|
|
41436
41623
|
process.exit(2);
|
|
41437
41624
|
}
|
|
41438
41625
|
const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
|
|
41439
|
-
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0,
|
|
41626
|
+
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path56.relative)(root, (0, import_node_path56.resolve)(p)) || ".") });
|
|
41440
41627
|
if (opts.hint && paths.length === 0) {
|
|
41441
41628
|
const hit = hintMatches(root, opts.hint);
|
|
41442
41629
|
if (hit.files.length > 0) {
|
|
@@ -41490,7 +41677,7 @@ function registerProveCommand(program2) {
|
|
|
41490
41677
|
});
|
|
41491
41678
|
prove.command("check [model]").description("Elaborate a model (or every model) with the local Lean toolchain and report each property").option("--timeout <ms>", "Per-model timeout in ms", "120000").option("--json", "Machine-readable output").action((model, opts) => {
|
|
41492
41679
|
const root = repoRoot();
|
|
41493
|
-
if (!(0,
|
|
41680
|
+
if (!(0, import_node_fs73.existsSync)((0, import_node_path56.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41494
41681
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41495
41682
|
process.exit(2);
|
|
41496
41683
|
}
|
|
@@ -41514,7 +41701,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41514
41701
|
const reports = [];
|
|
41515
41702
|
for (const f of files) {
|
|
41516
41703
|
const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
|
|
41517
|
-
report.file = (0,
|
|
41704
|
+
report.file = (0, import_node_path56.relative)(root, f);
|
|
41518
41705
|
reports.push(report);
|
|
41519
41706
|
try {
|
|
41520
41707
|
writeResult(root, report);
|
|
@@ -41552,7 +41739,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41552
41739
|
printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
|
|
41553
41740
|
process.exit(2);
|
|
41554
41741
|
}
|
|
41555
|
-
if (!(0,
|
|
41742
|
+
if (!(0, import_node_fs73.existsSync)((0, import_node_path56.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41556
41743
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41557
41744
|
process.exit(2);
|
|
41558
41745
|
}
|
|
@@ -41583,7 +41770,7 @@ ${report.error ?? ""}`);
|
|
|
41583
41770
|
printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
|
|
41584
41771
|
return;
|
|
41585
41772
|
}
|
|
41586
|
-
const modelSource = readRegularFileInRoot(root, (0,
|
|
41773
|
+
const modelSource = readRegularFileInRoot(root, (0, import_node_path56.relative)(root, file), 512 * 1024);
|
|
41587
41774
|
if (!opts.json) printInfo(`replaying ${targets.length} counterexample(s) of ${model} in network-less containers (${Math.min(targets.length, REPLAY_CONCURRENCY)} at a time)\u2026`);
|
|
41588
41775
|
const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
|
|
41589
41776
|
const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
|
|
@@ -41603,7 +41790,7 @@ ${report.error ?? ""}`);
|
|
|
41603
41790
|
});
|
|
41604
41791
|
prove.command("auto [files...]").description("The formal phase the pre-push guard runs: select one risky symbol among changed files, generate a model, check it, replay counterexamples (default files: the commits ahead of upstream)").option("--deadline <ms>", "Budget for the whole phase", "170000").option("--json", "Machine-readable output").action(async (paths, opts) => {
|
|
41605
41792
|
const root = repoRoot();
|
|
41606
|
-
let files = paths.map((p) => (0,
|
|
41793
|
+
let files = paths.map((p) => (0, import_node_path56.relative)(root, (0, import_node_path56.resolve)(p)));
|
|
41607
41794
|
if (files.length === 0) {
|
|
41608
41795
|
const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
|
|
41609
41796
|
const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
|
|
@@ -41613,8 +41800,10 @@ ${report.error ?? ""}`);
|
|
|
41613
41800
|
printInfo("No changed files to consider (nothing ahead of upstream). Pass paths explicitly.");
|
|
41614
41801
|
return;
|
|
41615
41802
|
}
|
|
41616
|
-
const
|
|
41803
|
+
const auth2 = await proveAuth(program2);
|
|
41804
|
+
const prep = await prepareFormalPhase(root, process.env, auth2 ?? void 0);
|
|
41617
41805
|
const outcome = prep.ok ? await runFormalPhaseWithin({ root, files, deadlineAt: Date.now() + Math.max(3e4, Number(opts.deadline) || 17e4), deps: prep.deps }).catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200))) : skippedOutcome(prep.skip, prep.detail);
|
|
41806
|
+
if (auth2) await postPhaseRecord(outcome, { moment: "on-demand", parentRunId: null, pushedFiles: [] }, auth2);
|
|
41618
41807
|
if (opts.json) {
|
|
41619
41808
|
printJson(outcome);
|
|
41620
41809
|
} else {
|
|
@@ -41675,7 +41864,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41675
41864
|
let revise;
|
|
41676
41865
|
if (opts.revise) {
|
|
41677
41866
|
const existing = resolveModelFile(root, opts.revise);
|
|
41678
|
-
const src = existing ? readRegularFileInRoot(root, (0,
|
|
41867
|
+
const src = existing ? readRegularFileInRoot(root, (0, import_node_path56.relative)(root, existing), 64 * 1024) : null;
|
|
41679
41868
|
if (!src || !src.ok || !opts.note) {
|
|
41680
41869
|
printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
|
|
41681
41870
|
process.exit(2);
|
|
@@ -41688,21 +41877,22 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41688
41877
|
printError("Verity library did not build");
|
|
41689
41878
|
process.exit(2);
|
|
41690
41879
|
}
|
|
41691
|
-
const deps =
|
|
41880
|
+
const deps = await onDemandDeps(root, { auth: auth2 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc });
|
|
41692
41881
|
if (!opts.json) printInfo(`asking the Verity service for a model of ${symbol || `${file}:${opts.lines}`} \u2026`);
|
|
41693
41882
|
const out2 = await generateAndCheck(root, { file, symbol: symbol || `${file}:${opts.lines}`, lines, hint: opts.hint, revise }, { deps, maxRounds: 3 });
|
|
41694
41883
|
if (!out2.ok) {
|
|
41695
41884
|
if (opts.json) printJson(out2);
|
|
41696
|
-
else printError(`${out2.error} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""}) \u2014 write the model by hand (Models/README.md) or narrow the target`);
|
|
41885
|
+
else printError(out2.rounds === 0 ? out2.error : `${out2.error} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""}) \u2014 write the model by hand (Models/README.md) or narrow the target`);
|
|
41697
41886
|
process.exit(2);
|
|
41698
41887
|
}
|
|
41888
|
+
if (out2.warning && !opts.json) printWarn(out2.warning);
|
|
41699
41889
|
try {
|
|
41700
41890
|
writeResult(root, out2.report);
|
|
41701
41891
|
} catch (err2) {
|
|
41702
41892
|
if (!(err2 instanceof SafeWriteError)) throw err2;
|
|
41703
41893
|
}
|
|
41704
41894
|
if (opts.json) {
|
|
41705
|
-
printJson({ name: out2.name, file: out2.file, rounds: out2.rounds, cost_usd: out2.costUsd, report: { ...out2.report, passes: reportPasses(out2.report), summary: summarize(out2.report) } });
|
|
41895
|
+
printJson({ name: out2.name, file: out2.file, rounds: out2.rounds, cost_usd: out2.costUsd, ...out2.warning ? { warning: out2.warning } : {}, report: { ...out2.report, passes: reportPasses(out2.report), summary: summarize(out2.report) } });
|
|
41706
41896
|
return;
|
|
41707
41897
|
}
|
|
41708
41898
|
printInfo(`wrote ${out2.file} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""})`);
|
|
@@ -41714,8 +41904,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41714
41904
|
});
|
|
41715
41905
|
prove.command("waive <file>").description("Dismiss the remembered formal finding(s) on a file for its current bytes \u2014 the accepted-risk path for a formal block").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action((file, opts) => {
|
|
41716
41906
|
const root = repoRoot();
|
|
41717
|
-
const rel0 = (0,
|
|
41718
|
-
const rel = rel0.startsWith("..") || (0,
|
|
41907
|
+
const rel0 = (0, import_node_path56.relative)(root, (0, import_node_path56.isAbsolute)(file) ? file : (0, import_node_path56.join)(root, file)).replace(/\\/g, "/");
|
|
41908
|
+
const rel = rel0.startsWith("..") || (0, import_node_path56.isAbsolute)(rel0) ? null : rel0;
|
|
41719
41909
|
if (!rel) {
|
|
41720
41910
|
printError(`${file} is not inside this repository`);
|
|
41721
41911
|
process.exit(2);
|
|
@@ -41731,8 +41921,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41731
41921
|
});
|
|
41732
41922
|
prove.command("hash <file>").description("Print the sha256 of a file, for a model header (Verity.model \u2026 sha256). Path is REPO-relative, as in the header").action((file) => {
|
|
41733
41923
|
const root = repoRoot();
|
|
41734
|
-
const rel = (0,
|
|
41735
|
-
const digest = rel.startsWith("..") || (0,
|
|
41924
|
+
const rel = (0, import_node_path56.relative)(root, (0, import_node_path56.isAbsolute)(file) ? file : (0, import_node_path56.join)(root, file));
|
|
41925
|
+
const digest = rel.startsWith("..") || (0, import_node_path56.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
|
|
41736
41926
|
if (!digest) {
|
|
41737
41927
|
printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
|
|
41738
41928
|
process.exit(2);
|
|
@@ -41766,10 +41956,10 @@ function refreshScaffold(root) {
|
|
|
41766
41956
|
}
|
|
41767
41957
|
|
|
41768
41958
|
// src/commands/lean.ts
|
|
41769
|
-
var
|
|
41959
|
+
var import_node_fs74 = require("node:fs");
|
|
41770
41960
|
var import_node_child_process20 = require("node:child_process");
|
|
41771
41961
|
var import_node_os12 = require("node:os");
|
|
41772
|
-
var
|
|
41962
|
+
var import_node_path57 = require("node:path");
|
|
41773
41963
|
function registerLeanCommand(program2) {
|
|
41774
41964
|
const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
|
|
41775
41965
|
lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
|
|
@@ -41786,7 +41976,7 @@ function registerLeanCommand(program2) {
|
|
|
41786
41976
|
const managed = pinnedVersionDir();
|
|
41787
41977
|
const matches = version ? version.includes(pin) : false;
|
|
41788
41978
|
if (opts.json) {
|
|
41789
|
-
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0,
|
|
41979
|
+
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs74.existsSync)((0, import_node_path57.join)(managed, "bin")), asset: leanAssetName() });
|
|
41790
41980
|
return;
|
|
41791
41981
|
}
|
|
41792
41982
|
printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
|
|
@@ -41804,7 +41994,7 @@ function registerLeanCommand(program2) {
|
|
|
41804
41994
|
process.exit(2);
|
|
41805
41995
|
}
|
|
41806
41996
|
const dir = pinnedVersionDir();
|
|
41807
|
-
if ((0,
|
|
41997
|
+
if ((0, import_node_fs74.existsSync)((0, import_node_path57.join)(dir, "bin", "lake")) && !opts.force) {
|
|
41808
41998
|
printInfo(`already installed at ${dir}`);
|
|
41809
41999
|
return;
|
|
41810
42000
|
}
|
|
@@ -41840,18 +42030,18 @@ function registerLeanCommand(program2) {
|
|
|
41840
42030
|
});
|
|
41841
42031
|
lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
|
|
41842
42032
|
const dir = pinnedVersionDir();
|
|
41843
|
-
if (!(0,
|
|
42033
|
+
if (!(0, import_node_fs74.existsSync)(dir)) {
|
|
41844
42034
|
printInfo("nothing to remove");
|
|
41845
42035
|
return;
|
|
41846
42036
|
}
|
|
41847
|
-
(0,
|
|
42037
|
+
(0, import_node_fs74.rmSync)(dir, { recursive: true, force: true });
|
|
41848
42038
|
printInfo(`removed ${dir}`);
|
|
41849
42039
|
});
|
|
41850
42040
|
}
|
|
41851
42041
|
|
|
41852
42042
|
// src/cli.ts
|
|
41853
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.34.1-experimental.
|
|
41854
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.1-experimental.
|
|
42043
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.34.1-experimental.c910405").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
|
|
42044
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.1-experimental.c910405");
|
|
41855
42045
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
41856
42046
|
try {
|
|
41857
42047
|
await foldLegacyLocalCredential();
|