@codacy/verity-cli 0.34.1-experimental.542af3d → 0.34.1-experimental.56274e2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/bin/verity.js +765 -460
- package/package.json +1 -1
package/bin/verity.js
CHANGED
|
@@ -6975,10 +6975,10 @@ var require_resolve_block_map = __commonJS2({
|
|
|
6975
6975
|
let offset = bm.offset;
|
|
6976
6976
|
let commentEnd = null;
|
|
6977
6977
|
for (const collItem of bm.items) {
|
|
6978
|
-
const { start: start2, key, sep:
|
|
6978
|
+
const { start: start2, key, sep: 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;
|
|
@@ -13782,9 +13782,9 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
13782
13782
|
PatternStructure: 5
|
|
13783
13783
|
};
|
|
13784
13784
|
var QueryError = class _QueryError extends Error {
|
|
13785
|
-
constructor(
|
|
13786
|
-
super(_QueryError.formatMessage(
|
|
13787
|
-
this.kind =
|
|
13785
|
+
constructor(kind2, info2, index, length) {
|
|
13786
|
+
super(_QueryError.formatMessage(kind2, info2));
|
|
13787
|
+
this.kind = kind2;
|
|
13788
13788
|
this.info = info2;
|
|
13789
13789
|
this.index = index;
|
|
13790
13790
|
this.length = length;
|
|
@@ -13798,8 +13798,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
|
|
|
13798
13798
|
__name(this, "QueryError");
|
|
13799
13799
|
}
|
|
13800
13800
|
/** Formats an error message based on the error kind and info */
|
|
13801
|
-
static formatMessage(
|
|
13802
|
-
switch (
|
|
13801
|
+
static formatMessage(kind2, info2) {
|
|
13802
|
+
switch (kind2) {
|
|
13803
13803
|
case QueryErrorKind.NodeName:
|
|
13804
13804
|
return `Bad node name '${info2.word}'`;
|
|
13805
13805
|
case QueryErrorKind.FieldName:
|
|
@@ -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
|
});
|
|
@@ -16278,8 +16278,8 @@ async function reportLoginOutcome(out2, opts = {}) {
|
|
|
16278
16278
|
printWarn(" repository will report that account. Remove its line from ~/.verity/credentials");
|
|
16279
16279
|
printWarn(" only if you want this repository on the login you just completed.");
|
|
16280
16280
|
} else {
|
|
16281
|
-
const
|
|
16282
|
-
printWarn(` Note: this repository has a ${
|
|
16281
|
+
const kind2 = rec.userId != null ? "superseded per-repository" : "anonymous project-specific";
|
|
16282
|
+
printWarn(` Note: this repository has a ${kind2} credential that takes`);
|
|
16283
16283
|
printWarn(" precedence here. Remove its line from ~/.verity/credentials to use your login.");
|
|
16284
16284
|
printWarn(' Until then, "verity login" in this repository re-runs the full GitHub flow');
|
|
16285
16285
|
printWarn(" every time.");
|
|
@@ -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
|
}
|
|
@@ -16851,6 +16860,7 @@ var VERITY_SESSION_END_HOOK = {
|
|
|
16851
16860
|
command: "verity session end"
|
|
16852
16861
|
};
|
|
16853
16862
|
var GUARD_TIMEOUT = 300;
|
|
16863
|
+
var GUARD_TIMEOUT_MS = GUARD_TIMEOUT * 1e3;
|
|
16854
16864
|
function buildGuardHook(on) {
|
|
16855
16865
|
return {
|
|
16856
16866
|
type: "command",
|
|
@@ -17606,9 +17616,9 @@ function pointsAtVerity(src) {
|
|
|
17606
17616
|
}
|
|
17607
17617
|
function describeSource(src) {
|
|
17608
17618
|
if (!src || typeof src !== "object") return "an unrecognised source";
|
|
17609
|
-
const
|
|
17619
|
+
const kind2 = typeof src.source === "string" ? src.source : "unknown";
|
|
17610
17620
|
const target = typeof src.repo === "string" && src.repo || typeof src.url === "string" && src.url || typeof src.path === "string" && src.path || "";
|
|
17611
|
-
return target ? `${
|
|
17621
|
+
return target ? `${kind2} \u2192 ${target}` : kind2;
|
|
17612
17622
|
}
|
|
17613
17623
|
function legacyMarketplaceInstall() {
|
|
17614
17624
|
const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
|
|
@@ -18532,8 +18542,8 @@ function slugify(s) {
|
|
|
18532
18542
|
return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
|
|
18533
18543
|
}
|
|
18534
18544
|
function orgNodePath(node) {
|
|
18535
|
-
const
|
|
18536
|
-
return `${
|
|
18545
|
+
const kind2 = ORG_KINDS.includes(node.kind) ? node.kind : "domain";
|
|
18546
|
+
return `${kind2}/${slugify(node.title) || "claim"}-${node.tag_id.replace(/-/g, "").slice(0, 8)}.md`;
|
|
18537
18547
|
}
|
|
18538
18548
|
function renderOrgNode(node, orgName) {
|
|
18539
18549
|
const fm = [
|
|
@@ -18622,10 +18632,10 @@ function renderIndex(orgName, nodes) {
|
|
|
18622
18632
|
];
|
|
18623
18633
|
const byKind = /* @__PURE__ */ new Map();
|
|
18624
18634
|
for (const n of nodes) byKind.set(n.kind, [...byKind.get(n.kind) ?? [], n]);
|
|
18625
|
-
for (const
|
|
18626
|
-
const list2 = byKind.get(
|
|
18635
|
+
for (const kind2 of ORG_KINDS) {
|
|
18636
|
+
const list2 = byKind.get(kind2);
|
|
18627
18637
|
if (!list2?.length) continue;
|
|
18628
|
-
lines.push(`## ${
|
|
18638
|
+
lines.push(`## ${kind2}/ (${list2.length})`);
|
|
18629
18639
|
for (const n of list2) lines.push(`- [[${orgNodePath(n).split("/")[1].replace(/\.md$/, "")}]] \u2014 ${n.title} \xB7 ${n.origin}`);
|
|
18630
18640
|
lines.push("");
|
|
18631
18641
|
}
|
|
@@ -18684,8 +18694,8 @@ async function readOrgMirror(remote = requestRemote()) {
|
|
|
18684
18694
|
const dir = orgMirrorDir(remote);
|
|
18685
18695
|
if (!dir || !(0, import_node_fs14.existsSync)(dir)) return [];
|
|
18686
18696
|
const out2 = [];
|
|
18687
|
-
for (const
|
|
18688
|
-
const kindDir = (0, import_node_path14.join)(dir,
|
|
18697
|
+
for (const kind2 of ORG_KINDS) {
|
|
18698
|
+
const kindDir = (0, import_node_path14.join)(dir, kind2);
|
|
18689
18699
|
if (!(0, import_node_fs14.existsSync)(kindDir)) continue;
|
|
18690
18700
|
let files;
|
|
18691
18701
|
try {
|
|
@@ -18953,16 +18963,16 @@ function relevance(node, ctx) {
|
|
|
18953
18963
|
return { score, via: { glob: globHit, tag: tagScore, text: textScore } };
|
|
18954
18964
|
}
|
|
18955
18965
|
var KIND_POOL_STRENGTH = 20;
|
|
18956
|
-
function priorFor(
|
|
18957
|
-
const base = KIND_PRIOR_MEAN[
|
|
18966
|
+
function priorFor(kind2, pooled) {
|
|
18967
|
+
const base = KIND_PRIOR_MEAN[kind2] ?? DEFAULT_PRIOR_MEAN;
|
|
18958
18968
|
const a = pooled ? Math.max(0, pooled.alpha) : 0;
|
|
18959
18969
|
const b = pooled ? Math.max(0, pooled.beta) : 0;
|
|
18960
|
-
const mean = pooled &&
|
|
18970
|
+
const mean = pooled && kind2 !== "integration" ? (KIND_POOL_STRENGTH * base + a) / (KIND_POOL_STRENGTH + a + b) : base;
|
|
18961
18971
|
return { alpha: mean * PRIOR_STRENGTH, beta: (1 - mean) * PRIOR_STRENGTH };
|
|
18962
18972
|
}
|
|
18963
|
-
function posteriorFor(
|
|
18964
|
-
const p = priorFor(
|
|
18965
|
-
if (!own ||
|
|
18973
|
+
function posteriorFor(kind2, own, pooled) {
|
|
18974
|
+
const p = priorFor(kind2, pooled);
|
|
18975
|
+
if (!own || kind2 === "integration") return p;
|
|
18966
18976
|
return { alpha: p.alpha + Math.max(0, own.alpha), beta: p.beta + Math.max(0, own.beta) };
|
|
18967
18977
|
}
|
|
18968
18978
|
function posteriorMean(p) {
|
|
@@ -19476,8 +19486,8 @@ function ensureVerityGitignore() {
|
|
|
19476
19486
|
}
|
|
19477
19487
|
let text = next.join("\n");
|
|
19478
19488
|
if (!hasMarker) {
|
|
19479
|
-
const
|
|
19480
|
-
text = text +
|
|
19489
|
+
const sep7 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
19490
|
+
text = text + sep7 + VERITY_GITIGNORE_BLOCK;
|
|
19481
19491
|
}
|
|
19482
19492
|
if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
|
|
19483
19493
|
return verified(
|
|
@@ -19507,8 +19517,8 @@ function writeFencedBlock() {
|
|
|
19507
19517
|
lines = fenceMemoryLines(lines);
|
|
19508
19518
|
let text = lines.join("\n");
|
|
19509
19519
|
if (!hasMarker) {
|
|
19510
|
-
const
|
|
19511
|
-
text = text +
|
|
19520
|
+
const sep7 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
|
|
19521
|
+
text = text + sep7 + VERITY_GITIGNORE_BLOCK;
|
|
19512
19522
|
}
|
|
19513
19523
|
try {
|
|
19514
19524
|
(0, import_node_fs19.writeFileSync)(".gitignore", text);
|
|
@@ -19558,8 +19568,8 @@ function keepMemoryTracked() {
|
|
|
19558
19568
|
}
|
|
19559
19569
|
if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
|
|
19560
19570
|
try {
|
|
19561
|
-
const
|
|
19562
|
-
(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);
|
|
19563
19573
|
} catch {
|
|
19564
19574
|
return "failed";
|
|
19565
19575
|
}
|
|
@@ -20002,7 +20012,7 @@ async function regenerateIndex() {
|
|
|
20002
20012
|
try {
|
|
20003
20013
|
const content = await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8");
|
|
20004
20014
|
const title = pickFrontmatter(content, "title") ?? slug;
|
|
20005
|
-
const
|
|
20015
|
+
const kind2 = pickFrontmatter(content, "kind") ?? "-";
|
|
20006
20016
|
const confidence = pickFrontmatter(content, "confidence");
|
|
20007
20017
|
const globs = pickFrontmatterArray(content, "file_globs");
|
|
20008
20018
|
const status = pickFrontmatter(content, "status") ?? "active";
|
|
@@ -20010,7 +20020,7 @@ async function regenerateIndex() {
|
|
|
20010
20020
|
const globPart = globs.length > 0 ? ` \xB7 scope: \`${globs.slice(0, 3).join("`, `")}\`` : "";
|
|
20011
20021
|
const statusPart = status !== "active" ? ` \xB7 *${status}*` : "";
|
|
20012
20022
|
lines.push(`- [[${slug}]] \u2014 **${title}**`);
|
|
20013
|
-
lines.push(` *${
|
|
20023
|
+
lines.push(` *${kind2}*${confPart}${globPart}${statusPart}`);
|
|
20014
20024
|
} catch {
|
|
20015
20025
|
lines.push(`- [[${slug}]]`);
|
|
20016
20026
|
}
|
|
@@ -22053,8 +22063,8 @@ function toRegister(severity) {
|
|
|
22053
22063
|
return "NOTE";
|
|
22054
22064
|
}
|
|
22055
22065
|
}
|
|
22056
|
-
function recordMark(d,
|
|
22057
|
-
appendEvent(d, { k: "mark", kind, from: from ?? null, to: to ?? null });
|
|
22066
|
+
function recordMark(d, kind2, from, to) {
|
|
22067
|
+
appendEvent(d, { k: "mark", kind: kind2, from: from ?? null, to: to ?? null });
|
|
22058
22068
|
}
|
|
22059
22069
|
function recordCapabilities(d, c, known) {
|
|
22060
22070
|
const put = (field, value, tier) => {
|
|
@@ -22149,13 +22159,13 @@ function registerIntentCommands(program2) {
|
|
|
22149
22159
|
if (!prompt) {
|
|
22150
22160
|
process.exit(0);
|
|
22151
22161
|
}
|
|
22152
|
-
if (deferredToPlugin("intent capture", event.session_id ??
|
|
22162
|
+
if (deferredToPlugin("intent capture", event.session_id ?? envSessionId() ?? null)) {
|
|
22153
22163
|
process.exit(0);
|
|
22154
22164
|
}
|
|
22155
22165
|
const isPrimitive = isSlashCommand(prompt);
|
|
22156
22166
|
const authForScope = await resolveToken(program2.opts().token);
|
|
22157
22167
|
const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
|
|
22158
|
-
const scopeSession = event.session_id ||
|
|
22168
|
+
const scopeSession = event.session_id || envSessionId() || "";
|
|
22159
22169
|
if (!isPrimitive) await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
|
|
22160
22170
|
if (!isPrimitive) {
|
|
22161
22171
|
try {
|
|
@@ -22875,7 +22885,12 @@ function registerLifecycleCommands(program2) {
|
|
|
22875
22885
|
}
|
|
22876
22886
|
if (!verityConfigured()) process.exit(0);
|
|
22877
22887
|
const event = await readHookStdin();
|
|
22878
|
-
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;
|
|
22879
22894
|
if (deferredToPlugin("compact", sessionId)) process.exit(0);
|
|
22880
22895
|
const globals = program2.opts();
|
|
22881
22896
|
const tok = await resolveToken(globals.token);
|
|
@@ -22904,9 +22919,14 @@ function registerLifecycleCommands(program2) {
|
|
|
22904
22919
|
}
|
|
22905
22920
|
if (!verityConfigured()) process.exit(0);
|
|
22906
22921
|
const event = await readHookStdin();
|
|
22907
|
-
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;
|
|
22908
22928
|
if (deferredToPlugin("session end", sessionId)) process.exit(0);
|
|
22909
|
-
const reason = opts.reason ?? event.session_end_reason ?? event.reason ?? "other";
|
|
22929
|
+
const reason = hookWord(opts.reason) ?? event.session_end_reason ?? event.reason ?? "other";
|
|
22910
22930
|
if (reason === "clear") {
|
|
22911
22931
|
writeCarry(sessionId ?? void 0, getCurrentCommit());
|
|
22912
22932
|
}
|
|
@@ -22990,20 +23010,56 @@ function buildCompactionContext(session) {
|
|
|
22990
23010
|
const trimmed = [...lines.slice(0, 5), ...lines.slice(5, 5 + 2)].join("\n");
|
|
22991
23011
|
return trimmed.length <= MAX_CHARS ? trimmed : null;
|
|
22992
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
|
+
}
|
|
22993
23046
|
async function readHookStdin() {
|
|
22994
23047
|
try {
|
|
22995
23048
|
if (process.stdin.isTTY) return {};
|
|
22996
23049
|
const chunks = [];
|
|
23050
|
+
let size = 0;
|
|
22997
23051
|
const timeout = new Promise((resolve9) => setTimeout(() => resolve9({}), 500));
|
|
22998
23052
|
const read2 = new Promise((resolve9) => {
|
|
22999
|
-
process.stdin.on("data", (c) =>
|
|
23000
|
-
|
|
23001
|
-
|
|
23002
|
-
|
|
23003
|
-
} catch {
|
|
23053
|
+
process.stdin.on("data", (c) => {
|
|
23054
|
+
size += c.length;
|
|
23055
|
+
if (size > MAX_HOOK_EVENT_BYTES) {
|
|
23056
|
+
process.stdin.destroy();
|
|
23004
23057
|
resolve9({});
|
|
23058
|
+
return;
|
|
23005
23059
|
}
|
|
23060
|
+
chunks.push(c);
|
|
23006
23061
|
});
|
|
23062
|
+
process.stdin.on("end", () => resolve9(parseHookEvent(Buffer.concat(chunks).toString("utf-8"))));
|
|
23007
23063
|
process.stdin.on("error", () => resolve9({}));
|
|
23008
23064
|
process.stdin.resume();
|
|
23009
23065
|
});
|
|
@@ -23827,8 +23883,8 @@ async function correctVerityMdVersion(opts) {
|
|
|
23827
23883
|
origin: { kind: "synthesized", tools: opts.tools }
|
|
23828
23884
|
}));
|
|
23829
23885
|
}
|
|
23830
|
-
async function writeFileTo(
|
|
23831
|
-
const target = projectPath(
|
|
23886
|
+
async function writeFileTo(relative7, body2) {
|
|
23887
|
+
const target = projectPath(relative7);
|
|
23832
23888
|
await (0, import_promises10.mkdir)((0, import_node_path29.dirname)(target), { recursive: true });
|
|
23833
23889
|
await (0, import_promises10.writeFile)(target, body2);
|
|
23834
23890
|
}
|
|
@@ -24907,7 +24963,7 @@ function registerStatusCommand(program2) {
|
|
|
24907
24963
|
{
|
|
24908
24964
|
const tokenForScope = tokenResult.data.token;
|
|
24909
24965
|
const found = resolveIgnoreState(
|
|
24910
|
-
ignoreStateKeys(tokenForScope,
|
|
24966
|
+
ignoreStateKeys(tokenForScope, envSessionId())
|
|
24911
24967
|
);
|
|
24912
24968
|
const now = Math.floor(Date.now() / 1e3);
|
|
24913
24969
|
const active = resolveActive(found?.state ?? null, now);
|
|
@@ -25100,7 +25156,7 @@ async function sendGeneralFeedback(message, opts, globals) {
|
|
|
25100
25156
|
process.exit(1);
|
|
25101
25157
|
}
|
|
25102
25158
|
const body2 = { message };
|
|
25103
|
-
const sessionId = opts.sessionId ??
|
|
25159
|
+
const sessionId = opts.sessionId ?? envSessionId();
|
|
25104
25160
|
const model = opts.model ?? process.env.CLAUDE_MODEL ?? "unknown";
|
|
25105
25161
|
if (sessionId) body2.session_id = sessionId;
|
|
25106
25162
|
if (model) body2.agent_model = model;
|
|
@@ -26344,7 +26400,7 @@ function resolveFrame(input) {
|
|
|
26344
26400
|
const hookDirUsable = !!input.hookCwd && (0, import_node_fs40.existsSync)(input.hookCwd);
|
|
26345
26401
|
const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
|
|
26346
26402
|
let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
|
|
26347
|
-
const
|
|
26403
|
+
const refuse2 = (refusal) => ({
|
|
26348
26404
|
moment: found?.moment ?? null,
|
|
26349
26405
|
frame: { worktreeRoot: null, gitDir: null, commonDir: null, isLinkedWorktree: false, branch: null, anchor, refusal }
|
|
26350
26406
|
});
|
|
@@ -26358,19 +26414,19 @@ function resolveFrame(input) {
|
|
|
26358
26414
|
if (!kindRes.some((re) => re.test(segments[i2]))) continue;
|
|
26359
26415
|
const target = extractCommandTarget(input.command, i2, baseDir);
|
|
26360
26416
|
if (target.named) anchor = "command-target";
|
|
26361
|
-
if (target.unresolvable) return
|
|
26417
|
+
if (target.unresolvable) return refuse2(`target:${target.unresolvable}`);
|
|
26362
26418
|
dirs.add(target.dir ?? baseDir);
|
|
26363
26419
|
}
|
|
26364
|
-
if (dirs.size > 1) return
|
|
26420
|
+
if (dirs.size > 1) return refuse2(`target:multiple ${found.moment} targets in one command`);
|
|
26365
26421
|
const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
|
|
26366
26422
|
if (targetDir !== baseDir) {
|
|
26367
|
-
if (!(0, import_node_fs40.existsSync)(targetDir)) return
|
|
26423
|
+
if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse2(`target:directory does not exist: ${targetDir}`);
|
|
26368
26424
|
dir = targetDir;
|
|
26369
26425
|
}
|
|
26370
26426
|
}
|
|
26371
26427
|
const toplevel = gitAt(dir, ["rev-parse", "--show-toplevel"]);
|
|
26372
26428
|
if (!toplevel) {
|
|
26373
|
-
return
|
|
26429
|
+
return refuse2(anchor === "command-target" ? `target:not a git repository: ${dir}` : `anchor:not a git repository: ${dir}`);
|
|
26374
26430
|
}
|
|
26375
26431
|
const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
|
|
26376
26432
|
const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
|
|
@@ -26966,7 +27022,7 @@ function sanitizeCommandWithLoss(rawCmd) {
|
|
|
26966
27022
|
const lost = lines.slice(1).some((l) => l.trim().length > 0);
|
|
26967
27023
|
const first = lines[0];
|
|
26968
27024
|
const cmd = sanitizeCommand(first);
|
|
26969
|
-
const hadSeparator = SEPARATORS.some((
|
|
27025
|
+
const hadSeparator = SEPARATORS.some((sep7) => first.indexOf(sep7) > 0);
|
|
26970
27026
|
return { cmd, lost: lost || !hadSeparator && first.length > MAX_COMMAND_CHARS };
|
|
26971
27027
|
}
|
|
26972
27028
|
var SEPARATORS = [" | ", " > ", " >> ", " 2>", " && ", " ; "];
|
|
@@ -26975,11 +27031,11 @@ function sanitizeCommand(rawCmd) {
|
|
|
26975
27031
|
let cmd = rawCmd.split("\n")[0];
|
|
26976
27032
|
let cut = -1;
|
|
26977
27033
|
let marker = "";
|
|
26978
|
-
for (const
|
|
26979
|
-
const idx = cmd.indexOf(
|
|
27034
|
+
for (const sep7 of SEPARATORS) {
|
|
27035
|
+
const idx = cmd.indexOf(sep7);
|
|
26980
27036
|
if (idx > 0 && (cut === -1 || idx < cut)) {
|
|
26981
27037
|
cut = idx;
|
|
26982
|
-
marker =
|
|
27038
|
+
marker = sep7.trim();
|
|
26983
27039
|
}
|
|
26984
27040
|
}
|
|
26985
27041
|
if (cut > -1) cmd = cmd.slice(0, cut);
|
|
@@ -27046,13 +27102,13 @@ async function bootstrap(run4) {
|
|
|
27046
27102
|
isTTY: process.stdout.isTTY === true
|
|
27047
27103
|
});
|
|
27048
27104
|
const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
|
|
27049
|
-
if (deferredToPlugin("analyze", sessionId ??
|
|
27105
|
+
if (deferredToPlugin("analyze", sessionId ?? envSessionId() ?? null)) {
|
|
27050
27106
|
process.exit(0);
|
|
27051
27107
|
}
|
|
27052
27108
|
const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
|
|
27053
27109
|
const tokenResult = await resolveToken(globals.token);
|
|
27054
27110
|
const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
27055
|
-
const rawSessionId = sessionId ||
|
|
27111
|
+
const rawSessionId = sessionId || envSessionId();
|
|
27056
27112
|
const baselineSessionId = sessionScopeKey(scopeToken, rawSessionId);
|
|
27057
27113
|
if (tokenResult.ok) {
|
|
27058
27114
|
run4.beacon = {
|
|
@@ -27257,7 +27313,7 @@ function channelSilence(input) {
|
|
|
27257
27313
|
// src/lib/cli-version.ts
|
|
27258
27314
|
function cliVersion() {
|
|
27259
27315
|
try {
|
|
27260
|
-
return true ? "0.34.1-experimental.
|
|
27316
|
+
return true ? "0.34.1-experimental.56274e2" : "dev";
|
|
27261
27317
|
} catch {
|
|
27262
27318
|
return "dev";
|
|
27263
27319
|
}
|
|
@@ -27497,10 +27553,10 @@ var EMPTY_RESULT = {
|
|
|
27497
27553
|
findings: [],
|
|
27498
27554
|
summary: { total_findings: 0, by_severity: {}, tools_run: [] }
|
|
27499
27555
|
};
|
|
27500
|
-
function withFailure(
|
|
27556
|
+
function withFailure(kind2, detail) {
|
|
27501
27557
|
return {
|
|
27502
27558
|
...EMPTY_RESULT,
|
|
27503
|
-
summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
|
|
27559
|
+
summary: { ...EMPTY_RESULT.summary, failure: { kind: kind2, detail: detail.slice(0, 300) } }
|
|
27504
27560
|
};
|
|
27505
27561
|
}
|
|
27506
27562
|
function runCodacyAnalysisIfAvailable(files) {
|
|
@@ -28058,7 +28114,7 @@ async function connect(run4) {
|
|
|
28058
28114
|
async function mode(run4) {
|
|
28059
28115
|
const { opts, globals } = run4;
|
|
28060
28116
|
const { actionSummary, allForReview, assistantResponse, baseline, conversation, memory: memory2, noFilesChanged, serviceUrl, sessionId, token, turnAuthoredCode } = run4;
|
|
28061
|
-
const sessionIdForMemory = sessionId ||
|
|
28117
|
+
const sessionIdForMemory = sessionId || envSessionId() || "";
|
|
28062
28118
|
let predictedMode;
|
|
28063
28119
|
try {
|
|
28064
28120
|
const memoryPath2 = sessionIdForMemory ? `/memory?session_id=${encodeURIComponent(sessionIdForMemory)}` : "/memory";
|
|
@@ -28259,11 +28315,11 @@ var rootCandidateCache = /* @__PURE__ */ new Map();
|
|
|
28259
28315
|
function candidateRoots(repoRoot2) {
|
|
28260
28316
|
const cached2 = rootCandidateCache.get(repoRoot2);
|
|
28261
28317
|
if (cached2) return cached2;
|
|
28262
|
-
const
|
|
28263
|
-
const out2 = [
|
|
28318
|
+
const norm3 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
28319
|
+
const out2 = [norm3];
|
|
28264
28320
|
try {
|
|
28265
|
-
const real = import_node_fs44.realpathSync.native(
|
|
28266
|
-
if (real !==
|
|
28321
|
+
const real = import_node_fs44.realpathSync.native(norm3).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
28322
|
+
if (real !== norm3) out2.push(real);
|
|
28267
28323
|
} catch {
|
|
28268
28324
|
}
|
|
28269
28325
|
for (const r of [...out2]) {
|
|
@@ -29114,39 +29170,39 @@ function extentOf(node) {
|
|
|
29114
29170
|
}
|
|
29115
29171
|
function definitionsIn(root, spec) {
|
|
29116
29172
|
const out2 = [];
|
|
29117
|
-
const add = (name2,
|
|
29173
|
+
const add = (name2, kind2, extent, fn, owner, last = extent) => {
|
|
29118
29174
|
const q = qualifierOf(owner, spec);
|
|
29119
|
-
out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind, extent, last, fn });
|
|
29175
|
+
out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind: kind2, extent, last, fn });
|
|
29120
29176
|
};
|
|
29121
29177
|
const visit = (n) => {
|
|
29122
|
-
const
|
|
29123
|
-
if (
|
|
29178
|
+
const kind2 = spec.definitions[n.type];
|
|
29179
|
+
if (kind2 && n.childForFieldName("body")) {
|
|
29124
29180
|
const nameNode = n.childForFieldName("name");
|
|
29125
29181
|
if (nameNode && nameNode.type !== "computed_property_name") {
|
|
29126
29182
|
const inClass = qualifierOf(n, spec) !== null;
|
|
29127
|
-
const k = spec.id === "python" ? inClass ? "method" : "function" :
|
|
29183
|
+
const k = spec.id === "python" ? inClass ? "method" : "function" : kind2;
|
|
29128
29184
|
add(nameNode.text, k, extentOf(n), n, n, n.parent?.type === "decorated_definition" ? n.parent : n);
|
|
29129
29185
|
}
|
|
29130
29186
|
} else if (spec.functionValues.has(n.type) && n.parent) {
|
|
29131
29187
|
const p = n.parent;
|
|
29132
|
-
const
|
|
29188
|
+
const kind3 = n.type === "arrow_function" ? "arrow" : n.type === "lambda" || n.type === "lambda_expression" ? "lambda" : "function";
|
|
29133
29189
|
const bound = p.childForFieldName("value")?.id === n.id;
|
|
29134
29190
|
if (bound && p.type === "variable_declarator" && p.childForFieldName("name")?.type === "identifier") {
|
|
29135
29191
|
const decl = p.parent && p.parent.namedChildren.filter((c) => c.type === "variable_declarator").length === 1 ? p.parent : p;
|
|
29136
|
-
add(p.childForFieldName("name").text,
|
|
29192
|
+
add(p.childForFieldName("name").text, kind3, decl, n, p);
|
|
29137
29193
|
} else if (bound && (p.type === "public_field_definition" || p.type === "field_definition")) {
|
|
29138
29194
|
const nameNode = p.childForFieldName("name") ?? p.childForFieldName("property");
|
|
29139
|
-
if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text,
|
|
29195
|
+
if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind3, extentOf(p), n, p, p);
|
|
29140
29196
|
} else if (bound && p.type === "pair") {
|
|
29141
29197
|
const key = p.childForFieldName("key");
|
|
29142
|
-
if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text,
|
|
29198
|
+
if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind3, p, n, p);
|
|
29143
29199
|
} else if (p.type === "arguments" && moduleCall(p.parent)) {
|
|
29144
29200
|
const call = p.parent;
|
|
29145
29201
|
const route = p.namedChildren[0];
|
|
29146
29202
|
const quoted = route && route.id !== n.id && route.type === "string" ? unquote2(route.text) : null;
|
|
29147
29203
|
const path = quoted && /^[\w/:.{}*-]{1,60}$/.test(quoted) ? quoted : null;
|
|
29148
29204
|
const callee = call.childForFieldName("function").text;
|
|
29149
|
-
add(path ? `${callee} ${path}` : callee,
|
|
29205
|
+
add(path ? `${callee} ${path}` : callee, kind3, call.parent, n, call);
|
|
29150
29206
|
}
|
|
29151
29207
|
}
|
|
29152
29208
|
for (const c of n.namedChildren) visit(c);
|
|
@@ -29423,15 +29479,15 @@ var STABLE_EXPRESSION = (t) => {
|
|
|
29423
29479
|
const root = t.split(".")[0];
|
|
29424
29480
|
return root === "this" || root === "self" || /^[A-Z]/.test(root);
|
|
29425
29481
|
};
|
|
29426
|
-
function argResource(
|
|
29427
|
-
if (!arg) return { kind, name: null, confidence: "unknown" };
|
|
29482
|
+
function argResource(kind2, arg) {
|
|
29483
|
+
if (!arg) return { kind: kind2, name: null, confidence: "unknown" };
|
|
29428
29484
|
if (arg.literal !== null) {
|
|
29429
29485
|
const n = literalName(arg.literal);
|
|
29430
|
-
return n ? { kind, name: n.name, confidence: n.confidence } : { kind, name: null, confidence: "unknown" };
|
|
29486
|
+
return n ? { kind: kind2, name: n.name, confidence: n.confidence } : { kind: kind2, name: null, confidence: "unknown" };
|
|
29431
29487
|
}
|
|
29432
|
-
if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind, name: arg.text, confidence: "expression" };
|
|
29488
|
+
if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind: kind2, name: arg.text, confidence: "expression" };
|
|
29433
29489
|
const keyed = keyedCall(arg.text);
|
|
29434
|
-
return keyed ? { kind, name: keyed, confidence: "expression" } : { kind, name: null, confidence: "unknown" };
|
|
29490
|
+
return keyed ? { kind: kind2, name: keyed, confidence: "expression" } : { kind: kind2, name: null, confidence: "unknown" };
|
|
29435
29491
|
}
|
|
29436
29492
|
function keyedCall(text) {
|
|
29437
29493
|
const t = text.trim();
|
|
@@ -30940,8 +30996,8 @@ ${m.accessors.map((x) => ` ${x.fn.path}:${x.fn.start.line} ${x.fn.qualified} \u
|
|
|
30940
30996
|
var KINDS = ["table", "cache", "file", "http", "queue", "service", "memory"];
|
|
30941
30997
|
function parseResource(text) {
|
|
30942
30998
|
const colon = text.indexOf(":");
|
|
30943
|
-
const
|
|
30944
|
-
if (KINDS.includes(
|
|
30999
|
+
const kind2 = colon > 0 ? text.slice(0, colon) : "";
|
|
31000
|
+
if (KINDS.includes(kind2)) return { kinds: [kind2], name: text.slice(colon + 1) };
|
|
30945
31001
|
return { kinds: KINDS, name: text };
|
|
30946
31002
|
}
|
|
30947
31003
|
var writersOfTool = async (ctx, args2) => {
|
|
@@ -31951,7 +32007,7 @@ async function workingMemory(run4) {
|
|
|
31951
32007
|
const { opts } = run4;
|
|
31952
32008
|
const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run4;
|
|
31953
32009
|
let { reachability } = run4;
|
|
31954
|
-
const memorySession = sessionDossier(token, sessionId ??
|
|
32010
|
+
const memorySession = sessionDossier(token, sessionId ?? envSessionId() ?? null);
|
|
31955
32011
|
let memory2 = null;
|
|
31956
32012
|
let incrementReport = null;
|
|
31957
32013
|
if (memorySession) {
|
|
@@ -32224,7 +32280,7 @@ async function buildRequest(run4) {
|
|
|
32224
32280
|
context: {
|
|
32225
32281
|
agent_model: process.env.CLAUDE_MODEL ?? "unknown",
|
|
32226
32282
|
agent_harness: "claude-code",
|
|
32227
|
-
session_id: sessionId ||
|
|
32283
|
+
session_id: sessionId || envSessionId() || "unknown",
|
|
32228
32284
|
iteration,
|
|
32229
32285
|
// Makes fleet composition falsifiable — without it, no adoption-gated
|
|
32230
32286
|
// rollout decision can be checked against anything.
|
|
@@ -33434,12 +33490,41 @@ async function runAnalyze(opts, globals) {
|
|
|
33434
33490
|
}
|
|
33435
33491
|
|
|
33436
33492
|
// src/commands/baseline.ts
|
|
33437
|
-
var
|
|
33438
|
-
var
|
|
33493
|
+
var import_node_fs56 = require("node:fs");
|
|
33494
|
+
var import_node_path43 = require("node:path");
|
|
33439
33495
|
|
|
33440
|
-
// src/lib/
|
|
33496
|
+
// src/lib/skew-notice.ts
|
|
33441
33497
|
var import_node_fs54 = require("node:fs");
|
|
33442
33498
|
var import_node_path41 = require("node:path");
|
|
33499
|
+
var MARKER = ".skew-notice.json";
|
|
33500
|
+
function markerPath2() {
|
|
33501
|
+
return (0, import_node_path41.join)(verityHome(), MARKER);
|
|
33502
|
+
}
|
|
33503
|
+
function today(now) {
|
|
33504
|
+
const y = now.getFullYear();
|
|
33505
|
+
const m = String(now.getMonth() + 1).padStart(2, "0");
|
|
33506
|
+
const d = String(now.getDate()).padStart(2, "0");
|
|
33507
|
+
return `${y}-${m}-${d}`;
|
|
33508
|
+
}
|
|
33509
|
+
function skewNoticeDue(skew, now = /* @__PURE__ */ new Date()) {
|
|
33510
|
+
try {
|
|
33511
|
+
const seen = JSON.parse((0, import_node_fs54.readFileSync)(markerPath2(), "utf-8"));
|
|
33512
|
+
return !(seen.global === skew.global && seen.hooks === skew.hooks && seen.day === today(now));
|
|
33513
|
+
} catch {
|
|
33514
|
+
return true;
|
|
33515
|
+
}
|
|
33516
|
+
}
|
|
33517
|
+
function recordSkewNotice(skew, now = /* @__PURE__ */ new Date()) {
|
|
33518
|
+
try {
|
|
33519
|
+
(0, import_node_fs54.mkdirSync)(verityHome(), { recursive: true, mode: 448 });
|
|
33520
|
+
(0, import_node_fs54.writeFileSync)(markerPath2(), JSON.stringify({ global: skew.global, hooks: skew.hooks, day: today(now) }) + "\n");
|
|
33521
|
+
} catch {
|
|
33522
|
+
}
|
|
33523
|
+
}
|
|
33524
|
+
|
|
33525
|
+
// src/lib/project-skills.ts
|
|
33526
|
+
var import_node_fs55 = require("node:fs");
|
|
33527
|
+
var import_node_path42 = require("node:path");
|
|
33443
33528
|
var PROJECT_SKILL_NAMES = [
|
|
33444
33529
|
"verity-setup",
|
|
33445
33530
|
"verity-analyze",
|
|
@@ -33465,14 +33550,14 @@ var LEGACY_SKILL_NAMES = [
|
|
|
33465
33550
|
var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
|
|
33466
33551
|
function staleProjectSkills() {
|
|
33467
33552
|
const root = projectPath(".claude/skills");
|
|
33468
|
-
if (!(0,
|
|
33469
|
-
return ALL.filter((name2) => (0,
|
|
33553
|
+
if (!(0, import_node_fs55.existsSync)(root)) return [];
|
|
33554
|
+
return ALL.filter((name2) => (0, import_node_fs55.existsSync)((0, import_node_path42.join)(root, name2)));
|
|
33470
33555
|
}
|
|
33471
33556
|
function removeProjectSkills() {
|
|
33472
33557
|
const root = projectPath(".claude/skills");
|
|
33473
33558
|
const removed = [];
|
|
33474
33559
|
for (const name2 of staleProjectSkills()) {
|
|
33475
|
-
(0,
|
|
33560
|
+
(0, import_node_fs55.rmSync)((0, import_node_path42.join)(root, name2), { recursive: true, force: true });
|
|
33476
33561
|
removed.push(name2);
|
|
33477
33562
|
}
|
|
33478
33563
|
return removed;
|
|
@@ -33492,20 +33577,22 @@ function registerBaselineCommands(program2) {
|
|
|
33492
33577
|
if (!process.stdin.isTTY) {
|
|
33493
33578
|
const input = (await readStdin()).trim();
|
|
33494
33579
|
if (input) {
|
|
33495
|
-
const event =
|
|
33580
|
+
const event = parseHookEvent2(input);
|
|
33496
33581
|
if (opts.sessionId === void 0) sessionId = event.sessionId;
|
|
33497
33582
|
if (opts.source === void 0) source2 = event.source;
|
|
33498
33583
|
}
|
|
33499
33584
|
}
|
|
33500
|
-
const session = sessionId ?? validSessionId(
|
|
33585
|
+
const session = sessionId ?? validSessionId(envSessionId());
|
|
33501
33586
|
const cli = pluginCliInvocation();
|
|
33502
33587
|
const skew = cliVersionSkew();
|
|
33503
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";
|
|
33504
33589
|
const cliLine = cli ? `Verity CLI: ${why}. When a Verity skill tells you to run \`verity <args>\`, run \`${cli} <args>\` instead. Everything else about the command is identical.` : null;
|
|
33505
|
-
const
|
|
33506
|
-
const
|
|
33590
|
+
const skewLoud = !!skew && skewNoticeDue(skew);
|
|
33591
|
+
const skewMsg = skew && skewLoud ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
|
|
33592
|
+
const loginWarning = "Until they have, do not send them to run `verity login` in a terminal: that runs the global one, which can sign this machine in to a different server.";
|
|
33593
|
+
const skewNote = !skew ? null : skewLoud ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. ${loginWarning}` : `The user's global \`verity\` is ${skew.global} and the hooks run ${skew.hooks}; \`${skew.remedy}\` fixes it. They were already told today, so do not repeat it unprompted \u2014 mention it only where it matters, such as before suggesting a \`verity\` command for their terminal. ${loginWarning}`;
|
|
33507
33594
|
if (!verityConfigured()) {
|
|
33508
|
-
if (isMachineStore((0,
|
|
33595
|
+
if (isMachineStore((0, import_node_path43.join)(repoRoot(), VERITY_DIR))) process.exit(0);
|
|
33509
33596
|
const how = isPluginInvocation() ? "Tell the user to run /verity:init \u2014 they type it; you cannot invoke it." : "Tell the user to run `verity init` in their terminal.";
|
|
33510
33597
|
const lines = [
|
|
33511
33598
|
`Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
|
|
@@ -33532,19 +33619,20 @@ function registerBaselineCommands(program2) {
|
|
|
33532
33619
|
}
|
|
33533
33620
|
}) + "\n"
|
|
33534
33621
|
);
|
|
33622
|
+
if (skew && skewMsg) recordSkewNotice(skew);
|
|
33535
33623
|
process.exit(0);
|
|
33536
33624
|
}
|
|
33537
33625
|
const realStart = source2 === void 0 || source2 === "startup" || source2 === "clear";
|
|
33538
33626
|
let memoryMsg = null;
|
|
33539
33627
|
let memoryAgentLine = null;
|
|
33540
33628
|
const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
|
|
33541
|
-
if (realStart && !(0,
|
|
33629
|
+
if (realStart && !(0, import_node_fs56.existsSync)(memoryNotice)) {
|
|
33542
33630
|
const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
|
|
33543
33631
|
if (trackedGraph > 0) {
|
|
33544
33632
|
memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
|
|
33545
33633
|
memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
|
|
33546
33634
|
try {
|
|
33547
|
-
(0,
|
|
33635
|
+
(0, import_node_fs56.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
|
|
33548
33636
|
} catch {
|
|
33549
33637
|
}
|
|
33550
33638
|
}
|
|
@@ -33572,7 +33660,7 @@ function registerBaselineCommands(program2) {
|
|
|
33572
33660
|
}
|
|
33573
33661
|
}
|
|
33574
33662
|
if (memoryAgentLine) notices.push(memoryAgentLine);
|
|
33575
|
-
if (notices.length > 0) {
|
|
33663
|
+
if (notices.length > 0 || skewMsg) {
|
|
33576
33664
|
process.stdout.write(
|
|
33577
33665
|
JSON.stringify({
|
|
33578
33666
|
...userMsg || skewMsg || memoryMsg ? { systemMessage: [skewMsg, userMsg, memoryMsg].filter(Boolean).join("\n") } : {},
|
|
@@ -33582,6 +33670,7 @@ function registerBaselineCommands(program2) {
|
|
|
33582
33670
|
}
|
|
33583
33671
|
}) + "\n"
|
|
33584
33672
|
);
|
|
33673
|
+
if (skew && skewMsg) recordSkewNotice(skew);
|
|
33585
33674
|
}
|
|
33586
33675
|
} else if (memoryMsg) {
|
|
33587
33676
|
process.stdout.write(
|
|
@@ -33613,7 +33702,7 @@ function registerBaselineCommands(program2) {
|
|
|
33613
33702
|
process.exit(0);
|
|
33614
33703
|
});
|
|
33615
33704
|
}
|
|
33616
|
-
var
|
|
33705
|
+
var MAX_HOOK_EVENT_BYTES2 = 64 * 1024;
|
|
33617
33706
|
var HOOK_SOURCES = /* @__PURE__ */ new Set(["startup", "resume", "clear", "compact"]);
|
|
33618
33707
|
var SESSION_ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
33619
33708
|
async function readStdin() {
|
|
@@ -33621,11 +33710,11 @@ async function readStdin() {
|
|
|
33621
33710
|
let size = 0;
|
|
33622
33711
|
for await (const chunk of process.stdin) {
|
|
33623
33712
|
size += chunk.length;
|
|
33624
|
-
if (size <=
|
|
33713
|
+
if (size <= MAX_HOOK_EVENT_BYTES2) chunks.push(chunk);
|
|
33625
33714
|
}
|
|
33626
|
-
return size >
|
|
33715
|
+
return size > MAX_HOOK_EVENT_BYTES2 ? "" : Buffer.concat(chunks).toString("utf-8");
|
|
33627
33716
|
}
|
|
33628
|
-
function
|
|
33717
|
+
function parseHookEvent2(input) {
|
|
33629
33718
|
let event;
|
|
33630
33719
|
try {
|
|
33631
33720
|
event = JSON.parse(input);
|
|
@@ -33645,7 +33734,35 @@ function hookSource(value) {
|
|
|
33645
33734
|
}
|
|
33646
33735
|
|
|
33647
33736
|
// src/commands/review.ts
|
|
33648
|
-
var
|
|
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
|
+
}
|
|
33649
33766
|
function registerReviewCommand(program2) {
|
|
33650
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) => {
|
|
33651
33768
|
const globals = program2.opts();
|
|
@@ -33664,11 +33781,23 @@ function registerReviewCommand(program2) {
|
|
|
33664
33781
|
});
|
|
33665
33782
|
}
|
|
33666
33783
|
async function runReview(opts, globals) {
|
|
33667
|
-
const
|
|
33668
|
-
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;
|
|
33669
33798
|
const analyzable = filterAnalyzable(allFiles);
|
|
33670
33799
|
const securityFiles = filterSecurity(allFiles);
|
|
33671
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0,
|
|
33800
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs57.existsSync)(f) || resolveFile(f) !== null);
|
|
33672
33801
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
33673
33802
|
const codeDelta = collectCodeDelta(allFiles);
|
|
33674
33803
|
const tokenResult = await resolveToken(globals.token);
|
|
@@ -33693,7 +33822,7 @@ async function runReview(opts, globals) {
|
|
|
33693
33822
|
context: {
|
|
33694
33823
|
agent_model: process.env.CLAUDE_MODEL ?? "unknown",
|
|
33695
33824
|
agent_harness: "claude-code",
|
|
33696
|
-
session_id:
|
|
33825
|
+
session_id: envSessionId() ?? "unknown",
|
|
33697
33826
|
trigger: "review",
|
|
33698
33827
|
iteration: 1
|
|
33699
33828
|
}
|
|
@@ -33734,12 +33863,12 @@ async function runReview(opts, globals) {
|
|
|
33734
33863
|
}
|
|
33735
33864
|
|
|
33736
33865
|
// src/commands/guard.ts
|
|
33737
|
-
var
|
|
33738
|
-
var
|
|
33866
|
+
var import_node_fs62 = require("node:fs");
|
|
33867
|
+
var import_node_path50 = require("node:path");
|
|
33739
33868
|
|
|
33740
33869
|
// src/lib/vendored.ts
|
|
33741
|
-
var
|
|
33742
|
-
var
|
|
33870
|
+
var import_node_fs58 = require("node:fs");
|
|
33871
|
+
var import_node_path45 = require("node:path");
|
|
33743
33872
|
var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
|
|
33744
33873
|
function dataDirOrNull() {
|
|
33745
33874
|
try {
|
|
@@ -33754,7 +33883,7 @@ function shippedSkillFile(path, dataDir = dataDirOrNull()) {
|
|
|
33754
33883
|
const [, skill, rel] = m;
|
|
33755
33884
|
if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
|
|
33756
33885
|
try {
|
|
33757
|
-
return (0,
|
|
33886
|
+
return (0, import_node_fs58.readFileSync)((0, import_node_path45.join)(dataDir, "skills", skill, rel), "utf8");
|
|
33758
33887
|
} catch {
|
|
33759
33888
|
return null;
|
|
33760
33889
|
}
|
|
@@ -33864,7 +33993,7 @@ async function runAgentReview(options) {
|
|
|
33864
33993
|
}
|
|
33865
33994
|
|
|
33866
33995
|
// src/lib/prove/auto.ts
|
|
33867
|
-
var
|
|
33996
|
+
var import_node_path49 = require("node:path");
|
|
33868
33997
|
var import_node_crypto19 = require("node:crypto");
|
|
33869
33998
|
|
|
33870
33999
|
// src/lib/prove/signals.ts
|
|
@@ -34906,9 +35035,9 @@ function effectSites(numbered2) {
|
|
|
34906
35035
|
const t = r.text.trim();
|
|
34907
35036
|
if (!t || t.startsWith("//") || t.startsWith("#") || t.startsWith("*")) continue;
|
|
34908
35037
|
const onParam = [...params].some((p) => callsOn(t, p) || callsDirect(t, p));
|
|
34909
|
-
const
|
|
34910
|
-
if (!
|
|
34911
|
-
out2.push(`L${r.n} [${
|
|
35038
|
+
const kind2 = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
|
|
35039
|
+
if (!kind2) continue;
|
|
35040
|
+
out2.push(`L${r.n} [${kind2}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
|
|
34912
35041
|
if (out2.length >= MAX_EFFECT_SITES) break;
|
|
34913
35042
|
}
|
|
34914
35043
|
return out2;
|
|
@@ -35551,9 +35680,9 @@ async function runReplay(brief, opts) {
|
|
|
35551
35680
|
if (opts.auth) return runReplayViaServer(brief, opts.auth, opts.timeoutMs);
|
|
35552
35681
|
const env = opts.env ?? process.env;
|
|
35553
35682
|
const none = { covered: 0, total: 0, ratio: 0, basis: "none" };
|
|
35554
|
-
const
|
|
35555
|
-
if (env.VERITY_PROVE_DIRECT !== "1") return
|
|
35556
|
-
if (!opts.apiKey) return
|
|
35683
|
+
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 });
|
|
35684
|
+
if (env.VERITY_PROVE_DIRECT !== "1") return refuse2("not logged in (run `verity login`); replays run on the Verity service");
|
|
35685
|
+
if (!opts.apiKey) return refuse2("OPENAI_API_KEY is not set");
|
|
35557
35686
|
return runReplayInContainer(brief, { apiKey: opts.apiKey, model: opts.model, timeoutMs: opts.timeoutMs, maxRounds: opts.maxRounds, fetchImpl: opts.fetchImpl });
|
|
35558
35687
|
}
|
|
35559
35688
|
function renderReplay(model, property, r) {
|
|
@@ -35591,18 +35720,18 @@ function renderReplay(model, property, r) {
|
|
|
35591
35720
|
// src/lib/prove/runner.ts
|
|
35592
35721
|
var import_node_child_process15 = require("node:child_process");
|
|
35593
35722
|
var import_node_os8 = require("node:os");
|
|
35594
|
-
var
|
|
35723
|
+
var import_node_fs61 = require("node:fs");
|
|
35595
35724
|
var import_node_os9 = require("node:os");
|
|
35596
|
-
var
|
|
35725
|
+
var import_node_path48 = require("node:path");
|
|
35597
35726
|
|
|
35598
35727
|
// src/lib/prove/scaffold.ts
|
|
35599
|
-
var
|
|
35600
|
-
var
|
|
35728
|
+
var import_node_fs60 = require("node:fs");
|
|
35729
|
+
var import_node_path47 = require("node:path");
|
|
35601
35730
|
|
|
35602
35731
|
// src/lib/prove/safe-write.ts
|
|
35603
|
-
var
|
|
35732
|
+
var import_node_fs59 = require("node:fs");
|
|
35604
35733
|
var import_node_crypto15 = require("node:crypto");
|
|
35605
|
-
var
|
|
35734
|
+
var import_node_path46 = require("node:path");
|
|
35606
35735
|
var SafeWriteError = class extends Error {
|
|
35607
35736
|
constructor(reason, path) {
|
|
35608
35737
|
super(`refusing to write ${path}: ${reason}`);
|
|
@@ -35611,10 +35740,10 @@ var SafeWriteError = class extends Error {
|
|
|
35611
35740
|
this.name = "SafeWriteError";
|
|
35612
35741
|
}
|
|
35613
35742
|
};
|
|
35614
|
-
var FLAGS3 =
|
|
35743
|
+
var FLAGS3 = import_node_fs59.constants;
|
|
35615
35744
|
var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
|
|
35616
35745
|
function assertPlainRelative(rel) {
|
|
35617
|
-
if (!rel || (0,
|
|
35746
|
+
if (!rel || (0, import_node_path46.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
|
|
35618
35747
|
for (const part of rel.split(/[\\/]/)) {
|
|
35619
35748
|
if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
|
|
35620
35749
|
}
|
|
@@ -35623,34 +35752,34 @@ function ensureDirsNoFollow(root, rel) {
|
|
|
35623
35752
|
const parts2 = rel.split(/[\\/]/);
|
|
35624
35753
|
let cur = root;
|
|
35625
35754
|
for (const part of parts2.slice(0, -1)) {
|
|
35626
|
-
cur = (0,
|
|
35755
|
+
cur = (0, import_node_path46.join)(cur, part);
|
|
35627
35756
|
let st;
|
|
35628
35757
|
try {
|
|
35629
|
-
st = (0,
|
|
35758
|
+
st = (0, import_node_fs59.lstatSync)(cur);
|
|
35630
35759
|
} catch {
|
|
35631
|
-
(0,
|
|
35760
|
+
(0, import_node_fs59.mkdirSync)(cur);
|
|
35632
35761
|
continue;
|
|
35633
35762
|
}
|
|
35634
35763
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
|
|
35635
35764
|
if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
|
|
35636
35765
|
}
|
|
35637
|
-
return (0,
|
|
35766
|
+
return (0, import_node_path46.join)(root, rel);
|
|
35638
35767
|
}
|
|
35639
35768
|
function insideRoot(realRoot, realPath) {
|
|
35640
|
-
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(
|
|
35769
|
+
return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path46.sep) ? realRoot : realRoot + import_node_path46.sep);
|
|
35641
35770
|
}
|
|
35642
35771
|
function removeQuietly(path) {
|
|
35643
35772
|
try {
|
|
35644
|
-
(0,
|
|
35773
|
+
(0, import_node_fs59.unlinkSync)(path);
|
|
35645
35774
|
} catch {
|
|
35646
35775
|
}
|
|
35647
35776
|
}
|
|
35648
35777
|
function writeFileInRootNoFollow(root, rel, content) {
|
|
35649
35778
|
assertPlainRelative(rel);
|
|
35650
35779
|
const dest = ensureDirsNoFollow(root, rel);
|
|
35651
|
-
const dir = (0,
|
|
35780
|
+
const dir = (0, import_node_path46.dirname)(dest);
|
|
35652
35781
|
try {
|
|
35653
|
-
const st = (0,
|
|
35782
|
+
const st = (0, import_node_fs59.lstatSync)(dest);
|
|
35654
35783
|
if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
|
|
35655
35784
|
if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
|
|
35656
35785
|
} catch (err2) {
|
|
@@ -35658,41 +35787,41 @@ function writeFileInRootNoFollow(root, rel, content) {
|
|
|
35658
35787
|
}
|
|
35659
35788
|
let realRoot;
|
|
35660
35789
|
try {
|
|
35661
|
-
realRoot = (0,
|
|
35790
|
+
realRoot = (0, import_node_fs59.realpathSync)(root);
|
|
35662
35791
|
} catch {
|
|
35663
35792
|
throw new SafeWriteError("unwritable", root);
|
|
35664
35793
|
}
|
|
35665
|
-
const tmp = (0,
|
|
35794
|
+
const tmp = (0, import_node_path46.join)(dir, `.${(0, import_node_path46.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
|
|
35666
35795
|
let fd;
|
|
35667
35796
|
try {
|
|
35668
|
-
fd = (0,
|
|
35797
|
+
fd = (0, import_node_fs59.openSync)(tmp, import_node_fs59.constants.O_WRONLY | import_node_fs59.constants.O_CREAT | import_node_fs59.constants.O_EXCL | NOFOLLOW2, 420);
|
|
35669
35798
|
} catch {
|
|
35670
35799
|
throw new SafeWriteError("unwritable", tmp);
|
|
35671
35800
|
}
|
|
35672
35801
|
try {
|
|
35673
|
-
const opened = (0,
|
|
35802
|
+
const opened = (0, import_node_fs59.fstatSync)(fd, { bigint: true });
|
|
35674
35803
|
let realTmp;
|
|
35675
35804
|
try {
|
|
35676
|
-
realTmp = (0,
|
|
35805
|
+
realTmp = (0, import_node_fs59.realpathSync)(tmp);
|
|
35677
35806
|
} catch {
|
|
35678
35807
|
throw new SafeWriteError("escaped", tmp);
|
|
35679
35808
|
}
|
|
35680
|
-
const there = (0,
|
|
35809
|
+
const there = (0, import_node_fs59.lstatSync)(realTmp, { bigint: true });
|
|
35681
35810
|
if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
|
|
35682
35811
|
throw new SafeWriteError("escaped", tmp);
|
|
35683
35812
|
}
|
|
35684
35813
|
const buf = Buffer.from(content, "utf-8");
|
|
35685
35814
|
let off = 0;
|
|
35686
|
-
while (off < buf.length) off += (0,
|
|
35815
|
+
while (off < buf.length) off += (0, import_node_fs59.writeSync)(fd, buf, off, buf.length - off);
|
|
35687
35816
|
} catch (err2) {
|
|
35688
|
-
(0,
|
|
35817
|
+
(0, import_node_fs59.closeSync)(fd);
|
|
35689
35818
|
removeQuietly(tmp);
|
|
35690
35819
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
|
|
35691
35820
|
}
|
|
35692
|
-
(0,
|
|
35821
|
+
(0, import_node_fs59.closeSync)(fd);
|
|
35693
35822
|
try {
|
|
35694
|
-
if (!insideRoot(realRoot, (0,
|
|
35695
|
-
(0,
|
|
35823
|
+
if (!insideRoot(realRoot, (0, import_node_fs59.realpathSync)(dir)) || (0, import_node_fs59.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
|
|
35824
|
+
(0, import_node_fs59.renameSync)(tmp, dest);
|
|
35696
35825
|
} catch (err2) {
|
|
35697
35826
|
removeQuietly(tmp);
|
|
35698
35827
|
throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
|
|
@@ -35706,9 +35835,9 @@ function pathHasNoLink(root, rel) {
|
|
|
35706
35835
|
}
|
|
35707
35836
|
let cur = root;
|
|
35708
35837
|
for (const part of rel.split(/[\\/]/)) {
|
|
35709
|
-
cur = cur +
|
|
35838
|
+
cur = cur + import_node_path46.sep + part;
|
|
35710
35839
|
try {
|
|
35711
|
-
if ((0,
|
|
35840
|
+
if ((0, import_node_fs59.lstatSync)(cur).isSymbolicLink()) return false;
|
|
35712
35841
|
} catch {
|
|
35713
35842
|
return true;
|
|
35714
35843
|
}
|
|
@@ -36018,20 +36147,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
|
|
|
36018
36147
|
never committed; what reaches the team is the bug report and the fix.
|
|
36019
36148
|
`;
|
|
36020
36149
|
function scaffoldProofs(root) {
|
|
36021
|
-
const proofsDir = (0,
|
|
36150
|
+
const proofsDir = (0, import_node_path47.join)(root, PROOFS_DIR);
|
|
36022
36151
|
const written = [];
|
|
36023
36152
|
const kept = [];
|
|
36024
36153
|
for (const stray of ["lakefile.lean"]) {
|
|
36025
36154
|
const rel = `${PROOFS_DIR}/${stray}`;
|
|
36026
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36155
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path47.join)(root, rel));
|
|
36027
36156
|
try {
|
|
36028
|
-
(0,
|
|
36157
|
+
(0, import_node_fs60.rmSync)((0, import_node_path47.join)(root, rel), { force: true });
|
|
36029
36158
|
} catch {
|
|
36030
36159
|
}
|
|
36031
36160
|
}
|
|
36032
36161
|
for (const f of PROOFS_TEMPLATE_FILES) {
|
|
36033
36162
|
const rel = `${PROOFS_DIR}/${f.path}`;
|
|
36034
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36163
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path47.join)(root, rel));
|
|
36035
36164
|
const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
|
|
36036
36165
|
if (current.ok && current.content === f.content) {
|
|
36037
36166
|
kept.push(rel);
|
|
@@ -36044,8 +36173,8 @@ function scaffoldProofs(root) {
|
|
|
36044
36173
|
[`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
|
|
36045
36174
|
[`${MODELS_DIR}/README.md`, MODELS_README]
|
|
36046
36175
|
]) {
|
|
36047
|
-
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0,
|
|
36048
|
-
if (existsNoFollow((0,
|
|
36176
|
+
if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path47.join)(root, rel));
|
|
36177
|
+
if (existsNoFollow((0, import_node_path47.join)(root, rel))) {
|
|
36049
36178
|
kept.push(rel);
|
|
36050
36179
|
continue;
|
|
36051
36180
|
}
|
|
@@ -36056,7 +36185,7 @@ function scaffoldProofs(root) {
|
|
|
36056
36185
|
}
|
|
36057
36186
|
function existsNoFollow(abs) {
|
|
36058
36187
|
try {
|
|
36059
|
-
(0,
|
|
36188
|
+
(0, import_node_fs60.lstatSync)(abs);
|
|
36060
36189
|
return true;
|
|
36061
36190
|
} catch {
|
|
36062
36191
|
return false;
|
|
@@ -36135,12 +36264,12 @@ function parseHeader(obj) {
|
|
|
36135
36264
|
function parseProperty(obj) {
|
|
36136
36265
|
const model = ident(obj.model);
|
|
36137
36266
|
const id = ident(obj.id);
|
|
36138
|
-
const
|
|
36267
|
+
const kind2 = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
|
|
36139
36268
|
const result = typeof obj.result === "string" && RESULTS.has(obj.result) ? obj.result : null;
|
|
36140
36269
|
const source2 = obj.source === void 0 ? "" : str2(obj.source, LIMITS.text);
|
|
36141
36270
|
const desc = obj.desc === void 0 ? "" : str2(obj.desc, LIMITS.text);
|
|
36142
|
-
if (!model || !id || !
|
|
36143
|
-
const p = { model, id, kind, source: source2, desc, result };
|
|
36271
|
+
if (!model || !id || !kind2 || !result || source2 === null || desc === null) return null;
|
|
36272
|
+
const p = { model, id, kind: kind2, source: source2, desc, result };
|
|
36144
36273
|
if (obj.bound !== void 0) {
|
|
36145
36274
|
const n = nat(obj.bound);
|
|
36146
36275
|
if (n === null) return null;
|
|
@@ -36314,17 +36443,17 @@ function renderReport(r) {
|
|
|
36314
36443
|
|
|
36315
36444
|
// src/lib/prove/runner.ts
|
|
36316
36445
|
function verityLeanHome(env = process.env) {
|
|
36317
|
-
return env.VERITY_LEAN_HOME ?? (0,
|
|
36446
|
+
return env.VERITY_LEAN_HOME ?? (0, import_node_path48.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
|
|
36318
36447
|
}
|
|
36319
36448
|
function findToolchain(env = process.env) {
|
|
36320
|
-
const managedBin = (0,
|
|
36321
|
-
const elanBin = (0,
|
|
36322
|
-
const elanHas = (0,
|
|
36323
|
-
const userPath = (env.PATH ?? "").split(
|
|
36324
|
-
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(
|
|
36449
|
+
const managedBin = (0, import_node_path48.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
|
|
36450
|
+
const elanBin = (0, import_node_path48.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
|
|
36451
|
+
const elanHas = (0, import_node_fs61.existsSync)((0, import_node_path48.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
|
|
36452
|
+
const userPath = (env.PATH ?? "").split(import_node_path48.delimiter).filter((d) => d && (elanHas || (0, import_node_path48.resolve)(d) !== (0, import_node_path48.resolve)(elanBin)));
|
|
36453
|
+
const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path48.delimiter);
|
|
36325
36454
|
const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
|
|
36326
36455
|
const exe = process.platform === "win32" ? "lake.exe" : "lake";
|
|
36327
|
-
const candidates2 = [(0,
|
|
36456
|
+
const candidates2 = [(0, import_node_path48.join)(managedBin, exe), ...elanHas ? [(0, import_node_path48.join)(elanBin, exe)] : [], exe];
|
|
36328
36457
|
for (const candidate of candidates2) {
|
|
36329
36458
|
try {
|
|
36330
36459
|
(0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
|
|
@@ -36403,7 +36532,7 @@ function proofsWorkspaceProblem(root) {
|
|
|
36403
36532
|
for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
|
|
36404
36533
|
let st;
|
|
36405
36534
|
try {
|
|
36406
|
-
st = (0,
|
|
36535
|
+
st = (0, import_node_fs61.lstatSync)((0, import_node_path48.join)(root, rel));
|
|
36407
36536
|
} catch {
|
|
36408
36537
|
break;
|
|
36409
36538
|
}
|
|
@@ -36423,44 +36552,44 @@ function refused(problem) {
|
|
|
36423
36552
|
function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36424
36553
|
const problem = proofsWorkspaceProblem(root);
|
|
36425
36554
|
if (problem) return refused(problem);
|
|
36426
|
-
return run2(tc, (0,
|
|
36555
|
+
return run2(tc, (0, import_node_path48.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36427
36556
|
}
|
|
36428
36557
|
async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
|
|
36429
36558
|
const problem = proofsWorkspaceProblem(root);
|
|
36430
36559
|
if (problem) return refused(problem);
|
|
36431
|
-
return runAsync(tc, (0,
|
|
36560
|
+
return runAsync(tc, (0, import_node_path48.join)(root, PROOFS_DIR), ["build"], timeoutMs);
|
|
36432
36561
|
}
|
|
36433
36562
|
function isModelInRoot(modelsAbs, rel) {
|
|
36434
|
-
if (!rel.endsWith(".lean") || (0,
|
|
36563
|
+
if (!rel.endsWith(".lean") || (0, import_node_path48.isAbsolute)(rel) || rel.startsWith("..")) return false;
|
|
36435
36564
|
return statRegularInRoot(modelsAbs, rel).ok;
|
|
36436
36565
|
}
|
|
36437
36566
|
function resolveModelFile(root, arg) {
|
|
36438
|
-
const modelsAbs = (0,
|
|
36439
|
-
const asPath = (0,
|
|
36567
|
+
const modelsAbs = (0, import_node_path48.join)(root, MODELS_DIR);
|
|
36568
|
+
const asPath = (0, import_node_path48.relative)(modelsAbs, (0, import_node_path48.isAbsolute)(arg) ? arg : (0, import_node_path48.resolve)(root, arg));
|
|
36440
36569
|
const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
|
|
36441
36570
|
for (const rel of candidates2) {
|
|
36442
|
-
if (isModelInRoot(modelsAbs, rel)) return (0,
|
|
36571
|
+
if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path48.join)(modelsAbs, rel);
|
|
36443
36572
|
}
|
|
36444
36573
|
return null;
|
|
36445
36574
|
}
|
|
36446
36575
|
function listModelFiles(root) {
|
|
36447
|
-
const modelsAbs = (0,
|
|
36448
|
-
if (!(0,
|
|
36449
|
-
return (0,
|
|
36576
|
+
const modelsAbs = (0, import_node_path48.join)(root, MODELS_DIR);
|
|
36577
|
+
if (!(0, import_node_fs61.existsSync)(modelsAbs)) return [];
|
|
36578
|
+
return (0, import_node_fs61.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path48.join)(modelsAbs, f));
|
|
36450
36579
|
}
|
|
36451
36580
|
function trimDiagnostics(text) {
|
|
36452
36581
|
return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
|
|
36453
36582
|
}
|
|
36454
36583
|
function checkModel(tc, root, modelFile, opts = {}) {
|
|
36455
|
-
const proofsAbs = (0,
|
|
36456
|
-
const rel = (0,
|
|
36584
|
+
const proofsAbs = (0, import_node_path48.join)(root, PROOFS_DIR);
|
|
36585
|
+
const rel = (0, import_node_path48.relative)(proofsAbs, modelFile);
|
|
36457
36586
|
const problem = proofsWorkspaceProblem(root);
|
|
36458
36587
|
const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36459
36588
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36460
36589
|
}
|
|
36461
36590
|
async function checkModelAsync(tc, root, modelFile, opts = {}) {
|
|
36462
|
-
const proofsAbs = (0,
|
|
36463
|
-
const rel = (0,
|
|
36591
|
+
const proofsAbs = (0, import_node_path48.join)(root, PROOFS_DIR);
|
|
36592
|
+
const rel = (0, import_node_path48.relative)(proofsAbs, modelFile);
|
|
36464
36593
|
const problem = proofsWorkspaceProblem(root);
|
|
36465
36594
|
const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
36466
36595
|
return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
|
|
@@ -36469,10 +36598,10 @@ function toReport(res, root, modelFile, timeoutMs) {
|
|
|
36469
36598
|
const parsed = parseVerityLines(res.stdout);
|
|
36470
36599
|
const combined = `${res.stdout}
|
|
36471
36600
|
${res.stderr}`;
|
|
36472
|
-
const name2 = parsed.header?.model ?? (0,
|
|
36601
|
+
const name2 = parsed.header?.model ?? (0, import_node_path48.basename)(modelFile, ".lean");
|
|
36473
36602
|
const report = {
|
|
36474
36603
|
model: name2,
|
|
36475
|
-
file: (0,
|
|
36604
|
+
file: (0, import_node_path48.relative)(root, modelFile),
|
|
36476
36605
|
ok: res.ok,
|
|
36477
36606
|
header: parsed.header,
|
|
36478
36607
|
properties: parsed.properties,
|
|
@@ -36519,9 +36648,9 @@ function isCrashTrace(trace) {
|
|
|
36519
36648
|
}
|
|
36520
36649
|
function mergeFormalFindings(response, outcome, pushedFiles) {
|
|
36521
36650
|
if (!outcome) return { blocking: 0 };
|
|
36522
|
-
const
|
|
36523
|
-
const pushed = new Set(pushedFiles.map(
|
|
36524
|
-
const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(
|
|
36651
|
+
const norm3 = (p) => p.replace(/\\/g, "/");
|
|
36652
|
+
const pushed = new Set(pushedFiles.map(norm3));
|
|
36653
|
+
const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm3(f.file)));
|
|
36525
36654
|
if (blocking.length === 0) return { blocking: 0 };
|
|
36526
36655
|
const existing = Array.isArray(response.findings) ? response.findings : [];
|
|
36527
36656
|
response.findings = [
|
|
@@ -36717,15 +36846,15 @@ function nonNegative(v) {
|
|
|
36717
36846
|
return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
|
|
36718
36847
|
}
|
|
36719
36848
|
function readLedger(root) {
|
|
36720
|
-
const
|
|
36721
|
-
const empty = { day:
|
|
36849
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
36850
|
+
const empty = { day: today2, models: 0, costUsd: 0 };
|
|
36722
36851
|
if (!isLocalState(root, AUTO_LEDGER)) return empty;
|
|
36723
36852
|
const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
|
|
36724
36853
|
if (!read2.ok) return empty;
|
|
36725
36854
|
try {
|
|
36726
36855
|
const o = JSON.parse(read2.content);
|
|
36727
|
-
if (o.day !==
|
|
36728
|
-
return { day:
|
|
36856
|
+
if (o.day !== today2 || typeof o.models !== "number") return empty;
|
|
36857
|
+
return { day: today2, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
|
|
36729
36858
|
} catch {
|
|
36730
36859
|
return empty;
|
|
36731
36860
|
}
|
|
@@ -36903,7 +37032,7 @@ async function runFormalPhase(input) {
|
|
|
36903
37032
|
const ranked = await deps.rank(eligible, root, input.changedLines);
|
|
36904
37033
|
if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
|
|
36905
37034
|
if (ranked.ok) spend(ranked);
|
|
36906
|
-
candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
|
|
37035
|
+
candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)), commits: c.commits, fixCommits: c.fixCommits, risk: c.risk }));
|
|
36907
37036
|
if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
|
|
36908
37037
|
const minScore = input.minScore ?? DEFAULT_MIN_SCORE;
|
|
36909
37038
|
let qualified = ranked.ranked.filter((c) => c.ai && c.ai.score >= minScore);
|
|
@@ -37012,7 +37141,7 @@ async function runFormalPhase(input) {
|
|
|
37012
37141
|
const sha2562 = sha256Of(chosen.content);
|
|
37013
37142
|
const chosenContent = chosen.content;
|
|
37014
37143
|
const { lines, numbered: numbered2 } = chosen;
|
|
37015
|
-
const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {} };
|
|
37144
|
+
const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {}, signals: { commits: top.commits, fixCommits: top.fixCommits, risk: top.risk } };
|
|
37016
37145
|
progress.target = target;
|
|
37017
37146
|
if (!REPLAYABLE.test(top.file)) return done({ status: "skipped", skip: "replay-unsupported", detail: `${top.file}: replay supports TS/JS and Python`, target });
|
|
37018
37147
|
if (timeLeft() < GENERATE_RESERVE_MS) return done({ status: "skipped", skip: "not-enough-time", detail: `${Math.round(timeLeft() / 1e3)} s left before generation`, target });
|
|
@@ -37042,7 +37171,7 @@ async function runFormalPhase(input) {
|
|
|
37042
37171
|
modelName = gen.name;
|
|
37043
37172
|
const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
|
|
37044
37173
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
37045
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37174
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path49.join)(root, rel);
|
|
37046
37175
|
progress.model = { name: gen.name, file: rel, rounds: round };
|
|
37047
37176
|
progress.step = "check";
|
|
37048
37177
|
report = await deps.check(root, abs);
|
|
@@ -37164,7 +37293,7 @@ async function runFormalPhase(input) {
|
|
|
37164
37293
|
return done({
|
|
37165
37294
|
status: "checked",
|
|
37166
37295
|
target,
|
|
37167
|
-
model: { name: modelName, file: (0,
|
|
37296
|
+
model: { name: modelName, file: (0, import_node_path49.relative)(root, (0, import_node_path49.join)(root, modelFile)), rounds },
|
|
37168
37297
|
properties: report.properties,
|
|
37169
37298
|
findings
|
|
37170
37299
|
});
|
|
@@ -37241,7 +37370,7 @@ async function generateAndCheck(root, req, opts) {
|
|
|
37241
37370
|
}
|
|
37242
37371
|
const rel = `${dir}/${gen.name}.lean`;
|
|
37243
37372
|
writeFileInRootNoFollow(root, rel, gen.source);
|
|
37244
|
-
const abs = resolveModelFile(root, rel) ?? (0,
|
|
37373
|
+
const abs = resolveModelFile(root, rel) ?? (0, import_node_path49.join)(root, rel);
|
|
37245
37374
|
const report = await opts.deps.check(root, abs);
|
|
37246
37375
|
const abstracts = report.header?.abstracts ?? [];
|
|
37247
37376
|
const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
|
|
@@ -37372,13 +37501,138 @@ function describeFormalOutcome(o) {
|
|
|
37372
37501
|
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}`;
|
|
37373
37502
|
}
|
|
37374
37503
|
|
|
37504
|
+
// src/lib/prove/record.ts
|
|
37505
|
+
var RECORD_TIMEOUT_MS = 8e3;
|
|
37506
|
+
var HOOK_EXIT_MARGIN_MS = 5e3;
|
|
37507
|
+
var MIN_RECORD_POST_MS = 1e3;
|
|
37508
|
+
function guardRecordDeadline(hookStartedAt) {
|
|
37509
|
+
return hookStartedAt + GUARD_TIMEOUT_MS - HOOK_EXIT_MARGIN_MS;
|
|
37510
|
+
}
|
|
37511
|
+
function recordPostTimeout(now, deadlineAt, timeoutMs = RECORD_TIMEOUT_MS) {
|
|
37512
|
+
if (deadlineAt === void 0) return timeoutMs;
|
|
37513
|
+
const left = deadlineAt - now;
|
|
37514
|
+
return left < MIN_RECORD_POST_MS ? null : Math.min(timeoutMs, left);
|
|
37515
|
+
}
|
|
37516
|
+
var norm2 = (p) => p.replace(/\\/g, "/");
|
|
37517
|
+
var SAFE_SEGMENT = /^[A-Za-z0-9._@+~$()[\]-]{1,255}$/;
|
|
37518
|
+
function safeRepoPath(p) {
|
|
37519
|
+
const n = norm2(p);
|
|
37520
|
+
if (!n || n.length > 512 || n.startsWith("/") || /^[A-Za-z]:\//.test(n)) return null;
|
|
37521
|
+
return n.split("/").every((s) => s !== "." && s !== ".." && SAFE_SEGMENT.test(s)) ? n : null;
|
|
37522
|
+
}
|
|
37523
|
+
var SYMBOL = /^[A-Za-z_$][\w$]*(?:[.#:][A-Za-z_$][\w$]*)*$/;
|
|
37524
|
+
var IDENT3 = /^[A-Za-z][\w]*$/;
|
|
37525
|
+
var TRACE_STEP = /^[A-Za-z_]\w{0,63}$/;
|
|
37526
|
+
var ELIDED_STEP = "\u2026";
|
|
37527
|
+
function recordBasis(source2) {
|
|
37528
|
+
if (typeof source2 !== "string") return "";
|
|
37529
|
+
if (/^rule:[a-z-]+$/.test(source2)) return source2;
|
|
37530
|
+
const m = /^(?:([^:\s]+):)?L(\d+)(?::|$)/.exec(source2);
|
|
37531
|
+
return m ? m[1] ? `${norm2(m[1])}:L${m[2]}` : `L${m[2]}` : "";
|
|
37532
|
+
}
|
|
37533
|
+
function recordTrace(trace) {
|
|
37534
|
+
return trace.slice(0, 16).map((s) => {
|
|
37535
|
+
const name2 = (s.trim().split(/[\s(]/, 1)[0] ?? "").split(".").pop() ?? "";
|
|
37536
|
+
return TRACE_STEP.test(name2) ? name2 : ELIDED_STEP;
|
|
37537
|
+
});
|
|
37538
|
+
}
|
|
37539
|
+
var ident2 = (s, re, max) => typeof s === "string" && s.length <= max && re.test(s) ? s : null;
|
|
37540
|
+
var kind = (k) => k === "intent" ? "intent" : "structural";
|
|
37541
|
+
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;
|
|
37542
|
+
function buildPhaseRecord(outcome, ctx) {
|
|
37543
|
+
const pushed = new Set(ctx.pushedFiles.map(norm2));
|
|
37544
|
+
const blocks = (f) => ctx.moment === "push" && f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file));
|
|
37545
|
+
const symbol = (s) => ident2(s, SYMBOL, 200);
|
|
37546
|
+
return {
|
|
37547
|
+
moment: ctx.moment,
|
|
37548
|
+
status: outcome.status,
|
|
37549
|
+
skip: outcome.skip ?? null,
|
|
37550
|
+
parent_run_id: ctx.parentRunId,
|
|
37551
|
+
target: outcome.target && symbol(outcome.target.symbol) && safeRepoPath(outcome.target.file) ? {
|
|
37552
|
+
file: safeRepoPath(outcome.target.file),
|
|
37553
|
+
symbol: symbol(outcome.target.symbol),
|
|
37554
|
+
lines: outcome.target.lines ?? null,
|
|
37555
|
+
score: Math.max(0, Math.min(1, outcome.target.score)),
|
|
37556
|
+
extent: ident2(outcome.target.extent, /^[a-z-]+(?::[a-z-]+)?$/, 60),
|
|
37557
|
+
signals: signalsOf(outcome.target.signals)
|
|
37558
|
+
} : null,
|
|
37559
|
+
candidates: (outcome.candidates ?? []).filter((c) => safeRepoPath(c.file)).slice(0, 12).map((c) => ({
|
|
37560
|
+
file: safeRepoPath(c.file),
|
|
37561
|
+
symbol: c.symbol === null ? null : symbol(c.symbol),
|
|
37562
|
+
score: c.score === null ? null : Math.max(0, Math.min(1, c.score)),
|
|
37563
|
+
criteria: c.criteria,
|
|
37564
|
+
reasked: c.reasked,
|
|
37565
|
+
signals: signalsOf(c)
|
|
37566
|
+
})),
|
|
37567
|
+
model: outcome.model && ident2(outcome.model.name, /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)*$/, 120) ? { name: outcome.model.name, rounds: Math.max(0, Math.min(20, outcome.model.rounds)) } : null,
|
|
37568
|
+
properties: (outcome.properties ?? []).filter((p) => ident2(p.id, IDENT3, 120)).slice(0, 16).map((p) => ({
|
|
37569
|
+
id: p.id,
|
|
37570
|
+
kind: kind(p.kind),
|
|
37571
|
+
basis: recordBasis(p.source),
|
|
37572
|
+
result: p.result,
|
|
37573
|
+
bound: p.bound ?? null,
|
|
37574
|
+
states: p.states ?? null
|
|
37575
|
+
})),
|
|
37576
|
+
findings: outcome.findings.filter((f) => ident2(f.property, IDENT3, 120) && symbol(f.symbol) && safeRepoPath(f.file)).slice(0, 8).map((f) => ({
|
|
37577
|
+
property: f.property,
|
|
37578
|
+
kind: kind(f.kind),
|
|
37579
|
+
trace: recordTrace(f.trace),
|
|
37580
|
+
file: safeRepoPath(f.file),
|
|
37581
|
+
symbol: f.symbol,
|
|
37582
|
+
verdict: f.verdict,
|
|
37583
|
+
waived: f.waived === true,
|
|
37584
|
+
blocked: blocks(f)
|
|
37585
|
+
})),
|
|
37586
|
+
grounding: outcome.grounding ? {
|
|
37587
|
+
sent_back: outcome.grounding.sentBack,
|
|
37588
|
+
dropped: outcome.grounding.dropped.filter((id) => ident2(id, IDENT3, 120)).slice(0, 16),
|
|
37589
|
+
trigger_missing: (outcome.grounding.triggerMissing ?? []).filter((id) => ident2(id, IDENT3, 120)).slice(0, 16)
|
|
37590
|
+
} : null,
|
|
37591
|
+
usage: {
|
|
37592
|
+
input_tokens: outcome.usage.inputTokens,
|
|
37593
|
+
output_tokens: outcome.usage.outputTokens,
|
|
37594
|
+
cost_usd: outcome.usage.costUsd,
|
|
37595
|
+
unpriced: outcome.usage.unpriced
|
|
37596
|
+
},
|
|
37597
|
+
duration_ms: Math.round(outcome.durationMs)
|
|
37598
|
+
};
|
|
37599
|
+
}
|
|
37600
|
+
async function postPhaseRecord(outcome, ctx, post) {
|
|
37601
|
+
try {
|
|
37602
|
+
const timeout = recordPostTimeout((post.now ?? Date.now)(), post.deadlineAt, post.timeoutMs ?? RECORD_TIMEOUT_MS);
|
|
37603
|
+
if (timeout === null) {
|
|
37604
|
+
logEvent("formal_record_skipped", { moment: ctx.moment, reason: "hook-deadline" });
|
|
37605
|
+
return null;
|
|
37606
|
+
}
|
|
37607
|
+
const res = await apiRequest({
|
|
37608
|
+
method: "POST",
|
|
37609
|
+
path: "/prove/record",
|
|
37610
|
+
serviceUrl: post.serviceUrl,
|
|
37611
|
+
token: post.token,
|
|
37612
|
+
body: buildPhaseRecord(outcome, ctx),
|
|
37613
|
+
timeout,
|
|
37614
|
+
cmd: "prove-record"
|
|
37615
|
+
});
|
|
37616
|
+
if (!res.ok) {
|
|
37617
|
+
logEvent("formal_record_failed", { moment: ctx.moment, category: res.category ?? "unknown", http_status: res.http_status ?? null });
|
|
37618
|
+
return null;
|
|
37619
|
+
}
|
|
37620
|
+
const runId = typeof res.data?.run_id === "string" ? res.data.run_id : null;
|
|
37621
|
+
logEvent("formal_record", { moment: ctx.moment, run_id: runId });
|
|
37622
|
+
return runId;
|
|
37623
|
+
} catch (err2) {
|
|
37624
|
+
logEvent("formal_record_failed", { moment: ctx.moment, category: "exception", name: err2?.constructor?.name ?? "Error" });
|
|
37625
|
+
return null;
|
|
37626
|
+
}
|
|
37627
|
+
}
|
|
37628
|
+
|
|
37375
37629
|
// src/commands/guard.ts
|
|
37376
37630
|
var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
|
|
37377
37631
|
var WRITERS_BUDGET_MS = 1500;
|
|
37378
37632
|
var EXCERPT_MAX_LINES2 = 30;
|
|
37379
37633
|
var VENDORED_READ_MAX_BYTES = 256 * 1024;
|
|
37380
37634
|
var GUARD_BLOCK_CAP = 2;
|
|
37381
|
-
var GUARD_ITER_FILE = (0,
|
|
37635
|
+
var GUARD_ITER_FILE = (0, import_node_path50.join)(VERITY_DIR, ".guard-iteration");
|
|
37382
37636
|
function readPreToolUseStdin() {
|
|
37383
37637
|
const empty = { command: "", cwd: null, sessionId: null };
|
|
37384
37638
|
return new Promise((resolve9) => {
|
|
@@ -37423,7 +37677,7 @@ function readPreToolUseStdin() {
|
|
|
37423
37677
|
}
|
|
37424
37678
|
function readIterMap() {
|
|
37425
37679
|
try {
|
|
37426
|
-
const raw = JSON.parse((0,
|
|
37680
|
+
const raw = JSON.parse((0, import_node_fs62.readFileSync)(GUARD_ITER_FILE, "utf-8"));
|
|
37427
37681
|
if (raw && typeof raw === "object") {
|
|
37428
37682
|
if (typeof raw.moment === "string" && typeof raw.count === "number") {
|
|
37429
37683
|
return { [raw.moment]: raw.count };
|
|
@@ -37443,10 +37697,10 @@ function readIter(moment) {
|
|
|
37443
37697
|
}
|
|
37444
37698
|
function writeIter(moment, count) {
|
|
37445
37699
|
try {
|
|
37446
|
-
(0,
|
|
37700
|
+
(0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37447
37701
|
const map = readIterMap();
|
|
37448
37702
|
map[moment] = count;
|
|
37449
|
-
(0,
|
|
37703
|
+
(0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37450
37704
|
} catch {
|
|
37451
37705
|
}
|
|
37452
37706
|
}
|
|
@@ -37456,10 +37710,10 @@ function resetIter(moment) {
|
|
|
37456
37710
|
if (!(moment in map)) return;
|
|
37457
37711
|
delete map[moment];
|
|
37458
37712
|
if (Object.keys(map).length === 0) {
|
|
37459
|
-
if ((0,
|
|
37713
|
+
if ((0, import_node_fs62.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs62.unlinkSync)(GUARD_ITER_FILE);
|
|
37460
37714
|
} else {
|
|
37461
|
-
(0,
|
|
37462
|
-
(0,
|
|
37715
|
+
(0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
|
|
37716
|
+
(0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
|
|
37463
37717
|
}
|
|
37464
37718
|
} catch {
|
|
37465
37719
|
}
|
|
@@ -37529,7 +37783,7 @@ function hasBlockingFinding(response, sentFiles) {
|
|
|
37529
37783
|
function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
|
|
37530
37784
|
const analyzable = filterAnalyzable(files);
|
|
37531
37785
|
const securityFiles = filterSecurity(files);
|
|
37532
|
-
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0,
|
|
37786
|
+
const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs62.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
|
|
37533
37787
|
const staticResults = runCodacyAnalysisIfAvailable(scannable);
|
|
37534
37788
|
const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
|
|
37535
37789
|
const requestBody = {
|
|
@@ -37542,7 +37796,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
|
|
|
37542
37796
|
agent_harness: "claude-code",
|
|
37543
37797
|
// Prefer the session id Claude Code passes on the hook payload; fall back
|
|
37544
37798
|
// to the env var, then 'unknown'.
|
|
37545
|
-
session_id: sessionId ??
|
|
37799
|
+
session_id: sessionId ?? envSessionId() ?? "unknown",
|
|
37546
37800
|
trigger,
|
|
37547
37801
|
iteration: iter + 1
|
|
37548
37802
|
}
|
|
@@ -37946,6 +38200,13 @@ async function runGuard(opts, globals) {
|
|
|
37946
38200
|
const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
|
|
37947
38201
|
mergeFormalFindings(response, formalOutcome, files);
|
|
37948
38202
|
decision = response.gate_decision ?? "(unrecognised)";
|
|
38203
|
+
if (formalOutcome) {
|
|
38204
|
+
await postPhaseRecord(formalOutcome, {
|
|
38205
|
+
moment: "push",
|
|
38206
|
+
parentRunId: typeof response.run_id === "string" ? response.run_id : null,
|
|
38207
|
+
pushedFiles: files
|
|
38208
|
+
}, { serviceUrl: urlResult.data, token: tokenResult.data.token, deadlineAt: guardRecordDeadline(hookStartedAt) });
|
|
38209
|
+
}
|
|
37949
38210
|
if (!result.ok) {
|
|
37950
38211
|
const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
|
|
37951
38212
|
if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
|
|
@@ -38063,7 +38324,7 @@ function writeBlockMessage(moment, response, covDetail) {
|
|
|
38063
38324
|
|
|
38064
38325
|
// src/commands/ignore.ts
|
|
38065
38326
|
function registerIgnoreCommand(program2) {
|
|
38066
|
-
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) => {
|
|
38327
|
+
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) => {
|
|
38067
38328
|
const globals = program2.opts();
|
|
38068
38329
|
const now = Math.floor(Date.now() / 1e3);
|
|
38069
38330
|
const reason = opts.reason?.trim();
|
|
@@ -38090,7 +38351,7 @@ function registerIgnoreCommand(program2) {
|
|
|
38090
38351
|
}
|
|
38091
38352
|
const tokenResult = await resolveToken(globals.token);
|
|
38092
38353
|
const token = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
38093
|
-
const sessionId = opts.sessionId ||
|
|
38354
|
+
const sessionId = opts.sessionId || envSessionId();
|
|
38094
38355
|
const keys = ignoreStateKeys(token, sessionId);
|
|
38095
38356
|
const existing = resolveIgnoreState(keys);
|
|
38096
38357
|
const spent = existing?.state.spent ?? 0;
|
|
@@ -38136,11 +38397,11 @@ function registerIgnoreCommand(program2) {
|
|
|
38136
38397
|
printInfo(`Verity will skip ${window2} \u2014 "${reason}" (${spent + 1}/${IGNORE_BUDGET} this session).`);
|
|
38137
38398
|
printInfo("It covers turns that author nothing. If anything is written, the declaration voids and the review runs.");
|
|
38138
38399
|
});
|
|
38139
|
-
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) => {
|
|
38400
|
+
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) => {
|
|
38140
38401
|
const globals = program2.opts();
|
|
38141
38402
|
const tokenResult = await resolveToken(globals.token);
|
|
38142
38403
|
const token = tokenResult.ok ? tokenResult.data.token : void 0;
|
|
38143
|
-
const sessionId = opts.sessionId ||
|
|
38404
|
+
const sessionId = opts.sessionId || envSessionId();
|
|
38144
38405
|
const found = resolveIgnoreState(ignoreStateKeys(token, sessionId));
|
|
38145
38406
|
const active = resolveActive(found?.state ?? null, Math.floor(Date.now() / 1e3));
|
|
38146
38407
|
if (!found || !active) {
|
|
@@ -38155,7 +38416,7 @@ function registerIgnoreCommand(program2) {
|
|
|
38155
38416
|
|
|
38156
38417
|
// src/commands/waive.ts
|
|
38157
38418
|
var import_node_crypto20 = require("node:crypto");
|
|
38158
|
-
var
|
|
38419
|
+
var import_node_fs63 = require("node:fs");
|
|
38159
38420
|
function registerWaiveCommand(program2) {
|
|
38160
38421
|
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) => {
|
|
38161
38422
|
const globals = program2.opts();
|
|
@@ -38184,7 +38445,7 @@ function registerWaiveCommand(program2) {
|
|
|
38184
38445
|
if (opts.file) {
|
|
38185
38446
|
body2.file = opts.file;
|
|
38186
38447
|
try {
|
|
38187
|
-
body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0,
|
|
38448
|
+
body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs63.readFileSync)(opts.file)).digest("hex");
|
|
38188
38449
|
} catch {
|
|
38189
38450
|
printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
|
|
38190
38451
|
process.exit(1);
|
|
@@ -38209,10 +38470,10 @@ function registerWaiveCommand(program2) {
|
|
|
38209
38470
|
}
|
|
38210
38471
|
|
|
38211
38472
|
// src/commands/init.ts
|
|
38212
|
-
var
|
|
38473
|
+
var import_node_fs68 = require("node:fs");
|
|
38213
38474
|
var import_promises20 = require("node:fs/promises");
|
|
38214
38475
|
var import_yaml6 = __toESM2(require_dist());
|
|
38215
|
-
var
|
|
38476
|
+
var import_node_path54 = require("node:path");
|
|
38216
38477
|
var import_node_os11 = require("node:os");
|
|
38217
38478
|
var import_node_child_process19 = require("node:child_process");
|
|
38218
38479
|
|
|
@@ -38292,7 +38553,7 @@ function printPhase(n, of, title, subtitle) {
|
|
|
38292
38553
|
}
|
|
38293
38554
|
|
|
38294
38555
|
// src/commands/doctor.ts
|
|
38295
|
-
var
|
|
38556
|
+
var import_node_fs64 = require("node:fs");
|
|
38296
38557
|
|
|
38297
38558
|
// src/lib/prereqs.ts
|
|
38298
38559
|
var import_node_child_process16 = require("node:child_process");
|
|
@@ -38500,11 +38761,11 @@ async function buildReport() {
|
|
|
38500
38761
|
const hooks = wiring.status;
|
|
38501
38762
|
const provenance = cliProvenance();
|
|
38502
38763
|
const telemetry = await checkTelemetry();
|
|
38503
|
-
const hasConfig = (0,
|
|
38764
|
+
const hasConfig = (0, import_node_fs64.existsSync)(projectPath(CODACY_CONFIG_FILE));
|
|
38504
38765
|
const artifacts = {
|
|
38505
|
-
standard: (0,
|
|
38766
|
+
standard: (0, import_node_fs64.existsSync)(projectPath(STANDARD_FILE)),
|
|
38506
38767
|
analysisConfig: hasConfig,
|
|
38507
|
-
verityMd: (0,
|
|
38768
|
+
verityMd: (0, import_node_fs64.existsSync)(projectPath(VERITY_MD_FILE)),
|
|
38508
38769
|
analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
|
|
38509
38770
|
};
|
|
38510
38771
|
const next = [];
|
|
@@ -38663,8 +38924,8 @@ function registerDoctorCommand(program2) {
|
|
|
38663
38924
|
}
|
|
38664
38925
|
|
|
38665
38926
|
// src/commands/migrate.ts
|
|
38666
|
-
var
|
|
38667
|
-
var
|
|
38927
|
+
var import_node_fs65 = require("node:fs");
|
|
38928
|
+
var import_node_path51 = require("node:path");
|
|
38668
38929
|
var import_node_child_process17 = require("node:child_process");
|
|
38669
38930
|
var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
|
|
38670
38931
|
function defaultNpmRemover(pkg) {
|
|
@@ -38701,12 +38962,12 @@ async function runMigration(opts = {}) {
|
|
|
38701
38962
|
return { actions, migrated: actions.length > 0 };
|
|
38702
38963
|
}
|
|
38703
38964
|
function migrateProjectDir(root, actions) {
|
|
38704
|
-
const gateDir = (0,
|
|
38705
|
-
const verityDir = (0,
|
|
38706
|
-
if ((0,
|
|
38965
|
+
const gateDir = (0, import_node_path51.join)(root, ".gate");
|
|
38966
|
+
const verityDir = (0, import_node_path51.join)(root, ".verity");
|
|
38967
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) {
|
|
38707
38968
|
return migrateProjectDirRename(root, gateDir, verityDir, actions);
|
|
38708
38969
|
}
|
|
38709
|
-
if ((0,
|
|
38970
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
|
|
38710
38971
|
return migrateProjectDirCarry(gateDir, verityDir, actions);
|
|
38711
38972
|
}
|
|
38712
38973
|
return false;
|
|
@@ -38727,13 +38988,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
|
|
|
38727
38988
|
}
|
|
38728
38989
|
}
|
|
38729
38990
|
if (moved) {
|
|
38730
|
-
if ((0,
|
|
38991
|
+
if ((0, import_node_fs65.existsSync)(gateDir)) {
|
|
38731
38992
|
const carried = carryLegacyContents(gateDir, verityDir);
|
|
38732
38993
|
if (carried > 0) {
|
|
38733
38994
|
actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
|
|
38734
38995
|
}
|
|
38735
38996
|
try {
|
|
38736
|
-
(0,
|
|
38997
|
+
(0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
|
|
38737
38998
|
} catch {
|
|
38738
38999
|
}
|
|
38739
39000
|
}
|
|
@@ -38749,18 +39010,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
|
|
|
38749
39010
|
actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
|
|
38750
39011
|
}
|
|
38751
39012
|
try {
|
|
38752
|
-
(0,
|
|
39013
|
+
(0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
|
|
38753
39014
|
} catch {
|
|
38754
39015
|
}
|
|
38755
39016
|
return carried > 0;
|
|
38756
39017
|
}
|
|
38757
39018
|
function migrateGlobalCredentials(home, actions) {
|
|
38758
39019
|
if (!home) return;
|
|
38759
|
-
const gateCreds = (0,
|
|
38760
|
-
const verityCreds = (0,
|
|
38761
|
-
if (!(0,
|
|
38762
|
-
if (!(0,
|
|
38763
|
-
(0,
|
|
39020
|
+
const gateCreds = (0, import_node_path51.join)(home, ".gate", "credentials");
|
|
39021
|
+
const verityCreds = (0, import_node_path51.join)(home, ".verity", "credentials");
|
|
39022
|
+
if (!(0, import_node_fs65.existsSync)(gateCreds)) return;
|
|
39023
|
+
if (!(0, import_node_fs65.existsSync)(verityCreds)) {
|
|
39024
|
+
(0, import_node_fs65.mkdirSync)((0, import_node_path51.join)(home, ".verity"), { recursive: true });
|
|
38764
39025
|
moveFile(gateCreds, verityCreds);
|
|
38765
39026
|
actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
|
|
38766
39027
|
return;
|
|
@@ -38782,8 +39043,8 @@ async function migrateLegacyHooks(root, actions) {
|
|
|
38782
39043
|
}
|
|
38783
39044
|
}
|
|
38784
39045
|
async function migrateClaudeMd(root, actions) {
|
|
38785
|
-
const claudeMd = (0,
|
|
38786
|
-
const hadLegacyBlock = (0,
|
|
39046
|
+
const claudeMd = (0, import_node_path51.join)(root, "CLAUDE.md");
|
|
39047
|
+
const hadLegacyBlock = (0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
|
|
38787
39048
|
if (!hadLegacyBlock) return;
|
|
38788
39049
|
try {
|
|
38789
39050
|
await ensureClaudeMdPointer(root);
|
|
@@ -38793,9 +39054,9 @@ async function migrateClaudeMd(root, actions) {
|
|
|
38793
39054
|
}
|
|
38794
39055
|
}
|
|
38795
39056
|
function migrateStandardFile(root, actions) {
|
|
38796
|
-
const gateMd = (0,
|
|
38797
|
-
const verityMd = (0,
|
|
38798
|
-
if (!(0,
|
|
39057
|
+
const gateMd = (0, import_node_path51.join)(root, "GATE.md");
|
|
39058
|
+
const verityMd = (0, import_node_path51.join)(root, "VERITY.md");
|
|
39059
|
+
if (!(0, import_node_fs65.existsSync)(gateMd) || (0, import_node_fs65.existsSync)(verityMd)) return;
|
|
38799
39060
|
let moved = false;
|
|
38800
39061
|
if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
|
|
38801
39062
|
try {
|
|
@@ -38807,12 +39068,12 @@ function migrateStandardFile(root, actions) {
|
|
|
38807
39068
|
if (!moved) moveFile(gateMd, verityMd);
|
|
38808
39069
|
const content = readFileSyncSafe(verityMd);
|
|
38809
39070
|
const refreshed = content.split("GATE.md").join("VERITY.md");
|
|
38810
|
-
if (refreshed !== content) (0,
|
|
39071
|
+
if (refreshed !== content) (0, import_node_fs65.writeFileSync)(verityMd, refreshed);
|
|
38811
39072
|
actions.push("Renamed GATE.md \u2192 VERITY.md");
|
|
38812
39073
|
}
|
|
38813
39074
|
async function migrateTelemetryHeaders(root, actions) {
|
|
38814
|
-
const file = (0,
|
|
38815
|
-
if (!(0,
|
|
39075
|
+
const file = (0, import_node_path51.join)(root, ".claude", "settings.local.json");
|
|
39076
|
+
if (!(0, import_node_fs65.existsSync)(file)) return;
|
|
38816
39077
|
let settings;
|
|
38817
39078
|
try {
|
|
38818
39079
|
settings = JSON.parse(readFileSyncSafe(file) || "{}");
|
|
@@ -38859,15 +39120,15 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
|
|
|
38859
39120
|
toAppend.push(line2.replace(/\r$/, ""));
|
|
38860
39121
|
}
|
|
38861
39122
|
if (toAppend.length > 0) {
|
|
38862
|
-
const
|
|
38863
|
-
(0,
|
|
39123
|
+
const sep7 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
|
|
39124
|
+
(0, import_node_fs65.writeFileSync)(verityCreds, verityContent + sep7 + toAppend.join("\n") + "\n");
|
|
38864
39125
|
}
|
|
38865
|
-
(0,
|
|
39126
|
+
(0, import_node_fs65.rmSync)(gateCreds, { force: true });
|
|
38866
39127
|
return toAppend.length;
|
|
38867
39128
|
}
|
|
38868
39129
|
function readFileSyncSafe(path) {
|
|
38869
39130
|
try {
|
|
38870
|
-
return (0,
|
|
39131
|
+
return (0, import_node_fs65.readFileSync)(path, "utf-8");
|
|
38871
39132
|
} catch {
|
|
38872
39133
|
return "";
|
|
38873
39134
|
}
|
|
@@ -38882,35 +39143,35 @@ function hasStagedChanges(root) {
|
|
|
38882
39143
|
}
|
|
38883
39144
|
function moveDir(from, to) {
|
|
38884
39145
|
try {
|
|
38885
|
-
(0,
|
|
39146
|
+
(0, import_node_fs65.renameSync)(from, to);
|
|
38886
39147
|
} catch (err2) {
|
|
38887
39148
|
if (err2.code !== "EXDEV") throw err2;
|
|
38888
|
-
(0,
|
|
38889
|
-
(0,
|
|
39149
|
+
(0, import_node_fs65.cpSync)(from, to, { recursive: true });
|
|
39150
|
+
(0, import_node_fs65.rmSync)(from, { recursive: true, force: true });
|
|
38890
39151
|
}
|
|
38891
39152
|
}
|
|
38892
39153
|
function moveFile(from, to) {
|
|
38893
39154
|
try {
|
|
38894
|
-
(0,
|
|
39155
|
+
(0, import_node_fs65.renameSync)(from, to);
|
|
38895
39156
|
} catch (err2) {
|
|
38896
39157
|
if (err2.code !== "EXDEV") throw err2;
|
|
38897
|
-
(0,
|
|
38898
|
-
(0,
|
|
39158
|
+
(0, import_node_fs65.cpSync)(from, to);
|
|
39159
|
+
(0, import_node_fs65.rmSync)(from, { force: true });
|
|
38899
39160
|
}
|
|
38900
39161
|
}
|
|
38901
39162
|
function carryLegacyContents(gateDir, verityDir) {
|
|
38902
39163
|
let copied = 0;
|
|
38903
39164
|
const walk2 = (relDir) => {
|
|
38904
|
-
const srcDir = (0,
|
|
38905
|
-
for (const entry of (0,
|
|
38906
|
-
const rel = relDir ? (0,
|
|
38907
|
-
const src = (0,
|
|
38908
|
-
const dest = (0,
|
|
38909
|
-
if ((0,
|
|
39165
|
+
const srcDir = (0, import_node_path51.join)(gateDir, relDir);
|
|
39166
|
+
for (const entry of (0, import_node_fs65.readdirSync)(srcDir)) {
|
|
39167
|
+
const rel = relDir ? (0, import_node_path51.join)(relDir, entry) : entry;
|
|
39168
|
+
const src = (0, import_node_path51.join)(gateDir, rel);
|
|
39169
|
+
const dest = (0, import_node_path51.join)(verityDir, rel);
|
|
39170
|
+
if ((0, import_node_fs65.statSync)(src).isDirectory()) {
|
|
38910
39171
|
walk2(rel);
|
|
38911
|
-
} else if (!(0,
|
|
38912
|
-
(0,
|
|
38913
|
-
(0,
|
|
39172
|
+
} else if (!(0, import_node_fs65.existsSync)(dest)) {
|
|
39173
|
+
(0, import_node_fs65.mkdirSync)((0, import_node_path51.dirname)(dest), { recursive: true });
|
|
39174
|
+
(0, import_node_fs65.cpSync)(src, dest);
|
|
38914
39175
|
copied++;
|
|
38915
39176
|
}
|
|
38916
39177
|
}
|
|
@@ -38919,22 +39180,22 @@ function carryLegacyContents(gateDir, verityDir) {
|
|
|
38919
39180
|
return copied;
|
|
38920
39181
|
}
|
|
38921
39182
|
async function needsMigration(root = repoRoot()) {
|
|
38922
|
-
const gateDir = (0,
|
|
38923
|
-
const verityDir = (0,
|
|
38924
|
-
if ((0,
|
|
38925
|
-
if ((0,
|
|
38926
|
-
if ((0,
|
|
39183
|
+
const gateDir = (0, import_node_path51.join)(root, ".gate");
|
|
39184
|
+
const verityDir = (0, import_node_path51.join)(root, ".verity");
|
|
39185
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) return true;
|
|
39186
|
+
if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
|
|
39187
|
+
if ((0, import_node_fs65.existsSync)((0, import_node_path51.join)(gateDir, "credentials")) && !(0, import_node_fs65.existsSync)((0, import_node_path51.join)(verityDir, "credentials"))) {
|
|
38927
39188
|
return true;
|
|
38928
39189
|
}
|
|
38929
|
-
if ((0,
|
|
39190
|
+
if ((0, import_node_fs65.existsSync)((0, import_node_path51.join)(gateDir, "memory")) && !(0, import_node_fs65.existsSync)((0, import_node_path51.join)(verityDir, "memory"))) {
|
|
38930
39191
|
return true;
|
|
38931
39192
|
}
|
|
38932
39193
|
}
|
|
38933
|
-
const claudeMd = (0,
|
|
38934
|
-
if ((0,
|
|
39194
|
+
const claudeMd = (0, import_node_path51.join)(root, "CLAUDE.md");
|
|
39195
|
+
if ((0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
|
|
38935
39196
|
return true;
|
|
38936
39197
|
}
|
|
38937
|
-
if ((0,
|
|
39198
|
+
if ((0, import_node_fs65.existsSync)((0, import_node_path51.join)(root, "GATE.md")) && !(0, import_node_fs65.existsSync)((0, import_node_path51.join)(root, "VERITY.md"))) {
|
|
38938
39199
|
return true;
|
|
38939
39200
|
}
|
|
38940
39201
|
if (await hasLegacyHooksAt(root)) return true;
|
|
@@ -39215,11 +39476,11 @@ async function promptMultiSelect(question, choices, fallback) {
|
|
|
39215
39476
|
}
|
|
39216
39477
|
|
|
39217
39478
|
// src/lib/prove/lean-install.ts
|
|
39218
|
-
var
|
|
39479
|
+
var import_node_fs66 = require("node:fs");
|
|
39219
39480
|
var import_node_crypto21 = require("node:crypto");
|
|
39220
39481
|
var import_node_child_process18 = require("node:child_process");
|
|
39221
39482
|
var import_node_os10 = require("node:os");
|
|
39222
|
-
var
|
|
39483
|
+
var import_node_path52 = require("node:path");
|
|
39223
39484
|
var import_promises18 = require("node:stream/promises");
|
|
39224
39485
|
var import_node_stream = require("node:stream");
|
|
39225
39486
|
var RELEASES = "https://releases.lean-lang.org/lean4";
|
|
@@ -39230,10 +39491,10 @@ function freeBytes(dir) {
|
|
|
39230
39491
|
let d = dir;
|
|
39231
39492
|
for (let i2 = 0; i2 < 64; i2++) {
|
|
39232
39493
|
try {
|
|
39233
|
-
const st = (0,
|
|
39494
|
+
const st = (0, import_node_fs66.statfsSync)(d);
|
|
39234
39495
|
return Number(st.bavail) * Number(st.bsize);
|
|
39235
39496
|
} catch {
|
|
39236
|
-
const up = (0,
|
|
39497
|
+
const up = (0, import_node_path52.join)(d, "..");
|
|
39237
39498
|
if (up === d) return null;
|
|
39238
39499
|
d = up;
|
|
39239
39500
|
}
|
|
@@ -39255,7 +39516,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
|
|
|
39255
39516
|
function sha256File(path) {
|
|
39256
39517
|
return new Promise((resolve9, reject) => {
|
|
39257
39518
|
const hash = (0, import_node_crypto21.createHash)("sha256");
|
|
39258
|
-
(0,
|
|
39519
|
+
(0, import_node_fs66.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
|
|
39259
39520
|
});
|
|
39260
39521
|
}
|
|
39261
39522
|
async function verifyDownload(zip, asset, version = pinnedVersion()) {
|
|
@@ -39275,7 +39536,7 @@ function leanAssetName(version = pinnedVersion()) {
|
|
|
39275
39536
|
return suffix ? `lean-${v}-${suffix}.zip` : null;
|
|
39276
39537
|
}
|
|
39277
39538
|
function pinnedVersionDir(env = process.env) {
|
|
39278
|
-
return (0,
|
|
39539
|
+
return (0, import_node_path52.join)(verityLeanHome(env), pinnedVersion());
|
|
39279
39540
|
}
|
|
39280
39541
|
function lakeBinary() {
|
|
39281
39542
|
return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
|
|
@@ -39286,12 +39547,12 @@ function unzip(zip, dest) {
|
|
|
39286
39547
|
for (const [cmd, args2] of attempts) {
|
|
39287
39548
|
try {
|
|
39288
39549
|
(0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
|
|
39289
|
-
if ((0,
|
|
39550
|
+
if ((0, import_node_fs66.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
|
|
39290
39551
|
errors.push(`${cmd}: produced nothing`);
|
|
39291
39552
|
} catch (err2) {
|
|
39292
39553
|
errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
|
|
39293
39554
|
try {
|
|
39294
|
-
for (const e of (0,
|
|
39555
|
+
for (const e of (0, import_node_fs66.readdirSync)(dest)) (0, import_node_fs66.rmSync)((0, import_node_path52.join)(dest, e), { recursive: true, force: true });
|
|
39295
39556
|
} catch {
|
|
39296
39557
|
}
|
|
39297
39558
|
}
|
|
@@ -39317,7 +39578,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
|
|
|
39317
39578
|
seen += chunk.length;
|
|
39318
39579
|
onProgress(seen, total);
|
|
39319
39580
|
});
|
|
39320
|
-
await (0, import_promises18.pipeline)(stream, (0,
|
|
39581
|
+
await (0, import_promises18.pipeline)(stream, (0, import_node_fs66.createWriteStream)(dest), { signal: ctrl.signal });
|
|
39321
39582
|
} catch (err2) {
|
|
39322
39583
|
if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
|
|
39323
39584
|
throw err2;
|
|
@@ -39367,10 +39628,10 @@ async function installLean(opts = {}) {
|
|
|
39367
39628
|
const gb = (n) => (n / 1024 ** 3).toFixed(1);
|
|
39368
39629
|
return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
|
|
39369
39630
|
}
|
|
39370
|
-
const tmp = (0,
|
|
39371
|
-
(0,
|
|
39372
|
-
(0,
|
|
39373
|
-
const zip = (0,
|
|
39631
|
+
const tmp = (0, import_node_path52.join)(home, ".tmp");
|
|
39632
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39633
|
+
(0, import_node_fs66.mkdirSync)(tmp, { recursive: true });
|
|
39634
|
+
const zip = (0, import_node_path52.join)(tmp, asset);
|
|
39374
39635
|
say(`downloading ${url}`);
|
|
39375
39636
|
let lastPct = -1;
|
|
39376
39637
|
try {
|
|
@@ -39383,40 +39644,40 @@ async function installLean(opts = {}) {
|
|
|
39383
39644
|
}
|
|
39384
39645
|
});
|
|
39385
39646
|
} catch (err2) {
|
|
39386
|
-
(0,
|
|
39647
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39387
39648
|
return { ok: false, error: err2.message };
|
|
39388
39649
|
}
|
|
39389
39650
|
say("verifying checksum");
|
|
39390
39651
|
const verified = await verifyDownload(zip, asset);
|
|
39391
39652
|
if (!verified.ok) {
|
|
39392
|
-
(0,
|
|
39653
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39393
39654
|
return { ok: false, error: verified.error };
|
|
39394
39655
|
}
|
|
39395
39656
|
say("unpacking (this takes a minute)");
|
|
39396
|
-
const unpack = (0,
|
|
39397
|
-
(0,
|
|
39657
|
+
const unpack = (0, import_node_path52.join)(tmp, "unpack");
|
|
39658
|
+
(0, import_node_fs66.mkdirSync)(unpack);
|
|
39398
39659
|
const unpacked = unzip(zip, unpack);
|
|
39399
39660
|
if (!unpacked.ok) {
|
|
39400
|
-
(0,
|
|
39661
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39401
39662
|
return { ok: false, error: `unpack failed: ${unpacked.error}` };
|
|
39402
39663
|
}
|
|
39403
|
-
const entries = (0,
|
|
39404
|
-
const top = entries.length === 1 && (0,
|
|
39405
|
-
if (!(0,
|
|
39406
|
-
(0,
|
|
39664
|
+
const entries = (0, import_node_fs66.readdirSync)(unpack);
|
|
39665
|
+
const top = entries.length === 1 && (0, import_node_fs66.statSync)((0, import_node_path52.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path52.join)(unpack, entries[0]) : unpack;
|
|
39666
|
+
if (!(0, import_node_fs66.existsSync)((0, import_node_path52.join)(top, "bin", lakeBinary()))) {
|
|
39667
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39407
39668
|
return { ok: false, error: "the archive did not contain bin/lake" };
|
|
39408
39669
|
}
|
|
39409
|
-
(0,
|
|
39410
|
-
(0,
|
|
39411
|
-
(0,
|
|
39412
|
-
(0,
|
|
39670
|
+
(0, import_node_fs66.rmSync)(dir, { recursive: true, force: true });
|
|
39671
|
+
(0, import_node_fs66.mkdirSync)(home, { recursive: true });
|
|
39672
|
+
(0, import_node_fs66.renameSync)(top, dir);
|
|
39673
|
+
(0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
|
|
39413
39674
|
return { ok: true, dir };
|
|
39414
39675
|
}
|
|
39415
39676
|
|
|
39416
39677
|
// src/lib/remote-config.ts
|
|
39417
|
-
var
|
|
39678
|
+
var import_node_fs67 = require("node:fs");
|
|
39418
39679
|
var import_promises19 = require("node:fs/promises");
|
|
39419
|
-
var
|
|
39680
|
+
var import_node_path53 = require("node:path");
|
|
39420
39681
|
var import_yaml5 = __toESM2(require_dist());
|
|
39421
39682
|
var IGNORE_RIDER = "verityignore";
|
|
39422
39683
|
async function fetchRemoteSetup(opts) {
|
|
@@ -39461,7 +39722,7 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39461
39722
|
written.push(STANDARD_FILE);
|
|
39462
39723
|
if (rider !== null) {
|
|
39463
39724
|
const localIgnore = projectPath(VERITYIGNORE_FILE);
|
|
39464
|
-
if (!(0,
|
|
39725
|
+
if (!(0, import_node_fs67.existsSync)(localIgnore)) {
|
|
39465
39726
|
await writeOut(VERITYIGNORE_FILE, rider);
|
|
39466
39727
|
written.push(VERITYIGNORE_FILE);
|
|
39467
39728
|
} else {
|
|
@@ -39492,9 +39753,9 @@ async function adoptRemoteSetup(found, opts) {
|
|
|
39492
39753
|
written.push(VERITY_MD_FILE);
|
|
39493
39754
|
return { written, notes };
|
|
39494
39755
|
}
|
|
39495
|
-
async function writeOut(
|
|
39496
|
-
const target = projectPath(
|
|
39497
|
-
await (0, import_promises19.mkdir)((0,
|
|
39756
|
+
async function writeOut(relative7, body2) {
|
|
39757
|
+
const target = projectPath(relative7);
|
|
39758
|
+
await (0, import_promises19.mkdir)((0, import_node_path53.dirname)(target), { recursive: true });
|
|
39498
39759
|
await (0, import_promises19.writeFile)(target, body2);
|
|
39499
39760
|
}
|
|
39500
39761
|
function describeRemote(found) {
|
|
@@ -39611,15 +39872,15 @@ async function runOptionalAuth(resolution, opts = {}) {
|
|
|
39611
39872
|
}
|
|
39612
39873
|
function resolveDataDir2() {
|
|
39613
39874
|
const candidates2 = [
|
|
39614
|
-
(0,
|
|
39875
|
+
(0, import_node_path54.join)(__dirname, "..", "data"),
|
|
39615
39876
|
// installed: node_modules/@codacy/verity-cli/data
|
|
39616
|
-
(0,
|
|
39877
|
+
(0, import_node_path54.join)(__dirname, "..", "..", "data"),
|
|
39617
39878
|
// edge case: nested resolution
|
|
39618
|
-
(0,
|
|
39879
|
+
(0, import_node_path54.join)(process.cwd(), "cli", "data")
|
|
39619
39880
|
// local dev: running from repo root
|
|
39620
39881
|
];
|
|
39621
39882
|
for (const candidate of candidates2) {
|
|
39622
|
-
if ((0,
|
|
39883
|
+
if ((0, import_node_fs68.existsSync)((0, import_node_path54.join)(candidate, "skills"))) {
|
|
39623
39884
|
return candidate;
|
|
39624
39885
|
}
|
|
39625
39886
|
}
|
|
@@ -39635,9 +39896,9 @@ async function skillIsCurrent(src, dest) {
|
|
|
39635
39896
|
const list2 = (dir) => {
|
|
39636
39897
|
const out2 = [];
|
|
39637
39898
|
const walk2 = (d, prefix) => {
|
|
39638
|
-
for (const e of (0,
|
|
39899
|
+
for (const e of (0, import_node_fs68.readdirSync)(d, { withFileTypes: true })) {
|
|
39639
39900
|
const rel = prefix ? `${prefix}/${e.name}` : e.name;
|
|
39640
|
-
if (e.isDirectory()) walk2((0,
|
|
39901
|
+
if (e.isDirectory()) walk2((0, import_node_path54.join)(d, e.name), rel);
|
|
39641
39902
|
else if (e.isFile()) out2.push(rel);
|
|
39642
39903
|
}
|
|
39643
39904
|
};
|
|
@@ -39648,8 +39909,8 @@ async function skillIsCurrent(src, dest) {
|
|
|
39648
39909
|
const shipped = list2(src);
|
|
39649
39910
|
if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
|
|
39650
39911
|
for (const rel of shipped) {
|
|
39651
|
-
const a = await (0, import_promises20.readFile)((0,
|
|
39652
|
-
const b = await (0, import_promises20.readFile)((0,
|
|
39912
|
+
const a = await (0, import_promises20.readFile)((0, import_node_path54.join)(src, rel), "utf-8");
|
|
39913
|
+
const b = await (0, import_promises20.readFile)((0, import_node_path54.join)(dest, rel), "utf-8");
|
|
39653
39914
|
if (a !== b) return false;
|
|
39654
39915
|
}
|
|
39655
39916
|
return true;
|
|
@@ -39745,7 +40006,7 @@ function parseTelemetryAnswer(raw) {
|
|
|
39745
40006
|
return null;
|
|
39746
40007
|
}
|
|
39747
40008
|
function insideClaudeCode() {
|
|
39748
|
-
return !!process.env.CLAUDECODE || !!
|
|
40009
|
+
return !!process.env.CLAUDECODE || !!envSessionId();
|
|
39749
40010
|
}
|
|
39750
40011
|
function resumeDeferredPending(previous) {
|
|
39751
40012
|
return previous?.telemetry === "deferred";
|
|
@@ -39852,7 +40113,7 @@ async function synthesizeLocally(opts) {
|
|
|
39852
40113
|
async function healStaleAnalysisConfig(globals) {
|
|
39853
40114
|
const configPath = projectPath(CODACY_CONFIG_FILE);
|
|
39854
40115
|
const standardPath = projectPath(STANDARD_FILE);
|
|
39855
|
-
if (!(0,
|
|
40116
|
+
if (!(0, import_node_fs68.existsSync)(configPath) || !(0, import_node_fs68.existsSync)(standardPath)) return;
|
|
39856
40117
|
const validation = validatePatternIds();
|
|
39857
40118
|
if (validation.status !== "invalid") return;
|
|
39858
40119
|
printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
|
|
@@ -39949,17 +40210,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
|
|
|
39949
40210
|
async function installSkills(force, step) {
|
|
39950
40211
|
step("Installing skills");
|
|
39951
40212
|
const dataDir = resolveDataDir2();
|
|
39952
|
-
const skillsSource = (0,
|
|
40213
|
+
const skillsSource = (0, import_node_path54.join)(dataDir, "skills");
|
|
39953
40214
|
const skillsDest = ".claude/skills";
|
|
39954
40215
|
let skillsInstalled = 0;
|
|
39955
40216
|
for (const skill of SKILLS) {
|
|
39956
|
-
const src = (0,
|
|
39957
|
-
const dest = (0,
|
|
39958
|
-
if (!(0,
|
|
40217
|
+
const src = (0, import_node_path54.join)(skillsSource, skill);
|
|
40218
|
+
const dest = (0, import_node_path54.join)(skillsDest, skill);
|
|
40219
|
+
if (!(0, import_node_fs68.existsSync)(src)) {
|
|
39959
40220
|
printWarn(` Skill data not found: ${skill}`);
|
|
39960
40221
|
continue;
|
|
39961
40222
|
}
|
|
39962
|
-
if ((0,
|
|
40223
|
+
if ((0, import_node_fs68.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
|
|
39963
40224
|
skillsInstalled++;
|
|
39964
40225
|
continue;
|
|
39965
40226
|
}
|
|
@@ -40108,7 +40369,7 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
|
|
|
40108
40369
|
if (!toolchain) {
|
|
40109
40370
|
const dir = pinnedVersionDir();
|
|
40110
40371
|
const home = (0, import_node_os11.homedir)();
|
|
40111
|
-
const shown = dir.startsWith(home +
|
|
40372
|
+
const shown = dir.startsWith(home + import_node_path54.sep) ? `~${dir.slice(home.length)}` : dir;
|
|
40112
40373
|
console.log("");
|
|
40113
40374
|
console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
|
|
40114
40375
|
}
|
|
@@ -40167,7 +40428,7 @@ function registerInitCommand(program2) {
|
|
|
40167
40428
|
const staleMarker = clearStalePluginMarker();
|
|
40168
40429
|
const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
|
|
40169
40430
|
const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
|
|
40170
|
-
const isProject = projectMarkers.some((m) => (0,
|
|
40431
|
+
const isProject = projectMarkers.some((m) => (0, import_node_fs68.existsSync)(m));
|
|
40171
40432
|
if (!isProject) {
|
|
40172
40433
|
printError("No project detected in the current directory.");
|
|
40173
40434
|
printInfo('Run "verity init" from your project root.');
|
|
@@ -40270,7 +40531,7 @@ function registerInitCommand(program2) {
|
|
|
40270
40531
|
untrackMemory: opts.untrackMemory === true,
|
|
40271
40532
|
untrackState: opts.untrackState === true
|
|
40272
40533
|
});
|
|
40273
|
-
const globalVerityDir = (0,
|
|
40534
|
+
const globalVerityDir = (0, import_node_path54.join)(process.env.HOME ?? "", ".verity");
|
|
40274
40535
|
await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
|
|
40275
40536
|
console.log("");
|
|
40276
40537
|
step("Wiring Claude Code hooks");
|
|
@@ -40345,7 +40606,7 @@ function registerInitCommand(program2) {
|
|
|
40345
40606
|
}
|
|
40346
40607
|
step("Your project's Standard");
|
|
40347
40608
|
let haveStandard = false;
|
|
40348
|
-
if ((0,
|
|
40609
|
+
if ((0, import_node_fs68.existsSync)(projectPath(STANDARD_FILE))) {
|
|
40349
40610
|
printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
|
|
40350
40611
|
haveStandard = true;
|
|
40351
40612
|
} else {
|
|
@@ -40375,7 +40636,7 @@ function registerInitCommand(program2) {
|
|
|
40375
40636
|
...telemetryChoice ? { telemetry: telemetryChoice } : {},
|
|
40376
40637
|
init: {
|
|
40377
40638
|
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40378
|
-
cli_version: true ? "0.34.1-experimental.
|
|
40639
|
+
cli_version: true ? "0.34.1-experimental.56274e2" : "dev"
|
|
40379
40640
|
}
|
|
40380
40641
|
});
|
|
40381
40642
|
} catch (err2) {
|
|
@@ -40425,8 +40686,8 @@ function registerInitCommand(program2) {
|
|
|
40425
40686
|
}
|
|
40426
40687
|
|
|
40427
40688
|
// src/commands/uninstall.ts
|
|
40428
|
-
var
|
|
40429
|
-
var
|
|
40689
|
+
var import_node_fs69 = require("node:fs");
|
|
40690
|
+
var import_node_path55 = require("node:path");
|
|
40430
40691
|
function registerUninstallCommand(program2) {
|
|
40431
40692
|
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) => {
|
|
40432
40693
|
const dryRun = opts.dryRun ?? false;
|
|
@@ -40435,11 +40696,11 @@ function registerUninstallCommand(program2) {
|
|
|
40435
40696
|
const actions = [];
|
|
40436
40697
|
const skillsRoot = projectPath(".claude/skills");
|
|
40437
40698
|
for (const name2 of PROJECT_SKILL_NAMES) {
|
|
40438
|
-
const dir = (0,
|
|
40439
|
-
if ((0,
|
|
40699
|
+
const dir = (0, import_node_path55.join)(skillsRoot, name2);
|
|
40700
|
+
if ((0, import_node_fs69.existsSync)(dir)) {
|
|
40440
40701
|
actions.push({
|
|
40441
40702
|
label: `Remove .claude/skills/${name2}/`,
|
|
40442
|
-
apply: () => (0,
|
|
40703
|
+
apply: () => (0, import_node_fs69.rmSync)(dir, { recursive: true, force: true })
|
|
40443
40704
|
});
|
|
40444
40705
|
}
|
|
40445
40706
|
}
|
|
@@ -40453,24 +40714,24 @@ function registerUninstallCommand(program2) {
|
|
|
40453
40714
|
});
|
|
40454
40715
|
}
|
|
40455
40716
|
const verityDir = projectPath(VERITY_DIR);
|
|
40456
|
-
if ((0,
|
|
40717
|
+
if ((0, import_node_fs69.existsSync)(verityDir)) {
|
|
40457
40718
|
actions.push({
|
|
40458
40719
|
label: `Remove ${VERITY_DIR}/`,
|
|
40459
|
-
apply: () => (0,
|
|
40720
|
+
apply: () => (0, import_node_fs69.rmSync)(verityDir, { recursive: true, force: true })
|
|
40460
40721
|
});
|
|
40461
40722
|
}
|
|
40462
40723
|
if (!keepVerityMd) {
|
|
40463
40724
|
const verityMd = projectPath(VERITY_MD_FILE);
|
|
40464
|
-
if ((0,
|
|
40725
|
+
if ((0, import_node_fs69.existsSync)(verityMd)) {
|
|
40465
40726
|
actions.push({
|
|
40466
40727
|
label: `Remove ${VERITY_MD_FILE}`,
|
|
40467
|
-
apply: () => (0,
|
|
40728
|
+
apply: () => (0, import_node_fs69.rmSync)(verityMd, { force: true })
|
|
40468
40729
|
});
|
|
40469
40730
|
}
|
|
40470
40731
|
}
|
|
40471
40732
|
const cleanupEmptyDir = (path) => {
|
|
40472
|
-
if ((0,
|
|
40473
|
-
(0,
|
|
40733
|
+
if ((0, import_node_fs69.existsSync)(path) && (0, import_node_fs69.statSync)(path).isDirectory() && (0, import_node_fs69.readdirSync)(path).length === 0) {
|
|
40734
|
+
(0, import_node_fs69.rmdirSync)(path);
|
|
40474
40735
|
}
|
|
40475
40736
|
};
|
|
40476
40737
|
actions.push({
|
|
@@ -40481,11 +40742,11 @@ function registerUninstallCommand(program2) {
|
|
|
40481
40742
|
}
|
|
40482
40743
|
});
|
|
40483
40744
|
const home = process.env.HOME ?? "";
|
|
40484
|
-
const globalVerityDir = (0,
|
|
40485
|
-
if (purgeGlobal && (0,
|
|
40745
|
+
const globalVerityDir = (0, import_node_path55.join)(home, ".verity");
|
|
40746
|
+
if (purgeGlobal && (0, import_node_fs69.existsSync)(globalVerityDir)) {
|
|
40486
40747
|
actions.push({
|
|
40487
40748
|
label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
|
|
40488
|
-
apply: () => (0,
|
|
40749
|
+
apply: () => (0, import_node_fs69.rmSync)(globalVerityDir, { recursive: true, force: true })
|
|
40489
40750
|
});
|
|
40490
40751
|
}
|
|
40491
40752
|
if (actions.length === 0) {
|
|
@@ -40512,9 +40773,26 @@ function registerUninstallCommand(program2) {
|
|
|
40512
40773
|
|
|
40513
40774
|
// src/commands/task.ts
|
|
40514
40775
|
function memoryPath() {
|
|
40515
|
-
const sid =
|
|
40776
|
+
const sid = envSessionId();
|
|
40516
40777
|
return sid ? `/memory?session_id=${encodeURIComponent(sid)}` : "/memory";
|
|
40517
40778
|
}
|
|
40779
|
+
var TASK_STATUSES = ["active", "closed", "merged"];
|
|
40780
|
+
var TASK_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
40781
|
+
function isTaskId(value) {
|
|
40782
|
+
return typeof value === "string" && TASK_ID.test(value);
|
|
40783
|
+
}
|
|
40784
|
+
function taskListPath(status) {
|
|
40785
|
+
if (status === void 0) return "/tasks";
|
|
40786
|
+
if (!TASK_STATUSES.includes(status)) return null;
|
|
40787
|
+
return `/tasks?status=${encodeURIComponent(status)}`;
|
|
40788
|
+
}
|
|
40789
|
+
function taskActionPath(taskId, action) {
|
|
40790
|
+
return isTaskId(taskId) ? `/tasks/${encodeURIComponent(taskId)}/${action}` : null;
|
|
40791
|
+
}
|
|
40792
|
+
function refuse(message) {
|
|
40793
|
+
printError(message);
|
|
40794
|
+
process.exit(1);
|
|
40795
|
+
}
|
|
40518
40796
|
function timeAgo2(isoDate) {
|
|
40519
40797
|
const ms = Date.now() - new Date(isoDate).getTime();
|
|
40520
40798
|
const mins = Math.floor(ms / 6e4);
|
|
@@ -40542,10 +40820,11 @@ function registerTaskCommands(program2) {
|
|
|
40542
40820
|
task.command("list").description("List tasks").option("--status <status>", "Filter by status (active, closed, merged)").action(async (opts) => {
|
|
40543
40821
|
const globals = program2.opts();
|
|
40544
40822
|
const { token, serviceUrl } = await getAuth(globals);
|
|
40545
|
-
const
|
|
40823
|
+
const listPath = taskListPath(opts.status);
|
|
40824
|
+
if (!listPath) refuse(`Unknown status ${JSON.stringify(String(opts.status).slice(0, 40))} \u2014 use one of: ${TASK_STATUSES.join(", ")}`);
|
|
40546
40825
|
const result = await apiRequest({
|
|
40547
40826
|
method: "GET",
|
|
40548
|
-
path:
|
|
40827
|
+
path: listPath,
|
|
40549
40828
|
serviceUrl,
|
|
40550
40829
|
token,
|
|
40551
40830
|
verbose: globals.verbose,
|
|
@@ -40594,9 +40873,11 @@ function registerTaskCommands(program2) {
|
|
|
40594
40873
|
}
|
|
40595
40874
|
taskId = ct.id;
|
|
40596
40875
|
}
|
|
40876
|
+
const closePath = taskActionPath(taskId, "close");
|
|
40877
|
+
if (!closePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
|
|
40597
40878
|
const result = await apiRequest({
|
|
40598
40879
|
method: "POST",
|
|
40599
|
-
path:
|
|
40880
|
+
path: closePath,
|
|
40600
40881
|
serviceUrl,
|
|
40601
40882
|
token,
|
|
40602
40883
|
verbose: globals.verbose,
|
|
@@ -40643,9 +40924,11 @@ function registerTaskCommands(program2) {
|
|
|
40643
40924
|
}
|
|
40644
40925
|
taskId = ct.id;
|
|
40645
40926
|
}
|
|
40927
|
+
const renamePath = taskActionPath(taskId, "rename");
|
|
40928
|
+
if (!renamePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
|
|
40646
40929
|
const result = await apiRequest({
|
|
40647
40930
|
method: "POST",
|
|
40648
|
-
path:
|
|
40931
|
+
path: renamePath,
|
|
40649
40932
|
serviceUrl,
|
|
40650
40933
|
token,
|
|
40651
40934
|
body: { label: label2.slice(0, 120) },
|
|
@@ -40660,6 +40943,9 @@ function registerTaskCommands(program2) {
|
|
|
40660
40943
|
});
|
|
40661
40944
|
task.command("merge <source> <target>").description("Merge source task into target task").action(async (source2, target) => {
|
|
40662
40945
|
const globals = program2.opts();
|
|
40946
|
+
if (!isTaskId(source2) || !isTaskId(target)) {
|
|
40947
|
+
refuse("task merge takes two task ids (UUIDs): `verity task merge <source> <target>`");
|
|
40948
|
+
}
|
|
40663
40949
|
const { token, serviceUrl } = await getAuth(globals);
|
|
40664
40950
|
const result = await apiRequest({
|
|
40665
40951
|
method: "POST",
|
|
@@ -40679,8 +40965,8 @@ function registerTaskCommands(program2) {
|
|
|
40679
40965
|
}
|
|
40680
40966
|
|
|
40681
40967
|
// src/commands/reset.ts
|
|
40682
|
-
var
|
|
40683
|
-
var
|
|
40968
|
+
var import_node_fs70 = require("node:fs");
|
|
40969
|
+
var import_node_path56 = require("node:path");
|
|
40684
40970
|
function registerResetCommand(program2) {
|
|
40685
40971
|
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) => {
|
|
40686
40972
|
const globals = program2.opts();
|
|
@@ -40689,78 +40975,95 @@ function registerResetCommand(program2) {
|
|
|
40689
40975
|
const tokenResult = await resolveToken(globals.token);
|
|
40690
40976
|
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
40691
40977
|
if (tokenResult.ok && urlResult.ok) {
|
|
40978
|
+
const sessionId = envSessionId();
|
|
40692
40979
|
const mem = await apiRequest({
|
|
40693
40980
|
method: "GET",
|
|
40694
|
-
path:
|
|
40981
|
+
path: sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory",
|
|
40695
40982
|
serviceUrl: urlResult.data,
|
|
40696
40983
|
token: tokenResult.data.token,
|
|
40697
40984
|
timeout: 1e4,
|
|
40698
40985
|
cmd: "reset_lookup"
|
|
40699
40986
|
});
|
|
40700
40987
|
const ct = mem.ok ? mem.data.current_task : null;
|
|
40701
|
-
|
|
40988
|
+
const closePath = ct?.id ? taskActionPath(ct.id, "close") : null;
|
|
40989
|
+
if (ct?.id && !closePath) {
|
|
40990
|
+
printError("The current task in the service response has a malformed id \u2014 not closing it.");
|
|
40991
|
+
}
|
|
40992
|
+
if (closePath) {
|
|
40702
40993
|
const closeResult = await apiRequest({
|
|
40703
40994
|
method: "POST",
|
|
40704
|
-
path:
|
|
40995
|
+
path: closePath,
|
|
40705
40996
|
serviceUrl: urlResult.data,
|
|
40706
40997
|
token: tokenResult.data.token,
|
|
40707
40998
|
timeout: 1e4,
|
|
40708
40999
|
cmd: "reset_close"
|
|
40709
41000
|
});
|
|
40710
41001
|
if (closeResult.ok) {
|
|
40711
|
-
printInfo(`Closed task: "${ct
|
|
41002
|
+
printInfo(`Closed task: "${terminalText(ct?.label, 200) || "(unnamed)"}"`);
|
|
40712
41003
|
}
|
|
40713
41004
|
}
|
|
40714
41005
|
}
|
|
40715
41006
|
} catch {
|
|
40716
41007
|
}
|
|
40717
41008
|
}
|
|
40718
|
-
const
|
|
40719
|
-
|
|
40720
|
-
|
|
40721
|
-
for (const entry of (0, import_node_fs69.readdirSync)(cacheDir)) {
|
|
40722
|
-
if (entry.startsWith("pending-")) {
|
|
40723
|
-
try {
|
|
40724
|
-
(0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(cacheDir, entry));
|
|
40725
|
-
purged++;
|
|
40726
|
-
} catch {
|
|
40727
|
-
}
|
|
40728
|
-
}
|
|
40729
|
-
}
|
|
40730
|
-
}
|
|
41009
|
+
const purged = purgeVerityDir((0, import_node_path56.basename)(CACHE_DIR), (name2) => name2.startsWith("pending-"));
|
|
41010
|
+
if (purged === null) printError(`Did not purge ${CACHE_DIR}: it is not a directory inside ${VERITY_DIR}.`);
|
|
41011
|
+
const stateDir2 = projectPath(VERITY_DIR);
|
|
40731
41012
|
const filesToClear = [
|
|
40732
|
-
|
|
40733
|
-
|
|
40734
|
-
|
|
40735
|
-
|
|
40736
|
-
|
|
41013
|
+
(0, import_node_path56.basename)(INTENT_FILE),
|
|
41014
|
+
(0, import_node_path56.basename)(HASH_FILE),
|
|
41015
|
+
(0, import_node_path56.basename)(BASELINE_SHA_FILE),
|
|
41016
|
+
".iteration-count",
|
|
41017
|
+
".last-analysis"
|
|
40737
41018
|
];
|
|
40738
|
-
for (const
|
|
40739
|
-
if ((0,
|
|
40740
|
-
|
|
40741
|
-
(0, import_node_fs69.writeFileSync)(file, "");
|
|
40742
|
-
} catch {
|
|
40743
|
-
}
|
|
41019
|
+
for (const name2 of filesToClear) {
|
|
41020
|
+
if (lstatOrNull((0, import_node_path56.join)(stateDir2, name2)) && !replaceInRoot(stateDir2, name2, "")) {
|
|
41021
|
+
printError(`Did not clear ${VERITY_DIR}/${name2}: it is not a regular file inside ${VERITY_DIR}.`);
|
|
40744
41022
|
}
|
|
40745
41023
|
}
|
|
40746
41024
|
if (opts.all) {
|
|
40747
|
-
const
|
|
40748
|
-
if (
|
|
40749
|
-
|
|
40750
|
-
try {
|
|
40751
|
-
(0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(logsDir, entry));
|
|
40752
|
-
} catch {
|
|
40753
|
-
}
|
|
40754
|
-
}
|
|
40755
|
-
}
|
|
40756
|
-
printInfo("Cleared diagnostic logs.");
|
|
41025
|
+
const logs = purgeVerityDir(".logs", () => true);
|
|
41026
|
+
if (logs === null) printError(`Did not clear ${VERITY_DIR}/.logs: it is not a directory inside ${VERITY_DIR}.`);
|
|
41027
|
+
else printInfo("Cleared diagnostic logs.");
|
|
40757
41028
|
}
|
|
40758
|
-
|
|
41029
|
+
const count = purged ?? 0;
|
|
41030
|
+
printInfo(`Reset complete. Purged ${count} cached request${count !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
|
|
40759
41031
|
});
|
|
40760
41032
|
}
|
|
41033
|
+
function lstatOrNull(path) {
|
|
41034
|
+
try {
|
|
41035
|
+
return (0, import_node_fs70.lstatSync)(path);
|
|
41036
|
+
} catch {
|
|
41037
|
+
return null;
|
|
41038
|
+
}
|
|
41039
|
+
}
|
|
41040
|
+
function purgeVerityDir(child, select) {
|
|
41041
|
+
const verityDir = projectPath(VERITY_DIR);
|
|
41042
|
+
const dir = (0, import_node_path56.join)(verityDir, child);
|
|
41043
|
+
const parent = lstatOrNull(verityDir);
|
|
41044
|
+
const st = lstatOrNull(dir);
|
|
41045
|
+
if (!st) return 0;
|
|
41046
|
+
if (!parent || parent.isSymbolicLink() || !parent.isDirectory()) return null;
|
|
41047
|
+
if (st.isSymbolicLink() || !st.isDirectory()) return null;
|
|
41048
|
+
try {
|
|
41049
|
+
if ((0, import_node_fs70.realpathSync)(dir) !== (0, import_node_path56.join)((0, import_node_fs70.realpathSync)(verityDir), child)) return null;
|
|
41050
|
+
} catch {
|
|
41051
|
+
return null;
|
|
41052
|
+
}
|
|
41053
|
+
let removed = 0;
|
|
41054
|
+
for (const entry of (0, import_node_fs70.readdirSync)(dir, { withFileTypes: true })) {
|
|
41055
|
+
if (entry.isDirectory() || !select(entry.name)) continue;
|
|
41056
|
+
try {
|
|
41057
|
+
(0, import_node_fs70.unlinkSync)((0, import_node_path56.join)(dir, entry.name));
|
|
41058
|
+
removed++;
|
|
41059
|
+
} catch {
|
|
41060
|
+
}
|
|
41061
|
+
}
|
|
41062
|
+
return removed;
|
|
41063
|
+
}
|
|
40761
41064
|
|
|
40762
41065
|
// src/commands/reflect.ts
|
|
40763
|
-
var
|
|
41066
|
+
var import_node_fs71 = require("node:fs");
|
|
40764
41067
|
|
|
40765
41068
|
// src/lib/reflection-globs.ts
|
|
40766
41069
|
var MAX_GLOBS = 6;
|
|
@@ -40798,7 +41101,7 @@ async function writeNodeToDisk(args2) {
|
|
|
40798
41101
|
{ treePaths: listTrackedFiles(), recordBaseline: false }
|
|
40799
41102
|
);
|
|
40800
41103
|
if (written === 0) return false;
|
|
40801
|
-
return (0,
|
|
41104
|
+
return (0, import_node_fs71.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
|
|
40802
41105
|
} catch {
|
|
40803
41106
|
return false;
|
|
40804
41107
|
}
|
|
@@ -40829,7 +41132,7 @@ function registerReflectCommand(program2) {
|
|
|
40829
41132
|
let taskResolution = "flag";
|
|
40830
41133
|
let inheritedGlobs = [];
|
|
40831
41134
|
if (!taskId) {
|
|
40832
|
-
const sessionId =
|
|
41135
|
+
const sessionId = envSessionId() ?? "";
|
|
40833
41136
|
const memPath = sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory";
|
|
40834
41137
|
const mem = await apiRequest({
|
|
40835
41138
|
method: "GET",
|
|
@@ -40874,7 +41177,7 @@ function registerReflectCommand(program2) {
|
|
|
40874
41177
|
const userInput = input.text;
|
|
40875
41178
|
if (userInput) {
|
|
40876
41179
|
const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
|
|
40877
|
-
const
|
|
41180
|
+
const kind2 = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
|
|
40878
41181
|
const confirmed = opts.confirmed === true;
|
|
40879
41182
|
const source2 = confirmed ? "user" : "agent";
|
|
40880
41183
|
const explicitGlobs = Array.isArray(opts.fileGlobs) ? opts.fileGlobs.map((g) => g.trim()).filter(Boolean) : [];
|
|
@@ -40886,7 +41189,7 @@ function registerReflectCommand(program2) {
|
|
|
40886
41189
|
serviceUrl,
|
|
40887
41190
|
token,
|
|
40888
41191
|
body: {
|
|
40889
|
-
kind,
|
|
41192
|
+
kind: kind2,
|
|
40890
41193
|
title: userInput.slice(0, 200),
|
|
40891
41194
|
body: userInput,
|
|
40892
41195
|
domains: [],
|
|
@@ -41235,9 +41538,9 @@ function registerRunCommand(program2) {
|
|
|
41235
41538
|
}
|
|
41236
41539
|
|
|
41237
41540
|
// src/commands/telemetry.ts
|
|
41238
|
-
var
|
|
41541
|
+
var import_node_fs72 = require("node:fs");
|
|
41239
41542
|
async function recordTelemetryChoice(choice) {
|
|
41240
|
-
if (!(0,
|
|
41543
|
+
if (!(0, import_node_fs72.existsSync)(projectPath(SETUP_STATE_FILE))) return;
|
|
41241
41544
|
try {
|
|
41242
41545
|
if ((await readSetupState())?.telemetry === choice) return;
|
|
41243
41546
|
await writeSetupState({ telemetry: choice });
|
|
@@ -41314,8 +41617,8 @@ function registerTelemetryCommands(program2) {
|
|
|
41314
41617
|
}
|
|
41315
41618
|
|
|
41316
41619
|
// src/commands/prove.ts
|
|
41317
|
-
var
|
|
41318
|
-
var
|
|
41620
|
+
var import_node_fs73 = require("node:fs");
|
|
41621
|
+
var import_node_path57 = require("node:path");
|
|
41319
41622
|
|
|
41320
41623
|
// src/lib/prove/hint-pool.ts
|
|
41321
41624
|
var STOP2 = /* @__PURE__ */ new Set([
|
|
@@ -41457,7 +41760,7 @@ function registerProveCommand(program2) {
|
|
|
41457
41760
|
process.exit(2);
|
|
41458
41761
|
}
|
|
41459
41762
|
const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
|
|
41460
|
-
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0,
|
|
41763
|
+
let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path57.relative)(root, (0, import_node_path57.resolve)(p)) || ".") });
|
|
41461
41764
|
if (opts.hint && paths.length === 0) {
|
|
41462
41765
|
const hit = hintMatches(root, opts.hint);
|
|
41463
41766
|
if (hit.files.length > 0) {
|
|
@@ -41511,7 +41814,7 @@ function registerProveCommand(program2) {
|
|
|
41511
41814
|
});
|
|
41512
41815
|
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) => {
|
|
41513
41816
|
const root = repoRoot();
|
|
41514
|
-
if (!(0,
|
|
41817
|
+
if (!(0, import_node_fs73.existsSync)((0, import_node_path57.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41515
41818
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41516
41819
|
process.exit(2);
|
|
41517
41820
|
}
|
|
@@ -41535,7 +41838,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41535
41838
|
const reports = [];
|
|
41536
41839
|
for (const f of files) {
|
|
41537
41840
|
const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
|
|
41538
|
-
report.file = (0,
|
|
41841
|
+
report.file = (0, import_node_path57.relative)(root, f);
|
|
41539
41842
|
reports.push(report);
|
|
41540
41843
|
try {
|
|
41541
41844
|
writeResult(root, report);
|
|
@@ -41573,7 +41876,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
|
|
|
41573
41876
|
printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
|
|
41574
41877
|
process.exit(2);
|
|
41575
41878
|
}
|
|
41576
|
-
if (!(0,
|
|
41879
|
+
if (!(0, import_node_fs73.existsSync)((0, import_node_path57.join)(root, PROOFS_DIR, "lakefile.toml"))) {
|
|
41577
41880
|
printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
|
|
41578
41881
|
process.exit(2);
|
|
41579
41882
|
}
|
|
@@ -41604,7 +41907,7 @@ ${report.error ?? ""}`);
|
|
|
41604
41907
|
printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
|
|
41605
41908
|
return;
|
|
41606
41909
|
}
|
|
41607
|
-
const modelSource = readRegularFileInRoot(root, (0,
|
|
41910
|
+
const modelSource = readRegularFileInRoot(root, (0, import_node_path57.relative)(root, file), 512 * 1024);
|
|
41608
41911
|
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`);
|
|
41609
41912
|
const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
|
|
41610
41913
|
const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
|
|
@@ -41624,7 +41927,7 @@ ${report.error ?? ""}`);
|
|
|
41624
41927
|
});
|
|
41625
41928
|
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) => {
|
|
41626
41929
|
const root = repoRoot();
|
|
41627
|
-
let files = paths.map((p) => (0,
|
|
41930
|
+
let files = paths.map((p) => (0, import_node_path57.relative)(root, (0, import_node_path57.resolve)(p)));
|
|
41628
41931
|
if (files.length === 0) {
|
|
41629
41932
|
const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
|
|
41630
41933
|
const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
|
|
@@ -41634,8 +41937,10 @@ ${report.error ?? ""}`);
|
|
|
41634
41937
|
printInfo("No changed files to consider (nothing ahead of upstream). Pass paths explicitly.");
|
|
41635
41938
|
return;
|
|
41636
41939
|
}
|
|
41637
|
-
const
|
|
41940
|
+
const auth2 = await proveAuth(program2);
|
|
41941
|
+
const prep = await prepareFormalPhase(root, process.env, auth2 ?? void 0);
|
|
41638
41942
|
const outcome = prep.ok ? await runFormalPhaseWithin({ root, files, deadlineAt: Date.now() + Math.max(3e4, Number(opts.deadline) || 17e4), deps: prep.deps }).catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200))) : skippedOutcome(prep.skip, prep.detail);
|
|
41943
|
+
if (auth2) await postPhaseRecord(outcome, { moment: "on-demand", parentRunId: null, pushedFiles: [] }, auth2);
|
|
41639
41944
|
if (opts.json) {
|
|
41640
41945
|
printJson(outcome);
|
|
41641
41946
|
} else {
|
|
@@ -41696,7 +42001,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41696
42001
|
let revise;
|
|
41697
42002
|
if (opts.revise) {
|
|
41698
42003
|
const existing = resolveModelFile(root, opts.revise);
|
|
41699
|
-
const src = existing ? readRegularFileInRoot(root, (0,
|
|
42004
|
+
const src = existing ? readRegularFileInRoot(root, (0, import_node_path57.relative)(root, existing), 64 * 1024) : null;
|
|
41700
42005
|
if (!src || !src.ok || !opts.note) {
|
|
41701
42006
|
printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
|
|
41702
42007
|
process.exit(2);
|
|
@@ -41736,8 +42041,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41736
42041
|
});
|
|
41737
42042
|
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) => {
|
|
41738
42043
|
const root = repoRoot();
|
|
41739
|
-
const rel0 = (0,
|
|
41740
|
-
const rel = rel0.startsWith("..") || (0,
|
|
42044
|
+
const rel0 = (0, import_node_path57.relative)(root, (0, import_node_path57.isAbsolute)(file) ? file : (0, import_node_path57.join)(root, file)).replace(/\\/g, "/");
|
|
42045
|
+
const rel = rel0.startsWith("..") || (0, import_node_path57.isAbsolute)(rel0) ? null : rel0;
|
|
41741
42046
|
if (!rel) {
|
|
41742
42047
|
printError(`${file} is not inside this repository`);
|
|
41743
42048
|
process.exit(2);
|
|
@@ -41753,8 +42058,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
|
|
|
41753
42058
|
});
|
|
41754
42059
|
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) => {
|
|
41755
42060
|
const root = repoRoot();
|
|
41756
|
-
const rel = (0,
|
|
41757
|
-
const digest = rel.startsWith("..") || (0,
|
|
42061
|
+
const rel = (0, import_node_path57.relative)(root, (0, import_node_path57.isAbsolute)(file) ? file : (0, import_node_path57.join)(root, file));
|
|
42062
|
+
const digest = rel.startsWith("..") || (0, import_node_path57.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
|
|
41758
42063
|
if (!digest) {
|
|
41759
42064
|
printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
|
|
41760
42065
|
process.exit(2);
|
|
@@ -41788,10 +42093,10 @@ function refreshScaffold(root) {
|
|
|
41788
42093
|
}
|
|
41789
42094
|
|
|
41790
42095
|
// src/commands/lean.ts
|
|
41791
|
-
var
|
|
42096
|
+
var import_node_fs74 = require("node:fs");
|
|
41792
42097
|
var import_node_child_process20 = require("node:child_process");
|
|
41793
42098
|
var import_node_os12 = require("node:os");
|
|
41794
|
-
var
|
|
42099
|
+
var import_node_path58 = require("node:path");
|
|
41795
42100
|
function registerLeanCommand(program2) {
|
|
41796
42101
|
const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
|
|
41797
42102
|
lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
|
|
@@ -41808,7 +42113,7 @@ function registerLeanCommand(program2) {
|
|
|
41808
42113
|
const managed = pinnedVersionDir();
|
|
41809
42114
|
const matches = version ? version.includes(pin) : false;
|
|
41810
42115
|
if (opts.json) {
|
|
41811
|
-
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0,
|
|
42116
|
+
printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs74.existsSync)((0, import_node_path58.join)(managed, "bin")), asset: leanAssetName() });
|
|
41812
42117
|
return;
|
|
41813
42118
|
}
|
|
41814
42119
|
printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
|
|
@@ -41826,7 +42131,7 @@ function registerLeanCommand(program2) {
|
|
|
41826
42131
|
process.exit(2);
|
|
41827
42132
|
}
|
|
41828
42133
|
const dir = pinnedVersionDir();
|
|
41829
|
-
if ((0,
|
|
42134
|
+
if ((0, import_node_fs74.existsSync)((0, import_node_path58.join)(dir, "bin", "lake")) && !opts.force) {
|
|
41830
42135
|
printInfo(`already installed at ${dir}`);
|
|
41831
42136
|
return;
|
|
41832
42137
|
}
|
|
@@ -41862,18 +42167,18 @@ function registerLeanCommand(program2) {
|
|
|
41862
42167
|
});
|
|
41863
42168
|
lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
|
|
41864
42169
|
const dir = pinnedVersionDir();
|
|
41865
|
-
if (!(0,
|
|
42170
|
+
if (!(0, import_node_fs74.existsSync)(dir)) {
|
|
41866
42171
|
printInfo("nothing to remove");
|
|
41867
42172
|
return;
|
|
41868
42173
|
}
|
|
41869
|
-
(0,
|
|
42174
|
+
(0, import_node_fs74.rmSync)(dir, { recursive: true, force: true });
|
|
41870
42175
|
printInfo(`removed ${dir}`);
|
|
41871
42176
|
});
|
|
41872
42177
|
}
|
|
41873
42178
|
|
|
41874
42179
|
// src/cli.ts
|
|
41875
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.34.1-experimental.
|
|
41876
|
-
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.1-experimental.
|
|
42180
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.34.1-experimental.56274e2").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) => {
|
|
42181
|
+
installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.1-experimental.56274e2");
|
|
41877
42182
|
setUserNamedServiceUrl(program.opts().serviceUrl);
|
|
41878
42183
|
try {
|
|
41879
42184
|
await foldLegacyLocalCredential();
|