@codacy/verity-cli 0.34.0 → 0.34.1-experimental.199c728
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/CHANGELOG.md +27 -0
- package/README.md +2 -0
- package/bin/verity.js +1234 -734
- package/data/skills/verity-analyze/SKILL.md +17 -5
- package/data/skills/verity-feedback/SKILL.md +19 -3
- package/data/skills/verity-learn/SKILL.md +19 -7
- package/data/skills/verity-memory/SKILL.md +21 -8
- package/data/skills/verity-prove/SKILL.md +35 -9
- package/data/skills/verity-reflect/SKILL.md +16 -3
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -6975,10 +6975,10 @@ var require_resolve_block_map = __commonJS2({
|
|
|
6975
6975
|
let offset = bm.offset;
|
|
6976
6976
|
let commentEnd = null;
|
|
6977
6977
|
for (const collItem of bm.items) {
|
|
6978
|
-
const { start: start2, key, sep:
|
|
6978
|
+
const { start: start2, key, sep: sep6, value } = collItem;
|
|
6979
6979
|
const keyProps = resolveProps.resolveProps(start2, {
|
|
6980
6980
|
indicator: "explicit-key-ind",
|
|
6981
|
-
next: key ??
|
|
6981
|
+
next: key ?? sep6?.[0],
|
|
6982
6982
|
offset,
|
|
6983
6983
|
onError,
|
|
6984
6984
|
parentIndent: bm.indent,
|
|
@@ -6992,7 +6992,7 @@ var require_resolve_block_map = __commonJS2({
|
|
|
6992
6992
|
else if ("indent" in key && key.indent !== bm.indent)
|
|
6993
6993
|
onError(offset, "BAD_INDENT", startColMsg);
|
|
6994
6994
|
}
|
|
6995
|
-
if (!keyProps.anchor && !keyProps.tag && !
|
|
6995
|
+
if (!keyProps.anchor && !keyProps.tag && !sep6) {
|
|
6996
6996
|
commentEnd = keyProps.end;
|
|
6997
6997
|
if (keyProps.comment) {
|
|
6998
6998
|
if (map.comment)
|
|
@@ -7016,7 +7016,7 @@ var require_resolve_block_map = __commonJS2({
|
|
|
7016
7016
|
ctx.atKey = false;
|
|
7017
7017
|
if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
|
|
7018
7018
|
onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
|
|
7019
|
-
const valueProps = resolveProps.resolveProps(
|
|
7019
|
+
const valueProps = resolveProps.resolveProps(sep6 ?? [], {
|
|
7020
7020
|
indicator: "map-value-ind",
|
|
7021
7021
|
next: value,
|
|
7022
7022
|
offset: keyNode.range[2],
|
|
@@ -7032,7 +7032,7 @@ var require_resolve_block_map = __commonJS2({
|
|
|
7032
7032
|
if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
|
|
7033
7033
|
onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
|
|
7034
7034
|
}
|
|
7035
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset,
|
|
7035
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep6, null, valueProps, onError);
|
|
7036
7036
|
if (ctx.schema.compat)
|
|
7037
7037
|
utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
|
|
7038
7038
|
offset = valueNode.range[2];
|
|
@@ -7123,7 +7123,7 @@ var require_resolve_end = __commonJS2({
|
|
|
7123
7123
|
let comment = "";
|
|
7124
7124
|
if (end) {
|
|
7125
7125
|
let hasSpace = false;
|
|
7126
|
-
let
|
|
7126
|
+
let sep6 = "";
|
|
7127
7127
|
for (const token of end) {
|
|
7128
7128
|
const { source: source2, type } = token;
|
|
7129
7129
|
switch (type) {
|
|
@@ -7137,13 +7137,13 @@ var require_resolve_end = __commonJS2({
|
|
|
7137
7137
|
if (!comment)
|
|
7138
7138
|
comment = cb;
|
|
7139
7139
|
else
|
|
7140
|
-
comment +=
|
|
7141
|
-
|
|
7140
|
+
comment += sep6 + cb;
|
|
7141
|
+
sep6 = "";
|
|
7142
7142
|
break;
|
|
7143
7143
|
}
|
|
7144
7144
|
case "newline":
|
|
7145
7145
|
if (comment)
|
|
7146
|
-
|
|
7146
|
+
sep6 += source2;
|
|
7147
7147
|
hasSpace = true;
|
|
7148
7148
|
break;
|
|
7149
7149
|
default:
|
|
@@ -7186,18 +7186,18 @@ var require_resolve_flow_collection = __commonJS2({
|
|
|
7186
7186
|
let offset = fc.offset + fc.start.source.length;
|
|
7187
7187
|
for (let i2 = 0; i2 < fc.items.length; ++i2) {
|
|
7188
7188
|
const collItem = fc.items[i2];
|
|
7189
|
-
const { start: start2, key, sep:
|
|
7189
|
+
const { start: start2, key, sep: sep6, value } = collItem;
|
|
7190
7190
|
const props = resolveProps.resolveProps(start2, {
|
|
7191
7191
|
flow: fcName,
|
|
7192
7192
|
indicator: "explicit-key-ind",
|
|
7193
|
-
next: key ??
|
|
7193
|
+
next: key ?? sep6?.[0],
|
|
7194
7194
|
offset,
|
|
7195
7195
|
onError,
|
|
7196
7196
|
parentIndent: fc.indent,
|
|
7197
7197
|
startOnNewline: false
|
|
7198
7198
|
});
|
|
7199
7199
|
if (!props.found) {
|
|
7200
|
-
if (!props.anchor && !props.tag && !
|
|
7200
|
+
if (!props.anchor && !props.tag && !sep6 && !value) {
|
|
7201
7201
|
if (i2 === 0 && props.comma)
|
|
7202
7202
|
onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
|
|
7203
7203
|
else if (i2 < fc.items.length - 1)
|
|
@@ -7251,8 +7251,8 @@ var require_resolve_flow_collection = __commonJS2({
|
|
|
7251
7251
|
}
|
|
7252
7252
|
}
|
|
7253
7253
|
}
|
|
7254
|
-
if (!isMap && !
|
|
7255
|
-
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end,
|
|
7254
|
+
if (!isMap && !sep6 && !props.found) {
|
|
7255
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep6, null, props, onError);
|
|
7256
7256
|
coll.items.push(valueNode);
|
|
7257
7257
|
offset = valueNode.range[2];
|
|
7258
7258
|
if (isBlock(value))
|
|
@@ -7264,7 +7264,7 @@ var require_resolve_flow_collection = __commonJS2({
|
|
|
7264
7264
|
if (isBlock(key))
|
|
7265
7265
|
onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
7266
7266
|
ctx.atKey = false;
|
|
7267
|
-
const valueProps = resolveProps.resolveProps(
|
|
7267
|
+
const valueProps = resolveProps.resolveProps(sep6 ?? [], {
|
|
7268
7268
|
flow: fcName,
|
|
7269
7269
|
indicator: "map-value-ind",
|
|
7270
7270
|
next: value,
|
|
@@ -7275,8 +7275,8 @@ var require_resolve_flow_collection = __commonJS2({
|
|
|
7275
7275
|
});
|
|
7276
7276
|
if (valueProps.found) {
|
|
7277
7277
|
if (!isMap && !props.found && ctx.options.strict) {
|
|
7278
|
-
if (
|
|
7279
|
-
for (const st of
|
|
7278
|
+
if (sep6)
|
|
7279
|
+
for (const st of sep6) {
|
|
7280
7280
|
if (st === valueProps.found)
|
|
7281
7281
|
break;
|
|
7282
7282
|
if (st.type === "newline") {
|
|
@@ -7293,7 +7293,7 @@ var require_resolve_flow_collection = __commonJS2({
|
|
|
7293
7293
|
else
|
|
7294
7294
|
onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
|
|
7295
7295
|
}
|
|
7296
|
-
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end,
|
|
7296
|
+
const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep6, null, valueProps, onError) : null;
|
|
7297
7297
|
if (valueNode) {
|
|
7298
7298
|
if (isBlock(value))
|
|
7299
7299
|
onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
|
|
@@ -7473,7 +7473,7 @@ var require_resolve_block_scalar = __commonJS2({
|
|
|
7473
7473
|
chompStart = i2 + 1;
|
|
7474
7474
|
}
|
|
7475
7475
|
let value = "";
|
|
7476
|
-
let
|
|
7476
|
+
let sep6 = "";
|
|
7477
7477
|
let prevMoreIndented = false;
|
|
7478
7478
|
for (let i2 = 0; i2 < contentStart; ++i2)
|
|
7479
7479
|
value += lines[i2][0].slice(trimIndent) + "\n";
|
|
@@ -7490,24 +7490,24 @@ var require_resolve_block_scalar = __commonJS2({
|
|
|
7490
7490
|
indent = "";
|
|
7491
7491
|
}
|
|
7492
7492
|
if (type === Scalar.Scalar.BLOCK_LITERAL) {
|
|
7493
|
-
value +=
|
|
7494
|
-
|
|
7493
|
+
value += sep6 + indent.slice(trimIndent) + content;
|
|
7494
|
+
sep6 = "\n";
|
|
7495
7495
|
} else if (indent.length > trimIndent || content[0] === " ") {
|
|
7496
|
-
if (
|
|
7497
|
-
|
|
7498
|
-
else if (!prevMoreIndented &&
|
|
7499
|
-
|
|
7500
|
-
value +=
|
|
7501
|
-
|
|
7496
|
+
if (sep6 === " ")
|
|
7497
|
+
sep6 = "\n";
|
|
7498
|
+
else if (!prevMoreIndented && sep6 === "\n")
|
|
7499
|
+
sep6 = "\n\n";
|
|
7500
|
+
value += sep6 + indent.slice(trimIndent) + content;
|
|
7501
|
+
sep6 = "\n";
|
|
7502
7502
|
prevMoreIndented = true;
|
|
7503
7503
|
} else if (content === "") {
|
|
7504
|
-
if (
|
|
7504
|
+
if (sep6 === "\n")
|
|
7505
7505
|
value += "\n";
|
|
7506
7506
|
else
|
|
7507
|
-
|
|
7507
|
+
sep6 = "\n";
|
|
7508
7508
|
} else {
|
|
7509
|
-
value +=
|
|
7510
|
-
|
|
7509
|
+
value += sep6 + content;
|
|
7510
|
+
sep6 = " ";
|
|
7511
7511
|
prevMoreIndented = false;
|
|
7512
7512
|
}
|
|
7513
7513
|
}
|
|
@@ -7689,25 +7689,25 @@ var require_resolve_flow_scalar = __commonJS2({
|
|
|
7689
7689
|
if (!match)
|
|
7690
7690
|
return source2;
|
|
7691
7691
|
let res = match[1];
|
|
7692
|
-
let
|
|
7692
|
+
let sep6 = " ";
|
|
7693
7693
|
let pos = first.lastIndex;
|
|
7694
7694
|
line2.lastIndex = pos;
|
|
7695
7695
|
while (match = line2.exec(source2)) {
|
|
7696
7696
|
if (match[1] === "") {
|
|
7697
|
-
if (
|
|
7698
|
-
res +=
|
|
7697
|
+
if (sep6 === "\n")
|
|
7698
|
+
res += sep6;
|
|
7699
7699
|
else
|
|
7700
|
-
|
|
7700
|
+
sep6 = "\n";
|
|
7701
7701
|
} else {
|
|
7702
|
-
res +=
|
|
7703
|
-
|
|
7702
|
+
res += sep6 + match[1];
|
|
7703
|
+
sep6 = " ";
|
|
7704
7704
|
}
|
|
7705
7705
|
pos = line2.lastIndex;
|
|
7706
7706
|
}
|
|
7707
7707
|
const last = /[ \t]*(.*)/sy;
|
|
7708
7708
|
last.lastIndex = pos;
|
|
7709
7709
|
match = last.exec(source2);
|
|
7710
|
-
return res +
|
|
7710
|
+
return res + sep6 + (match?.[1] ?? "");
|
|
7711
7711
|
}
|
|
7712
7712
|
function doubleQuotedValue(source2, onError) {
|
|
7713
7713
|
let res = "";
|
|
@@ -8514,14 +8514,14 @@ var require_cst_stringify = __commonJS2({
|
|
|
8514
8514
|
}
|
|
8515
8515
|
}
|
|
8516
8516
|
}
|
|
8517
|
-
function stringifyItem({ start: start2, key, sep:
|
|
8517
|
+
function stringifyItem({ start: start2, key, sep: sep6, value }) {
|
|
8518
8518
|
let res = "";
|
|
8519
8519
|
for (const st of start2)
|
|
8520
8520
|
res += st.source;
|
|
8521
8521
|
if (key)
|
|
8522
8522
|
res += stringifyToken(key);
|
|
8523
|
-
if (
|
|
8524
|
-
for (const st of
|
|
8523
|
+
if (sep6)
|
|
8524
|
+
for (const st of sep6)
|
|
8525
8525
|
res += st.source;
|
|
8526
8526
|
if (value)
|
|
8527
8527
|
res += stringifyToken(value);
|
|
@@ -9671,18 +9671,18 @@ var require_parser = __commonJS2({
|
|
|
9671
9671
|
if (this.type === "map-value-ind") {
|
|
9672
9672
|
const prev = getPrevProps(this.peek(2));
|
|
9673
9673
|
const start2 = getFirstKeyStartProps(prev);
|
|
9674
|
-
let
|
|
9674
|
+
let sep6;
|
|
9675
9675
|
if (scalar.end) {
|
|
9676
|
-
|
|
9677
|
-
|
|
9676
|
+
sep6 = scalar.end;
|
|
9677
|
+
sep6.push(this.sourceToken);
|
|
9678
9678
|
delete scalar.end;
|
|
9679
9679
|
} else
|
|
9680
|
-
|
|
9680
|
+
sep6 = [this.sourceToken];
|
|
9681
9681
|
const map = {
|
|
9682
9682
|
type: "block-map",
|
|
9683
9683
|
offset: scalar.offset,
|
|
9684
9684
|
indent: scalar.indent,
|
|
9685
|
-
items: [{ start: start2, key: scalar, sep:
|
|
9685
|
+
items: [{ start: start2, key: scalar, sep: sep6 }]
|
|
9686
9686
|
};
|
|
9687
9687
|
this.onKeyLine = true;
|
|
9688
9688
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -9835,15 +9835,15 @@ var require_parser = __commonJS2({
|
|
|
9835
9835
|
} else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
|
|
9836
9836
|
const start3 = getFirstKeyStartProps(it.start);
|
|
9837
9837
|
const key = it.key;
|
|
9838
|
-
const
|
|
9839
|
-
|
|
9838
|
+
const sep6 = it.sep;
|
|
9839
|
+
sep6.push(this.sourceToken);
|
|
9840
9840
|
delete it.key;
|
|
9841
9841
|
delete it.sep;
|
|
9842
9842
|
this.stack.push({
|
|
9843
9843
|
type: "block-map",
|
|
9844
9844
|
offset: this.offset,
|
|
9845
9845
|
indent: this.indent,
|
|
9846
|
-
items: [{ start: start3, key, sep:
|
|
9846
|
+
items: [{ start: start3, key, sep: sep6 }]
|
|
9847
9847
|
});
|
|
9848
9848
|
} else if (start2.length > 0) {
|
|
9849
9849
|
it.sep = it.sep.concat(start2, this.sourceToken);
|
|
@@ -10037,13 +10037,13 @@ var require_parser = __commonJS2({
|
|
|
10037
10037
|
const prev = getPrevProps(parent);
|
|
10038
10038
|
const start2 = getFirstKeyStartProps(prev);
|
|
10039
10039
|
fixFlowSeqItems(fc);
|
|
10040
|
-
const
|
|
10041
|
-
|
|
10040
|
+
const sep6 = fc.end.splice(1, fc.end.length);
|
|
10041
|
+
sep6.push(this.sourceToken);
|
|
10042
10042
|
const map = {
|
|
10043
10043
|
type: "block-map",
|
|
10044
10044
|
offset: fc.offset,
|
|
10045
10045
|
indent: fc.indent,
|
|
10046
|
-
items: [{ start: start2, key: fc, sep:
|
|
10046
|
+
items: [{ start: start2, key: fc, sep: sep6 }]
|
|
10047
10047
|
};
|
|
10048
10048
|
this.onKeyLine = true;
|
|
10049
10049
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -10435,13 +10435,13 @@ var require_web_tree_sitter2 = __commonJS2({
|
|
|
10435
10435
|
}
|
|
10436
10436
|
readAsync = /* @__PURE__ */ __name(async (url) => {
|
|
10437
10437
|
if (isFileURI(url)) {
|
|
10438
|
-
return new Promise((
|
|
10438
|
+
return new Promise((resolve9, reject) => {
|
|
10439
10439
|
var xhr = new XMLHttpRequest();
|
|
10440
10440
|
xhr.open("GET", url, true);
|
|
10441
10441
|
xhr.responseType = "arraybuffer";
|
|
10442
10442
|
xhr.onload = () => {
|
|
10443
10443
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
10444
|
-
|
|
10444
|
+
resolve9(xhr.response);
|
|
10445
10445
|
return;
|
|
10446
10446
|
}
|
|
10447
10447
|
reject(xhr.status);
|
|
@@ -10634,9 +10634,9 @@ var require_web_tree_sitter2 = __commonJS2({
|
|
|
10634
10634
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
10635
10635
|
var info2 = getWasmImports();
|
|
10636
10636
|
if (Module["instantiateWasm"]) {
|
|
10637
|
-
return new Promise((
|
|
10637
|
+
return new Promise((resolve9, reject) => {
|
|
10638
10638
|
Module["instantiateWasm"](info2, (mod, inst) => {
|
|
10639
|
-
|
|
10639
|
+
resolve9(receiveInstance(mod, inst));
|
|
10640
10640
|
});
|
|
10641
10641
|
});
|
|
10642
10642
|
}
|
|
@@ -11969,8 +11969,8 @@ var require_web_tree_sitter2 = __commonJS2({
|
|
|
11969
11969
|
if (runtimeInitialized) {
|
|
11970
11970
|
moduleRtn = Module;
|
|
11971
11971
|
} else {
|
|
11972
|
-
moduleRtn = new Promise((
|
|
11973
|
-
readyPromiseResolve =
|
|
11972
|
+
moduleRtn = new Promise((resolve9, reject) => {
|
|
11973
|
+
readyPromiseResolve = resolve9;
|
|
11974
11974
|
readyPromiseReject = reject;
|
|
11975
11975
|
});
|
|
11976
11976
|
}
|
|
@@ -14447,8 +14447,87 @@ var import_node_child_process4 = require("node:child_process");
|
|
|
14447
14447
|
|
|
14448
14448
|
// src/constants.ts
|
|
14449
14449
|
var import_node_child_process = require("node:child_process");
|
|
14450
|
+
var import_node_fs2 = require("node:fs");
|
|
14451
|
+
var import_node_path2 = require("node:path");
|
|
14452
|
+
|
|
14453
|
+
// src/lib/context-identity.ts
|
|
14454
|
+
var import_node_crypto = require("node:crypto");
|
|
14450
14455
|
var import_node_fs = require("node:fs");
|
|
14456
|
+
var import_node_os = require("node:os");
|
|
14451
14457
|
var import_node_path = require("node:path");
|
|
14458
|
+
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
14459
|
+
"",
|
|
14460
|
+
"-",
|
|
14461
|
+
"n/a",
|
|
14462
|
+
"na",
|
|
14463
|
+
"none",
|
|
14464
|
+
"null",
|
|
14465
|
+
"undefined",
|
|
14466
|
+
"unknown",
|
|
14467
|
+
"anon",
|
|
14468
|
+
"anonymous",
|
|
14469
|
+
"default",
|
|
14470
|
+
"_default"
|
|
14471
|
+
]);
|
|
14472
|
+
function isSharedSentinel(value) {
|
|
14473
|
+
if (value == null) return true;
|
|
14474
|
+
return SHARED_SENTINELS.has(value.trim().toLowerCase());
|
|
14475
|
+
}
|
|
14476
|
+
var ephemeral = /* @__PURE__ */ new Map();
|
|
14477
|
+
function ephemeralId(slot, width) {
|
|
14478
|
+
let id = ephemeral.get(slot);
|
|
14479
|
+
if (!id) {
|
|
14480
|
+
id = `eph-${(0, import_node_crypto.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
|
|
14481
|
+
ephemeral.set(slot, id);
|
|
14482
|
+
}
|
|
14483
|
+
return id;
|
|
14484
|
+
}
|
|
14485
|
+
function contextIdentity(input) {
|
|
14486
|
+
const tokenUsable = !isSharedSentinel(input.token ?? null);
|
|
14487
|
+
const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
|
|
14488
|
+
const userKey = tokenUsable ? (0, import_node_crypto.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
|
|
14489
|
+
const sessionKey2 = sessionUsable ? (0, import_node_crypto.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
|
|
14490
|
+
let treeKey = "no-tree";
|
|
14491
|
+
const rawTree = input.treeRoot;
|
|
14492
|
+
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
14493
|
+
let resolved = rawTree;
|
|
14494
|
+
try {
|
|
14495
|
+
resolved = import_node_fs.realpathSync.native(rawTree);
|
|
14496
|
+
} catch {
|
|
14497
|
+
}
|
|
14498
|
+
treeKey = (0, import_node_crypto.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
14499
|
+
}
|
|
14500
|
+
return {
|
|
14501
|
+
userKey,
|
|
14502
|
+
treeKey,
|
|
14503
|
+
sessionKey: sessionKey2,
|
|
14504
|
+
userKeySource: tokenUsable ? "token" : "ephemeral",
|
|
14505
|
+
sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
|
|
14506
|
+
ephemeral: !tokenUsable || !sessionUsable
|
|
14507
|
+
};
|
|
14508
|
+
}
|
|
14509
|
+
function verityHome() {
|
|
14510
|
+
const override = process.env.VERITY_HOME;
|
|
14511
|
+
return override && override.trim() ? (0, import_node_path.resolve)(override) : (0, import_node_path.join)((0, import_node_os.homedir)(), ".verity");
|
|
14512
|
+
}
|
|
14513
|
+
function dossierDir(identity) {
|
|
14514
|
+
return (0, import_node_path.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
|
|
14515
|
+
}
|
|
14516
|
+
function treeDir(identity) {
|
|
14517
|
+
return (0, import_node_path.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
|
|
14518
|
+
}
|
|
14519
|
+
function scopeIdentity(token, sessionId) {
|
|
14520
|
+
const t = (token ?? "").trim();
|
|
14521
|
+
const s = (sessionId ?? "").trim();
|
|
14522
|
+
const userKey = t.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
|
|
14523
|
+
const sessionKey2 = s.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
|
|
14524
|
+
return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
|
|
14525
|
+
}
|
|
14526
|
+
function sessionScopeKey(token, sessionId) {
|
|
14527
|
+
return scopeIdentity(token, sessionId).bucket;
|
|
14528
|
+
}
|
|
14529
|
+
|
|
14530
|
+
// src/constants.ts
|
|
14452
14531
|
var _repoRoot = null;
|
|
14453
14532
|
function repoRoot() {
|
|
14454
14533
|
if (_repoRoot === null) {
|
|
@@ -14476,17 +14555,36 @@ function mainWorktreeRoot() {
|
|
|
14476
14555
|
_mainRoot = null;
|
|
14477
14556
|
return _mainRoot;
|
|
14478
14557
|
}
|
|
14479
|
-
const abs = common.startsWith("/") ? common : (0,
|
|
14480
|
-
_mainRoot = (0,
|
|
14558
|
+
const abs = common.startsWith("/") ? common : (0, import_node_path2.join)(repoRoot(), common);
|
|
14559
|
+
_mainRoot = (0, import_node_path2.dirname)(abs);
|
|
14481
14560
|
} catch {
|
|
14482
14561
|
_mainRoot = null;
|
|
14483
14562
|
}
|
|
14484
14563
|
return _mainRoot;
|
|
14485
14564
|
}
|
|
14486
14565
|
function verityConfigured() {
|
|
14487
|
-
if ((
|
|
14566
|
+
if (isProjectVerityDir((0, import_node_path2.join)(repoRoot(), VERITY_DIR))) return true;
|
|
14488
14567
|
const main = mainWorktreeRoot();
|
|
14489
|
-
return !!main && (
|
|
14568
|
+
return !!main && isProjectVerityDir((0, import_node_path2.join)(main, VERITY_DIR));
|
|
14569
|
+
}
|
|
14570
|
+
function isProjectVerityDir(dir) {
|
|
14571
|
+
return (0, import_node_fs2.existsSync)(dir) && !isMachineStore(dir);
|
|
14572
|
+
}
|
|
14573
|
+
function isMachineStore(dir) {
|
|
14574
|
+
const here = canonicalPath(dir);
|
|
14575
|
+
const stores = [process.env.HOME ? (0, import_node_path2.join)(process.env.HOME, VERITY_DIR) : null, verityHome()];
|
|
14576
|
+
return stores.some((s) => s !== null && canonicalPath(s) === here);
|
|
14577
|
+
}
|
|
14578
|
+
function canonicalPath(p) {
|
|
14579
|
+
try {
|
|
14580
|
+
return import_node_fs2.realpathSync.native(p);
|
|
14581
|
+
} catch {
|
|
14582
|
+
}
|
|
14583
|
+
try {
|
|
14584
|
+
return (0, import_node_path2.join)(import_node_fs2.realpathSync.native((0, import_node_path2.dirname)(p)), (0, import_node_path2.basename)(p));
|
|
14585
|
+
} catch {
|
|
14586
|
+
return (0, import_node_path2.resolve)(p);
|
|
14587
|
+
}
|
|
14490
14588
|
}
|
|
14491
14589
|
var VERITY_DIR = ".verity";
|
|
14492
14590
|
var CREDENTIALS_FILE = `${VERITY_DIR}/credentials`;
|
|
@@ -14507,7 +14605,7 @@ var MEMORY_DIR = `${VERITY_DIR}/memory`;
|
|
|
14507
14605
|
var CODACY_CONFIG_FILE = ".codacy/codacy.config.json";
|
|
14508
14606
|
var VERITYIGNORE_FILE = ".verityignore";
|
|
14509
14607
|
function projectPath(relativePath) {
|
|
14510
|
-
return (0,
|
|
14608
|
+
return (0, import_node_path2.join)(repoRoot(), relativePath);
|
|
14511
14609
|
}
|
|
14512
14610
|
var MAX_DELTA_BYTES = 194560;
|
|
14513
14611
|
var MAX_FILES = 40;
|
|
@@ -14628,7 +14726,7 @@ var SECURITY_PATTERNS = [
|
|
|
14628
14726
|
/Dockerfile/
|
|
14629
14727
|
];
|
|
14630
14728
|
var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
|
|
14631
|
-
var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
|
|
14729
|
+
var DEFAULT_SERVICE_URL = "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1".length > 0 ? "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1" : PROD_SERVICE_URL;
|
|
14632
14730
|
var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
|
|
14633
14731
|
var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
|
|
14634
14732
|
var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
|
|
@@ -14681,7 +14779,7 @@ function printVerbose(msg, verbose) {
|
|
|
14681
14779
|
}
|
|
14682
14780
|
|
|
14683
14781
|
// src/lib/debug-log.ts
|
|
14684
|
-
var
|
|
14782
|
+
var import_node_fs3 = require("node:fs");
|
|
14685
14783
|
function isDebugEnabled() {
|
|
14686
14784
|
const v = process.env.VERITY_DEBUG;
|
|
14687
14785
|
if (v === "0" || v === "false" || v === "off") return false;
|
|
@@ -14699,24 +14797,24 @@ function writeLine(obj) {
|
|
|
14699
14797
|
try {
|
|
14700
14798
|
const dir = projectPath(DEBUG_LOG_DIR);
|
|
14701
14799
|
const file = projectPath(DEBUG_LOG_FILE);
|
|
14702
|
-
(0,
|
|
14800
|
+
(0, import_node_fs3.mkdirSync)(dir, { recursive: true });
|
|
14703
14801
|
rotateIfNeeded(file);
|
|
14704
|
-
(0,
|
|
14802
|
+
(0, import_node_fs3.appendFileSync)(file, JSON.stringify(obj) + "\n");
|
|
14705
14803
|
} catch {
|
|
14706
14804
|
}
|
|
14707
14805
|
}
|
|
14708
14806
|
function rotateIfNeeded(file) {
|
|
14709
14807
|
try {
|
|
14710
|
-
const s = (0,
|
|
14808
|
+
const s = (0, import_node_fs3.statSync)(file);
|
|
14711
14809
|
if (s.size < DEBUG_LOG_MAX_BYTES) return;
|
|
14712
|
-
(0,
|
|
14810
|
+
(0, import_node_fs3.renameSync)(file, `${file}.1`);
|
|
14713
14811
|
} catch {
|
|
14714
14812
|
}
|
|
14715
14813
|
}
|
|
14716
14814
|
|
|
14717
14815
|
// src/lib/credentials.ts
|
|
14718
14816
|
var import_promises = require("node:fs/promises");
|
|
14719
|
-
var
|
|
14817
|
+
var import_node_path3 = require("node:path");
|
|
14720
14818
|
var import_node_child_process2 = require("node:child_process");
|
|
14721
14819
|
function globalCredentialsPath() {
|
|
14722
14820
|
return `${process.env.HOME}/.verity/credentials`;
|
|
@@ -14791,7 +14889,7 @@ async function readGlobalCredential(remote) {
|
|
|
14791
14889
|
}
|
|
14792
14890
|
async function upsertGlobalCredential(remote, rec) {
|
|
14793
14891
|
const path = globalCredentialsPath();
|
|
14794
|
-
await (0, import_promises.mkdir)((0,
|
|
14892
|
+
await (0, import_promises.mkdir)((0, import_node_path3.dirname)(path), { recursive: true });
|
|
14795
14893
|
let content = "";
|
|
14796
14894
|
try {
|
|
14797
14895
|
content = await (0, import_promises.readFile)(path, "utf-8");
|
|
@@ -14935,10 +15033,10 @@ async function foldLegacyLocalCredential(remoteArg) {
|
|
|
14935
15033
|
|
|
14936
15034
|
// src/lib/git.ts
|
|
14937
15035
|
var import_node_child_process3 = require("node:child_process");
|
|
14938
|
-
var
|
|
14939
|
-
var
|
|
15036
|
+
var import_node_fs4 = require("node:fs");
|
|
15037
|
+
var import_node_path4 = require("node:path");
|
|
14940
15038
|
function resolveFile(relpath) {
|
|
14941
|
-
return (0,
|
|
15039
|
+
return (0, import_node_fs4.existsSync)(relpath) ? relpath : null;
|
|
14942
15040
|
}
|
|
14943
15041
|
function execGit(cmd) {
|
|
14944
15042
|
try {
|
|
@@ -14956,7 +15054,7 @@ function readBaselineSha() {
|
|
|
14956
15054
|
if (sha === null) return null;
|
|
14957
15055
|
if (!commitResolves(sha)) {
|
|
14958
15056
|
try {
|
|
14959
|
-
(0,
|
|
15057
|
+
(0, import_node_fs4.unlinkSync)(BASELINE_SHA_FILE);
|
|
14960
15058
|
} catch {
|
|
14961
15059
|
}
|
|
14962
15060
|
return null;
|
|
@@ -14964,10 +15062,10 @@ function readBaselineSha() {
|
|
|
14964
15062
|
return sha;
|
|
14965
15063
|
}
|
|
14966
15064
|
function readRawBaselineSha() {
|
|
14967
|
-
if (!(0,
|
|
15065
|
+
if (!(0, import_node_fs4.existsSync)(BASELINE_SHA_FILE)) return null;
|
|
14968
15066
|
let sha;
|
|
14969
15067
|
try {
|
|
14970
|
-
sha = (0,
|
|
15068
|
+
sha = (0, import_node_fs4.readFileSync)(BASELINE_SHA_FILE, "utf-8").trim();
|
|
14971
15069
|
} catch {
|
|
14972
15070
|
return null;
|
|
14973
15071
|
}
|
|
@@ -14976,8 +15074,8 @@ function readRawBaselineSha() {
|
|
|
14976
15074
|
function writeBaselineSha(sha) {
|
|
14977
15075
|
if (!SHA_RE.test(sha)) return;
|
|
14978
15076
|
try {
|
|
14979
|
-
(0,
|
|
14980
|
-
(0,
|
|
15077
|
+
(0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(BASELINE_SHA_FILE), { recursive: true });
|
|
15078
|
+
(0, import_node_fs4.writeFileSync)(BASELINE_SHA_FILE, sha);
|
|
14981
15079
|
} catch {
|
|
14982
15080
|
}
|
|
14983
15081
|
}
|
|
@@ -15065,17 +15163,17 @@ function showContentAtRef(ref, repoRelPath) {
|
|
|
15065
15163
|
}
|
|
15066
15164
|
function filterAnalyzable(files) {
|
|
15067
15165
|
return files.filter((f) => {
|
|
15068
|
-
const ext = (0,
|
|
15166
|
+
const ext = (0, import_node_path4.extname)(f).slice(1);
|
|
15069
15167
|
return ANALYZABLE_EXTENSIONS.has(ext);
|
|
15070
15168
|
});
|
|
15071
15169
|
}
|
|
15072
15170
|
function filterReviewable(files) {
|
|
15073
15171
|
return files.filter((f) => {
|
|
15074
|
-
const ext = (0,
|
|
15172
|
+
const ext = (0, import_node_path4.extname)(f).slice(1);
|
|
15075
15173
|
if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
|
|
15076
15174
|
if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
|
|
15077
|
-
const
|
|
15078
|
-
if (REVIEWABLE_FILENAMES.has(
|
|
15175
|
+
const basename9 = f.split("/").pop() ?? "";
|
|
15176
|
+
if (REVIEWABLE_FILENAMES.has(basename9)) return true;
|
|
15079
15177
|
if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
|
|
15080
15178
|
return false;
|
|
15081
15179
|
});
|
|
@@ -15550,7 +15648,7 @@ async function maybeHealServiceUrl(resolution, verbose) {
|
|
|
15550
15648
|
|
|
15551
15649
|
// src/lib/register.ts
|
|
15552
15650
|
var readline = __toESM2(require("node:readline/promises"));
|
|
15553
|
-
var
|
|
15651
|
+
var import_node_os2 = require("node:os");
|
|
15554
15652
|
|
|
15555
15653
|
// src/lib/spinner.ts
|
|
15556
15654
|
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
@@ -15638,7 +15736,7 @@ function startSpinner(label2, opts = {}) {
|
|
|
15638
15736
|
}
|
|
15639
15737
|
|
|
15640
15738
|
// src/lib/provider-auth.ts
|
|
15641
|
-
var sleep = (ms) => new Promise((
|
|
15739
|
+
var sleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
|
|
15642
15740
|
var form = (fields) => new URLSearchParams(fields).toString();
|
|
15643
15741
|
async function githubAccountId(owner) {
|
|
15644
15742
|
try {
|
|
@@ -15903,7 +16001,7 @@ function deviceLabel() {
|
|
|
15903
16001
|
const override = process.env.VERITY_DEVICE_LABEL?.trim();
|
|
15904
16002
|
if (override) return override;
|
|
15905
16003
|
try {
|
|
15906
|
-
return (0,
|
|
16004
|
+
return (0, import_node_os2.hostname)() || void 0;
|
|
15907
16005
|
} catch {
|
|
15908
16006
|
return void 0;
|
|
15909
16007
|
}
|
|
@@ -16061,8 +16159,8 @@ function registerAuthCommands(program2) {
|
|
|
16061
16159
|
}
|
|
16062
16160
|
|
|
16063
16161
|
// src/lib/pending-login.ts
|
|
16064
|
-
var
|
|
16065
|
-
var
|
|
16162
|
+
var import_node_fs5 = require("node:fs");
|
|
16163
|
+
var import_node_path5 = require("node:path");
|
|
16066
16164
|
function pendingLoginPath() {
|
|
16067
16165
|
return `${process.env.HOME}/.verity/pending-login.json`;
|
|
16068
16166
|
}
|
|
@@ -16078,26 +16176,26 @@ function savePendingLogin(dc, serviceUrl, now = Date.now()) {
|
|
|
16078
16176
|
created_at: new Date(now).toISOString()
|
|
16079
16177
|
};
|
|
16080
16178
|
const path = pendingLoginPath();
|
|
16081
|
-
(0,
|
|
16179
|
+
(0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(path), { recursive: true });
|
|
16082
16180
|
clearPendingLogin();
|
|
16083
|
-
(0,
|
|
16181
|
+
(0, import_node_fs5.writeFileSync)(path, JSON.stringify(record, null, 2) + "\n", { mode: 384, flag: "wx" });
|
|
16084
16182
|
try {
|
|
16085
|
-
(0,
|
|
16183
|
+
(0, import_node_fs5.chmodSync)(path, 384);
|
|
16086
16184
|
} catch {
|
|
16087
16185
|
}
|
|
16088
16186
|
return record;
|
|
16089
16187
|
}
|
|
16090
16188
|
function readPendingLogin(now = Date.now()) {
|
|
16091
16189
|
const path = pendingLoginPath();
|
|
16092
|
-
if (!(0,
|
|
16190
|
+
if (!(0, import_node_fs5.existsSync)(path)) return { status: "none" };
|
|
16093
16191
|
try {
|
|
16094
|
-
if ((0,
|
|
16192
|
+
if ((0, import_node_fs5.lstatSync)(path).isSymbolicLink()) return { status: "invalid", reason: "it is a symlink" };
|
|
16095
16193
|
} catch {
|
|
16096
16194
|
return { status: "none" };
|
|
16097
16195
|
}
|
|
16098
16196
|
let parsed;
|
|
16099
16197
|
try {
|
|
16100
|
-
parsed = JSON.parse((0,
|
|
16198
|
+
parsed = JSON.parse((0, import_node_fs5.readFileSync)(path, "utf-8"));
|
|
16101
16199
|
} catch {
|
|
16102
16200
|
return { status: "invalid", reason: "it is not valid JSON" };
|
|
16103
16201
|
}
|
|
@@ -16118,7 +16216,7 @@ function readPendingLogin(now = Date.now()) {
|
|
|
16118
16216
|
}
|
|
16119
16217
|
function clearPendingLogin() {
|
|
16120
16218
|
try {
|
|
16121
|
-
(0,
|
|
16219
|
+
(0, import_node_fs5.unlinkSync)(pendingLoginPath());
|
|
16122
16220
|
return true;
|
|
16123
16221
|
} catch {
|
|
16124
16222
|
return false;
|
|
@@ -16674,11 +16772,11 @@ function registerLogoutCommand(program2) {
|
|
|
16674
16772
|
|
|
16675
16773
|
// src/lib/hooks.ts
|
|
16676
16774
|
var import_promises4 = require("node:fs/promises");
|
|
16677
|
-
var
|
|
16775
|
+
var import_node_path7 = require("node:path");
|
|
16678
16776
|
|
|
16679
16777
|
// src/lib/json-file.ts
|
|
16680
16778
|
var import_promises3 = require("node:fs/promises");
|
|
16681
|
-
var
|
|
16779
|
+
var import_node_path6 = require("node:path");
|
|
16682
16780
|
function jsonSemanticEqual(a, b) {
|
|
16683
16781
|
if (a === b) return true;
|
|
16684
16782
|
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) {
|
|
@@ -16724,7 +16822,7 @@ async function writeJsonFilePreservingStyle(file, value) {
|
|
|
16724
16822
|
const indent = currentRaw !== null ? detectJsonIndent(currentRaw) : 2;
|
|
16725
16823
|
const next = JSON.stringify(value, null, indent) + "\n";
|
|
16726
16824
|
if (next === currentRaw) return false;
|
|
16727
|
-
await (0, import_promises3.mkdir)((0,
|
|
16825
|
+
await (0, import_promises3.mkdir)((0, import_node_path6.dirname)(file), { recursive: true });
|
|
16728
16826
|
await (0, import_promises3.writeFile)(file, next);
|
|
16729
16827
|
return true;
|
|
16730
16828
|
}
|
|
@@ -16909,13 +17007,13 @@ async function writeSettings(settings) {
|
|
|
16909
17007
|
}
|
|
16910
17008
|
async function readSettingsAt(root) {
|
|
16911
17009
|
try {
|
|
16912
|
-
return JSON.parse(await (0, import_promises4.readFile)((0,
|
|
17010
|
+
return JSON.parse(await (0, import_promises4.readFile)((0, import_node_path7.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
|
|
16913
17011
|
} catch {
|
|
16914
17012
|
return {};
|
|
16915
17013
|
}
|
|
16916
17014
|
}
|
|
16917
17015
|
async function writeSettingsAt(root, settings) {
|
|
16918
|
-
await writeJsonFilePreservingStyle((0,
|
|
17016
|
+
await writeJsonFilePreservingStyle((0, import_node_path7.join)(root, CLAUDE_SETTINGS_FILE), settings);
|
|
16919
17017
|
}
|
|
16920
17018
|
async function hasLegacyHooksAt(root) {
|
|
16921
17019
|
const settings = await readSettingsAt(root);
|
|
@@ -17104,12 +17202,12 @@ async function applyMomentSelection(moments) {
|
|
|
17104
17202
|
}
|
|
17105
17203
|
|
|
17106
17204
|
// src/lib/project-config.ts
|
|
17107
|
-
var
|
|
17108
|
-
var
|
|
17205
|
+
var import_node_fs7 = require("node:fs");
|
|
17206
|
+
var import_node_path9 = require("node:path");
|
|
17109
17207
|
|
|
17110
17208
|
// src/lib/repo-controlled.ts
|
|
17111
|
-
var
|
|
17112
|
-
var
|
|
17209
|
+
var import_node_fs6 = require("node:fs");
|
|
17210
|
+
var import_node_path8 = require("node:path");
|
|
17113
17211
|
|
|
17114
17212
|
// src/lib/hardened-git.ts
|
|
17115
17213
|
var import_node_child_process5 = require("node:child_process");
|
|
@@ -17190,7 +17288,7 @@ function repoControlled(worktree, rel) {
|
|
|
17190
17288
|
for (let i2 = 1; i2 <= parts2.length; i2++) {
|
|
17191
17289
|
let st;
|
|
17192
17290
|
try {
|
|
17193
|
-
st = (0,
|
|
17291
|
+
st = (0, import_node_fs6.lstatSync)((0, import_node_path8.join)(worktree, ...parts2.slice(0, i2)));
|
|
17194
17292
|
} catch (err2) {
|
|
17195
17293
|
const code = err2?.code;
|
|
17196
17294
|
if (code === "ENOENT" || code === "ENOTDIR") return null;
|
|
@@ -17214,8 +17312,8 @@ function parseMoments(raw) {
|
|
|
17214
17312
|
}
|
|
17215
17313
|
function readConfigFile(path) {
|
|
17216
17314
|
try {
|
|
17217
|
-
if (!(0,
|
|
17218
|
-
const raw = JSON.parse((0,
|
|
17315
|
+
if (!(0, import_node_fs7.existsSync)(path)) return null;
|
|
17316
|
+
const raw = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf-8"));
|
|
17219
17317
|
const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
|
|
17220
17318
|
const source2 = raw.git_moments_source === "user" || raw.git_moments_source === "init" ? raw.git_moments_source : void 0;
|
|
17221
17319
|
return {
|
|
@@ -17232,13 +17330,13 @@ function candidates() {
|
|
|
17232
17330
|
const out2 = [{ path: local, source: "local" }];
|
|
17233
17331
|
const main = mainWorktreeRoot();
|
|
17234
17332
|
if (main) {
|
|
17235
|
-
const inherited = (0,
|
|
17333
|
+
const inherited = (0, import_node_path9.join)(main, PROJECT_CONFIG_FILE);
|
|
17236
17334
|
if (inherited !== local) out2.push({ path: inherited, source: "main-worktree" });
|
|
17237
17335
|
}
|
|
17238
17336
|
return out2;
|
|
17239
17337
|
}
|
|
17240
17338
|
function formalRefusal(path) {
|
|
17241
|
-
return repoControlled((0,
|
|
17339
|
+
return repoControlled((0, import_node_path9.dirname)((0, import_node_path9.dirname)(path)), PROJECT_CONFIG_FILE);
|
|
17242
17340
|
}
|
|
17243
17341
|
function readProjectConfigRaw() {
|
|
17244
17342
|
for (const { path, source: source2 } of candidates()) {
|
|
@@ -17274,8 +17372,8 @@ function writeProjectConfig(patch) {
|
|
|
17274
17372
|
...patch
|
|
17275
17373
|
};
|
|
17276
17374
|
const target = projectPath(PROJECT_CONFIG_FILE);
|
|
17277
|
-
(0,
|
|
17278
|
-
(0,
|
|
17375
|
+
(0, import_node_fs7.mkdirSync)((0, import_node_path9.dirname)(target), { recursive: true });
|
|
17376
|
+
(0, import_node_fs7.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
|
|
17279
17377
|
return next;
|
|
17280
17378
|
}
|
|
17281
17379
|
function resolveGuardMoments(explicit) {
|
|
@@ -17284,11 +17382,11 @@ function resolveGuardMoments(explicit) {
|
|
|
17284
17382
|
}
|
|
17285
17383
|
|
|
17286
17384
|
// src/lib/plugin-ownership.ts
|
|
17287
|
-
var
|
|
17385
|
+
var import_node_fs10 = require("node:fs");
|
|
17288
17386
|
|
|
17289
17387
|
// src/lib/which.ts
|
|
17290
|
-
var
|
|
17291
|
-
var
|
|
17388
|
+
var import_node_fs8 = require("node:fs");
|
|
17389
|
+
var import_node_path10 = require("node:path");
|
|
17292
17390
|
function executableExtensions(platform4, pathext) {
|
|
17293
17391
|
if (platform4 !== "win32") return [""];
|
|
17294
17392
|
const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
|
|
@@ -17306,14 +17404,14 @@ function whichSync(bin, opts = {}) {
|
|
|
17306
17404
|
if (!rawPath) return null;
|
|
17307
17405
|
const exts = executableExtensions(platform4, opts.pathext ?? process.env.PATHEXT);
|
|
17308
17406
|
const real = opts.real ?? true;
|
|
17309
|
-
for (const dir of rawPath.split(
|
|
17407
|
+
for (const dir of rawPath.split(import_node_path10.delimiter)) {
|
|
17310
17408
|
if (!dir) continue;
|
|
17311
17409
|
for (const ext of exts) {
|
|
17312
|
-
const candidate = (0,
|
|
17410
|
+
const candidate = (0, import_node_path10.join)(dir, bin + ext);
|
|
17313
17411
|
try {
|
|
17314
|
-
if (!(0,
|
|
17315
|
-
if (platform4 !== "win32") (0,
|
|
17316
|
-
return real ? (0,
|
|
17412
|
+
if (!(0, import_node_fs8.statSync)(candidate).isFile()) continue;
|
|
17413
|
+
if (platform4 !== "win32") (0, import_node_fs8.accessSync)(candidate, import_node_fs8.constants.X_OK);
|
|
17414
|
+
return real ? (0, import_node_fs8.realpathSync)(candidate) : candidate;
|
|
17317
17415
|
} catch {
|
|
17318
17416
|
continue;
|
|
17319
17417
|
}
|
|
@@ -17323,11 +17421,11 @@ function whichSync(bin, opts = {}) {
|
|
|
17323
17421
|
}
|
|
17324
17422
|
|
|
17325
17423
|
// src/lib/plugin-ownership.ts
|
|
17326
|
-
var
|
|
17327
|
-
var
|
|
17424
|
+
var import_node_os3 = require("node:os");
|
|
17425
|
+
var import_node_path11 = require("node:path");
|
|
17328
17426
|
|
|
17329
17427
|
// src/lib/stderr-log.ts
|
|
17330
|
-
var
|
|
17428
|
+
var import_node_fs9 = require("node:fs");
|
|
17331
17429
|
var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
|
|
17332
17430
|
var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
|
|
17333
17431
|
function scrub(s) {
|
|
@@ -17340,9 +17438,9 @@ function append(text) {
|
|
|
17340
17438
|
try {
|
|
17341
17439
|
const dir = projectPath(DEBUG_LOG_DIR);
|
|
17342
17440
|
const file = projectPath(STDERR_LOG_FILE);
|
|
17343
|
-
(0,
|
|
17441
|
+
(0, import_node_fs9.mkdirSync)(dir, { recursive: true });
|
|
17344
17442
|
rotateIfNeeded(file);
|
|
17345
|
-
(0,
|
|
17443
|
+
(0, import_node_fs9.appendFileSync)(file, text);
|
|
17346
17444
|
} catch {
|
|
17347
17445
|
}
|
|
17348
17446
|
}
|
|
@@ -17390,8 +17488,8 @@ function markerPath() {
|
|
|
17390
17488
|
}
|
|
17391
17489
|
function readMarker() {
|
|
17392
17490
|
try {
|
|
17393
|
-
if (!(0,
|
|
17394
|
-
const raw = JSON.parse((0,
|
|
17491
|
+
if (!(0, import_node_fs10.existsSync)(markerPath())) return null;
|
|
17492
|
+
const raw = JSON.parse((0, import_node_fs10.readFileSync)(markerPath(), "utf-8"));
|
|
17395
17493
|
const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
|
|
17396
17494
|
if (!pluginRoot || CONTROL_CHARS2.test(pluginRoot)) return null;
|
|
17397
17495
|
const version = typeof raw.version === "string" && !CONTROL_CHARS2.test(raw.version) ? raw.version : null;
|
|
@@ -17409,23 +17507,23 @@ function recordPluginOwnership(sessionId) {
|
|
|
17409
17507
|
const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
|
|
17410
17508
|
if (!pluginRoot) return;
|
|
17411
17509
|
try {
|
|
17412
|
-
(0,
|
|
17510
|
+
(0, import_node_fs10.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
|
|
17413
17511
|
const marker = {
|
|
17414
17512
|
session_id: sessionId,
|
|
17415
17513
|
plugin_root: pluginRoot,
|
|
17416
17514
|
version: process.env.VERITY_PLUGIN_VERSION || null,
|
|
17417
17515
|
ts: Math.floor(Date.now() / 1e3)
|
|
17418
17516
|
};
|
|
17419
|
-
(0,
|
|
17517
|
+
(0, import_node_fs10.writeFileSync)(markerPath(), JSON.stringify(marker));
|
|
17420
17518
|
} catch {
|
|
17421
17519
|
}
|
|
17422
17520
|
}
|
|
17423
17521
|
function claudeConfigDir() {
|
|
17424
|
-
return process.env.CLAUDE_CONFIG_DIR || (0,
|
|
17522
|
+
return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".claude");
|
|
17425
17523
|
}
|
|
17426
17524
|
function readJsonFile(path) {
|
|
17427
17525
|
try {
|
|
17428
|
-
const parsed = JSON.parse((0,
|
|
17526
|
+
const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
|
|
17429
17527
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
17430
17528
|
} catch {
|
|
17431
17529
|
return null;
|
|
@@ -17433,9 +17531,9 @@ function readJsonFile(path) {
|
|
|
17433
17531
|
}
|
|
17434
17532
|
function enabledPluginSetting(key) {
|
|
17435
17533
|
const files = [
|
|
17436
|
-
projectPath((0,
|
|
17437
|
-
projectPath((0,
|
|
17438
|
-
(0,
|
|
17534
|
+
projectPath((0, import_node_path11.join)(".claude", "settings.local.json")),
|
|
17535
|
+
projectPath((0, import_node_path11.join)(".claude", "settings.json")),
|
|
17536
|
+
(0, import_node_path11.join)(claudeConfigDir(), "settings.json")
|
|
17439
17537
|
];
|
|
17440
17538
|
for (const file of files) {
|
|
17441
17539
|
const map = readJsonFile(file)?.enabledPlugins;
|
|
@@ -17447,11 +17545,11 @@ function enabledPluginSetting(key) {
|
|
|
17447
17545
|
}
|
|
17448
17546
|
function marketplaceLocations() {
|
|
17449
17547
|
const out2 = /* @__PURE__ */ new Map();
|
|
17450
|
-
const known = readJsonFile((0,
|
|
17548
|
+
const known = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
17451
17549
|
if (!known) return out2;
|
|
17452
17550
|
for (const [name2, entry] of Object.entries(known)) {
|
|
17453
17551
|
const loc2 = entry?.installLocation;
|
|
17454
|
-
if (typeof loc2 === "string" && loc2) out2.set(name2, (0,
|
|
17552
|
+
if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path11.resolve)(loc2));
|
|
17455
17553
|
}
|
|
17456
17554
|
return out2;
|
|
17457
17555
|
}
|
|
@@ -17465,7 +17563,7 @@ function globalVerityVersion() {
|
|
|
17465
17563
|
const entry = verityPathEntry();
|
|
17466
17564
|
if (!entry) return null;
|
|
17467
17565
|
try {
|
|
17468
|
-
const pkg = readJsonFile((0,
|
|
17566
|
+
const pkg = readJsonFile((0, import_node_path11.join)((0, import_node_path11.dirname)((0, import_node_fs10.realpathSync)(entry)), "..", "package.json"));
|
|
17469
17567
|
if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
|
|
17470
17568
|
return pkg.version;
|
|
17471
17569
|
} catch {
|
|
@@ -17482,7 +17580,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
|
|
|
17482
17580
|
function marketplaceConflict() {
|
|
17483
17581
|
const wanted = VERITY_MARKETPLACE;
|
|
17484
17582
|
for (const file of ["settings.json", "settings.local.json"]) {
|
|
17485
|
-
const path = (0,
|
|
17583
|
+
const path = (0, import_node_path11.join)(claudeConfigDir(), file);
|
|
17486
17584
|
const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
|
|
17487
17585
|
const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
|
|
17488
17586
|
if (entry2 && typeof entry2 === "object") {
|
|
@@ -17492,7 +17590,7 @@ function marketplaceConflict() {
|
|
|
17492
17590
|
}
|
|
17493
17591
|
}
|
|
17494
17592
|
}
|
|
17495
|
-
const known = readJsonFile((0,
|
|
17593
|
+
const known = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
|
|
17496
17594
|
const entry = known?.[wanted];
|
|
17497
17595
|
if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
|
|
17498
17596
|
return { name: wanted, declaredAs: describeSource(entry.source) };
|
|
@@ -17513,7 +17611,7 @@ function describeSource(src) {
|
|
|
17513
17611
|
return target ? `${kind} \u2192 ${target}` : kind;
|
|
17514
17612
|
}
|
|
17515
17613
|
function legacyMarketplaceInstall() {
|
|
17516
|
-
const plugins = readJsonFile((0,
|
|
17614
|
+
const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17517
17615
|
if (!plugins || typeof plugins !== "object") return null;
|
|
17518
17616
|
for (const key of Object.keys(plugins)) {
|
|
17519
17617
|
const at = key.lastIndexOf("@");
|
|
@@ -17525,13 +17623,13 @@ function legacyMarketplaceInstall() {
|
|
|
17525
17623
|
}
|
|
17526
17624
|
function realpathOr(p) {
|
|
17527
17625
|
try {
|
|
17528
|
-
return
|
|
17626
|
+
return import_node_fs10.realpathSync.native(p);
|
|
17529
17627
|
} catch {
|
|
17530
|
-
return (0,
|
|
17628
|
+
return (0, import_node_path11.resolve)(p);
|
|
17531
17629
|
}
|
|
17532
17630
|
}
|
|
17533
17631
|
function isWithin(want, dir) {
|
|
17534
|
-
return want === dir || want.startsWith(dir +
|
|
17632
|
+
return want === dir || want.startsWith(dir + import_node_path11.sep);
|
|
17535
17633
|
}
|
|
17536
17634
|
function entryAppliesHere(entry, here) {
|
|
17537
17635
|
const e = entry;
|
|
@@ -17541,9 +17639,9 @@ function entryAppliesHere(entry, here) {
|
|
|
17541
17639
|
return forProject === here;
|
|
17542
17640
|
}
|
|
17543
17641
|
function registrySays(pluginRoot) {
|
|
17544
|
-
const plugins = readJsonFile((0,
|
|
17642
|
+
const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17545
17643
|
if (!plugins || typeof plugins !== "object") return "unverified";
|
|
17546
|
-
const want = (0,
|
|
17644
|
+
const want = (0, import_node_path11.resolve)(pluginRoot);
|
|
17547
17645
|
const here = realpathOr(repoRoot());
|
|
17548
17646
|
const markets = marketplaceLocations();
|
|
17549
17647
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -17552,15 +17650,15 @@ function registrySays(pluginRoot) {
|
|
|
17552
17650
|
const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
|
|
17553
17651
|
const claims = applicable.some((entry) => {
|
|
17554
17652
|
const installPath = entry?.installPath;
|
|
17555
|
-
return typeof installPath === "string" && (0,
|
|
17653
|
+
return typeof installPath === "string" && (0, import_node_path11.resolve)(installPath) === want;
|
|
17556
17654
|
}) || source2 !== void 0 && applicable.length > 0 && isWithin(want, source2);
|
|
17557
17655
|
if (claims) {
|
|
17558
17656
|
if (enabledPluginSetting(key) === false) return "gone";
|
|
17559
|
-
return (0,
|
|
17657
|
+
return (0, import_node_fs10.existsSync)(pluginRoot) ? "live" : "gone";
|
|
17560
17658
|
}
|
|
17561
17659
|
}
|
|
17562
|
-
const managed = (0,
|
|
17563
|
-
return want === managed || want.startsWith(managed +
|
|
17660
|
+
const managed = (0, import_node_path11.resolve)((0, import_node_path11.join)(claudeConfigDir(), "plugins", "cache"));
|
|
17661
|
+
return want === managed || want.startsWith(managed + import_node_path11.sep) ? "gone" : "unverified";
|
|
17564
17662
|
}
|
|
17565
17663
|
var _live = /* @__PURE__ */ new Map();
|
|
17566
17664
|
function pluginLiveness(pluginRoot) {
|
|
@@ -17574,7 +17672,7 @@ function clearStalePluginMarker() {
|
|
|
17574
17672
|
const marker = readMarker();
|
|
17575
17673
|
if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
|
|
17576
17674
|
try {
|
|
17577
|
-
(0,
|
|
17675
|
+
(0, import_node_fs10.rmSync)(markerPath(), { force: true });
|
|
17578
17676
|
} catch {
|
|
17579
17677
|
return null;
|
|
17580
17678
|
}
|
|
@@ -17602,7 +17700,7 @@ function pluginActiveHere() {
|
|
|
17602
17700
|
return activePluginInstall() !== null;
|
|
17603
17701
|
}
|
|
17604
17702
|
function registeredVerityPlugin() {
|
|
17605
|
-
const plugins = readJsonFile((0,
|
|
17703
|
+
const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
17606
17704
|
if (!plugins || typeof plugins !== "object") return null;
|
|
17607
17705
|
const here = realpathOr(repoRoot());
|
|
17608
17706
|
for (const [key, value] of Object.entries(plugins)) {
|
|
@@ -17612,7 +17710,7 @@ function registeredVerityPlugin() {
|
|
|
17612
17710
|
for (const entry of Array.isArray(value) ? value : []) {
|
|
17613
17711
|
const e = entry;
|
|
17614
17712
|
const installPath = typeof e.installPath === "string" ? e.installPath : "";
|
|
17615
|
-
if (!installPath || !(0,
|
|
17713
|
+
if (!installPath || !(0, import_node_fs10.existsSync)(installPath)) continue;
|
|
17616
17714
|
if (!entryAppliesHere(entry, here)) continue;
|
|
17617
17715
|
return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
|
|
17618
17716
|
}
|
|
@@ -17664,28 +17762,28 @@ async function resolveHookWiring() {
|
|
|
17664
17762
|
}
|
|
17665
17763
|
|
|
17666
17764
|
// src/lib/cli-provenance.ts
|
|
17667
|
-
var
|
|
17668
|
-
var
|
|
17669
|
-
var
|
|
17765
|
+
var import_node_fs11 = require("node:fs");
|
|
17766
|
+
var import_node_os4 = require("node:os");
|
|
17767
|
+
var import_node_path12 = require("node:path");
|
|
17670
17768
|
var CLI_PACKAGE = "@codacy/verity-cli";
|
|
17671
|
-
var CLI_ENTRY = (0,
|
|
17769
|
+
var CLI_ENTRY = (0, import_node_path12.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
|
|
17672
17770
|
function readJson(path) {
|
|
17673
17771
|
try {
|
|
17674
|
-
const parsed = JSON.parse((0,
|
|
17772
|
+
const parsed = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
|
|
17675
17773
|
return parsed && typeof parsed === "object" ? parsed : null;
|
|
17676
17774
|
} catch {
|
|
17677
17775
|
return null;
|
|
17678
17776
|
}
|
|
17679
17777
|
}
|
|
17680
17778
|
function versionUnder(base) {
|
|
17681
|
-
const entry = (0,
|
|
17682
|
-
if (!(0,
|
|
17683
|
-
const pkg = readJson((0,
|
|
17779
|
+
const entry = (0, import_node_path12.join)(base, CLI_ENTRY);
|
|
17780
|
+
if (!(0, import_node_fs11.existsSync)(entry)) return null;
|
|
17781
|
+
const pkg = readJson((0, import_node_path12.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
|
|
17684
17782
|
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
17685
17783
|
}
|
|
17686
17784
|
function versionForEntry(entry) {
|
|
17687
17785
|
try {
|
|
17688
|
-
const pkg = readJson((0,
|
|
17786
|
+
const pkg = readJson((0, import_node_path12.join)((0, import_node_path12.dirname)((0, import_node_fs11.realpathSync)(entry)), "..", "package.json"));
|
|
17689
17787
|
return typeof pkg?.version === "string" ? pkg.version : null;
|
|
17690
17788
|
} catch {
|
|
17691
17789
|
return null;
|
|
@@ -17693,16 +17791,16 @@ function versionForEntry(entry) {
|
|
|
17693
17791
|
}
|
|
17694
17792
|
function resolveHooksCli(pluginRoot) {
|
|
17695
17793
|
const override = process.env.VERITY_CLI_PATH;
|
|
17696
|
-
if (override && (0,
|
|
17794
|
+
if (override && (0, import_node_fs11.existsSync)(override)) {
|
|
17697
17795
|
return { version: versionForEntry(override), rung: "override" };
|
|
17698
17796
|
}
|
|
17699
17797
|
const fromPlugin = versionUnder(pluginRoot);
|
|
17700
17798
|
if (fromPlugin !== null) return { version: fromPlugin, rung: "plugin" };
|
|
17701
|
-
if ((0,
|
|
17702
|
-
const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0,
|
|
17799
|
+
if ((0, import_node_fs11.existsSync)((0, import_node_path12.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
|
|
17800
|
+
const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity", "plugin-cli");
|
|
17703
17801
|
const fromData = versionUnder(dataDir);
|
|
17704
17802
|
if (fromData !== null) return { version: fromData, rung: "plugin-data" };
|
|
17705
|
-
if ((0,
|
|
17803
|
+
if ((0, import_node_fs11.existsSync)((0, import_node_path12.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
|
|
17706
17804
|
const global = globalVerityVersion();
|
|
17707
17805
|
if (global !== null) return { version: global, rung: "global" };
|
|
17708
17806
|
return null;
|
|
@@ -17804,7 +17902,7 @@ function pluginCliInvocation() {
|
|
|
17804
17902
|
return resolverCommand(root);
|
|
17805
17903
|
}
|
|
17806
17904
|
function resolverCommand(root) {
|
|
17807
|
-
return `node ${JSON.stringify((0,
|
|
17905
|
+
return `node ${JSON.stringify((0, import_node_path12.join)(root, "scripts", "verity.mjs"))}`;
|
|
17808
17906
|
}
|
|
17809
17907
|
|
|
17810
17908
|
// src/commands/hooks.ts
|
|
@@ -17940,18 +18038,18 @@ function registerHooksCommands(program2) {
|
|
|
17940
18038
|
}
|
|
17941
18039
|
|
|
17942
18040
|
// src/commands/intent.ts
|
|
17943
|
-
var
|
|
18041
|
+
var import_node_crypto10 = require("node:crypto");
|
|
17944
18042
|
|
|
17945
18043
|
// src/lib/conversation-buffer.ts
|
|
17946
18044
|
var import_promises5 = require("node:fs/promises");
|
|
17947
|
-
var
|
|
18045
|
+
var import_node_fs12 = require("node:fs");
|
|
17948
18046
|
var import_node_child_process6 = require("node:child_process");
|
|
17949
|
-
var
|
|
18047
|
+
var import_node_crypto2 = require("node:crypto");
|
|
17950
18048
|
function stripImageReferences(text) {
|
|
17951
18049
|
return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
|
|
17952
18050
|
}
|
|
17953
18051
|
function bufferTmpPath() {
|
|
17954
|
-
return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0,
|
|
18052
|
+
return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto2.randomBytes)(4).toString("hex")}.tmp`;
|
|
17955
18053
|
}
|
|
17956
18054
|
async function appendToConversationBuffer(prompt, sessionId) {
|
|
17957
18055
|
try {
|
|
@@ -17980,7 +18078,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
|
|
|
17980
18078
|
}
|
|
17981
18079
|
async function readAndClearConversationBuffer(currentSessionId) {
|
|
17982
18080
|
try {
|
|
17983
|
-
if ((0,
|
|
18081
|
+
if ((0, import_node_fs12.existsSync)(CONVERSATION_BUFFER_FILE)) {
|
|
17984
18082
|
const entries = await readBufferEntries();
|
|
17985
18083
|
let mine = entries;
|
|
17986
18084
|
let others = [];
|
|
@@ -18004,7 +18102,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
|
|
|
18004
18102
|
};
|
|
18005
18103
|
}
|
|
18006
18104
|
}
|
|
18007
|
-
if ((0,
|
|
18105
|
+
if ((0, import_node_fs12.existsSync)(INTENT_FILE)) {
|
|
18008
18106
|
try {
|
|
18009
18107
|
const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
|
|
18010
18108
|
await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
|
|
@@ -18295,83 +18393,6 @@ function isCommandOnlyTurn(input) {
|
|
|
18295
18393
|
return commands.every(isNonAuthoringCommand);
|
|
18296
18394
|
}
|
|
18297
18395
|
|
|
18298
|
-
// src/lib/context-identity.ts
|
|
18299
|
-
var import_node_crypto2 = require("node:crypto");
|
|
18300
|
-
var import_node_fs12 = require("node:fs");
|
|
18301
|
-
var import_node_os4 = require("node:os");
|
|
18302
|
-
var import_node_path12 = require("node:path");
|
|
18303
|
-
var SHARED_SENTINELS = /* @__PURE__ */ new Set([
|
|
18304
|
-
"",
|
|
18305
|
-
"-",
|
|
18306
|
-
"n/a",
|
|
18307
|
-
"na",
|
|
18308
|
-
"none",
|
|
18309
|
-
"null",
|
|
18310
|
-
"undefined",
|
|
18311
|
-
"unknown",
|
|
18312
|
-
"anon",
|
|
18313
|
-
"anonymous",
|
|
18314
|
-
"default",
|
|
18315
|
-
"_default"
|
|
18316
|
-
]);
|
|
18317
|
-
function isSharedSentinel(value) {
|
|
18318
|
-
if (value == null) return true;
|
|
18319
|
-
return SHARED_SENTINELS.has(value.trim().toLowerCase());
|
|
18320
|
-
}
|
|
18321
|
-
var ephemeral = /* @__PURE__ */ new Map();
|
|
18322
|
-
function ephemeralId(slot, width) {
|
|
18323
|
-
let id = ephemeral.get(slot);
|
|
18324
|
-
if (!id) {
|
|
18325
|
-
id = `eph-${(0, import_node_crypto2.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
|
|
18326
|
-
ephemeral.set(slot, id);
|
|
18327
|
-
}
|
|
18328
|
-
return id;
|
|
18329
|
-
}
|
|
18330
|
-
function contextIdentity(input) {
|
|
18331
|
-
const tokenUsable = !isSharedSentinel(input.token ?? null);
|
|
18332
|
-
const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
|
|
18333
|
-
const userKey = tokenUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
|
|
18334
|
-
const sessionKey2 = sessionUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
|
|
18335
|
-
let treeKey = "no-tree";
|
|
18336
|
-
const rawTree = input.treeRoot;
|
|
18337
|
-
if (rawTree && !isSharedSentinel(rawTree)) {
|
|
18338
|
-
let resolved = rawTree;
|
|
18339
|
-
try {
|
|
18340
|
-
resolved = import_node_fs12.realpathSync.native(rawTree);
|
|
18341
|
-
} catch {
|
|
18342
|
-
}
|
|
18343
|
-
treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
18344
|
-
}
|
|
18345
|
-
return {
|
|
18346
|
-
userKey,
|
|
18347
|
-
treeKey,
|
|
18348
|
-
sessionKey: sessionKey2,
|
|
18349
|
-
userKeySource: tokenUsable ? "token" : "ephemeral",
|
|
18350
|
-
sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
|
|
18351
|
-
ephemeral: !tokenUsable || !sessionUsable
|
|
18352
|
-
};
|
|
18353
|
-
}
|
|
18354
|
-
function verityHome() {
|
|
18355
|
-
const override = process.env.VERITY_HOME;
|
|
18356
|
-
return override && override.trim() ? (0, import_node_path12.resolve)(override) : (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity");
|
|
18357
|
-
}
|
|
18358
|
-
function dossierDir(identity) {
|
|
18359
|
-
return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
|
|
18360
|
-
}
|
|
18361
|
-
function treeDir(identity) {
|
|
18362
|
-
return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
|
|
18363
|
-
}
|
|
18364
|
-
function scopeIdentity(token, sessionId) {
|
|
18365
|
-
const t = (token ?? "").trim();
|
|
18366
|
-
const s = (sessionId ?? "").trim();
|
|
18367
|
-
const userKey = t.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
|
|
18368
|
-
const sessionKey2 = s.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
|
|
18369
|
-
return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
|
|
18370
|
-
}
|
|
18371
|
-
function sessionScopeKey(token, sessionId) {
|
|
18372
|
-
return scopeIdentity(token, sessionId).bucket;
|
|
18373
|
-
}
|
|
18374
|
-
|
|
18375
18396
|
// src/lib/task-context-buffer.ts
|
|
18376
18397
|
var import_promises6 = require("node:fs/promises");
|
|
18377
18398
|
var import_node_fs13 = require("node:fs");
|
|
@@ -19455,8 +19476,8 @@ function ensureVerityGitignore() {
|
|
|
19455
19476
|
}
|
|
19456
19477
|
let text = next.join("\n");
|
|
19457
19478
|
if (!hasMarker) {
|
|
19458
|
-
const
|
|
19459
|
-
text = text +
|
|
19479
|
+
const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
19480
|
+
text = text + sep6 + VERITY_GITIGNORE_BLOCK;
|
|
19460
19481
|
}
|
|
19461
19482
|
if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
|
|
19462
19483
|
return verified(
|
|
@@ -19486,8 +19507,8 @@ function writeFencedBlock() {
|
|
|
19486
19507
|
lines = fenceMemoryLines(lines);
|
|
19487
19508
|
let text = lines.join("\n");
|
|
19488
19509
|
if (!hasMarker) {
|
|
19489
|
-
const
|
|
19490
|
-
text = text +
|
|
19510
|
+
const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
19511
|
+
text = text + sep6 + VERITY_GITIGNORE_BLOCK;
|
|
19491
19512
|
}
|
|
19492
19513
|
try {
|
|
19493
19514
|
(0, import_node_fs19.writeFileSync)(".gitignore", text);
|
|
@@ -19537,8 +19558,8 @@ function keepMemoryTracked() {
|
|
|
19537
19558
|
}
|
|
19538
19559
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
19539
19560
|
try {
|
|
19540
|
-
const
|
|
19541
|
-
(0, import_node_fs19.writeFileSync)(".gitignore", content +
|
|
19561
|
+
const sep6 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
|
|
19562
|
+
(0, import_node_fs19.writeFileSync)(".gitignore", content + sep6 + MEMORY_OPT_OUT_STANZA);
|
|
19542
19563
|
} catch {
|
|
19543
19564
|
return "failed";
|
|
19544
19565
|
}
|
|
@@ -20076,9 +20097,16 @@ var CLAUDE_MD_PROSE = [
|
|
|
20076
20097
|
"Then record it straight away. There is no confirm step, in any environment:",
|
|
20077
20098
|
"",
|
|
20078
20099
|
"```bash",
|
|
20079
|
-
|
|
20100
|
+
"verity reflect --user-input - --kind <kind> <<'VERITY_EOF_<random>'",
|
|
20101
|
+
"<your draft>",
|
|
20102
|
+
"VERITY_EOF_<random>",
|
|
20080
20103
|
"```",
|
|
20081
20104
|
"",
|
|
20105
|
+
'The draft goes through the quoted heredoc, never inside `"\u2026"` on the command',
|
|
20106
|
+
'line, where a `"` or `$(\u2026)` in it would run in the shell. Replace `<random>`',
|
|
20107
|
+
"with 8 random letters and digits that you pick for this call, the same at both",
|
|
20108
|
+
"ends. Text written before you picked them cannot end the heredoc early.",
|
|
20109
|
+
"",
|
|
20082
20110
|
"Add `--confirmed` ONLY when the user authored or dictated the words. Without",
|
|
20083
20111
|
"it the node is stored as `source: agent` \u2014 Verity thought this, nobody checked",
|
|
20084
20112
|
"it. With it, `source: user` at full confidence \u2014 a person stands behind this.",
|
|
@@ -20087,7 +20115,7 @@ var CLAUDE_MD_PROSE = [
|
|
|
20087
20115
|
"**Name the files in the text.** Verity scopes the reflection to the paths it",
|
|
20088
20116
|
"cites, and a reflection that names no file in this repo is never retrieved for",
|
|
20089
20117
|
"a later review \u2014 it is recorded and then invisible. The command says so when it",
|
|
20090
|
-
|
|
20118
|
+
"happens; `--file-globs '<path or glob>'` is the fix when the prose cannot carry",
|
|
20091
20119
|
"the paths.",
|
|
20092
20120
|
"",
|
|
20093
20121
|
"Then tell the user, in one line, what you recorded and where: the command",
|
|
@@ -20120,7 +20148,7 @@ var CLAUDE_MD_PROSE = [
|
|
|
20120
20148
|
"a finding. Declarations are budgeted per session and every one is recorded with",
|
|
20121
20149
|
"its reason."
|
|
20122
20150
|
].join("\n");
|
|
20123
|
-
var
|
|
20151
|
+
var CLAUDE_MD_PROSE_PRE_STDIN = [
|
|
20124
20152
|
"## Project Memory",
|
|
20125
20153
|
"",
|
|
20126
20154
|
"This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
|
|
@@ -20131,6 +20159,11 @@ var CLAUDE_MD_PROSE_PRE_ORG = [
|
|
|
20131
20159
|
"The graph is auto-maintained by Verity. Files at `.verity/memory/_archive/` are",
|
|
20132
20160
|
"superseded \u2014 ignore them unless investigating history.",
|
|
20133
20161
|
"",
|
|
20162
|
+
"Knowledge the organization's other repositories learned is mirrored outside the",
|
|
20163
|
+
"repo at `~/.verity/orgs/<host>/<owner>/memory/` (`verity memory org` lists it).",
|
|
20164
|
+
"Each claim says where it came from; one that is wrong here is demoted for",
|
|
20165
|
+
'everyone with `verity memory demote <id> --reason "\u2026"`.',
|
|
20166
|
+
"",
|
|
20134
20167
|
"## Quality gate: accepted risks",
|
|
20135
20168
|
"",
|
|
20136
20169
|
"When the Verity pre-commit/pre-push gate FAILs, fix the findings \u2014 that is the",
|
|
@@ -20199,7 +20232,7 @@ var CLAUDE_MD_PROSE_PRE_ORG = [
|
|
|
20199
20232
|
"a finding. Declarations are budgeted per session and every one is recorded with",
|
|
20200
20233
|
"its reason."
|
|
20201
20234
|
].join("\n");
|
|
20202
|
-
var
|
|
20235
|
+
var CLAUDE_MD_PROSE_PRE_ORG = [
|
|
20203
20236
|
"## Project Memory",
|
|
20204
20237
|
"",
|
|
20205
20238
|
"This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
|
|
@@ -20225,22 +20258,33 @@ var CLAUDE_MD_PROSE_PRE_AUTORECORD = [
|
|
|
20225
20258
|
"## Post-task reflection",
|
|
20226
20259
|
"",
|
|
20227
20260
|
`When a task is complete (you've created a PR, the user says "done" or "ship it",`,
|
|
20228
|
-
"or the work is clearly finished), **draft the reflection yourself
|
|
20261
|
+
"or the work is clearly finished), **draft the reflection yourself** \u2014 1\u20133",
|
|
20229
20262
|
"concrete things worth remembering (a decision, a gotcha, or a pattern), each",
|
|
20230
20263
|
"cited with the files / PR / commands / error-signatures it came from. Skip",
|
|
20231
|
-
"entirely if nothing non-obvious happened
|
|
20264
|
+
"entirely if nothing non-obvious happened \u2014 that judgement is the ONLY filter,",
|
|
20265
|
+
"because nothing reviews the reflection before it lands.",
|
|
20232
20266
|
"",
|
|
20233
|
-
"Then
|
|
20267
|
+
"Then record it straight away. There is no confirm step, in any environment:",
|
|
20234
20268
|
"",
|
|
20235
|
-
"
|
|
20236
|
-
|
|
20237
|
-
"
|
|
20238
|
-
|
|
20239
|
-
|
|
20240
|
-
|
|
20241
|
-
"
|
|
20242
|
-
|
|
20243
|
-
"
|
|
20269
|
+
"```bash",
|
|
20270
|
+
'verity reflect --user-input "<your draft>" --kind <kind>',
|
|
20271
|
+
"```",
|
|
20272
|
+
"",
|
|
20273
|
+
"Add `--confirmed` ONLY when the user authored or dictated the words. Without",
|
|
20274
|
+
"it the node is stored as `source: agent` \u2014 Verity thought this, nobody checked",
|
|
20275
|
+
"it. With it, `source: user` at full confidence \u2014 a person stands behind this.",
|
|
20276
|
+
"Never claim the second for your own draft, however good it is.",
|
|
20277
|
+
"",
|
|
20278
|
+
"**Name the files in the text.** Verity scopes the reflection to the paths it",
|
|
20279
|
+
"cites, and a reflection that names no file in this repo is never retrieved for",
|
|
20280
|
+
"a later review \u2014 it is recorded and then invisible. The command says so when it",
|
|
20281
|
+
'happens; `--file-globs "<path or glob>"` is the fix when the prose cannot carry',
|
|
20282
|
+
"the paths.",
|
|
20283
|
+
"",
|
|
20284
|
+
"Then tell the user, in one line, what you recorded and where: the command",
|
|
20285
|
+
"prints the node id, the path under `.verity/memory/`, and a dashboard link.",
|
|
20286
|
+
"They did not agree to it in advance, so say it happened \u2014 editing or deleting",
|
|
20287
|
+
"that file is how they correct it.",
|
|
20244
20288
|
"",
|
|
20245
20289
|
"> Durable, hand-curated guidance goes in the preserve region below (it survives",
|
|
20246
20290
|
"> regeneration) or anywhere OUTSIDE these markers. Everything else between the",
|
|
@@ -20267,7 +20311,75 @@ var CLAUDE_MD_PROSE_PRE_AUTORECORD = [
|
|
|
20267
20311
|
"a finding. Declarations are budgeted per session and every one is recorded with",
|
|
20268
20312
|
"its reason."
|
|
20269
20313
|
].join("\n");
|
|
20270
|
-
var
|
|
20314
|
+
var CLAUDE_MD_PROSE_PRE_AUTORECORD = [
|
|
20315
|
+
"## Project Memory",
|
|
20316
|
+
"",
|
|
20317
|
+
"This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
|
|
20318
|
+
"non-trivial work, scan `.verity/memory/index.md` for decisions, gotchas, and patterns",
|
|
20319
|
+
"that may apply to the change you are about to make. Open specific node files via",
|
|
20320
|
+
"the Read tool when the title or scope suggests relevance.",
|
|
20321
|
+
"",
|
|
20322
|
+
"The graph is auto-maintained by Verity. Files at `.verity/memory/_archive/` are",
|
|
20323
|
+
"superseded \u2014 ignore them unless investigating history.",
|
|
20324
|
+
"",
|
|
20325
|
+
"## Quality gate: accepted risks",
|
|
20326
|
+
"",
|
|
20327
|
+
"When the Verity pre-commit/pre-push gate FAILs, fix the findings \u2014 that is the",
|
|
20328
|
+
'default. Use `verity waive <pattern-id> --file <path> --reason "\u2026"` ONLY to relay',
|
|
20329
|
+
"a risk a human has explicitly accepted: a named code-review finding, an ADR, or",
|
|
20330
|
+
"the user saying so in this conversation. The --reason must cite that source.",
|
|
20331
|
+
"",
|
|
20332
|
+
"Never waive on your own judgment, to get past a block, or pre-emptively. A waive",
|
|
20333
|
+
"binds to the file's current bytes and voids automatically when the file changes,",
|
|
20334
|
+
"and every waive is recorded in the run ledger. For a pattern-level false positive",
|
|
20335
|
+
"use `verity feedback finding <run-id> <pattern-id> false_positive` instead.",
|
|
20336
|
+
"",
|
|
20337
|
+
"## Post-task reflection",
|
|
20338
|
+
"",
|
|
20339
|
+
`When a task is complete (you've created a PR, the user says "done" or "ship it",`,
|
|
20340
|
+
"or the work is clearly finished), **draft the reflection yourself first** \u2014 1\u20133",
|
|
20341
|
+
"concrete things worth remembering (a decision, a gotcha, or a pattern), each",
|
|
20342
|
+
"cited with the files / PR / commands / error-signatures it came from. Skip",
|
|
20343
|
+
"entirely if nothing non-obvious happened.",
|
|
20344
|
+
"",
|
|
20345
|
+
"Then, depending on how the session is running:",
|
|
20346
|
+
"",
|
|
20347
|
+
"- **Interactive** (a person is at the keyboard): show your draft and ask one",
|
|
20348
|
+
` question before recording \u2014 "Here's my reflection draft for the project`,
|
|
20349
|
+
" memory: <draft>. Anything to confirm, correct, or add before I record it?",
|
|
20350
|
+
` (Say 'skip' to drop it.)" Record the final text (with their corrections) via`,
|
|
20351
|
+
' `verity reflect --user-input "<final reflection>" --kind <kind>`. If they say',
|
|
20352
|
+
' "skip", do not record.',
|
|
20353
|
+
"- **Autonomous** (headless / CI / cron, or `VERITY_AUTONOMOUS=1`): record your",
|
|
20354
|
+
' draft directly, never blocking \u2014 `verity reflect --user-input "<your draft>"',
|
|
20355
|
+
" --kind <kind> --autonomous`.",
|
|
20356
|
+
"",
|
|
20357
|
+
"> Durable, hand-curated guidance goes in the preserve region below (it survives",
|
|
20358
|
+
"> regeneration) or anywhere OUTSIDE these markers. Everything else between the",
|
|
20359
|
+
"> markers is tool-owned and overwritten on each run.",
|
|
20360
|
+
"",
|
|
20361
|
+
"## Housekeeping Turns",
|
|
20362
|
+
"",
|
|
20363
|
+
"When a turn will be pure housekeeping \u2014 pulling, installing dependencies,",
|
|
20364
|
+
"rebasing, a formatting sweep you are not authoring \u2014 declare it BEFORE doing it:",
|
|
20365
|
+
"",
|
|
20366
|
+
"```bash",
|
|
20367
|
+
'verity ignore --turn --agent --reason "pulling latest before starting"',
|
|
20368
|
+
"```",
|
|
20369
|
+
"",
|
|
20370
|
+
"This skips the review for that turn, which saves the turn Verity would",
|
|
20371
|
+
"otherwise spend saying it had nothing to say. Use `--for 30m` instead of",
|
|
20372
|
+
"`--turn` when a single piece of housekeeping spans several turns.",
|
|
20373
|
+
"",
|
|
20374
|
+
"**It is a claim about the turn, not a way to silence review.** The declaration",
|
|
20375
|
+
"is checked against what the turn actually did: if anything is authored \u2014 by you,",
|
|
20376
|
+
"by a subagent, or by a shell command that can write files \u2014 it voids, the review",
|
|
20377
|
+
"runs anyway, and the broken declaration is reported. So declare housekeeping you",
|
|
20378
|
+
"are about to do, never work you have already done, and never as a way to get past",
|
|
20379
|
+
"a finding. Declarations are budgeted per session and every one is recorded with",
|
|
20380
|
+
"its reason."
|
|
20381
|
+
].join("\n");
|
|
20382
|
+
var CLAUDE_MD_PROSE_PRE_REFLECT = [
|
|
20271
20383
|
"## Project Memory",
|
|
20272
20384
|
"",
|
|
20273
20385
|
"This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
|
|
@@ -20478,6 +20590,7 @@ function stripKnownProse(interior) {
|
|
|
20478
20590
|
const trimmed = interior.replace(/^\n+/, "");
|
|
20479
20591
|
for (const prose of [
|
|
20480
20592
|
CLAUDE_MD_PROSE,
|
|
20593
|
+
CLAUDE_MD_PROSE_PRE_STDIN,
|
|
20481
20594
|
CLAUDE_MD_PROSE_PRE_ORG,
|
|
20482
20595
|
CLAUDE_MD_PROSE_PRE_AUTORECORD,
|
|
20483
20596
|
CLAUDE_MD_PROSE_PRE_REFLECT,
|
|
@@ -20544,7 +20657,7 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
|
|
|
20544
20657
|
|
|
20545
20658
|
// src/lib/dossier-session.ts
|
|
20546
20659
|
var import_node_fs26 = require("node:fs");
|
|
20547
|
-
var
|
|
20660
|
+
var import_node_crypto9 = require("node:crypto");
|
|
20548
20661
|
var import_node_path22 = require("node:path");
|
|
20549
20662
|
|
|
20550
20663
|
// src/lib/pending-repeat.ts
|
|
@@ -20621,6 +20734,7 @@ function isRepeatOfAny(text, priorFingerprints, threshold = REPEAT_THRESHOLD) {
|
|
|
20621
20734
|
}
|
|
20622
20735
|
|
|
20623
20736
|
// src/lib/dossier/bounds.ts
|
|
20737
|
+
var import_node_crypto5 = require("node:crypto");
|
|
20624
20738
|
var MAX_LINE_BYTES = 4096;
|
|
20625
20739
|
var MAX_GOAL_CHARS = 2e3;
|
|
20626
20740
|
var GOAL_KEEP = 8;
|
|
@@ -20632,10 +20746,17 @@ var NOT_MINE_CAP = 300;
|
|
|
20632
20746
|
var STATEMENTS_OPEN_CAP = 40;
|
|
20633
20747
|
var COMMANDS_CAP = 12;
|
|
20634
20748
|
var DIVERGENCE_CAP = 10;
|
|
20635
|
-
var
|
|
20749
|
+
var DIVERGENCE_BULK_AT = 300;
|
|
20750
|
+
var DIVERGENCE_KEYS_PER_LINE = 200;
|
|
20636
20751
|
function divergenceKey(path, hash) {
|
|
20637
20752
|
return `${path}@${hash ?? "unknown"}`;
|
|
20638
20753
|
}
|
|
20754
|
+
function packedDivergenceDigest(key) {
|
|
20755
|
+
return (0, import_node_crypto5.createHash)("sha256").update(key).digest("hex").slice(0, 12);
|
|
20756
|
+
}
|
|
20757
|
+
function packedDivergenceKey(digest) {
|
|
20758
|
+
return `#${digest}`;
|
|
20759
|
+
}
|
|
20639
20760
|
var MARKS_CAP = 50;
|
|
20640
20761
|
var ROTATE_BYTES = 1048576;
|
|
20641
20762
|
var ROTATE_KEEP = 2;
|
|
@@ -20649,7 +20770,7 @@ function statementAnchorKey(file, patternId) {
|
|
|
20649
20770
|
}
|
|
20650
20771
|
|
|
20651
20772
|
// src/lib/dossier/log.ts
|
|
20652
|
-
var
|
|
20773
|
+
var import_node_crypto6 = require("node:crypto");
|
|
20653
20774
|
var import_node_fs22 = require("node:fs");
|
|
20654
20775
|
var import_node_path20 = require("node:path");
|
|
20655
20776
|
var CRC_TABLE = (() => {
|
|
@@ -20691,7 +20812,7 @@ function nextSeq() {
|
|
|
20691
20812
|
function encodeEvent(ev) {
|
|
20692
20813
|
const full = {
|
|
20693
20814
|
v: 1,
|
|
20694
|
-
id: (0,
|
|
20815
|
+
id: (0, import_node_crypto6.randomBytes)(4).toString("hex"),
|
|
20695
20816
|
...ev
|
|
20696
20817
|
};
|
|
20697
20818
|
let body2 = JSON.stringify(full);
|
|
@@ -20762,7 +20883,7 @@ function rotateIfNeeded2(d) {
|
|
|
20762
20883
|
}
|
|
20763
20884
|
|
|
20764
20885
|
// src/lib/dossier/fold-dossier.ts
|
|
20765
|
-
var
|
|
20886
|
+
var import_node_crypto7 = require("node:crypto");
|
|
20766
20887
|
var import_node_fs23 = require("node:fs");
|
|
20767
20888
|
var import_node_path21 = require("node:path");
|
|
20768
20889
|
var EMPTY_CAPABILITIES = () => ({
|
|
@@ -20854,7 +20975,7 @@ function reduce(state, events, now) {
|
|
|
20854
20975
|
state.meta.seq = Math.max(state.meta.seq, ev.seq);
|
|
20855
20976
|
switch (ev.k) {
|
|
20856
20977
|
case "goal": {
|
|
20857
|
-
const hash = (0,
|
|
20978
|
+
const hash = (0, import_node_crypto7.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
|
|
20858
20979
|
const prev = state.goal[state.goal.length - 1];
|
|
20859
20980
|
if (prev && prev.hash === hash) {
|
|
20860
20981
|
prev.repeats = (prev.repeats ?? 0) + 1;
|
|
@@ -20982,12 +21103,13 @@ function reduce(state, events, now) {
|
|
|
20982
21103
|
break;
|
|
20983
21104
|
}
|
|
20984
21105
|
case "divergence": {
|
|
20985
|
-
state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
|
|
20986
21106
|
state.divergence.events.push({ kind: ev.kind, path: ev.path, at: ev.at });
|
|
20987
|
-
const
|
|
20988
|
-
|
|
21107
|
+
const keys = Array.isArray(ev.keys) ? ev.keys.filter((k) => typeof k === "string").map(packedDivergenceKey) : [divergenceKey(ev.path, ev.hash ?? null)];
|
|
21108
|
+
for (const key of keys) {
|
|
21109
|
+
if (seenDivergence.has(key)) continue;
|
|
20989
21110
|
seenDivergence.add(key);
|
|
20990
|
-
|
|
21111
|
+
state.divergence.seen.push(key);
|
|
21112
|
+
state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
|
|
20991
21113
|
}
|
|
20992
21114
|
break;
|
|
20993
21115
|
}
|
|
@@ -21294,14 +21416,14 @@ function assessContinuity(i2) {
|
|
|
21294
21416
|
}
|
|
21295
21417
|
|
|
21296
21418
|
// src/lib/dossier/reanchor.ts
|
|
21297
|
-
var
|
|
21419
|
+
var import_node_crypto8 = require("node:crypto");
|
|
21298
21420
|
var import_node_fs25 = require("node:fs");
|
|
21299
21421
|
function lineSha(text) {
|
|
21300
|
-
return (0,
|
|
21422
|
+
return (0, import_node_crypto8.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
21301
21423
|
}
|
|
21302
21424
|
function fileHash(path) {
|
|
21303
21425
|
try {
|
|
21304
|
-
return (0,
|
|
21426
|
+
return (0, import_node_crypto8.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
|
|
21305
21427
|
} catch {
|
|
21306
21428
|
return null;
|
|
21307
21429
|
}
|
|
@@ -21798,7 +21920,7 @@ function recordTurn(d, t) {
|
|
|
21798
21920
|
// Identity is the COMMAND, not its category — otherwise `npm test -- a` and
|
|
21799
21921
|
// `npm test -- b` are one row and the streak counts two different commands
|
|
21800
21922
|
// as a run of one.
|
|
21801
|
-
cmd_hash: (0,
|
|
21923
|
+
cmd_hash: (0, import_node_crypto9.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
|
|
21802
21924
|
head: c.head || c.class,
|
|
21803
21925
|
status: toStatus(c.last_status)
|
|
21804
21926
|
});
|
|
@@ -21816,10 +21938,23 @@ function recordTurn(d, t) {
|
|
|
21816
21938
|
}
|
|
21817
21939
|
}
|
|
21818
21940
|
const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
|
|
21941
|
+
const fresh = [];
|
|
21819
21942
|
for (const u of t.unobserved) {
|
|
21820
21943
|
const hash = fileHash((0, import_node_path22.join)(root, u.p));
|
|
21821
|
-
|
|
21822
|
-
|
|
21944
|
+
const key = divergenceKey(u.p, hash);
|
|
21945
|
+
const digest = packedDivergenceDigest(key);
|
|
21946
|
+
if (seenDivergence.has(key) || seenDivergence.has(packedDivergenceKey(digest))) continue;
|
|
21947
|
+
fresh.push({ path: u.p, hash, digest });
|
|
21948
|
+
}
|
|
21949
|
+
if (fresh.length > DIVERGENCE_BULK_AT) {
|
|
21950
|
+
for (let i2 = 0; i2 < fresh.length; i2 += DIVERGENCE_KEYS_PER_LINE) {
|
|
21951
|
+
const slice2 = fresh.slice(i2, i2 + DIVERGENCE_KEYS_PER_LINE);
|
|
21952
|
+
appendEvent(d, { k: "divergence", kind: "external_mutation", path: slice2[0].path, keys: slice2.map((f) => f.digest) });
|
|
21953
|
+
}
|
|
21954
|
+
} else {
|
|
21955
|
+
for (const f of fresh) {
|
|
21956
|
+
appendEvent(d, { k: "divergence", kind: "external_mutation", path: f.path, hash: f.hash });
|
|
21957
|
+
}
|
|
21823
21958
|
}
|
|
21824
21959
|
const newCompactions = (t.compactions ?? 0) - (t.known?.compactions ?? 0);
|
|
21825
21960
|
for (let i2 = 0; i2 < newCompactions; i2++) {
|
|
@@ -22084,7 +22219,7 @@ async function fireClassify(prompt, sessionId, globals) {
|
|
|
22084
22219
|
logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
|
|
22085
22220
|
return;
|
|
22086
22221
|
}
|
|
22087
|
-
const promptHash = (0,
|
|
22222
|
+
const promptHash = (0, import_node_crypto10.createHash)("sha256").update(prompt).digest("hex");
|
|
22088
22223
|
const result = await apiRequest({
|
|
22089
22224
|
method: "POST",
|
|
22090
22225
|
path: "/classify-task",
|
|
@@ -22128,7 +22263,7 @@ var import_node_path26 = require("node:path");
|
|
|
22128
22263
|
// src/lib/baseline.ts
|
|
22129
22264
|
var import_node_fs28 = require("node:fs");
|
|
22130
22265
|
var import_node_path25 = require("node:path");
|
|
22131
|
-
var
|
|
22266
|
+
var import_node_crypto11 = require("node:crypto");
|
|
22132
22267
|
|
|
22133
22268
|
// src/lib/snapshot.ts
|
|
22134
22269
|
var import_node_fs27 = require("node:fs");
|
|
@@ -22397,7 +22532,7 @@ var MIRROR_MAX_BYTES = 2 * 1024 * 1024;
|
|
|
22397
22532
|
var DEFAULT_SESSION_KEY = "_default";
|
|
22398
22533
|
function sessionKey(sessionId) {
|
|
22399
22534
|
if (!sessionId) return DEFAULT_SESSION_KEY;
|
|
22400
|
-
return (0,
|
|
22535
|
+
return (0, import_node_crypto11.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
22401
22536
|
}
|
|
22402
22537
|
function sessionDir(key) {
|
|
22403
22538
|
return (0, import_node_path25.join)(projectPath(BASELINE_DIR), key);
|
|
@@ -22859,17 +22994,17 @@ async function readHookStdin() {
|
|
|
22859
22994
|
try {
|
|
22860
22995
|
if (process.stdin.isTTY) return {};
|
|
22861
22996
|
const chunks = [];
|
|
22862
|
-
const timeout = new Promise((
|
|
22863
|
-
const read2 = new Promise((
|
|
22997
|
+
const timeout = new Promise((resolve9) => setTimeout(() => resolve9({}), 500));
|
|
22998
|
+
const read2 = new Promise((resolve9) => {
|
|
22864
22999
|
process.stdin.on("data", (c) => chunks.push(c));
|
|
22865
23000
|
process.stdin.on("end", () => {
|
|
22866
23001
|
try {
|
|
22867
|
-
|
|
23002
|
+
resolve9(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
|
|
22868
23003
|
} catch {
|
|
22869
|
-
|
|
23004
|
+
resolve9({});
|
|
22870
23005
|
}
|
|
22871
23006
|
});
|
|
22872
|
-
process.stdin.on("error", () =>
|
|
23007
|
+
process.stdin.on("error", () => resolve9({}));
|
|
22873
23008
|
process.stdin.resume();
|
|
22874
23009
|
});
|
|
22875
23010
|
return await Promise.race([read2, timeout]);
|
|
@@ -22929,6 +23064,41 @@ function setupDataPath(file) {
|
|
|
22929
23064
|
var import_node_child_process9 = require("node:child_process");
|
|
22930
23065
|
var import_node_fs31 = require("node:fs");
|
|
22931
23066
|
var import_node_path28 = require("node:path");
|
|
23067
|
+
|
|
23068
|
+
// src/lib/self-scope.ts
|
|
23069
|
+
var LEGACY_GATE_SKILLS = /* @__PURE__ */ new Set([
|
|
23070
|
+
"gate-setup",
|
|
23071
|
+
"gate-analyze",
|
|
23072
|
+
"gate-review",
|
|
23073
|
+
"gate-status",
|
|
23074
|
+
"gate-feedback",
|
|
23075
|
+
"gate-insights",
|
|
23076
|
+
"gate-learn",
|
|
23077
|
+
"gate-memory",
|
|
23078
|
+
"gate-reflect"
|
|
23079
|
+
]);
|
|
23080
|
+
function isVerityOwned(path) {
|
|
23081
|
+
const segments = path.replace(/\\/g, "/").split("/");
|
|
23082
|
+
for (let i2 = 0; i2 < segments.length; i2++) {
|
|
23083
|
+
const seg = segments[i2];
|
|
23084
|
+
if (seg === ".verity" || seg === ".codacy") return true;
|
|
23085
|
+
if (i2 === segments.length - 1 && (seg === "VERITY.md" || seg === "GATE.md")) return true;
|
|
23086
|
+
if (seg === ".claude" && segments[i2 + 1] === "skills" && typeof segments[i2 + 2] === "string") {
|
|
23087
|
+
const skill = segments[i2 + 2];
|
|
23088
|
+
if (skill.startsWith("verity-") || LEGACY_GATE_SKILLS.has(skill)) return true;
|
|
23089
|
+
}
|
|
23090
|
+
if (seg === ".claude" && segments[i2 + 1] === "settings.json") return true;
|
|
23091
|
+
}
|
|
23092
|
+
return false;
|
|
23093
|
+
}
|
|
23094
|
+
function partitionVerityOwned(paths) {
|
|
23095
|
+
const kept = [];
|
|
23096
|
+
const owned = [];
|
|
23097
|
+
for (const p of paths) (isVerityOwned(p) ? owned : kept).push(p);
|
|
23098
|
+
return { kept, owned };
|
|
23099
|
+
}
|
|
23100
|
+
|
|
23101
|
+
// src/lib/detect.ts
|
|
22932
23102
|
var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
|
|
22933
23103
|
"typescript",
|
|
22934
23104
|
"javascript",
|
|
@@ -22963,19 +23133,22 @@ function isIgnored2(path) {
|
|
|
22963
23133
|
const parts2 = path.split("/");
|
|
22964
23134
|
return parts2.some((p) => IGNORED_SEGMENTS.includes(p));
|
|
22965
23135
|
}
|
|
23136
|
+
function isProjectFile(path) {
|
|
23137
|
+
return !isIgnored2(path) && !isVerityOwned(path);
|
|
23138
|
+
}
|
|
22966
23139
|
function listProjectFiles(root) {
|
|
22967
23140
|
try {
|
|
22968
|
-
const out2 = (0, import_node_child_process9.execSync)("git ls-files -z", {
|
|
23141
|
+
const out2 = (0, import_node_child_process9.execSync)("git ls-files -z --cached --others --exclude-standard", {
|
|
22969
23142
|
cwd: root,
|
|
22970
23143
|
encoding: "utf-8",
|
|
22971
23144
|
maxBuffer: 32 * 1024 * 1024,
|
|
22972
23145
|
stdio: ["pipe", "pipe", "pipe"]
|
|
22973
23146
|
});
|
|
22974
|
-
const tracked = out2.split("\0").filter(Boolean).filter(
|
|
23147
|
+
const tracked = out2.split("\0").filter(Boolean).filter(isProjectFile);
|
|
22975
23148
|
if (tracked.length > 0) return tracked;
|
|
22976
23149
|
} catch {
|
|
22977
23150
|
}
|
|
22978
|
-
return walk(root);
|
|
23151
|
+
return walk(root).filter(isProjectFile);
|
|
22979
23152
|
}
|
|
22980
23153
|
var WALK_MAX_FILES = 2e4;
|
|
22981
23154
|
var WALK_MAX_DEPTH = 8;
|
|
@@ -24317,10 +24490,10 @@ var import_node_fs38 = require("node:fs");
|
|
|
24317
24490
|
|
|
24318
24491
|
// src/lib/debounce.ts
|
|
24319
24492
|
var import_node_fs37 = require("node:fs");
|
|
24320
|
-
var
|
|
24493
|
+
var import_node_crypto12 = require("node:crypto");
|
|
24321
24494
|
function scopedFile(base, sessionId) {
|
|
24322
24495
|
if (!sessionId) return base;
|
|
24323
|
-
return `${base}.${(0,
|
|
24496
|
+
return `${base}.${(0, import_node_crypto12.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
|
|
24324
24497
|
}
|
|
24325
24498
|
function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
|
|
24326
24499
|
const file = scopedFile(DEBOUNCE_FILE, sessionId);
|
|
@@ -24361,7 +24534,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
|
|
|
24361
24534
|
return "No files modified since last analysis";
|
|
24362
24535
|
}
|
|
24363
24536
|
function computeContentHash(files) {
|
|
24364
|
-
const hash = (0,
|
|
24537
|
+
const hash = (0, import_node_crypto12.createHash)("sha1");
|
|
24365
24538
|
const sorted = [...files].sort();
|
|
24366
24539
|
for (const f of sorted) {
|
|
24367
24540
|
const resolved = resolveFile(f) ?? f;
|
|
@@ -24817,20 +24990,56 @@ function registerStatusCommand(program2) {
|
|
|
24817
24990
|
});
|
|
24818
24991
|
}
|
|
24819
24992
|
|
|
24993
|
+
// src/lib/text-input.ts
|
|
24994
|
+
var import_node_fs39 = require("node:fs");
|
|
24995
|
+
var MAX_STDIN_BYTES = 64 * 1024;
|
|
24996
|
+
function readTextInput(value, flag, readStdin2 = () => (0, import_node_fs39.readFileSync)(0)) {
|
|
24997
|
+
if (value !== "-") return { ok: true, text: value };
|
|
24998
|
+
let raw;
|
|
24999
|
+
try {
|
|
25000
|
+
raw = readStdin2();
|
|
25001
|
+
} catch (err2) {
|
|
25002
|
+
return { ok: false, error: `Could not read ${flag} from stdin: ${err2.message}` };
|
|
25003
|
+
}
|
|
25004
|
+
if (raw.length > MAX_STDIN_BYTES) {
|
|
25005
|
+
return { ok: false, error: `${flag} from stdin is ${raw.length} bytes; the limit is ${MAX_STDIN_BYTES}.` };
|
|
25006
|
+
}
|
|
25007
|
+
const text = raw.toString("utf8").replace(/\r?\n$/, "");
|
|
25008
|
+
if (!text.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
|
|
25009
|
+
return { ok: true, text };
|
|
25010
|
+
}
|
|
25011
|
+
|
|
25012
|
+
// src/lib/terminal-text.ts
|
|
25013
|
+
var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
|
|
25014
|
+
function terminalText(value, max = 4e3) {
|
|
25015
|
+
if (typeof value !== "string") return "";
|
|
25016
|
+
const clean2 = value.replace(CONTROL, "");
|
|
25017
|
+
return clean2.length > max ? `${clean2.slice(0, max - 1)}\u2026` : clean2;
|
|
25018
|
+
}
|
|
25019
|
+
function terminalUrl(value) {
|
|
25020
|
+
const clean2 = terminalText(value, 2e3);
|
|
25021
|
+
return /^https?:\/\/\S+$/.test(clean2) ? clean2 : "";
|
|
25022
|
+
}
|
|
25023
|
+
|
|
24820
25024
|
// src/commands/feedback.ts
|
|
24821
25025
|
function registerFeedbackCommand(program2) {
|
|
24822
25026
|
const feedbackCmd = program2.command("feedback").description("Send feedback to the Verity team");
|
|
24823
|
-
feedbackCmd.command("message <text>").description("Send general feedback").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (
|
|
24824
|
-
|
|
24825
|
-
await sendGeneralFeedback(message, opts, globals);
|
|
25027
|
+
feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text, opts) => {
|
|
25028
|
+
await sendMessageArg(text, opts, program2.opts());
|
|
24826
25029
|
});
|
|
24827
|
-
feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.)").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action,
|
|
25030
|
+
feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.); a note of - is read from stdin").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action, inlineNote, opts) => {
|
|
24828
25031
|
const globals = program2.opts();
|
|
24829
25032
|
const validActions = ["false_positive", "acknowledged", "will_fix_later", "wrong_severity", "useful"];
|
|
24830
25033
|
if (!validActions.includes(action)) {
|
|
24831
25034
|
printError(`Invalid action "${action}". Must be one of: ${validActions.join(", ")}`);
|
|
24832
25035
|
process.exit(1);
|
|
24833
25036
|
}
|
|
25037
|
+
const noteInput = readTextInput(inlineNote, "the note");
|
|
25038
|
+
if (!noteInput.ok) {
|
|
25039
|
+
printError(noteInput.error);
|
|
25040
|
+
process.exit(1);
|
|
25041
|
+
}
|
|
25042
|
+
const note = noteInput.text;
|
|
24834
25043
|
const tokenResult = await resolveToken(globals.token);
|
|
24835
25044
|
if (!tokenResult.ok) {
|
|
24836
25045
|
printError(tokenResult.error);
|
|
@@ -24866,21 +25075,28 @@ function registerFeedbackCommand(program2) {
|
|
|
24866
25075
|
});
|
|
24867
25076
|
feedbackCmd.argument("[message]", "Feedback message (for backwards compat)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (message, opts) => {
|
|
24868
25077
|
if (!message) return;
|
|
24869
|
-
|
|
24870
|
-
await sendGeneralFeedback(message, opts, globals);
|
|
25078
|
+
await sendMessageArg(message, opts, program2.opts());
|
|
24871
25079
|
});
|
|
24872
25080
|
}
|
|
25081
|
+
async function sendMessageArg(arg, opts, globals) {
|
|
25082
|
+
const input = readTextInput(arg, "the message");
|
|
25083
|
+
if (!input.ok || !input.text) {
|
|
25084
|
+
printError(input.ok ? "Nothing to send." : input.error);
|
|
25085
|
+
process.exit(1);
|
|
25086
|
+
}
|
|
25087
|
+
await sendGeneralFeedback(input.text, opts, globals);
|
|
25088
|
+
}
|
|
24873
25089
|
async function sendGeneralFeedback(message, opts, globals) {
|
|
24874
25090
|
const tokenResult = await resolveToken(globals.token);
|
|
24875
25091
|
if (!tokenResult.ok) {
|
|
24876
25092
|
printError(tokenResult.error);
|
|
24877
|
-
printInfo(`Your message: ${message}`);
|
|
25093
|
+
printInfo(`Your message: ${terminalText(message, message.length)}`);
|
|
24878
25094
|
process.exit(1);
|
|
24879
25095
|
}
|
|
24880
25096
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
24881
25097
|
if (!urlResult.ok) {
|
|
24882
25098
|
printError(urlResult.error);
|
|
24883
|
-
printInfo(`Your message: ${message}`);
|
|
25099
|
+
printInfo(`Your message: ${terminalText(message, message.length)}`);
|
|
24884
25100
|
process.exit(1);
|
|
24885
25101
|
}
|
|
24886
25102
|
const body2 = { message };
|
|
@@ -24898,7 +25114,7 @@ async function sendGeneralFeedback(message, opts, globals) {
|
|
|
24898
25114
|
});
|
|
24899
25115
|
if (!result.ok) {
|
|
24900
25116
|
printError(`Couldn't send feedback: ${result.error}`);
|
|
24901
|
-
printInfo(`Your message: ${message}`);
|
|
25117
|
+
printInfo(`Your message: ${terminalText(message, message.length)}`);
|
|
24902
25118
|
process.exit(1);
|
|
24903
25119
|
}
|
|
24904
25120
|
printInfo("Thanks, feedback sent!");
|
|
@@ -24983,7 +25199,8 @@ function createRun(opts, globals) {
|
|
|
24983
25199
|
}
|
|
24984
25200
|
|
|
24985
25201
|
// src/commands/analyze/index.ts
|
|
24986
|
-
var
|
|
25202
|
+
var import_node_fs53 = require("node:fs");
|
|
25203
|
+
var import_node_path40 = require("node:path");
|
|
24987
25204
|
|
|
24988
25205
|
// src/lib/repo-context.ts
|
|
24989
25206
|
var import_node_child_process11 = require("node:child_process");
|
|
@@ -25947,7 +26164,7 @@ function installRunEvidence(run4) {
|
|
|
25947
26164
|
}
|
|
25948
26165
|
|
|
25949
26166
|
// src/lib/git-frame.ts
|
|
25950
|
-
var
|
|
26167
|
+
var import_node_fs40 = require("node:fs");
|
|
25951
26168
|
var import_node_os6 = require("node:os");
|
|
25952
26169
|
var import_node_path30 = require("node:path");
|
|
25953
26170
|
var import_node_path31 = require("node:path");
|
|
@@ -26117,14 +26334,14 @@ function gitAt(dir, args2) {
|
|
|
26117
26334
|
}
|
|
26118
26335
|
function realpathOr2(p) {
|
|
26119
26336
|
try {
|
|
26120
|
-
return
|
|
26337
|
+
return import_node_fs40.realpathSync.native(p);
|
|
26121
26338
|
} catch {
|
|
26122
26339
|
return (0, import_node_path30.resolve)(p);
|
|
26123
26340
|
}
|
|
26124
26341
|
}
|
|
26125
26342
|
function resolveFrame(input) {
|
|
26126
26343
|
const found = findMomentSegment(input.command, input.on);
|
|
26127
|
-
const hookDirUsable = !!input.hookCwd && (0,
|
|
26344
|
+
const hookDirUsable = !!input.hookCwd && (0, import_node_fs40.existsSync)(input.hookCwd);
|
|
26128
26345
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
26129
26346
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
26130
26347
|
const refuse = (refusal) => ({
|
|
@@ -26147,7 +26364,7 @@ function resolveFrame(input) {
|
|
|
26147
26364
|
if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
|
|
26148
26365
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
26149
26366
|
if (targetDir !== baseDir) {
|
|
26150
|
-
if (!(0,
|
|
26367
|
+
if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
|
|
26151
26368
|
dir = targetDir;
|
|
26152
26369
|
}
|
|
26153
26370
|
}
|
|
@@ -26334,7 +26551,7 @@ function stagedRange(frame, command) {
|
|
|
26334
26551
|
return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
|
|
26335
26552
|
}
|
|
26336
26553
|
const mergeHead = frame.gitDir ? (0, import_node_path31.join)(frame.gitDir, "MERGE_HEAD") : null;
|
|
26337
|
-
if (mergeHead && (0,
|
|
26554
|
+
if (mergeHead && (0, import_node_fs40.existsSync)(mergeHead)) {
|
|
26338
26555
|
const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
|
|
26339
26556
|
const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
|
|
26340
26557
|
const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
|
|
@@ -26468,7 +26685,7 @@ function truthy(v) {
|
|
|
26468
26685
|
}
|
|
26469
26686
|
|
|
26470
26687
|
// src/lib/transcript.ts
|
|
26471
|
-
var
|
|
26688
|
+
var import_node_fs41 = require("node:fs");
|
|
26472
26689
|
var MAX_READ_BYTES = 256 * 1024;
|
|
26473
26690
|
var SMALL_FILE_BYTES = 64 * 1024;
|
|
26474
26691
|
var MAX_FILES_LIST = 20;
|
|
@@ -26495,7 +26712,7 @@ async function extractActionSummary(transcriptPath) {
|
|
|
26495
26712
|
function readTurnLines(transcriptPath) {
|
|
26496
26713
|
let size;
|
|
26497
26714
|
try {
|
|
26498
|
-
size = (0,
|
|
26715
|
+
size = (0, import_node_fs41.statSync)(transcriptPath).size;
|
|
26499
26716
|
} catch {
|
|
26500
26717
|
return null;
|
|
26501
26718
|
}
|
|
@@ -26503,7 +26720,7 @@ function readTurnLines(transcriptPath) {
|
|
|
26503
26720
|
let raw;
|
|
26504
26721
|
let windowed = false;
|
|
26505
26722
|
if (size <= SMALL_FILE_BYTES) {
|
|
26506
|
-
raw = (0,
|
|
26723
|
+
raw = (0, import_node_fs41.readFileSync)(transcriptPath, "utf-8");
|
|
26507
26724
|
} else {
|
|
26508
26725
|
windowed = true;
|
|
26509
26726
|
const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
|
|
@@ -26749,7 +26966,7 @@ function sanitizeCommandWithLoss(rawCmd) {
|
|
|
26749
26966
|
const lost = lines.slice(1).some((l) => l.trim().length > 0);
|
|
26750
26967
|
const first = lines[0];
|
|
26751
26968
|
const cmd = sanitizeCommand(first);
|
|
26752
|
-
const hadSeparator = SEPARATORS.some((
|
|
26969
|
+
const hadSeparator = SEPARATORS.some((sep6) => first.indexOf(sep6) > 0);
|
|
26753
26970
|
return { cmd, lost: lost || !hadSeparator && first.length > MAX_COMMAND_CHARS };
|
|
26754
26971
|
}
|
|
26755
26972
|
var SEPARATORS = [" | ", " > ", " >> ", " 2>", " && ", " ; "];
|
|
@@ -26758,11 +26975,11 @@ function sanitizeCommand(rawCmd) {
|
|
|
26758
26975
|
let cmd = rawCmd.split("\n")[0];
|
|
26759
26976
|
let cut = -1;
|
|
26760
26977
|
let marker = "";
|
|
26761
|
-
for (const
|
|
26762
|
-
const idx = cmd.indexOf(
|
|
26978
|
+
for (const sep6 of SEPARATORS) {
|
|
26979
|
+
const idx = cmd.indexOf(sep6);
|
|
26763
26980
|
if (idx > 0 && (cut === -1 || idx < cut)) {
|
|
26764
26981
|
cut = idx;
|
|
26765
|
-
marker =
|
|
26982
|
+
marker = sep6.trim();
|
|
26766
26983
|
}
|
|
26767
26984
|
}
|
|
26768
26985
|
if (cut > -1) cmd = cmd.slice(0, cut);
|
|
@@ -26786,28 +27003,28 @@ async function readStopHookStdin() {
|
|
|
26786
27003
|
try {
|
|
26787
27004
|
if (process.stdin.isTTY) return empty;
|
|
26788
27005
|
const chunks = [];
|
|
26789
|
-
const timeout = new Promise((
|
|
26790
|
-
const read2 = new Promise((
|
|
27006
|
+
const timeout = new Promise((resolve9) => setTimeout(() => resolve9(empty), 500));
|
|
27007
|
+
const read2 = new Promise((resolve9) => {
|
|
26791
27008
|
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
26792
27009
|
process.stdin.on("end", () => {
|
|
26793
27010
|
const raw = Buffer.concat(chunks).toString("utf-8").trim();
|
|
26794
27011
|
if (!raw) {
|
|
26795
|
-
|
|
27012
|
+
resolve9(empty);
|
|
26796
27013
|
return;
|
|
26797
27014
|
}
|
|
26798
27015
|
try {
|
|
26799
27016
|
const data = JSON.parse(raw);
|
|
26800
|
-
|
|
27017
|
+
resolve9({
|
|
26801
27018
|
assistantMessage: typeof data.last_assistant_message === "string" ? data.last_assistant_message : null,
|
|
26802
27019
|
stopReason: typeof data.stop_reason === "string" ? data.stop_reason : null,
|
|
26803
27020
|
transcriptPath: typeof data.transcript_path === "string" ? data.transcript_path : null,
|
|
26804
27021
|
sessionId: typeof data.session_id === "string" ? data.session_id : null
|
|
26805
27022
|
});
|
|
26806
27023
|
} catch {
|
|
26807
|
-
|
|
27024
|
+
resolve9(empty);
|
|
26808
27025
|
}
|
|
26809
27026
|
});
|
|
26810
|
-
process.stdin.on("error", () =>
|
|
27027
|
+
process.stdin.on("error", () => resolve9(empty));
|
|
26811
27028
|
process.stdin.resume();
|
|
26812
27029
|
});
|
|
26813
27030
|
return await Promise.race([read2, timeout]);
|
|
@@ -26861,39 +27078,6 @@ async function bootstrap(run4) {
|
|
|
26861
27078
|
Object.assign(run4, { actionSummary, assistantResponse, baseline, baselineSessionId, reachability, sessionId, stopReason, tokenResult, transcriptPath, turnId });
|
|
26862
27079
|
}
|
|
26863
27080
|
|
|
26864
|
-
// src/lib/self-scope.ts
|
|
26865
|
-
var LEGACY_GATE_SKILLS = /* @__PURE__ */ new Set([
|
|
26866
|
-
"gate-setup",
|
|
26867
|
-
"gate-analyze",
|
|
26868
|
-
"gate-review",
|
|
26869
|
-
"gate-status",
|
|
26870
|
-
"gate-feedback",
|
|
26871
|
-
"gate-insights",
|
|
26872
|
-
"gate-learn",
|
|
26873
|
-
"gate-memory",
|
|
26874
|
-
"gate-reflect"
|
|
26875
|
-
]);
|
|
26876
|
-
function isVerityOwned(path) {
|
|
26877
|
-
const segments = path.replace(/\\/g, "/").split("/");
|
|
26878
|
-
for (let i2 = 0; i2 < segments.length; i2++) {
|
|
26879
|
-
const seg = segments[i2];
|
|
26880
|
-
if (seg === ".verity" || seg === ".codacy") return true;
|
|
26881
|
-
if (i2 === segments.length - 1 && (seg === "VERITY.md" || seg === "GATE.md")) return true;
|
|
26882
|
-
if (seg === ".claude" && segments[i2 + 1] === "skills" && typeof segments[i2 + 2] === "string") {
|
|
26883
|
-
const skill = segments[i2 + 2];
|
|
26884
|
-
if (skill.startsWith("verity-") || LEGACY_GATE_SKILLS.has(skill)) return true;
|
|
26885
|
-
}
|
|
26886
|
-
if (seg === ".claude" && segments[i2 + 1] === "settings.json") return true;
|
|
26887
|
-
}
|
|
26888
|
-
return false;
|
|
26889
|
-
}
|
|
26890
|
-
function partitionVerityOwned(paths) {
|
|
26891
|
-
const kept = [];
|
|
26892
|
-
const owned = [];
|
|
26893
|
-
for (const p of paths) (isVerityOwned(p) ? owned : kept).push(p);
|
|
26894
|
-
return { kept, owned };
|
|
26895
|
-
}
|
|
26896
|
-
|
|
26897
27081
|
// src/lib/knowledge-note-state.ts
|
|
26898
27082
|
var stateDir = () => projectPath(VERITY_DIR);
|
|
26899
27083
|
var STATE_FILE2 = "knowledge-note-state.json";
|
|
@@ -27073,7 +27257,7 @@ function channelSilence(input) {
|
|
|
27073
27257
|
// src/lib/cli-version.ts
|
|
27074
27258
|
function cliVersion() {
|
|
27075
27259
|
try {
|
|
27076
|
-
return true ? "0.34.
|
|
27260
|
+
return true ? "0.34.1-experimental.199c728" : "dev";
|
|
27077
27261
|
} catch {
|
|
27078
27262
|
return "dev";
|
|
27079
27263
|
}
|
|
@@ -27114,7 +27298,171 @@ async function sendSkipBeacon(ctx, reason) {
|
|
|
27114
27298
|
|
|
27115
27299
|
// src/lib/static-analysis.ts
|
|
27116
27300
|
var import_node_child_process12 = require("node:child_process");
|
|
27117
|
-
var
|
|
27301
|
+
var import_node_fs42 = require("node:fs");
|
|
27302
|
+
|
|
27303
|
+
// src/lib/environment-globals.ts
|
|
27304
|
+
var NODE = [
|
|
27305
|
+
"process",
|
|
27306
|
+
"Buffer",
|
|
27307
|
+
"global",
|
|
27308
|
+
"require",
|
|
27309
|
+
"module",
|
|
27310
|
+
"exports",
|
|
27311
|
+
"__dirname",
|
|
27312
|
+
"__filename",
|
|
27313
|
+
"console",
|
|
27314
|
+
"setTimeout",
|
|
27315
|
+
"clearTimeout",
|
|
27316
|
+
"setInterval",
|
|
27317
|
+
"clearInterval",
|
|
27318
|
+
"setImmediate",
|
|
27319
|
+
"clearImmediate",
|
|
27320
|
+
"queueMicrotask",
|
|
27321
|
+
"structuredClone",
|
|
27322
|
+
"performance",
|
|
27323
|
+
"fetch",
|
|
27324
|
+
"Request",
|
|
27325
|
+
"Response",
|
|
27326
|
+
"Headers",
|
|
27327
|
+
"FormData",
|
|
27328
|
+
"Blob",
|
|
27329
|
+
"File",
|
|
27330
|
+
"URL",
|
|
27331
|
+
"URLSearchParams",
|
|
27332
|
+
"TextEncoder",
|
|
27333
|
+
"TextDecoder",
|
|
27334
|
+
"TextEncoderStream",
|
|
27335
|
+
"TextDecoderStream",
|
|
27336
|
+
"AbortController",
|
|
27337
|
+
"AbortSignal",
|
|
27338
|
+
"Event",
|
|
27339
|
+
"EventTarget",
|
|
27340
|
+
"CustomEvent",
|
|
27341
|
+
"MessageChannel",
|
|
27342
|
+
"MessagePort",
|
|
27343
|
+
"MessageEvent",
|
|
27344
|
+
"BroadcastChannel",
|
|
27345
|
+
"WebSocket",
|
|
27346
|
+
"WebAssembly",
|
|
27347
|
+
"crypto",
|
|
27348
|
+
"Crypto",
|
|
27349
|
+
"CryptoKey",
|
|
27350
|
+
"SubtleCrypto",
|
|
27351
|
+
"atob",
|
|
27352
|
+
"btoa",
|
|
27353
|
+
"navigator",
|
|
27354
|
+
"DOMException",
|
|
27355
|
+
"ReadableStream",
|
|
27356
|
+
"WritableStream",
|
|
27357
|
+
"TransformStream",
|
|
27358
|
+
"CompressionStream",
|
|
27359
|
+
"DecompressionStream",
|
|
27360
|
+
"ByteLengthQueuingStrategy",
|
|
27361
|
+
"CountQueuingStrategy",
|
|
27362
|
+
"PerformanceObserver",
|
|
27363
|
+
"PerformanceEntry",
|
|
27364
|
+
"PerformanceMark",
|
|
27365
|
+
"PerformanceMeasure"
|
|
27366
|
+
];
|
|
27367
|
+
var BROWSER = [
|
|
27368
|
+
"window",
|
|
27369
|
+
"self",
|
|
27370
|
+
"document",
|
|
27371
|
+
"location",
|
|
27372
|
+
"history",
|
|
27373
|
+
"localStorage",
|
|
27374
|
+
"sessionStorage",
|
|
27375
|
+
"screen",
|
|
27376
|
+
"alert",
|
|
27377
|
+
"confirm",
|
|
27378
|
+
"prompt",
|
|
27379
|
+
"requestAnimationFrame",
|
|
27380
|
+
"cancelAnimationFrame",
|
|
27381
|
+
"requestIdleCallback",
|
|
27382
|
+
"cancelIdleCallback",
|
|
27383
|
+
"getComputedStyle",
|
|
27384
|
+
"matchMedia",
|
|
27385
|
+
"getSelection",
|
|
27386
|
+
"scrollTo",
|
|
27387
|
+
"scrollBy",
|
|
27388
|
+
"innerWidth",
|
|
27389
|
+
"innerHeight",
|
|
27390
|
+
"outerWidth",
|
|
27391
|
+
"outerHeight",
|
|
27392
|
+
"devicePixelRatio",
|
|
27393
|
+
"visualViewport",
|
|
27394
|
+
"postMessage",
|
|
27395
|
+
"addEventListener",
|
|
27396
|
+
"removeEventListener",
|
|
27397
|
+
"dispatchEvent",
|
|
27398
|
+
"customElements",
|
|
27399
|
+
"indexedDB",
|
|
27400
|
+
"IDBKeyRange",
|
|
27401
|
+
"caches",
|
|
27402
|
+
"XMLHttpRequest",
|
|
27403
|
+
"EventSource",
|
|
27404
|
+
"FileReader",
|
|
27405
|
+
"Image",
|
|
27406
|
+
"Audio",
|
|
27407
|
+
"Worker",
|
|
27408
|
+
"SharedWorker",
|
|
27409
|
+
"Notification",
|
|
27410
|
+
"MutationObserver",
|
|
27411
|
+
"IntersectionObserver",
|
|
27412
|
+
"ResizeObserver",
|
|
27413
|
+
"DOMParser",
|
|
27414
|
+
"XMLSerializer",
|
|
27415
|
+
"Node",
|
|
27416
|
+
"Element",
|
|
27417
|
+
"HTMLElement",
|
|
27418
|
+
"SVGElement",
|
|
27419
|
+
"NodeList",
|
|
27420
|
+
"HTMLCollection",
|
|
27421
|
+
"DocumentFragment",
|
|
27422
|
+
"ShadowRoot",
|
|
27423
|
+
"Range",
|
|
27424
|
+
"Selection",
|
|
27425
|
+
"KeyboardEvent",
|
|
27426
|
+
"MouseEvent",
|
|
27427
|
+
"PointerEvent",
|
|
27428
|
+
"FocusEvent",
|
|
27429
|
+
"InputEvent",
|
|
27430
|
+
"TouchEvent",
|
|
27431
|
+
"UIEvent",
|
|
27432
|
+
"ErrorEvent",
|
|
27433
|
+
"ProgressEvent",
|
|
27434
|
+
"StorageEvent",
|
|
27435
|
+
"CloseEvent",
|
|
27436
|
+
"CSS",
|
|
27437
|
+
"CSSStyleSheet",
|
|
27438
|
+
"FontFace",
|
|
27439
|
+
"ImageData",
|
|
27440
|
+
"ImageBitmap",
|
|
27441
|
+
"createImageBitmap",
|
|
27442
|
+
"OffscreenCanvas",
|
|
27443
|
+
"Path2D",
|
|
27444
|
+
"CanvasRenderingContext2D",
|
|
27445
|
+
"AudioContext",
|
|
27446
|
+
"MediaStream",
|
|
27447
|
+
"MediaRecorder",
|
|
27448
|
+
"RTCPeerConnection",
|
|
27449
|
+
"ClipboardItem",
|
|
27450
|
+
"isSecureContext",
|
|
27451
|
+
"crossOriginIsolated",
|
|
27452
|
+
"reportError",
|
|
27453
|
+
"speechSynthesis"
|
|
27454
|
+
];
|
|
27455
|
+
var ENVIRONMENT_GLOBALS = /* @__PURE__ */ new Set([...NODE, ...BROWSER]);
|
|
27456
|
+
var NOT_DEFINED = /^'([^']+)' is not defined\.?$/;
|
|
27457
|
+
var COMMONJS_ONLY = /* @__PURE__ */ new Set(["require", "module", "exports", "__dirname", "__filename"]);
|
|
27458
|
+
function isEnvironmentGlobalNoUndef(ruleId, message, filePath = "") {
|
|
27459
|
+
if (!/(^|_)no-undef$/.test(ruleId)) return false;
|
|
27460
|
+
const name2 = message.trim().match(NOT_DEFINED)?.[1];
|
|
27461
|
+
if (name2 === void 0 || !ENVIRONMENT_GLOBALS.has(name2)) return false;
|
|
27462
|
+
return !(COMMONJS_ONLY.has(name2) && /\.m[jt]s$/.test(filePath));
|
|
27463
|
+
}
|
|
27464
|
+
|
|
27465
|
+
// src/lib/static-analysis.ts
|
|
27118
27466
|
var SEVERITY_ORDER = {
|
|
27119
27467
|
Error: 0,
|
|
27120
27468
|
Critical: 0,
|
|
@@ -27170,7 +27518,7 @@ function runCodacyAnalysis(files) {
|
|
|
27170
27518
|
if (files.length === 0) return empty;
|
|
27171
27519
|
const existingFiles = files.filter((f) => {
|
|
27172
27520
|
try {
|
|
27173
|
-
return (0,
|
|
27521
|
+
return (0, import_node_fs42.existsSync)(f);
|
|
27174
27522
|
} catch {
|
|
27175
27523
|
return false;
|
|
27176
27524
|
}
|
|
@@ -27202,7 +27550,10 @@ function interpretAnalyzerRun(run4) {
|
|
|
27202
27550
|
} catch {
|
|
27203
27551
|
return withFailure("unparseable_output", output);
|
|
27204
27552
|
}
|
|
27205
|
-
const
|
|
27553
|
+
const reported = parsed.issues ?? [];
|
|
27554
|
+
const issues = reported.filter(
|
|
27555
|
+
(i2) => !isEnvironmentGlobalNoUndef(i2.patternId ?? "", i2.message ?? "", i2.filePath ?? "")
|
|
27556
|
+
);
|
|
27206
27557
|
const findings = issues.map((issue) => ({
|
|
27207
27558
|
rule_id: issue.patternId ?? "",
|
|
27208
27559
|
tool: issue.toolId ?? "",
|
|
@@ -27225,7 +27576,7 @@ function interpretAnalyzerRun(run4) {
|
|
|
27225
27576
|
);
|
|
27226
27577
|
const analyzerErrors = parsed.errors ?? [];
|
|
27227
27578
|
let failure;
|
|
27228
|
-
if (
|
|
27579
|
+
if (reported.length === 0) {
|
|
27229
27580
|
if (analyzerErrors.length > 0) {
|
|
27230
27581
|
const first = analyzerErrors[0];
|
|
27231
27582
|
failure = {
|
|
@@ -27439,7 +27790,7 @@ async function scope(run4) {
|
|
|
27439
27790
|
}
|
|
27440
27791
|
|
|
27441
27792
|
// src/lib/specs.ts
|
|
27442
|
-
var
|
|
27793
|
+
var import_node_fs43 = require("node:fs");
|
|
27443
27794
|
var import_node_path32 = require("node:path");
|
|
27444
27795
|
var SPEC_CANDIDATES = [
|
|
27445
27796
|
"CLAUDE.md",
|
|
@@ -27481,7 +27832,7 @@ function discoverSpecs(consulted = []) {
|
|
|
27481
27832
|
const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
|
|
27482
27833
|
if (totalBytes >= totalCap) return false;
|
|
27483
27834
|
if (seen.has(specPath)) return true;
|
|
27484
|
-
if (!(0,
|
|
27835
|
+
if (!(0, import_node_fs43.existsSync)(specPath)) return true;
|
|
27485
27836
|
seen.add(specPath);
|
|
27486
27837
|
const remaining = totalCap - totalBytes;
|
|
27487
27838
|
const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
|
|
@@ -27504,7 +27855,7 @@ function discoverSpecs(consulted = []) {
|
|
|
27504
27855
|
if (!addSpec(candidate)) break;
|
|
27505
27856
|
}
|
|
27506
27857
|
for (const dir of ["spec", "docs"]) {
|
|
27507
|
-
if (!(0,
|
|
27858
|
+
if (!(0, import_node_fs43.existsSync)(dir)) continue;
|
|
27508
27859
|
try {
|
|
27509
27860
|
const mdFiles = findMdFiles(dir, 2).sort();
|
|
27510
27861
|
for (const mdFile of mdFiles) {
|
|
@@ -27519,7 +27870,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
|
|
|
27519
27870
|
if (depth >= maxDepth) return [];
|
|
27520
27871
|
const result = [];
|
|
27521
27872
|
try {
|
|
27522
|
-
const entries = (0,
|
|
27873
|
+
const entries = (0, import_node_fs43.readdirSync)(dir, { withFileTypes: true });
|
|
27523
27874
|
for (const entry of entries) {
|
|
27524
27875
|
const fullPath = (0, import_node_path32.join)(dir, entry.name);
|
|
27525
27876
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
@@ -27539,13 +27890,13 @@ function discoverPlans() {
|
|
|
27539
27890
|
if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
|
|
27540
27891
|
sources.push({ root: process.cwd(), prefix: (0, import_node_path32.join)(".claude", "plans") });
|
|
27541
27892
|
}
|
|
27542
|
-
if (home && (0,
|
|
27893
|
+
if (home && (0, import_node_fs43.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
|
|
27543
27894
|
const candidates2 = [];
|
|
27544
27895
|
const seen = /* @__PURE__ */ new Set();
|
|
27545
27896
|
for (const source2 of sources) {
|
|
27546
27897
|
let names2;
|
|
27547
27898
|
try {
|
|
27548
|
-
names2 = (0,
|
|
27899
|
+
names2 = (0, import_node_fs43.readdirSync)(source2.prefix ? (0, import_node_path32.join)(source2.root, source2.prefix) : source2.root);
|
|
27549
27900
|
} catch {
|
|
27550
27901
|
continue;
|
|
27551
27902
|
}
|
|
@@ -27572,7 +27923,7 @@ function isRealDirectoryChain(root, parts2) {
|
|
|
27572
27923
|
for (const part of parts2) {
|
|
27573
27924
|
current = (0, import_node_path32.join)(current, part);
|
|
27574
27925
|
try {
|
|
27575
|
-
if (!(0,
|
|
27926
|
+
if (!(0, import_node_fs43.lstatSync)(current).isDirectory()) return false;
|
|
27576
27927
|
} catch {
|
|
27577
27928
|
return false;
|
|
27578
27929
|
}
|
|
@@ -27587,7 +27938,7 @@ function discoverGuardDocs(rangeFiles2) {
|
|
|
27587
27938
|
if (result.length >= MAX_SPEC_FILES) break;
|
|
27588
27939
|
if (!GUARD_DOC_EXT.test(path)) continue;
|
|
27589
27940
|
if (path.startsWith("/") || path.includes("..")) continue;
|
|
27590
|
-
if (!(0,
|
|
27941
|
+
if (!(0, import_node_fs43.existsSync)(path)) continue;
|
|
27591
27942
|
const opened = openRegularInRoot(process.cwd(), path);
|
|
27592
27943
|
if (!opened.ok) continue;
|
|
27593
27944
|
if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
|
|
@@ -27773,7 +28124,7 @@ async function mode(run4) {
|
|
|
27773
28124
|
}
|
|
27774
28125
|
|
|
27775
28126
|
// src/lib/fold.ts
|
|
27776
|
-
var
|
|
28127
|
+
var import_node_fs44 = require("node:fs");
|
|
27777
28128
|
var import_node_path33 = require("node:path");
|
|
27778
28129
|
var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
|
|
27779
28130
|
"user",
|
|
@@ -27911,7 +28262,7 @@ function candidateRoots(repoRoot2) {
|
|
|
27911
28262
|
const norm2 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
27912
28263
|
const out2 = [norm2];
|
|
27913
28264
|
try {
|
|
27914
|
-
const real =
|
|
28265
|
+
const real = import_node_fs44.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
27915
28266
|
if (real !== norm2) out2.push(real);
|
|
27916
28267
|
} catch {
|
|
27917
28268
|
}
|
|
@@ -27999,8 +28350,8 @@ function fold(transcriptPath, opts = {}) {
|
|
|
27999
28350
|
}
|
|
28000
28351
|
};
|
|
28001
28352
|
try {
|
|
28002
|
-
if (!(0,
|
|
28003
|
-
ingest((0,
|
|
28353
|
+
if (!(0, import_node_fs44.existsSync)(transcriptPath)) return result;
|
|
28354
|
+
ingest((0, import_node_fs44.readFileSync)(transcriptPath, "utf8"), "agent");
|
|
28004
28355
|
result.coverage.complete = true;
|
|
28005
28356
|
} catch {
|
|
28006
28357
|
return result;
|
|
@@ -28011,19 +28362,19 @@ function fold(transcriptPath, opts = {}) {
|
|
|
28011
28362
|
(0, import_node_path33.basename)(transcriptPath).replace(/\.jsonl$/, ""),
|
|
28012
28363
|
"subagents"
|
|
28013
28364
|
);
|
|
28014
|
-
if ((0,
|
|
28365
|
+
if ((0, import_node_fs44.existsSync)(sidecarDir)) {
|
|
28015
28366
|
const maxFiles = opts.maxSidecars ?? 200;
|
|
28016
28367
|
const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
|
|
28017
28368
|
const found = [];
|
|
28018
28369
|
const walk2 = (d, depth) => {
|
|
28019
28370
|
if (depth > 4) return;
|
|
28020
|
-
for (const e of (0,
|
|
28371
|
+
for (const e of (0, import_node_fs44.readdirSync)(d, { withFileTypes: true })) {
|
|
28021
28372
|
const p = (0, import_node_path33.join)(d, e.name);
|
|
28022
28373
|
if (e.isDirectory()) {
|
|
28023
28374
|
walk2(p, depth + 1);
|
|
28024
28375
|
} else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
|
|
28025
28376
|
try {
|
|
28026
|
-
const st = (0,
|
|
28377
|
+
const st = (0, import_node_fs44.statSync)(p);
|
|
28027
28378
|
found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
|
|
28028
28379
|
} catch {
|
|
28029
28380
|
result.coverage.malformed++;
|
|
@@ -28040,7 +28391,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
28040
28391
|
continue;
|
|
28041
28392
|
}
|
|
28042
28393
|
try {
|
|
28043
|
-
ingest((0,
|
|
28394
|
+
ingest((0, import_node_fs44.readFileSync)(f.path, "utf8"), "subagent");
|
|
28044
28395
|
bytes += f.size;
|
|
28045
28396
|
result.coverage.subagentFiles++;
|
|
28046
28397
|
} catch {
|
|
@@ -28075,7 +28426,7 @@ function fold(transcriptPath, opts = {}) {
|
|
|
28075
28426
|
}
|
|
28076
28427
|
function classifyUnobserved(path) {
|
|
28077
28428
|
try {
|
|
28078
|
-
const st = (0,
|
|
28429
|
+
const st = (0, import_node_fs44.statSync)(path);
|
|
28079
28430
|
if (!st.isFile()) return "unreadable";
|
|
28080
28431
|
} catch {
|
|
28081
28432
|
return "unreadable";
|
|
@@ -28390,20 +28741,20 @@ async function evidence(run4) {
|
|
|
28390
28741
|
}
|
|
28391
28742
|
|
|
28392
28743
|
// src/lib/cache-cleanup.ts
|
|
28393
|
-
var
|
|
28744
|
+
var import_node_fs45 = require("node:fs");
|
|
28394
28745
|
var import_node_path34 = require("node:path");
|
|
28395
28746
|
var CACHE_TTL_DAYS = 7;
|
|
28396
28747
|
function pruneStaleCache() {
|
|
28397
28748
|
try {
|
|
28398
28749
|
const dir = projectPath(CACHE_DIR);
|
|
28399
28750
|
const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
|
|
28400
|
-
for (const entry of (0,
|
|
28751
|
+
for (const entry of (0, import_node_fs45.readdirSync)(dir)) {
|
|
28401
28752
|
if (!entry.startsWith("pending-")) continue;
|
|
28402
28753
|
const path = (0, import_node_path34.join)(dir, entry);
|
|
28403
28754
|
try {
|
|
28404
|
-
const stat3 = (0,
|
|
28755
|
+
const stat3 = (0, import_node_fs45.statSync)(path);
|
|
28405
28756
|
if (stat3.mtimeMs < cutoff) {
|
|
28406
|
-
(0,
|
|
28757
|
+
(0, import_node_fs45.unlinkSync)(path);
|
|
28407
28758
|
logEvent("cache_entry_pruned", {
|
|
28408
28759
|
path: entry,
|
|
28409
28760
|
age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
|
|
@@ -28417,7 +28768,7 @@ function pruneStaleCache() {
|
|
|
28417
28768
|
}
|
|
28418
28769
|
|
|
28419
28770
|
// src/lib/context-files.ts
|
|
28420
|
-
var
|
|
28771
|
+
var import_node_fs46 = require("node:fs");
|
|
28421
28772
|
var import_node_os7 = require("node:os");
|
|
28422
28773
|
var MAX_CONTEXT_FILES = 10;
|
|
28423
28774
|
var MAX_CONTEXT_FILE_BYTES = 10240;
|
|
@@ -28475,7 +28826,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
|
|
|
28475
28826
|
continue;
|
|
28476
28827
|
}
|
|
28477
28828
|
try {
|
|
28478
|
-
const content = (0,
|
|
28829
|
+
const content = (0, import_node_fs46.readFileSync)(safePath, "utf8");
|
|
28479
28830
|
const bytes = Buffer.byteLength(content);
|
|
28480
28831
|
if (bytes > MAX_CONTEXT_FILE_BYTES) {
|
|
28481
28832
|
logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
|
|
@@ -28541,7 +28892,7 @@ async function contextFiles(run4) {
|
|
|
28541
28892
|
}
|
|
28542
28893
|
|
|
28543
28894
|
// src/lib/code/index.ts
|
|
28544
|
-
var
|
|
28895
|
+
var import_node_crypto13 = require("node:crypto");
|
|
28545
28896
|
|
|
28546
28897
|
// src/lib/code/languages.ts
|
|
28547
28898
|
var JS_LIKE = {
|
|
@@ -28633,7 +28984,7 @@ function languageOf2(path) {
|
|
|
28633
28984
|
}
|
|
28634
28985
|
|
|
28635
28986
|
// src/lib/code/runtime.ts
|
|
28636
|
-
var
|
|
28987
|
+
var import_node_fs47 = require("node:fs");
|
|
28637
28988
|
var import_node_path35 = require("node:path");
|
|
28638
28989
|
var import_web_tree_sitter2 = __toESM2(require_web_tree_sitter2());
|
|
28639
28990
|
|
|
@@ -28705,7 +29056,7 @@ function grammarCandidates(file, pkg, env = process.env) {
|
|
|
28705
29056
|
}
|
|
28706
29057
|
function locateGrammar(id, env = process.env) {
|
|
28707
29058
|
const g = grammars_default[id];
|
|
28708
|
-
return grammarCandidates(g.file, g.package, env).find((p) => (0,
|
|
29059
|
+
return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs47.existsSync)(p)) ?? null;
|
|
28709
29060
|
}
|
|
28710
29061
|
var loading = null;
|
|
28711
29062
|
function loadRuntime(env = process.env) {
|
|
@@ -30319,7 +30670,7 @@ function byPath(fns, name2) {
|
|
|
30319
30670
|
function makeCodeMap(rt) {
|
|
30320
30671
|
const cache = /* @__PURE__ */ new Map();
|
|
30321
30672
|
const outline = (path, content, deadlineAt = Date.now() + DEFAULT_PARSE_MS) => {
|
|
30322
|
-
const key = `${path}\0${(0,
|
|
30673
|
+
const key = `${path}\0${(0, import_node_crypto13.createHash)("sha1").update(content).digest("hex")}`;
|
|
30323
30674
|
const hit = cache.get(key);
|
|
30324
30675
|
if (hit) return { source: "tree-sitter", value: hit, elapsedMs: 0 };
|
|
30325
30676
|
let r;
|
|
@@ -31034,7 +31385,7 @@ async function repoContext(run4) {
|
|
|
31034
31385
|
|
|
31035
31386
|
// src/lib/seed-runner.ts
|
|
31036
31387
|
var import_promises15 = require("node:fs/promises");
|
|
31037
|
-
var
|
|
31388
|
+
var import_node_fs48 = require("node:fs");
|
|
31038
31389
|
var import_node_path36 = require("node:path");
|
|
31039
31390
|
var import_yaml4 = __toESM2(require_dist());
|
|
31040
31391
|
|
|
@@ -31259,7 +31610,7 @@ async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
|
|
|
31259
31610
|
const titles = /* @__PURE__ */ new Set();
|
|
31260
31611
|
for (const dir of NODE_DIRS) {
|
|
31261
31612
|
const full = (0, import_node_path36.join)(memoryDir3, dir);
|
|
31262
|
-
if (!(0,
|
|
31613
|
+
if (!(0, import_node_fs48.existsSync)(full)) continue;
|
|
31263
31614
|
let files;
|
|
31264
31615
|
try {
|
|
31265
31616
|
files = await (0, import_promises15.readdir)(full);
|
|
@@ -31341,7 +31692,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
|
|
|
31341
31692
|
return fm;
|
|
31342
31693
|
}
|
|
31343
31694
|
async function runSeed(opts) {
|
|
31344
|
-
if (!(0,
|
|
31695
|
+
if (!(0, import_node_fs48.existsSync)(STANDARD_FILE)) {
|
|
31345
31696
|
return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
|
|
31346
31697
|
}
|
|
31347
31698
|
let standardDoc;
|
|
@@ -31353,7 +31704,7 @@ async function runSeed(opts) {
|
|
|
31353
31704
|
}
|
|
31354
31705
|
const knowledgeSpec = standardDoc.knowledge_spec ?? {};
|
|
31355
31706
|
let readmeContent;
|
|
31356
|
-
if ((0,
|
|
31707
|
+
if ((0, import_node_fs48.existsSync)("README.md")) {
|
|
31357
31708
|
try {
|
|
31358
31709
|
readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
|
|
31359
31710
|
} catch {
|
|
@@ -31361,7 +31712,7 @@ async function runSeed(opts) {
|
|
|
31361
31712
|
}
|
|
31362
31713
|
let claudeMdContent;
|
|
31363
31714
|
for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
|
|
31364
|
-
if ((0,
|
|
31715
|
+
if ((0, import_node_fs48.existsSync)(p)) {
|
|
31365
31716
|
try {
|
|
31366
31717
|
claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
|
|
31367
31718
|
break;
|
|
@@ -31441,7 +31792,7 @@ async function runSeed(opts) {
|
|
|
31441
31792
|
continue;
|
|
31442
31793
|
}
|
|
31443
31794
|
const deduplicated = res.data.deduplicated === true;
|
|
31444
|
-
if (deduplicated && (0,
|
|
31795
|
+
if (deduplicated && (0, import_node_fs48.existsSync)(targetPath)) {
|
|
31445
31796
|
existing++;
|
|
31446
31797
|
continue;
|
|
31447
31798
|
}
|
|
@@ -31463,7 +31814,7 @@ async function runSeed(opts) {
|
|
|
31463
31814
|
}
|
|
31464
31815
|
|
|
31465
31816
|
// src/commands/analyze/phases/08-memory-manifest.ts
|
|
31466
|
-
var
|
|
31817
|
+
var import_node_fs49 = require("node:fs");
|
|
31467
31818
|
var import_node_path37 = require("node:path");
|
|
31468
31819
|
async function memoryManifest(run4) {
|
|
31469
31820
|
const { globals } = run4;
|
|
@@ -31475,8 +31826,8 @@ async function memoryManifest(run4) {
|
|
|
31475
31826
|
try {
|
|
31476
31827
|
await ensureMemoryDir();
|
|
31477
31828
|
const seedMarker = (0, import_node_path37.join)(VERITY_DIR, ".seeded");
|
|
31478
|
-
const hasStandard = (0,
|
|
31479
|
-
const alreadyTried = (0,
|
|
31829
|
+
const hasStandard = (0, import_node_fs49.existsSync)(STANDARD_FILE);
|
|
31830
|
+
const alreadyTried = (0, import_node_fs49.existsSync)(seedMarker);
|
|
31480
31831
|
if (hasStandard && !alreadyTried) {
|
|
31481
31832
|
const preManifest = await buildManifest();
|
|
31482
31833
|
if (preManifest.nodes.length === 0) {
|
|
@@ -31489,7 +31840,7 @@ async function memoryManifest(run4) {
|
|
|
31489
31840
|
dryRun: false
|
|
31490
31841
|
});
|
|
31491
31842
|
if (seedResult.created > 0 || seedResult.existing > 0) {
|
|
31492
|
-
(0,
|
|
31843
|
+
(0, import_node_fs49.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
|
|
31493
31844
|
`);
|
|
31494
31845
|
if (seedResult.created > 0) {
|
|
31495
31846
|
autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
|
|
@@ -31500,7 +31851,7 @@ async function memoryManifest(run4) {
|
|
|
31500
31851
|
failed: seedResult.failed
|
|
31501
31852
|
});
|
|
31502
31853
|
} else if (seedResult.skipped === "already_seeded") {
|
|
31503
|
-
(0,
|
|
31854
|
+
(0, import_node_fs49.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
|
|
31504
31855
|
`);
|
|
31505
31856
|
} else {
|
|
31506
31857
|
logEvent("auto_seed_noop", {
|
|
@@ -31688,8 +32039,24 @@ async function workingMemory(run4) {
|
|
|
31688
32039
|
Object.assign(run4, { incrementReport, memory: memory2, memorySession, reachability });
|
|
31689
32040
|
}
|
|
31690
32041
|
|
|
32042
|
+
// src/lib/payload-bounds.ts
|
|
32043
|
+
var MAX_WIRE_PATHS = 500;
|
|
32044
|
+
function boundPaths(paths, first, max = MAX_WIRE_PATHS) {
|
|
32045
|
+
if (paths.length <= max) return [...paths];
|
|
32046
|
+
const present = new Set(paths);
|
|
32047
|
+
const kept = /* @__PURE__ */ new Set();
|
|
32048
|
+
const out2 = [];
|
|
32049
|
+
for (const p of [...first, ...paths]) {
|
|
32050
|
+
if (out2.length >= max) break;
|
|
32051
|
+
if (!present.has(p) || kept.has(p)) continue;
|
|
32052
|
+
kept.add(p);
|
|
32053
|
+
out2.push(p);
|
|
32054
|
+
}
|
|
32055
|
+
return out2;
|
|
32056
|
+
}
|
|
32057
|
+
|
|
31691
32058
|
// src/lib/note-budget.ts
|
|
31692
|
-
var
|
|
32059
|
+
var import_node_fs50 = require("node:fs");
|
|
31693
32060
|
var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
|
|
31694
32061
|
var EPISODE_STALE_SECONDS = 30 * 60;
|
|
31695
32062
|
var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
|
|
@@ -31711,9 +32078,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
|
|
|
31711
32078
|
}
|
|
31712
32079
|
function readAdvisoryEpisode(sessionId) {
|
|
31713
32080
|
const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
|
|
31714
|
-
if (!(0,
|
|
32081
|
+
if (!(0, import_node_fs50.existsSync)(file)) return null;
|
|
31715
32082
|
try {
|
|
31716
|
-
const o = JSON.parse((0,
|
|
32083
|
+
const o = JSON.parse((0, import_node_fs50.readFileSync)(file, "utf-8")) ?? {};
|
|
31717
32084
|
const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
|
|
31718
32085
|
if (isNaN(delivered)) return null;
|
|
31719
32086
|
return {
|
|
@@ -31727,8 +32094,8 @@ function readAdvisoryEpisode(sessionId) {
|
|
|
31727
32094
|
}
|
|
31728
32095
|
function writeAdvisoryEpisode(episode, sessionId) {
|
|
31729
32096
|
try {
|
|
31730
|
-
(0,
|
|
31731
|
-
(0,
|
|
32097
|
+
(0, import_node_fs50.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
32098
|
+
(0, import_node_fs50.writeFileSync)(
|
|
31732
32099
|
scopedFile(ADVISORY_EPISODE_FILE, sessionId),
|
|
31733
32100
|
JSON.stringify({ v: 1, ...episode })
|
|
31734
32101
|
);
|
|
@@ -31802,6 +32169,7 @@ async function buildRequest(run4) {
|
|
|
31802
32169
|
(conversation?.prompts?.length ?? 0) > 0
|
|
31803
32170
|
);
|
|
31804
32171
|
const noteConfirmation = peekNoteOutcome();
|
|
32172
|
+
const unobserved = foldResult?.unobserved ?? [];
|
|
31805
32173
|
const excludedByReason = {};
|
|
31806
32174
|
for (const e of codeDelta.excluded ?? []) {
|
|
31807
32175
|
excludedByReason[e.reason] = (excludedByReason[e.reason] ?? 0) + 1;
|
|
@@ -31846,7 +32214,9 @@ async function buildRequest(run4) {
|
|
|
31846
32214
|
coverage_telemetry: coverageTelemetry,
|
|
31847
32215
|
static_results: staticResults,
|
|
31848
32216
|
code_delta: codeDelta,
|
|
31849
|
-
|
|
32217
|
+
// Bounded, reviewed paths first — the server applies the same bound. The
|
|
32218
|
+
// full count is `coverage_telemetry.for_review`. VRT-242.
|
|
32219
|
+
changed_files: boundPaths(allForReview, codeDelta.files.map((f) => f.path)),
|
|
31850
32220
|
standard_version: "latest",
|
|
31851
32221
|
analysis_mode: analysisMode,
|
|
31852
32222
|
plan_only: analysisMode === "plan",
|
|
@@ -31897,7 +32267,9 @@ async function buildRequest(run4) {
|
|
|
31897
32267
|
// `hash_at_last_verdict` is frozen at each verdict and `hash_now` tracks
|
|
31898
32268
|
// disk, so their inequality IS "changed since we last spoke".
|
|
31899
32269
|
authored_since_verdict: memorySession ? foldDossier(memorySession.d).authored_all.filter((a) => a.hash_now !== a.hash_at_last_verdict).map((a) => a.path) : [],
|
|
31900
|
-
|
|
32270
|
+
// The server reads only how many; a bulk change sent every path. VRT-242.
|
|
32271
|
+
unobserved: unobserved.slice(0, MAX_WIRE_PATHS),
|
|
32272
|
+
...unobserved.length > MAX_WIRE_PATHS && { unobserved_total: unobserved.length },
|
|
31901
32273
|
commands: foldResult?.commands ?? [],
|
|
31902
32274
|
tools: foldResult?.tools ?? [],
|
|
31903
32275
|
tasks: foldResult?.tasks ?? [],
|
|
@@ -32060,14 +32432,14 @@ async function buildRequest(run4) {
|
|
|
32060
32432
|
}
|
|
32061
32433
|
|
|
32062
32434
|
// src/lib/offline.ts
|
|
32063
|
-
var
|
|
32064
|
-
var
|
|
32435
|
+
var import_node_fs51 = require("node:fs");
|
|
32436
|
+
var import_node_crypto14 = require("node:crypto");
|
|
32065
32437
|
function cacheRequest(body2) {
|
|
32066
32438
|
try {
|
|
32067
|
-
(0,
|
|
32068
|
-
const suffix = (0,
|
|
32439
|
+
(0, import_node_fs51.mkdirSync)(CACHE_DIR, { recursive: true });
|
|
32440
|
+
const suffix = (0, import_node_crypto14.randomBytes)(4).toString("hex");
|
|
32069
32441
|
const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
|
|
32070
|
-
(0,
|
|
32442
|
+
(0, import_node_fs51.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
|
|
32071
32443
|
} catch {
|
|
32072
32444
|
}
|
|
32073
32445
|
}
|
|
@@ -32108,8 +32480,10 @@ function buildOfflineFallback(reason, staticResults) {
|
|
|
32108
32480
|
}
|
|
32109
32481
|
|
|
32110
32482
|
// src/lib/retry.ts
|
|
32483
|
+
var WORKER_RESOURCE_LIMIT = 546;
|
|
32111
32484
|
function shouldWarmRetryAnalyze(result) {
|
|
32112
32485
|
if (result.ok) return false;
|
|
32486
|
+
if (result.http_status === WORKER_RESOURCE_LIMIT) return false;
|
|
32113
32487
|
if (result.category === "network" || result.category === "timeout") return true;
|
|
32114
32488
|
if (result.category === "http_5xx") return true;
|
|
32115
32489
|
if (result.category === "invalid_json" && (result.http_status ?? 0) >= 500) return true;
|
|
@@ -32119,7 +32493,7 @@ function shouldWarmRetryAnalyze(result) {
|
|
|
32119
32493
|
// src/commands/analyze/phases/12-transmit.ts
|
|
32120
32494
|
async function transmit(run4) {
|
|
32121
32495
|
const { globals } = run4;
|
|
32122
|
-
const {
|
|
32496
|
+
const { requestBody, serviceUrl, staticResults, token } = run4;
|
|
32123
32497
|
const ANALYZE_TIMEOUT_MS = 1e5;
|
|
32124
32498
|
let result = await analyzeRequest({
|
|
32125
32499
|
serviceUrl,
|
|
@@ -32156,11 +32530,12 @@ async function transmit(run4) {
|
|
|
32156
32530
|
}
|
|
32157
32531
|
if (!result.ok) {
|
|
32158
32532
|
cacheRequest(requestBody);
|
|
32533
|
+
const sentKb = () => Math.round(Buffer.byteLength(JSON.stringify(requestBody)) / 1024);
|
|
32159
32534
|
let message;
|
|
32160
32535
|
if (result.http_status === 413) {
|
|
32161
|
-
|
|
32162
|
-
|
|
32163
|
-
message = `Verity:
|
|
32536
|
+
message = `Verity: request rejected \u2014 payload too large (${sentKb()} KB sent: ${result.error}). Commit or stash pre-existing changes, or run with --mode skip if you didn't intend to submit code this turn.`;
|
|
32537
|
+
} else if (result.http_status === WORKER_RESOURCE_LIMIT) {
|
|
32538
|
+
message = `Verity: the service ran out of CPU or memory on this request (HTTP 546, ${sentKb()} KB sent). This is not a cold start: the same change fails the same way, so it was not retried. Commit or stash unrelated changes to shrink the request (local analysis this run).`;
|
|
32164
32539
|
} else if (result.category === "network" || result.category === "timeout") {
|
|
32165
32540
|
message = `Verity offline \u2014 ${result.error}`;
|
|
32166
32541
|
} else if (result.error.startsWith("STALE_VERIFICATION")) {
|
|
@@ -32186,7 +32561,7 @@ async function transmit(run4) {
|
|
|
32186
32561
|
}
|
|
32187
32562
|
|
|
32188
32563
|
// src/commands/analyze/phases/13-reconcile.ts
|
|
32189
|
-
var
|
|
32564
|
+
var import_node_fs52 = require("node:fs");
|
|
32190
32565
|
var import_node_path39 = require("node:path");
|
|
32191
32566
|
async function reconcile(run4) {
|
|
32192
32567
|
const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory: memory2, memorySession, response, reviewable, securityFiles, turnId } = run4;
|
|
@@ -32216,7 +32591,7 @@ async function reconcile(run4) {
|
|
|
32216
32591
|
const st = foldDossier(memorySession.d);
|
|
32217
32592
|
openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line2) => {
|
|
32218
32593
|
try {
|
|
32219
|
-
const src = (0,
|
|
32594
|
+
const src = (0, import_node_fs52.readFileSync)((0, import_node_path39.join)(repoRoot(), file), "utf8").split("\n");
|
|
32220
32595
|
const at = src[line2 - 1];
|
|
32221
32596
|
return at === void 0 ? null : lineSha(at);
|
|
32222
32597
|
} catch {
|
|
@@ -33038,7 +33413,7 @@ function registerAnalyzeCommand(program2) {
|
|
|
33038
33413
|
var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
|
|
33039
33414
|
async function runAnalyze(opts, globals) {
|
|
33040
33415
|
if (!verityConfigured()) {
|
|
33041
|
-
(0,
|
|
33416
|
+
(0, import_node_fs53.writeSync)(2, isMachineStore((0, import_node_path40.join)(repoRoot(), VERITY_DIR)) ? "[verity] nothing to review in your home directory \u2014 run Verity inside a project.\n" : '[verity] not set up in this project \u2014 run "verity init" first.\n');
|
|
33042
33417
|
process.exit(0);
|
|
33043
33418
|
}
|
|
33044
33419
|
const run4 = createRun(opts, globals);
|
|
@@ -33059,11 +33434,41 @@ async function runAnalyze(opts, globals) {
|
|
|
33059
33434
|
}
|
|
33060
33435
|
|
|
33061
33436
|
// src/commands/baseline.ts
|
|
33437
|
+
var import_node_fs56 = require("node:fs");
|
|
33438
|
+
var import_node_path43 = require("node:path");
|
|
33439
|
+
|
|
33440
|
+
// src/lib/skew-notice.ts
|
|
33062
33441
|
var import_node_fs54 = require("node:fs");
|
|
33442
|
+
var import_node_path41 = require("node:path");
|
|
33443
|
+
var MARKER = ".skew-notice.json";
|
|
33444
|
+
function markerPath2() {
|
|
33445
|
+
return (0, import_node_path41.join)(verityHome(), MARKER);
|
|
33446
|
+
}
|
|
33447
|
+
function today(now) {
|
|
33448
|
+
const y = now.getFullYear();
|
|
33449
|
+
const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
33450
|
+
const d = String(now.getDate()).padStart(2, "0");
|
|
33451
|
+
return `${y}-${m}-${d}`;
|
|
33452
|
+
}
|
|
33453
|
+
function skewNoticeDue(skew, now = /* @__PURE__ */ new Date()) {
|
|
33454
|
+
try {
|
|
33455
|
+
const seen = JSON.parse((0, import_node_fs54.readFileSync)(markerPath2(), "utf-8"));
|
|
33456
|
+
return !(seen.global === skew.global && seen.hooks === skew.hooks && seen.day === today(now));
|
|
33457
|
+
} catch {
|
|
33458
|
+
return true;
|
|
33459
|
+
}
|
|
33460
|
+
}
|
|
33461
|
+
function recordSkewNotice(skew, now = /* @__PURE__ */ new Date()) {
|
|
33462
|
+
try {
|
|
33463
|
+
(0, import_node_fs54.mkdirSync)(verityHome(), { recursive: true, mode: 448 });
|
|
33464
|
+
(0, import_node_fs54.writeFileSync)(markerPath2(), JSON.stringify({ global: skew.global, hooks: skew.hooks, day: today(now) }) + "\n");
|
|
33465
|
+
} catch {
|
|
33466
|
+
}
|
|
33467
|
+
}
|
|
33063
33468
|
|
|
33064
33469
|
// src/lib/project-skills.ts
|
|
33065
|
-
var
|
|
33066
|
-
var
|
|
33470
|
+
var import_node_fs55 = require("node:fs");
|
|
33471
|
+
var import_node_path42 = require("node:path");
|
|
33067
33472
|
var PROJECT_SKILL_NAMES = [
|
|
33068
33473
|
"verity-setup",
|
|
33069
33474
|
"verity-analyze",
|
|
@@ -33089,14 +33494,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
33089
33494
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
33090
33495
|
function staleProjectSkills() {
|
|
33091
33496
|
const root = projectPath(".claude/skills");
|
|
33092
|
-
if (!(0,
|
|
33093
|
-
return ALL.filter((name2) => (0,
|
|
33497
|
+
if (!(0, import_node_fs55.existsSync)(root)) return [];
|
|
33498
|
+
return ALL.filter((name2) => (0, import_node_fs55.existsSync)((0, import_node_path42.join)(root, name2)));
|
|
33094
33499
|
}
|
|
33095
33500
|
function removeProjectSkills() {
|
|
33096
33501
|
const root = projectPath(".claude/skills");
|
|
33097
33502
|
const removed = [];
|
|
33098
33503
|
for (const name2 of staleProjectSkills()) {
|
|
33099
|
-
(0,
|
|
33504
|
+
(0, import_node_fs55.rmSync)((0, import_node_path42.join)(root, name2), { recursive: true, force: true });
|
|
33100
33505
|
removed.push(name2);
|
|
33101
33506
|
}
|
|
33102
33507
|
return removed;
|
|
@@ -33126,9 +33531,12 @@ function registerBaselineCommands(program2) {
|
|
|
33126
33531
|
const skew = cliVersionSkew();
|
|
33127
33532
|
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";
|
|
33128
33533
|
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;
|
|
33129
|
-
const
|
|
33130
|
-
const
|
|
33534
|
+
const skewLoud = !!skew && skewNoticeDue(skew);
|
|
33535
|
+
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;
|
|
33536
|
+
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.";
|
|
33537
|
+
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}`;
|
|
33131
33538
|
if (!verityConfigured()) {
|
|
33539
|
+
if (isMachineStore((0, import_node_path43.join)(repoRoot(), VERITY_DIR))) process.exit(0);
|
|
33132
33540
|
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.";
|
|
33133
33541
|
const lines = [
|
|
33134
33542
|
`Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
|
|
@@ -33155,19 +33563,20 @@ function registerBaselineCommands(program2) {
|
|
|
33155
33563
|
}
|
|
33156
33564
|
}) + "\n"
|
|
33157
33565
|
);
|
|
33566
|
+
if (skew && skewMsg) recordSkewNotice(skew);
|
|
33158
33567
|
process.exit(0);
|
|
33159
33568
|
}
|
|
33160
33569
|
const realStart = source2 === void 0 || source2 === "startup" || source2 === "clear";
|
|
33161
33570
|
let memoryMsg = null;
|
|
33162
33571
|
let memoryAgentLine = null;
|
|
33163
33572
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
33164
|
-
if (realStart && !(0,
|
|
33573
|
+
if (realStart && !(0, import_node_fs56.existsSync)(memoryNotice)) {
|
|
33165
33574
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
33166
33575
|
if (trackedGraph > 0) {
|
|
33167
33576
|
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.`;
|
|
33168
33577
|
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.`;
|
|
33169
33578
|
try {
|
|
33170
|
-
(0,
|
|
33579
|
+
(0, import_node_fs56.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
33171
33580
|
} catch {
|
|
33172
33581
|
}
|
|
33173
33582
|
}
|
|
@@ -33195,7 +33604,7 @@ function registerBaselineCommands(program2) {
|
|
|
33195
33604
|
}
|
|
33196
33605
|
}
|
|
33197
33606
|
if (memoryAgentLine) notices.push(memoryAgentLine);
|
|
33198
|
-
if (notices.length > 0) {
|
|
33607
|
+
if (notices.length > 0 || skewMsg) {
|
|
33199
33608
|
process.stdout.write(
|
|
33200
33609
|
JSON.stringify({
|
|
33201
33610
|
...userMsg || skewMsg || memoryMsg ? { systemMessage: [skewMsg, userMsg, memoryMsg].filter(Boolean).join("\n") } : {},
|
|
@@ -33205,6 +33614,7 @@ function registerBaselineCommands(program2) {
|
|
|
33205
33614
|
}
|
|
33206
33615
|
}) + "\n"
|
|
33207
33616
|
);
|
|
33617
|
+
if (skew && skewMsg) recordSkewNotice(skew);
|
|
33208
33618
|
}
|
|
33209
33619
|
} else if (memoryMsg) {
|
|
33210
33620
|
process.stdout.write(
|
|
@@ -33268,10 +33678,16 @@ function hookSource(value) {
|
|
|
33268
33678
|
}
|
|
33269
33679
|
|
|
33270
33680
|
// src/commands/review.ts
|
|
33271
|
-
var
|
|
33681
|
+
var import_node_fs57 = require("node:fs");
|
|
33272
33682
|
function registerReviewCommand(program2) {
|
|
33273
|
-
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)").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
|
|
33683
|
+
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) => {
|
|
33274
33684
|
const globals = program2.opts();
|
|
33685
|
+
const intent = readTextInput(opts.intent, "--intent");
|
|
33686
|
+
if (!intent.ok) {
|
|
33687
|
+
printError(intent.error);
|
|
33688
|
+
process.exit(0);
|
|
33689
|
+
}
|
|
33690
|
+
opts.intent = intent.text;
|
|
33275
33691
|
try {
|
|
33276
33692
|
await runReview(opts, globals);
|
|
33277
33693
|
} catch (err2) {
|
|
@@ -33285,7 +33701,7 @@ async function runReview(opts, globals) {
|
|
|
33285
33701
|
const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
|
|
33286
33702
|
const analyzable = filterAnalyzable(allFiles);
|
|
33287
33703
|
const securityFiles = filterSecurity(allFiles);
|
|
33288
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
33704
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs57.existsSync)(f) || resolveFile(f) !== null);
|
|
33289
33705
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
33290
33706
|
const codeDelta = collectCodeDelta(allFiles);
|
|
33291
33707
|
const tokenResult = await resolveToken(globals.token);
|
|
@@ -33351,19 +33767,40 @@ async function runReview(opts, globals) {
|
|
|
33351
33767
|
}
|
|
33352
33768
|
|
|
33353
33769
|
// src/commands/guard.ts
|
|
33354
|
-
var
|
|
33355
|
-
var
|
|
33770
|
+
var import_node_fs62 = require("node:fs");
|
|
33771
|
+
var import_node_path49 = require("node:path");
|
|
33356
33772
|
|
|
33357
|
-
// src/lib/
|
|
33358
|
-
var
|
|
33359
|
-
|
|
33360
|
-
|
|
33361
|
-
|
|
33362
|
-
|
|
33773
|
+
// src/lib/vendored.ts
|
|
33774
|
+
var import_node_fs58 = require("node:fs");
|
|
33775
|
+
var import_node_path44 = require("node:path");
|
|
33776
|
+
var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
|
|
33777
|
+
function dataDirOrNull() {
|
|
33778
|
+
try {
|
|
33779
|
+
return resolveDataDir();
|
|
33780
|
+
} catch {
|
|
33781
|
+
return null;
|
|
33782
|
+
}
|
|
33363
33783
|
}
|
|
33364
|
-
function
|
|
33365
|
-
const
|
|
33366
|
-
|
|
33784
|
+
function shippedSkillFile(path, dataDir = dataDirOrNull()) {
|
|
33785
|
+
const m = path.replace(/\\/g, "/").match(INSTALLED_SKILL);
|
|
33786
|
+
if (!m || !dataDir) return null;
|
|
33787
|
+
const [, skill, rel] = m;
|
|
33788
|
+
if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
|
|
33789
|
+
try {
|
|
33790
|
+
return (0, import_node_fs58.readFileSync)((0, import_node_path44.join)(dataDir, "skills", skill, rel), "utf8");
|
|
33791
|
+
} catch {
|
|
33792
|
+
return null;
|
|
33793
|
+
}
|
|
33794
|
+
}
|
|
33795
|
+
function partitionVendored(files, read2, dataDir = dataDirOrNull()) {
|
|
33796
|
+
const review = [];
|
|
33797
|
+
const vendored = [];
|
|
33798
|
+
for (const f of files) {
|
|
33799
|
+
const shipped = shippedSkillFile(f, dataDir);
|
|
33800
|
+
if (shipped !== null && read2(f) === shipped) vendored.push(f);
|
|
33801
|
+
else review.push(f);
|
|
33802
|
+
}
|
|
33803
|
+
return { review, vendored };
|
|
33367
33804
|
}
|
|
33368
33805
|
|
|
33369
33806
|
// src/lib/agent-driver.ts
|
|
@@ -33445,7 +33882,7 @@ async function runAgentReview(options) {
|
|
|
33445
33882
|
}
|
|
33446
33883
|
if (!settled) {
|
|
33447
33884
|
const wait = Math.max(0, remaining() - FINISH_TIMEOUT_MS);
|
|
33448
|
-
await Promise.race([oneShotDone, new Promise((
|
|
33885
|
+
await Promise.race([oneShotDone, new Promise((resolve9) => setTimeout(resolve9, wait))]);
|
|
33449
33886
|
}
|
|
33450
33887
|
const finished = await options.http.post(
|
|
33451
33888
|
"/agent-review/finish",
|
|
@@ -33460,8 +33897,8 @@ async function runAgentReview(options) {
|
|
|
33460
33897
|
}
|
|
33461
33898
|
|
|
33462
33899
|
// src/lib/prove/auto.ts
|
|
33463
|
-
var
|
|
33464
|
-
var
|
|
33900
|
+
var import_node_path48 = require("node:path");
|
|
33901
|
+
var import_node_crypto19 = require("node:crypto");
|
|
33465
33902
|
|
|
33466
33903
|
// src/lib/prove/signals.ts
|
|
33467
33904
|
var DEFAULT_SINCE = "180 days ago";
|
|
@@ -35187,18 +35624,18 @@ function renderReplay(model, property, r) {
|
|
|
35187
35624
|
// src/lib/prove/runner.ts
|
|
35188
35625
|
var import_node_child_process15 = require("node:child_process");
|
|
35189
35626
|
var import_node_os8 = require("node:os");
|
|
35190
|
-
var
|
|
35627
|
+
var import_node_fs61 = require("node:fs");
|
|
35191
35628
|
var import_node_os9 = require("node:os");
|
|
35192
|
-
var
|
|
35629
|
+
var import_node_path47 = require("node:path");
|
|
35193
35630
|
|
|
35194
35631
|
// src/lib/prove/scaffold.ts
|
|
35195
|
-
var
|
|
35196
|
-
var
|
|
35632
|
+
var import_node_fs60 = require("node:fs");
|
|
35633
|
+
var import_node_path46 = require("node:path");
|
|
35197
35634
|
|
|
35198
35635
|
// src/lib/prove/safe-write.ts
|
|
35199
|
-
var
|
|
35200
|
-
var
|
|
35201
|
-
var
|
|
35636
|
+
var import_node_fs59 = require("node:fs");
|
|
35637
|
+
var import_node_crypto15 = require("node:crypto");
|
|
35638
|
+
var import_node_path45 = require("node:path");
|
|
35202
35639
|
var SafeWriteError = class extends Error {
|
|
35203
35640
|
constructor(reason, path) {
|
|
35204
35641
|
super(`refusing to write ${path}: ${reason}`);
|
|
@@ -35207,10 +35644,10 @@ var SafeWriteError = class extends Error {
|
|
|
35207
35644
|
this.name = "SafeWriteError";
|
|
35208
35645
|
}
|
|
35209
35646
|
};
|
|
35210
|
-
var FLAGS3 =
|
|
35647
|
+
var FLAGS3 = import_node_fs59.constants;
|
|
35211
35648
|
var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
|
|
35212
35649
|
function assertPlainRelative(rel) {
|
|
35213
|
-
if (!rel || (0,
|
|
35650
|
+
if (!rel || (0, import_node_path45.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
|
|
35214
35651
|
for (const part of rel.split(/[\\/]/)) {
|
|
35215
35652
|
if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
|
|
35216
35653
|
}
|
|
@@ -35219,34 +35656,34 @@ function ensureDirsNoFollow(root, rel) {
|
|
|
35219
35656
|
const parts2 = rel.split(/[\\/]/);
|
|
35220
35657
|
let cur = root;
|
|
35221
35658
|
for (const part of parts2.slice(0, -1)) {
|
|
35222
|
-
cur = (0,
|
|
35659
|
+
cur = (0, import_node_path45.join)(cur, part);
|
|
35223
35660
|
let st;
|
|
35224
35661
|
try {
|
|
35225
|
-
st = (0,
|
|
35662
|
+
st = (0, import_node_fs59.lstatSync)(cur);
|
|
35226
35663
|
} catch {
|
|
35227
|
-
(0,
|
|
35664
|
+
(0, import_node_fs59.mkdirSync)(cur);
|
|
35228
35665
|
continue;
|
|
35229
35666
|
}
|
|
35230
35667
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
|
|
35231
35668
|
if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
|
|
35232
35669
|
}
|
|
35233
|
-
return (0,
|
|
35670
|
+
return (0, import_node_path45.join)(root, rel);
|
|
35234
35671
|
}
|
|
35235
35672
|
function insideRoot(realRoot, realPath) {
|
|
35236
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
35673
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path45.sep) ? realRoot : realRoot + import_node_path45.sep);
|
|
35237
35674
|
}
|
|
35238
35675
|
function removeQuietly(path) {
|
|
35239
35676
|
try {
|
|
35240
|
-
(0,
|
|
35677
|
+
(0, import_node_fs59.unlinkSync)(path);
|
|
35241
35678
|
} catch {
|
|
35242
35679
|
}
|
|
35243
35680
|
}
|
|
35244
35681
|
function writeFileInRootNoFollow(root, rel, content) {
|
|
35245
35682
|
assertPlainRelative(rel);
|
|
35246
35683
|
const dest = ensureDirsNoFollow(root, rel);
|
|
35247
|
-
const dir = (0,
|
|
35684
|
+
const dir = (0, import_node_path45.dirname)(dest);
|
|
35248
35685
|
try {
|
|
35249
|
-
const st = (0,
|
|
35686
|
+
const st = (0, import_node_fs59.lstatSync)(dest);
|
|
35250
35687
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
|
|
35251
35688
|
if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
|
|
35252
35689
|
} catch (err2) {
|
|
@@ -35254,41 +35691,41 @@ function writeFileInRootNoFollow(root, rel, content) {
|
|
|
35254
35691
|
}
|
|
35255
35692
|
let realRoot;
|
|
35256
35693
|
try {
|
|
35257
|
-
realRoot = (0,
|
|
35694
|
+
realRoot = (0, import_node_fs59.realpathSync)(root);
|
|
35258
35695
|
} catch {
|
|
35259
35696
|
throw new SafeWriteError("unwritable", root);
|
|
35260
35697
|
}
|
|
35261
|
-
const tmp = (0,
|
|
35698
|
+
const tmp = (0, import_node_path45.join)(dir, `.${(0, import_node_path45.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
|
|
35262
35699
|
let fd;
|
|
35263
35700
|
try {
|
|
35264
|
-
fd = (0,
|
|
35701
|
+
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);
|
|
35265
35702
|
} catch {
|
|
35266
35703
|
throw new SafeWriteError("unwritable", tmp);
|
|
35267
35704
|
}
|
|
35268
35705
|
try {
|
|
35269
|
-
const opened = (0,
|
|
35706
|
+
const opened = (0, import_node_fs59.fstatSync)(fd, { bigint: true });
|
|
35270
35707
|
let realTmp;
|
|
35271
35708
|
try {
|
|
35272
|
-
realTmp = (0,
|
|
35709
|
+
realTmp = (0, import_node_fs59.realpathSync)(tmp);
|
|
35273
35710
|
} catch {
|
|
35274
35711
|
throw new SafeWriteError("escaped", tmp);
|
|
35275
35712
|
}
|
|
35276
|
-
const there = (0,
|
|
35713
|
+
const there = (0, import_node_fs59.lstatSync)(realTmp, { bigint: true });
|
|
35277
35714
|
if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
|
|
35278
35715
|
throw new SafeWriteError("escaped", tmp);
|
|
35279
35716
|
}
|
|
35280
35717
|
const buf = Buffer.from(content, "utf-8");
|
|
35281
35718
|
let off = 0;
|
|
35282
|
-
while (off < buf.length) off += (0,
|
|
35719
|
+
while (off < buf.length) off += (0, import_node_fs59.writeSync)(fd, buf, off, buf.length - off);
|
|
35283
35720
|
} catch (err2) {
|
|
35284
|
-
(0,
|
|
35721
|
+
(0, import_node_fs59.closeSync)(fd);
|
|
35285
35722
|
removeQuietly(tmp);
|
|
35286
35723
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
|
|
35287
35724
|
}
|
|
35288
|
-
(0,
|
|
35725
|
+
(0, import_node_fs59.closeSync)(fd);
|
|
35289
35726
|
try {
|
|
35290
|
-
if (!insideRoot(realRoot, (0,
|
|
35291
|
-
(0,
|
|
35727
|
+
if (!insideRoot(realRoot, (0, import_node_fs59.realpathSync)(dir)) || (0, import_node_fs59.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
|
|
35728
|
+
(0, import_node_fs59.renameSync)(tmp, dest);
|
|
35292
35729
|
} catch (err2) {
|
|
35293
35730
|
removeQuietly(tmp);
|
|
35294
35731
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
|
|
@@ -35302,9 +35739,9 @@ function pathHasNoLink(root, rel) {
|
|
|
35302
35739
|
}
|
|
35303
35740
|
let cur = root;
|
|
35304
35741
|
for (const part of rel.split(/[\\/]/)) {
|
|
35305
|
-
cur = cur +
|
|
35742
|
+
cur = cur + import_node_path45.sep + part;
|
|
35306
35743
|
try {
|
|
35307
|
-
if ((0,
|
|
35744
|
+
if ((0, import_node_fs59.lstatSync)(cur).isSymbolicLink()) return false;
|
|
35308
35745
|
} catch {
|
|
35309
35746
|
return true;
|
|
35310
35747
|
}
|
|
@@ -35614,20 +36051,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
|
|
|
35614
36051
|
never committed; what reaches the team is the bug report and the fix.
|
|
35615
36052
|
`;
|
|
35616
36053
|
function scaffoldProofs(root) {
|
|
35617
|
-
const proofsDir = (0,
|
|
36054
|
+
const proofsDir = (0, import_node_path46.join)(root, PROOFS_DIR);
|
|
35618
36055
|
const written = [];
|
|
35619
36056
|
const kept = [];
|
|
35620
36057
|
for (const stray of ["lakefile.lean"]) {
|
|
35621
36058
|
const rel = `${PROOFS_DIR}/${stray}`;
|
|
35622
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36059
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path46.join)(root, rel));
|
|
35623
36060
|
try {
|
|
35624
|
-
(0,
|
|
36061
|
+
(0, import_node_fs60.rmSync)((0, import_node_path46.join)(root, rel), { force: true });
|
|
35625
36062
|
} catch {
|
|
35626
36063
|
}
|
|
35627
36064
|
}
|
|
35628
36065
|
for (const f of PROOFS_TEMPLATE_FILES) {
|
|
35629
36066
|
const rel = `${PROOFS_DIR}/${f.path}`;
|
|
35630
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36067
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path46.join)(root, rel));
|
|
35631
36068
|
const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
|
|
35632
36069
|
if (current.ok && current.content === f.content) {
|
|
35633
36070
|
kept.push(rel);
|
|
@@ -35640,8 +36077,8 @@ function scaffoldProofs(root) {
|
|
|
35640
36077
|
[`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
|
|
35641
36078
|
[`${MODELS_DIR}/README.md`, MODELS_README]
|
|
35642
36079
|
]) {
|
|
35643
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
35644
|
-
if (existsNoFollow((0,
|
|
36080
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path46.join)(root, rel));
|
|
36081
|
+
if (existsNoFollow((0, import_node_path46.join)(root, rel))) {
|
|
35645
36082
|
kept.push(rel);
|
|
35646
36083
|
continue;
|
|
35647
36084
|
}
|
|
@@ -35652,7 +36089,7 @@ function scaffoldProofs(root) {
|
|
|
35652
36089
|
}
|
|
35653
36090
|
function existsNoFollow(abs) {
|
|
35654
36091
|
try {
|
|
35655
|
-
(0,
|
|
36092
|
+
(0, import_node_fs60.lstatSync)(abs);
|
|
35656
36093
|
return true;
|
|
35657
36094
|
} catch {
|
|
35658
36095
|
return false;
|
|
@@ -35660,7 +36097,7 @@ function existsNoFollow(abs) {
|
|
|
35660
36097
|
}
|
|
35661
36098
|
|
|
35662
36099
|
// src/lib/prove/report.ts
|
|
35663
|
-
var
|
|
36100
|
+
var import_node_crypto16 = require("node:crypto");
|
|
35664
36101
|
var IDENT2 = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$/;
|
|
35665
36102
|
var SHA256 = /^(sha256:)?[0-9a-f]{64}$/;
|
|
35666
36103
|
var KINDS2 = /* @__PURE__ */ new Set(["structural", "intent"]);
|
|
@@ -35808,7 +36245,7 @@ function sha256InRoot(root, file) {
|
|
|
35808
36245
|
const opened = openRegularInRoot(root, file);
|
|
35809
36246
|
if (!opened.ok) return null;
|
|
35810
36247
|
try {
|
|
35811
|
-
return (0,
|
|
36248
|
+
return (0, import_node_crypto16.createHash)("sha256").update(readOpened(opened.fd, opened.size)).digest("hex");
|
|
35812
36249
|
} catch {
|
|
35813
36250
|
return null;
|
|
35814
36251
|
}
|
|
@@ -35910,17 +36347,17 @@ function renderReport(r) {
|
|
|
35910
36347
|
|
|
35911
36348
|
// src/lib/prove/runner.ts
|
|
35912
36349
|
function verityLeanHome(env = process.env) {
|
|
35913
|
-
return env.VERITY_LEAN_HOME ?? (0,
|
|
36350
|
+
return env.VERITY_LEAN_HOME ?? (0, import_node_path47.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
|
|
35914
36351
|
}
|
|
35915
36352
|
function findToolchain(env = process.env) {
|
|
35916
|
-
const managedBin = (0,
|
|
35917
|
-
const elanBin = (0,
|
|
35918
|
-
const elanHas = (0,
|
|
35919
|
-
const userPath = (env.PATH ?? "").split(
|
|
35920
|
-
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(
|
|
36353
|
+
const managedBin = (0, import_node_path47.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
|
|
36354
|
+
const elanBin = (0, import_node_path47.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
|
|
36355
|
+
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(":", "---")));
|
|
36356
|
+
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)));
|
|
36357
|
+
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path47.delimiter);
|
|
35921
36358
|
const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
|
|
35922
36359
|
const exe = process.platform === "win32" ? "lake.exe" : "lake";
|
|
35923
|
-
const candidates2 = [(0,
|
|
36360
|
+
const candidates2 = [(0, import_node_path47.join)(managedBin, exe), ...elanHas ? [(0, import_node_path47.join)(elanBin, exe)] : [], exe];
|
|
35924
36361
|
for (const candidate of candidates2) {
|
|
35925
36362
|
try {
|
|
35926
36363
|
(0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
|
|
@@ -35958,7 +36395,7 @@ function run2(tc, cwd, args2, timeoutMs) {
|
|
|
35958
36395
|
function runAsync(tc, cwd, args2, timeoutMs) {
|
|
35959
36396
|
const started = Date.now();
|
|
35960
36397
|
const MAX = 16 * 1024 * 1024;
|
|
35961
|
-
return new Promise((
|
|
36398
|
+
return new Promise((resolve9) => {
|
|
35962
36399
|
const posix = (0, import_node_os8.platform)() !== "win32";
|
|
35963
36400
|
const child = (0, import_node_child_process15.spawn)(tc.lake, args2, { cwd, env: tc.env, stdio: ["ignore", "pipe", "pipe"], detached: posix });
|
|
35964
36401
|
let stdout = "";
|
|
@@ -35986,8 +36423,8 @@ function runAsync(tc, cwd, args2, timeoutMs) {
|
|
|
35986
36423
|
if (settled) return;
|
|
35987
36424
|
settled = true;
|
|
35988
36425
|
clearTimeout(timer);
|
|
35989
|
-
if (ok)
|
|
35990
|
-
else
|
|
36426
|
+
if (ok) resolve9({ ok: true, stdout, stderr: "", durationMs: Date.now() - started, timedOut: false });
|
|
36427
|
+
else resolve9({ ok: false, stdout, stderr: stderr || message || "", durationMs: Date.now() - started, timedOut });
|
|
35991
36428
|
};
|
|
35992
36429
|
child.on("error", (err2) => finish(false, err2.message));
|
|
35993
36430
|
child.on("close", (code) => finish(code === 0 && !timedOut));
|
|
@@ -35999,7 +36436,7 @@ function proofsWorkspaceProblem(root) {
|
|
|
35999
36436
|
for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
|
|
36000
36437
|
let st;
|
|
36001
36438
|
try {
|
|
36002
|
-
st = (0,
|
|
36439
|
+
st = (0, import_node_fs61.lstatSync)((0, import_node_path47.join)(root, rel));
|
|
36003
36440
|
} catch {
|
|
36004
36441
|
break;
|
|
36005
36442
|
}
|
|
@@ -36019,44 +36456,44 @@ function refused(problem) {
|
|
|
36019
36456
|
function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36020
36457
|
const problem = proofsWorkspaceProblem(root);
|
|
36021
36458
|
if (problem) return refused(problem);
|
|
36022
|
-
return run2(tc, (0,
|
|
36459
|
+
return run2(tc, (0, import_node_path47.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36023
36460
|
}
|
|
36024
36461
|
async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36025
36462
|
const problem = proofsWorkspaceProblem(root);
|
|
36026
36463
|
if (problem) return refused(problem);
|
|
36027
|
-
return runAsync(tc, (0,
|
|
36464
|
+
return runAsync(tc, (0, import_node_path47.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36028
36465
|
}
|
|
36029
36466
|
function isModelInRoot(modelsAbs, rel) {
|
|
36030
|
-
if (!rel.endsWith(".lean") || (0,
|
|
36467
|
+
if (!rel.endsWith(".lean") || (0, import_node_path47.isAbsolute)(rel) || rel.startsWith("..")) return false;
|
|
36031
36468
|
return statRegularInRoot(modelsAbs, rel).ok;
|
|
36032
36469
|
}
|
|
36033
36470
|
function resolveModelFile(root, arg) {
|
|
36034
|
-
const modelsAbs = (0,
|
|
36035
|
-
const asPath = (0,
|
|
36471
|
+
const modelsAbs = (0, import_node_path47.join)(root, MODELS_DIR);
|
|
36472
|
+
const asPath = (0, import_node_path47.relative)(modelsAbs, (0, import_node_path47.isAbsolute)(arg) ? arg : (0, import_node_path47.resolve)(root, arg));
|
|
36036
36473
|
const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
|
|
36037
36474
|
for (const rel of candidates2) {
|
|
36038
|
-
if (isModelInRoot(modelsAbs, rel)) return (0,
|
|
36475
|
+
if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path47.join)(modelsAbs, rel);
|
|
36039
36476
|
}
|
|
36040
36477
|
return null;
|
|
36041
36478
|
}
|
|
36042
36479
|
function listModelFiles(root) {
|
|
36043
|
-
const modelsAbs = (0,
|
|
36044
|
-
if (!(0,
|
|
36045
|
-
return (0,
|
|
36480
|
+
const modelsAbs = (0, import_node_path47.join)(root, MODELS_DIR);
|
|
36481
|
+
if (!(0, import_node_fs61.existsSync)(modelsAbs)) return [];
|
|
36482
|
+
return (0, import_node_fs61.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path47.join)(modelsAbs, f));
|
|
36046
36483
|
}
|
|
36047
36484
|
function trimDiagnostics(text) {
|
|
36048
36485
|
return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
|
|
36049
36486
|
}
|
|
36050
36487
|
function checkModel(tc, root, modelFile, opts = {}) {
|
|
36051
|
-
const proofsAbs = (0,
|
|
36052
|
-
const rel = (0,
|
|
36488
|
+
const proofsAbs = (0, import_node_path47.join)(root, PROOFS_DIR);
|
|
36489
|
+
const rel = (0, import_node_path47.relative)(proofsAbs, modelFile);
|
|
36053
36490
|
const problem = proofsWorkspaceProblem(root);
|
|
36054
36491
|
const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36055
36492
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36056
36493
|
}
|
|
36057
36494
|
async function checkModelAsync(tc, root, modelFile, opts = {}) {
|
|
36058
|
-
const proofsAbs = (0,
|
|
36059
|
-
const rel = (0,
|
|
36495
|
+
const proofsAbs = (0, import_node_path47.join)(root, PROOFS_DIR);
|
|
36496
|
+
const rel = (0, import_node_path47.relative)(proofsAbs, modelFile);
|
|
36060
36497
|
const problem = proofsWorkspaceProblem(root);
|
|
36061
36498
|
const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36062
36499
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
@@ -36065,10 +36502,10 @@ function toReport(res, root, modelFile, timeoutMs) {
|
|
|
36065
36502
|
const parsed = parseVerityLines(res.stdout);
|
|
36066
36503
|
const combined = `${res.stdout}
|
|
36067
36504
|
${res.stderr}`;
|
|
36068
|
-
const name2 = parsed.header?.model ?? (0,
|
|
36505
|
+
const name2 = parsed.header?.model ?? (0, import_node_path47.basename)(modelFile, ".lean");
|
|
36069
36506
|
const report = {
|
|
36070
36507
|
model: name2,
|
|
36071
|
-
file: (0,
|
|
36508
|
+
file: (0, import_node_path47.relative)(root, modelFile),
|
|
36072
36509
|
ok: res.ok,
|
|
36073
36510
|
header: parsed.header,
|
|
36074
36511
|
properties: parsed.properties,
|
|
@@ -36143,7 +36580,7 @@ function mergeFormalFindings(response, outcome, pushedFiles) {
|
|
|
36143
36580
|
}
|
|
36144
36581
|
|
|
36145
36582
|
// src/lib/prove/scalpel.ts
|
|
36146
|
-
var
|
|
36583
|
+
var import_node_crypto17 = require("node:crypto");
|
|
36147
36584
|
var ARITHMETIC = /Math\.(?:round|floor|ceil|trunc)\(|\bround\(|\bdivmod\(|[\w)\]]\s*(?:\*|\/(?!\/)|%)\s*[\w(]/;
|
|
36148
36585
|
function functionHazard(numbered2) {
|
|
36149
36586
|
const sites = effectSites(numbered2);
|
|
@@ -36173,7 +36610,7 @@ function semanticFingerprint(numbered2) {
|
|
|
36173
36610
|
if (LOG_LINE.test(t)) continue;
|
|
36174
36611
|
kept.push(t.replace(/\s+/g, " "));
|
|
36175
36612
|
}
|
|
36176
|
-
return (0,
|
|
36613
|
+
return (0, import_node_crypto17.createHash)("sha256").update(kept.join("\n")).digest("hex");
|
|
36177
36614
|
}
|
|
36178
36615
|
function readVerified(root, now = Date.now()) {
|
|
36179
36616
|
const read2 = readRegularFileInRoot(root, VERIFIED_FILE, 256 * 1024);
|
|
@@ -36196,9 +36633,9 @@ function recordVerified(root, rec, now = Date.now()) {
|
|
|
36196
36633
|
}
|
|
36197
36634
|
|
|
36198
36635
|
// src/lib/prove/context.ts
|
|
36199
|
-
var
|
|
36636
|
+
var import_node_crypto18 = require("node:crypto");
|
|
36200
36637
|
var CONTEXT_BUDGET_MS = 2e3;
|
|
36201
|
-
var sha256 = (s) => (0,
|
|
36638
|
+
var sha256 = (s) => (0, import_node_crypto18.createHash)("sha256").update(s).digest("hex");
|
|
36202
36639
|
var TEST_PATH4 = /(^|\/)(tests?|__tests__|spec)\/|\.(test|spec)\.[a-z]+$/;
|
|
36203
36640
|
function slice(content, f, maxLines) {
|
|
36204
36641
|
const all = content.split("\n");
|
|
@@ -36313,15 +36750,15 @@ function nonNegative(v) {
|
|
|
36313
36750
|
return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
|
|
36314
36751
|
}
|
|
36315
36752
|
function readLedger(root) {
|
|
36316
|
-
const
|
|
36317
|
-
const empty = { day:
|
|
36753
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
36754
|
+
const empty = { day: today2, models: 0, costUsd: 0 };
|
|
36318
36755
|
if (!isLocalState(root, AUTO_LEDGER)) return empty;
|
|
36319
36756
|
const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
|
|
36320
36757
|
if (!read2.ok) return empty;
|
|
36321
36758
|
try {
|
|
36322
36759
|
const o = JSON.parse(read2.content);
|
|
36323
|
-
if (o.day !==
|
|
36324
|
-
return { day:
|
|
36760
|
+
if (o.day !== today2 || typeof o.models !== "number") return empty;
|
|
36761
|
+
return { day: today2, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
|
|
36325
36762
|
} catch {
|
|
36326
36763
|
return empty;
|
|
36327
36764
|
}
|
|
@@ -36387,7 +36824,7 @@ function workingTreeReader(root) {
|
|
|
36387
36824
|
};
|
|
36388
36825
|
}
|
|
36389
36826
|
function sha256Of(content) {
|
|
36390
|
-
return (0,
|
|
36827
|
+
return (0, import_node_crypto19.createHash)("sha256").update(content).digest("hex");
|
|
36391
36828
|
}
|
|
36392
36829
|
function defaultDeps(opts) {
|
|
36393
36830
|
const env = opts.env ?? process.env;
|
|
@@ -36638,7 +37075,7 @@ async function runFormalPhase(input) {
|
|
|
36638
37075
|
modelName = gen.name;
|
|
36639
37076
|
const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
|
|
36640
37077
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
36641
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37078
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path48.join)(root, rel);
|
|
36642
37079
|
progress.model = { name: gen.name, file: rel, rounds: round };
|
|
36643
37080
|
progress.step = "check";
|
|
36644
37081
|
report = await deps.check(root, abs);
|
|
@@ -36699,11 +37136,11 @@ async function runFormalPhase(input) {
|
|
|
36699
37136
|
const budget = Math.max(2e4, timeLeft() - 5e3);
|
|
36700
37137
|
const byId = /* @__PURE__ */ new Map();
|
|
36701
37138
|
let stoppedEarly = false;
|
|
36702
|
-
await new Promise((
|
|
37139
|
+
await new Promise((resolve9) => {
|
|
36703
37140
|
let left = toReplay.length;
|
|
36704
|
-
if (left === 0) return
|
|
37141
|
+
if (left === 0) return resolve9();
|
|
36705
37142
|
const settle = () => {
|
|
36706
|
-
if (--left === 0)
|
|
37143
|
+
if (--left === 0) resolve9();
|
|
36707
37144
|
};
|
|
36708
37145
|
for (const p of toReplay) {
|
|
36709
37146
|
void (async () => {
|
|
@@ -36716,7 +37153,7 @@ async function runFormalPhase(input) {
|
|
|
36716
37153
|
if (!stoppedEarly) byId.set(p.id, r);
|
|
36717
37154
|
if (r.verdict === "reproduced" && !stoppedEarly && !isCrash(p)) {
|
|
36718
37155
|
stoppedEarly = true;
|
|
36719
|
-
|
|
37156
|
+
resolve9();
|
|
36720
37157
|
}
|
|
36721
37158
|
})().catch(() => {
|
|
36722
37159
|
byId.set(p.id, null);
|
|
@@ -36760,7 +37197,7 @@ async function runFormalPhase(input) {
|
|
|
36760
37197
|
return done({
|
|
36761
37198
|
status: "checked",
|
|
36762
37199
|
target,
|
|
36763
|
-
model: { name: modelName, file: (0,
|
|
37200
|
+
model: { name: modelName, file: (0, import_node_path48.relative)(root, (0, import_node_path48.join)(root, modelFile)), rounds },
|
|
36764
37201
|
properties: report.properties,
|
|
36765
37202
|
findings
|
|
36766
37203
|
});
|
|
@@ -36793,7 +37230,19 @@ async function generateAndCheck(root, req, opts) {
|
|
|
36793
37230
|
const read2 = readSrc(req.file, 96 * 1024);
|
|
36794
37231
|
if (!read2.ok) return { ok: false, error: `${req.file}: ${read2.reason}`, rounds: 0, costUsd: 0 };
|
|
36795
37232
|
const sha2562 = sha256Of(read2.content);
|
|
36796
|
-
const { lines, numbered: numbered2 } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
|
|
37233
|
+
const { lines, numbered: numbered2, extent } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
|
|
37234
|
+
let warning;
|
|
37235
|
+
if (!lines) {
|
|
37236
|
+
const outline = extent === "fallback:not-found" ? opts.deps.codeMap?.outline(req.file, read2.content) : void 0;
|
|
37237
|
+
if (outline?.source === "tree-sitter") {
|
|
37238
|
+
const names2 = [...new Set(outline.value.filter((f) => f.name && f.kind !== "lambda").map((f) => f.qualified))];
|
|
37239
|
+
const last = (req.symbol.split(/[.#:]/).pop() ?? req.symbol).toLowerCase();
|
|
37240
|
+
const close = names2.filter((n) => n.toLowerCase().includes(last));
|
|
37241
|
+
const shown = (close.length > 0 ? close : names2).slice(0, 12);
|
|
37242
|
+
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 };
|
|
37243
|
+
}
|
|
37244
|
+
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.`;
|
|
37245
|
+
}
|
|
36797
37246
|
const target = {
|
|
36798
37247
|
file: req.file,
|
|
36799
37248
|
symbol: req.symbol,
|
|
@@ -36801,7 +37250,9 @@ async function generateAndCheck(root, req, opts) {
|
|
|
36801
37250
|
sha256: sha2562,
|
|
36802
37251
|
numbered: numbered2,
|
|
36803
37252
|
reasons: req.hint ? [`the user's worry, in their words: ${req.hint.slice(0, 280)}`] : [],
|
|
36804
|
-
properties: []
|
|
37253
|
+
properties: [],
|
|
37254
|
+
// The run row records which extractor answered, as at push.
|
|
37255
|
+
extentSource: extent
|
|
36805
37256
|
};
|
|
36806
37257
|
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;
|
|
36807
37258
|
Object.assign(target, context?.fields ?? {});
|
|
@@ -36823,7 +37274,7 @@ async function generateAndCheck(root, req, opts) {
|
|
|
36823
37274
|
}
|
|
36824
37275
|
const rel = `${dir}/${gen.name}.lean`;
|
|
36825
37276
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
36826
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37277
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path48.join)(root, rel);
|
|
36827
37278
|
const report = await opts.deps.check(root, abs);
|
|
36828
37279
|
const abstracts = report.header?.abstracts ?? [];
|
|
36829
37280
|
const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
|
|
@@ -36837,14 +37288,14 @@ async function generateAndCheck(root, req, opts) {
|
|
|
36837
37288
|
const g = basisOf(p.source, files);
|
|
36838
37289
|
return g.ok ? [] : [`${p.id}: ${g.why}`];
|
|
36839
37290
|
});
|
|
36840
|
-
if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd };
|
|
37291
|
+
if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd, ...warning ? { warning } : {} };
|
|
36841
37292
|
lastError = ungroundedMessage(bad.join("; "));
|
|
36842
37293
|
if (round < maxRounds) {
|
|
36843
37294
|
previous = { source: gen.source, error: lastError };
|
|
36844
37295
|
continue;
|
|
36845
37296
|
}
|
|
36846
37297
|
const grounded = report.properties.filter((p) => basisOf(p.source, files).ok);
|
|
36847
|
-
if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd };
|
|
37298
|
+
if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd, ...warning ? { warning } : {} };
|
|
36848
37299
|
break;
|
|
36849
37300
|
}
|
|
36850
37301
|
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");
|
|
@@ -36870,9 +37321,16 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
|
|
|
36870
37321
|
}
|
|
36871
37322
|
const build = await buildLibraryAsync(toolchain, root, 9e4);
|
|
36872
37323
|
if (!build.ok) return { ok: false, skip: "library-build-failed", detail: build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).join(" ").slice(0, 200) };
|
|
37324
|
+
const code = await loadCodeContext(root, env, codeSource);
|
|
37325
|
+
return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...code }), codeSource: code.codeSource } };
|
|
37326
|
+
}
|
|
37327
|
+
async function loadCodeContext(root, env = process.env, codeSource) {
|
|
36873
37328
|
const loaded = await loadCodeMap(env);
|
|
36874
|
-
|
|
36875
|
-
|
|
37329
|
+
return { codeMap: loaded.ok ? loaded.map : null, codeSource: codeSource ?? withoutPaths(worktreeSource(root), isDeniedPath) };
|
|
37330
|
+
}
|
|
37331
|
+
async function onDemandDeps(root, opts) {
|
|
37332
|
+
const code = await loadCodeContext(root, opts.env);
|
|
37333
|
+
return { ...defaultDeps({ ...opts, tier: "deep", ...code }), codeSource: code.codeSource };
|
|
36876
37334
|
}
|
|
36877
37335
|
function changedFunction(codeMap, file, content, changed) {
|
|
36878
37336
|
const outline = codeMap.outline(file, content);
|
|
@@ -36911,10 +37369,10 @@ function runFormalPhaseWithin(input) {
|
|
|
36911
37369
|
if (left <= 0) return Promise.resolve(skippedOutcome("deadline", "no time left"));
|
|
36912
37370
|
const progress = input.progress ?? {};
|
|
36913
37371
|
let timer = null;
|
|
36914
|
-
const cutoff = new Promise((
|
|
37372
|
+
const cutoff = new Promise((resolve9) => {
|
|
36915
37373
|
timer = setTimeout(() => {
|
|
36916
37374
|
progress.cancelled = true;
|
|
36917
|
-
|
|
37375
|
+
resolve9(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
|
|
36918
37376
|
}, left);
|
|
36919
37377
|
});
|
|
36920
37378
|
return Promise.race([runFormalPhase({ ...input, progress }), cutoff]).finally(() => {
|
|
@@ -36951,13 +37409,14 @@ function describeFormalOutcome(o) {
|
|
|
36951
37409
|
var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
36952
37410
|
var WRITERS_BUDGET_MS = 1500;
|
|
36953
37411
|
var EXCERPT_MAX_LINES2 = 30;
|
|
37412
|
+
var VENDORED_READ_MAX_BYTES = 256 * 1024;
|
|
36954
37413
|
var GUARD_BLOCK_CAP = 2;
|
|
36955
|
-
var GUARD_ITER_FILE = (0,
|
|
37414
|
+
var GUARD_ITER_FILE = (0, import_node_path49.join)(VERITY_DIR, ".guard-iteration");
|
|
36956
37415
|
function readPreToolUseStdin() {
|
|
36957
37416
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
36958
|
-
return new Promise((
|
|
37417
|
+
return new Promise((resolve9) => {
|
|
36959
37418
|
try {
|
|
36960
|
-
if (process.stdin.isTTY) return
|
|
37419
|
+
if (process.stdin.isTTY) return resolve9(empty);
|
|
36961
37420
|
const chunks = [];
|
|
36962
37421
|
let timer;
|
|
36963
37422
|
let settled = false;
|
|
@@ -36970,7 +37429,7 @@ function readPreToolUseStdin() {
|
|
|
36970
37429
|
process.stdin.removeListener("end", onEnd);
|
|
36971
37430
|
process.stdin.removeListener("error", onError);
|
|
36972
37431
|
process.stdin.pause();
|
|
36973
|
-
|
|
37432
|
+
resolve9(value);
|
|
36974
37433
|
};
|
|
36975
37434
|
const onEnd = () => {
|
|
36976
37435
|
try {
|
|
@@ -36991,13 +37450,13 @@ function readPreToolUseStdin() {
|
|
|
36991
37450
|
process.stdin.on("error", onError);
|
|
36992
37451
|
process.stdin.resume();
|
|
36993
37452
|
} catch {
|
|
36994
|
-
|
|
37453
|
+
resolve9(empty);
|
|
36995
37454
|
}
|
|
36996
37455
|
});
|
|
36997
37456
|
}
|
|
36998
37457
|
function readIterMap() {
|
|
36999
37458
|
try {
|
|
37000
|
-
const raw = JSON.parse((0,
|
|
37459
|
+
const raw = JSON.parse((0, import_node_fs62.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
37001
37460
|
if (raw && typeof raw === "object") {
|
|
37002
37461
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
37003
37462
|
return { [raw.moment]: raw.count };
|
|
@@ -37017,10 +37476,10 @@ function readIter(moment) {
|
|
|
37017
37476
|
}
|
|
37018
37477
|
function writeIter(moment, count) {
|
|
37019
37478
|
try {
|
|
37020
|
-
(0,
|
|
37479
|
+
(0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37021
37480
|
const map = readIterMap();
|
|
37022
37481
|
map[moment] = count;
|
|
37023
|
-
(0,
|
|
37482
|
+
(0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37024
37483
|
} catch {
|
|
37025
37484
|
}
|
|
37026
37485
|
}
|
|
@@ -37030,10 +37489,10 @@ function resetIter(moment) {
|
|
|
37030
37489
|
if (!(moment in map)) return;
|
|
37031
37490
|
delete map[moment];
|
|
37032
37491
|
if (Object.keys(map).length === 0) {
|
|
37033
|
-
if ((0,
|
|
37492
|
+
if ((0, import_node_fs62.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs62.unlinkSync)(GUARD_ITER_FILE);
|
|
37034
37493
|
} else {
|
|
37035
|
-
(0,
|
|
37036
|
-
(0,
|
|
37494
|
+
(0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37495
|
+
(0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37037
37496
|
}
|
|
37038
37497
|
} catch {
|
|
37039
37498
|
}
|
|
@@ -37103,7 +37562,7 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
37103
37562
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
37104
37563
|
const analyzable = filterAnalyzable(files);
|
|
37105
37564
|
const securityFiles = filterSecurity(files);
|
|
37106
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
37565
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs62.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
37107
37566
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
37108
37567
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
37109
37568
|
const requestBody = {
|
|
@@ -37340,7 +37799,15 @@ async function runGuard(opts, globals) {
|
|
|
37340
37799
|
`Verity ${moment}: this command stages files as it runs and the resulting set could not be resolved (${range.refusal}); the ${verb} was allowed WITHOUT a Verity review. Stage first (\`git add \u2026\`) and re-run the ${verb} to have it reviewed.`
|
|
37341
37800
|
);
|
|
37342
37801
|
}
|
|
37343
|
-
const
|
|
37802
|
+
const committed = revisionSource(
|
|
37803
|
+
frame.worktreeRoot ?? process.cwd(),
|
|
37804
|
+
range.kind === "push" && range.head !== "INDEX" ? range.head : null
|
|
37805
|
+
);
|
|
37806
|
+
const { review: files, vendored } = partitionVendored(rangeFiles(frame, range), (p) => {
|
|
37807
|
+
const read2 = committed.read(p, VENDORED_READ_MAX_BYTES);
|
|
37808
|
+
return read2.ok ? read2.content : null;
|
|
37809
|
+
});
|
|
37810
|
+
if (vendored.length > 0) logEvent("guard_vendored", { moment, n: vendored.length, paths: vendored.slice(0, 20) });
|
|
37344
37811
|
if (files.length === 0) process.exit(0);
|
|
37345
37812
|
const tokenResult = await resolveToken(globals.token);
|
|
37346
37813
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
@@ -37720,8 +38187,8 @@ function registerIgnoreCommand(program2) {
|
|
|
37720
38187
|
}
|
|
37721
38188
|
|
|
37722
38189
|
// src/commands/waive.ts
|
|
37723
|
-
var
|
|
37724
|
-
var
|
|
38190
|
+
var import_node_crypto20 = require("node:crypto");
|
|
38191
|
+
var import_node_fs63 = require("node:fs");
|
|
37725
38192
|
function registerWaiveCommand(program2) {
|
|
37726
38193
|
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) => {
|
|
37727
38194
|
const globals = program2.opts();
|
|
@@ -37750,7 +38217,7 @@ function registerWaiveCommand(program2) {
|
|
|
37750
38217
|
if (opts.file) {
|
|
37751
38218
|
body2.file = opts.file;
|
|
37752
38219
|
try {
|
|
37753
|
-
body2.file_sha256 = (0,
|
|
38220
|
+
body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs63.readFileSync)(opts.file)).digest("hex");
|
|
37754
38221
|
} catch {
|
|
37755
38222
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
37756
38223
|
process.exit(1);
|
|
@@ -37775,10 +38242,11 @@ function registerWaiveCommand(program2) {
|
|
|
37775
38242
|
}
|
|
37776
38243
|
|
|
37777
38244
|
// src/commands/init.ts
|
|
37778
|
-
var
|
|
38245
|
+
var import_node_fs68 = require("node:fs");
|
|
37779
38246
|
var import_promises20 = require("node:fs/promises");
|
|
37780
38247
|
var import_yaml6 = __toESM2(require_dist());
|
|
37781
|
-
var
|
|
38248
|
+
var import_node_path53 = require("node:path");
|
|
38249
|
+
var import_node_os11 = require("node:os");
|
|
37782
38250
|
var import_node_child_process19 = require("node:child_process");
|
|
37783
38251
|
|
|
37784
38252
|
// src/lib/banner.ts
|
|
@@ -37857,7 +38325,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
37857
38325
|
}
|
|
37858
38326
|
|
|
37859
38327
|
// src/commands/doctor.ts
|
|
37860
|
-
var
|
|
38328
|
+
var import_node_fs64 = require("node:fs");
|
|
37861
38329
|
|
|
37862
38330
|
// src/lib/prereqs.ts
|
|
37863
38331
|
var import_node_child_process16 = require("node:child_process");
|
|
@@ -37918,13 +38386,13 @@ function checkAnalysisCli() {
|
|
|
37918
38386
|
}
|
|
37919
38387
|
var INSTALL_TIMEOUT_MS = 12e4;
|
|
37920
38388
|
function run3(command, args2, opts = {}) {
|
|
37921
|
-
return new Promise((
|
|
38389
|
+
return new Promise((resolve9) => {
|
|
37922
38390
|
const child = (0, import_node_child_process16.spawn)(command, args2, {
|
|
37923
38391
|
stdio: opts.inherit ? "inherit" : "pipe",
|
|
37924
38392
|
timeout: INSTALL_TIMEOUT_MS
|
|
37925
38393
|
});
|
|
37926
|
-
child.on("error", () =>
|
|
37927
|
-
child.on("close", (code) =>
|
|
38394
|
+
child.on("error", () => resolve9(false));
|
|
38395
|
+
child.on("close", (code) => resolve9(code === 0));
|
|
37928
38396
|
});
|
|
37929
38397
|
}
|
|
37930
38398
|
async function installAnalysisCli() {
|
|
@@ -38065,11 +38533,11 @@ async function buildReport() {
|
|
|
38065
38533
|
const hooks = wiring.status;
|
|
38066
38534
|
const provenance = cliProvenance();
|
|
38067
38535
|
const telemetry = await checkTelemetry();
|
|
38068
|
-
const hasConfig = (0,
|
|
38536
|
+
const hasConfig = (0, import_node_fs64.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
38069
38537
|
const artifacts = {
|
|
38070
|
-
standard: (0,
|
|
38538
|
+
standard: (0, import_node_fs64.existsSync)(projectPath(STANDARD_FILE)),
|
|
38071
38539
|
analysisConfig: hasConfig,
|
|
38072
|
-
verityMd: (0,
|
|
38540
|
+
verityMd: (0, import_node_fs64.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
38073
38541
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
38074
38542
|
};
|
|
38075
38543
|
const next = [];
|
|
@@ -38228,8 +38696,8 @@ function registerDoctorCommand(program2) {
|
|
|
38228
38696
|
}
|
|
38229
38697
|
|
|
38230
38698
|
// src/commands/migrate.ts
|
|
38231
|
-
var
|
|
38232
|
-
var
|
|
38699
|
+
var import_node_fs65 = require("node:fs");
|
|
38700
|
+
var import_node_path50 = require("node:path");
|
|
38233
38701
|
var import_node_child_process17 = require("node:child_process");
|
|
38234
38702
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
38235
38703
|
function defaultNpmRemover(pkg) {
|
|
@@ -38266,12 +38734,12 @@ async function runMigration(opts = {}) {
|
|
|
38266
38734
|
return { actions, migrated: actions.length > 0 };
|
|
38267
38735
|
}
|
|
38268
38736
|
function migrateProjectDir(root, actions) {
|
|
38269
|
-
const gateDir = (0,
|
|
38270
|
-
const verityDir = (0,
|
|
38271
|
-
if ((0,
|
|
38737
|
+
const gateDir = (0, import_node_path50.join)(root, ".gate");
|
|
38738
|
+
const verityDir = (0, import_node_path50.join)(root, ".verity");
|
|
38739
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) {
|
|
38272
38740
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
38273
38741
|
}
|
|
38274
|
-
if ((0,
|
|
38742
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
|
|
38275
38743
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
38276
38744
|
}
|
|
38277
38745
|
return false;
|
|
@@ -38292,13 +38760,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
38292
38760
|
}
|
|
38293
38761
|
}
|
|
38294
38762
|
if (moved) {
|
|
38295
|
-
if ((0,
|
|
38763
|
+
if ((0, import_node_fs65.existsSync)(gateDir)) {
|
|
38296
38764
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
38297
38765
|
if (carried > 0) {
|
|
38298
38766
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
38299
38767
|
}
|
|
38300
38768
|
try {
|
|
38301
|
-
(0,
|
|
38769
|
+
(0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
|
|
38302
38770
|
} catch {
|
|
38303
38771
|
}
|
|
38304
38772
|
}
|
|
@@ -38314,18 +38782,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
38314
38782
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
38315
38783
|
}
|
|
38316
38784
|
try {
|
|
38317
|
-
(0,
|
|
38785
|
+
(0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
|
|
38318
38786
|
} catch {
|
|
38319
38787
|
}
|
|
38320
38788
|
return carried > 0;
|
|
38321
38789
|
}
|
|
38322
38790
|
function migrateGlobalCredentials(home, actions) {
|
|
38323
38791
|
if (!home) return;
|
|
38324
|
-
const gateCreds = (0,
|
|
38325
|
-
const verityCreds = (0,
|
|
38326
|
-
if (!(0,
|
|
38327
|
-
if (!(0,
|
|
38328
|
-
(0,
|
|
38792
|
+
const gateCreds = (0, import_node_path50.join)(home, ".gate", "credentials");
|
|
38793
|
+
const verityCreds = (0, import_node_path50.join)(home, ".verity", "credentials");
|
|
38794
|
+
if (!(0, import_node_fs65.existsSync)(gateCreds)) return;
|
|
38795
|
+
if (!(0, import_node_fs65.existsSync)(verityCreds)) {
|
|
38796
|
+
(0, import_node_fs65.mkdirSync)((0, import_node_path50.join)(home, ".verity"), { recursive: true });
|
|
38329
38797
|
moveFile(gateCreds, verityCreds);
|
|
38330
38798
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
38331
38799
|
return;
|
|
@@ -38347,8 +38815,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
38347
38815
|
}
|
|
38348
38816
|
}
|
|
38349
38817
|
async function migrateClaudeMd(root, actions) {
|
|
38350
|
-
const claudeMd = (0,
|
|
38351
|
-
const hadLegacyBlock = (0,
|
|
38818
|
+
const claudeMd = (0, import_node_path50.join)(root, "CLAUDE.md");
|
|
38819
|
+
const hadLegacyBlock = (0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
38352
38820
|
if (!hadLegacyBlock) return;
|
|
38353
38821
|
try {
|
|
38354
38822
|
await ensureClaudeMdPointer(root);
|
|
@@ -38358,9 +38826,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
38358
38826
|
}
|
|
38359
38827
|
}
|
|
38360
38828
|
function migrateStandardFile(root, actions) {
|
|
38361
|
-
const gateMd = (0,
|
|
38362
|
-
const verityMd = (0,
|
|
38363
|
-
if (!(0,
|
|
38829
|
+
const gateMd = (0, import_node_path50.join)(root, "GATE.md");
|
|
38830
|
+
const verityMd = (0, import_node_path50.join)(root, "VERITY.md");
|
|
38831
|
+
if (!(0, import_node_fs65.existsSync)(gateMd) || (0, import_node_fs65.existsSync)(verityMd)) return;
|
|
38364
38832
|
let moved = false;
|
|
38365
38833
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
38366
38834
|
try {
|
|
@@ -38372,12 +38840,12 @@ function migrateStandardFile(root, actions) {
|
|
|
38372
38840
|
if (!moved) moveFile(gateMd, verityMd);
|
|
38373
38841
|
const content = readFileSyncSafe(verityMd);
|
|
38374
38842
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
38375
|
-
if (refreshed !== content) (0,
|
|
38843
|
+
if (refreshed !== content) (0, import_node_fs65.writeFileSync)(verityMd, refreshed);
|
|
38376
38844
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
38377
38845
|
}
|
|
38378
38846
|
async function migrateTelemetryHeaders(root, actions) {
|
|
38379
|
-
const file = (0,
|
|
38380
|
-
if (!(0,
|
|
38847
|
+
const file = (0, import_node_path50.join)(root, ".claude", "settings.local.json");
|
|
38848
|
+
if (!(0, import_node_fs65.existsSync)(file)) return;
|
|
38381
38849
|
let settings;
|
|
38382
38850
|
try {
|
|
38383
38851
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -38424,15 +38892,15 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
38424
38892
|
toAppend.push(line2.replace(/\r$/, ""));
|
|
38425
38893
|
}
|
|
38426
38894
|
if (toAppend.length > 0) {
|
|
38427
|
-
const
|
|
38428
|
-
(0,
|
|
38895
|
+
const sep6 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
38896
|
+
(0, import_node_fs65.writeFileSync)(verityCreds, verityContent + sep6 + toAppend.join("\n") + "\n");
|
|
38429
38897
|
}
|
|
38430
|
-
(0,
|
|
38898
|
+
(0, import_node_fs65.rmSync)(gateCreds, { force: true });
|
|
38431
38899
|
return toAppend.length;
|
|
38432
38900
|
}
|
|
38433
38901
|
function readFileSyncSafe(path) {
|
|
38434
38902
|
try {
|
|
38435
|
-
return (0,
|
|
38903
|
+
return (0, import_node_fs65.readFileSync)(path, "utf-8");
|
|
38436
38904
|
} catch {
|
|
38437
38905
|
return "";
|
|
38438
38906
|
}
|
|
@@ -38447,35 +38915,35 @@ function hasStagedChanges(root) {
|
|
|
38447
38915
|
}
|
|
38448
38916
|
function moveDir(from, to) {
|
|
38449
38917
|
try {
|
|
38450
|
-
(0,
|
|
38918
|
+
(0, import_node_fs65.renameSync)(from, to);
|
|
38451
38919
|
} catch (err2) {
|
|
38452
38920
|
if (err2.code !== "EXDEV") throw err2;
|
|
38453
|
-
(0,
|
|
38454
|
-
(0,
|
|
38921
|
+
(0, import_node_fs65.cpSync)(from, to, { recursive: true });
|
|
38922
|
+
(0, import_node_fs65.rmSync)(from, { recursive: true, force: true });
|
|
38455
38923
|
}
|
|
38456
38924
|
}
|
|
38457
38925
|
function moveFile(from, to) {
|
|
38458
38926
|
try {
|
|
38459
|
-
(0,
|
|
38927
|
+
(0, import_node_fs65.renameSync)(from, to);
|
|
38460
38928
|
} catch (err2) {
|
|
38461
38929
|
if (err2.code !== "EXDEV") throw err2;
|
|
38462
|
-
(0,
|
|
38463
|
-
(0,
|
|
38930
|
+
(0, import_node_fs65.cpSync)(from, to);
|
|
38931
|
+
(0, import_node_fs65.rmSync)(from, { force: true });
|
|
38464
38932
|
}
|
|
38465
38933
|
}
|
|
38466
38934
|
function carryLegacyContents(gateDir, verityDir) {
|
|
38467
38935
|
let copied = 0;
|
|
38468
38936
|
const walk2 = (relDir) => {
|
|
38469
|
-
const srcDir = (0,
|
|
38470
|
-
for (const entry of (0,
|
|
38471
|
-
const rel = relDir ? (0,
|
|
38472
|
-
const src = (0,
|
|
38473
|
-
const dest = (0,
|
|
38474
|
-
if ((0,
|
|
38937
|
+
const srcDir = (0, import_node_path50.join)(gateDir, relDir);
|
|
38938
|
+
for (const entry of (0, import_node_fs65.readdirSync)(srcDir)) {
|
|
38939
|
+
const rel = relDir ? (0, import_node_path50.join)(relDir, entry) : entry;
|
|
38940
|
+
const src = (0, import_node_path50.join)(gateDir, rel);
|
|
38941
|
+
const dest = (0, import_node_path50.join)(verityDir, rel);
|
|
38942
|
+
if ((0, import_node_fs65.statSync)(src).isDirectory()) {
|
|
38475
38943
|
walk2(rel);
|
|
38476
|
-
} else if (!(0,
|
|
38477
|
-
(0,
|
|
38478
|
-
(0,
|
|
38944
|
+
} else if (!(0, import_node_fs65.existsSync)(dest)) {
|
|
38945
|
+
(0, import_node_fs65.mkdirSync)((0, import_node_path50.dirname)(dest), { recursive: true });
|
|
38946
|
+
(0, import_node_fs65.cpSync)(src, dest);
|
|
38479
38947
|
copied++;
|
|
38480
38948
|
}
|
|
38481
38949
|
}
|
|
@@ -38484,22 +38952,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
38484
38952
|
return copied;
|
|
38485
38953
|
}
|
|
38486
38954
|
async function needsMigration(root = repoRoot()) {
|
|
38487
|
-
const gateDir = (0,
|
|
38488
|
-
const verityDir = (0,
|
|
38489
|
-
if ((0,
|
|
38490
|
-
if ((0,
|
|
38491
|
-
if ((0,
|
|
38955
|
+
const gateDir = (0, import_node_path50.join)(root, ".gate");
|
|
38956
|
+
const verityDir = (0, import_node_path50.join)(root, ".verity");
|
|
38957
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) return true;
|
|
38958
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
|
|
38959
|
+
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"))) {
|
|
38492
38960
|
return true;
|
|
38493
38961
|
}
|
|
38494
|
-
if ((0,
|
|
38962
|
+
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"))) {
|
|
38495
38963
|
return true;
|
|
38496
38964
|
}
|
|
38497
38965
|
}
|
|
38498
|
-
const claudeMd = (0,
|
|
38499
|
-
if ((0,
|
|
38966
|
+
const claudeMd = (0, import_node_path50.join)(root, "CLAUDE.md");
|
|
38967
|
+
if ((0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
38500
38968
|
return true;
|
|
38501
38969
|
}
|
|
38502
|
-
if ((0,
|
|
38970
|
+
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"))) {
|
|
38503
38971
|
return true;
|
|
38504
38972
|
}
|
|
38505
38973
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -38628,7 +39096,7 @@ function runSelect(opts) {
|
|
|
38628
39096
|
cursor: initialIdx[0] ?? 0,
|
|
38629
39097
|
chosen: new Set(mode2 === "single" ? [initialIdx[0] ?? 0] : initialIdx)
|
|
38630
39098
|
};
|
|
38631
|
-
return new Promise((
|
|
39099
|
+
return new Promise((resolve9) => {
|
|
38632
39100
|
let painted = 0;
|
|
38633
39101
|
let settled = false;
|
|
38634
39102
|
const draw = () => {
|
|
@@ -38676,7 +39144,7 @@ function runSelect(opts) {
|
|
|
38676
39144
|
if (settled) return;
|
|
38677
39145
|
settled = true;
|
|
38678
39146
|
restore();
|
|
38679
|
-
|
|
39147
|
+
resolve9(value);
|
|
38680
39148
|
};
|
|
38681
39149
|
readline2.emitKeypressEvents(input);
|
|
38682
39150
|
input.setRawMode(true);
|
|
@@ -38697,9 +39165,9 @@ async function askLine(question, io = {}) {
|
|
|
38697
39165
|
output: io.output ?? process.stdout
|
|
38698
39166
|
});
|
|
38699
39167
|
try {
|
|
38700
|
-
return await new Promise((
|
|
38701
|
-
rl.question(question).then((a) =>
|
|
38702
|
-
rl.once("close", () => setImmediate(() =>
|
|
39168
|
+
return await new Promise((resolve9) => {
|
|
39169
|
+
rl.question(question).then((a) => resolve9(a.trim())).catch(() => resolve9(null));
|
|
39170
|
+
rl.once("close", () => setImmediate(() => resolve9(null)));
|
|
38703
39171
|
});
|
|
38704
39172
|
} finally {
|
|
38705
39173
|
rl.close();
|
|
@@ -38780,11 +39248,11 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
38780
39248
|
}
|
|
38781
39249
|
|
|
38782
39250
|
// src/lib/prove/lean-install.ts
|
|
38783
|
-
var
|
|
38784
|
-
var
|
|
39251
|
+
var import_node_fs66 = require("node:fs");
|
|
39252
|
+
var import_node_crypto21 = require("node:crypto");
|
|
38785
39253
|
var import_node_child_process18 = require("node:child_process");
|
|
38786
39254
|
var import_node_os10 = require("node:os");
|
|
38787
|
-
var
|
|
39255
|
+
var import_node_path51 = require("node:path");
|
|
38788
39256
|
var import_promises18 = require("node:stream/promises");
|
|
38789
39257
|
var import_node_stream = require("node:stream");
|
|
38790
39258
|
var RELEASES = "https://releases.lean-lang.org/lean4";
|
|
@@ -38795,10 +39263,10 @@ function freeBytes(dir) {
|
|
|
38795
39263
|
let d = dir;
|
|
38796
39264
|
for (let i2 = 0; i2 < 64; i2++) {
|
|
38797
39265
|
try {
|
|
38798
|
-
const st = (0,
|
|
39266
|
+
const st = (0, import_node_fs66.statfsSync)(d);
|
|
38799
39267
|
return Number(st.bavail) * Number(st.bsize);
|
|
38800
39268
|
} catch {
|
|
38801
|
-
const up = (0,
|
|
39269
|
+
const up = (0, import_node_path51.join)(d, "..");
|
|
38802
39270
|
if (up === d) return null;
|
|
38803
39271
|
d = up;
|
|
38804
39272
|
}
|
|
@@ -38818,9 +39286,9 @@ function expectedSha256(asset, version = pinnedVersion()) {
|
|
|
38818
39286
|
return LEAN_ASSET_SHA256[version]?.[asset] ?? null;
|
|
38819
39287
|
}
|
|
38820
39288
|
function sha256File(path) {
|
|
38821
|
-
return new Promise((
|
|
38822
|
-
const hash = (0,
|
|
38823
|
-
(0,
|
|
39289
|
+
return new Promise((resolve9, reject) => {
|
|
39290
|
+
const hash = (0, import_node_crypto21.createHash)("sha256");
|
|
39291
|
+
(0, import_node_fs66.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
|
|
38824
39292
|
});
|
|
38825
39293
|
}
|
|
38826
39294
|
async function verifyDownload(zip, asset, version = pinnedVersion()) {
|
|
@@ -38840,7 +39308,7 @@ function leanAssetName(version = pinnedVersion()) {
|
|
|
38840
39308
|
return suffix ? `lean-${v}-${suffix}.zip` : null;
|
|
38841
39309
|
}
|
|
38842
39310
|
function pinnedVersionDir(env = process.env) {
|
|
38843
|
-
return (0,
|
|
39311
|
+
return (0, import_node_path51.join)(verityLeanHome(env), pinnedVersion());
|
|
38844
39312
|
}
|
|
38845
39313
|
function lakeBinary() {
|
|
38846
39314
|
return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
|
|
@@ -38851,12 +39319,12 @@ function unzip(zip, dest) {
|
|
|
38851
39319
|
for (const [cmd, args2] of attempts) {
|
|
38852
39320
|
try {
|
|
38853
39321
|
(0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
|
|
38854
|
-
if ((0,
|
|
39322
|
+
if ((0, import_node_fs66.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
|
|
38855
39323
|
errors.push(`${cmd}: produced nothing`);
|
|
38856
39324
|
} catch (err2) {
|
|
38857
39325
|
errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
|
|
38858
39326
|
try {
|
|
38859
|
-
for (const e of (0,
|
|
39327
|
+
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 });
|
|
38860
39328
|
} catch {
|
|
38861
39329
|
}
|
|
38862
39330
|
}
|
|
@@ -38882,7 +39350,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
|
|
|
38882
39350
|
seen += chunk.length;
|
|
38883
39351
|
onProgress(seen, total);
|
|
38884
39352
|
});
|
|
38885
|
-
await (0, import_promises18.pipeline)(stream, (0,
|
|
39353
|
+
await (0, import_promises18.pipeline)(stream, (0, import_node_fs66.createWriteStream)(dest), { signal: ctrl.signal });
|
|
38886
39354
|
} catch (err2) {
|
|
38887
39355
|
if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
|
|
38888
39356
|
throw err2;
|
|
@@ -38932,10 +39400,10 @@ async function installLean(opts = {}) {
|
|
|
38932
39400
|
const gb = (n) => (n / 1024 ** 3).toFixed(1);
|
|
38933
39401
|
return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
|
|
38934
39402
|
}
|
|
38935
|
-
const tmp = (0,
|
|
38936
|
-
(0,
|
|
38937
|
-
(0,
|
|
38938
|
-
const zip = (0,
|
|
39403
|
+
const tmp = (0, import_node_path51.join)(home, ".tmp");
|
|
39404
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39405
|
+
(0, import_node_fs66.mkdirSync)(tmp, { recursive: true });
|
|
39406
|
+
const zip = (0, import_node_path51.join)(tmp, asset);
|
|
38939
39407
|
say(`downloading ${url}`);
|
|
38940
39408
|
let lastPct = -1;
|
|
38941
39409
|
try {
|
|
@@ -38948,40 +39416,40 @@ async function installLean(opts = {}) {
|
|
|
38948
39416
|
}
|
|
38949
39417
|
});
|
|
38950
39418
|
} catch (err2) {
|
|
38951
|
-
(0,
|
|
39419
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
38952
39420
|
return { ok: false, error: err2.message };
|
|
38953
39421
|
}
|
|
38954
39422
|
say("verifying checksum");
|
|
38955
39423
|
const verified = await verifyDownload(zip, asset);
|
|
38956
39424
|
if (!verified.ok) {
|
|
38957
|
-
(0,
|
|
39425
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
38958
39426
|
return { ok: false, error: verified.error };
|
|
38959
39427
|
}
|
|
38960
39428
|
say("unpacking (this takes a minute)");
|
|
38961
|
-
const unpack = (0,
|
|
38962
|
-
(0,
|
|
39429
|
+
const unpack = (0, import_node_path51.join)(tmp, "unpack");
|
|
39430
|
+
(0, import_node_fs66.mkdirSync)(unpack);
|
|
38963
39431
|
const unpacked = unzip(zip, unpack);
|
|
38964
39432
|
if (!unpacked.ok) {
|
|
38965
|
-
(0,
|
|
39433
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
38966
39434
|
return { ok: false, error: `unpack failed: ${unpacked.error}` };
|
|
38967
39435
|
}
|
|
38968
|
-
const entries = (0,
|
|
38969
|
-
const top = entries.length === 1 && (0,
|
|
38970
|
-
if (!(0,
|
|
38971
|
-
(0,
|
|
39436
|
+
const entries = (0, import_node_fs66.readdirSync)(unpack);
|
|
39437
|
+
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;
|
|
39438
|
+
if (!(0, import_node_fs66.existsSync)((0, import_node_path51.join)(top, "bin", lakeBinary()))) {
|
|
39439
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
38972
39440
|
return { ok: false, error: "the archive did not contain bin/lake" };
|
|
38973
39441
|
}
|
|
38974
|
-
(0,
|
|
38975
|
-
(0,
|
|
38976
|
-
(0,
|
|
38977
|
-
(0,
|
|
39442
|
+
(0, import_node_fs66.rmSync)(dir, { recursive: true, force: true });
|
|
39443
|
+
(0, import_node_fs66.mkdirSync)(home, { recursive: true });
|
|
39444
|
+
(0, import_node_fs66.renameSync)(top, dir);
|
|
39445
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
38978
39446
|
return { ok: true, dir };
|
|
38979
39447
|
}
|
|
38980
39448
|
|
|
38981
39449
|
// src/lib/remote-config.ts
|
|
38982
|
-
var
|
|
39450
|
+
var import_node_fs67 = require("node:fs");
|
|
38983
39451
|
var import_promises19 = require("node:fs/promises");
|
|
38984
|
-
var
|
|
39452
|
+
var import_node_path52 = require("node:path");
|
|
38985
39453
|
var import_yaml5 = __toESM2(require_dist());
|
|
38986
39454
|
var IGNORE_RIDER = "verityignore";
|
|
38987
39455
|
async function fetchRemoteSetup(opts) {
|
|
@@ -39026,7 +39494,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39026
39494
|
written.push(STANDARD_FILE);
|
|
39027
39495
|
if (rider !== null) {
|
|
39028
39496
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
39029
|
-
if (!(0,
|
|
39497
|
+
if (!(0, import_node_fs67.existsSync)(localIgnore)) {
|
|
39030
39498
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
39031
39499
|
written.push(VERITYIGNORE_FILE);
|
|
39032
39500
|
} else {
|
|
@@ -39059,7 +39527,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39059
39527
|
}
|
|
39060
39528
|
async function writeOut(relative6, body2) {
|
|
39061
39529
|
const target = projectPath(relative6);
|
|
39062
|
-
await (0, import_promises19.mkdir)((0,
|
|
39530
|
+
await (0, import_promises19.mkdir)((0, import_node_path52.dirname)(target), { recursive: true });
|
|
39063
39531
|
await (0, import_promises19.writeFile)(target, body2);
|
|
39064
39532
|
}
|
|
39065
39533
|
function describeRemote(found) {
|
|
@@ -39176,15 +39644,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
39176
39644
|
}
|
|
39177
39645
|
function resolveDataDir2() {
|
|
39178
39646
|
const candidates2 = [
|
|
39179
|
-
(0,
|
|
39647
|
+
(0, import_node_path53.join)(__dirname, "..", "data"),
|
|
39180
39648
|
// installed: node_modules/@codacy/verity-cli/data
|
|
39181
|
-
(0,
|
|
39649
|
+
(0, import_node_path53.join)(__dirname, "..", "..", "data"),
|
|
39182
39650
|
// edge case: nested resolution
|
|
39183
|
-
(0,
|
|
39651
|
+
(0, import_node_path53.join)(process.cwd(), "cli", "data")
|
|
39184
39652
|
// local dev: running from repo root
|
|
39185
39653
|
];
|
|
39186
39654
|
for (const candidate of candidates2) {
|
|
39187
|
-
if ((0,
|
|
39655
|
+
if ((0, import_node_fs68.existsSync)((0, import_node_path53.join)(candidate, "skills"))) {
|
|
39188
39656
|
return candidate;
|
|
39189
39657
|
}
|
|
39190
39658
|
}
|
|
@@ -39200,9 +39668,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
39200
39668
|
const list2 = (dir) => {
|
|
39201
39669
|
const out2 = [];
|
|
39202
39670
|
const walk2 = (d, prefix) => {
|
|
39203
|
-
for (const e of (0,
|
|
39671
|
+
for (const e of (0, import_node_fs68.readdirSync)(d, { withFileTypes: true })) {
|
|
39204
39672
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
39205
|
-
if (e.isDirectory()) walk2((0,
|
|
39673
|
+
if (e.isDirectory()) walk2((0, import_node_path53.join)(d, e.name), rel);
|
|
39206
39674
|
else if (e.isFile()) out2.push(rel);
|
|
39207
39675
|
}
|
|
39208
39676
|
};
|
|
@@ -39213,8 +39681,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
39213
39681
|
const shipped = list2(src);
|
|
39214
39682
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
39215
39683
|
for (const rel of shipped) {
|
|
39216
|
-
const a = await (0, import_promises20.readFile)((0,
|
|
39217
|
-
const b = await (0, import_promises20.readFile)((0,
|
|
39684
|
+
const a = await (0, import_promises20.readFile)((0, import_node_path53.join)(src, rel), "utf-8");
|
|
39685
|
+
const b = await (0, import_promises20.readFile)((0, import_node_path53.join)(dest, rel), "utf-8");
|
|
39218
39686
|
if (a !== b) return false;
|
|
39219
39687
|
}
|
|
39220
39688
|
return true;
|
|
@@ -39417,7 +39885,7 @@ async function synthesizeLocally(opts) {
|
|
|
39417
39885
|
async function healStaleAnalysisConfig(globals) {
|
|
39418
39886
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
39419
39887
|
const standardPath = projectPath(STANDARD_FILE);
|
|
39420
|
-
if (!(0,
|
|
39888
|
+
if (!(0, import_node_fs68.existsSync)(configPath) || !(0, import_node_fs68.existsSync)(standardPath)) return;
|
|
39421
39889
|
const validation = validatePatternIds();
|
|
39422
39890
|
if (validation.status !== "invalid") return;
|
|
39423
39891
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -39514,17 +39982,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
39514
39982
|
async function installSkills(force, step) {
|
|
39515
39983
|
step("Installing skills");
|
|
39516
39984
|
const dataDir = resolveDataDir2();
|
|
39517
|
-
const skillsSource = (0,
|
|
39985
|
+
const skillsSource = (0, import_node_path53.join)(dataDir, "skills");
|
|
39518
39986
|
const skillsDest = ".claude/skills";
|
|
39519
39987
|
let skillsInstalled = 0;
|
|
39520
39988
|
for (const skill of SKILLS) {
|
|
39521
|
-
const src = (0,
|
|
39522
|
-
const dest = (0,
|
|
39523
|
-
if (!(0,
|
|
39989
|
+
const src = (0, import_node_path53.join)(skillsSource, skill);
|
|
39990
|
+
const dest = (0, import_node_path53.join)(skillsDest, skill);
|
|
39991
|
+
if (!(0, import_node_fs68.existsSync)(src)) {
|
|
39524
39992
|
printWarn(` Skill data not found: ${skill}`);
|
|
39525
39993
|
continue;
|
|
39526
39994
|
}
|
|
39527
|
-
if ((0,
|
|
39995
|
+
if ((0, import_node_fs68.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
39528
39996
|
skillsInstalled++;
|
|
39529
39997
|
continue;
|
|
39530
39998
|
}
|
|
@@ -39668,7 +40136,15 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
|
|
|
39668
40136
|
console.log(" At push, Verity picks the riskiest changed function, checks a small model of");
|
|
39669
40137
|
console.log(" it, and replays any counterexample on the real code (its source is sent to");
|
|
39670
40138
|
console.log(" Verity for that). Only a reproduced bug can block; most pushes get no model.");
|
|
39671
|
-
console.log(
|
|
40139
|
+
console.log(" Adds /verity-prove <worry> to check any code on demand, e.g.");
|
|
40140
|
+
console.log(` ${DIM}/verity-prove can the webhook handler charge twice on a retried event?${NC}`);
|
|
40141
|
+
if (!toolchain) {
|
|
40142
|
+
const dir = pinnedVersionDir();
|
|
40143
|
+
const home = (0, import_node_os11.homedir)();
|
|
40144
|
+
const shown = dir.startsWith(home + import_node_path53.sep) ? `~${dir.slice(home.length)}` : dir;
|
|
40145
|
+
console.log("");
|
|
40146
|
+
console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
|
|
40147
|
+
}
|
|
39672
40148
|
console.log("");
|
|
39673
40149
|
const wants = await promptChoice("Formal verification at push?", FORMAL_CHOICES, "no");
|
|
39674
40150
|
if (wants === "yes" && pluginMode) printInfo(" Plugin: the push check works now; /verity:verity-prove arrives with the plugin's next release.");
|
|
@@ -39724,7 +40200,7 @@ function registerInitCommand(program2) {
|
|
|
39724
40200
|
const staleMarker = clearStalePluginMarker();
|
|
39725
40201
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
39726
40202
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
39727
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
40203
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs68.existsSync)(m));
|
|
39728
40204
|
if (!isProject) {
|
|
39729
40205
|
printError("No project detected in the current directory.");
|
|
39730
40206
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -39778,7 +40254,7 @@ function registerInitCommand(program2) {
|
|
|
39778
40254
|
const claudeInstalled = await checkPrerequisites(step);
|
|
39779
40255
|
console.log("");
|
|
39780
40256
|
if (pluginMode) {
|
|
39781
|
-
|
|
40257
|
+
step("Skills already installed by the plugin, namespaced as /verity:<name>");
|
|
39782
40258
|
} else {
|
|
39783
40259
|
await installSkills(force, step);
|
|
39784
40260
|
}
|
|
@@ -39827,7 +40303,7 @@ function registerInitCommand(program2) {
|
|
|
39827
40303
|
untrackMemory: opts.untrackMemory === true,
|
|
39828
40304
|
untrackState: opts.untrackState === true
|
|
39829
40305
|
});
|
|
39830
|
-
const globalVerityDir = (0,
|
|
40306
|
+
const globalVerityDir = (0, import_node_path53.join)(process.env.HOME ?? "", ".verity");
|
|
39831
40307
|
await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
|
|
39832
40308
|
console.log("");
|
|
39833
40309
|
step("Wiring Claude Code hooks");
|
|
@@ -39902,7 +40378,7 @@ function registerInitCommand(program2) {
|
|
|
39902
40378
|
}
|
|
39903
40379
|
step("Your project's Standard");
|
|
39904
40380
|
let haveStandard = false;
|
|
39905
|
-
if ((0,
|
|
40381
|
+
if ((0, import_node_fs68.existsSync)(projectPath(STANDARD_FILE))) {
|
|
39906
40382
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
39907
40383
|
haveStandard = true;
|
|
39908
40384
|
} else {
|
|
@@ -39932,7 +40408,7 @@ function registerInitCommand(program2) {
|
|
|
39932
40408
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
39933
40409
|
init: {
|
|
39934
40410
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39935
|
-
cli_version: true ? "0.34.
|
|
40411
|
+
cli_version: true ? "0.34.1-experimental.199c728" : "dev"
|
|
39936
40412
|
}
|
|
39937
40413
|
});
|
|
39938
40414
|
} catch (err2) {
|
|
@@ -39982,8 +40458,8 @@ function registerInitCommand(program2) {
|
|
|
39982
40458
|
}
|
|
39983
40459
|
|
|
39984
40460
|
// src/commands/uninstall.ts
|
|
39985
|
-
var
|
|
39986
|
-
var
|
|
40461
|
+
var import_node_fs69 = require("node:fs");
|
|
40462
|
+
var import_node_path54 = require("node:path");
|
|
39987
40463
|
function registerUninstallCommand(program2) {
|
|
39988
40464
|
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) => {
|
|
39989
40465
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -39992,11 +40468,11 @@ function registerUninstallCommand(program2) {
|
|
|
39992
40468
|
const actions = [];
|
|
39993
40469
|
const skillsRoot = projectPath(".claude/skills");
|
|
39994
40470
|
for (const name2 of PROJECT_SKILL_NAMES) {
|
|
39995
|
-
const dir = (0,
|
|
39996
|
-
if ((0,
|
|
40471
|
+
const dir = (0, import_node_path54.join)(skillsRoot, name2);
|
|
40472
|
+
if ((0, import_node_fs69.existsSync)(dir)) {
|
|
39997
40473
|
actions.push({
|
|
39998
40474
|
label: `Remove .claude/skills/${name2}/`,
|
|
39999
|
-
apply: () => (0,
|
|
40475
|
+
apply: () => (0, import_node_fs69.rmSync)(dir, { recursive: true, force: true })
|
|
40000
40476
|
});
|
|
40001
40477
|
}
|
|
40002
40478
|
}
|
|
@@ -40010,24 +40486,24 @@ function registerUninstallCommand(program2) {
|
|
|
40010
40486
|
});
|
|
40011
40487
|
}
|
|
40012
40488
|
const verityDir = projectPath(VERITY_DIR);
|
|
40013
|
-
if ((0,
|
|
40489
|
+
if ((0, import_node_fs69.existsSync)(verityDir)) {
|
|
40014
40490
|
actions.push({
|
|
40015
40491
|
label: `Remove ${VERITY_DIR}/`,
|
|
40016
|
-
apply: () => (0,
|
|
40492
|
+
apply: () => (0, import_node_fs69.rmSync)(verityDir, { recursive: true, force: true })
|
|
40017
40493
|
});
|
|
40018
40494
|
}
|
|
40019
40495
|
if (!keepVerityMd) {
|
|
40020
40496
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
40021
|
-
if ((0,
|
|
40497
|
+
if ((0, import_node_fs69.existsSync)(verityMd)) {
|
|
40022
40498
|
actions.push({
|
|
40023
40499
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
40024
|
-
apply: () => (0,
|
|
40500
|
+
apply: () => (0, import_node_fs69.rmSync)(verityMd, { force: true })
|
|
40025
40501
|
});
|
|
40026
40502
|
}
|
|
40027
40503
|
}
|
|
40028
40504
|
const cleanupEmptyDir = (path) => {
|
|
40029
|
-
if ((0,
|
|
40030
|
-
(0,
|
|
40505
|
+
if ((0, import_node_fs69.existsSync)(path) && (0, import_node_fs69.statSync)(path).isDirectory() && (0, import_node_fs69.readdirSync)(path).length === 0) {
|
|
40506
|
+
(0, import_node_fs69.rmdirSync)(path);
|
|
40031
40507
|
}
|
|
40032
40508
|
};
|
|
40033
40509
|
actions.push({
|
|
@@ -40038,11 +40514,11 @@ function registerUninstallCommand(program2) {
|
|
|
40038
40514
|
}
|
|
40039
40515
|
});
|
|
40040
40516
|
const home = process.env.HOME ?? "";
|
|
40041
|
-
const globalVerityDir = (0,
|
|
40042
|
-
if (purgeGlobal && (0,
|
|
40517
|
+
const globalVerityDir = (0, import_node_path54.join)(home, ".verity");
|
|
40518
|
+
if (purgeGlobal && (0, import_node_fs69.existsSync)(globalVerityDir)) {
|
|
40043
40519
|
actions.push({
|
|
40044
40520
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
40045
|
-
apply: () => (0,
|
|
40521
|
+
apply: () => (0, import_node_fs69.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
40046
40522
|
});
|
|
40047
40523
|
}
|
|
40048
40524
|
if (actions.length === 0) {
|
|
@@ -40236,8 +40712,8 @@ function registerTaskCommands(program2) {
|
|
|
40236
40712
|
}
|
|
40237
40713
|
|
|
40238
40714
|
// src/commands/reset.ts
|
|
40239
|
-
var
|
|
40240
|
-
var
|
|
40715
|
+
var import_node_fs70 = require("node:fs");
|
|
40716
|
+
var import_node_path55 = require("node:path");
|
|
40241
40717
|
function registerResetCommand(program2) {
|
|
40242
40718
|
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) => {
|
|
40243
40719
|
const globals = program2.opts();
|
|
@@ -40274,11 +40750,11 @@ function registerResetCommand(program2) {
|
|
|
40274
40750
|
}
|
|
40275
40751
|
const cacheDir = projectPath(CACHE_DIR);
|
|
40276
40752
|
let purged = 0;
|
|
40277
|
-
if ((0,
|
|
40278
|
-
for (const entry of (0,
|
|
40753
|
+
if ((0, import_node_fs70.existsSync)(cacheDir)) {
|
|
40754
|
+
for (const entry of (0, import_node_fs70.readdirSync)(cacheDir)) {
|
|
40279
40755
|
if (entry.startsWith("pending-")) {
|
|
40280
40756
|
try {
|
|
40281
|
-
(0,
|
|
40757
|
+
(0, import_node_fs70.unlinkSync)((0, import_node_path55.join)(cacheDir, entry));
|
|
40282
40758
|
purged++;
|
|
40283
40759
|
} catch {
|
|
40284
40760
|
}
|
|
@@ -40293,19 +40769,19 @@ function registerResetCommand(program2) {
|
|
|
40293
40769
|
projectPath(`${VERITY_DIR}/.last-analysis`)
|
|
40294
40770
|
];
|
|
40295
40771
|
for (const file of filesToClear) {
|
|
40296
|
-
if ((0,
|
|
40772
|
+
if ((0, import_node_fs70.existsSync)(file)) {
|
|
40297
40773
|
try {
|
|
40298
|
-
(0,
|
|
40774
|
+
(0, import_node_fs70.writeFileSync)(file, "");
|
|
40299
40775
|
} catch {
|
|
40300
40776
|
}
|
|
40301
40777
|
}
|
|
40302
40778
|
}
|
|
40303
40779
|
if (opts.all) {
|
|
40304
40780
|
const logsDir = projectPath(`${VERITY_DIR}/.logs`);
|
|
40305
|
-
if ((0,
|
|
40306
|
-
for (const entry of (0,
|
|
40781
|
+
if ((0, import_node_fs70.existsSync)(logsDir)) {
|
|
40782
|
+
for (const entry of (0, import_node_fs70.readdirSync)(logsDir)) {
|
|
40307
40783
|
try {
|
|
40308
|
-
(0,
|
|
40784
|
+
(0, import_node_fs70.unlinkSync)((0, import_node_path55.join)(logsDir, entry));
|
|
40309
40785
|
} catch {
|
|
40310
40786
|
}
|
|
40311
40787
|
}
|
|
@@ -40317,7 +40793,7 @@ function registerResetCommand(program2) {
|
|
|
40317
40793
|
}
|
|
40318
40794
|
|
|
40319
40795
|
// src/commands/reflect.ts
|
|
40320
|
-
var
|
|
40796
|
+
var import_node_fs71 = require("node:fs");
|
|
40321
40797
|
|
|
40322
40798
|
// src/lib/reflection-globs.ts
|
|
40323
40799
|
var MAX_GLOBS = 6;
|
|
@@ -40325,7 +40801,7 @@ var PATH_TOKEN = /[A-Za-z0-9_./-]*[A-Za-z0-9_-]\.[A-Za-z0-9]{1,8}(?::\d+(?::\d+)
|
|
|
40325
40801
|
function clean(token) {
|
|
40326
40802
|
return token.replace(/:\d+(?::\d+)?$/, "").replace(/^[`'"(\[]+/, "").replace(/[`'"),\].;!?]+$/, "").replace(/^\.\//, "");
|
|
40327
40803
|
}
|
|
40328
|
-
function
|
|
40804
|
+
function resolve7(token, treePaths) {
|
|
40329
40805
|
if (treePaths.includes(token)) return token;
|
|
40330
40806
|
const suffix = token.startsWith("/") ? token : `/${token}`;
|
|
40331
40807
|
const matches = treePaths.filter((p) => p.endsWith(suffix));
|
|
@@ -40338,7 +40814,7 @@ function deriveFileGlobs(text, treePaths) {
|
|
|
40338
40814
|
for (const raw of text.match(PATH_TOKEN) ?? []) {
|
|
40339
40815
|
const token = clean(raw);
|
|
40340
40816
|
if (!token) continue;
|
|
40341
|
-
const path =
|
|
40817
|
+
const path = resolve7(token, treePaths);
|
|
40342
40818
|
if (!path || seen.has(path)) continue;
|
|
40343
40819
|
seen.add(path);
|
|
40344
40820
|
out2.push(path);
|
|
@@ -40355,14 +40831,19 @@ async function writeNodeToDisk(args2) {
|
|
|
40355
40831
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
40356
40832
|
);
|
|
40357
40833
|
if (written === 0) return false;
|
|
40358
|
-
return (0,
|
|
40834
|
+
return (0, import_node_fs71.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
|
|
40359
40835
|
} catch {
|
|
40360
40836
|
return false;
|
|
40361
40837
|
}
|
|
40362
40838
|
}
|
|
40363
40839
|
function registerReflectCommand(program2) {
|
|
40364
|
-
program2.command("reflect").description("Capture learnings \u2014 auto-extract or record a reflection").option("--user-input <text>", "The reflection to record (the agent-drafted or user-dictated text)").option("--kind <kind>", "Node kind (decision, gotcha, pattern, security, quality, intent, domain, integration)", "gotcha").option("--task-id <id>", "Task to reflect on (defaults to current task)").option("--confirmed", "The USER authored or confirmed these exact words \u2014 records as human-authored (source: user, confidence 1.0)").option("--file-globs <glob...>", "Files this reflection is about. Without any, the paths cited in the text are used; a reflection matching no file never surfaces in a review").option("--autonomous", "(deprecated, ignored) reflections are always recorded without a confirm step").action(async (opts) => {
|
|
40840
|
+
program2.command("reflect").description("Capture learnings \u2014 auto-extract or record a reflection").option("--user-input <text>", "The reflection to record (the agent-drafted or user-dictated text); - reads it from stdin, so the words never pass through shell quoting").option("--kind <kind>", "Node kind (decision, gotcha, pattern, security, quality, intent, domain, integration)", "gotcha").option("--task-id <id>", "Task to reflect on (defaults to current task)").option("--confirmed", "The USER authored or confirmed these exact words \u2014 records as human-authored (source: user, confidence 1.0)").option("--file-globs <glob...>", "Files this reflection is about. Without any, the paths cited in the text are used; a reflection matching no file never surfaces in a review").option("--autonomous", "(deprecated, ignored) reflections are always recorded without a confirm step").action(async (opts) => {
|
|
40365
40841
|
const globals = program2.opts();
|
|
40842
|
+
const input = readTextInput(opts.userInput, "--user-input");
|
|
40843
|
+
if (!input.ok) {
|
|
40844
|
+
printError(input.error);
|
|
40845
|
+
process.exit(1);
|
|
40846
|
+
}
|
|
40366
40847
|
await ensureMemoryDir();
|
|
40367
40848
|
const tokenResult = await resolveToken(globals.token);
|
|
40368
40849
|
if (!tokenResult.ok) {
|
|
@@ -40423,7 +40904,7 @@ function registerReflectCommand(program2) {
|
|
|
40423
40904
|
taskResolution = "none";
|
|
40424
40905
|
printWarn("No active task found \u2014 saving as an unattached reflection.");
|
|
40425
40906
|
}
|
|
40426
|
-
const userInput =
|
|
40907
|
+
const userInput = input.text;
|
|
40427
40908
|
if (userInput) {
|
|
40428
40909
|
const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
|
|
40429
40910
|
const kind = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
|
|
@@ -40787,9 +41268,9 @@ function registerRunCommand(program2) {
|
|
|
40787
41268
|
}
|
|
40788
41269
|
|
|
40789
41270
|
// src/commands/telemetry.ts
|
|
40790
|
-
var
|
|
41271
|
+
var import_node_fs72 = require("node:fs");
|
|
40791
41272
|
async function recordTelemetryChoice(choice) {
|
|
40792
|
-
if (!(0,
|
|
41273
|
+
if (!(0, import_node_fs72.existsSync)(projectPath(SETUP_STATE_FILE))) return;
|
|
40793
41274
|
try {
|
|
40794
41275
|
if ((await readSetupState())?.telemetry === choice) return;
|
|
40795
41276
|
await writeSetupState({ telemetry: choice });
|
|
@@ -40866,8 +41347,8 @@ function registerTelemetryCommands(program2) {
|
|
|
40866
41347
|
}
|
|
40867
41348
|
|
|
40868
41349
|
// src/commands/prove.ts
|
|
40869
|
-
var
|
|
40870
|
-
var
|
|
41350
|
+
var import_node_fs73 = require("node:fs");
|
|
41351
|
+
var import_node_path56 = require("node:path");
|
|
40871
41352
|
|
|
40872
41353
|
// src/lib/prove/hint-pool.ts
|
|
40873
41354
|
var STOP2 = /* @__PURE__ */ new Set([
|
|
@@ -40994,7 +41475,13 @@ async function proveAuth(program2) {
|
|
|
40994
41475
|
}
|
|
40995
41476
|
function registerProveCommand(program2) {
|
|
40996
41477
|
const prove = program2.command("prove").description("Formal verification (Lean 4) of small, risky pieces of code \u2014 on demand");
|
|
40997
|
-
prove.command("candidates [paths...]").description("Rank code worth a formal model, from git history and risk signals").option("--since <when>", `git --since window (default: "${DEFAULT_SINCE}")`).option("--limit <n>", "Candidates to show", "10").option("--rank <ranker>", "deterministic | luna | jev (luna and jev need an API key)", "deterministic").option("--hint <text>", "What the user wants checked, in their words (biases the rank; implies --rank luna)").option("--json", "Machine-readable output").action(async (paths, opts) => {
|
|
41478
|
+
prove.command("candidates [paths...]").description("Rank code worth a formal model, from git history and risk signals").option("--since <when>", `git --since window (default: "${DEFAULT_SINCE}")`).option("--limit <n>", "Candidates to show", "10").option("--rank <ranker>", "deterministic | luna | jev (luna and jev need an API key)", "deterministic").option("--hint <text>", "What the user wants checked, in their words (biases the rank; implies --rank luna); - reads it from stdin, so the words never pass through shell quoting").option("--json", "Machine-readable output").action(async (paths, opts) => {
|
|
41479
|
+
const hint = readTextInput(opts.hint, "--hint");
|
|
41480
|
+
if (!hint.ok) {
|
|
41481
|
+
printError(hint.error);
|
|
41482
|
+
process.exit(2);
|
|
41483
|
+
}
|
|
41484
|
+
opts.hint = hint.text;
|
|
40998
41485
|
if (opts.hint && opts.rank === "deterministic") opts.rank = "luna";
|
|
40999
41486
|
const root = repoRoot();
|
|
41000
41487
|
const ranker = RANKERS[opts.rank];
|
|
@@ -41003,7 +41490,7 @@ function registerProveCommand(program2) {
|
|
|
41003
41490
|
process.exit(2);
|
|
41004
41491
|
}
|
|
41005
41492
|
const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
|
|
41006
|
-
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0,
|
|
41493
|
+
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path56.relative)(root, (0, import_node_path56.resolve)(p)) || ".") });
|
|
41007
41494
|
if (opts.hint && paths.length === 0) {
|
|
41008
41495
|
const hit = hintMatches(root, opts.hint);
|
|
41009
41496
|
if (hit.files.length > 0) {
|
|
@@ -41057,7 +41544,7 @@ function registerProveCommand(program2) {
|
|
|
41057
41544
|
});
|
|
41058
41545
|
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) => {
|
|
41059
41546
|
const root = repoRoot();
|
|
41060
|
-
if (!(0,
|
|
41547
|
+
if (!(0, import_node_fs73.existsSync)((0, import_node_path56.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41061
41548
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41062
41549
|
process.exit(2);
|
|
41063
41550
|
}
|
|
@@ -41081,7 +41568,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41081
41568
|
const reports = [];
|
|
41082
41569
|
for (const f of files) {
|
|
41083
41570
|
const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
|
|
41084
|
-
report.file = (0,
|
|
41571
|
+
report.file = (0, import_node_path56.relative)(root, f);
|
|
41085
41572
|
reports.push(report);
|
|
41086
41573
|
try {
|
|
41087
41574
|
writeResult(root, report);
|
|
@@ -41119,7 +41606,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41119
41606
|
printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
|
|
41120
41607
|
process.exit(2);
|
|
41121
41608
|
}
|
|
41122
|
-
if (!(0,
|
|
41609
|
+
if (!(0, import_node_fs73.existsSync)((0, import_node_path56.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41123
41610
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41124
41611
|
process.exit(2);
|
|
41125
41612
|
}
|
|
@@ -41150,7 +41637,7 @@ ${report.error ?? ""}`);
|
|
|
41150
41637
|
printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
|
|
41151
41638
|
return;
|
|
41152
41639
|
}
|
|
41153
|
-
const modelSource = readRegularFileInRoot(root, (0,
|
|
41640
|
+
const modelSource = readRegularFileInRoot(root, (0, import_node_path56.relative)(root, file), 512 * 1024);
|
|
41154
41641
|
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`);
|
|
41155
41642
|
const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
|
|
41156
41643
|
const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
|
|
@@ -41170,7 +41657,7 @@ ${report.error ?? ""}`);
|
|
|
41170
41657
|
});
|
|
41171
41658
|
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) => {
|
|
41172
41659
|
const root = repoRoot();
|
|
41173
|
-
let files = paths.map((p) => (0,
|
|
41660
|
+
let files = paths.map((p) => (0, import_node_path56.relative)(root, (0, import_node_path56.resolve)(p)));
|
|
41174
41661
|
if (files.length === 0) {
|
|
41175
41662
|
const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
|
|
41176
41663
|
const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
|
|
@@ -41199,7 +41686,19 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41199
41686
|
}
|
|
41200
41687
|
process.exit(outcome.findings.some((f) => f.verdict === "reproduced") ? 1 : 0);
|
|
41201
41688
|
});
|
|
41202
|
-
prove.command("generate <target>").description("Have the Verity service write a Lean model of one symbol (file#symbol), lint it, and check it here \u2014 up to 3 rounds").option("--lines <a-b>", "Model a region of the file (1-based, inclusive) instead of a named symbol").option("--hint <text>", "The user's worry, in their words (may become an intent property)").option("--revise <model>", "Revise this existing model after a diverged replay (with --note)").option("--note <text>", "What the replay showed was different (with --revise)").option("--json", "Machine-readable output").action(async (targetArg, opts) => {
|
|
41689
|
+
prove.command("generate <target>").description("Have the Verity service write a Lean model of one symbol (file#symbol), lint it, and check it here \u2014 up to 3 rounds").option("--lines <a-b>", "Model a region of the file (1-based, inclusive) instead of a named symbol").option("--hint <text>", "The user's worry, in their words (may become an intent property); - reads it from stdin").option("--revise <model>", "Revise this existing model after a diverged replay (with --note)").option("--note <text>", "What the replay showed was different (with --revise); - reads it from stdin").option("--json", "Machine-readable output").action(async (targetArg, opts) => {
|
|
41690
|
+
if (opts.hint === "-" && opts.note === "-") {
|
|
41691
|
+
printError("Only one of --hint and --note can read stdin (-).");
|
|
41692
|
+
process.exit(2);
|
|
41693
|
+
}
|
|
41694
|
+
for (const flag of ["hint", "note"]) {
|
|
41695
|
+
const input = readTextInput(opts[flag], `--${flag}`);
|
|
41696
|
+
if (!input.ok) {
|
|
41697
|
+
printError(input.error);
|
|
41698
|
+
process.exit(2);
|
|
41699
|
+
}
|
|
41700
|
+
opts[flag] = input.text;
|
|
41701
|
+
}
|
|
41203
41702
|
const root = repoRoot();
|
|
41204
41703
|
const auth2 = await proveAuth(program2);
|
|
41205
41704
|
if (!auth2 && !(process.env.VERITY_PROVE_DIRECT === "1" && process.env.OPENAI_API_KEY)) {
|
|
@@ -41230,9 +41729,9 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41230
41729
|
let revise;
|
|
41231
41730
|
if (opts.revise) {
|
|
41232
41731
|
const existing = resolveModelFile(root, opts.revise);
|
|
41233
|
-
const src = existing ? readRegularFileInRoot(root, (0,
|
|
41732
|
+
const src = existing ? readRegularFileInRoot(root, (0, import_node_path56.relative)(root, existing), 64 * 1024) : null;
|
|
41234
41733
|
if (!src || !src.ok || !opts.note) {
|
|
41235
|
-
printError(
|
|
41734
|
+
printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
|
|
41236
41735
|
process.exit(2);
|
|
41237
41736
|
}
|
|
41238
41737
|
revise = { source: src.content, note: opts.note };
|
|
@@ -41243,21 +41742,22 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41243
41742
|
printError("Verity library did not build");
|
|
41244
41743
|
process.exit(2);
|
|
41245
41744
|
}
|
|
41246
|
-
const deps =
|
|
41745
|
+
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 });
|
|
41247
41746
|
if (!opts.json) printInfo(`asking the Verity service for a model of ${symbol || `${file}:${opts.lines}`} \u2026`);
|
|
41248
41747
|
const out2 = await generateAndCheck(root, { file, symbol: symbol || `${file}:${opts.lines}`, lines, hint: opts.hint, revise }, { deps, maxRounds: 3 });
|
|
41249
41748
|
if (!out2.ok) {
|
|
41250
41749
|
if (opts.json) printJson(out2);
|
|
41251
|
-
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`);
|
|
41750
|
+
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`);
|
|
41252
41751
|
process.exit(2);
|
|
41253
41752
|
}
|
|
41753
|
+
if (out2.warning && !opts.json) printWarn(out2.warning);
|
|
41254
41754
|
try {
|
|
41255
41755
|
writeResult(root, out2.report);
|
|
41256
41756
|
} catch (err2) {
|
|
41257
41757
|
if (!(err2 instanceof SafeWriteError)) throw err2;
|
|
41258
41758
|
}
|
|
41259
41759
|
if (opts.json) {
|
|
41260
|
-
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) } });
|
|
41760
|
+
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) } });
|
|
41261
41761
|
return;
|
|
41262
41762
|
}
|
|
41263
41763
|
printInfo(`wrote ${out2.file} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""})`);
|
|
@@ -41269,8 +41769,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41269
41769
|
});
|
|
41270
41770
|
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) => {
|
|
41271
41771
|
const root = repoRoot();
|
|
41272
|
-
const rel0 = (0,
|
|
41273
|
-
const rel = rel0.startsWith("..") || (0,
|
|
41772
|
+
const rel0 = (0, import_node_path56.relative)(root, (0, import_node_path56.isAbsolute)(file) ? file : (0, import_node_path56.join)(root, file)).replace(/\\/g, "/");
|
|
41773
|
+
const rel = rel0.startsWith("..") || (0, import_node_path56.isAbsolute)(rel0) ? null : rel0;
|
|
41274
41774
|
if (!rel) {
|
|
41275
41775
|
printError(`${file} is not inside this repository`);
|
|
41276
41776
|
process.exit(2);
|
|
@@ -41286,8 +41786,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41286
41786
|
});
|
|
41287
41787
|
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) => {
|
|
41288
41788
|
const root = repoRoot();
|
|
41289
|
-
const rel = (0,
|
|
41290
|
-
const digest = rel.startsWith("..") || (0,
|
|
41789
|
+
const rel = (0, import_node_path56.relative)(root, (0, import_node_path56.isAbsolute)(file) ? file : (0, import_node_path56.join)(root, file));
|
|
41790
|
+
const digest = rel.startsWith("..") || (0, import_node_path56.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
|
|
41291
41791
|
if (!digest) {
|
|
41292
41792
|
printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
|
|
41293
41793
|
process.exit(2);
|
|
@@ -41321,10 +41821,10 @@ function refreshScaffold(root) {
|
|
|
41321
41821
|
}
|
|
41322
41822
|
|
|
41323
41823
|
// src/commands/lean.ts
|
|
41324
|
-
var
|
|
41824
|
+
var import_node_fs74 = require("node:fs");
|
|
41325
41825
|
var import_node_child_process20 = require("node:child_process");
|
|
41326
|
-
var
|
|
41327
|
-
var
|
|
41826
|
+
var import_node_os12 = require("node:os");
|
|
41827
|
+
var import_node_path57 = require("node:path");
|
|
41328
41828
|
function registerLeanCommand(program2) {
|
|
41329
41829
|
const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
|
|
41330
41830
|
lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
|
|
@@ -41341,7 +41841,7 @@ function registerLeanCommand(program2) {
|
|
|
41341
41841
|
const managed = pinnedVersionDir();
|
|
41342
41842
|
const matches = version ? version.includes(pin) : false;
|
|
41343
41843
|
if (opts.json) {
|
|
41344
|
-
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0,
|
|
41844
|
+
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() });
|
|
41345
41845
|
return;
|
|
41346
41846
|
}
|
|
41347
41847
|
printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
|
|
@@ -41355,11 +41855,11 @@ function registerLeanCommand(program2) {
|
|
|
41355
41855
|
lean.command("install").description("Download and unpack the pinned Lean 4 into ~/.verity/lean/<version> (official release, \u2248800 MB, 2.7 GB on disk)").option("--yes", "Do not ask").option("--force", "Reinstall even if present").action(async (opts) => {
|
|
41356
41856
|
const asset = leanAssetName();
|
|
41357
41857
|
if (!asset) {
|
|
41358
|
-
printError(`no Lean release for ${(0,
|
|
41858
|
+
printError(`no Lean release for ${(0, import_node_os12.platform)()}/${(0, import_node_os12.arch)()}`);
|
|
41359
41859
|
process.exit(2);
|
|
41360
41860
|
}
|
|
41361
41861
|
const dir = pinnedVersionDir();
|
|
41362
|
-
if ((0,
|
|
41862
|
+
if ((0, import_node_fs74.existsSync)((0, import_node_path57.join)(dir, "bin", "lake")) && !opts.force) {
|
|
41363
41863
|
printInfo(`already installed at ${dir}`);
|
|
41364
41864
|
return;
|
|
41365
41865
|
}
|
|
@@ -41395,18 +41895,18 @@ function registerLeanCommand(program2) {
|
|
|
41395
41895
|
});
|
|
41396
41896
|
lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
|
|
41397
41897
|
const dir = pinnedVersionDir();
|
|
41398
|
-
if (!(0,
|
|
41898
|
+
if (!(0, import_node_fs74.existsSync)(dir)) {
|
|
41399
41899
|
printInfo("nothing to remove");
|
|
41400
41900
|
return;
|
|
41401
41901
|
}
|
|
41402
|
-
(0,
|
|
41902
|
+
(0, import_node_fs74.rmSync)(dir, { recursive: true, force: true });
|
|
41403
41903
|
printInfo(`removed ${dir}`);
|
|
41404
41904
|
});
|
|
41405
41905
|
}
|
|
41406
41906
|
|
|
41407
41907
|
// src/cli.ts
|
|
41408
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.34.
|
|
41409
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.
|
|
41908
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.34.1-experimental.199c728").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) => {
|
|
41909
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.1-experimental.199c728");
|
|
41410
41910
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
41411
41911
|
try {
|
|
41412
41912
|
await foldLegacyLocalCredential();
|