@codacy/verity-cli 0.34.1-experimental.c910405 → 0.34.2-experimental.2cad220
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 +28 -0
- package/bin/verity.js +1019 -636
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -2928,7 +2928,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2928
2928
|
* @param {(string | Function)} text - string to add, or a function returning a string
|
|
2929
2929
|
* @return {Command} `this` command for chaining
|
|
2930
2930
|
*/
|
|
2931
|
-
addHelpText(position,
|
|
2931
|
+
addHelpText(position, text2) {
|
|
2932
2932
|
const allowedValues = ["beforeAll", "before", "after", "afterAll"];
|
|
2933
2933
|
if (!allowedValues.includes(position)) {
|
|
2934
2934
|
throw new Error(`Unexpected value for position to addHelpText.
|
|
@@ -2937,10 +2937,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2937
2937
|
const helpEvent = `${position}Help`;
|
|
2938
2938
|
this.on(helpEvent, (context) => {
|
|
2939
2939
|
let helpStr;
|
|
2940
|
-
if (typeof
|
|
2941
|
-
helpStr =
|
|
2940
|
+
if (typeof text2 === "function") {
|
|
2941
|
+
helpStr = text2({ error: context.error, command: context.command });
|
|
2942
2942
|
} else {
|
|
2943
|
-
helpStr =
|
|
2943
|
+
helpStr = text2;
|
|
2944
2944
|
}
|
|
2945
2945
|
if (helpStr) {
|
|
2946
2946
|
context.write(`${helpStr}
|
|
@@ -3982,14 +3982,14 @@ var require_foldFlowLines = __commonJS2({
|
|
|
3982
3982
|
var FOLD_FLOW = "flow";
|
|
3983
3983
|
var FOLD_BLOCK = "block";
|
|
3984
3984
|
var FOLD_QUOTED = "quoted";
|
|
3985
|
-
function foldFlowLines(
|
|
3985
|
+
function foldFlowLines(text2, indent, mode2 = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
|
|
3986
3986
|
if (!lineWidth || lineWidth < 0)
|
|
3987
|
-
return
|
|
3987
|
+
return text2;
|
|
3988
3988
|
if (lineWidth < minContentWidth)
|
|
3989
3989
|
minContentWidth = 0;
|
|
3990
3990
|
const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
|
|
3991
|
-
if (
|
|
3992
|
-
return
|
|
3991
|
+
if (text2.length <= endStep)
|
|
3992
|
+
return text2;
|
|
3993
3993
|
const folds = [];
|
|
3994
3994
|
const escapedFolds = {};
|
|
3995
3995
|
let end = lineWidth - indent.length;
|
|
@@ -4006,14 +4006,14 @@ var require_foldFlowLines = __commonJS2({
|
|
|
4006
4006
|
let escStart = -1;
|
|
4007
4007
|
let escEnd = -1;
|
|
4008
4008
|
if (mode2 === FOLD_BLOCK) {
|
|
4009
|
-
i2 = consumeMoreIndentedLines(
|
|
4009
|
+
i2 = consumeMoreIndentedLines(text2, i2, indent.length);
|
|
4010
4010
|
if (i2 !== -1)
|
|
4011
4011
|
end = i2 + endStep;
|
|
4012
4012
|
}
|
|
4013
|
-
for (let ch; ch =
|
|
4013
|
+
for (let ch; ch = text2[i2 += 1]; ) {
|
|
4014
4014
|
if (mode2 === FOLD_QUOTED && ch === "\\") {
|
|
4015
4015
|
escStart = i2;
|
|
4016
|
-
switch (
|
|
4016
|
+
switch (text2[i2 + 1]) {
|
|
4017
4017
|
case "x":
|
|
4018
4018
|
i2 += 3;
|
|
4019
4019
|
break;
|
|
@@ -4030,12 +4030,12 @@ var require_foldFlowLines = __commonJS2({
|
|
|
4030
4030
|
}
|
|
4031
4031
|
if (ch === "\n") {
|
|
4032
4032
|
if (mode2 === FOLD_BLOCK)
|
|
4033
|
-
i2 = consumeMoreIndentedLines(
|
|
4033
|
+
i2 = consumeMoreIndentedLines(text2, i2, indent.length);
|
|
4034
4034
|
end = i2 + indent.length + endStep;
|
|
4035
4035
|
split = void 0;
|
|
4036
4036
|
} else {
|
|
4037
4037
|
if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") {
|
|
4038
|
-
const next =
|
|
4038
|
+
const next = text2[i2 + 1];
|
|
4039
4039
|
if (next && next !== " " && next !== "\n" && next !== " ")
|
|
4040
4040
|
split = i2;
|
|
4041
4041
|
}
|
|
@@ -4047,12 +4047,12 @@ var require_foldFlowLines = __commonJS2({
|
|
|
4047
4047
|
} else if (mode2 === FOLD_QUOTED) {
|
|
4048
4048
|
while (prev === " " || prev === " ") {
|
|
4049
4049
|
prev = ch;
|
|
4050
|
-
ch =
|
|
4050
|
+
ch = text2[i2 += 1];
|
|
4051
4051
|
overflow = true;
|
|
4052
4052
|
}
|
|
4053
4053
|
const j = i2 > escEnd + 1 ? i2 - 2 : escStart - 1;
|
|
4054
4054
|
if (escapedFolds[j])
|
|
4055
|
-
return
|
|
4055
|
+
return text2;
|
|
4056
4056
|
folds.push(j);
|
|
4057
4057
|
escapedFolds[j] = true;
|
|
4058
4058
|
end = j + endStep;
|
|
@@ -4067,39 +4067,39 @@ var require_foldFlowLines = __commonJS2({
|
|
|
4067
4067
|
if (overflow && onOverflow)
|
|
4068
4068
|
onOverflow();
|
|
4069
4069
|
if (folds.length === 0)
|
|
4070
|
-
return
|
|
4070
|
+
return text2;
|
|
4071
4071
|
if (onFold)
|
|
4072
4072
|
onFold();
|
|
4073
|
-
let res =
|
|
4073
|
+
let res = text2.slice(0, folds[0]);
|
|
4074
4074
|
for (let i3 = 0; i3 < folds.length; ++i3) {
|
|
4075
4075
|
const fold2 = folds[i3];
|
|
4076
|
-
const end2 = folds[i3 + 1] ||
|
|
4076
|
+
const end2 = folds[i3 + 1] || text2.length;
|
|
4077
4077
|
if (fold2 === 0)
|
|
4078
4078
|
res = `
|
|
4079
|
-
${indent}${
|
|
4079
|
+
${indent}${text2.slice(0, end2)}`;
|
|
4080
4080
|
else {
|
|
4081
4081
|
if (mode2 === FOLD_QUOTED && escapedFolds[fold2])
|
|
4082
|
-
res += `${
|
|
4082
|
+
res += `${text2[fold2]}\\`;
|
|
4083
4083
|
res += `
|
|
4084
|
-
${indent}${
|
|
4084
|
+
${indent}${text2.slice(fold2 + 1, end2)}`;
|
|
4085
4085
|
}
|
|
4086
4086
|
}
|
|
4087
4087
|
return res;
|
|
4088
4088
|
}
|
|
4089
|
-
function consumeMoreIndentedLines(
|
|
4089
|
+
function consumeMoreIndentedLines(text2, i2, indent) {
|
|
4090
4090
|
let end = i2;
|
|
4091
4091
|
let start2 = i2 + 1;
|
|
4092
|
-
let ch =
|
|
4092
|
+
let ch = text2[start2];
|
|
4093
4093
|
while (ch === " " || ch === " ") {
|
|
4094
4094
|
if (i2 < start2 + indent) {
|
|
4095
|
-
ch =
|
|
4095
|
+
ch = text2[++i2];
|
|
4096
4096
|
} else {
|
|
4097
4097
|
do {
|
|
4098
|
-
ch =
|
|
4098
|
+
ch = text2[++i2];
|
|
4099
4099
|
} while (ch && ch !== "\n");
|
|
4100
4100
|
end = i2;
|
|
4101
4101
|
start2 = i2 + 1;
|
|
4102
|
-
ch =
|
|
4102
|
+
ch = text2[start2];
|
|
4103
4103
|
}
|
|
4104
4104
|
}
|
|
4105
4105
|
return end;
|
|
@@ -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: sep7, value } = collItem;
|
|
6979
6979
|
const keyProps = resolveProps.resolveProps(start2, {
|
|
6980
6980
|
indicator: "explicit-key-ind",
|
|
6981
|
-
next: key ??
|
|
6981
|
+
next: key ?? sep7?.[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 && !sep7) {
|
|
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(sep7 ?? [], {
|
|
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, sep7, 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 sep7 = "";
|
|
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 += sep7 + cb;
|
|
7141
|
+
sep7 = "";
|
|
7142
7142
|
break;
|
|
7143
7143
|
}
|
|
7144
7144
|
case "newline":
|
|
7145
7145
|
if (comment)
|
|
7146
|
-
|
|
7146
|
+
sep7 += 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: sep7, 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 ?? sep7?.[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 && !sep7 && !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 && !sep7 && !props.found) {
|
|
7255
|
+
const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep7, 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(sep7 ?? [], {
|
|
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 (sep7)
|
|
7279
|
+
for (const st of sep7) {
|
|
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, sep7, 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 sep7 = "";
|
|
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 += sep7 + indent.slice(trimIndent) + content;
|
|
7494
|
+
sep7 = "\n";
|
|
7495
7495
|
} else if (indent.length > trimIndent || content[0] === " ") {
|
|
7496
|
-
if (
|
|
7497
|
-
|
|
7498
|
-
else if (!prevMoreIndented &&
|
|
7499
|
-
|
|
7500
|
-
value +=
|
|
7501
|
-
|
|
7496
|
+
if (sep7 === " ")
|
|
7497
|
+
sep7 = "\n";
|
|
7498
|
+
else if (!prevMoreIndented && sep7 === "\n")
|
|
7499
|
+
sep7 = "\n\n";
|
|
7500
|
+
value += sep7 + indent.slice(trimIndent) + content;
|
|
7501
|
+
sep7 = "\n";
|
|
7502
7502
|
prevMoreIndented = true;
|
|
7503
7503
|
} else if (content === "") {
|
|
7504
|
-
if (
|
|
7504
|
+
if (sep7 === "\n")
|
|
7505
7505
|
value += "\n";
|
|
7506
7506
|
else
|
|
7507
|
-
|
|
7507
|
+
sep7 = "\n";
|
|
7508
7508
|
} else {
|
|
7509
|
-
value +=
|
|
7510
|
-
|
|
7509
|
+
value += sep7 + content;
|
|
7510
|
+
sep7 = " ";
|
|
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 sep7 = " ";
|
|
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 (sep7 === "\n")
|
|
7698
|
+
res += sep7;
|
|
7699
7699
|
else
|
|
7700
|
-
|
|
7700
|
+
sep7 = "\n";
|
|
7701
7701
|
} else {
|
|
7702
|
-
res +=
|
|
7703
|
-
|
|
7702
|
+
res += sep7 + match[1];
|
|
7703
|
+
sep7 = " ";
|
|
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 + sep7 + (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: sep7, 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 (sep7)
|
|
8524
|
+
for (const st of sep7)
|
|
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 sep7;
|
|
9675
9675
|
if (scalar.end) {
|
|
9676
|
-
|
|
9677
|
-
|
|
9676
|
+
sep7 = scalar.end;
|
|
9677
|
+
sep7.push(this.sourceToken);
|
|
9678
9678
|
delete scalar.end;
|
|
9679
9679
|
} else
|
|
9680
|
-
|
|
9680
|
+
sep7 = [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: sep7 }]
|
|
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 sep7 = it.sep;
|
|
9839
|
+
sep7.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: sep7 }]
|
|
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 sep7 = fc.end.splice(1, fc.end.length);
|
|
10041
|
+
sep7.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: sep7 }]
|
|
10047
10047
|
};
|
|
10048
10048
|
this.onKeyLine = true;
|
|
10049
10049
|
this.stack[this.stack.length - 1] = map;
|
|
@@ -13882,11 +13882,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
13882
13882
|
for (const c of captures) {
|
|
13883
13883
|
if (c.name === captureName) nodes.push(c.node.text);
|
|
13884
13884
|
}
|
|
13885
|
-
const test = /* @__PURE__ */ __name((
|
|
13886
|
-
return positive ? regex.test(
|
|
13885
|
+
const test = /* @__PURE__ */ __name((text2, positive) => {
|
|
13886
|
+
return positive ? regex.test(text2) : !regex.test(text2);
|
|
13887
13887
|
}, "test");
|
|
13888
13888
|
if (nodes.length === 0) return !isPositive;
|
|
13889
|
-
return matchAll2 ? nodes.every((
|
|
13889
|
+
return matchAll2 ? nodes.every((text2) => test(text2, isPositive)) : nodes.some((text2) => test(text2, isPositive));
|
|
13890
13890
|
});
|
|
13891
13891
|
}
|
|
13892
13892
|
__name(parseMatchPredicate, "parseMatchPredicate");
|
|
@@ -13916,7 +13916,7 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
13916
13916
|
if (c.name === captureName) nodes.push(c.node.text);
|
|
13917
13917
|
}
|
|
13918
13918
|
if (nodes.length === 0) return !isPositive;
|
|
13919
|
-
return nodes.every((
|
|
13919
|
+
return nodes.every((text2) => values.includes(text2)) === isPositive;
|
|
13920
13920
|
});
|
|
13921
13921
|
}
|
|
13922
13922
|
__name(parseAnyOfPredicate, "parseAnyOfPredicate");
|
|
@@ -15172,8 +15172,8 @@ function filterReviewable(files) {
|
|
|
15172
15172
|
const ext = (0, import_node_path4.extname)(f).slice(1);
|
|
15173
15173
|
if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
|
|
15174
15174
|
if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
|
|
15175
|
-
const
|
|
15176
|
-
if (REVIEWABLE_FILENAMES.has(
|
|
15175
|
+
const basename11 = f.split("/").pop() ?? "";
|
|
15176
|
+
if (REVIEWABLE_FILENAMES.has(basename11)) return true;
|
|
15177
15177
|
if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
|
|
15178
15178
|
return false;
|
|
15179
15179
|
});
|
|
@@ -15712,11 +15712,11 @@ function startSpinner(label2, opts = {}) {
|
|
|
15712
15712
|
},
|
|
15713
15713
|
succeed(message) {
|
|
15714
15714
|
finish(() => {
|
|
15715
|
-
const
|
|
15715
|
+
const text2 = message ?? current;
|
|
15716
15716
|
const clock = showElapsed ? ` (${secondsSince(start2)})` : "";
|
|
15717
15717
|
stream.write(
|
|
15718
|
-
color ? ` ${GREEN2}\u2713${RESET} ${
|
|
15719
|
-
` : ` \u2713 ${
|
|
15718
|
+
color ? ` ${GREEN2}\u2713${RESET} ${text2}${DIM2}${clock}${RESET}
|
|
15719
|
+
` : ` \u2713 ${text2}${clock}
|
|
15720
15720
|
`
|
|
15721
15721
|
);
|
|
15722
15722
|
});
|
|
@@ -16287,6 +16287,15 @@ async function reportLoginOutcome(out2, opts = {}) {
|
|
|
16287
16287
|
}
|
|
16288
16288
|
}
|
|
16289
16289
|
|
|
16290
|
+
// src/lib/session-env.ts
|
|
16291
|
+
function envSessionId(env = process.env) {
|
|
16292
|
+
for (const name2 of ["CLAUDE_SESSION_ID", "CLAUDE_CODE_SESSION_ID"]) {
|
|
16293
|
+
const value = env[name2];
|
|
16294
|
+
if (value) return value;
|
|
16295
|
+
}
|
|
16296
|
+
return void 0;
|
|
16297
|
+
}
|
|
16298
|
+
|
|
16290
16299
|
// src/commands/login.ts
|
|
16291
16300
|
function registerLoginCommand(program2) {
|
|
16292
16301
|
program2.command("login").description("Log in to Verity (one GitHub login grants access to all your repositories)").option("--force", "Re-authenticate even if already logged in").option("--start", "Show the GitHub code and return at once (finish with --finish); prints JSON").option("--finish", "Wait for approval of the code --start showed, then log in; prints JSON").option("--wait <seconds>", "With --finish: how long to wait for approval before returning", "100").option("--cancel", "Discard a code --start showed that will not be approved").action(async (opts) => {
|
|
@@ -16303,7 +16312,7 @@ function registerLoginCommand(program2) {
|
|
|
16303
16312
|
return;
|
|
16304
16313
|
}
|
|
16305
16314
|
const split = !!(opts.start || opts.finish);
|
|
16306
|
-
if (!split && !process.stdin.isTTY && (process.env.CLAUDECODE ||
|
|
16315
|
+
if (!split && !process.stdin.isTTY && (process.env.CLAUDECODE || envSessionId())) {
|
|
16307
16316
|
printWarn("Inside a Claude Code session the code below may not be visible until this command ends.");
|
|
16308
16317
|
printWarn(' Use "verity login --start", then "verity login --finish" once it is approved.');
|
|
16309
16318
|
}
|
|
@@ -17435,13 +17444,13 @@ function scrub(s) {
|
|
|
17435
17444
|
var installed = false;
|
|
17436
17445
|
var wroteBanner = false;
|
|
17437
17446
|
var banner = "";
|
|
17438
|
-
function append(
|
|
17447
|
+
function append(text2) {
|
|
17439
17448
|
try {
|
|
17440
17449
|
const dir = projectPath(DEBUG_LOG_DIR);
|
|
17441
17450
|
const file = projectPath(STDERR_LOG_FILE);
|
|
17442
17451
|
(0, import_node_fs9.mkdirSync)(dir, { recursive: true });
|
|
17443
17452
|
rotateIfNeeded(file);
|
|
17444
|
-
(0, import_node_fs9.appendFileSync)(file,
|
|
17453
|
+
(0, import_node_fs9.appendFileSync)(file, text2);
|
|
17445
17454
|
} catch {
|
|
17446
17455
|
}
|
|
17447
17456
|
}
|
|
@@ -17463,19 +17472,19 @@ function installStderrLog(cmd, argv, version) {
|
|
|
17463
17472
|
const result = original(...args2);
|
|
17464
17473
|
try {
|
|
17465
17474
|
const chunk = args2[0];
|
|
17466
|
-
const
|
|
17475
|
+
const text2 = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
|
|
17467
17476
|
ensureBanner();
|
|
17468
|
-
append(scrub(
|
|
17477
|
+
append(scrub(text2));
|
|
17469
17478
|
} catch {
|
|
17470
17479
|
}
|
|
17471
17480
|
return result;
|
|
17472
17481
|
};
|
|
17473
17482
|
process.stderr.write = tee;
|
|
17474
17483
|
}
|
|
17475
|
-
function logToFileOnly(
|
|
17484
|
+
function logToFileOnly(text2) {
|
|
17476
17485
|
if (!installed) return;
|
|
17477
17486
|
ensureBanner();
|
|
17478
|
-
append(
|
|
17487
|
+
append(text2.endsWith("\n") ? text2 : `${text2}
|
|
17479
17488
|
`);
|
|
17480
17489
|
}
|
|
17481
17490
|
|
|
@@ -18046,8 +18055,8 @@ var import_promises5 = require("node:fs/promises");
|
|
|
18046
18055
|
var import_node_fs12 = require("node:fs");
|
|
18047
18056
|
var import_node_child_process6 = require("node:child_process");
|
|
18048
18057
|
var import_node_crypto2 = require("node:crypto");
|
|
18049
|
-
function stripImageReferences(
|
|
18050
|
-
return
|
|
18058
|
+
function stripImageReferences(text2) {
|
|
18059
|
+
return text2.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
|
|
18051
18060
|
}
|
|
18052
18061
|
function bufferTmpPath() {
|
|
18053
18062
|
return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto2.randomBytes)(4).toString("hex")}.tmp`;
|
|
@@ -18913,9 +18922,9 @@ var STOPWORDS = /* @__PURE__ */ new Set([
|
|
|
18913
18922
|
"within",
|
|
18914
18923
|
"without"
|
|
18915
18924
|
]);
|
|
18916
|
-
function tokenize(
|
|
18925
|
+
function tokenize(text2) {
|
|
18917
18926
|
return new Set(
|
|
18918
|
-
|
|
18927
|
+
text2.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOPWORDS.has(w))
|
|
18919
18928
|
);
|
|
18920
18929
|
}
|
|
18921
18930
|
function jaccardKeywords(a, b) {
|
|
@@ -18992,9 +19001,9 @@ var MAX_BUDGET_TOKENS = 4e3;
|
|
|
18992
19001
|
var MAX_NODE_FILE_BYTES = 64 * 1024;
|
|
18993
19002
|
var MIN_SCORE = RELEVANCE_FLOOR * 0.5;
|
|
18994
19003
|
var ORG_MIN_SHARED_TERMS = 2;
|
|
18995
|
-
function orgTerms(
|
|
19004
|
+
function orgTerms(text2) {
|
|
18996
19005
|
return new Set(
|
|
18997
|
-
|
|
19006
|
+
text2.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
|
|
18998
19007
|
);
|
|
18999
19008
|
}
|
|
19000
19009
|
function sharedTerms(a, b) {
|
|
@@ -19277,15 +19286,15 @@ function runHook(hooks) {
|
|
|
19277
19286
|
return false;
|
|
19278
19287
|
}
|
|
19279
19288
|
}
|
|
19280
|
-
function appendInRoot(root, name2,
|
|
19289
|
+
function appendInRoot(root, name2, text2, hooks = {}) {
|
|
19281
19290
|
return writeVerified(root, name2, hooks, true, (fd) => {
|
|
19282
|
-
(0, import_node_fs17.writeSync)(fd,
|
|
19291
|
+
(0, import_node_fs17.writeSync)(fd, text2);
|
|
19283
19292
|
});
|
|
19284
19293
|
}
|
|
19285
|
-
function replaceInRoot(root, name2,
|
|
19294
|
+
function replaceInRoot(root, name2, text2, hooks = {}) {
|
|
19286
19295
|
return writeVerified(root, name2, hooks, false, (fd) => {
|
|
19287
19296
|
(0, import_node_fs17.ftruncateSync)(fd, 0);
|
|
19288
|
-
(0, import_node_fs17.writeSync)(fd,
|
|
19297
|
+
(0, import_node_fs17.writeSync)(fd, text2, 0);
|
|
19289
19298
|
});
|
|
19290
19299
|
}
|
|
19291
19300
|
|
|
@@ -19475,12 +19484,12 @@ function ensureVerityGitignore() {
|
|
|
19475
19484
|
if (hasSupersededMemory && !memoryIsCommitted) {
|
|
19476
19485
|
next = fenceMemoryLines(next);
|
|
19477
19486
|
}
|
|
19478
|
-
let
|
|
19487
|
+
let text2 = next.join("\n");
|
|
19479
19488
|
if (!hasMarker) {
|
|
19480
|
-
const
|
|
19481
|
-
|
|
19489
|
+
const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
|
|
19490
|
+
text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
|
|
19482
19491
|
}
|
|
19483
|
-
if (
|
|
19492
|
+
if (text2 !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text2);
|
|
19484
19493
|
return verified(
|
|
19485
19494
|
memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
|
|
19486
19495
|
);
|
|
@@ -19506,13 +19515,13 @@ function writeFencedBlock() {
|
|
|
19506
19515
|
const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
|
|
19507
19516
|
let lines = content.split("\n").map((l) => BREAKING_ENTRIES.has(l.trim()) ? ".verity/*" : l);
|
|
19508
19517
|
lines = fenceMemoryLines(lines);
|
|
19509
|
-
let
|
|
19518
|
+
let text2 = lines.join("\n");
|
|
19510
19519
|
if (!hasMarker) {
|
|
19511
|
-
const
|
|
19512
|
-
|
|
19520
|
+
const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
|
|
19521
|
+
text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
|
|
19513
19522
|
}
|
|
19514
19523
|
try {
|
|
19515
|
-
(0, import_node_fs19.writeFileSync)(".gitignore",
|
|
19524
|
+
(0, import_node_fs19.writeFileSync)(".gitignore", text2);
|
|
19516
19525
|
return true;
|
|
19517
19526
|
} catch {
|
|
19518
19527
|
return false;
|
|
@@ -19559,8 +19568,8 @@ function keepMemoryTracked() {
|
|
|
19559
19568
|
}
|
|
19560
19569
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
19561
19570
|
try {
|
|
19562
|
-
const
|
|
19563
|
-
(0, import_node_fs19.writeFileSync)(".gitignore", content +
|
|
19571
|
+
const sep7 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
|
|
19572
|
+
(0, import_node_fs19.writeFileSync)(".gitignore", content + sep7 + MEMORY_OPT_OUT_STANZA);
|
|
19564
19573
|
} catch {
|
|
19565
19574
|
return "failed";
|
|
19566
19575
|
}
|
|
@@ -20491,26 +20500,26 @@ var CLAUDE_MD_PROSE_LEGACY = [
|
|
|
20491
20500
|
"superseded \u2014 ignore them unless investigating history."
|
|
20492
20501
|
].join("\n");
|
|
20493
20502
|
var PRESERVE_PLACEHOLDER = "<!-- Add binding, hand-curated guidance here; it survives Verity regeneration. -->";
|
|
20494
|
-
function* scanLines(
|
|
20503
|
+
function* scanLines(text2) {
|
|
20495
20504
|
let offset = 0;
|
|
20496
20505
|
let inFence = false;
|
|
20497
|
-
for (const line2 of
|
|
20506
|
+
for (const line2 of text2.split("\n")) {
|
|
20498
20507
|
const isFence = /^(`{3,}|~{3,})/.test(line2.trim());
|
|
20499
20508
|
if (isFence) inFence = !inFence;
|
|
20500
20509
|
yield { line: line2, start: offset, inFence: inFence || isFence };
|
|
20501
20510
|
offset += line2.length + 1;
|
|
20502
20511
|
}
|
|
20503
20512
|
}
|
|
20504
|
-
function findMarker(
|
|
20505
|
-
for (const { line: line2, start: start2, inFence } of scanLines(
|
|
20513
|
+
function findMarker(text2, marker, from = 0) {
|
|
20514
|
+
for (const { line: line2, start: start2, inFence } of scanLines(text2)) {
|
|
20506
20515
|
if (!inFence && start2 >= from && line2.startsWith(marker)) {
|
|
20507
20516
|
return start2;
|
|
20508
20517
|
}
|
|
20509
20518
|
}
|
|
20510
20519
|
return -1;
|
|
20511
20520
|
}
|
|
20512
|
-
function hasLegacyMemoryBlock(
|
|
20513
|
-
return findMarker(
|
|
20521
|
+
function hasLegacyMemoryBlock(text2) {
|
|
20522
|
+
return findMarker(text2, LEGACY_MD_START) !== -1;
|
|
20514
20523
|
}
|
|
20515
20524
|
async function ensureClaudeMdPointer(cwd = repoRoot()) {
|
|
20516
20525
|
const claudeMdPath = (0, import_node_path19.join)(cwd, "CLAUDE.md");
|
|
@@ -20710,10 +20719,10 @@ var STOP = /* @__PURE__ */ new Set([
|
|
|
20710
20719
|
"verify",
|
|
20711
20720
|
"check"
|
|
20712
20721
|
]);
|
|
20713
|
-
function pendingTokens(
|
|
20714
|
-
if (!
|
|
20722
|
+
function pendingTokens(text2) {
|
|
20723
|
+
if (!text2 || typeof text2 !== "string") return [];
|
|
20715
20724
|
const out2 = /* @__PURE__ */ new Set();
|
|
20716
|
-
for (const raw of
|
|
20725
|
+
for (const raw of text2.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
20717
20726
|
if (raw.length <= 3) continue;
|
|
20718
20727
|
if (STOP.has(raw)) continue;
|
|
20719
20728
|
out2.add(raw);
|
|
@@ -20728,8 +20737,8 @@ function overlapCoefficient(a, b) {
|
|
|
20728
20737
|
for (const t of a) if (setB.has(t)) shared++;
|
|
20729
20738
|
return shared / Math.min(a.length, b.length);
|
|
20730
20739
|
}
|
|
20731
|
-
function isRepeatOfAny(
|
|
20732
|
-
const tokens = pendingTokens(
|
|
20740
|
+
function isRepeatOfAny(text2, priorFingerprints, threshold = REPEAT_THRESHOLD) {
|
|
20741
|
+
const tokens = pendingTokens(text2);
|
|
20733
20742
|
if (tokens.length === 0) return false;
|
|
20734
20743
|
return priorFingerprints.some((prior) => overlapCoefficient(tokens, prior) >= threshold);
|
|
20735
20744
|
}
|
|
@@ -21419,8 +21428,8 @@ function assessContinuity(i2) {
|
|
|
21419
21428
|
// src/lib/dossier/reanchor.ts
|
|
21420
21429
|
var import_node_crypto8 = require("node:crypto");
|
|
21421
21430
|
var import_node_fs25 = require("node:fs");
|
|
21422
|
-
function lineSha(
|
|
21423
|
-
return (0, import_node_crypto8.createHash)("sha256").update(
|
|
21431
|
+
function lineSha(text2) {
|
|
21432
|
+
return (0, import_node_crypto8.createHash)("sha256").update(text2.trim()).digest("hex").slice(0, HASH_WIDTH);
|
|
21424
21433
|
}
|
|
21425
21434
|
function fileHash(path) {
|
|
21426
21435
|
try {
|
|
@@ -21893,10 +21902,10 @@ function recordGoal(d, prompt, source2 = "prompt") {
|
|
|
21893
21902
|
appendEvent(d, { k: "goal_continue", text: prompt.slice(0, 64) });
|
|
21894
21903
|
return;
|
|
21895
21904
|
}
|
|
21896
|
-
const
|
|
21905
|
+
const text2 = prompt.slice(0, MAX_GOAL_CHARS);
|
|
21897
21906
|
appendEvent(d, {
|
|
21898
21907
|
k: "goal",
|
|
21899
|
-
text,
|
|
21908
|
+
text: text2,
|
|
21900
21909
|
text_len: prompt.length,
|
|
21901
21910
|
source: source2,
|
|
21902
21911
|
...prompt.length > MAX_GOAL_CHARS && { truncated: true }
|
|
@@ -22150,13 +22159,13 @@ function registerIntentCommands(program2) {
|
|
|
22150
22159
|
if (!prompt) {
|
|
22151
22160
|
process.exit(0);
|
|
22152
22161
|
}
|
|
22153
|
-
if (deferredToPlugin("intent capture", event.session_id ??
|
|
22162
|
+
if (deferredToPlugin("intent capture", event.session_id ?? envSessionId() ?? null)) {
|
|
22154
22163
|
process.exit(0);
|
|
22155
22164
|
}
|
|
22156
22165
|
const isPrimitive = isSlashCommand(prompt);
|
|
22157
22166
|
const authForScope = await resolveToken(program2.opts().token);
|
|
22158
22167
|
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
22159
|
-
const scopeSession = event.session_id ||
|
|
22168
|
+
const scopeSession = event.session_id || envSessionId() || "";
|
|
22160
22169
|
if (!isPrimitive) await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
|
|
22161
22170
|
if (!isPrimitive) {
|
|
22162
22171
|
try {
|
|
@@ -22876,7 +22885,12 @@ function registerLifecycleCommands(program2) {
|
|
|
22876
22885
|
}
|
|
22877
22886
|
if (!verityConfigured()) process.exit(0);
|
|
22878
22887
|
const event = await readHookStdin();
|
|
22879
|
-
const
|
|
22888
|
+
const resolved = resolveHookSession(opts.sessionId, event, envSessionId());
|
|
22889
|
+
if (!resolved.ok) {
|
|
22890
|
+
logEvent("lifecycle_session_flag_refused", { command: "compact" });
|
|
22891
|
+
process.exit(0);
|
|
22892
|
+
}
|
|
22893
|
+
const sessionId = resolved.sessionId;
|
|
22880
22894
|
if (deferredToPlugin("compact", sessionId)) process.exit(0);
|
|
22881
22895
|
const globals = program2.opts();
|
|
22882
22896
|
const tok = await resolveToken(globals.token);
|
|
@@ -22905,9 +22919,14 @@ function registerLifecycleCommands(program2) {
|
|
|
22905
22919
|
}
|
|
22906
22920
|
if (!verityConfigured()) process.exit(0);
|
|
22907
22921
|
const event = await readHookStdin();
|
|
22908
|
-
const
|
|
22922
|
+
const resolved = resolveHookSession(opts.sessionId, event, envSessionId());
|
|
22923
|
+
if (!resolved.ok) {
|
|
22924
|
+
logEvent("lifecycle_session_flag_refused", { command: "session end" });
|
|
22925
|
+
process.exit(0);
|
|
22926
|
+
}
|
|
22927
|
+
const sessionId = resolved.sessionId;
|
|
22909
22928
|
if (deferredToPlugin("session end", sessionId)) process.exit(0);
|
|
22910
|
-
const reason = opts.reason ?? event.session_end_reason ?? event.reason ?? "other";
|
|
22929
|
+
const reason = hookWord(opts.reason) ?? event.session_end_reason ?? event.reason ?? "other";
|
|
22911
22930
|
if (reason === "clear") {
|
|
22912
22931
|
writeCarry(sessionId ?? void 0, getCurrentCommit());
|
|
22913
22932
|
}
|
|
@@ -22986,25 +23005,61 @@ function buildCompactionContext(session) {
|
|
|
22986
23005
|
`${r.projection.fold.refused} earlier finding(s) were dropped because the code they pointed at no longer matches. They are resolved; do not revisit them.`
|
|
22987
23006
|
);
|
|
22988
23007
|
}
|
|
22989
|
-
const
|
|
22990
|
-
if (
|
|
23008
|
+
const text2 = lines.join("\n");
|
|
23009
|
+
if (text2.length <= MAX_CHARS) return text2;
|
|
22991
23010
|
const trimmed = [...lines.slice(0, 5), ...lines.slice(5, 5 + 2)].join("\n");
|
|
22992
23011
|
return trimmed.length <= MAX_CHARS ? trimmed : null;
|
|
22993
23012
|
}
|
|
23013
|
+
var MAX_HOOK_EVENT_BYTES = 64 * 1024;
|
|
23014
|
+
var SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
23015
|
+
var HOOK_WORD = /^[a-z][a-z_]{0,63}$/;
|
|
23016
|
+
function isHookSessionId(value) {
|
|
23017
|
+
return typeof value === "string" && SESSION_ID.test(value);
|
|
23018
|
+
}
|
|
23019
|
+
function hookWord(value) {
|
|
23020
|
+
return typeof value === "string" && HOOK_WORD.test(value) ? value : void 0;
|
|
23021
|
+
}
|
|
23022
|
+
function resolveHookSession(flag, event, env) {
|
|
23023
|
+
if (flag !== void 0) return isHookSessionId(flag) ? { ok: true, sessionId: flag } : { ok: false };
|
|
23024
|
+
if (event.session_id) return { ok: true, sessionId: event.session_id };
|
|
23025
|
+
return { ok: true, sessionId: isHookSessionId(env) ? env : null };
|
|
23026
|
+
}
|
|
23027
|
+
function parseHookEvent(raw) {
|
|
23028
|
+
let data;
|
|
23029
|
+
try {
|
|
23030
|
+
data = JSON.parse(raw.trim() || "{}");
|
|
23031
|
+
} catch {
|
|
23032
|
+
return {};
|
|
23033
|
+
}
|
|
23034
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) return {};
|
|
23035
|
+
const o = data;
|
|
23036
|
+
const event = {};
|
|
23037
|
+
if (isHookSessionId(o.session_id)) event.session_id = o.session_id;
|
|
23038
|
+
const compaction = hookWord(o.compaction_type);
|
|
23039
|
+
if (compaction) event.compaction_type = compaction;
|
|
23040
|
+
const endReason = hookWord(o.session_end_reason);
|
|
23041
|
+
if (endReason) event.session_end_reason = endReason;
|
|
23042
|
+
const reason = hookWord(o.reason);
|
|
23043
|
+
if (reason) event.reason = reason;
|
|
23044
|
+
return event;
|
|
23045
|
+
}
|
|
22994
23046
|
async function readHookStdin() {
|
|
22995
23047
|
try {
|
|
22996
23048
|
if (process.stdin.isTTY) return {};
|
|
22997
23049
|
const chunks = [];
|
|
23050
|
+
let size = 0;
|
|
22998
23051
|
const timeout = new Promise((resolve9) => setTimeout(() => resolve9({}), 500));
|
|
22999
23052
|
const read2 = new Promise((resolve9) => {
|
|
23000
|
-
process.stdin.on("data", (c) =>
|
|
23001
|
-
|
|
23002
|
-
|
|
23003
|
-
|
|
23004
|
-
} catch {
|
|
23053
|
+
process.stdin.on("data", (c) => {
|
|
23054
|
+
size += c.length;
|
|
23055
|
+
if (size > MAX_HOOK_EVENT_BYTES) {
|
|
23056
|
+
process.stdin.destroy();
|
|
23005
23057
|
resolve9({});
|
|
23058
|
+
return;
|
|
23006
23059
|
}
|
|
23060
|
+
chunks.push(c);
|
|
23007
23061
|
});
|
|
23062
|
+
process.stdin.on("end", () => resolve9(parseHookEvent(Buffer.concat(chunks).toString("utf-8"))));
|
|
23008
23063
|
process.stdin.on("error", () => resolve9({}));
|
|
23009
23064
|
process.stdin.resume();
|
|
23010
23065
|
});
|
|
@@ -23269,9 +23324,9 @@ function declaredDependencies(root, files) {
|
|
|
23269
23324
|
for (const path of pythonManifests) {
|
|
23270
23325
|
if (!(0, import_node_fs31.existsSync)(path)) continue;
|
|
23271
23326
|
try {
|
|
23272
|
-
const
|
|
23273
|
-
for (const m of
|
|
23274
|
-
for (const line2 of
|
|
23327
|
+
const text2 = (0, import_node_fs31.readFileSync)(path, "utf-8");
|
|
23328
|
+
for (const m of text2.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
|
|
23329
|
+
for (const line2 of text2.split("\n")) {
|
|
23275
23330
|
if (!/dependencies\s*=/.test(line2)) continue;
|
|
23276
23331
|
for (const m of line2.matchAll(/["']([A-Za-z][A-Za-z0-9._-]+)/g)) names2.push(m[1]);
|
|
23277
23332
|
}
|
|
@@ -23285,8 +23340,8 @@ function declaredDependencies(root, files) {
|
|
|
23285
23340
|
for (const path of goMods) {
|
|
23286
23341
|
if (!(0, import_node_fs31.existsSync)(path)) continue;
|
|
23287
23342
|
try {
|
|
23288
|
-
const
|
|
23289
|
-
for (const m of
|
|
23343
|
+
const text2 = (0, import_node_fs31.readFileSync)(path, "utf-8");
|
|
23344
|
+
for (const m of text2.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
|
|
23290
23345
|
names2.push(m[1].replace(/^github\.com\//, ""));
|
|
23291
23346
|
}
|
|
23292
23347
|
} catch {
|
|
@@ -23296,8 +23351,8 @@ function declaredDependencies(root, files) {
|
|
|
23296
23351
|
const path = (0, import_node_path28.join)(root, file);
|
|
23297
23352
|
if (!(0, import_node_fs31.existsSync)(path)) continue;
|
|
23298
23353
|
try {
|
|
23299
|
-
const
|
|
23300
|
-
for (const m of
|
|
23354
|
+
const text2 = (0, import_node_fs31.readFileSync)(path, "utf-8");
|
|
23355
|
+
for (const m of text2.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
|
|
23301
23356
|
} catch {
|
|
23302
23357
|
}
|
|
23303
23358
|
}
|
|
@@ -23828,8 +23883,8 @@ async function correctVerityMdVersion(opts) {
|
|
|
23828
23883
|
origin: { kind: "synthesized", tools: opts.tools }
|
|
23829
23884
|
}));
|
|
23830
23885
|
}
|
|
23831
|
-
async function writeFileTo(
|
|
23832
|
-
const target = projectPath(
|
|
23886
|
+
async function writeFileTo(relative7, body2) {
|
|
23887
|
+
const target = projectPath(relative7);
|
|
23833
23888
|
await (0, import_promises10.mkdir)((0, import_node_path29.dirname)(target), { recursive: true });
|
|
23834
23889
|
await (0, import_promises10.writeFile)(target, body2);
|
|
23835
23890
|
}
|
|
@@ -24908,7 +24963,7 @@ function registerStatusCommand(program2) {
|
|
|
24908
24963
|
{
|
|
24909
24964
|
const tokenForScope = tokenResult.data.token;
|
|
24910
24965
|
const found = resolveIgnoreState(
|
|
24911
|
-
ignoreStateKeys(tokenForScope,
|
|
24966
|
+
ignoreStateKeys(tokenForScope, envSessionId())
|
|
24912
24967
|
);
|
|
24913
24968
|
const now = Math.floor(Date.now() / 1e3);
|
|
24914
24969
|
const active = resolveActive(found?.state ?? null, now);
|
|
@@ -25005,9 +25060,9 @@ function readTextInput(value, flag, readStdin2 = () => (0, import_node_fs39.read
|
|
|
25005
25060
|
if (raw.length > MAX_STDIN_BYTES) {
|
|
25006
25061
|
return { ok: false, error: `${flag} from stdin is ${raw.length} bytes; the limit is ${MAX_STDIN_BYTES}.` };
|
|
25007
25062
|
}
|
|
25008
|
-
const
|
|
25009
|
-
if (!
|
|
25010
|
-
return { ok: true, text };
|
|
25063
|
+
const text2 = raw.toString("utf8").replace(/\r?\n$/, "");
|
|
25064
|
+
if (!text2.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
|
|
25065
|
+
return { ok: true, text: text2 };
|
|
25011
25066
|
}
|
|
25012
25067
|
|
|
25013
25068
|
// src/lib/terminal-text.ts
|
|
@@ -25025,8 +25080,8 @@ function terminalUrl(value) {
|
|
|
25025
25080
|
// src/commands/feedback.ts
|
|
25026
25081
|
function registerFeedbackCommand(program2) {
|
|
25027
25082
|
const feedbackCmd = program2.command("feedback").description("Send feedback to the Verity team");
|
|
25028
|
-
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 (
|
|
25029
|
-
await sendMessageArg(
|
|
25083
|
+
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 (text2, opts) => {
|
|
25084
|
+
await sendMessageArg(text2, opts, program2.opts());
|
|
25030
25085
|
});
|
|
25031
25086
|
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) => {
|
|
25032
25087
|
const globals = program2.opts();
|
|
@@ -25101,7 +25156,7 @@ async function sendGeneralFeedback(message, opts, globals) {
|
|
|
25101
25156
|
process.exit(1);
|
|
25102
25157
|
}
|
|
25103
25158
|
const body2 = { message };
|
|
25104
|
-
const sessionId = opts.sessionId ??
|
|
25159
|
+
const sessionId = opts.sessionId ?? envSessionId();
|
|
25105
25160
|
const model = opts.model ?? process.env.CLAUDE_MODEL ?? "unknown";
|
|
25106
25161
|
if (sessionId) body2.session_id = sessionId;
|
|
25107
25162
|
if (model) body2.agent_model = model;
|
|
@@ -25631,28 +25686,28 @@ function parseRgLine(line2) {
|
|
|
25631
25686
|
return { file: line2.slice(0, first), line: n, text: line2.slice(second + 1) };
|
|
25632
25687
|
}
|
|
25633
25688
|
var isWordChar = (c) => c !== void 0 && /[A-Za-z0-9_]/.test(c);
|
|
25634
|
-
function wordHit(
|
|
25689
|
+
function wordHit(text2, symbol) {
|
|
25635
25690
|
let from = 0;
|
|
25636
25691
|
for (; ; ) {
|
|
25637
|
-
const at =
|
|
25692
|
+
const at = text2.indexOf(symbol, from);
|
|
25638
25693
|
if (at < 0) return false;
|
|
25639
|
-
const before = at === 0 ? void 0 :
|
|
25640
|
-
const after =
|
|
25694
|
+
const before = at === 0 ? void 0 : text2[at - 1];
|
|
25695
|
+
const after = text2[at + symbol.length];
|
|
25641
25696
|
if (!isWordChar(before) && !isWordChar(after)) return true;
|
|
25642
25697
|
from = at + 1;
|
|
25643
25698
|
}
|
|
25644
25699
|
}
|
|
25645
|
-
function isContractLine(
|
|
25700
|
+
function isContractLine(text2, symbol) {
|
|
25646
25701
|
for (const kw of ["implements", "extends"]) {
|
|
25647
25702
|
let from = 0;
|
|
25648
25703
|
for (; ; ) {
|
|
25649
|
-
const at =
|
|
25704
|
+
const at = text2.indexOf(kw, from);
|
|
25650
25705
|
if (at < 0) break;
|
|
25651
25706
|
from = at + 1;
|
|
25652
|
-
const before = at === 0 ? void 0 :
|
|
25653
|
-
const after =
|
|
25707
|
+
const before = at === 0 ? void 0 : text2[at - 1];
|
|
25708
|
+
const after = text2[at + kw.length];
|
|
25654
25709
|
if (isWordChar(before) || isWordChar(after)) continue;
|
|
25655
|
-
let clause =
|
|
25710
|
+
let clause = text2.slice(at + kw.length);
|
|
25656
25711
|
const stop2 = Math.min(
|
|
25657
25712
|
...[clause.indexOf(";"), clause.indexOf("{")].filter((i2) => i2 >= 0)
|
|
25658
25713
|
);
|
|
@@ -25684,20 +25739,20 @@ function partitionSites(rgLines, symbols, opts) {
|
|
|
25684
25739
|
if (opts.sentPaths.has(h.file)) continue;
|
|
25685
25740
|
if (opts.isExcluded(h.file)) continue;
|
|
25686
25741
|
if (!isCodeSiteFile(h.file)) continue;
|
|
25687
|
-
const
|
|
25688
|
-
if (
|
|
25689
|
-
if (COMMENT_LINE.test(
|
|
25690
|
-
if (BARE_MEMBER_LINE.test(
|
|
25742
|
+
const text2 = h.text.trim();
|
|
25743
|
+
if (text2.length === 0 || IMPORT_LINE.test(h.text)) continue;
|
|
25744
|
+
if (COMMENT_LINE.test(text2)) continue;
|
|
25745
|
+
if (BARE_MEMBER_LINE.test(text2) || GO_IMPORT_PATH_LINE.test(text2)) continue;
|
|
25691
25746
|
const n = perFile.get(h.file) ?? 0;
|
|
25692
25747
|
if (n >= MAX_SITES_PER_FILE) continue;
|
|
25693
25748
|
const site = {
|
|
25694
25749
|
file: h.file,
|
|
25695
25750
|
line: h.line,
|
|
25696
|
-
text:
|
|
25751
|
+
text: text2.slice(0, SITE_TEXT_MAX),
|
|
25697
25752
|
symbol: h.symbol,
|
|
25698
25753
|
// R2 falls out of R1 for free: a word search for `Sym` already matches
|
|
25699
25754
|
// `implements Sym` / `extends Sym` lines — classification is all R2 is.
|
|
25700
|
-
...isContractLine(
|
|
25755
|
+
...isContractLine(text2, h.symbol) ? { kind: "contract" } : {}
|
|
25701
25756
|
};
|
|
25702
25757
|
if (isTestPath(h.file)) {
|
|
25703
25758
|
if (tests.length < MAX_TEST_SLOTS) {
|
|
@@ -25717,8 +25772,8 @@ var MAX_IMPORTERS_PER_FILE = 2;
|
|
|
25717
25772
|
function moduleKey(path) {
|
|
25718
25773
|
return path.replace(/\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/i, "").replace(/\/index$/, "");
|
|
25719
25774
|
}
|
|
25720
|
-
function importSpecifier(
|
|
25721
|
-
const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(
|
|
25775
|
+
function importSpecifier(text2) {
|
|
25776
|
+
const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text2);
|
|
25722
25777
|
return m?.[1] ?? null;
|
|
25723
25778
|
}
|
|
25724
25779
|
function resolveSpecifier(fromFile, spec) {
|
|
@@ -25988,8 +26043,8 @@ function extractEnclosingExcerpt(content, siteLine, path) {
|
|
|
25988
26043
|
start2 = Math.max(1, siteLine - (EXCERPT_MAX_LINES - 6));
|
|
25989
26044
|
}
|
|
25990
26045
|
const end = Math.min(lines.length, start2 + EXCERPT_MAX_LINES - 1);
|
|
25991
|
-
const
|
|
25992
|
-
return { start_line: start2, text };
|
|
26046
|
+
const text2 = lines.slice(start2 - 1, end).join("\n").slice(0, EXCERPT_MAX_CHARS);
|
|
26047
|
+
return { start_line: start2, text: text2 };
|
|
25993
26048
|
}
|
|
25994
26049
|
function upgradeToExcerpts(rc, opts) {
|
|
25995
26050
|
if (rc.state !== "ok") return;
|
|
@@ -26345,7 +26400,7 @@ function resolveFrame(input) {
|
|
|
26345
26400
|
const hookDirUsable = !!input.hookCwd && (0, import_node_fs40.existsSync)(input.hookCwd);
|
|
26346
26401
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
26347
26402
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
26348
|
-
const
|
|
26403
|
+
const refuse2 = (refusal) => ({
|
|
26349
26404
|
moment: found?.moment ?? null,
|
|
26350
26405
|
frame: { worktreeRoot: null, gitDir: null, commonDir: null, isLinkedWorktree: false, branch: null, anchor, refusal }
|
|
26351
26406
|
});
|
|
@@ -26359,19 +26414,19 @@ function resolveFrame(input) {
|
|
|
26359
26414
|
if (!kindRes.some((re) => re.test(segments[i2]))) continue;
|
|
26360
26415
|
const target = extractCommandTarget(input.command, i2, baseDir);
|
|
26361
26416
|
if (target.named) anchor = "command-target";
|
|
26362
|
-
if (target.unresolvable) return
|
|
26417
|
+
if (target.unresolvable) return refuse2(`target:${target.unresolvable}`);
|
|
26363
26418
|
dirs.add(target.dir ?? baseDir);
|
|
26364
26419
|
}
|
|
26365
|
-
if (dirs.size > 1) return
|
|
26420
|
+
if (dirs.size > 1) return refuse2(`target:multiple ${found.moment} targets in one command`);
|
|
26366
26421
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
26367
26422
|
if (targetDir !== baseDir) {
|
|
26368
|
-
if (!(0, import_node_fs40.existsSync)(targetDir)) return
|
|
26423
|
+
if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse2(`target:directory does not exist: ${targetDir}`);
|
|
26369
26424
|
dir = targetDir;
|
|
26370
26425
|
}
|
|
26371
26426
|
}
|
|
26372
26427
|
const toplevel = gitAt(dir, ["rev-parse", "--show-toplevel"]);
|
|
26373
26428
|
if (!toplevel) {
|
|
26374
|
-
return
|
|
26429
|
+
return refuse2(anchor === "command-target" ? `target:not a git repository: ${dir}` : `anchor:not a git repository: ${dir}`);
|
|
26375
26430
|
}
|
|
26376
26431
|
const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
|
|
26377
26432
|
const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
|
|
@@ -26967,7 +27022,7 @@ function sanitizeCommandWithLoss(rawCmd) {
|
|
|
26967
27022
|
const lost = lines.slice(1).some((l) => l.trim().length > 0);
|
|
26968
27023
|
const first = lines[0];
|
|
26969
27024
|
const cmd = sanitizeCommand(first);
|
|
26970
|
-
const hadSeparator = SEPARATORS.some((
|
|
27025
|
+
const hadSeparator = SEPARATORS.some((sep7) => first.indexOf(sep7) > 0);
|
|
26971
27026
|
return { cmd, lost: lost || !hadSeparator && first.length > MAX_COMMAND_CHARS };
|
|
26972
27027
|
}
|
|
26973
27028
|
var SEPARATORS = [" | ", " > ", " >> ", " 2>", " && ", " ; "];
|
|
@@ -26976,11 +27031,11 @@ function sanitizeCommand(rawCmd) {
|
|
|
26976
27031
|
let cmd = rawCmd.split("\n")[0];
|
|
26977
27032
|
let cut = -1;
|
|
26978
27033
|
let marker = "";
|
|
26979
|
-
for (const
|
|
26980
|
-
const idx = cmd.indexOf(
|
|
27034
|
+
for (const sep7 of SEPARATORS) {
|
|
27035
|
+
const idx = cmd.indexOf(sep7);
|
|
26981
27036
|
if (idx > 0 && (cut === -1 || idx < cut)) {
|
|
26982
27037
|
cut = idx;
|
|
26983
|
-
marker =
|
|
27038
|
+
marker = sep7.trim();
|
|
26984
27039
|
}
|
|
26985
27040
|
}
|
|
26986
27041
|
if (cut > -1) cmd = cmd.slice(0, cut);
|
|
@@ -27047,13 +27102,13 @@ async function bootstrap(run4) {
|
|
|
27047
27102
|
isTTY: process.stdout.isTTY === true
|
|
27048
27103
|
});
|
|
27049
27104
|
const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
|
|
27050
|
-
if (deferredToPlugin("analyze", sessionId ??
|
|
27105
|
+
if (deferredToPlugin("analyze", sessionId ?? envSessionId() ?? null)) {
|
|
27051
27106
|
process.exit(0);
|
|
27052
27107
|
}
|
|
27053
27108
|
const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
|
|
27054
27109
|
const tokenResult = await resolveToken(globals.token);
|
|
27055
27110
|
const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
27056
|
-
const rawSessionId = sessionId ||
|
|
27111
|
+
const rawSessionId = sessionId || envSessionId();
|
|
27057
27112
|
const baselineSessionId = sessionScopeKey(scopeToken, rawSessionId);
|
|
27058
27113
|
if (tokenResult.ok) {
|
|
27059
27114
|
run4.beacon = {
|
|
@@ -27086,12 +27141,12 @@ function parseKnowledgeNote(raw) {
|
|
|
27086
27141
|
if (!raw || typeof raw !== "object") return null;
|
|
27087
27142
|
const o = raw;
|
|
27088
27143
|
const node_id = typeof o.node_id === "string" ? o.node_id.trim() : "";
|
|
27089
|
-
const
|
|
27090
|
-
if (!node_id || !
|
|
27091
|
-
if (
|
|
27144
|
+
const text2 = typeof o.text === "string" ? o.text.trim() : "";
|
|
27145
|
+
if (!node_id || !text2) return null;
|
|
27146
|
+
if (text2.length > 1e3) return null;
|
|
27092
27147
|
return {
|
|
27093
27148
|
node_id,
|
|
27094
|
-
text,
|
|
27149
|
+
text: text2,
|
|
27095
27150
|
file: typeof o.file === "string" && o.file ? o.file : null,
|
|
27096
27151
|
line: typeof o.line === "number" && Number.isFinite(o.line) && o.line > 0 ? Math.floor(o.line) : null
|
|
27097
27152
|
};
|
|
@@ -27129,10 +27184,10 @@ function episodeForWire(e, humanSpoke) {
|
|
|
27129
27184
|
var MAX_AGENT_CONTEXT_CHARS = 1500;
|
|
27130
27185
|
var MAX_AGENT_ITEMS = 5;
|
|
27131
27186
|
var REPORT_PREFIX = "Verity review (a report on the code just written \u2014 relay what matters to the user; it is not an instruction to you):";
|
|
27132
|
-
function renderItem(label2,
|
|
27187
|
+
function renderItem(label2, text2, patternId, file, line2) {
|
|
27133
27188
|
const where2 = file ? ` (${file}${line2 !== void 0 && line2 !== "" ? `:${line2}` : ""})` : "";
|
|
27134
27189
|
const id = patternId ? ` [${patternId}]` : "";
|
|
27135
|
-
return `- ${label2}${
|
|
27190
|
+
return `- ${label2}${text2}${where2}${id}`;
|
|
27136
27191
|
}
|
|
27137
27192
|
function channelInputFrom(response, intentRepeat = 0, priorPendingFingerprints = []) {
|
|
27138
27193
|
const metadata2 = response.metadata ?? {};
|
|
@@ -27214,11 +27269,11 @@ function buildAgentContext(input) {
|
|
|
27214
27269
|
for (const p of input.pendingItems ?? []) {
|
|
27215
27270
|
if (lines.length >= MAX_AGENT_ITEMS) break;
|
|
27216
27271
|
if (p.pattern_id === "intent-misalignment") continue;
|
|
27217
|
-
const
|
|
27218
|
-
if (!
|
|
27219
|
-
const seenBefore = isRepeatOfAny(
|
|
27272
|
+
const text2 = p.description ?? p.title ?? p.reason;
|
|
27273
|
+
if (!text2) continue;
|
|
27274
|
+
const seenBefore = isRepeatOfAny(text2, input.priorPendingFingerprints ?? []);
|
|
27220
27275
|
lines.push(
|
|
27221
|
-
renderItem("",
|
|
27276
|
+
renderItem("", text2, p.pattern_id, p.file, p.line) + (seenBefore ? "\n (raised earlier this session and still open \u2014 do not re-explain it; act on it or carry on)" : "")
|
|
27222
27277
|
);
|
|
27223
27278
|
}
|
|
27224
27279
|
if (lines.length === 0) return null;
|
|
@@ -27226,11 +27281,11 @@ function buildAgentContext(input) {
|
|
|
27226
27281
|
${lines.slice(0, MAX_AGENT_ITEMS).join("\n")}`;
|
|
27227
27282
|
return truncateToCap(body2);
|
|
27228
27283
|
}
|
|
27229
|
-
function truncateToCap(
|
|
27230
|
-
if (
|
|
27284
|
+
function truncateToCap(text2) {
|
|
27285
|
+
if (text2.length <= MAX_AGENT_CONTEXT_CHARS) return text2;
|
|
27231
27286
|
const marker = "\n- (truncated)";
|
|
27232
27287
|
const budget = MAX_AGENT_CONTEXT_CHARS - marker.length;
|
|
27233
|
-
const lines =
|
|
27288
|
+
const lines = text2.slice(0, budget).split("\n");
|
|
27234
27289
|
lines.pop();
|
|
27235
27290
|
return `${lines.join("\n")}${marker}`;
|
|
27236
27291
|
}
|
|
@@ -27258,7 +27313,7 @@ function channelSilence(input) {
|
|
|
27258
27313
|
// src/lib/cli-version.ts
|
|
27259
27314
|
function cliVersion() {
|
|
27260
27315
|
try {
|
|
27261
|
-
return true ? "0.34.
|
|
27316
|
+
return true ? "0.34.2-experimental.2cad220" : "dev";
|
|
27262
27317
|
} catch {
|
|
27263
27318
|
return "dev";
|
|
27264
27319
|
}
|
|
@@ -28059,7 +28114,7 @@ async function connect(run4) {
|
|
|
28059
28114
|
async function mode(run4) {
|
|
28060
28115
|
const { opts, globals } = run4;
|
|
28061
28116
|
const { actionSummary, allForReview, assistantResponse, baseline, conversation, memory: memory2, noFilesChanged, serviceUrl, sessionId, token, turnAuthoredCode } = run4;
|
|
28062
|
-
const sessionIdForMemory = sessionId ||
|
|
28117
|
+
const sessionIdForMemory = sessionId || envSessionId() || "";
|
|
28063
28118
|
let predictedMode;
|
|
28064
28119
|
try {
|
|
28065
28120
|
const memoryPath2 = sessionIdForMemory ? `/memory?session_id=${encodeURIComponent(sessionIdForMemory)}` : "/memory";
|
|
@@ -29434,8 +29489,8 @@ function argResource(kind2, arg) {
|
|
|
29434
29489
|
const keyed = keyedCall(arg.text);
|
|
29435
29490
|
return keyed ? { kind: kind2, name: keyed, confidence: "expression" } : { kind: kind2, name: null, confidence: "unknown" };
|
|
29436
29491
|
}
|
|
29437
|
-
function keyedCall(
|
|
29438
|
-
const t =
|
|
29492
|
+
function keyedCall(text2) {
|
|
29493
|
+
const t = text2.trim();
|
|
29439
29494
|
const open = t.indexOf("(");
|
|
29440
29495
|
if (open <= 0 || !t.endsWith(")")) return null;
|
|
29441
29496
|
const callee = t.slice(0, open);
|
|
@@ -29469,16 +29524,16 @@ var SQL_TABLE = [
|
|
|
29469
29524
|
[/\bfrom\s+[`"[]?([\w.]+)/i, "read"]
|
|
29470
29525
|
];
|
|
29471
29526
|
function sqlLiteral(c) {
|
|
29472
|
-
const
|
|
29473
|
-
if (!
|
|
29527
|
+
const text2 = c.args.find((a) => a.literal !== null && SQL.test(a.literal))?.literal;
|
|
29528
|
+
if (!text2) return null;
|
|
29474
29529
|
for (const [re, op] of SQL_TABLE) {
|
|
29475
|
-
const m = re.exec(
|
|
29530
|
+
const m = re.exec(text2);
|
|
29476
29531
|
if (m) {
|
|
29477
29532
|
const name2 = m[1].split(".").pop();
|
|
29478
|
-
return { op, resource: table(name2), rule: "sql.literal", lock: op === "read" && /\bfor\s+(?:no\s+key\s+)?update\b/i.test(
|
|
29533
|
+
return { op, resource: table(name2), rule: "sql.literal", lock: op === "read" && /\bfor\s+(?:no\s+key\s+)?update\b/i.test(text2) };
|
|
29479
29534
|
}
|
|
29480
29535
|
}
|
|
29481
|
-
return { op: /^\s*select\b/i.test(
|
|
29536
|
+
return { op: /^\s*select\b/i.test(text2) ? "read" : "write", resource: { kind: "table", name: null, confidence: "unknown" }, rule: "sql.literal" };
|
|
29482
29537
|
}
|
|
29483
29538
|
var SB_WRITE = /* @__PURE__ */ new Set(["insert", "update", "upsert", "delete"]);
|
|
29484
29539
|
var SB_FROM = /\bfrom\(\s*(['"`])([\w.-]+)\1\s*\)\s*$/;
|
|
@@ -29874,28 +29929,28 @@ var ALIAS_OF = "alias-of:";
|
|
|
29874
29929
|
var FIELD_OF = "field-of:";
|
|
29875
29930
|
var IDENT_CHAR = /[\w$]/;
|
|
29876
29931
|
var isIdent = (s) => /^[A-Za-z_$][\w$]*$/.test(s);
|
|
29877
|
-
function wordAt(
|
|
29932
|
+
function wordAt(text2, word) {
|
|
29878
29933
|
const out2 = [];
|
|
29879
|
-
for (let i2 =
|
|
29880
|
-
if (IDENT_CHAR.test(
|
|
29934
|
+
for (let i2 = text2.indexOf(word); i2 >= 0; i2 = text2.indexOf(word, i2 + 1)) {
|
|
29935
|
+
if (IDENT_CHAR.test(text2[i2 - 1] ?? "") || IDENT_CHAR.test(text2[i2 + word.length] ?? "")) continue;
|
|
29881
29936
|
out2.push(i2);
|
|
29882
29937
|
}
|
|
29883
29938
|
return out2;
|
|
29884
29939
|
}
|
|
29885
29940
|
var GO_NOT_TYPES = /* @__PURE__ */ new Set(["int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64", "complex64", "complex128", "string", "bool", "byte", "rune", "error", "any", "func", "chan", "map", "struct", "interface", "range", "make", "new", "nil", "true", "false"]);
|
|
29886
|
-
function typeAt(
|
|
29941
|
+
function typeAt(text2, i2, lang) {
|
|
29887
29942
|
let j = i2;
|
|
29888
29943
|
const skip = () => {
|
|
29889
|
-
while (j <
|
|
29944
|
+
while (j < text2.length && /[\s?*&]/.test(text2[j])) j++;
|
|
29890
29945
|
};
|
|
29891
29946
|
skip();
|
|
29892
|
-
for (const kw of ["new ", "readonly ", "await "]) if (
|
|
29947
|
+
for (const kw of ["new ", "readonly ", "await "]) if (text2.startsWith(kw, j)) {
|
|
29893
29948
|
j += kw.length;
|
|
29894
29949
|
skip();
|
|
29895
29950
|
}
|
|
29896
29951
|
let k = j;
|
|
29897
|
-
while (k <
|
|
29898
|
-
const name2 =
|
|
29952
|
+
while (k < text2.length && /[\w$.]/.test(text2[k])) k++;
|
|
29953
|
+
const name2 = text2.slice(j, k).split(".").pop() ?? "";
|
|
29899
29954
|
if (lang === "go") return /^[A-Za-z_]\w*$/.test(name2) && !GO_NOT_TYPES.has(name2) ? name2 : null;
|
|
29900
29955
|
return /^[A-Z][\w$]*$/.test(name2) ? name2 : null;
|
|
29901
29956
|
}
|
|
@@ -30045,10 +30100,10 @@ function boundInGo(fnText, name2) {
|
|
|
30045
30100
|
const brace = fnText.indexOf("{");
|
|
30046
30101
|
return wordAt(brace < 0 ? fnText : fnText.slice(0, brace), name2).length > 0;
|
|
30047
30102
|
}
|
|
30048
|
-
function rebindsInGo(
|
|
30049
|
-
for (const i2 of wordAt(
|
|
30050
|
-
const lineEnd =
|
|
30051
|
-
const rest =
|
|
30103
|
+
function rebindsInGo(text2, name2) {
|
|
30104
|
+
for (const i2 of wordAt(text2, name2)) {
|
|
30105
|
+
const lineEnd = text2.indexOf("\n", i2);
|
|
30106
|
+
const rest = text2.slice(i2 + name2.length, lineEnd < 0 ? void 0 : lineEnd);
|
|
30052
30107
|
const decl = rest.indexOf(":=");
|
|
30053
30108
|
if (decl >= 0 && /^[\s\w,]*$/.test(rest.slice(0, decl))) return true;
|
|
30054
30109
|
}
|
|
@@ -30274,15 +30329,15 @@ function importOf(content, lang, name2, receiver) {
|
|
|
30274
30329
|
return null;
|
|
30275
30330
|
}
|
|
30276
30331
|
var TS_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
|
|
30277
|
-
function parseJsonc(
|
|
30332
|
+
function parseJsonc(text2) {
|
|
30278
30333
|
let out2 = "";
|
|
30279
30334
|
let inString = false;
|
|
30280
|
-
for (let i2 = 0; i2 <
|
|
30281
|
-
const c =
|
|
30335
|
+
for (let i2 = 0; i2 < text2.length; i2++) {
|
|
30336
|
+
const c = text2[i2];
|
|
30282
30337
|
if (inString) {
|
|
30283
30338
|
out2 += c;
|
|
30284
30339
|
if (c === "\\") {
|
|
30285
|
-
out2 +=
|
|
30340
|
+
out2 += text2[++i2] ?? "";
|
|
30286
30341
|
continue;
|
|
30287
30342
|
}
|
|
30288
30343
|
if (c === '"') inString = false;
|
|
@@ -30293,14 +30348,14 @@ function parseJsonc(text) {
|
|
|
30293
30348
|
out2 += c;
|
|
30294
30349
|
continue;
|
|
30295
30350
|
}
|
|
30296
|
-
if (c === "/" &&
|
|
30297
|
-
while (i2 <
|
|
30351
|
+
if (c === "/" && text2[i2 + 1] === "/") {
|
|
30352
|
+
while (i2 < text2.length && text2[i2] !== "\n") i2++;
|
|
30298
30353
|
out2 += "\n";
|
|
30299
30354
|
continue;
|
|
30300
30355
|
}
|
|
30301
|
-
if (c === "/" &&
|
|
30356
|
+
if (c === "/" && text2[i2 + 1] === "*") {
|
|
30302
30357
|
i2 += 2;
|
|
30303
|
-
while (i2 <
|
|
30358
|
+
while (i2 < text2.length && !(text2[i2] === "*" && text2[i2 + 1] === "/")) i2++;
|
|
30304
30359
|
i2++;
|
|
30305
30360
|
continue;
|
|
30306
30361
|
}
|
|
@@ -30509,36 +30564,36 @@ function definitionOf(input) {
|
|
|
30509
30564
|
}
|
|
30510
30565
|
var MAX_CALLER_SCAN_FILES = 60;
|
|
30511
30566
|
var isWordChar2 = (c) => c !== void 0 && /[\w$]/.test(c);
|
|
30512
|
-
function callStarts(
|
|
30567
|
+
function callStarts(text2, name2) {
|
|
30513
30568
|
const out2 = [];
|
|
30514
|
-
for (let i2 =
|
|
30569
|
+
for (let i2 = text2.indexOf(name2); i2 >= 0; i2 = text2.indexOf(name2, i2 + 1)) {
|
|
30515
30570
|
let j = i2 + name2.length;
|
|
30516
|
-
if (
|
|
30571
|
+
if (text2[j] === "<") {
|
|
30517
30572
|
let depth = 0;
|
|
30518
|
-
for (; j <
|
|
30519
|
-
if (
|
|
30520
|
-
else if (
|
|
30573
|
+
for (; j < text2.length; j++) {
|
|
30574
|
+
if (text2[j] === "<") depth++;
|
|
30575
|
+
else if (text2[j] === ">" && --depth === 0) break;
|
|
30521
30576
|
}
|
|
30522
30577
|
j++;
|
|
30523
30578
|
}
|
|
30524
|
-
if (
|
|
30579
|
+
if (text2[j] === "(") out2.push({ index: i2, open: j });
|
|
30525
30580
|
}
|
|
30526
30581
|
return out2;
|
|
30527
30582
|
}
|
|
30528
|
-
function callsName(
|
|
30529
|
-
const t =
|
|
30583
|
+
function callsName(text2, name2) {
|
|
30584
|
+
const t = text2.trim();
|
|
30530
30585
|
if (t.startsWith("//") || t.startsWith("*") || t.startsWith("/*") || t.startsWith("#")) return false;
|
|
30531
|
-
for (const at of callStarts(
|
|
30586
|
+
for (const at of callStarts(text2, name2)) {
|
|
30532
30587
|
const i2 = at.index;
|
|
30533
|
-
const spread =
|
|
30534
|
-
if (isWordChar2(
|
|
30588
|
+
const spread = text2.slice(Math.max(0, i2 - 3), i2) === "...";
|
|
30589
|
+
if (isWordChar2(text2[i2 - 1]) || text2[i2 - 1] === "." && !spread) continue;
|
|
30535
30590
|
let depth = 0;
|
|
30536
30591
|
let j = at.open;
|
|
30537
|
-
for (; j <
|
|
30538
|
-
if (
|
|
30539
|
-
else if (
|
|
30592
|
+
for (; j < text2.length; j++) {
|
|
30593
|
+
if (text2[j] === "(") depth++;
|
|
30594
|
+
else if (text2[j] === ")" && --depth === 0) break;
|
|
30540
30595
|
}
|
|
30541
|
-
const after =
|
|
30596
|
+
const after = text2.slice(j + 1).trimStart();
|
|
30542
30597
|
if (after.startsWith(":") || after.startsWith("{")) continue;
|
|
30543
30598
|
return true;
|
|
30544
30599
|
}
|
|
@@ -30628,11 +30683,11 @@ function callersOf(input) {
|
|
|
30628
30683
|
if (seen.has(line2) || declared.has(line2)) continue;
|
|
30629
30684
|
const inside2 = r.value.some((f) => f.start.line <= line2 && line2 <= f.end.line && f.calls.some((c) => c.line === line2 && c.name === name2));
|
|
30630
30685
|
if (inside2) continue;
|
|
30631
|
-
const
|
|
30632
|
-
if (!callsName(
|
|
30686
|
+
const text2 = lines[line2 - 1] ?? "";
|
|
30687
|
+
if (!callsName(text2, name2) || /^\s*(?:export\s+)?(?:async\s+)?(?:function|def|func)\b/.test(text2)) continue;
|
|
30633
30688
|
const enclosing = r.value.filter((f) => f.start.line <= line2 && line2 <= f.end.line).sort((a, b) => a.end.line - a.start.line - (b.end.line - b.start.line))[0];
|
|
30634
30689
|
seen.add(line2);
|
|
30635
|
-
callers.push({ path: p, caller: enclosing ? enclosing.qualified : null, line: line2, text:
|
|
30690
|
+
callers.push({ path: p, caller: enclosing ? enclosing.qualified : null, line: line2, text: text2.trim().slice(0, 200), provenance: fileTie });
|
|
30636
30691
|
}
|
|
30637
30692
|
}
|
|
30638
30693
|
}
|
|
@@ -30939,16 +30994,16 @@ ${m.accessors.map((x) => ` ${x.fn.path}:${x.fn.start.line} ${x.fn.qualified} \u
|
|
|
30939
30994
|
return { ok: true, value: lines.join("\n") };
|
|
30940
30995
|
};
|
|
30941
30996
|
var KINDS = ["table", "cache", "file", "http", "queue", "service", "memory"];
|
|
30942
|
-
function parseResource(
|
|
30943
|
-
const colon =
|
|
30944
|
-
const kind2 = colon > 0 ?
|
|
30945
|
-
if (KINDS.includes(kind2)) return { kinds: [kind2], name:
|
|
30946
|
-
return { kinds: KINDS, name:
|
|
30997
|
+
function parseResource(text2) {
|
|
30998
|
+
const colon = text2.indexOf(":");
|
|
30999
|
+
const kind2 = colon > 0 ? text2.slice(0, colon) : "";
|
|
31000
|
+
if (KINDS.includes(kind2)) return { kinds: [kind2], name: text2.slice(colon + 1) };
|
|
31001
|
+
return { kinds: KINDS, name: text2 };
|
|
30947
31002
|
}
|
|
30948
31003
|
var writersOfTool = async (ctx, args2) => {
|
|
30949
|
-
const
|
|
30950
|
-
if (!
|
|
30951
|
-
const { kinds, name: name2 } = parseResource(
|
|
31004
|
+
const text2 = str(args2.resource, 300, "resource");
|
|
31005
|
+
if (!text2.ok) return text2;
|
|
31006
|
+
const { kinds, name: name2 } = parseResource(text2.value);
|
|
30952
31007
|
if (name2.length < 2) return { ok: false, error: "resource name too short to search for" };
|
|
30953
31008
|
const deadline = Date.now() + TOOL_MS;
|
|
30954
31009
|
const src = source(ctx);
|
|
@@ -30987,7 +31042,7 @@ var writersOfTool = async (ctx, args2) => {
|
|
|
30987
31042
|
if (files.size > 25) truncated = true;
|
|
30988
31043
|
const list2 = (xs) => xs.length ? xs.slice(0, MAX_LIST).map((x) => ` ${x}`).join("\n") + (xs.length > MAX_LIST ? `
|
|
30989
31044
|
\u2026 ${xs.length - MAX_LIST} more` : "") : " none found";
|
|
30990
|
-
return { ok: true, value: `${
|
|
31045
|
+
return { ok: true, value: `${text2.value} (${where(ctx)}), heuristic${truncated ? ", search cut short" : ""}
|
|
30991
31046
|
writers:
|
|
30992
31047
|
${list2(writers)}
|
|
30993
31048
|
readers:
|
|
@@ -31045,9 +31100,9 @@ function validateRepoPath(value, { allowRoot = false } = {}) {
|
|
|
31045
31100
|
function lineNumber(value, fallback) {
|
|
31046
31101
|
return typeof value === "number" && Number.isInteger(value) && value >= 1 ? value : fallback;
|
|
31047
31102
|
}
|
|
31048
|
-
function capOutput(
|
|
31049
|
-
return
|
|
31050
|
-
[truncated at ${TOOL_LIMITS.outputChars} characters]` :
|
|
31103
|
+
function capOutput(text2) {
|
|
31104
|
+
return text2.length > TOOL_LIMITS.outputChars ? `${text2.slice(0, TOOL_LIMITS.outputChars)}
|
|
31105
|
+
[truncated at ${TOOL_LIMITS.outputChars} characters]` : text2;
|
|
31051
31106
|
}
|
|
31052
31107
|
function git(ctx, args2, opts = {}) {
|
|
31053
31108
|
return runGit(ctx.root, args2, { timeoutMs: opts.timeoutMs ?? TOOL_LIMITS.gitTimeoutMs, maxBuffer: opts.maxBuffer ?? TOOL_LIMITS.fileBytes });
|
|
@@ -31181,8 +31236,8 @@ var listFilesTool = async (ctx, args2) => {
|
|
|
31181
31236
|
\u2026 ${more} more` : ""}` : "no matching files" };
|
|
31182
31237
|
};
|
|
31183
31238
|
var searchTool = async (ctx, args2) => {
|
|
31184
|
-
const
|
|
31185
|
-
if (typeof
|
|
31239
|
+
const text2 = args2.text;
|
|
31240
|
+
if (typeof text2 !== "string" || text2.length === 0 || text2.length > TOOL_LIMITS.textChars || /[\n\r]/.test(text2)) {
|
|
31186
31241
|
return { ok: false, error: `text must be 1-${TOOL_LIMITS.textChars} characters on one line` };
|
|
31187
31242
|
}
|
|
31188
31243
|
const glob = typeof args2.path_glob === "string" && args2.path_glob.length > 0 ? args2.path_glob : null;
|
|
@@ -31191,7 +31246,7 @@ var searchTool = async (ctx, args2) => {
|
|
|
31191
31246
|
}
|
|
31192
31247
|
const pathspec = glob ? [`:(glob)${glob}`] : [];
|
|
31193
31248
|
const revision = ctx.range.kind === "push" ? [ctx.range.head] : ["--cached"];
|
|
31194
|
-
const res = await git(ctx, ["grep", "-n", "-I", "-F", "--no-color", ...revision.filter((r) => r === "--cached"), "-e",
|
|
31249
|
+
const res = await git(ctx, ["grep", "-n", "-I", "-F", "--no-color", ...revision.filter((r) => r === "--cached"), "-e", text2, ...revision.filter((r) => r !== "--cached"), "--", ...pathspec]);
|
|
31195
31250
|
if (!res.ok) {
|
|
31196
31251
|
if (res.error === "failed" && res.stderr.trim() === "") return { ok: true, value: "no matches" };
|
|
31197
31252
|
return { ok: false, error: gitFailure(res, "search") };
|
|
@@ -31325,10 +31380,10 @@ function writerExcerpts(codeMap, writers, read2, maxLines, maxChars, budget) {
|
|
|
31325
31380
|
if (content === null) continue;
|
|
31326
31381
|
const win = functionWindow(codeMap, w.file, content, w.line, maxLines);
|
|
31327
31382
|
if (!win) continue;
|
|
31328
|
-
const
|
|
31329
|
-
if (used +
|
|
31330
|
-
used +=
|
|
31331
|
-
out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text });
|
|
31383
|
+
const text2 = content.split("\n").slice(win.start_line - 1, win.end_line).join("\n").slice(0, maxChars);
|
|
31384
|
+
if (used + text2.length > budget) break;
|
|
31385
|
+
used += text2.length;
|
|
31386
|
+
out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text: text2 });
|
|
31332
31387
|
}
|
|
31333
31388
|
return out2;
|
|
31334
31389
|
}
|
|
@@ -31952,7 +32007,7 @@ async function workingMemory(run4) {
|
|
|
31952
32007
|
const { opts } = run4;
|
|
31953
32008
|
const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run4;
|
|
31954
32009
|
let { reachability } = run4;
|
|
31955
|
-
const memorySession = sessionDossier(token, sessionId ??
|
|
32010
|
+
const memorySession = sessionDossier(token, sessionId ?? envSessionId() ?? null);
|
|
31956
32011
|
let memory2 = null;
|
|
31957
32012
|
let incrementReport = null;
|
|
31958
32013
|
if (memorySession) {
|
|
@@ -32225,7 +32280,7 @@ async function buildRequest(run4) {
|
|
|
32225
32280
|
context: {
|
|
32226
32281
|
agent_model: process.env.CLAUDE_MODEL ?? "unknown",
|
|
32227
32282
|
agent_harness: "claude-code",
|
|
32228
|
-
session_id: sessionId ||
|
|
32283
|
+
session_id: sessionId || envSessionId() || "unknown",
|
|
32229
32284
|
iteration,
|
|
32230
32285
|
// Makes fleet composition falsifiable — without it, no adoption-gated
|
|
32231
32286
|
// rollout decision can be checked against anything.
|
|
@@ -33522,12 +33577,12 @@ function registerBaselineCommands(program2) {
|
|
|
33522
33577
|
if (!process.stdin.isTTY) {
|
|
33523
33578
|
const input = (await readStdin()).trim();
|
|
33524
33579
|
if (input) {
|
|
33525
|
-
const event =
|
|
33580
|
+
const event = parseHookEvent2(input);
|
|
33526
33581
|
if (opts.sessionId === void 0) sessionId = event.sessionId;
|
|
33527
33582
|
if (opts.source === void 0) source2 = event.source;
|
|
33528
33583
|
}
|
|
33529
33584
|
}
|
|
33530
|
-
const session = sessionId ?? validSessionId(
|
|
33585
|
+
const session = sessionId ?? validSessionId(envSessionId());
|
|
33531
33586
|
const cli = pluginCliInvocation();
|
|
33532
33587
|
const skew = cliVersionSkew();
|
|
33533
33588
|
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";
|
|
@@ -33647,7 +33702,7 @@ function registerBaselineCommands(program2) {
|
|
|
33647
33702
|
process.exit(0);
|
|
33648
33703
|
});
|
|
33649
33704
|
}
|
|
33650
|
-
var
|
|
33705
|
+
var MAX_HOOK_EVENT_BYTES2 = 64 * 1024;
|
|
33651
33706
|
var HOOK_SOURCES = /* @__PURE__ */ new Set(["startup", "resume", "clear", "compact"]);
|
|
33652
33707
|
var SESSION_ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
33653
33708
|
async function readStdin() {
|
|
@@ -33655,11 +33710,11 @@ async function readStdin() {
|
|
|
33655
33710
|
let size = 0;
|
|
33656
33711
|
for await (const chunk of process.stdin) {
|
|
33657
33712
|
size += chunk.length;
|
|
33658
|
-
if (size <=
|
|
33713
|
+
if (size <= MAX_HOOK_EVENT_BYTES2) chunks.push(chunk);
|
|
33659
33714
|
}
|
|
33660
|
-
return size >
|
|
33715
|
+
return size > MAX_HOOK_EVENT_BYTES2 ? "" : Buffer.concat(chunks).toString("utf-8");
|
|
33661
33716
|
}
|
|
33662
|
-
function
|
|
33717
|
+
function parseHookEvent2(input) {
|
|
33663
33718
|
let event;
|
|
33664
33719
|
try {
|
|
33665
33720
|
event = JSON.parse(input);
|
|
@@ -33680,6 +33735,34 @@ function hookSource(value) {
|
|
|
33680
33735
|
|
|
33681
33736
|
// src/commands/review.ts
|
|
33682
33737
|
var import_node_fs57 = require("node:fs");
|
|
33738
|
+
var import_node_path44 = require("node:path");
|
|
33739
|
+
function containReviewPaths(paths, base) {
|
|
33740
|
+
const kept = [];
|
|
33741
|
+
const refused2 = [];
|
|
33742
|
+
for (const raw of paths) {
|
|
33743
|
+
const candidate = (0, import_node_path44.isAbsolute)(raw) ? relativeForm(base, raw) : raw;
|
|
33744
|
+
if (candidate === "" || resolveInside(base, candidate) === null) refused2.push(raw);
|
|
33745
|
+
else kept.push(candidate);
|
|
33746
|
+
}
|
|
33747
|
+
return { kept, refused: refused2 };
|
|
33748
|
+
}
|
|
33749
|
+
function relativeForm(base, abs) {
|
|
33750
|
+
const lexical = (0, import_node_path44.relative)(base, abs);
|
|
33751
|
+
if (!(lexical === ".." || lexical.startsWith(`..${import_node_path44.sep}`) || (0, import_node_path44.isAbsolute)(lexical))) return lexical;
|
|
33752
|
+
try {
|
|
33753
|
+
let dir = (0, import_node_path44.dirname)(abs);
|
|
33754
|
+
let rest = (0, import_node_path44.basename)(abs);
|
|
33755
|
+
while (!(0, import_node_fs57.existsSync)(dir)) {
|
|
33756
|
+
const up = (0, import_node_path44.dirname)(dir);
|
|
33757
|
+
if (up === dir) return lexical;
|
|
33758
|
+
rest = (0, import_node_path44.join)((0, import_node_path44.basename)(dir), rest);
|
|
33759
|
+
dir = up;
|
|
33760
|
+
}
|
|
33761
|
+
return (0, import_node_path44.relative)((0, import_node_fs57.realpathSync)(base), (0, import_node_path44.join)((0, import_node_fs57.realpathSync)(dir), rest));
|
|
33762
|
+
} catch {
|
|
33763
|
+
return lexical;
|
|
33764
|
+
}
|
|
33765
|
+
}
|
|
33683
33766
|
function registerReviewCommand(program2) {
|
|
33684
33767
|
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) => {
|
|
33685
33768
|
const globals = program2.opts();
|
|
@@ -33698,8 +33781,20 @@ function registerReviewCommand(program2) {
|
|
|
33698
33781
|
});
|
|
33699
33782
|
}
|
|
33700
33783
|
async function runReview(opts, globals) {
|
|
33701
|
-
const
|
|
33702
|
-
const
|
|
33784
|
+
const base = process.cwd();
|
|
33785
|
+
const files = containReviewPaths(opts.files.split(",").map((f) => f.trim()).filter(Boolean), base);
|
|
33786
|
+
const changed = opts.changed ? containReviewPaths(opts.changed.split(",").map((f) => f.trim()).filter(Boolean), base) : files;
|
|
33787
|
+
const refused2 = Array.from(/* @__PURE__ */ new Set([...files.refused, ...changed.refused]));
|
|
33788
|
+
if (refused2.length > 0) {
|
|
33789
|
+
printJsonCompact({
|
|
33790
|
+
gate_decision: "WARN",
|
|
33791
|
+
systemMessage: `Verity: refused ${refused2.length} path(s) outside this repository \u2014 nothing was reviewed. Pass paths inside the repository you run \`verity review\` from.`,
|
|
33792
|
+
refused_paths: refused2
|
|
33793
|
+
});
|
|
33794
|
+
process.exit(0);
|
|
33795
|
+
}
|
|
33796
|
+
const allFiles = files.kept;
|
|
33797
|
+
const changedFiles = changed.kept;
|
|
33703
33798
|
const analyzable = filterAnalyzable(allFiles);
|
|
33704
33799
|
const securityFiles = filterSecurity(allFiles);
|
|
33705
33800
|
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs57.existsSync)(f) || resolveFile(f) !== null);
|
|
@@ -33727,7 +33822,7 @@ async function runReview(opts, globals) {
|
|
|
33727
33822
|
context: {
|
|
33728
33823
|
agent_model: process.env.CLAUDE_MODEL ?? "unknown",
|
|
33729
33824
|
agent_harness: "claude-code",
|
|
33730
|
-
session_id:
|
|
33825
|
+
session_id: envSessionId() ?? "unknown",
|
|
33731
33826
|
trigger: "review",
|
|
33732
33827
|
iteration: 1
|
|
33733
33828
|
}
|
|
@@ -33768,12 +33863,12 @@ async function runReview(opts, globals) {
|
|
|
33768
33863
|
}
|
|
33769
33864
|
|
|
33770
33865
|
// src/commands/guard.ts
|
|
33771
|
-
var
|
|
33772
|
-
var
|
|
33866
|
+
var import_node_fs63 = require("node:fs");
|
|
33867
|
+
var import_node_path51 = require("node:path");
|
|
33773
33868
|
|
|
33774
33869
|
// src/lib/vendored.ts
|
|
33775
33870
|
var import_node_fs58 = require("node:fs");
|
|
33776
|
-
var
|
|
33871
|
+
var import_node_path45 = require("node:path");
|
|
33777
33872
|
var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
|
|
33778
33873
|
function dataDirOrNull() {
|
|
33779
33874
|
try {
|
|
@@ -33788,7 +33883,7 @@ function shippedSkillFile(path, dataDir = dataDirOrNull()) {
|
|
|
33788
33883
|
const [, skill, rel] = m;
|
|
33789
33884
|
if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
|
|
33790
33885
|
try {
|
|
33791
|
-
return (0, import_node_fs58.readFileSync)((0,
|
|
33886
|
+
return (0, import_node_fs58.readFileSync)((0, import_node_path45.join)(dataDir, "skills", skill, rel), "utf8");
|
|
33792
33887
|
} catch {
|
|
33793
33888
|
return null;
|
|
33794
33889
|
}
|
|
@@ -33897,8 +33992,33 @@ async function runAgentReview(options) {
|
|
|
33897
33992
|
return { kind: "finished", response: finished.data };
|
|
33898
33993
|
}
|
|
33899
33994
|
|
|
33995
|
+
// src/lib/effort.ts
|
|
33996
|
+
var import_node_fs59 = require("node:fs");
|
|
33997
|
+
var import_node_path46 = require("node:path");
|
|
33998
|
+
var import_yaml5 = __toESM2(require_dist());
|
|
33999
|
+
var EFFORT_PROFILES = {
|
|
34000
|
+
default: { pushDeadlineMs: 18e4, formal: { tier: "fast", maxRounds: 2, minScore: 0.7, costCapUsd: 1, maxTargets: 1, relaxedGates: false, dailyModels: 5, dailyCostUsd: 5 } },
|
|
34001
|
+
high: { pushDeadlineMs: 22e4, formal: { tier: "deep", maxRounds: 2, minScore: 0.6, costCapUsd: 2, maxTargets: 2, relaxedGates: false, dailyModels: 15, dailyCostUsd: 15 } },
|
|
34002
|
+
max: { pushDeadlineMs: 27e4, formal: { tier: "deep", maxRounds: 3, minScore: 0.5, costCapUsd: 4, maxTargets: 3, relaxedGates: true, dailyModels: 30, dailyCostUsd: 30 } }
|
|
34003
|
+
};
|
|
34004
|
+
function asEffort(value) {
|
|
34005
|
+
return value === "high" || value === "max" ? value : "default";
|
|
34006
|
+
}
|
|
34007
|
+
function resolveEffort(root, env = process.env) {
|
|
34008
|
+
if (env.VERITY_EFFORT) return asEffort(env.VERITY_EFFORT);
|
|
34009
|
+
try {
|
|
34010
|
+
const standard = (0, import_yaml5.parse)((0, import_node_fs59.readFileSync)((0, import_node_path46.join)(root, STANDARD_FILE), "utf8"));
|
|
34011
|
+
return asEffort(standard?.process_constraints?.git_moment_effort);
|
|
34012
|
+
} catch {
|
|
34013
|
+
return "default";
|
|
34014
|
+
}
|
|
34015
|
+
}
|
|
34016
|
+
function effortProfile(root, env = process.env) {
|
|
34017
|
+
return EFFORT_PROFILES[resolveEffort(root, env)];
|
|
34018
|
+
}
|
|
34019
|
+
|
|
33900
34020
|
// src/lib/prove/auto.ts
|
|
33901
|
-
var
|
|
34021
|
+
var import_node_path50 = require("node:path");
|
|
33902
34022
|
var import_node_crypto19 = require("node:crypto");
|
|
33903
34023
|
|
|
33904
34024
|
// src/lib/prove/signals.ts
|
|
@@ -33961,14 +34081,14 @@ function trackedSourceFiles(root, opts = {}) {
|
|
|
33961
34081
|
return files.slice(0, opts.maxFiles ?? 5e3);
|
|
33962
34082
|
}
|
|
33963
34083
|
var EFFECT_LINE = /\bawait\b|\basync\s+with\b|\.then\(|\bsetTimeout\(|\bsetInterval\(|\bwith\s+\w[\w.]*\.(?:lock|acquire)\b|\bLock\(\)/;
|
|
33964
|
-
function countEffects(
|
|
34084
|
+
function countEffects(text2) {
|
|
33965
34085
|
let n = 0;
|
|
33966
|
-
for (const line2 of
|
|
34086
|
+
for (const line2 of text2.split("\n")) if (EFFECT_LINE.test(line2)) n++;
|
|
33967
34087
|
return n;
|
|
33968
34088
|
}
|
|
33969
|
-
function scanRisk(
|
|
34089
|
+
function scanRisk(text2) {
|
|
33970
34090
|
const counts = Object.fromEntries(RISK_PATTERNS.map(([c]) => [c, 0]));
|
|
33971
|
-
for (const line2 of
|
|
34091
|
+
for (const line2 of text2.split("\n")) {
|
|
33972
34092
|
for (const [category, re] of RISK_PATTERNS) {
|
|
33973
34093
|
if (re.test(line2)) counts[category]++;
|
|
33974
34094
|
}
|
|
@@ -34262,13 +34382,13 @@ var lunaRanker = {
|
|
|
34262
34382
|
signal: controller.signal
|
|
34263
34383
|
});
|
|
34264
34384
|
if (!res.ok) {
|
|
34265
|
-
const
|
|
34266
|
-
return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${
|
|
34385
|
+
const text3 = await res.text().catch(() => "");
|
|
34386
|
+
return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${text3.slice(0, 200)}`, ranked: fallback };
|
|
34267
34387
|
}
|
|
34268
34388
|
const data = await res.json();
|
|
34269
|
-
const
|
|
34270
|
-
if (!
|
|
34271
|
-
const parsed = JSON.parse(
|
|
34389
|
+
const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
|
|
34390
|
+
if (!text2) return { ok: false, ranker: "luna", error: "no output_text in response", ranked: fallback };
|
|
34391
|
+
const parsed = JSON.parse(text2);
|
|
34272
34392
|
const items = parsed.items.map((i2) => {
|
|
34273
34393
|
const legacy = i2.critical === void 0 && i2.hazard === void 0 && i2.error_prone === void 0;
|
|
34274
34394
|
const criteria = legacy ? { critical: Number(i2.score) || 0, hazard: Number(i2.score) || 0, error_prone: Number(i2.score) || 0 } : { critical: Number(i2.critical) || 0, hazard: Number(i2.hazard) || 0, error_prone: Number(i2.error_prone) || 0 };
|
|
@@ -34903,19 +35023,19 @@ var PURE_METHODS2 = /* @__PURE__ */ new Set([
|
|
|
34903
35023
|
"test",
|
|
34904
35024
|
"match"
|
|
34905
35025
|
]);
|
|
34906
|
-
function callsOn(
|
|
35026
|
+
function callsOn(text2, name2) {
|
|
34907
35027
|
const needle = `${name2}.`;
|
|
34908
|
-
for (let i2 =
|
|
34909
|
-
if (i2 > 0 && IDENT_CHAR2.test(
|
|
34910
|
-
const call = CALL_AFTER_DOT.exec(
|
|
35028
|
+
for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
|
|
35029
|
+
if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
|
|
35030
|
+
const call = CALL_AFTER_DOT.exec(text2.slice(i2 + needle.length));
|
|
34911
35031
|
if (call && !PURE_METHODS2.has(call[1])) return true;
|
|
34912
35032
|
}
|
|
34913
35033
|
return false;
|
|
34914
35034
|
}
|
|
34915
|
-
function callsDirect(
|
|
35035
|
+
function callsDirect(text2, name2) {
|
|
34916
35036
|
const needle = `${name2}(`;
|
|
34917
|
-
for (let i2 =
|
|
34918
|
-
if (i2 > 0 && IDENT_CHAR2.test(
|
|
35037
|
+
for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
|
|
35038
|
+
if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
|
|
34919
35039
|
return true;
|
|
34920
35040
|
}
|
|
34921
35041
|
return false;
|
|
@@ -35071,11 +35191,11 @@ async function generateModel(target, opts) {
|
|
|
35071
35191
|
return { ok: false, error: name2 === "TimeoutError" || name2 === "AbortError" ? "timed out" : err2.message };
|
|
35072
35192
|
}
|
|
35073
35193
|
const usage = data.usage ? { inputTokens: Number(data.usage.input_tokens ?? 0), outputTokens: Number(data.usage.output_tokens ?? 0) } : null;
|
|
35074
|
-
const
|
|
35075
|
-
if (!
|
|
35194
|
+
const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
|
|
35195
|
+
if (!text2) return { ok: false, error: "no output_text in response", usage };
|
|
35076
35196
|
let parsed;
|
|
35077
35197
|
try {
|
|
35078
|
-
parsed = JSON.parse(
|
|
35198
|
+
parsed = JSON.parse(text2);
|
|
35079
35199
|
} catch {
|
|
35080
35200
|
return { ok: false, error: "answer was not JSON", usage };
|
|
35081
35201
|
}
|
|
@@ -35085,8 +35205,8 @@ async function generateModel(target, opts) {
|
|
|
35085
35205
|
// src/lib/prove/replay.ts
|
|
35086
35206
|
var MAX_SOURCE_BYTES = 96 * 1024;
|
|
35087
35207
|
var MAX_MODEL_BYTES = 32 * 1024;
|
|
35088
|
-
function numberLines(
|
|
35089
|
-
return
|
|
35208
|
+
function numberLines(text2, from = 1) {
|
|
35209
|
+
return text2.split("\n").map((l, i2) => `${String(i2 + from).padStart(5)}| ${l}`).join("\n");
|
|
35090
35210
|
}
|
|
35091
35211
|
var PY_DECL = /^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(/;
|
|
35092
35212
|
var TS_DECLS = [
|
|
@@ -35160,9 +35280,9 @@ function extractSymbolBody(source2, symbol, file, range) {
|
|
|
35160
35280
|
}
|
|
35161
35281
|
return null;
|
|
35162
35282
|
}
|
|
35163
|
-
function significantLines(
|
|
35283
|
+
function significantLines(text2) {
|
|
35164
35284
|
const out2 = [];
|
|
35165
|
-
for (const raw of
|
|
35285
|
+
for (const raw of text2.split("\n")) {
|
|
35166
35286
|
const l = raw.trim();
|
|
35167
35287
|
if (l.length < 12) continue;
|
|
35168
35288
|
if (/^(\/\/|\/\*|\*|#)/.test(l)) continue;
|
|
@@ -35187,14 +35307,14 @@ function isTrackedInRoot(root, file) {
|
|
|
35187
35307
|
function buildReplayBrief(root, report, property, modelSource, readSource) {
|
|
35188
35308
|
const sources = (report.header?.abstracts ?? []).map((a) => {
|
|
35189
35309
|
const read2 = readSource ? readSource(a.file, MAX_SOURCE_BYTES) : isTrackedInRoot(root, a.file) ? readRegularFileInRoot(root, a.file, MAX_SOURCE_BYTES) : { ok: false, reason: "not tracked by git \u2014 models may only abstract tracked source" };
|
|
35190
|
-
const
|
|
35310
|
+
const text2 = read2.ok ? read2.content : "";
|
|
35191
35311
|
return {
|
|
35192
35312
|
file: a.file,
|
|
35193
35313
|
symbol: a.symbol,
|
|
35194
|
-
numbered:
|
|
35195
|
-
symbolBody:
|
|
35314
|
+
numbered: text2 ? numberLines(text2) : `(could not read ${a.file}: ${read2.ok ? "" : read2.reason})`,
|
|
35315
|
+
symbolBody: text2 ? extractSymbolBody(text2, a.symbol, a.file, a.lines) : null,
|
|
35196
35316
|
lines: a.lines,
|
|
35197
|
-
content:
|
|
35317
|
+
content: text2
|
|
35198
35318
|
};
|
|
35199
35319
|
});
|
|
35200
35320
|
return { model: report.model, property, modelSource: modelSource.slice(0, MAX_MODEL_BYTES), sources };
|
|
@@ -35276,7 +35396,7 @@ function parseReplayOutput(output) {
|
|
|
35276
35396
|
let executedCalls = 0;
|
|
35277
35397
|
const shellTexts = [];
|
|
35278
35398
|
const outputTexts = [];
|
|
35279
|
-
let
|
|
35399
|
+
let text2 = null;
|
|
35280
35400
|
for (const item of output) {
|
|
35281
35401
|
if (item.type === "shell_call") {
|
|
35282
35402
|
shellCalls++;
|
|
@@ -35292,13 +35412,13 @@ function parseReplayOutput(output) {
|
|
|
35292
35412
|
}
|
|
35293
35413
|
} else if (item.type === "message" && Array.isArray(item.content)) {
|
|
35294
35414
|
const t = item.content.find((c) => c.type === "output_text")?.text;
|
|
35295
|
-
if (typeof t === "string")
|
|
35415
|
+
if (typeof t === "string") text2 = t;
|
|
35296
35416
|
}
|
|
35297
35417
|
}
|
|
35298
35418
|
let claim = null;
|
|
35299
|
-
if (
|
|
35419
|
+
if (text2) {
|
|
35300
35420
|
try {
|
|
35301
|
-
const o = JSON.parse(
|
|
35421
|
+
const o = JSON.parse(text2);
|
|
35302
35422
|
const verdict = o.verdict;
|
|
35303
35423
|
if (verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable") {
|
|
35304
35424
|
claim = {
|
|
@@ -35585,9 +35705,9 @@ async function runReplay(brief, opts) {
|
|
|
35585
35705
|
if (opts.auth) return runReplayViaServer(brief, opts.auth, opts.timeoutMs);
|
|
35586
35706
|
const env = opts.env ?? process.env;
|
|
35587
35707
|
const none = { covered: 0, total: 0, ratio: 0, basis: "none" };
|
|
35588
|
-
const
|
|
35589
|
-
if (env.VERITY_PROVE_DIRECT !== "1") return
|
|
35590
|
-
if (!opts.apiKey) return
|
|
35708
|
+
const refuse2 = (error) => ({ claimed: null, verdict: "unverified", reason: "", downgrade: error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: 0, containerId: null, error });
|
|
35709
|
+
if (env.VERITY_PROVE_DIRECT !== "1") return refuse2("not logged in (run `verity login`); replays run on the Verity service");
|
|
35710
|
+
if (!opts.apiKey) return refuse2("OPENAI_API_KEY is not set");
|
|
35591
35711
|
return runReplayInContainer(brief, { apiKey: opts.apiKey, model: opts.model, timeoutMs: opts.timeoutMs, maxRounds: opts.maxRounds, fetchImpl: opts.fetchImpl });
|
|
35592
35712
|
}
|
|
35593
35713
|
function renderReplay(model, property, r) {
|
|
@@ -35625,18 +35745,18 @@ function renderReplay(model, property, r) {
|
|
|
35625
35745
|
// src/lib/prove/runner.ts
|
|
35626
35746
|
var import_node_child_process15 = require("node:child_process");
|
|
35627
35747
|
var import_node_os8 = require("node:os");
|
|
35628
|
-
var
|
|
35748
|
+
var import_node_fs62 = require("node:fs");
|
|
35629
35749
|
var import_node_os9 = require("node:os");
|
|
35630
|
-
var
|
|
35750
|
+
var import_node_path49 = require("node:path");
|
|
35631
35751
|
|
|
35632
35752
|
// src/lib/prove/scaffold.ts
|
|
35633
|
-
var
|
|
35634
|
-
var
|
|
35753
|
+
var import_node_fs61 = require("node:fs");
|
|
35754
|
+
var import_node_path48 = require("node:path");
|
|
35635
35755
|
|
|
35636
35756
|
// src/lib/prove/safe-write.ts
|
|
35637
|
-
var
|
|
35757
|
+
var import_node_fs60 = require("node:fs");
|
|
35638
35758
|
var import_node_crypto15 = require("node:crypto");
|
|
35639
|
-
var
|
|
35759
|
+
var import_node_path47 = require("node:path");
|
|
35640
35760
|
var SafeWriteError = class extends Error {
|
|
35641
35761
|
constructor(reason, path) {
|
|
35642
35762
|
super(`refusing to write ${path}: ${reason}`);
|
|
@@ -35645,10 +35765,10 @@ var SafeWriteError = class extends Error {
|
|
|
35645
35765
|
this.name = "SafeWriteError";
|
|
35646
35766
|
}
|
|
35647
35767
|
};
|
|
35648
|
-
var FLAGS3 =
|
|
35768
|
+
var FLAGS3 = import_node_fs60.constants;
|
|
35649
35769
|
var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
|
|
35650
35770
|
function assertPlainRelative(rel) {
|
|
35651
|
-
if (!rel || (0,
|
|
35771
|
+
if (!rel || (0, import_node_path47.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
|
|
35652
35772
|
for (const part of rel.split(/[\\/]/)) {
|
|
35653
35773
|
if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
|
|
35654
35774
|
}
|
|
@@ -35657,34 +35777,34 @@ function ensureDirsNoFollow(root, rel) {
|
|
|
35657
35777
|
const parts2 = rel.split(/[\\/]/);
|
|
35658
35778
|
let cur = root;
|
|
35659
35779
|
for (const part of parts2.slice(0, -1)) {
|
|
35660
|
-
cur = (0,
|
|
35780
|
+
cur = (0, import_node_path47.join)(cur, part);
|
|
35661
35781
|
let st;
|
|
35662
35782
|
try {
|
|
35663
|
-
st = (0,
|
|
35783
|
+
st = (0, import_node_fs60.lstatSync)(cur);
|
|
35664
35784
|
} catch {
|
|
35665
|
-
(0,
|
|
35785
|
+
(0, import_node_fs60.mkdirSync)(cur);
|
|
35666
35786
|
continue;
|
|
35667
35787
|
}
|
|
35668
35788
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
|
|
35669
35789
|
if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
|
|
35670
35790
|
}
|
|
35671
|
-
return (0,
|
|
35791
|
+
return (0, import_node_path47.join)(root, rel);
|
|
35672
35792
|
}
|
|
35673
35793
|
function insideRoot(realRoot, realPath) {
|
|
35674
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
35794
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path47.sep) ? realRoot : realRoot + import_node_path47.sep);
|
|
35675
35795
|
}
|
|
35676
35796
|
function removeQuietly(path) {
|
|
35677
35797
|
try {
|
|
35678
|
-
(0,
|
|
35798
|
+
(0, import_node_fs60.unlinkSync)(path);
|
|
35679
35799
|
} catch {
|
|
35680
35800
|
}
|
|
35681
35801
|
}
|
|
35682
35802
|
function writeFileInRootNoFollow(root, rel, content) {
|
|
35683
35803
|
assertPlainRelative(rel);
|
|
35684
35804
|
const dest = ensureDirsNoFollow(root, rel);
|
|
35685
|
-
const dir = (0,
|
|
35805
|
+
const dir = (0, import_node_path47.dirname)(dest);
|
|
35686
35806
|
try {
|
|
35687
|
-
const st = (0,
|
|
35807
|
+
const st = (0, import_node_fs60.lstatSync)(dest);
|
|
35688
35808
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
|
|
35689
35809
|
if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
|
|
35690
35810
|
} catch (err2) {
|
|
@@ -35692,41 +35812,41 @@ function writeFileInRootNoFollow(root, rel, content) {
|
|
|
35692
35812
|
}
|
|
35693
35813
|
let realRoot;
|
|
35694
35814
|
try {
|
|
35695
|
-
realRoot = (0,
|
|
35815
|
+
realRoot = (0, import_node_fs60.realpathSync)(root);
|
|
35696
35816
|
} catch {
|
|
35697
35817
|
throw new SafeWriteError("unwritable", root);
|
|
35698
35818
|
}
|
|
35699
|
-
const tmp = (0,
|
|
35819
|
+
const tmp = (0, import_node_path47.join)(dir, `.${(0, import_node_path47.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
|
|
35700
35820
|
let fd;
|
|
35701
35821
|
try {
|
|
35702
|
-
fd = (0,
|
|
35822
|
+
fd = (0, import_node_fs60.openSync)(tmp, import_node_fs60.constants.O_WRONLY | import_node_fs60.constants.O_CREAT | import_node_fs60.constants.O_EXCL | NOFOLLOW2, 420);
|
|
35703
35823
|
} catch {
|
|
35704
35824
|
throw new SafeWriteError("unwritable", tmp);
|
|
35705
35825
|
}
|
|
35706
35826
|
try {
|
|
35707
|
-
const opened = (0,
|
|
35827
|
+
const opened = (0, import_node_fs60.fstatSync)(fd, { bigint: true });
|
|
35708
35828
|
let realTmp;
|
|
35709
35829
|
try {
|
|
35710
|
-
realTmp = (0,
|
|
35830
|
+
realTmp = (0, import_node_fs60.realpathSync)(tmp);
|
|
35711
35831
|
} catch {
|
|
35712
35832
|
throw new SafeWriteError("escaped", tmp);
|
|
35713
35833
|
}
|
|
35714
|
-
const there = (0,
|
|
35834
|
+
const there = (0, import_node_fs60.lstatSync)(realTmp, { bigint: true });
|
|
35715
35835
|
if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
|
|
35716
35836
|
throw new SafeWriteError("escaped", tmp);
|
|
35717
35837
|
}
|
|
35718
35838
|
const buf = Buffer.from(content, "utf-8");
|
|
35719
35839
|
let off = 0;
|
|
35720
|
-
while (off < buf.length) off += (0,
|
|
35840
|
+
while (off < buf.length) off += (0, import_node_fs60.writeSync)(fd, buf, off, buf.length - off);
|
|
35721
35841
|
} catch (err2) {
|
|
35722
|
-
(0,
|
|
35842
|
+
(0, import_node_fs60.closeSync)(fd);
|
|
35723
35843
|
removeQuietly(tmp);
|
|
35724
35844
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
|
|
35725
35845
|
}
|
|
35726
|
-
(0,
|
|
35846
|
+
(0, import_node_fs60.closeSync)(fd);
|
|
35727
35847
|
try {
|
|
35728
|
-
if (!insideRoot(realRoot, (0,
|
|
35729
|
-
(0,
|
|
35848
|
+
if (!insideRoot(realRoot, (0, import_node_fs60.realpathSync)(dir)) || (0, import_node_fs60.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
|
|
35849
|
+
(0, import_node_fs60.renameSync)(tmp, dest);
|
|
35730
35850
|
} catch (err2) {
|
|
35731
35851
|
removeQuietly(tmp);
|
|
35732
35852
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
|
|
@@ -35740,9 +35860,9 @@ function pathHasNoLink(root, rel) {
|
|
|
35740
35860
|
}
|
|
35741
35861
|
let cur = root;
|
|
35742
35862
|
for (const part of rel.split(/[\\/]/)) {
|
|
35743
|
-
cur = cur +
|
|
35863
|
+
cur = cur + import_node_path47.sep + part;
|
|
35744
35864
|
try {
|
|
35745
|
-
if ((0,
|
|
35865
|
+
if ((0, import_node_fs60.lstatSync)(cur).isSymbolicLink()) return false;
|
|
35746
35866
|
} catch {
|
|
35747
35867
|
return true;
|
|
35748
35868
|
}
|
|
@@ -36052,20 +36172,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
|
|
|
36052
36172
|
never committed; what reaches the team is the bug report and the fix.
|
|
36053
36173
|
`;
|
|
36054
36174
|
function scaffoldProofs(root) {
|
|
36055
|
-
const proofsDir = (0,
|
|
36175
|
+
const proofsDir = (0, import_node_path48.join)(root, PROOFS_DIR);
|
|
36056
36176
|
const written = [];
|
|
36057
36177
|
const kept = [];
|
|
36058
36178
|
for (const stray of ["lakefile.lean"]) {
|
|
36059
36179
|
const rel = `${PROOFS_DIR}/${stray}`;
|
|
36060
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36180
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
|
|
36061
36181
|
try {
|
|
36062
|
-
(0,
|
|
36182
|
+
(0, import_node_fs61.rmSync)((0, import_node_path48.join)(root, rel), { force: true });
|
|
36063
36183
|
} catch {
|
|
36064
36184
|
}
|
|
36065
36185
|
}
|
|
36066
36186
|
for (const f of PROOFS_TEMPLATE_FILES) {
|
|
36067
36187
|
const rel = `${PROOFS_DIR}/${f.path}`;
|
|
36068
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36188
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
|
|
36069
36189
|
const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
|
|
36070
36190
|
if (current.ok && current.content === f.content) {
|
|
36071
36191
|
kept.push(rel);
|
|
@@ -36078,8 +36198,8 @@ function scaffoldProofs(root) {
|
|
|
36078
36198
|
[`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
|
|
36079
36199
|
[`${MODELS_DIR}/README.md`, MODELS_README]
|
|
36080
36200
|
]) {
|
|
36081
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36082
|
-
if (existsNoFollow((0,
|
|
36201
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
|
|
36202
|
+
if (existsNoFollow((0, import_node_path48.join)(root, rel))) {
|
|
36083
36203
|
kept.push(rel);
|
|
36084
36204
|
continue;
|
|
36085
36205
|
}
|
|
@@ -36090,7 +36210,7 @@ function scaffoldProofs(root) {
|
|
|
36090
36210
|
}
|
|
36091
36211
|
function existsNoFollow(abs) {
|
|
36092
36212
|
try {
|
|
36093
|
-
(0,
|
|
36213
|
+
(0, import_node_fs61.lstatSync)(abs);
|
|
36094
36214
|
return true;
|
|
36095
36215
|
} catch {
|
|
36096
36216
|
return false;
|
|
@@ -36348,17 +36468,17 @@ function renderReport(r) {
|
|
|
36348
36468
|
|
|
36349
36469
|
// src/lib/prove/runner.ts
|
|
36350
36470
|
function verityLeanHome(env = process.env) {
|
|
36351
|
-
return env.VERITY_LEAN_HOME ?? (0,
|
|
36471
|
+
return env.VERITY_LEAN_HOME ?? (0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
|
|
36352
36472
|
}
|
|
36353
36473
|
function findToolchain(env = process.env) {
|
|
36354
|
-
const managedBin = (0,
|
|
36355
|
-
const elanBin = (0,
|
|
36356
|
-
const elanHas = (0,
|
|
36357
|
-
const userPath = (env.PATH ?? "").split(
|
|
36358
|
-
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(
|
|
36474
|
+
const managedBin = (0, import_node_path49.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
|
|
36475
|
+
const elanBin = (0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
|
|
36476
|
+
const elanHas = (0, import_node_fs62.existsSync)((0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
|
|
36477
|
+
const userPath = (env.PATH ?? "").split(import_node_path49.delimiter).filter((d) => d && (elanHas || (0, import_node_path49.resolve)(d) !== (0, import_node_path49.resolve)(elanBin)));
|
|
36478
|
+
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path49.delimiter);
|
|
36359
36479
|
const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
|
|
36360
36480
|
const exe = process.platform === "win32" ? "lake.exe" : "lake";
|
|
36361
|
-
const candidates2 = [(0,
|
|
36481
|
+
const candidates2 = [(0, import_node_path49.join)(managedBin, exe), ...elanHas ? [(0, import_node_path49.join)(elanBin, exe)] : [], exe];
|
|
36362
36482
|
for (const candidate of candidates2) {
|
|
36363
36483
|
try {
|
|
36364
36484
|
(0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
|
|
@@ -36437,7 +36557,7 @@ function proofsWorkspaceProblem(root) {
|
|
|
36437
36557
|
for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
|
|
36438
36558
|
let st;
|
|
36439
36559
|
try {
|
|
36440
|
-
st = (0,
|
|
36560
|
+
st = (0, import_node_fs62.lstatSync)((0, import_node_path49.join)(root, rel));
|
|
36441
36561
|
} catch {
|
|
36442
36562
|
break;
|
|
36443
36563
|
}
|
|
@@ -36457,44 +36577,44 @@ function refused(problem) {
|
|
|
36457
36577
|
function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36458
36578
|
const problem = proofsWorkspaceProblem(root);
|
|
36459
36579
|
if (problem) return refused(problem);
|
|
36460
|
-
return run2(tc, (0,
|
|
36580
|
+
return run2(tc, (0, import_node_path49.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36461
36581
|
}
|
|
36462
36582
|
async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36463
36583
|
const problem = proofsWorkspaceProblem(root);
|
|
36464
36584
|
if (problem) return refused(problem);
|
|
36465
|
-
return runAsync(tc, (0,
|
|
36585
|
+
return runAsync(tc, (0, import_node_path49.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36466
36586
|
}
|
|
36467
36587
|
function isModelInRoot(modelsAbs, rel) {
|
|
36468
|
-
if (!rel.endsWith(".lean") || (0,
|
|
36588
|
+
if (!rel.endsWith(".lean") || (0, import_node_path49.isAbsolute)(rel) || rel.startsWith("..")) return false;
|
|
36469
36589
|
return statRegularInRoot(modelsAbs, rel).ok;
|
|
36470
36590
|
}
|
|
36471
36591
|
function resolveModelFile(root, arg) {
|
|
36472
|
-
const modelsAbs = (0,
|
|
36473
|
-
const asPath = (0,
|
|
36592
|
+
const modelsAbs = (0, import_node_path49.join)(root, MODELS_DIR);
|
|
36593
|
+
const asPath = (0, import_node_path49.relative)(modelsAbs, (0, import_node_path49.isAbsolute)(arg) ? arg : (0, import_node_path49.resolve)(root, arg));
|
|
36474
36594
|
const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
|
|
36475
36595
|
for (const rel of candidates2) {
|
|
36476
|
-
if (isModelInRoot(modelsAbs, rel)) return (0,
|
|
36596
|
+
if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path49.join)(modelsAbs, rel);
|
|
36477
36597
|
}
|
|
36478
36598
|
return null;
|
|
36479
36599
|
}
|
|
36480
36600
|
function listModelFiles(root) {
|
|
36481
|
-
const modelsAbs = (0,
|
|
36482
|
-
if (!(0,
|
|
36483
|
-
return (0,
|
|
36601
|
+
const modelsAbs = (0, import_node_path49.join)(root, MODELS_DIR);
|
|
36602
|
+
if (!(0, import_node_fs62.existsSync)(modelsAbs)) return [];
|
|
36603
|
+
return (0, import_node_fs62.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path49.join)(modelsAbs, f));
|
|
36484
36604
|
}
|
|
36485
|
-
function trimDiagnostics(
|
|
36486
|
-
return
|
|
36605
|
+
function trimDiagnostics(text2) {
|
|
36606
|
+
return text2.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
|
|
36487
36607
|
}
|
|
36488
36608
|
function checkModel(tc, root, modelFile, opts = {}) {
|
|
36489
|
-
const proofsAbs = (0,
|
|
36490
|
-
const rel = (0,
|
|
36609
|
+
const proofsAbs = (0, import_node_path49.join)(root, PROOFS_DIR);
|
|
36610
|
+
const rel = (0, import_node_path49.relative)(proofsAbs, modelFile);
|
|
36491
36611
|
const problem = proofsWorkspaceProblem(root);
|
|
36492
36612
|
const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36493
36613
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36494
36614
|
}
|
|
36495
36615
|
async function checkModelAsync(tc, root, modelFile, opts = {}) {
|
|
36496
|
-
const proofsAbs = (0,
|
|
36497
|
-
const rel = (0,
|
|
36616
|
+
const proofsAbs = (0, import_node_path49.join)(root, PROOFS_DIR);
|
|
36617
|
+
const rel = (0, import_node_path49.relative)(proofsAbs, modelFile);
|
|
36498
36618
|
const problem = proofsWorkspaceProblem(root);
|
|
36499
36619
|
const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36500
36620
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
@@ -36503,10 +36623,10 @@ function toReport(res, root, modelFile, timeoutMs) {
|
|
|
36503
36623
|
const parsed = parseVerityLines(res.stdout);
|
|
36504
36624
|
const combined = `${res.stdout}
|
|
36505
36625
|
${res.stderr}`;
|
|
36506
|
-
const name2 = parsed.header?.model ?? (0,
|
|
36626
|
+
const name2 = parsed.header?.model ?? (0, import_node_path49.basename)(modelFile, ".lean");
|
|
36507
36627
|
const report = {
|
|
36508
36628
|
model: name2,
|
|
36509
|
-
file: (0,
|
|
36629
|
+
file: (0, import_node_path49.relative)(root, modelFile),
|
|
36510
36630
|
ok: res.ok,
|
|
36511
36631
|
header: parsed.header,
|
|
36512
36632
|
properties: parsed.properties,
|
|
@@ -36551,33 +36671,70 @@ function writeResult(root, report) {
|
|
|
36551
36671
|
function isCrashTrace(trace) {
|
|
36552
36672
|
return trace.some((s) => /\b(crash\w*|kill\w*|restart\w*|interrupt\w*|power|abort\w*|process (dies|exit\w*)|lost (reply|response))\b/i.test(s));
|
|
36553
36673
|
}
|
|
36674
|
+
function formalDisposition(f) {
|
|
36675
|
+
if (f.verdict !== "reproduced" || f.waived) return "none";
|
|
36676
|
+
const c = f.check;
|
|
36677
|
+
if (!c || c.outcome !== "answered") return "block";
|
|
36678
|
+
switch (c.verdict) {
|
|
36679
|
+
case "REAL":
|
|
36680
|
+
return c.introduced === "no" ? "report" : "block";
|
|
36681
|
+
case "REAL-LOW":
|
|
36682
|
+
return "report";
|
|
36683
|
+
case "PREVENTED":
|
|
36684
|
+
case "ARTIFACT":
|
|
36685
|
+
return "checked";
|
|
36686
|
+
default:
|
|
36687
|
+
return "block";
|
|
36688
|
+
}
|
|
36689
|
+
}
|
|
36690
|
+
var CAUTION = { block: 3, report: 2, checked: 1, none: 0 };
|
|
36691
|
+
function cautiousCheck(f, checks) {
|
|
36692
|
+
if (checks.length === 0) return void 0;
|
|
36693
|
+
let chosen = checks[0];
|
|
36694
|
+
for (const c of checks.slice(1)) if (CAUTION[formalDisposition({ ...f, check: c })] > CAUTION[formalDisposition({ ...f, check: chosen })]) chosen = c;
|
|
36695
|
+
return { ...chosen, votes: checks.map((c) => c.outcome === "answered" && c.verdict ? c.verdict : c.outcome), costUsd: checks.reduce((n, c) => n + c.costUsd, 0), unpriced: checks.reduce((n, c) => n + c.unpriced, 0) };
|
|
36696
|
+
}
|
|
36697
|
+
function checkLine(f) {
|
|
36698
|
+
const c = f.check;
|
|
36699
|
+
if (!c || c.outcome !== "answered" || !c.verdict) return "";
|
|
36700
|
+
const why = c.verdict === "PREVENTED" ? c.preventedBy || c.reason : c.reason;
|
|
36701
|
+
const from = c.trigger ? ` Reached from: ${c.trigger}.` : "";
|
|
36702
|
+
const pre = c.introduced === "no" ? " Already possible before this change." : "";
|
|
36703
|
+
const votes = c.votes && c.votes.length > 1 ? ` (${c.votes.length} checks: ${c.votes.join(", ")})` : "";
|
|
36704
|
+
return `Checked: ${c.verdict}${votes}.${from}${pre} ${why ?? ""}`.trim();
|
|
36705
|
+
}
|
|
36554
36706
|
function mergeFormalFindings(response, outcome, pushedFiles) {
|
|
36555
|
-
if (!outcome) return { blocking: 0 };
|
|
36707
|
+
if (!outcome) return { blocking: 0, reported: 0 };
|
|
36556
36708
|
const norm3 = (p) => p.replace(/\\/g, "/");
|
|
36557
36709
|
const pushed = new Set(pushedFiles.map(norm3));
|
|
36558
|
-
const
|
|
36559
|
-
|
|
36710
|
+
const onPush = outcome.findings.filter((f) => pushed.has(norm3(f.file)));
|
|
36711
|
+
const blocking = onPush.filter((f) => formalDisposition(f) === "block");
|
|
36712
|
+
const reported = onPush.filter((f) => formalDisposition(f) === "report");
|
|
36713
|
+
if (blocking.length === 0 && reported.length === 0) return { blocking: 0, reported: 0 };
|
|
36560
36714
|
const existing = Array.isArray(response.findings) ? response.findings : [];
|
|
36561
|
-
|
|
36562
|
-
|
|
36563
|
-
|
|
36715
|
+
const asFinding = (f, blocks) => {
|
|
36716
|
+
const checked = checkLine(f);
|
|
36717
|
+
return {
|
|
36564
36718
|
pattern_id: "formal-counterexample",
|
|
36565
|
-
severity: "high",
|
|
36566
|
-
|
|
36719
|
+
severity: blocks ? "high" : "medium",
|
|
36720
|
+
// A bug this change did not introduce is filed the way the gate files everything it will not block on.
|
|
36721
|
+
scope: f.check?.introduced === "no" && !blocks ? "pre-existing" : "change",
|
|
36567
36722
|
file: f.file,
|
|
36568
36723
|
line: outcome.target?.lines?.from ?? null,
|
|
36569
36724
|
// Worded as the VIOLATION: the property text is what should hold, and
|
|
36570
36725
|
// as a title it read backwards (e2e, 2026-09-26). A trace that needs a
|
|
36571
36726
|
// crash between two writes is labelled: reproducing it means injecting
|
|
36572
36727
|
// the crash, so it is a crash-consistency finding, not a race.
|
|
36573
|
-
title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code`,
|
|
36574
|
-
description: terminalText(f.reason ?? "", 2e3),
|
|
36728
|
+
title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code${f.check?.outcome === "answered" ? `, checked ${f.check.verdict}` : ""}`,
|
|
36729
|
+
description: terminalText([f.reason ?? "", checked].filter(Boolean).join(" "), 2e3),
|
|
36575
36730
|
fix: { description: `Trace: ${terminalText(f.trace.join(" \u2192 ") || "(initial state)", 2e3)}. Replay: ${terminalText(f.reason ?? "reproduced in the container", 2e3)}` },
|
|
36576
36731
|
source: "formal"
|
|
36577
|
-
}
|
|
36578
|
-
|
|
36579
|
-
|
|
36580
|
-
|
|
36732
|
+
};
|
|
36733
|
+
};
|
|
36734
|
+
response.findings = [...existing, ...blocking.map((f) => asFinding(f, true)), ...reported.map((f) => asFinding(f, false))];
|
|
36735
|
+
if (blocking.length > 0) response.gate_decision = "FAIL";
|
|
36736
|
+
else if (response.gate_decision === "PASS") response.gate_decision = "WARN";
|
|
36737
|
+
return { blocking: blocking.length, reported: reported.length };
|
|
36581
36738
|
}
|
|
36582
36739
|
|
|
36583
36740
|
// src/lib/prove/scalpel.ts
|
|
@@ -36814,6 +36971,8 @@ function bumpLedger(root) {
|
|
|
36814
36971
|
}
|
|
36815
36972
|
var REPLAY_RESERVE_MS = 45e3;
|
|
36816
36973
|
var MAX_REPLAYS = 3;
|
|
36974
|
+
var MAX_CHECKS = 2;
|
|
36975
|
+
var CHECK_VOTES = 2;
|
|
36817
36976
|
function isNetworkError(message) {
|
|
36818
36977
|
return /Network error|fetch failed|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|socket hang up/i.test(message);
|
|
36819
36978
|
}
|
|
@@ -36896,12 +37055,14 @@ async function runFormalPhase(input) {
|
|
|
36896
37055
|
symbol: f.symbol,
|
|
36897
37056
|
verdict: "reproduced",
|
|
36898
37057
|
reason: f.waived ? `waived ${f.waived.at.slice(0, 10)}: ${f.waived.reason} (standing since ${f.at.slice(0, 10)}; the file has not changed)` : `${f.reason ?? "reproduced on the real code"} (standing since ${f.at.slice(0, 10)}; the file has not changed)`,
|
|
36899
|
-
...f.waived ? { waived: true } : {}
|
|
37058
|
+
...f.waived ? { waived: true } : {},
|
|
37059
|
+
// Same bytes, same answer: the check is not paid for twice.
|
|
37060
|
+
...f.check ? { check: { outcome: "answered", rounds: 0, costUsd: 0, unpriced: 0, durationMs: 0, ...f.check } } : {}
|
|
36900
37061
|
});
|
|
36901
37062
|
}
|
|
36902
37063
|
}
|
|
36903
37064
|
if (kept.length !== persisted.length) writePersistedFindings(root, kept);
|
|
36904
|
-
if (standing.length > 0) {
|
|
37065
|
+
if (standing.length > 0 && !input.skipStanding) {
|
|
36905
37066
|
const first = kept.find((f) => f.file === standing[0].file);
|
|
36906
37067
|
return done({
|
|
36907
37068
|
status: "checked",
|
|
@@ -36929,7 +37090,7 @@ async function runFormalPhase(input) {
|
|
|
36929
37090
|
return a.source === "tree-sitter" && a.value.effects.length >= 2;
|
|
36930
37091
|
})());
|
|
36931
37092
|
};
|
|
36932
|
-
const eligible = signals.filter((s) => isEligible(s, largePush).ok || mapEligible(s.file)).slice(0, 5);
|
|
37093
|
+
const eligible = signals.filter((s) => input.relaxedGates || isEligible(s, largePush).ok || mapEligible(s.file)).slice(0, 5);
|
|
36933
37094
|
if (eligible.length === 0) {
|
|
36934
37095
|
const best = signals[0];
|
|
36935
37096
|
return done({ status: "skipped", skip: "not-eligible", detail: `${best.file}: ${isEligible(best, largePush).why}` });
|
|
@@ -36983,6 +37144,10 @@ async function runFormalPhase(input) {
|
|
|
36983
37144
|
}
|
|
36984
37145
|
}
|
|
36985
37146
|
if (d.resolved && d.resolved !== c.ai.symbol) c.ai.symbol = d.resolved;
|
|
37147
|
+
if (input.exclude?.has(`${c.file}#${c.ai.symbol}`)) {
|
|
37148
|
+
note("verified", `${c.ai.symbol}: modelled earlier in this push`);
|
|
37149
|
+
continue;
|
|
37150
|
+
}
|
|
36986
37151
|
if (input.changedLines) {
|
|
36987
37152
|
const changed = input.changedLines.get(c.file) ?? [];
|
|
36988
37153
|
if (changed.length === 0) {
|
|
@@ -37024,7 +37189,7 @@ async function runFormalPhase(input) {
|
|
|
37024
37189
|
const hazard = hasHazard(functionHazard(d.numbered));
|
|
37025
37190
|
const shared = contextHazard(context);
|
|
37026
37191
|
const judged = (c.ai.criteria?.hazard ?? 0) >= 0.8;
|
|
37027
|
-
if (!hazard.ok && !shared?.ok && !judged) {
|
|
37192
|
+
if (!input.relaxedGates && !hazard.ok && !shared?.ok && !judged) {
|
|
37028
37193
|
note("no-hazard", `${c.ai.symbol}: ${hazard.why}`);
|
|
37029
37194
|
continue;
|
|
37030
37195
|
}
|
|
@@ -37057,7 +37222,7 @@ async function runFormalPhase(input) {
|
|
|
37057
37222
|
let report = null;
|
|
37058
37223
|
let modelName = "";
|
|
37059
37224
|
let rounds = 0;
|
|
37060
|
-
for (let round = 1; round <= 2; round++) {
|
|
37225
|
+
for (let round = 1; round <= (input.maxRounds ?? 2); round++) {
|
|
37061
37226
|
if (round > 1 && overCap()) return done({ status: "skipped", skip: "cost-cap", detail: `$${usage.costUsd.toFixed(2)} spent, cap $${costCap.toFixed(2)}; no retry`, target, model: { name: modelName, file: `${AUTO_MODELS_DIR}/${modelName}.lean`, rounds } });
|
|
37062
37227
|
if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off before generation", target });
|
|
37063
37228
|
rounds = round;
|
|
@@ -37076,7 +37241,7 @@ async function runFormalPhase(input) {
|
|
|
37076
37241
|
modelName = gen.name;
|
|
37077
37242
|
const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
|
|
37078
37243
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
37079
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37244
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path50.join)(root, rel);
|
|
37080
37245
|
progress.model = { name: gen.name, file: rel, rounds: round };
|
|
37081
37246
|
progress.step = "check";
|
|
37082
37247
|
report = await deps.check(root, abs);
|
|
@@ -37172,13 +37337,40 @@ async function runFormalPhase(input) {
|
|
|
37172
37337
|
const verdict = r.verdict === "reproduced" ? "reproduced" : r.verdict === "diverged" ? "diverged" : r.verdict === "unreplayable" ? "model-only" : "unverified";
|
|
37173
37338
|
findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0 });
|
|
37174
37339
|
}
|
|
37340
|
+
const toCheck = deps.verify && !cancelled() ? findings.filter((f) => f.verdict === "reproduced").slice(0, MAX_CHECKS) : [];
|
|
37341
|
+
if (toCheck.length > 0) {
|
|
37342
|
+
progress.step = "verify";
|
|
37343
|
+
const share = Math.max(0, costCap - usage.costUsd) / (toCheck.length * CHECK_VOTES);
|
|
37344
|
+
const failed = (error) => ({ outcome: "failed", verdict: null, introduced: "unknown", rounds: 0, costUsd: 0, unpriced: 0, durationMs: 0, error });
|
|
37345
|
+
await Promise.all(toCheck.map(async (f) => {
|
|
37346
|
+
const checks = await Promise.all(Array.from({ length: CHECK_VOTES }, () => deps.verify(f, { ...lines ? { lines } : {}, changedLines: input.changedLines?.get(f.file) ?? [], deadlineAt: input.deadlineAt, costLeftUsd: share }).catch((err2) => failed(String(err2?.message ?? err2).slice(0, 120)))));
|
|
37347
|
+
for (const c of checks) {
|
|
37348
|
+
if (c.costUsd > 0) spend({ costUsd: c.costUsd });
|
|
37349
|
+
for (let i2 = 0; i2 < c.unpriced; i2++) usage.unpriced++;
|
|
37350
|
+
}
|
|
37351
|
+
if (!cancelled()) f.check = cautiousCheck(f, checks);
|
|
37352
|
+
}));
|
|
37353
|
+
}
|
|
37175
37354
|
const reproduced = findings.filter((f) => f.verdict === "reproduced");
|
|
37176
37355
|
if (reproduced.length > 0 && !cancelled()) {
|
|
37177
37356
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
37178
37357
|
const others = readPersistedFindings(root).filter((f) => f.file !== top.file);
|
|
37179
37358
|
writePersistedFindings(root, [
|
|
37180
37359
|
...others,
|
|
37181
|
-
...reproduced.map((f) => ({
|
|
37360
|
+
...reproduced.map((f) => ({
|
|
37361
|
+
file: f.file,
|
|
37362
|
+
symbol: f.symbol,
|
|
37363
|
+
sha256: sha2562,
|
|
37364
|
+
property: f.property,
|
|
37365
|
+
desc: f.desc,
|
|
37366
|
+
kind: f.kind,
|
|
37367
|
+
trace: f.trace,
|
|
37368
|
+
model: modelName,
|
|
37369
|
+
reason: f.reason,
|
|
37370
|
+
...lines ? { lines } : {},
|
|
37371
|
+
at: now,
|
|
37372
|
+
...f.check?.outcome === "answered" ? { check: { verdict: f.check.verdict, introduced: f.check.introduced, trigger: f.check.trigger, preventedBy: f.check.preventedBy, effect: f.check.effect, reason: f.check.reason, ...f.check.votes ? { votes: f.check.votes } : {} } } : {}
|
|
37373
|
+
}))
|
|
37182
37374
|
]);
|
|
37183
37375
|
}
|
|
37184
37376
|
const clean2 = findings.every((f) => f.verdict === "diverged");
|
|
@@ -37198,7 +37390,7 @@ async function runFormalPhase(input) {
|
|
|
37198
37390
|
return done({
|
|
37199
37391
|
status: "checked",
|
|
37200
37392
|
target,
|
|
37201
|
-
model: { name: modelName, file: (0,
|
|
37393
|
+
model: { name: modelName, file: (0, import_node_path50.relative)(root, (0, import_node_path50.join)(root, modelFile)), rounds },
|
|
37202
37394
|
properties: report.properties,
|
|
37203
37395
|
findings
|
|
37204
37396
|
});
|
|
@@ -37275,7 +37467,7 @@ async function generateAndCheck(root, req, opts) {
|
|
|
37275
37467
|
}
|
|
37276
37468
|
const rel = `${dir}/${gen.name}.lean`;
|
|
37277
37469
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
37278
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37470
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path50.join)(root, rel);
|
|
37279
37471
|
const report = await opts.deps.check(root, abs);
|
|
37280
37472
|
const abstracts = report.header?.abstracts ?? [];
|
|
37281
37473
|
const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
|
|
@@ -37307,7 +37499,7 @@ async function generateAndCheck(root, req, opts) {
|
|
|
37307
37499
|
function skippedOutcome(skip, detail) {
|
|
37308
37500
|
return { status: "skipped", skip, ...detail ? { detail } : {}, findings: [], usage: { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 }, durationMs: 0 };
|
|
37309
37501
|
}
|
|
37310
|
-
async function prepareFormalPhase(root, env = process.env, auth2, readSource, codeSource) {
|
|
37502
|
+
async function prepareFormalPhase(root, env = process.env, auth2, readSource, codeSource, opts = {}) {
|
|
37311
37503
|
const direct = env.VERITY_PROVE_DIRECT === "1" && !!env.OPENAI_API_KEY;
|
|
37312
37504
|
if (!auth2 && !direct) return { ok: false, skip: "not-logged-in" };
|
|
37313
37505
|
const apiKey = direct ? env.OPENAI_API_KEY : void 0;
|
|
@@ -37323,7 +37515,7 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
|
|
|
37323
37515
|
const build = await buildLibraryAsync(toolchain, root, 9e4);
|
|
37324
37516
|
if (!build.ok) return { ok: false, skip: "library-build-failed", detail: build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).join(" ").slice(0, 200) };
|
|
37325
37517
|
const code = await loadCodeContext(root, env, codeSource);
|
|
37326
|
-
return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...code }), codeSource: code.codeSource } };
|
|
37518
|
+
return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...opts.tier ? { tier: opts.tier } : {}, ...code }), codeSource: code.codeSource } };
|
|
37327
37519
|
}
|
|
37328
37520
|
async function loadCodeContext(root, env = process.env, codeSource) {
|
|
37329
37521
|
const loaded = await loadCodeMap(env);
|
|
@@ -37376,10 +37568,52 @@ function runFormalPhaseWithin(input) {
|
|
|
37376
37568
|
resolve9(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
|
|
37377
37569
|
}, left);
|
|
37378
37570
|
});
|
|
37379
|
-
return Promise.race([
|
|
37571
|
+
return Promise.race([runFormalPhaseTargets({ ...input, progress }), cutoff]).finally(() => {
|
|
37380
37572
|
if (timer) clearTimeout(timer);
|
|
37381
37573
|
});
|
|
37382
37574
|
}
|
|
37575
|
+
var NOTHING_ELSE_QUALIFIES = /* @__PURE__ */ new Set(["no-source-files", "not-eligible", "no-candidate", "no-symbol", "symbol-not-in-push", "verified", "no-hazard", "too-large"]);
|
|
37576
|
+
async function runFormalPhaseTargets(input) {
|
|
37577
|
+
const first = await runFormalPhase(input);
|
|
37578
|
+
const max = Math.max(1, Math.floor(input.maxTargets ?? 1));
|
|
37579
|
+
if (max === 1 || first.status !== "checked" || !first.target) return first;
|
|
37580
|
+
const outcomes = [first];
|
|
37581
|
+
const exclude = /* @__PURE__ */ new Set([`${first.target.file}#${first.target.symbol}`]);
|
|
37582
|
+
const cap2 = input.costCapUsd ?? PUSH_COST_CAP_USD;
|
|
37583
|
+
let stoppedAt;
|
|
37584
|
+
while (outcomes.length < max) {
|
|
37585
|
+
if (input.progress?.cancelled) {
|
|
37586
|
+
stoppedAt = { skip: "deadline", detail: "cut off between targets" };
|
|
37587
|
+
break;
|
|
37588
|
+
}
|
|
37589
|
+
const left = input.deadlineAt - input.deps.now();
|
|
37590
|
+
if (left < GENERATE_RESERVE_MS + REPLAY_RESERVE_MS) {
|
|
37591
|
+
stoppedAt = { skip: "not-enough-time", detail: `${Math.round(left / 1e3)} s left before target ${outcomes.length + 1}` };
|
|
37592
|
+
break;
|
|
37593
|
+
}
|
|
37594
|
+
const spent = outcomes.reduce((sum, o) => sum + o.usage.costUsd, 0);
|
|
37595
|
+
if (spent >= cap2) {
|
|
37596
|
+
stoppedAt = { skip: "cost-cap", detail: `$${spent.toFixed(2)} spent, cap $${cap2.toFixed(2)}` };
|
|
37597
|
+
break;
|
|
37598
|
+
}
|
|
37599
|
+
const next = await runFormalPhase({ ...input, exclude, skipStanding: true, costCapUsd: cap2 - spent, progress: {} });
|
|
37600
|
+
if (next.status !== "checked" && next.skip && !NOTHING_ELSE_QUALIFIES.has(next.skip)) stoppedAt = { skip: next.skip, ...next.detail ? { detail: next.detail } : {} };
|
|
37601
|
+
if (!next.target || next.status !== "checked" && exclude.has(`${next.target.file}#${next.target.symbol}`)) break;
|
|
37602
|
+
exclude.add(`${next.target.file}#${next.target.symbol}`);
|
|
37603
|
+
outcomes.push(next);
|
|
37604
|
+
if (next.status !== "checked") break;
|
|
37605
|
+
}
|
|
37606
|
+
if (outcomes.length === 1) return stoppedAt ? { ...first, stoppedAt } : first;
|
|
37607
|
+
return {
|
|
37608
|
+
...first,
|
|
37609
|
+
...stoppedAt ? { stoppedAt } : {},
|
|
37610
|
+
findings: outcomes.flatMap((o) => o.findings),
|
|
37611
|
+
properties: outcomes.flatMap((o) => o.properties ?? []),
|
|
37612
|
+
targets: outcomes.flatMap((o) => o.target ? [{ file: o.target.file, symbol: o.target.symbol, status: o.status, ...o.skip ? { skip: o.skip } : {}, findings: o.findings.length }] : []),
|
|
37613
|
+
usage: outcomes.reduce((u, o) => ({ inputTokens: u.inputTokens + o.usage.inputTokens, outputTokens: u.outputTokens + o.usage.outputTokens, costUsd: Math.round((u.costUsd + o.usage.costUsd) * 1e6) / 1e6, unpriced: u.unpriced + o.usage.unpriced }), { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 }),
|
|
37614
|
+
durationMs: outcomes.reduce((sum, o) => sum + o.durationMs, 0)
|
|
37615
|
+
};
|
|
37616
|
+
}
|
|
37383
37617
|
function cutOffOutcome(p, detail, elapsedMs) {
|
|
37384
37618
|
const usage = p.usage ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 };
|
|
37385
37619
|
if (!p.report || !p.target || !p.model) {
|
|
@@ -37398,7 +37632,9 @@ function describeFormalOutcome(o) {
|
|
|
37398
37632
|
if (o.status === "skipped") return `formal: skipped (${o.skip}${o.detail ? `: ${o.detail}` : ""})`;
|
|
37399
37633
|
const parts2 = o.properties?.map((p) => {
|
|
37400
37634
|
const f = o.findings.find((x) => x.property === p.id);
|
|
37401
|
-
const
|
|
37635
|
+
const votes = f?.check?.votes && f.check.votes.length > 1 ? ` [${f.check.votes.join(", ")}]` : "";
|
|
37636
|
+
const checked = f?.check ? f.check.outcome === "answered" ? ` \u2192 checked ${f.check.verdict}${f.check.introduced === "no" ? " (pre-existing)" : ""}${votes}` : ` \u2192 not checked (${f.check.outcome})${votes}` : "";
|
|
37637
|
+
const tag = p.result === "counterexample" ? f ? f.verdict.toUpperCase() + (f.waived ? " (waived)" : "") + checked : "counterexample" : p.result;
|
|
37402
37638
|
return `${p.id} ${tag}`;
|
|
37403
37639
|
}) ?? [];
|
|
37404
37640
|
const cost = o.usage.costUsd > 0 ? ` \xB7 $${o.usage.costUsd.toFixed(2)}` : "";
|
|
@@ -37406,6 +37642,88 @@ function describeFormalOutcome(o) {
|
|
|
37406
37642
|
return `formal: ${o.model?.name ?? "?"} on ${o.target?.file ?? "?"}#${o.target?.symbol ?? "?"} (${o.model?.rounds ?? 1} round${o.model?.rounds === 1 ? "" : "s"}) \xB7 ${parts2.join(" \xB7 ")} \xB7 ${Math.round(o.durationMs / 1e3)} s${cost}${cut}`;
|
|
37407
37643
|
}
|
|
37408
37644
|
|
|
37645
|
+
// src/lib/prove/verify.ts
|
|
37646
|
+
var MIN_VERIFY_TURN_MS = 15e3;
|
|
37647
|
+
var MIN_VERIFY_START_MS = 45e3;
|
|
37648
|
+
var VERIFY_TURN_HOLD_USD = 0.1;
|
|
37649
|
+
var MAX_TURNS2 = 14;
|
|
37650
|
+
var VERDICTS = ["REAL", "REAL-LOW", "PREVENTED", "ARTIFACT", "UNSURE"];
|
|
37651
|
+
var verdictOf = (v) => typeof v === "string" && VERDICTS.includes(v) ? v : null;
|
|
37652
|
+
var introducedOf = (v) => v === "yes" || v === "no" ? v : "unknown";
|
|
37653
|
+
var text = (v, n) => typeof v === "string" ? v.slice(0, n) : "";
|
|
37654
|
+
function verifyPost(auth2) {
|
|
37655
|
+
return async (body2, timeoutMs) => {
|
|
37656
|
+
const res = await apiRequest({
|
|
37657
|
+
method: "POST",
|
|
37658
|
+
path: "/prove/verify",
|
|
37659
|
+
serviceUrl: auth2.serviceUrl,
|
|
37660
|
+
token: auth2.token,
|
|
37661
|
+
// Streamed with a heartbeat, like generate and replay (decision 53).
|
|
37662
|
+
extraHeaders: { "X-Verity-Keepalive": "1" },
|
|
37663
|
+
body: body2,
|
|
37664
|
+
timeout: timeoutMs,
|
|
37665
|
+
cmd: "prove-verify"
|
|
37666
|
+
});
|
|
37667
|
+
return res.ok ? { ok: true, data: res.data ?? {} } : { ok: false, error: res.error };
|
|
37668
|
+
};
|
|
37669
|
+
}
|
|
37670
|
+
async function verifyFinding(input, opts) {
|
|
37671
|
+
const now = opts.now ?? Date.now;
|
|
37672
|
+
const startedAt = now();
|
|
37673
|
+
const remaining = () => opts.deadlineAt - now();
|
|
37674
|
+
let rounds = 0;
|
|
37675
|
+
let costUsd = 0;
|
|
37676
|
+
let unpriced = 0;
|
|
37677
|
+
const end = (outcome, extra = {}) => ({ outcome, verdict: null, introduced: "unknown", rounds, costUsd, unpriced, durationMs: now() - startedAt, ...extra });
|
|
37678
|
+
if (remaining() < MIN_VERIFY_START_MS) return end("deadline", { error: "not enough time left" });
|
|
37679
|
+
let body2 = {
|
|
37680
|
+
target: {
|
|
37681
|
+
file: input.file,
|
|
37682
|
+
symbol: input.symbol,
|
|
37683
|
+
...input.lines ? { lines: input.lines } : {},
|
|
37684
|
+
property: input.property,
|
|
37685
|
+
replay_reason: input.replayReason,
|
|
37686
|
+
changed_lines: input.changedLines.slice(0, 200)
|
|
37687
|
+
},
|
|
37688
|
+
local_tools: opts.localTools
|
|
37689
|
+
};
|
|
37690
|
+
for (let turn = 0; turn < MAX_TURNS2; turn++) {
|
|
37691
|
+
if (remaining() < MIN_VERIFY_TURN_MS) return end("deadline");
|
|
37692
|
+
if (costUsd + VERIFY_TURN_HOLD_USD > opts.costLeftUsd) return end("cost-cap");
|
|
37693
|
+
const res = await opts.post({ ...body2, remaining_ms: remaining() }, Math.max(1, remaining()));
|
|
37694
|
+
if (!res.ok) return end("failed", { error: res.error.slice(0, 200) });
|
|
37695
|
+
const d = res.data;
|
|
37696
|
+
if (d.enabled === false) return end("disabled", { error: text(d.reason, 60) });
|
|
37697
|
+
if (d.error && typeof d.error === "object") return end("failed", { error: text(d.error.code, 60) || "SERVICE_ERROR" });
|
|
37698
|
+
rounds = typeof d.round === "number" ? d.round : rounds + 1;
|
|
37699
|
+
if (typeof d.cost_usd === "number") costUsd += d.cost_usd;
|
|
37700
|
+
else unpriced++;
|
|
37701
|
+
if (d.done) {
|
|
37702
|
+
const a = d.answer;
|
|
37703
|
+
if (!a) return end("failed", { error: text(d.error, 60) || "no verdict" });
|
|
37704
|
+
const verdict = verdictOf(a.verdict);
|
|
37705
|
+
if (!verdict) return end("failed", { error: "unknown verdict" });
|
|
37706
|
+
return end("answered", {
|
|
37707
|
+
verdict,
|
|
37708
|
+
claimed: verdictOf(a.claimed),
|
|
37709
|
+
introduced: introducedOf(a.introduced),
|
|
37710
|
+
trigger: text(a.trigger, 400),
|
|
37711
|
+
preventedBy: typeof a.prevented_by === "string" ? a.prevented_by.slice(0, 600) : null,
|
|
37712
|
+
effect: text(a.effect, 600),
|
|
37713
|
+
reason: text(a.reason, 2e3),
|
|
37714
|
+
quotes: (Array.isArray(a.quotes) ? a.quotes : []).slice(0, 12).flatMap((q) => {
|
|
37715
|
+
const o = q ?? {};
|
|
37716
|
+
return typeof o.path === "string" && typeof o.text === "string" ? [{ path: o.path.slice(0, 400), text: o.text.slice(0, 600), witnessed: o.witnessed === true }] : [];
|
|
37717
|
+
})
|
|
37718
|
+
});
|
|
37719
|
+
}
|
|
37720
|
+
if (typeof d.state !== "string" || !Array.isArray(d.calls)) return end("failed", { error: "malformed turn" });
|
|
37721
|
+
const results = await opts.executeTools(d.calls);
|
|
37722
|
+
body2 = { state: d.state, results };
|
|
37723
|
+
}
|
|
37724
|
+
return end("failed", { error: "too many turns" });
|
|
37725
|
+
}
|
|
37726
|
+
|
|
37409
37727
|
// src/lib/prove/record.ts
|
|
37410
37728
|
var RECORD_TIMEOUT_MS = 8e3;
|
|
37411
37729
|
var HOOK_EXIT_MARGIN_MS = 5e3;
|
|
@@ -37446,7 +37764,7 @@ var kind = (k) => k === "intent" ? "intent" : "structural";
|
|
|
37446
37764
|
var signalsOf = (c) => c && typeof c.commits === "number" && typeof c.fixCommits === "number" ? { commits: c.commits, fix_commits: c.fixCommits, risk: Object.fromEntries(Object.entries(c.risk ?? {}).filter(([, n]) => typeof n === "number" && n > 0).slice(0, 16)) } : null;
|
|
37447
37765
|
function buildPhaseRecord(outcome, ctx) {
|
|
37448
37766
|
const pushed = new Set(ctx.pushedFiles.map(norm2));
|
|
37449
|
-
const blocks = (f) => ctx.moment === "push" && f
|
|
37767
|
+
const blocks = (f) => ctx.moment === "push" && formalDisposition(f) === "block" && pushed.has(norm2(f.file));
|
|
37450
37768
|
const symbol = (s) => ident2(s, SYMBOL, 200);
|
|
37451
37769
|
return {
|
|
37452
37770
|
moment: ctx.moment,
|
|
@@ -37486,7 +37804,9 @@ function buildPhaseRecord(outcome, ctx) {
|
|
|
37486
37804
|
symbol: f.symbol,
|
|
37487
37805
|
verdict: f.verdict,
|
|
37488
37806
|
waived: f.waived === true,
|
|
37489
|
-
blocked: blocks(f)
|
|
37807
|
+
blocked: blocks(f),
|
|
37808
|
+
// The check's closed codes only (decision 91): never its reason, trigger or quotes.
|
|
37809
|
+
check: f.check ? { outcome: f.check.outcome, verdict: f.check.verdict, introduced: f.check.introduced, rounds: f.check.rounds } : null
|
|
37490
37810
|
})),
|
|
37491
37811
|
grounding: outcome.grounding ? {
|
|
37492
37812
|
sent_back: outcome.grounding.sentBack,
|
|
@@ -37537,7 +37857,7 @@ var WRITERS_BUDGET_MS = 1500;
|
|
|
37537
37857
|
var EXCERPT_MAX_LINES2 = 30;
|
|
37538
37858
|
var VENDORED_READ_MAX_BYTES = 256 * 1024;
|
|
37539
37859
|
var GUARD_BLOCK_CAP = 2;
|
|
37540
|
-
var GUARD_ITER_FILE = (0,
|
|
37860
|
+
var GUARD_ITER_FILE = (0, import_node_path51.join)(VERITY_DIR, ".guard-iteration");
|
|
37541
37861
|
function readPreToolUseStdin() {
|
|
37542
37862
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
37543
37863
|
return new Promise((resolve9) => {
|
|
@@ -37582,7 +37902,7 @@ function readPreToolUseStdin() {
|
|
|
37582
37902
|
}
|
|
37583
37903
|
function readIterMap() {
|
|
37584
37904
|
try {
|
|
37585
|
-
const raw = JSON.parse((0,
|
|
37905
|
+
const raw = JSON.parse((0, import_node_fs63.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
37586
37906
|
if (raw && typeof raw === "object") {
|
|
37587
37907
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
37588
37908
|
return { [raw.moment]: raw.count };
|
|
@@ -37602,10 +37922,10 @@ function readIter(moment) {
|
|
|
37602
37922
|
}
|
|
37603
37923
|
function writeIter(moment, count) {
|
|
37604
37924
|
try {
|
|
37605
|
-
(0,
|
|
37925
|
+
(0, import_node_fs63.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37606
37926
|
const map = readIterMap();
|
|
37607
37927
|
map[moment] = count;
|
|
37608
|
-
(0,
|
|
37928
|
+
(0, import_node_fs63.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37609
37929
|
} catch {
|
|
37610
37930
|
}
|
|
37611
37931
|
}
|
|
@@ -37615,10 +37935,10 @@ function resetIter(moment) {
|
|
|
37615
37935
|
if (!(moment in map)) return;
|
|
37616
37936
|
delete map[moment];
|
|
37617
37937
|
if (Object.keys(map).length === 0) {
|
|
37618
|
-
if ((0,
|
|
37938
|
+
if ((0, import_node_fs63.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs63.unlinkSync)(GUARD_ITER_FILE);
|
|
37619
37939
|
} else {
|
|
37620
|
-
(0,
|
|
37621
|
-
(0,
|
|
37940
|
+
(0, import_node_fs63.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37941
|
+
(0, import_node_fs63.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37622
37942
|
}
|
|
37623
37943
|
} catch {
|
|
37624
37944
|
}
|
|
@@ -37668,17 +37988,17 @@ function parsePrIntent(command) {
|
|
|
37668
37988
|
}
|
|
37669
37989
|
var TRIVIAL_INTENT = /^(wip|tmp|temp|test|fix|chore|amend|\.+|fixup!.*|squash!.*|merge\b.*)$/i;
|
|
37670
37990
|
var SHELL_PLUMBING = /\$\(|`|<<-?\s*['"]?[A-Za-z_]/;
|
|
37671
|
-
function isSubstantiveIntent(
|
|
37672
|
-
if (!
|
|
37673
|
-
const t =
|
|
37991
|
+
function isSubstantiveIntent(text2) {
|
|
37992
|
+
if (!text2) return false;
|
|
37993
|
+
const t = text2.trim();
|
|
37674
37994
|
if (t.length < 12) return false;
|
|
37675
37995
|
if (TRIVIAL_INTENT.test(t)) return false;
|
|
37676
37996
|
if (SHELL_PLUMBING.test(t)) return false;
|
|
37677
37997
|
return true;
|
|
37678
37998
|
}
|
|
37679
37999
|
function extractStatedIntent(moment, command, pushedMessages = null) {
|
|
37680
|
-
const
|
|
37681
|
-
return isSubstantiveIntent(
|
|
38000
|
+
const text2 = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
|
|
38001
|
+
return isSubstantiveIntent(text2) ? text2 : null;
|
|
37682
38002
|
}
|
|
37683
38003
|
function hasBlockingFinding(response, sentFiles) {
|
|
37684
38004
|
const findings = response.findings ?? [];
|
|
@@ -37688,7 +38008,7 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
37688
38008
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
37689
38009
|
const analyzable = filterAnalyzable(files);
|
|
37690
38010
|
const securityFiles = filterSecurity(files);
|
|
37691
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
38011
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs63.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
37692
38012
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
37693
38013
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
37694
38014
|
const requestBody = {
|
|
@@ -37701,7 +38021,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
|
|
|
37701
38021
|
agent_harness: "claude-code",
|
|
37702
38022
|
// Prefer the session id Claude Code passes on the hook payload; fall back
|
|
37703
38023
|
// to the env var, then 'unknown'.
|
|
37704
|
-
session_id: sessionId ??
|
|
38024
|
+
session_id: sessionId ?? envSessionId() ?? "unknown",
|
|
37705
38025
|
trigger,
|
|
37706
38026
|
iteration: iter + 1
|
|
37707
38027
|
}
|
|
@@ -37769,6 +38089,14 @@ function oneShotLostOutcome(input) {
|
|
|
37769
38089
|
return input.agentGate === "FAIL" && input.agentBlocking ? "block" : "allow-without-review";
|
|
37770
38090
|
}
|
|
37771
38091
|
function withAgentVerdict(oneShot, agent) {
|
|
38092
|
+
if (agent.one_shot_source === "none" && agent.findings_mode === "agent" && agent.gate_decision !== null) {
|
|
38093
|
+
return {
|
|
38094
|
+
...oneShot,
|
|
38095
|
+
gate_decision: worstGate(agent.gate_decision, "WARN", "WARN"),
|
|
38096
|
+
findings: agent.findings.filter((f) => f.agent_added === true),
|
|
38097
|
+
agent_review: { ...agent.agent_review, gate_decision_before: oneShot.gate_decision ?? null, one_shot_source: "none", cleared: [], downgraded: [] }
|
|
38098
|
+
};
|
|
38099
|
+
}
|
|
37772
38100
|
if (agent.one_shot_source === "none" && typeof oneShot.gate_decision === "string") {
|
|
37773
38101
|
const added = agent.findings.filter((f) => f.agent_added === true);
|
|
37774
38102
|
return {
|
|
@@ -37832,7 +38160,8 @@ function startAgentReview(input) {
|
|
|
37832
38160
|
http: http2,
|
|
37833
38161
|
executeTools: makeToolExecutor(ctx),
|
|
37834
38162
|
startedAt: input.hookStartedAt,
|
|
37835
|
-
|
|
38163
|
+
// The push's deadline follows the review effort (lib/effort.ts); the commit's never does.
|
|
38164
|
+
deadlineMs: input.moment === "pre-push" ? effortProfile(input.root).pushDeadlineMs : AGENT_DEADLINE_MS[input.moment],
|
|
37836
38165
|
start: {
|
|
37837
38166
|
moment: input.moment,
|
|
37838
38167
|
iteration: input.iteration,
|
|
@@ -37857,7 +38186,8 @@ function startFormalPhase(input) {
|
|
|
37857
38186
|
const env = process.env.VERITY_GIT_MOMENT_FORMAL;
|
|
37858
38187
|
if (env === "off") return null;
|
|
37859
38188
|
if (env !== "push" && readProjectConfig().formal !== "push") return null;
|
|
37860
|
-
const
|
|
38189
|
+
const profile = effortProfile(input.root);
|
|
38190
|
+
const deadlineAt = input.hookStartedAt + profile.pushDeadlineMs - 1e4;
|
|
37861
38191
|
const ig = loadVerityIgnore();
|
|
37862
38192
|
const files = input.files.filter((f) => !isVerityOwnedPath(f) && !isIgnored3(ig, f));
|
|
37863
38193
|
let changedLines = /* @__PURE__ */ new Map();
|
|
@@ -37879,9 +38209,17 @@ function startFormalPhase(input) {
|
|
|
37879
38209
|
return { ok: true, content };
|
|
37880
38210
|
} : void 0;
|
|
37881
38211
|
const run4 = async () => {
|
|
37882
|
-
const prep = await prepareFormalPhase(input.root, process.env, input.auth, readSource, withoutPaths(tip ? revisionSource(input.root, tip) : worktreeSource(input.root), isDeniedPath));
|
|
38212
|
+
const prep = await prepareFormalPhase(input.root, process.env, input.auth, readSource, withoutPaths(tip ? revisionSource(input.root, tip) : worktreeSource(input.root), isDeniedPath), { tier: profile.formal.tier });
|
|
37883
38213
|
if (!prep.ok) return skippedOutcome(prep.skip, prep.detail);
|
|
37884
|
-
|
|
38214
|
+
if (process.env.VERITY_FORMAL_VERIFY !== "off") {
|
|
38215
|
+
const ctx = { root: input.root, range: input.range, codeMap: prep.deps.codeMap ?? null };
|
|
38216
|
+
const post = verifyPost(input.auth);
|
|
38217
|
+
prep.deps.verify = (f, v) => verifyFinding(
|
|
38218
|
+
{ file: f.file, symbol: f.symbol, ...v.lines ? { lines: v.lines } : {}, property: { desc: f.desc, kind: f.kind, trace: f.trace }, replayReason: f.reason ?? "", changedLines: v.changedLines },
|
|
38219
|
+
{ executeTools: makeToolExecutor(ctx), localTools: offeredLocalTools(ctx), deadlineAt: v.deadlineAt, costLeftUsd: v.costLeftUsd, post }
|
|
38220
|
+
);
|
|
38221
|
+
}
|
|
38222
|
+
return runFormalPhaseWithin({ root: input.root, files, changedLines, deadlineAt, deps: prep.deps, minScore: profile.formal.minScore, maxRounds: profile.formal.maxRounds, costCapUsd: profile.formal.costCapUsd, maxTargets: profile.formal.maxTargets, relaxedGates: profile.formal.relaxedGates, dailyCap: profile.formal.dailyModels, dailyCostCapUsd: profile.formal.dailyCostUsd });
|
|
37885
38223
|
};
|
|
37886
38224
|
return run4().catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200)));
|
|
37887
38225
|
}
|
|
@@ -38073,6 +38411,9 @@ async function runGuard(opts, globals) {
|
|
|
38073
38411
|
rounds: formalOutcome.model?.rounds ?? null,
|
|
38074
38412
|
properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
|
|
38075
38413
|
findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
|
|
38414
|
+
// Review effort "max" models more than one function: each one, and why the search stopped early.
|
|
38415
|
+
targets: (formalOutcome.targets ?? []).map((t) => `${t.file}#${t.symbol}:${t.status}${t.skip ? `(${t.skip})` : ""}`),
|
|
38416
|
+
stopped_at: formalOutcome.stoppedAt?.skip ?? null,
|
|
38076
38417
|
// Decision 81: what each property rests on (a rule, or "line"), what was
|
|
38077
38418
|
// sent back or dropped as ungrounded, and which counterexamples lack their
|
|
38078
38419
|
// property's trigger (shadow). Ids and rule names only, never code.
|
|
@@ -38229,7 +38570,7 @@ function writeBlockMessage(moment, response, covDetail) {
|
|
|
38229
38570
|
|
|
38230
38571
|
// src/commands/ignore.ts
|
|
38231
38572
|
function registerIgnoreCommand(program2) {
|
|
38232
|
-
const ignore = program2.command("ignore").description("Declare the next turn (or a short window) as housekeeping \u2014 no review needed").option("--turn", "Cover the next turn only (the default)").option("--for <duration>", "Cover a window: 30m, 45s, 1h (max 60m)").option("--reason <reason>", "Why this window needs no review \u2014 required, and recorded").option("--agent", "Mark the declaration as agent-invoked (a ledger label, not a permission)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID)").option("--json", "Output raw JSON").action(async (opts) => {
|
|
38573
|
+
const ignore = program2.command("ignore").description("Declare the next turn (or a short window) as housekeeping \u2014 no review needed").option("--turn", "Cover the next turn only (the default)").option("--for <duration>", "Cover a window: 30m, 45s, 1h (max 60m)").option("--reason <reason>", "Why this window needs no review \u2014 required, and recorded").option("--agent", "Mark the declaration as agent-invoked (a ledger label, not a permission)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").option("--json", "Output raw JSON").action(async (opts) => {
|
|
38233
38574
|
const globals = program2.opts();
|
|
38234
38575
|
const now = Math.floor(Date.now() / 1e3);
|
|
38235
38576
|
const reason = opts.reason?.trim();
|
|
@@ -38256,7 +38597,7 @@ function registerIgnoreCommand(program2) {
|
|
|
38256
38597
|
}
|
|
38257
38598
|
const tokenResult = await resolveToken(globals.token);
|
|
38258
38599
|
const token = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
38259
|
-
const sessionId = opts.sessionId ||
|
|
38600
|
+
const sessionId = opts.sessionId || envSessionId();
|
|
38260
38601
|
const keys = ignoreStateKeys(token, sessionId);
|
|
38261
38602
|
const existing = resolveIgnoreState(keys);
|
|
38262
38603
|
const spent = existing?.state.spent ?? 0;
|
|
@@ -38302,11 +38643,11 @@ function registerIgnoreCommand(program2) {
|
|
|
38302
38643
|
printInfo(`Verity will skip ${window2} \u2014 "${reason}" (${spent + 1}/${IGNORE_BUDGET} this session).`);
|
|
38303
38644
|
printInfo("It covers turns that author nothing. If anything is written, the declaration voids and the review runs.");
|
|
38304
38645
|
});
|
|
38305
|
-
ignore.command("clear").description("Cancel the active declaration (the spent budget is not refunded)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID)").action(async (opts) => {
|
|
38646
|
+
ignore.command("clear").description("Cancel the active declaration (the spent budget is not refunded)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").action(async (opts) => {
|
|
38306
38647
|
const globals = program2.opts();
|
|
38307
38648
|
const tokenResult = await resolveToken(globals.token);
|
|
38308
38649
|
const token = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
38309
|
-
const sessionId = opts.sessionId ||
|
|
38650
|
+
const sessionId = opts.sessionId || envSessionId();
|
|
38310
38651
|
const found = resolveIgnoreState(ignoreStateKeys(token, sessionId));
|
|
38311
38652
|
const active = resolveActive(found?.state ?? null, Math.floor(Date.now() / 1e3));
|
|
38312
38653
|
if (!found || !active) {
|
|
@@ -38321,7 +38662,7 @@ function registerIgnoreCommand(program2) {
|
|
|
38321
38662
|
|
|
38322
38663
|
// src/commands/waive.ts
|
|
38323
38664
|
var import_node_crypto20 = require("node:crypto");
|
|
38324
|
-
var
|
|
38665
|
+
var import_node_fs64 = require("node:fs");
|
|
38325
38666
|
function registerWaiveCommand(program2) {
|
|
38326
38667
|
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) => {
|
|
38327
38668
|
const globals = program2.opts();
|
|
@@ -38350,7 +38691,7 @@ function registerWaiveCommand(program2) {
|
|
|
38350
38691
|
if (opts.file) {
|
|
38351
38692
|
body2.file = opts.file;
|
|
38352
38693
|
try {
|
|
38353
|
-
body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0,
|
|
38694
|
+
body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs64.readFileSync)(opts.file)).digest("hex");
|
|
38354
38695
|
} catch {
|
|
38355
38696
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
38356
38697
|
process.exit(1);
|
|
@@ -38375,10 +38716,10 @@ function registerWaiveCommand(program2) {
|
|
|
38375
38716
|
}
|
|
38376
38717
|
|
|
38377
38718
|
// src/commands/init.ts
|
|
38378
|
-
var
|
|
38719
|
+
var import_node_fs69 = require("node:fs");
|
|
38379
38720
|
var import_promises20 = require("node:fs/promises");
|
|
38380
|
-
var
|
|
38381
|
-
var
|
|
38721
|
+
var import_yaml7 = __toESM2(require_dist());
|
|
38722
|
+
var import_node_path55 = require("node:path");
|
|
38382
38723
|
var import_node_os11 = require("node:os");
|
|
38383
38724
|
var import_node_child_process19 = require("node:child_process");
|
|
38384
38725
|
|
|
@@ -38413,12 +38754,12 @@ function printBanner(opts) {
|
|
|
38413
38754
|
const color = colorEnabled();
|
|
38414
38755
|
const version = `v${cliVersion()}`;
|
|
38415
38756
|
const art = [WORDMARK, WORDMARK_NARROW].find((a) => artWidth(a) <= columns) ?? null;
|
|
38416
|
-
const dim = (
|
|
38757
|
+
const dim = (text2) => color ? `${DIM3}${text2}${RESET2}` : text2;
|
|
38417
38758
|
process.stderr.write("\n");
|
|
38418
38759
|
if (!art) {
|
|
38419
38760
|
const candidates2 = [`Verity ${version}`, "Verity"];
|
|
38420
|
-
const
|
|
38421
|
-
if (
|
|
38761
|
+
const text2 = candidates2.find((c) => c.length + INDENT.length <= columns);
|
|
38762
|
+
if (text2) process.stderr.write(`${INDENT}${dim(text2)}
|
|
38422
38763
|
`);
|
|
38423
38764
|
process.stderr.write("\n");
|
|
38424
38765
|
return;
|
|
@@ -38458,7 +38799,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
38458
38799
|
}
|
|
38459
38800
|
|
|
38460
38801
|
// src/commands/doctor.ts
|
|
38461
|
-
var
|
|
38802
|
+
var import_node_fs65 = require("node:fs");
|
|
38462
38803
|
|
|
38463
38804
|
// src/lib/prereqs.ts
|
|
38464
38805
|
var import_node_child_process16 = require("node:child_process");
|
|
@@ -38666,11 +39007,11 @@ async function buildReport() {
|
|
|
38666
39007
|
const hooks = wiring.status;
|
|
38667
39008
|
const provenance = cliProvenance();
|
|
38668
39009
|
const telemetry = await checkTelemetry();
|
|
38669
|
-
const hasConfig = (0,
|
|
39010
|
+
const hasConfig = (0, import_node_fs65.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
38670
39011
|
const artifacts = {
|
|
38671
|
-
standard: (0,
|
|
39012
|
+
standard: (0, import_node_fs65.existsSync)(projectPath(STANDARD_FILE)),
|
|
38672
39013
|
analysisConfig: hasConfig,
|
|
38673
|
-
verityMd: (0,
|
|
39014
|
+
verityMd: (0, import_node_fs65.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
38674
39015
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
38675
39016
|
};
|
|
38676
39017
|
const next = [];
|
|
@@ -38829,8 +39170,8 @@ function registerDoctorCommand(program2) {
|
|
|
38829
39170
|
}
|
|
38830
39171
|
|
|
38831
39172
|
// src/commands/migrate.ts
|
|
38832
|
-
var
|
|
38833
|
-
var
|
|
39173
|
+
var import_node_fs66 = require("node:fs");
|
|
39174
|
+
var import_node_path52 = require("node:path");
|
|
38834
39175
|
var import_node_child_process17 = require("node:child_process");
|
|
38835
39176
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
38836
39177
|
function defaultNpmRemover(pkg) {
|
|
@@ -38867,12 +39208,12 @@ async function runMigration(opts = {}) {
|
|
|
38867
39208
|
return { actions, migrated: actions.length > 0 };
|
|
38868
39209
|
}
|
|
38869
39210
|
function migrateProjectDir(root, actions) {
|
|
38870
|
-
const gateDir = (0,
|
|
38871
|
-
const verityDir = (0,
|
|
38872
|
-
if ((0,
|
|
39211
|
+
const gateDir = (0, import_node_path52.join)(root, ".gate");
|
|
39212
|
+
const verityDir = (0, import_node_path52.join)(root, ".verity");
|
|
39213
|
+
if ((0, import_node_fs66.existsSync)(gateDir) && !(0, import_node_fs66.existsSync)(verityDir)) {
|
|
38873
39214
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
38874
39215
|
}
|
|
38875
|
-
if ((0,
|
|
39216
|
+
if ((0, import_node_fs66.existsSync)(gateDir) && (0, import_node_fs66.existsSync)(verityDir)) {
|
|
38876
39217
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
38877
39218
|
}
|
|
38878
39219
|
return false;
|
|
@@ -38893,13 +39234,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
38893
39234
|
}
|
|
38894
39235
|
}
|
|
38895
39236
|
if (moved) {
|
|
38896
|
-
if ((0,
|
|
39237
|
+
if ((0, import_node_fs66.existsSync)(gateDir)) {
|
|
38897
39238
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
38898
39239
|
if (carried > 0) {
|
|
38899
39240
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
38900
39241
|
}
|
|
38901
39242
|
try {
|
|
38902
|
-
(0,
|
|
39243
|
+
(0, import_node_fs66.rmSync)(gateDir, { recursive: true, force: true });
|
|
38903
39244
|
} catch {
|
|
38904
39245
|
}
|
|
38905
39246
|
}
|
|
@@ -38915,18 +39256,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
38915
39256
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
38916
39257
|
}
|
|
38917
39258
|
try {
|
|
38918
|
-
(0,
|
|
39259
|
+
(0, import_node_fs66.rmSync)(gateDir, { recursive: true, force: true });
|
|
38919
39260
|
} catch {
|
|
38920
39261
|
}
|
|
38921
39262
|
return carried > 0;
|
|
38922
39263
|
}
|
|
38923
39264
|
function migrateGlobalCredentials(home, actions) {
|
|
38924
39265
|
if (!home) return;
|
|
38925
|
-
const gateCreds = (0,
|
|
38926
|
-
const verityCreds = (0,
|
|
38927
|
-
if (!(0,
|
|
38928
|
-
if (!(0,
|
|
38929
|
-
(0,
|
|
39266
|
+
const gateCreds = (0, import_node_path52.join)(home, ".gate", "credentials");
|
|
39267
|
+
const verityCreds = (0, import_node_path52.join)(home, ".verity", "credentials");
|
|
39268
|
+
if (!(0, import_node_fs66.existsSync)(gateCreds)) return;
|
|
39269
|
+
if (!(0, import_node_fs66.existsSync)(verityCreds)) {
|
|
39270
|
+
(0, import_node_fs66.mkdirSync)((0, import_node_path52.join)(home, ".verity"), { recursive: true });
|
|
38930
39271
|
moveFile(gateCreds, verityCreds);
|
|
38931
39272
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
38932
39273
|
return;
|
|
@@ -38948,8 +39289,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
38948
39289
|
}
|
|
38949
39290
|
}
|
|
38950
39291
|
async function migrateClaudeMd(root, actions) {
|
|
38951
|
-
const claudeMd = (0,
|
|
38952
|
-
const hadLegacyBlock = (0,
|
|
39292
|
+
const claudeMd = (0, import_node_path52.join)(root, "CLAUDE.md");
|
|
39293
|
+
const hadLegacyBlock = (0, import_node_fs66.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
38953
39294
|
if (!hadLegacyBlock) return;
|
|
38954
39295
|
try {
|
|
38955
39296
|
await ensureClaudeMdPointer(root);
|
|
@@ -38959,9 +39300,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
38959
39300
|
}
|
|
38960
39301
|
}
|
|
38961
39302
|
function migrateStandardFile(root, actions) {
|
|
38962
|
-
const gateMd = (0,
|
|
38963
|
-
const verityMd = (0,
|
|
38964
|
-
if (!(0,
|
|
39303
|
+
const gateMd = (0, import_node_path52.join)(root, "GATE.md");
|
|
39304
|
+
const verityMd = (0, import_node_path52.join)(root, "VERITY.md");
|
|
39305
|
+
if (!(0, import_node_fs66.existsSync)(gateMd) || (0, import_node_fs66.existsSync)(verityMd)) return;
|
|
38965
39306
|
let moved = false;
|
|
38966
39307
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
38967
39308
|
try {
|
|
@@ -38973,12 +39314,12 @@ function migrateStandardFile(root, actions) {
|
|
|
38973
39314
|
if (!moved) moveFile(gateMd, verityMd);
|
|
38974
39315
|
const content = readFileSyncSafe(verityMd);
|
|
38975
39316
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
38976
|
-
if (refreshed !== content) (0,
|
|
39317
|
+
if (refreshed !== content) (0, import_node_fs66.writeFileSync)(verityMd, refreshed);
|
|
38977
39318
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
38978
39319
|
}
|
|
38979
39320
|
async function migrateTelemetryHeaders(root, actions) {
|
|
38980
|
-
const file = (0,
|
|
38981
|
-
if (!(0,
|
|
39321
|
+
const file = (0, import_node_path52.join)(root, ".claude", "settings.local.json");
|
|
39322
|
+
if (!(0, import_node_fs66.existsSync)(file)) return;
|
|
38982
39323
|
let settings;
|
|
38983
39324
|
try {
|
|
38984
39325
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -39025,15 +39366,15 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
39025
39366
|
toAppend.push(line2.replace(/\r$/, ""));
|
|
39026
39367
|
}
|
|
39027
39368
|
if (toAppend.length > 0) {
|
|
39028
|
-
const
|
|
39029
|
-
(0,
|
|
39369
|
+
const sep7 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
39370
|
+
(0, import_node_fs66.writeFileSync)(verityCreds, verityContent + sep7 + toAppend.join("\n") + "\n");
|
|
39030
39371
|
}
|
|
39031
|
-
(0,
|
|
39372
|
+
(0, import_node_fs66.rmSync)(gateCreds, { force: true });
|
|
39032
39373
|
return toAppend.length;
|
|
39033
39374
|
}
|
|
39034
39375
|
function readFileSyncSafe(path) {
|
|
39035
39376
|
try {
|
|
39036
|
-
return (0,
|
|
39377
|
+
return (0, import_node_fs66.readFileSync)(path, "utf-8");
|
|
39037
39378
|
} catch {
|
|
39038
39379
|
return "";
|
|
39039
39380
|
}
|
|
@@ -39048,35 +39389,35 @@ function hasStagedChanges(root) {
|
|
|
39048
39389
|
}
|
|
39049
39390
|
function moveDir(from, to) {
|
|
39050
39391
|
try {
|
|
39051
|
-
(0,
|
|
39392
|
+
(0, import_node_fs66.renameSync)(from, to);
|
|
39052
39393
|
} catch (err2) {
|
|
39053
39394
|
if (err2.code !== "EXDEV") throw err2;
|
|
39054
|
-
(0,
|
|
39055
|
-
(0,
|
|
39395
|
+
(0, import_node_fs66.cpSync)(from, to, { recursive: true });
|
|
39396
|
+
(0, import_node_fs66.rmSync)(from, { recursive: true, force: true });
|
|
39056
39397
|
}
|
|
39057
39398
|
}
|
|
39058
39399
|
function moveFile(from, to) {
|
|
39059
39400
|
try {
|
|
39060
|
-
(0,
|
|
39401
|
+
(0, import_node_fs66.renameSync)(from, to);
|
|
39061
39402
|
} catch (err2) {
|
|
39062
39403
|
if (err2.code !== "EXDEV") throw err2;
|
|
39063
|
-
(0,
|
|
39064
|
-
(0,
|
|
39404
|
+
(0, import_node_fs66.cpSync)(from, to);
|
|
39405
|
+
(0, import_node_fs66.rmSync)(from, { force: true });
|
|
39065
39406
|
}
|
|
39066
39407
|
}
|
|
39067
39408
|
function carryLegacyContents(gateDir, verityDir) {
|
|
39068
39409
|
let copied = 0;
|
|
39069
39410
|
const walk2 = (relDir) => {
|
|
39070
|
-
const srcDir = (0,
|
|
39071
|
-
for (const entry of (0,
|
|
39072
|
-
const rel = relDir ? (0,
|
|
39073
|
-
const src = (0,
|
|
39074
|
-
const dest = (0,
|
|
39075
|
-
if ((0,
|
|
39411
|
+
const srcDir = (0, import_node_path52.join)(gateDir, relDir);
|
|
39412
|
+
for (const entry of (0, import_node_fs66.readdirSync)(srcDir)) {
|
|
39413
|
+
const rel = relDir ? (0, import_node_path52.join)(relDir, entry) : entry;
|
|
39414
|
+
const src = (0, import_node_path52.join)(gateDir, rel);
|
|
39415
|
+
const dest = (0, import_node_path52.join)(verityDir, rel);
|
|
39416
|
+
if ((0, import_node_fs66.statSync)(src).isDirectory()) {
|
|
39076
39417
|
walk2(rel);
|
|
39077
|
-
} else if (!(0,
|
|
39078
|
-
(0,
|
|
39079
|
-
(0,
|
|
39418
|
+
} else if (!(0, import_node_fs66.existsSync)(dest)) {
|
|
39419
|
+
(0, import_node_fs66.mkdirSync)((0, import_node_path52.dirname)(dest), { recursive: true });
|
|
39420
|
+
(0, import_node_fs66.cpSync)(src, dest);
|
|
39080
39421
|
copied++;
|
|
39081
39422
|
}
|
|
39082
39423
|
}
|
|
@@ -39085,22 +39426,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
39085
39426
|
return copied;
|
|
39086
39427
|
}
|
|
39087
39428
|
async function needsMigration(root = repoRoot()) {
|
|
39088
|
-
const gateDir = (0,
|
|
39089
|
-
const verityDir = (0,
|
|
39090
|
-
if ((0,
|
|
39091
|
-
if ((0,
|
|
39092
|
-
if ((0,
|
|
39429
|
+
const gateDir = (0, import_node_path52.join)(root, ".gate");
|
|
39430
|
+
const verityDir = (0, import_node_path52.join)(root, ".verity");
|
|
39431
|
+
if ((0, import_node_fs66.existsSync)(gateDir) && !(0, import_node_fs66.existsSync)(verityDir)) return true;
|
|
39432
|
+
if ((0, import_node_fs66.existsSync)(gateDir) && (0, import_node_fs66.existsSync)(verityDir)) {
|
|
39433
|
+
if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(gateDir, "credentials")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(verityDir, "credentials"))) {
|
|
39093
39434
|
return true;
|
|
39094
39435
|
}
|
|
39095
|
-
if ((0,
|
|
39436
|
+
if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(gateDir, "memory")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(verityDir, "memory"))) {
|
|
39096
39437
|
return true;
|
|
39097
39438
|
}
|
|
39098
39439
|
}
|
|
39099
|
-
const claudeMd = (0,
|
|
39100
|
-
if ((0,
|
|
39440
|
+
const claudeMd = (0, import_node_path52.join)(root, "CLAUDE.md");
|
|
39441
|
+
if ((0, import_node_fs66.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
39101
39442
|
return true;
|
|
39102
39443
|
}
|
|
39103
|
-
if ((0,
|
|
39444
|
+
if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(root, "GATE.md")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(root, "VERITY.md"))) {
|
|
39104
39445
|
return true;
|
|
39105
39446
|
}
|
|
39106
39447
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -39202,7 +39543,7 @@ var DIM4 = "\x1B[2m";
|
|
|
39202
39543
|
var BOLD2 = "\x1B[1m";
|
|
39203
39544
|
var RESET3 = "\x1B[0m";
|
|
39204
39545
|
function renderSelect(question, choices, state, mode2, color = colorEnabled()) {
|
|
39205
|
-
const paint = (
|
|
39546
|
+
const paint = (text2, code) => color ? `${code}${text2}${RESET3}` : text2;
|
|
39206
39547
|
const lines = ["", ` ${question}`];
|
|
39207
39548
|
const labelOf = (c) => `${c.label}${c.recommended ? " (recommended)" : ""}`;
|
|
39208
39549
|
const gutter = Math.max(...choices.map((c) => labelOf(c).length));
|
|
@@ -39381,11 +39722,11 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
39381
39722
|
}
|
|
39382
39723
|
|
|
39383
39724
|
// src/lib/prove/lean-install.ts
|
|
39384
|
-
var
|
|
39725
|
+
var import_node_fs67 = require("node:fs");
|
|
39385
39726
|
var import_node_crypto21 = require("node:crypto");
|
|
39386
39727
|
var import_node_child_process18 = require("node:child_process");
|
|
39387
39728
|
var import_node_os10 = require("node:os");
|
|
39388
|
-
var
|
|
39729
|
+
var import_node_path53 = require("node:path");
|
|
39389
39730
|
var import_promises18 = require("node:stream/promises");
|
|
39390
39731
|
var import_node_stream = require("node:stream");
|
|
39391
39732
|
var RELEASES = "https://releases.lean-lang.org/lean4";
|
|
@@ -39396,10 +39737,10 @@ function freeBytes(dir) {
|
|
|
39396
39737
|
let d = dir;
|
|
39397
39738
|
for (let i2 = 0; i2 < 64; i2++) {
|
|
39398
39739
|
try {
|
|
39399
|
-
const st = (0,
|
|
39740
|
+
const st = (0, import_node_fs67.statfsSync)(d);
|
|
39400
39741
|
return Number(st.bavail) * Number(st.bsize);
|
|
39401
39742
|
} catch {
|
|
39402
|
-
const up = (0,
|
|
39743
|
+
const up = (0, import_node_path53.join)(d, "..");
|
|
39403
39744
|
if (up === d) return null;
|
|
39404
39745
|
d = up;
|
|
39405
39746
|
}
|
|
@@ -39421,7 +39762,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
|
|
|
39421
39762
|
function sha256File(path) {
|
|
39422
39763
|
return new Promise((resolve9, reject) => {
|
|
39423
39764
|
const hash = (0, import_node_crypto21.createHash)("sha256");
|
|
39424
|
-
(0,
|
|
39765
|
+
(0, import_node_fs67.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
|
|
39425
39766
|
});
|
|
39426
39767
|
}
|
|
39427
39768
|
async function verifyDownload(zip, asset, version = pinnedVersion()) {
|
|
@@ -39441,7 +39782,7 @@ function leanAssetName(version = pinnedVersion()) {
|
|
|
39441
39782
|
return suffix ? `lean-${v}-${suffix}.zip` : null;
|
|
39442
39783
|
}
|
|
39443
39784
|
function pinnedVersionDir(env = process.env) {
|
|
39444
|
-
return (0,
|
|
39785
|
+
return (0, import_node_path53.join)(verityLeanHome(env), pinnedVersion());
|
|
39445
39786
|
}
|
|
39446
39787
|
function lakeBinary() {
|
|
39447
39788
|
return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
|
|
@@ -39452,12 +39793,12 @@ function unzip(zip, dest) {
|
|
|
39452
39793
|
for (const [cmd, args2] of attempts) {
|
|
39453
39794
|
try {
|
|
39454
39795
|
(0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
|
|
39455
|
-
if ((0,
|
|
39796
|
+
if ((0, import_node_fs67.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
|
|
39456
39797
|
errors.push(`${cmd}: produced nothing`);
|
|
39457
39798
|
} catch (err2) {
|
|
39458
39799
|
errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
|
|
39459
39800
|
try {
|
|
39460
|
-
for (const e of (0,
|
|
39801
|
+
for (const e of (0, import_node_fs67.readdirSync)(dest)) (0, import_node_fs67.rmSync)((0, import_node_path53.join)(dest, e), { recursive: true, force: true });
|
|
39461
39802
|
} catch {
|
|
39462
39803
|
}
|
|
39463
39804
|
}
|
|
@@ -39483,7 +39824,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
|
|
|
39483
39824
|
seen += chunk.length;
|
|
39484
39825
|
onProgress(seen, total);
|
|
39485
39826
|
});
|
|
39486
|
-
await (0, import_promises18.pipeline)(stream, (0,
|
|
39827
|
+
await (0, import_promises18.pipeline)(stream, (0, import_node_fs67.createWriteStream)(dest), { signal: ctrl.signal });
|
|
39487
39828
|
} catch (err2) {
|
|
39488
39829
|
if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
|
|
39489
39830
|
throw err2;
|
|
@@ -39533,10 +39874,10 @@ async function installLean(opts = {}) {
|
|
|
39533
39874
|
const gb = (n) => (n / 1024 ** 3).toFixed(1);
|
|
39534
39875
|
return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
|
|
39535
39876
|
}
|
|
39536
|
-
const tmp = (0,
|
|
39537
|
-
(0,
|
|
39538
|
-
(0,
|
|
39539
|
-
const zip = (0,
|
|
39877
|
+
const tmp = (0, import_node_path53.join)(home, ".tmp");
|
|
39878
|
+
(0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
|
|
39879
|
+
(0, import_node_fs67.mkdirSync)(tmp, { recursive: true });
|
|
39880
|
+
const zip = (0, import_node_path53.join)(tmp, asset);
|
|
39540
39881
|
say(`downloading ${url}`);
|
|
39541
39882
|
let lastPct = -1;
|
|
39542
39883
|
try {
|
|
@@ -39549,41 +39890,41 @@ async function installLean(opts = {}) {
|
|
|
39549
39890
|
}
|
|
39550
39891
|
});
|
|
39551
39892
|
} catch (err2) {
|
|
39552
|
-
(0,
|
|
39893
|
+
(0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
|
|
39553
39894
|
return { ok: false, error: err2.message };
|
|
39554
39895
|
}
|
|
39555
39896
|
say("verifying checksum");
|
|
39556
39897
|
const verified = await verifyDownload(zip, asset);
|
|
39557
39898
|
if (!verified.ok) {
|
|
39558
|
-
(0,
|
|
39899
|
+
(0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
|
|
39559
39900
|
return { ok: false, error: verified.error };
|
|
39560
39901
|
}
|
|
39561
39902
|
say("unpacking (this takes a minute)");
|
|
39562
|
-
const unpack = (0,
|
|
39563
|
-
(0,
|
|
39903
|
+
const unpack = (0, import_node_path53.join)(tmp, "unpack");
|
|
39904
|
+
(0, import_node_fs67.mkdirSync)(unpack);
|
|
39564
39905
|
const unpacked = unzip(zip, unpack);
|
|
39565
39906
|
if (!unpacked.ok) {
|
|
39566
|
-
(0,
|
|
39907
|
+
(0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
|
|
39567
39908
|
return { ok: false, error: `unpack failed: ${unpacked.error}` };
|
|
39568
39909
|
}
|
|
39569
|
-
const entries = (0,
|
|
39570
|
-
const top = entries.length === 1 && (0,
|
|
39571
|
-
if (!(0,
|
|
39572
|
-
(0,
|
|
39910
|
+
const entries = (0, import_node_fs67.readdirSync)(unpack);
|
|
39911
|
+
const top = entries.length === 1 && (0, import_node_fs67.statSync)((0, import_node_path53.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path53.join)(unpack, entries[0]) : unpack;
|
|
39912
|
+
if (!(0, import_node_fs67.existsSync)((0, import_node_path53.join)(top, "bin", lakeBinary()))) {
|
|
39913
|
+
(0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
|
|
39573
39914
|
return { ok: false, error: "the archive did not contain bin/lake" };
|
|
39574
39915
|
}
|
|
39575
|
-
(0,
|
|
39576
|
-
(0,
|
|
39577
|
-
(0,
|
|
39578
|
-
(0,
|
|
39916
|
+
(0, import_node_fs67.rmSync)(dir, { recursive: true, force: true });
|
|
39917
|
+
(0, import_node_fs67.mkdirSync)(home, { recursive: true });
|
|
39918
|
+
(0, import_node_fs67.renameSync)(top, dir);
|
|
39919
|
+
(0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
|
|
39579
39920
|
return { ok: true, dir };
|
|
39580
39921
|
}
|
|
39581
39922
|
|
|
39582
39923
|
// src/lib/remote-config.ts
|
|
39583
|
-
var
|
|
39924
|
+
var import_node_fs68 = require("node:fs");
|
|
39584
39925
|
var import_promises19 = require("node:fs/promises");
|
|
39585
|
-
var
|
|
39586
|
-
var
|
|
39926
|
+
var import_node_path54 = require("node:path");
|
|
39927
|
+
var import_yaml6 = __toESM2(require_dist());
|
|
39587
39928
|
var IGNORE_RIDER = "verityignore";
|
|
39588
39929
|
async function fetchRemoteSetup(opts) {
|
|
39589
39930
|
const standard = await apiRequest({
|
|
@@ -39623,11 +39964,11 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39623
39964
|
const content = { ...found.standard.content };
|
|
39624
39965
|
const rider = typeof content[IGNORE_RIDER] === "string" ? content[IGNORE_RIDER] : null;
|
|
39625
39966
|
delete content[IGNORE_RIDER];
|
|
39626
|
-
await writeOut(STANDARD_FILE, (0,
|
|
39967
|
+
await writeOut(STANDARD_FILE, (0, import_yaml6.stringify)(content));
|
|
39627
39968
|
written.push(STANDARD_FILE);
|
|
39628
39969
|
if (rider !== null) {
|
|
39629
39970
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
39630
|
-
if (!(0,
|
|
39971
|
+
if (!(0, import_node_fs68.existsSync)(localIgnore)) {
|
|
39631
39972
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
39632
39973
|
written.push(VERITYIGNORE_FILE);
|
|
39633
39974
|
} else {
|
|
@@ -39658,9 +39999,9 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39658
39999
|
written.push(VERITY_MD_FILE);
|
|
39659
40000
|
return { written, notes };
|
|
39660
40001
|
}
|
|
39661
|
-
async function writeOut(
|
|
39662
|
-
const target = projectPath(
|
|
39663
|
-
await (0, import_promises19.mkdir)((0,
|
|
40002
|
+
async function writeOut(relative7, body2) {
|
|
40003
|
+
const target = projectPath(relative7);
|
|
40004
|
+
await (0, import_promises19.mkdir)((0, import_node_path54.dirname)(target), { recursive: true });
|
|
39664
40005
|
await (0, import_promises19.writeFile)(target, body2);
|
|
39665
40006
|
}
|
|
39666
40007
|
function describeRemote(found) {
|
|
@@ -39777,15 +40118,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
39777
40118
|
}
|
|
39778
40119
|
function resolveDataDir2() {
|
|
39779
40120
|
const candidates2 = [
|
|
39780
|
-
(0,
|
|
40121
|
+
(0, import_node_path55.join)(__dirname, "..", "data"),
|
|
39781
40122
|
// installed: node_modules/@codacy/verity-cli/data
|
|
39782
|
-
(0,
|
|
40123
|
+
(0, import_node_path55.join)(__dirname, "..", "..", "data"),
|
|
39783
40124
|
// edge case: nested resolution
|
|
39784
|
-
(0,
|
|
40125
|
+
(0, import_node_path55.join)(process.cwd(), "cli", "data")
|
|
39785
40126
|
// local dev: running from repo root
|
|
39786
40127
|
];
|
|
39787
40128
|
for (const candidate of candidates2) {
|
|
39788
|
-
if ((0,
|
|
40129
|
+
if ((0, import_node_fs69.existsSync)((0, import_node_path55.join)(candidate, "skills"))) {
|
|
39789
40130
|
return candidate;
|
|
39790
40131
|
}
|
|
39791
40132
|
}
|
|
@@ -39801,9 +40142,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
39801
40142
|
const list2 = (dir) => {
|
|
39802
40143
|
const out2 = [];
|
|
39803
40144
|
const walk2 = (d, prefix) => {
|
|
39804
|
-
for (const e of (0,
|
|
40145
|
+
for (const e of (0, import_node_fs69.readdirSync)(d, { withFileTypes: true })) {
|
|
39805
40146
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
39806
|
-
if (e.isDirectory()) walk2((0,
|
|
40147
|
+
if (e.isDirectory()) walk2((0, import_node_path55.join)(d, e.name), rel);
|
|
39807
40148
|
else if (e.isFile()) out2.push(rel);
|
|
39808
40149
|
}
|
|
39809
40150
|
};
|
|
@@ -39814,8 +40155,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
39814
40155
|
const shipped = list2(src);
|
|
39815
40156
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
39816
40157
|
for (const rel of shipped) {
|
|
39817
|
-
const a = await (0, import_promises20.readFile)((0,
|
|
39818
|
-
const b = await (0, import_promises20.readFile)((0,
|
|
40158
|
+
const a = await (0, import_promises20.readFile)((0, import_node_path55.join)(src, rel), "utf-8");
|
|
40159
|
+
const b = await (0, import_promises20.readFile)((0, import_node_path55.join)(dest, rel), "utf-8");
|
|
39819
40160
|
if (a !== b) return false;
|
|
39820
40161
|
}
|
|
39821
40162
|
return true;
|
|
@@ -39911,7 +40252,7 @@ function parseTelemetryAnswer(raw) {
|
|
|
39911
40252
|
return null;
|
|
39912
40253
|
}
|
|
39913
40254
|
function insideClaudeCode() {
|
|
39914
|
-
return !!process.env.CLAUDECODE || !!
|
|
40255
|
+
return !!process.env.CLAUDECODE || !!envSessionId();
|
|
39915
40256
|
}
|
|
39916
40257
|
function resumeDeferredPending(previous) {
|
|
39917
40258
|
return previous?.telemetry === "deferred";
|
|
@@ -40018,13 +40359,13 @@ async function synthesizeLocally(opts) {
|
|
|
40018
40359
|
async function healStaleAnalysisConfig(globals) {
|
|
40019
40360
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
40020
40361
|
const standardPath = projectPath(STANDARD_FILE);
|
|
40021
|
-
if (!(0,
|
|
40362
|
+
if (!(0, import_node_fs69.existsSync)(configPath) || !(0, import_node_fs69.existsSync)(standardPath)) return;
|
|
40022
40363
|
const validation = validatePatternIds();
|
|
40023
40364
|
if (validation.status !== "invalid") return;
|
|
40024
40365
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
40025
40366
|
printWarn(" running silently with nothing enabled. Re-deriving it from your Standard\u2026");
|
|
40026
40367
|
try {
|
|
40027
|
-
const content = (0,
|
|
40368
|
+
const content = (0, import_yaml7.parse)(await (0, import_promises20.readFile)(standardPath, "utf-8"));
|
|
40028
40369
|
const derived = await deriveConfigForStandard(content);
|
|
40029
40370
|
for (const path of derived.written) printInfo(` ${path} \u2713 (re-derived)`);
|
|
40030
40371
|
for (const note of derived.notes) printWarn(` ${note}`);
|
|
@@ -40115,17 +40456,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
40115
40456
|
async function installSkills(force, step) {
|
|
40116
40457
|
step("Installing skills");
|
|
40117
40458
|
const dataDir = resolveDataDir2();
|
|
40118
|
-
const skillsSource = (0,
|
|
40459
|
+
const skillsSource = (0, import_node_path55.join)(dataDir, "skills");
|
|
40119
40460
|
const skillsDest = ".claude/skills";
|
|
40120
40461
|
let skillsInstalled = 0;
|
|
40121
40462
|
for (const skill of SKILLS) {
|
|
40122
|
-
const src = (0,
|
|
40123
|
-
const dest = (0,
|
|
40124
|
-
if (!(0,
|
|
40463
|
+
const src = (0, import_node_path55.join)(skillsSource, skill);
|
|
40464
|
+
const dest = (0, import_node_path55.join)(skillsDest, skill);
|
|
40465
|
+
if (!(0, import_node_fs69.existsSync)(src)) {
|
|
40125
40466
|
printWarn(` Skill data not found: ${skill}`);
|
|
40126
40467
|
continue;
|
|
40127
40468
|
}
|
|
40128
|
-
if ((0,
|
|
40469
|
+
if ((0, import_node_fs69.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
40129
40470
|
skillsInstalled++;
|
|
40130
40471
|
continue;
|
|
40131
40472
|
}
|
|
@@ -40274,7 +40615,7 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
|
|
|
40274
40615
|
if (!toolchain) {
|
|
40275
40616
|
const dir = pinnedVersionDir();
|
|
40276
40617
|
const home = (0, import_node_os11.homedir)();
|
|
40277
|
-
const shown = dir.startsWith(home +
|
|
40618
|
+
const shown = dir.startsWith(home + import_node_path55.sep) ? `~${dir.slice(home.length)}` : dir;
|
|
40278
40619
|
console.log("");
|
|
40279
40620
|
console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
|
|
40280
40621
|
}
|
|
@@ -40333,7 +40674,7 @@ function registerInitCommand(program2) {
|
|
|
40333
40674
|
const staleMarker = clearStalePluginMarker();
|
|
40334
40675
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
40335
40676
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
40336
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
40677
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs69.existsSync)(m));
|
|
40337
40678
|
if (!isProject) {
|
|
40338
40679
|
printError("No project detected in the current directory.");
|
|
40339
40680
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -40436,7 +40777,7 @@ function registerInitCommand(program2) {
|
|
|
40436
40777
|
untrackMemory: opts.untrackMemory === true,
|
|
40437
40778
|
untrackState: opts.untrackState === true
|
|
40438
40779
|
});
|
|
40439
|
-
const globalVerityDir = (0,
|
|
40780
|
+
const globalVerityDir = (0, import_node_path55.join)(process.env.HOME ?? "", ".verity");
|
|
40440
40781
|
await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
|
|
40441
40782
|
console.log("");
|
|
40442
40783
|
step("Wiring Claude Code hooks");
|
|
@@ -40511,7 +40852,7 @@ function registerInitCommand(program2) {
|
|
|
40511
40852
|
}
|
|
40512
40853
|
step("Your project's Standard");
|
|
40513
40854
|
let haveStandard = false;
|
|
40514
|
-
if ((0,
|
|
40855
|
+
if ((0, import_node_fs69.existsSync)(projectPath(STANDARD_FILE))) {
|
|
40515
40856
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
40516
40857
|
haveStandard = true;
|
|
40517
40858
|
} else {
|
|
@@ -40541,7 +40882,7 @@ function registerInitCommand(program2) {
|
|
|
40541
40882
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
40542
40883
|
init: {
|
|
40543
40884
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40544
|
-
cli_version: true ? "0.34.
|
|
40885
|
+
cli_version: true ? "0.34.2-experimental.2cad220" : "dev"
|
|
40545
40886
|
}
|
|
40546
40887
|
});
|
|
40547
40888
|
} catch (err2) {
|
|
@@ -40591,8 +40932,8 @@ function registerInitCommand(program2) {
|
|
|
40591
40932
|
}
|
|
40592
40933
|
|
|
40593
40934
|
// src/commands/uninstall.ts
|
|
40594
|
-
var
|
|
40595
|
-
var
|
|
40935
|
+
var import_node_fs70 = require("node:fs");
|
|
40936
|
+
var import_node_path56 = require("node:path");
|
|
40596
40937
|
function registerUninstallCommand(program2) {
|
|
40597
40938
|
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) => {
|
|
40598
40939
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -40601,11 +40942,11 @@ function registerUninstallCommand(program2) {
|
|
|
40601
40942
|
const actions = [];
|
|
40602
40943
|
const skillsRoot = projectPath(".claude/skills");
|
|
40603
40944
|
for (const name2 of PROJECT_SKILL_NAMES) {
|
|
40604
|
-
const dir = (0,
|
|
40605
|
-
if ((0,
|
|
40945
|
+
const dir = (0, import_node_path56.join)(skillsRoot, name2);
|
|
40946
|
+
if ((0, import_node_fs70.existsSync)(dir)) {
|
|
40606
40947
|
actions.push({
|
|
40607
40948
|
label: `Remove .claude/skills/${name2}/`,
|
|
40608
|
-
apply: () => (0,
|
|
40949
|
+
apply: () => (0, import_node_fs70.rmSync)(dir, { recursive: true, force: true })
|
|
40609
40950
|
});
|
|
40610
40951
|
}
|
|
40611
40952
|
}
|
|
@@ -40619,24 +40960,24 @@ function registerUninstallCommand(program2) {
|
|
|
40619
40960
|
});
|
|
40620
40961
|
}
|
|
40621
40962
|
const verityDir = projectPath(VERITY_DIR);
|
|
40622
|
-
if ((0,
|
|
40963
|
+
if ((0, import_node_fs70.existsSync)(verityDir)) {
|
|
40623
40964
|
actions.push({
|
|
40624
40965
|
label: `Remove ${VERITY_DIR}/`,
|
|
40625
|
-
apply: () => (0,
|
|
40966
|
+
apply: () => (0, import_node_fs70.rmSync)(verityDir, { recursive: true, force: true })
|
|
40626
40967
|
});
|
|
40627
40968
|
}
|
|
40628
40969
|
if (!keepVerityMd) {
|
|
40629
40970
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
40630
|
-
if ((0,
|
|
40971
|
+
if ((0, import_node_fs70.existsSync)(verityMd)) {
|
|
40631
40972
|
actions.push({
|
|
40632
40973
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
40633
|
-
apply: () => (0,
|
|
40974
|
+
apply: () => (0, import_node_fs70.rmSync)(verityMd, { force: true })
|
|
40634
40975
|
});
|
|
40635
40976
|
}
|
|
40636
40977
|
}
|
|
40637
40978
|
const cleanupEmptyDir = (path) => {
|
|
40638
|
-
if ((0,
|
|
40639
|
-
(0,
|
|
40979
|
+
if ((0, import_node_fs70.existsSync)(path) && (0, import_node_fs70.statSync)(path).isDirectory() && (0, import_node_fs70.readdirSync)(path).length === 0) {
|
|
40980
|
+
(0, import_node_fs70.rmdirSync)(path);
|
|
40640
40981
|
}
|
|
40641
40982
|
};
|
|
40642
40983
|
actions.push({
|
|
@@ -40647,11 +40988,11 @@ function registerUninstallCommand(program2) {
|
|
|
40647
40988
|
}
|
|
40648
40989
|
});
|
|
40649
40990
|
const home = process.env.HOME ?? "";
|
|
40650
|
-
const globalVerityDir = (0,
|
|
40651
|
-
if (purgeGlobal && (0,
|
|
40991
|
+
const globalVerityDir = (0, import_node_path56.join)(home, ".verity");
|
|
40992
|
+
if (purgeGlobal && (0, import_node_fs70.existsSync)(globalVerityDir)) {
|
|
40652
40993
|
actions.push({
|
|
40653
40994
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
40654
|
-
apply: () => (0,
|
|
40995
|
+
apply: () => (0, import_node_fs70.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
40655
40996
|
});
|
|
40656
40997
|
}
|
|
40657
40998
|
if (actions.length === 0) {
|
|
@@ -40678,9 +41019,26 @@ function registerUninstallCommand(program2) {
|
|
|
40678
41019
|
|
|
40679
41020
|
// src/commands/task.ts
|
|
40680
41021
|
function memoryPath() {
|
|
40681
|
-
const sid =
|
|
41022
|
+
const sid = envSessionId();
|
|
40682
41023
|
return sid ? `/memory?session_id=${encodeURIComponent(sid)}` : "/memory";
|
|
40683
41024
|
}
|
|
41025
|
+
var TASK_STATUSES = ["active", "closed", "merged"];
|
|
41026
|
+
var TASK_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
41027
|
+
function isTaskId(value) {
|
|
41028
|
+
return typeof value === "string" && TASK_ID.test(value);
|
|
41029
|
+
}
|
|
41030
|
+
function taskListPath(status) {
|
|
41031
|
+
if (status === void 0) return "/tasks";
|
|
41032
|
+
if (!TASK_STATUSES.includes(status)) return null;
|
|
41033
|
+
return `/tasks?status=${encodeURIComponent(status)}`;
|
|
41034
|
+
}
|
|
41035
|
+
function taskActionPath(taskId, action) {
|
|
41036
|
+
return isTaskId(taskId) ? `/tasks/${encodeURIComponent(taskId)}/${action}` : null;
|
|
41037
|
+
}
|
|
41038
|
+
function refuse(message) {
|
|
41039
|
+
printError(message);
|
|
41040
|
+
process.exit(1);
|
|
41041
|
+
}
|
|
40684
41042
|
function timeAgo2(isoDate) {
|
|
40685
41043
|
const ms = Date.now() - new Date(isoDate).getTime();
|
|
40686
41044
|
const mins = Math.floor(ms / 6e4);
|
|
@@ -40708,10 +41066,11 @@ function registerTaskCommands(program2) {
|
|
|
40708
41066
|
task.command("list").description("List tasks").option("--status <status>", "Filter by status (active, closed, merged)").action(async (opts) => {
|
|
40709
41067
|
const globals = program2.opts();
|
|
40710
41068
|
const { token, serviceUrl } = await getAuth(globals);
|
|
40711
|
-
const
|
|
41069
|
+
const listPath = taskListPath(opts.status);
|
|
41070
|
+
if (!listPath) refuse(`Unknown status ${JSON.stringify(String(opts.status).slice(0, 40))} \u2014 use one of: ${TASK_STATUSES.join(", ")}`);
|
|
40712
41071
|
const result = await apiRequest({
|
|
40713
41072
|
method: "GET",
|
|
40714
|
-
path:
|
|
41073
|
+
path: listPath,
|
|
40715
41074
|
serviceUrl,
|
|
40716
41075
|
token,
|
|
40717
41076
|
verbose: globals.verbose,
|
|
@@ -40760,9 +41119,11 @@ function registerTaskCommands(program2) {
|
|
|
40760
41119
|
}
|
|
40761
41120
|
taskId = ct.id;
|
|
40762
41121
|
}
|
|
41122
|
+
const closePath = taskActionPath(taskId, "close");
|
|
41123
|
+
if (!closePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
|
|
40763
41124
|
const result = await apiRequest({
|
|
40764
41125
|
method: "POST",
|
|
40765
|
-
path:
|
|
41126
|
+
path: closePath,
|
|
40766
41127
|
serviceUrl,
|
|
40767
41128
|
token,
|
|
40768
41129
|
verbose: globals.verbose,
|
|
@@ -40809,9 +41170,11 @@ function registerTaskCommands(program2) {
|
|
|
40809
41170
|
}
|
|
40810
41171
|
taskId = ct.id;
|
|
40811
41172
|
}
|
|
41173
|
+
const renamePath = taskActionPath(taskId, "rename");
|
|
41174
|
+
if (!renamePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
|
|
40812
41175
|
const result = await apiRequest({
|
|
40813
41176
|
method: "POST",
|
|
40814
|
-
path:
|
|
41177
|
+
path: renamePath,
|
|
40815
41178
|
serviceUrl,
|
|
40816
41179
|
token,
|
|
40817
41180
|
body: { label: label2.slice(0, 120) },
|
|
@@ -40826,6 +41189,9 @@ function registerTaskCommands(program2) {
|
|
|
40826
41189
|
});
|
|
40827
41190
|
task.command("merge <source> <target>").description("Merge source task into target task").action(async (source2, target) => {
|
|
40828
41191
|
const globals = program2.opts();
|
|
41192
|
+
if (!isTaskId(source2) || !isTaskId(target)) {
|
|
41193
|
+
refuse("task merge takes two task ids (UUIDs): `verity task merge <source> <target>`");
|
|
41194
|
+
}
|
|
40829
41195
|
const { token, serviceUrl } = await getAuth(globals);
|
|
40830
41196
|
const result = await apiRequest({
|
|
40831
41197
|
method: "POST",
|
|
@@ -40845,8 +41211,8 @@ function registerTaskCommands(program2) {
|
|
|
40845
41211
|
}
|
|
40846
41212
|
|
|
40847
41213
|
// src/commands/reset.ts
|
|
40848
|
-
var
|
|
40849
|
-
var
|
|
41214
|
+
var import_node_fs71 = require("node:fs");
|
|
41215
|
+
var import_node_path57 = require("node:path");
|
|
40850
41216
|
function registerResetCommand(program2) {
|
|
40851
41217
|
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) => {
|
|
40852
41218
|
const globals = program2.opts();
|
|
@@ -40855,78 +41221,95 @@ function registerResetCommand(program2) {
|
|
|
40855
41221
|
const tokenResult = await resolveToken(globals.token);
|
|
40856
41222
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
40857
41223
|
if (tokenResult.ok && urlResult.ok) {
|
|
41224
|
+
const sessionId = envSessionId();
|
|
40858
41225
|
const mem = await apiRequest({
|
|
40859
41226
|
method: "GET",
|
|
40860
|
-
path:
|
|
41227
|
+
path: sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory",
|
|
40861
41228
|
serviceUrl: urlResult.data,
|
|
40862
41229
|
token: tokenResult.data.token,
|
|
40863
41230
|
timeout: 1e4,
|
|
40864
41231
|
cmd: "reset_lookup"
|
|
40865
41232
|
});
|
|
40866
41233
|
const ct = mem.ok ? mem.data.current_task : null;
|
|
40867
|
-
|
|
41234
|
+
const closePath = ct?.id ? taskActionPath(ct.id, "close") : null;
|
|
41235
|
+
if (ct?.id && !closePath) {
|
|
41236
|
+
printError("The current task in the service response has a malformed id \u2014 not closing it.");
|
|
41237
|
+
}
|
|
41238
|
+
if (closePath) {
|
|
40868
41239
|
const closeResult = await apiRequest({
|
|
40869
41240
|
method: "POST",
|
|
40870
|
-
path:
|
|
41241
|
+
path: closePath,
|
|
40871
41242
|
serviceUrl: urlResult.data,
|
|
40872
41243
|
token: tokenResult.data.token,
|
|
40873
41244
|
timeout: 1e4,
|
|
40874
41245
|
cmd: "reset_close"
|
|
40875
41246
|
});
|
|
40876
41247
|
if (closeResult.ok) {
|
|
40877
|
-
printInfo(`Closed task: "${ct
|
|
41248
|
+
printInfo(`Closed task: "${terminalText(ct?.label, 200) || "(unnamed)"}"`);
|
|
40878
41249
|
}
|
|
40879
41250
|
}
|
|
40880
41251
|
}
|
|
40881
41252
|
} catch {
|
|
40882
41253
|
}
|
|
40883
41254
|
}
|
|
40884
|
-
const
|
|
40885
|
-
|
|
40886
|
-
|
|
40887
|
-
for (const entry of (0, import_node_fs70.readdirSync)(cacheDir)) {
|
|
40888
|
-
if (entry.startsWith("pending-")) {
|
|
40889
|
-
try {
|
|
40890
|
-
(0, import_node_fs70.unlinkSync)((0, import_node_path55.join)(cacheDir, entry));
|
|
40891
|
-
purged++;
|
|
40892
|
-
} catch {
|
|
40893
|
-
}
|
|
40894
|
-
}
|
|
40895
|
-
}
|
|
40896
|
-
}
|
|
41255
|
+
const purged = purgeVerityDir((0, import_node_path57.basename)(CACHE_DIR), (name2) => name2.startsWith("pending-"));
|
|
41256
|
+
if (purged === null) printError(`Did not purge ${CACHE_DIR}: it is not a directory inside ${VERITY_DIR}.`);
|
|
41257
|
+
const stateDir2 = projectPath(VERITY_DIR);
|
|
40897
41258
|
const filesToClear = [
|
|
40898
|
-
|
|
40899
|
-
|
|
40900
|
-
|
|
40901
|
-
|
|
40902
|
-
|
|
41259
|
+
(0, import_node_path57.basename)(INTENT_FILE),
|
|
41260
|
+
(0, import_node_path57.basename)(HASH_FILE),
|
|
41261
|
+
(0, import_node_path57.basename)(BASELINE_SHA_FILE),
|
|
41262
|
+
".iteration-count",
|
|
41263
|
+
".last-analysis"
|
|
40903
41264
|
];
|
|
40904
|
-
for (const
|
|
40905
|
-
if ((0,
|
|
40906
|
-
|
|
40907
|
-
(0, import_node_fs70.writeFileSync)(file, "");
|
|
40908
|
-
} catch {
|
|
40909
|
-
}
|
|
41265
|
+
for (const name2 of filesToClear) {
|
|
41266
|
+
if (lstatOrNull((0, import_node_path57.join)(stateDir2, name2)) && !replaceInRoot(stateDir2, name2, "")) {
|
|
41267
|
+
printError(`Did not clear ${VERITY_DIR}/${name2}: it is not a regular file inside ${VERITY_DIR}.`);
|
|
40910
41268
|
}
|
|
40911
41269
|
}
|
|
40912
41270
|
if (opts.all) {
|
|
40913
|
-
const
|
|
40914
|
-
if (
|
|
40915
|
-
|
|
40916
|
-
try {
|
|
40917
|
-
(0, import_node_fs70.unlinkSync)((0, import_node_path55.join)(logsDir, entry));
|
|
40918
|
-
} catch {
|
|
40919
|
-
}
|
|
40920
|
-
}
|
|
40921
|
-
}
|
|
40922
|
-
printInfo("Cleared diagnostic logs.");
|
|
41271
|
+
const logs = purgeVerityDir(".logs", () => true);
|
|
41272
|
+
if (logs === null) printError(`Did not clear ${VERITY_DIR}/.logs: it is not a directory inside ${VERITY_DIR}.`);
|
|
41273
|
+
else printInfo("Cleared diagnostic logs.");
|
|
40923
41274
|
}
|
|
40924
|
-
|
|
41275
|
+
const count = purged ?? 0;
|
|
41276
|
+
printInfo(`Reset complete. Purged ${count} cached request${count !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
|
|
40925
41277
|
});
|
|
40926
41278
|
}
|
|
41279
|
+
function lstatOrNull(path) {
|
|
41280
|
+
try {
|
|
41281
|
+
return (0, import_node_fs71.lstatSync)(path);
|
|
41282
|
+
} catch {
|
|
41283
|
+
return null;
|
|
41284
|
+
}
|
|
41285
|
+
}
|
|
41286
|
+
function purgeVerityDir(child, select) {
|
|
41287
|
+
const verityDir = projectPath(VERITY_DIR);
|
|
41288
|
+
const dir = (0, import_node_path57.join)(verityDir, child);
|
|
41289
|
+
const parent = lstatOrNull(verityDir);
|
|
41290
|
+
const st = lstatOrNull(dir);
|
|
41291
|
+
if (!st) return 0;
|
|
41292
|
+
if (!parent || parent.isSymbolicLink() || !parent.isDirectory()) return null;
|
|
41293
|
+
if (st.isSymbolicLink() || !st.isDirectory()) return null;
|
|
41294
|
+
try {
|
|
41295
|
+
if ((0, import_node_fs71.realpathSync)(dir) !== (0, import_node_path57.join)((0, import_node_fs71.realpathSync)(verityDir), child)) return null;
|
|
41296
|
+
} catch {
|
|
41297
|
+
return null;
|
|
41298
|
+
}
|
|
41299
|
+
let removed = 0;
|
|
41300
|
+
for (const entry of (0, import_node_fs71.readdirSync)(dir, { withFileTypes: true })) {
|
|
41301
|
+
if (entry.isDirectory() || !select(entry.name)) continue;
|
|
41302
|
+
try {
|
|
41303
|
+
(0, import_node_fs71.unlinkSync)((0, import_node_path57.join)(dir, entry.name));
|
|
41304
|
+
removed++;
|
|
41305
|
+
} catch {
|
|
41306
|
+
}
|
|
41307
|
+
}
|
|
41308
|
+
return removed;
|
|
41309
|
+
}
|
|
40927
41310
|
|
|
40928
41311
|
// src/commands/reflect.ts
|
|
40929
|
-
var
|
|
41312
|
+
var import_node_fs72 = require("node:fs");
|
|
40930
41313
|
|
|
40931
41314
|
// src/lib/reflection-globs.ts
|
|
40932
41315
|
var MAX_GLOBS = 6;
|
|
@@ -40940,11 +41323,11 @@ function resolve7(token, treePaths) {
|
|
|
40940
41323
|
const matches = treePaths.filter((p) => p.endsWith(suffix));
|
|
40941
41324
|
return matches.length === 1 ? matches[0] : null;
|
|
40942
41325
|
}
|
|
40943
|
-
function deriveFileGlobs(
|
|
40944
|
-
if (!
|
|
41326
|
+
function deriveFileGlobs(text2, treePaths) {
|
|
41327
|
+
if (!text2 || treePaths.length === 0) return [];
|
|
40945
41328
|
const out2 = [];
|
|
40946
41329
|
const seen = /* @__PURE__ */ new Set();
|
|
40947
|
-
for (const raw of
|
|
41330
|
+
for (const raw of text2.match(PATH_TOKEN) ?? []) {
|
|
40948
41331
|
const token = clean(raw);
|
|
40949
41332
|
if (!token) continue;
|
|
40950
41333
|
const path = resolve7(token, treePaths);
|
|
@@ -40964,7 +41347,7 @@ async function writeNodeToDisk(args2) {
|
|
|
40964
41347
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
40965
41348
|
);
|
|
40966
41349
|
if (written === 0) return false;
|
|
40967
|
-
return (0,
|
|
41350
|
+
return (0, import_node_fs72.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
|
|
40968
41351
|
} catch {
|
|
40969
41352
|
return false;
|
|
40970
41353
|
}
|
|
@@ -40995,7 +41378,7 @@ function registerReflectCommand(program2) {
|
|
|
40995
41378
|
let taskResolution = "flag";
|
|
40996
41379
|
let inheritedGlobs = [];
|
|
40997
41380
|
if (!taskId) {
|
|
40998
|
-
const sessionId =
|
|
41381
|
+
const sessionId = envSessionId() ?? "";
|
|
40999
41382
|
const memPath = sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory";
|
|
41000
41383
|
const mem = await apiRequest({
|
|
41001
41384
|
method: "GET",
|
|
@@ -41401,9 +41784,9 @@ function registerRunCommand(program2) {
|
|
|
41401
41784
|
}
|
|
41402
41785
|
|
|
41403
41786
|
// src/commands/telemetry.ts
|
|
41404
|
-
var
|
|
41787
|
+
var import_node_fs73 = require("node:fs");
|
|
41405
41788
|
async function recordTelemetryChoice(choice) {
|
|
41406
|
-
if (!(0,
|
|
41789
|
+
if (!(0, import_node_fs73.existsSync)(projectPath(SETUP_STATE_FILE))) return;
|
|
41407
41790
|
try {
|
|
41408
41791
|
if ((await readSetupState())?.telemetry === choice) return;
|
|
41409
41792
|
await writeSetupState({ telemetry: choice });
|
|
@@ -41480,8 +41863,8 @@ function registerTelemetryCommands(program2) {
|
|
|
41480
41863
|
}
|
|
41481
41864
|
|
|
41482
41865
|
// src/commands/prove.ts
|
|
41483
|
-
var
|
|
41484
|
-
var
|
|
41866
|
+
var import_node_fs74 = require("node:fs");
|
|
41867
|
+
var import_node_path58 = require("node:path");
|
|
41485
41868
|
|
|
41486
41869
|
// src/lib/prove/hint-pool.ts
|
|
41487
41870
|
var STOP2 = /* @__PURE__ */ new Set([
|
|
@@ -41623,7 +42006,7 @@ function registerProveCommand(program2) {
|
|
|
41623
42006
|
process.exit(2);
|
|
41624
42007
|
}
|
|
41625
42008
|
const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
|
|
41626
|
-
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0,
|
|
42009
|
+
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path58.relative)(root, (0, import_node_path58.resolve)(p)) || ".") });
|
|
41627
42010
|
if (opts.hint && paths.length === 0) {
|
|
41628
42011
|
const hit = hintMatches(root, opts.hint);
|
|
41629
42012
|
if (hit.files.length > 0) {
|
|
@@ -41677,7 +42060,7 @@ function registerProveCommand(program2) {
|
|
|
41677
42060
|
});
|
|
41678
42061
|
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) => {
|
|
41679
42062
|
const root = repoRoot();
|
|
41680
|
-
if (!(0,
|
|
42063
|
+
if (!(0, import_node_fs74.existsSync)((0, import_node_path58.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41681
42064
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41682
42065
|
process.exit(2);
|
|
41683
42066
|
}
|
|
@@ -41701,7 +42084,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41701
42084
|
const reports = [];
|
|
41702
42085
|
for (const f of files) {
|
|
41703
42086
|
const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
|
|
41704
|
-
report.file = (0,
|
|
42087
|
+
report.file = (0, import_node_path58.relative)(root, f);
|
|
41705
42088
|
reports.push(report);
|
|
41706
42089
|
try {
|
|
41707
42090
|
writeResult(root, report);
|
|
@@ -41739,7 +42122,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41739
42122
|
printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
|
|
41740
42123
|
process.exit(2);
|
|
41741
42124
|
}
|
|
41742
|
-
if (!(0,
|
|
42125
|
+
if (!(0, import_node_fs74.existsSync)((0, import_node_path58.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41743
42126
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41744
42127
|
process.exit(2);
|
|
41745
42128
|
}
|
|
@@ -41770,7 +42153,7 @@ ${report.error ?? ""}`);
|
|
|
41770
42153
|
printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
|
|
41771
42154
|
return;
|
|
41772
42155
|
}
|
|
41773
|
-
const modelSource = readRegularFileInRoot(root, (0,
|
|
42156
|
+
const modelSource = readRegularFileInRoot(root, (0, import_node_path58.relative)(root, file), 512 * 1024);
|
|
41774
42157
|
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`);
|
|
41775
42158
|
const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
|
|
41776
42159
|
const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
|
|
@@ -41790,7 +42173,7 @@ ${report.error ?? ""}`);
|
|
|
41790
42173
|
});
|
|
41791
42174
|
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) => {
|
|
41792
42175
|
const root = repoRoot();
|
|
41793
|
-
let files = paths.map((p) => (0,
|
|
42176
|
+
let files = paths.map((p) => (0, import_node_path58.relative)(root, (0, import_node_path58.resolve)(p)));
|
|
41794
42177
|
if (files.length === 0) {
|
|
41795
42178
|
const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
|
|
41796
42179
|
const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
|
|
@@ -41864,7 +42247,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41864
42247
|
let revise;
|
|
41865
42248
|
if (opts.revise) {
|
|
41866
42249
|
const existing = resolveModelFile(root, opts.revise);
|
|
41867
|
-
const src = existing ? readRegularFileInRoot(root, (0,
|
|
42250
|
+
const src = existing ? readRegularFileInRoot(root, (0, import_node_path58.relative)(root, existing), 64 * 1024) : null;
|
|
41868
42251
|
if (!src || !src.ok || !opts.note) {
|
|
41869
42252
|
printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
|
|
41870
42253
|
process.exit(2);
|
|
@@ -41904,8 +42287,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41904
42287
|
});
|
|
41905
42288
|
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) => {
|
|
41906
42289
|
const root = repoRoot();
|
|
41907
|
-
const rel0 = (0,
|
|
41908
|
-
const rel = rel0.startsWith("..") || (0,
|
|
42290
|
+
const rel0 = (0, import_node_path58.relative)(root, (0, import_node_path58.isAbsolute)(file) ? file : (0, import_node_path58.join)(root, file)).replace(/\\/g, "/");
|
|
42291
|
+
const rel = rel0.startsWith("..") || (0, import_node_path58.isAbsolute)(rel0) ? null : rel0;
|
|
41909
42292
|
if (!rel) {
|
|
41910
42293
|
printError(`${file} is not inside this repository`);
|
|
41911
42294
|
process.exit(2);
|
|
@@ -41921,8 +42304,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41921
42304
|
});
|
|
41922
42305
|
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) => {
|
|
41923
42306
|
const root = repoRoot();
|
|
41924
|
-
const rel = (0,
|
|
41925
|
-
const digest = rel.startsWith("..") || (0,
|
|
42307
|
+
const rel = (0, import_node_path58.relative)(root, (0, import_node_path58.isAbsolute)(file) ? file : (0, import_node_path58.join)(root, file));
|
|
42308
|
+
const digest = rel.startsWith("..") || (0, import_node_path58.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
|
|
41926
42309
|
if (!digest) {
|
|
41927
42310
|
printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
|
|
41928
42311
|
process.exit(2);
|
|
@@ -41956,10 +42339,10 @@ function refreshScaffold(root) {
|
|
|
41956
42339
|
}
|
|
41957
42340
|
|
|
41958
42341
|
// src/commands/lean.ts
|
|
41959
|
-
var
|
|
42342
|
+
var import_node_fs75 = require("node:fs");
|
|
41960
42343
|
var import_node_child_process20 = require("node:child_process");
|
|
41961
42344
|
var import_node_os12 = require("node:os");
|
|
41962
|
-
var
|
|
42345
|
+
var import_node_path59 = require("node:path");
|
|
41963
42346
|
function registerLeanCommand(program2) {
|
|
41964
42347
|
const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
|
|
41965
42348
|
lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
|
|
@@ -41976,7 +42359,7 @@ function registerLeanCommand(program2) {
|
|
|
41976
42359
|
const managed = pinnedVersionDir();
|
|
41977
42360
|
const matches = version ? version.includes(pin) : false;
|
|
41978
42361
|
if (opts.json) {
|
|
41979
|
-
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0,
|
|
42362
|
+
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs75.existsSync)((0, import_node_path59.join)(managed, "bin")), asset: leanAssetName() });
|
|
41980
42363
|
return;
|
|
41981
42364
|
}
|
|
41982
42365
|
printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
|
|
@@ -41994,7 +42377,7 @@ function registerLeanCommand(program2) {
|
|
|
41994
42377
|
process.exit(2);
|
|
41995
42378
|
}
|
|
41996
42379
|
const dir = pinnedVersionDir();
|
|
41997
|
-
if ((0,
|
|
42380
|
+
if ((0, import_node_fs75.existsSync)((0, import_node_path59.join)(dir, "bin", "lake")) && !opts.force) {
|
|
41998
42381
|
printInfo(`already installed at ${dir}`);
|
|
41999
42382
|
return;
|
|
42000
42383
|
}
|
|
@@ -42030,18 +42413,18 @@ function registerLeanCommand(program2) {
|
|
|
42030
42413
|
});
|
|
42031
42414
|
lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
|
|
42032
42415
|
const dir = pinnedVersionDir();
|
|
42033
|
-
if (!(0,
|
|
42416
|
+
if (!(0, import_node_fs75.existsSync)(dir)) {
|
|
42034
42417
|
printInfo("nothing to remove");
|
|
42035
42418
|
return;
|
|
42036
42419
|
}
|
|
42037
|
-
(0,
|
|
42420
|
+
(0, import_node_fs75.rmSync)(dir, { recursive: true, force: true });
|
|
42038
42421
|
printInfo(`removed ${dir}`);
|
|
42039
42422
|
});
|
|
42040
42423
|
}
|
|
42041
42424
|
|
|
42042
42425
|
// src/cli.ts
|
|
42043
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.34.
|
|
42044
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.
|
|
42426
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.34.2-experimental.2cad220").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) => {
|
|
42427
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.2-experimental.2cad220");
|
|
42045
42428
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
42046
42429
|
try {
|
|
42047
42430
|
await foldLegacyLocalCredential();
|