@codacy/verity-cli 0.34.2 → 0.34.4

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/bin/verity.js +1001 -620
  3. package/package.json +1 -1
package/bin/verity.js CHANGED
@@ -2928,7 +2928,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2928
2928
  * @param {(string | Function)} text - string to add, or a function returning a string
2929
2929
  * @return {Command} `this` command for chaining
2930
2930
  */
2931
- addHelpText(position, text) {
2931
+ addHelpText(position, text2) {
2932
2932
  const allowedValues = ["beforeAll", "before", "after", "afterAll"];
2933
2933
  if (!allowedValues.includes(position)) {
2934
2934
  throw new Error(`Unexpected value for position to addHelpText.
@@ -2937,10 +2937,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
2937
2937
  const helpEvent = `${position}Help`;
2938
2938
  this.on(helpEvent, (context) => {
2939
2939
  let helpStr;
2940
- if (typeof text === "function") {
2941
- helpStr = text({ error: context.error, command: context.command });
2940
+ if (typeof text2 === "function") {
2941
+ helpStr = text2({ error: context.error, command: context.command });
2942
2942
  } else {
2943
- helpStr = text;
2943
+ helpStr = text2;
2944
2944
  }
2945
2945
  if (helpStr) {
2946
2946
  context.write(`${helpStr}
@@ -3919,8 +3919,8 @@ var require_Collection = __commonJS2({
3919
3919
  return this.items.every((node) => {
3920
3920
  if (!identity.isPair(node))
3921
3921
  return false;
3922
- const n = node.value;
3923
- return n == null || allowScalar && identity.isScalar(n) && n.value == null && !n.commentBefore && !n.comment && !n.tag;
3922
+ const n2 = node.value;
3923
+ return n2 == null || allowScalar && identity.isScalar(n2) && n2.value == null && !n2.commentBefore && !n2.comment && !n2.tag;
3924
3924
  });
3925
3925
  }
3926
3926
  /**
@@ -3982,14 +3982,14 @@ var require_foldFlowLines = __commonJS2({
3982
3982
  var FOLD_FLOW = "flow";
3983
3983
  var FOLD_BLOCK = "block";
3984
3984
  var FOLD_QUOTED = "quoted";
3985
- function foldFlowLines(text, indent, mode2 = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
3985
+ function foldFlowLines(text2, indent, mode2 = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
3986
3986
  if (!lineWidth || lineWidth < 0)
3987
- return text;
3987
+ return text2;
3988
3988
  if (lineWidth < minContentWidth)
3989
3989
  minContentWidth = 0;
3990
3990
  const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
3991
- if (text.length <= endStep)
3992
- return text;
3991
+ if (text2.length <= endStep)
3992
+ return text2;
3993
3993
  const folds = [];
3994
3994
  const escapedFolds = {};
3995
3995
  let end = lineWidth - indent.length;
@@ -4006,14 +4006,14 @@ var require_foldFlowLines = __commonJS2({
4006
4006
  let escStart = -1;
4007
4007
  let escEnd = -1;
4008
4008
  if (mode2 === FOLD_BLOCK) {
4009
- i2 = consumeMoreIndentedLines(text, i2, indent.length);
4009
+ i2 = consumeMoreIndentedLines(text2, i2, indent.length);
4010
4010
  if (i2 !== -1)
4011
4011
  end = i2 + endStep;
4012
4012
  }
4013
- for (let ch; ch = text[i2 += 1]; ) {
4013
+ for (let ch; ch = text2[i2 += 1]; ) {
4014
4014
  if (mode2 === FOLD_QUOTED && ch === "\\") {
4015
4015
  escStart = i2;
4016
- switch (text[i2 + 1]) {
4016
+ switch (text2[i2 + 1]) {
4017
4017
  case "x":
4018
4018
  i2 += 3;
4019
4019
  break;
@@ -4030,12 +4030,12 @@ var require_foldFlowLines = __commonJS2({
4030
4030
  }
4031
4031
  if (ch === "\n") {
4032
4032
  if (mode2 === FOLD_BLOCK)
4033
- i2 = consumeMoreIndentedLines(text, i2, indent.length);
4033
+ i2 = consumeMoreIndentedLines(text2, i2, indent.length);
4034
4034
  end = i2 + indent.length + endStep;
4035
4035
  split = void 0;
4036
4036
  } else {
4037
4037
  if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") {
4038
- const next = text[i2 + 1];
4038
+ const next = text2[i2 + 1];
4039
4039
  if (next && next !== " " && next !== "\n" && next !== " ")
4040
4040
  split = i2;
4041
4041
  }
@@ -4047,12 +4047,12 @@ var require_foldFlowLines = __commonJS2({
4047
4047
  } else if (mode2 === FOLD_QUOTED) {
4048
4048
  while (prev === " " || prev === " ") {
4049
4049
  prev = ch;
4050
- ch = text[i2 += 1];
4050
+ ch = text2[i2 += 1];
4051
4051
  overflow = true;
4052
4052
  }
4053
4053
  const j = i2 > escEnd + 1 ? i2 - 2 : escStart - 1;
4054
4054
  if (escapedFolds[j])
4055
- return text;
4055
+ return text2;
4056
4056
  folds.push(j);
4057
4057
  escapedFolds[j] = true;
4058
4058
  end = j + endStep;
@@ -4067,39 +4067,39 @@ var require_foldFlowLines = __commonJS2({
4067
4067
  if (overflow && onOverflow)
4068
4068
  onOverflow();
4069
4069
  if (folds.length === 0)
4070
- return text;
4070
+ return text2;
4071
4071
  if (onFold)
4072
4072
  onFold();
4073
- let res = text.slice(0, folds[0]);
4073
+ let res = text2.slice(0, folds[0]);
4074
4074
  for (let i3 = 0; i3 < folds.length; ++i3) {
4075
4075
  const fold2 = folds[i3];
4076
- const end2 = folds[i3 + 1] || text.length;
4076
+ const end2 = folds[i3 + 1] || text2.length;
4077
4077
  if (fold2 === 0)
4078
4078
  res = `
4079
- ${indent}${text.slice(0, end2)}`;
4079
+ ${indent}${text2.slice(0, end2)}`;
4080
4080
  else {
4081
4081
  if (mode2 === FOLD_QUOTED && escapedFolds[fold2])
4082
- res += `${text[fold2]}\\`;
4082
+ res += `${text2[fold2]}\\`;
4083
4083
  res += `
4084
- ${indent}${text.slice(fold2 + 1, end2)}`;
4084
+ ${indent}${text2.slice(fold2 + 1, end2)}`;
4085
4085
  }
4086
4086
  }
4087
4087
  return res;
4088
4088
  }
4089
- function consumeMoreIndentedLines(text, i2, indent) {
4089
+ function consumeMoreIndentedLines(text2, i2, indent) {
4090
4090
  let end = i2;
4091
4091
  let start2 = i2 + 1;
4092
- let ch = text[start2];
4092
+ let ch = text2[start2];
4093
4093
  while (ch === " " || ch === " ") {
4094
4094
  if (i2 < start2 + indent) {
4095
- ch = text[++i2];
4095
+ ch = text2[++i2];
4096
4096
  } else {
4097
4097
  do {
4098
- ch = text[++i2];
4098
+ ch = text2[++i2];
4099
4099
  } while (ch && ch !== "\n");
4100
4100
  end = i2;
4101
4101
  start2 = i2 + 1;
4102
- ch = text[start2];
4102
+ ch = text2[start2];
4103
4103
  }
4104
4104
  }
4105
4105
  return end;
@@ -5360,18 +5360,18 @@ var require_stringifyNumber = __commonJS2({
5360
5360
  const num = typeof value === "number" ? value : Number(value);
5361
5361
  if (!isFinite(num))
5362
5362
  return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
5363
- let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
5364
- if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^\d/.test(n)) {
5365
- let i2 = n.indexOf(".");
5363
+ let n2 = Object.is(value, -0) ? "-0" : JSON.stringify(value);
5364
+ if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^\d/.test(n2)) {
5365
+ let i2 = n2.indexOf(".");
5366
5366
  if (i2 < 0) {
5367
- i2 = n.length;
5368
- n += ".";
5367
+ i2 = n2.length;
5368
+ n2 += ".";
5369
5369
  }
5370
- let d = minFractionDigits - (n.length - i2 - 1);
5370
+ let d = minFractionDigits - (n2.length - i2 - 1);
5371
5371
  while (d-- > 0)
5372
- n += "0";
5372
+ n2 += "0";
5373
5373
  }
5374
- return n;
5374
+ return n2;
5375
5375
  }
5376
5376
  exports2.stringifyNumber = stringifyNumber;
5377
5377
  }
@@ -5615,9 +5615,9 @@ var require_binary = __commonJS2({
5615
5615
  type ?? (type = Scalar.Scalar.BLOCK_LITERAL);
5616
5616
  if (type !== Scalar.Scalar.QUOTE_DOUBLE) {
5617
5617
  const lineWidth = Math.max(ctx.options.lineWidth - ctx.indent.length, ctx.options.minContentWidth);
5618
- const n = Math.ceil(str3.length / lineWidth);
5619
- const lines = new Array(n);
5620
- for (let i2 = 0, o = 0; i2 < n; ++i2, o += lineWidth) {
5618
+ const n2 = Math.ceil(str3.length / lineWidth);
5619
+ const lines = new Array(n2);
5620
+ for (let i2 = 0, o = 0; i2 < n2; ++i2, o += lineWidth) {
5621
5621
  lines[i2] = str3.substr(o, lineWidth);
5622
5622
  }
5623
5623
  str3 = lines.join(type === Scalar.Scalar.BLOCK_LITERAL ? "\n" : " ");
@@ -5889,11 +5889,11 @@ var require_int2 = __commonJS2({
5889
5889
  str3 = `0x${str3}`;
5890
5890
  break;
5891
5891
  }
5892
- const n2 = BigInt(str3);
5893
- return sign === "-" ? BigInt(-1) * n2 : n2;
5892
+ const n3 = BigInt(str3);
5893
+ return sign === "-" ? BigInt(-1) * n3 : n3;
5894
5894
  }
5895
- const n = parseInt(str3, radix);
5896
- return sign === "-" ? -1 * n : n;
5895
+ const n2 = parseInt(str3, radix);
5896
+ return sign === "-" ? -1 * n2 : n2;
5897
5897
  }
5898
5898
  function intStringify(node, radix, prefix) {
5899
5899
  const { value } = node;
@@ -6042,15 +6042,15 @@ var require_timestamp = __commonJS2({
6042
6042
  function parseSexagesimal(str3, asBigInt) {
6043
6043
  const sign = str3[0];
6044
6044
  const parts2 = sign === "-" || sign === "+" ? str3.substring(1) : str3;
6045
- const num = (n) => asBigInt ? BigInt(n) : Number(n);
6045
+ const num = (n2) => asBigInt ? BigInt(n2) : Number(n2);
6046
6046
  const res = parts2.replace(/_/g, "").split(":").reduce((res2, p) => res2 * num(60) + num(p), num(0));
6047
6047
  return sign === "-" ? num(-1) * res : res;
6048
6048
  }
6049
6049
  function stringifySexagesimal(node) {
6050
6050
  let { value } = node;
6051
- let num = (n) => n;
6051
+ let num = (n2) => n2;
6052
6052
  if (typeof value === "bigint")
6053
- num = (n) => BigInt(n);
6053
+ num = (n2) => BigInt(n2);
6054
6054
  else if (isNaN(value) || !isFinite(value))
6055
6055
  return stringifyNumber.stringifyNumber(node);
6056
6056
  let sign = "";
@@ -6070,7 +6070,7 @@ var require_timestamp = __commonJS2({
6070
6070
  parts2.unshift(value);
6071
6071
  }
6072
6072
  }
6073
- return sign + parts2.map((n) => String(n).padStart(2, "0")).join(":").replace(/000000\d*$/, "");
6073
+ return sign + parts2.map((n2) => String(n2).padStart(2, "0")).join(":").replace(/000000\d*$/, "");
6074
6074
  }
6075
6075
  var intTime = {
6076
6076
  identify: (value) => typeof value === "bigint" || Number.isInteger(value),
@@ -7541,9 +7541,9 @@ var require_resolve_block_scalar = __commonJS2({
7541
7541
  if (!chomp && (ch === "-" || ch === "+"))
7542
7542
  chomp = ch;
7543
7543
  else {
7544
- const n = Number(ch);
7545
- if (!indent && n)
7546
- indent = n;
7544
+ const n2 = Number(ch);
7545
+ if (!indent && n2)
7546
+ indent = n2;
7547
7547
  else if (error === -1)
7548
7548
  error = offset + i2;
7549
7549
  }
@@ -8760,8 +8760,8 @@ var require_lexer = __commonJS2({
8760
8760
  return this.buffer[i2 + 1] === "\n";
8761
8761
  return false;
8762
8762
  }
8763
- charAt(n) {
8764
- return this.buffer[this.pos + n];
8763
+ charAt(n2) {
8764
+ return this.buffer[this.pos + n2];
8765
8765
  }
8766
8766
  continueScalar(offset) {
8767
8767
  let ch = this.buffer[offset];
@@ -8795,8 +8795,8 @@ var require_lexer = __commonJS2({
8795
8795
  end -= 1;
8796
8796
  return this.buffer.substring(this.pos, end);
8797
8797
  }
8798
- hasChars(n) {
8799
- return this.pos + n <= this.buffer.length;
8798
+ hasChars(n2) {
8799
+ return this.pos + n2 <= this.buffer.length;
8800
8800
  }
8801
8801
  setNext(state) {
8802
8802
  this.buffer = this.buffer.substring(this.pos);
@@ -8805,8 +8805,8 @@ var require_lexer = __commonJS2({
8805
8805
  this.next = state;
8806
8806
  return null;
8807
8807
  }
8808
- peek(n) {
8809
- return this.buffer.substr(this.pos, n);
8808
+ peek(n2) {
8809
+ return this.buffer.substr(this.pos, n2);
8810
8810
  }
8811
8811
  *parseNext(next) {
8812
8812
  switch (next) {
@@ -8855,8 +8855,8 @@ var require_lexer = __commonJS2({
8855
8855
  else
8856
8856
  break;
8857
8857
  }
8858
- const n = (yield* this.pushCount(dirEnd)) + (yield* this.pushSpaces(true));
8859
- yield* this.pushCount(line2.length - n);
8858
+ const n2 = (yield* this.pushCount(dirEnd)) + (yield* this.pushSpaces(true));
8859
+ yield* this.pushCount(line2.length - n2);
8860
8860
  this.pushNewline();
8861
8861
  return "stream";
8862
8862
  }
@@ -8894,9 +8894,9 @@ var require_lexer = __commonJS2({
8894
8894
  if (!ch1 && !this.atEnd)
8895
8895
  return this.setNext("block-start");
8896
8896
  if ((ch0 === "-" || ch0 === "?" || ch0 === ":") && isEmpty(ch1)) {
8897
- const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
8897
+ const n2 = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
8898
8898
  this.indentNext = this.indentValue + 1;
8899
- this.indentValue += n;
8899
+ this.indentValue += n2;
8900
8900
  return yield* this.parseBlockStart();
8901
8901
  }
8902
8902
  return "doc";
@@ -8906,10 +8906,10 @@ var require_lexer = __commonJS2({
8906
8906
  const line2 = this.getLine();
8907
8907
  if (line2 === null)
8908
8908
  return this.setNext("doc");
8909
- let n = yield* this.pushIndicators();
8910
- switch (line2[n]) {
8909
+ let n2 = yield* this.pushIndicators();
8910
+ switch (line2[n2]) {
8911
8911
  case "#":
8912
- yield* this.pushCount(line2.length - n);
8912
+ yield* this.pushCount(line2.length - n2);
8913
8913
  // fallthrough
8914
8914
  case void 0:
8915
8915
  yield* this.pushNewline();
@@ -8932,9 +8932,9 @@ var require_lexer = __commonJS2({
8932
8932
  return yield* this.parseQuotedScalar();
8933
8933
  case "|":
8934
8934
  case ">":
8935
- n += yield* this.parseBlockScalarHeader();
8936
- n += yield* this.pushSpaces(true);
8937
- yield* this.pushCount(line2.length - n);
8935
+ n2 += yield* this.parseBlockScalarHeader();
8936
+ n2 += yield* this.pushSpaces(true);
8937
+ yield* this.pushCount(line2.length - n2);
8938
8938
  yield* this.pushNewline();
8939
8939
  return yield* this.parseBlockScalar();
8940
8940
  default:
@@ -8965,18 +8965,18 @@ var require_lexer = __commonJS2({
8965
8965
  return yield* this.parseLineStart();
8966
8966
  }
8967
8967
  }
8968
- let n = 0;
8969
- while (line2[n] === ",") {
8970
- n += yield* this.pushCount(1);
8971
- n += yield* this.pushSpaces(true);
8968
+ let n2 = 0;
8969
+ while (line2[n2] === ",") {
8970
+ n2 += yield* this.pushCount(1);
8971
+ n2 += yield* this.pushSpaces(true);
8972
8972
  this.flowKey = false;
8973
8973
  }
8974
- n += yield* this.pushIndicators();
8975
- switch (line2[n]) {
8974
+ n2 += yield* this.pushIndicators();
8975
+ switch (line2[n2]) {
8976
8976
  case void 0:
8977
8977
  return "flow";
8978
8978
  case "#":
8979
- yield* this.pushCount(line2.length - n);
8979
+ yield* this.pushCount(line2.length - n2);
8980
8980
  return "flow";
8981
8981
  case "{":
8982
8982
  case "[":
@@ -9020,10 +9020,10 @@ var require_lexer = __commonJS2({
9020
9020
  end = this.buffer.indexOf("'", end + 2);
9021
9021
  } else {
9022
9022
  while (end !== -1) {
9023
- let n = 0;
9024
- while (this.buffer[end - 1 - n] === "\\")
9025
- n += 1;
9026
- if (n % 2 === 0)
9023
+ let n2 = 0;
9024
+ while (this.buffer[end - 1 - n2] === "\\")
9025
+ n2 += 1;
9026
+ if (n2 % 2 === 0)
9027
9027
  break;
9028
9028
  end = this.buffer.indexOf('"', end + 1);
9029
9029
  }
@@ -9177,11 +9177,11 @@ var require_lexer = __commonJS2({
9177
9177
  yield* this.pushToIndex(end + 1, true);
9178
9178
  return inFlow ? "flow" : "doc";
9179
9179
  }
9180
- *pushCount(n) {
9181
- if (n > 0) {
9182
- yield this.buffer.substr(this.pos, n);
9183
- this.pos += n;
9184
- return n;
9180
+ *pushCount(n2) {
9181
+ if (n2 > 0) {
9182
+ yield this.buffer.substr(this.pos, n2);
9183
+ this.pos += n2;
9184
+ return n2;
9185
9185
  }
9186
9186
  return 0;
9187
9187
  }
@@ -9255,12 +9255,12 @@ var require_lexer = __commonJS2({
9255
9255
  do {
9256
9256
  ch = this.buffer[++i2];
9257
9257
  } while (ch === " " || allowTabs && ch === " ");
9258
- const n = i2 - this.pos;
9259
- if (n > 0) {
9260
- yield this.buffer.substr(this.pos, n);
9258
+ const n2 = i2 - this.pos;
9259
+ if (n2 > 0) {
9260
+ yield this.buffer.substr(this.pos, n2);
9261
9261
  this.pos = i2;
9262
9262
  }
9263
- return n;
9263
+ return n2;
9264
9264
  }
9265
9265
  *pushUntil(test) {
9266
9266
  let i2 = this.pos;
@@ -9528,8 +9528,8 @@ var require_parser = __commonJS2({
9528
9528
  }
9529
9529
  yield* this.pop();
9530
9530
  }
9531
- peek(n) {
9532
- return this.stack[this.stack.length - n];
9531
+ peek(n2) {
9532
+ return this.stack[this.stack.length - n2];
9533
9533
  }
9534
9534
  *pop(error) {
9535
9535
  const token = error ?? this.stack.pop();
@@ -10895,8 +10895,8 @@ var require_web_tree_sitter2 = __commonJS2({
10895
10895
  }, "getMemory");
10896
10896
  var isInternalSym = /* @__PURE__ */ __name((symName) => ["__cpp_exception", "__c_longjmp", "__wasm_apply_data_relocs", "__dso_handle", "__tls_size", "__tls_align", "__set_stack_limits", "_emscripten_tls_init", "__wasm_init_tls", "__wasm_call_ctors", "__start_em_asm", "__stop_em_asm", "__start_em_js", "__stop_em_js"].includes(symName) || symName.startsWith("__em_js__"), "isInternalSym");
10897
10897
  var uleb128EncodeWithLen = /* @__PURE__ */ __name((arr) => {
10898
- const n = arr.length;
10899
- return [n % 128 | 128, n >> 7, ...arr];
10898
+ const n2 = arr.length;
10899
+ return [n2 % 128 | 128, n2 >> 7, ...arr];
10900
10900
  }, "uleb128EncodeWithLen");
10901
10901
  var wasmTypeCodes = {
10902
10902
  "i": 127,
@@ -13001,13 +13001,13 @@ var require_web_tree_sitter2 = __commonJS2({
13001
13001
  symbols.push(65535);
13002
13002
  }
13003
13003
  }
13004
- for (let i2 = 0, n = typesBySymbol.length; i2 < n; i2++) {
13004
+ for (let i2 = 0, n2 = typesBySymbol.length; i2 < n2; i2++) {
13005
13005
  if (types.includes(typesBySymbol[i2])) {
13006
13006
  symbols.push(i2);
13007
13007
  }
13008
13008
  }
13009
13009
  const symbolsAddress = C._malloc(SIZE_OF_INT * symbols.length);
13010
- for (let i2 = 0, n = symbols.length; i2 < n; i2++) {
13010
+ for (let i2 = 0, n2 = symbols.length; i2 < n2; i2++) {
13011
13011
  C.setValue(symbolsAddress + i2 * SIZE_OF_INT, symbols[i2], "i32");
13012
13012
  }
13013
13013
  marshalNode(this);
@@ -13196,7 +13196,7 @@ var require_web_tree_sitter2 = __commonJS2({
13196
13196
  }
13197
13197
  };
13198
13198
  function unmarshalCaptures(query, tree, address, patternIndex, result) {
13199
- for (let i2 = 0, n = result.length; i2 < n; i2++) {
13199
+ for (let i2 = 0, n2 = result.length; i2 < n2; i2++) {
13200
13200
  const captureIndex = C.getValue(address, "i32");
13201
13201
  address += SIZE_OF_INT;
13202
13202
  const node = unmarshalNode(tree, address);
@@ -13335,13 +13335,13 @@ var require_web_tree_sitter2 = __commonJS2({
13335
13335
  assertInternal(internal);
13336
13336
  this[0] = address;
13337
13337
  this.types = new Array(C._ts_language_symbol_count(this[0]));
13338
- for (let i2 = 0, n = this.types.length; i2 < n; i2++) {
13338
+ for (let i2 = 0, n2 = this.types.length; i2 < n2; i2++) {
13339
13339
  if (C._ts_language_symbol_type(this[0], i2) < 2) {
13340
13340
  this.types[i2] = C.UTF8ToString(C._ts_language_symbol_name(this[0], i2));
13341
13341
  }
13342
13342
  }
13343
13343
  this.fields = new Array(C._ts_language_field_count(this[0]) + 1);
13344
- for (let i2 = 0, n = this.fields.length; i2 < n; i2++) {
13344
+ for (let i2 = 0, n2 = this.fields.length; i2 < n2; i2++) {
13345
13345
  const fieldName = C._ts_language_field_name_for_id(this[0], i2);
13346
13346
  if (fieldName !== 0) {
13347
13347
  this.fields[i2] = C.UTF8ToString(fieldName);
@@ -13844,8 +13844,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13844
13844
  } else {
13845
13845
  const captureName = steps[1].name;
13846
13846
  const stringValue = steps[2].value;
13847
- const matches = /* @__PURE__ */ __name((n) => n.text === stringValue, "matches");
13848
- const doesNotMatch = /* @__PURE__ */ __name((n) => n.text !== stringValue, "doesNotMatch");
13847
+ const matches = /* @__PURE__ */ __name((n2) => n2.text === stringValue, "matches");
13848
+ const doesNotMatch = /* @__PURE__ */ __name((n2) => n2.text !== stringValue, "doesNotMatch");
13849
13849
  textPredicates[index].push((captures) => {
13850
13850
  const nodes = [];
13851
13851
  for (const c of captures) {
@@ -13882,11 +13882,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13882
13882
  for (const c of captures) {
13883
13883
  if (c.name === captureName) nodes.push(c.node.text);
13884
13884
  }
13885
- const test = /* @__PURE__ */ __name((text, positive) => {
13886
- return positive ? regex.test(text) : !regex.test(text);
13885
+ const test = /* @__PURE__ */ __name((text2, positive) => {
13886
+ return positive ? regex.test(text2) : !regex.test(text2);
13887
13887
  }, "test");
13888
13888
  if (nodes.length === 0) return !isPositive;
13889
- return matchAll2 ? nodes.every((text) => test(text, isPositive)) : nodes.some((text) => test(text, isPositive));
13889
+ return matchAll2 ? nodes.every((text2) => test(text2, isPositive)) : nodes.some((text2) => test(text2, isPositive));
13890
13890
  });
13891
13891
  }
13892
13892
  __name(parseMatchPredicate, "parseMatchPredicate");
@@ -13916,7 +13916,7 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13916
13916
  if (c.name === captureName) nodes.push(c.node.text);
13917
13917
  }
13918
13918
  if (nodes.length === 0) return !isPositive;
13919
- return nodes.every((text) => values.includes(text)) === isPositive;
13919
+ return nodes.every((text2) => values.includes(text2)) === isPositive;
13920
13920
  });
13921
13921
  }
13922
13922
  __name(parseAnyOfPredicate, "parseAnyOfPredicate");
@@ -15210,8 +15210,8 @@ function commitsSincePaths(sha, paths) {
15210
15210
  encoding: "utf-8",
15211
15211
  stdio: ["pipe", "pipe", "pipe"]
15212
15212
  }).trim();
15213
- const n = Number.parseInt(out2, 10);
15214
- return Number.isFinite(n) ? n : null;
15213
+ const n2 = Number.parseInt(out2, 10);
15214
+ return Number.isFinite(n2) ? n2 : null;
15215
15215
  } catch {
15216
15216
  return null;
15217
15217
  }
@@ -15579,15 +15579,15 @@ function reverifyNudge(who) {
15579
15579
  }
15580
15580
  return null;
15581
15581
  }
15582
- function isLegacyPerRepoCredential(auth2) {
15583
- return auth2.source === "local" || auth2.source === "global" && auth2.keyed === true;
15582
+ function isLegacyPerRepoCredential(auth3) {
15583
+ return auth3.source === "local" || auth3.source === "global" && auth3.keyed === true;
15584
15584
  }
15585
- async function shouldUpgradeOnLogin(auth2) {
15586
- if (!isLegacyPerRepoCredential(auth2)) return false;
15587
- if (auth2.userId == null) return true;
15585
+ async function shouldUpgradeOnLogin(auth3) {
15586
+ if (!isLegacyPerRepoCredential(auth3)) return false;
15587
+ if (auth3.userId == null) return true;
15588
15588
  const bare = await readGlobalCredential("");
15589
15589
  if (bare?.userId == null) return true;
15590
- return bare.userId === auth2.userId;
15590
+ return bare.userId === auth3.userId;
15591
15591
  }
15592
15592
  function authDenialRemedy(error) {
15593
15593
  if (error.startsWith("STALE_VERIFICATION")) {
@@ -15712,11 +15712,11 @@ function startSpinner(label2, opts = {}) {
15712
15712
  },
15713
15713
  succeed(message) {
15714
15714
  finish(() => {
15715
- const text = message ?? current;
15715
+ const text2 = message ?? current;
15716
15716
  const clock = showElapsed ? ` (${secondsSince(start2)})` : "";
15717
15717
  stream.write(
15718
- color ? ` ${GREEN2}\u2713${RESET} ${text}${DIM2}${clock}${RESET}
15719
- ` : ` \u2713 ${text}${clock}
15718
+ color ? ` ${GREEN2}\u2713${RESET} ${text2}${DIM2}${clock}${RESET}
15719
+ ` : ` \u2713 ${text2}${clock}
15720
15720
  `
15721
15721
  );
15722
15722
  });
@@ -16073,8 +16073,8 @@ async function loginOnce(opts) {
16073
16073
 
16074
16074
  // src/commands/auth.ts
16075
16075
  function registerAuthCommands(program2) {
16076
- const auth2 = program2.command("auth").description("Manage project authentication");
16077
- auth2.command("register").description("Register a project with Verity").requiredOption("--project <name>", "Project name").option("--remote <url>", "Git remote URL (auto-detected if omitted)").action(async (opts) => {
16076
+ const auth3 = program2.command("auth").description("Manage project authentication");
16077
+ auth3.command("register").description("Register a project with Verity").requiredOption("--project <name>", "Project name").option("--remote <url>", "Git remote URL (auto-detected if omitted)").action(async (opts) => {
16078
16078
  const globals = program2.opts();
16079
16079
  const serviceUrl = globals.serviceUrl ?? DEFAULT_SERVICE_URL;
16080
16080
  let remote = opts.remote;
@@ -16101,7 +16101,7 @@ function registerAuthCommands(program2) {
16101
16101
  if (email) printInfo(`Authenticated as: ${email}`);
16102
16102
  printJson({ project_id: projectId, service_url: resolvedUrl });
16103
16103
  });
16104
- auth2.command("verify").description("Verify the current token is valid").action(async () => {
16104
+ auth3.command("verify").description("Verify the current token is valid").action(async () => {
16105
16105
  const globals = program2.opts();
16106
16106
  const tokenResult = await resolveToken(globals.token);
16107
16107
  if (!tokenResult.ok) {
@@ -16127,7 +16127,7 @@ function registerAuthCommands(program2) {
16127
16127
  printInfo(`Token valid. Project: ${result.data.project_name}`);
16128
16128
  printJson(result.data);
16129
16129
  });
16130
- auth2.command("discover").description("Check if a project is registered").option("--remote <url>", "Git remote URL (auto-detected if omitted)").action(async (opts) => {
16130
+ auth3.command("discover").description("Check if a project is registered").option("--remote <url>", "Git remote URL (auto-detected if omitted)").action(async (opts) => {
16131
16131
  const globals = program2.opts();
16132
16132
  let remote = opts.remote;
16133
16133
  if (!remote) {
@@ -16718,8 +16718,8 @@ function registerLogoutCommand(program2) {
16718
16718
  explain(result.error);
16719
16719
  process.exit(1);
16720
16720
  }
16721
- const n = result.data.revoked;
16722
- printInfo(`Revoked ${n} login${n === 1 ? "" : "s"}. \u2713`);
16721
+ const n2 = result.data.revoked;
16722
+ printInfo(`Revoked ${n2} login${n2 === 1 ? "" : "s"}. \u2713`);
16723
16723
  if (opts.others) {
16724
16724
  printInfo(" This machine is still signed in.");
16725
16725
  return;
@@ -17444,13 +17444,13 @@ function scrub(s) {
17444
17444
  var installed = false;
17445
17445
  var wroteBanner = false;
17446
17446
  var banner = "";
17447
- function append(text) {
17447
+ function append(text2) {
17448
17448
  try {
17449
17449
  const dir = projectPath(DEBUG_LOG_DIR);
17450
17450
  const file = projectPath(STDERR_LOG_FILE);
17451
17451
  (0, import_node_fs9.mkdirSync)(dir, { recursive: true });
17452
17452
  rotateIfNeeded(file);
17453
- (0, import_node_fs9.appendFileSync)(file, text);
17453
+ (0, import_node_fs9.appendFileSync)(file, text2);
17454
17454
  } catch {
17455
17455
  }
17456
17456
  }
@@ -17472,19 +17472,19 @@ function installStderrLog(cmd, argv, version) {
17472
17472
  const result = original(...args2);
17473
17473
  try {
17474
17474
  const chunk = args2[0];
17475
- const text = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
17475
+ const text2 = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
17476
17476
  ensureBanner();
17477
- append(scrub(text));
17477
+ append(scrub(text2));
17478
17478
  } catch {
17479
17479
  }
17480
17480
  return result;
17481
17481
  };
17482
17482
  process.stderr.write = tee;
17483
17483
  }
17484
- function logToFileOnly(text) {
17484
+ function logToFileOnly(text2) {
17485
17485
  if (!installed) return;
17486
17486
  ensureBanner();
17487
- append(text.endsWith("\n") ? text : `${text}
17487
+ append(text2.endsWith("\n") ? text2 : `${text2}
17488
17488
  `);
17489
17489
  }
17490
17490
 
@@ -18055,8 +18055,8 @@ var import_promises5 = require("node:fs/promises");
18055
18055
  var import_node_fs12 = require("node:fs");
18056
18056
  var import_node_child_process6 = require("node:child_process");
18057
18057
  var import_node_crypto2 = require("node:crypto");
18058
- function stripImageReferences(text) {
18059
- return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
18058
+ function stripImageReferences(text2) {
18059
+ return text2.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
18060
18060
  }
18061
18061
  function bufferTmpPath() {
18062
18062
  return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto2.randomBytes)(4).toString("hex")}.tmp`;
@@ -18631,12 +18631,12 @@ function renderIndex(orgName, nodes) {
18631
18631
  ""
18632
18632
  ];
18633
18633
  const byKind = /* @__PURE__ */ new Map();
18634
- for (const n of nodes) byKind.set(n.kind, [...byKind.get(n.kind) ?? [], n]);
18634
+ for (const n2 of nodes) byKind.set(n2.kind, [...byKind.get(n2.kind) ?? [], n2]);
18635
18635
  for (const kind2 of ORG_KINDS) {
18636
18636
  const list2 = byKind.get(kind2);
18637
18637
  if (!list2?.length) continue;
18638
18638
  lines.push(`## ${kind2}/ (${list2.length})`);
18639
- for (const n of list2) lines.push(`- [[${orgNodePath(n).split("/")[1].replace(/\.md$/, "")}]] \u2014 ${n.title} \xB7 ${n.origin}`);
18639
+ for (const n2 of list2) lines.push(`- [[${orgNodePath(n2).split("/")[1].replace(/\.md$/, "")}]] \u2014 ${n2.title} \xB7 ${n2.origin}`);
18640
18640
  lines.push("");
18641
18641
  }
18642
18642
  if (nodes.length === 0) lines.push("No org knowledge yet.", "");
@@ -18661,26 +18661,26 @@ async function pullOrgKnowledge(opts) {
18661
18661
  const page = res.data;
18662
18662
  if (page.unchanged) return { ok: true, status: "unchanged", received: 0, dir };
18663
18663
  const org = page.organization;
18664
- const nodes = org ? (page.nodes ?? []).flatMap((n) => typeof n.tag_id === "string" && typeof n.title === "string" && typeof n.body === "string" ? [{
18665
- tag_id: n.tag_id,
18666
- node_id: typeof n.node_id === "string" ? n.node_id : "",
18667
- kind: typeof n.kind === "string" ? n.kind : "domain",
18668
- title: n.title,
18669
- body: n.body.slice(0, BODY_MAX),
18670
- origin: typeof n.origin === "string" ? n.origin : "",
18671
- signal: typeof n.signal === "string" ? n.signal : "",
18672
- tier: typeof n.tier === "number" ? n.tier : null,
18673
- applies_to: Array.isArray(n.applies_to) ? n.applies_to.filter((v) => typeof v === "string") : [],
18674
- source_repo_count: typeof n.source_repo_count === "number" ? n.source_repo_count : 1,
18675
- promoted_at: typeof n.promoted_at === "string" ? n.promoted_at : ""
18664
+ const nodes = org ? (page.nodes ?? []).flatMap((n2) => typeof n2.tag_id === "string" && typeof n2.title === "string" && typeof n2.body === "string" ? [{
18665
+ tag_id: n2.tag_id,
18666
+ node_id: typeof n2.node_id === "string" ? n2.node_id : "",
18667
+ kind: typeof n2.kind === "string" ? n2.kind : "domain",
18668
+ title: n2.title,
18669
+ body: n2.body.slice(0, BODY_MAX),
18670
+ origin: typeof n2.origin === "string" ? n2.origin : "",
18671
+ signal: typeof n2.signal === "string" ? n2.signal : "",
18672
+ tier: typeof n2.tier === "number" ? n2.tier : null,
18673
+ applies_to: Array.isArray(n2.applies_to) ? n2.applies_to.filter((v) => typeof v === "string") : [],
18674
+ source_repo_count: typeof n2.source_repo_count === "number" ? n2.source_repo_count : 1,
18675
+ promoted_at: typeof n2.promoted_at === "string" ? n2.promoted_at : ""
18676
18676
  }] : []) : [];
18677
18677
  const written = /* @__PURE__ */ new Set();
18678
18678
  await (0, import_promises7.mkdir)(dir, { recursive: true });
18679
- for (const n of nodes) {
18680
- const rel = orgNodePath(n);
18679
+ for (const n2 of nodes) {
18680
+ const rel = orgNodePath(n2);
18681
18681
  if (written.has(rel)) continue;
18682
18682
  await (0, import_promises7.mkdir)((0, import_node_path14.join)(dir, rel.split("/")[0]), { recursive: true });
18683
- await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
18683
+ await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, rel), renderOrgNode(n2, org?.name ?? ""));
18684
18684
  written.add(rel);
18685
18685
  }
18686
18686
  for (const rel of state.files) {
@@ -18779,9 +18779,9 @@ function readOpened(fd, size) {
18779
18779
  const buffer = Buffer.alloc(size);
18780
18780
  let offset = 0;
18781
18781
  while (offset < size) {
18782
- const n = (0, import_node_fs15.readSync)(fd, buffer, offset, size - offset, offset);
18783
- if (n === 0) break;
18784
- offset += n;
18782
+ const n2 = (0, import_node_fs15.readSync)(fd, buffer, offset, size - offset, offset);
18783
+ if (n2 === 0) break;
18784
+ offset += n2;
18785
18785
  }
18786
18786
  return buffer.subarray(0, offset);
18787
18787
  } finally {
@@ -18922,9 +18922,9 @@ var STOPWORDS = /* @__PURE__ */ new Set([
18922
18922
  "within",
18923
18923
  "without"
18924
18924
  ]);
18925
- function tokenize(text) {
18925
+ function tokenize(text2) {
18926
18926
  return new Set(
18927
- text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOPWORDS.has(w))
18927
+ text2.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOPWORDS.has(w))
18928
18928
  );
18929
18929
  }
18930
18930
  function jaccardKeywords(a, b) {
@@ -18976,18 +18976,18 @@ function posteriorFor(kind2, own, pooled) {
18976
18976
  return { alpha: p.alpha + Math.max(0, own.alpha), beta: p.beta + Math.max(0, own.beta) };
18977
18977
  }
18978
18978
  function posteriorMean(p) {
18979
- const n = p.alpha + p.beta;
18980
- return n <= 0 ? DEFAULT_PRIOR_MEAN : p.alpha / n;
18979
+ const n2 = p.alpha + p.beta;
18980
+ return n2 <= 0 ? DEFAULT_PRIOR_MEAN : p.alpha / n2;
18981
18981
  }
18982
18982
  function scoreCandidates(nodes, ctx, opts = {}) {
18983
18983
  const floor = opts.relevanceFloor ?? RELEVANCE_FLOOR;
18984
18984
  const out2 = [];
18985
- for (const n of nodes) {
18986
- const rel = relevance(n, ctx);
18985
+ for (const n2 of nodes) {
18986
+ const rel = relevance(n2, ctx);
18987
18987
  if (rel.score < floor) continue;
18988
- const post = posteriorFor(n.kind, opts.posteriors?.get(n.id), opts.kindPosteriors?.get(n.kind));
18988
+ const post = posteriorFor(n2.kind, opts.posteriors?.get(n2.id), opts.kindPosteriors?.get(n2.kind));
18989
18989
  const usefulness = posteriorMean(post);
18990
- out2.push({ id: n.id, score: rel.score * usefulness, relevance: rel.score, usefulness, via: rel.via });
18990
+ out2.push({ id: n2.id, score: rel.score * usefulness, relevance: rel.score, usefulness, via: rel.via });
18991
18991
  }
18992
18992
  out2.sort((a, b) => b.score - a.score || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
18993
18993
  return out2;
@@ -19001,29 +19001,29 @@ var MAX_BUDGET_TOKENS = 4e3;
19001
19001
  var MAX_NODE_FILE_BYTES = 64 * 1024;
19002
19002
  var MIN_SCORE = RELEVANCE_FLOOR * 0.5;
19003
19003
  var ORG_MIN_SHARED_TERMS = 2;
19004
- function orgTerms(text) {
19004
+ function orgTerms(text2) {
19005
19005
  return new Set(
19006
- text.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
19006
+ text2.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
19007
19007
  );
19008
19008
  }
19009
19009
  function sharedTerms(a, b) {
19010
- let n = 0;
19011
- for (const w of a) if (b.has(w)) n++;
19012
- return n;
19010
+ let n2 = 0;
19011
+ for (const w of a) if (b.has(w)) n2++;
19012
+ return n2;
19013
19013
  }
19014
- function orgNodeToLocal(n) {
19014
+ function orgNodeToLocal(n2) {
19015
19015
  return {
19016
- path: `org:${n.tag_id}`,
19017
- nodeId: n.tag_id,
19018
- kind: n.kind,
19019
- title: n.title,
19020
- body: n.body.slice(0, 2e3),
19016
+ path: `org:${n2.tag_id}`,
19017
+ nodeId: n2.tag_id,
19018
+ kind: n2.kind,
19019
+ title: n2.title,
19020
+ body: n2.body.slice(0, 2e3),
19021
19021
  fileGlobs: [],
19022
19022
  confidence: 0.5,
19023
19023
  citedCount: 0,
19024
- tokenEstimate: Math.ceil((n.title.length + n.body.length) / 4) + 20,
19024
+ tokenEstimate: Math.ceil((n2.title.length + n2.body.length) / 4) + 20,
19025
19025
  scope: "org",
19026
- origin: n.origin
19026
+ origin: n2.origin
19027
19027
  };
19028
19028
  }
19029
19029
  function globMatch(glob, filePath) {
@@ -19136,11 +19136,11 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
19136
19136
  } catch {
19137
19137
  }
19138
19138
  if (nodes.length === 0) return null;
19139
- const scored = nodes.map((n) => ({
19140
- ...n,
19141
- score: scoreNode(n, promptTokens, taskFiles)
19139
+ const scored = nodes.map((n2) => ({
19140
+ ...n2,
19141
+ score: scoreNode(n2, promptTokens, taskFiles)
19142
19142
  }));
19143
- const filtered = scored.filter((n) => n.score >= MIN_SCORE);
19143
+ const filtered = scored.filter((n2) => n2.score >= MIN_SCORE);
19144
19144
  filtered.sort((a, b) => b.score - a.score);
19145
19145
  const selected = [];
19146
19146
  let tokensUsed = 0;
@@ -19153,7 +19153,7 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
19153
19153
  const lines = [
19154
19154
  "## Project Knowledge (auto-injected)",
19155
19155
  "",
19156
- `*${selected.length} node(s) relevant to your current task. See \`.verity/memory/index.md\` for the full knowledge base${selected.some((n) => n.scope === "org") ? ", and `~/.verity/orgs/` for what the organization's other repositories learned" : ""}.*`,
19156
+ `*${selected.length} node(s) relevant to your current task. See \`.verity/memory/index.md\` for the full knowledge base${selected.some((n2) => n2.scope === "org") ? ", and `~/.verity/orgs/` for what the organization's other repositories learned" : ""}.*`,
19157
19157
  ""
19158
19158
  ];
19159
19159
  for (const node of selected) {
@@ -19286,15 +19286,15 @@ function runHook(hooks) {
19286
19286
  return false;
19287
19287
  }
19288
19288
  }
19289
- function appendInRoot(root, name2, text, hooks = {}) {
19289
+ function appendInRoot(root, name2, text2, hooks = {}) {
19290
19290
  return writeVerified(root, name2, hooks, true, (fd) => {
19291
- (0, import_node_fs17.writeSync)(fd, text);
19291
+ (0, import_node_fs17.writeSync)(fd, text2);
19292
19292
  });
19293
19293
  }
19294
- function replaceInRoot(root, name2, text, hooks = {}) {
19294
+ function replaceInRoot(root, name2, text2, hooks = {}) {
19295
19295
  return writeVerified(root, name2, hooks, false, (fd) => {
19296
19296
  (0, import_node_fs17.ftruncateSync)(fd, 0);
19297
- (0, import_node_fs17.writeSync)(fd, text, 0);
19297
+ (0, import_node_fs17.writeSync)(fd, text2, 0);
19298
19298
  });
19299
19299
  }
19300
19300
 
@@ -19317,9 +19317,9 @@ function parseInjectionEvent(raw) {
19317
19317
  if (!nonNegInt(o.eligible, 1e5) || !nonNegInt(o.tokens, 1e6)) return null;
19318
19318
  if (!Array.isArray(o.nodes) || o.nodes.length > MAX_NODES) return null;
19319
19319
  const nodes = [];
19320
- for (const n of o.nodes) {
19321
- if (!n || typeof n !== "object") return null;
19322
- const r = n;
19320
+ for (const n2 of o.nodes) {
19321
+ if (!n2 || typeof n2 !== "object") return null;
19322
+ const r = n2;
19323
19323
  if (typeof r.id !== "string" || !SAFE_ID.test(r.id)) return null;
19324
19324
  if (typeof r.score !== "number" || !Number.isFinite(r.score) || r.score < 0 || r.score > 10) return null;
19325
19325
  if (typeof r.via !== "string" || !VIA.test(r.via)) return null;
@@ -19484,12 +19484,12 @@ function ensureVerityGitignore() {
19484
19484
  if (hasSupersededMemory && !memoryIsCommitted) {
19485
19485
  next = fenceMemoryLines(next);
19486
19486
  }
19487
- let text = next.join("\n");
19487
+ let text2 = next.join("\n");
19488
19488
  if (!hasMarker) {
19489
- const sep7 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19490
- text = text + sep7 + VERITY_GITIGNORE_BLOCK;
19489
+ const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
19490
+ text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
19491
19491
  }
19492
- if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
19492
+ if (text2 !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text2);
19493
19493
  return verified(
19494
19494
  memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
19495
19495
  );
@@ -19515,13 +19515,13 @@ function writeFencedBlock() {
19515
19515
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
19516
19516
  let lines = content.split("\n").map((l) => BREAKING_ENTRIES.has(l.trim()) ? ".verity/*" : l);
19517
19517
  lines = fenceMemoryLines(lines);
19518
- let text = lines.join("\n");
19518
+ let text2 = lines.join("\n");
19519
19519
  if (!hasMarker) {
19520
- const sep7 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19521
- text = text + sep7 + VERITY_GITIGNORE_BLOCK;
19520
+ const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
19521
+ text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
19522
19522
  }
19523
19523
  try {
19524
- (0, import_node_fs19.writeFileSync)(".gitignore", text);
19524
+ (0, import_node_fs19.writeFileSync)(".gitignore", text2);
19525
19525
  return true;
19526
19526
  } catch {
19527
19527
  return false;
@@ -19671,9 +19671,9 @@ function readFileInside(baseDir, candidate, maxBytes) {
19671
19671
  // src/lib/glob-match.ts
19672
19672
  function globToRegex(glob) {
19673
19673
  let out2 = "";
19674
- const n = glob.length;
19674
+ const n2 = glob.length;
19675
19675
  let i2 = 0;
19676
- while (i2 < n) {
19676
+ while (i2 < n2) {
19677
19677
  const c = glob[i2];
19678
19678
  if (c === "*" && glob[i2 + 1] === "*") {
19679
19679
  if (i2 > 0 && glob[i2 - 1] === "/" && glob[i2 + 2] === "/") {
@@ -19681,7 +19681,7 @@ function globToRegex(glob) {
19681
19681
  i2 += 3;
19682
19682
  continue;
19683
19683
  }
19684
- if (i2 > 0 && glob[i2 - 1] === "/" && i2 + 2 === n) {
19684
+ if (i2 > 0 && glob[i2 - 1] === "/" && i2 + 2 === n2) {
19685
19685
  out2 = out2.slice(0, -1) + "(?:/.*)?";
19686
19686
  i2 += 2;
19687
19687
  continue;
@@ -19821,7 +19821,7 @@ async function readSyncBaseline() {
19821
19821
  try {
19822
19822
  const parsed = JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
19823
19823
  if (Array.isArray(parsed?.nodes)) {
19824
- for (const n of parsed.nodes) if (n?.path) out2.set(n.path, n.hash ?? null);
19824
+ for (const n2 of parsed.nodes) if (n2?.path) out2.set(n2.path, n2.hash ?? null);
19825
19825
  } else if (Array.isArray(parsed?.paths)) {
19826
19826
  for (const p of parsed.paths) out2.set(p, null);
19827
19827
  }
@@ -19901,7 +19901,7 @@ async function applyMemoryWrites(writes, opts = {}) {
19901
19901
  }
19902
19902
  }
19903
19903
  const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
19904
- for (const n of notes) logLines.push(` - ${n}`);
19904
+ for (const n2 of notes) logLines.push(` - ${n2}`);
19905
19905
  try {
19906
19906
  const existing = (0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
19907
19907
  await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
@@ -20500,26 +20500,26 @@ var CLAUDE_MD_PROSE_LEGACY = [
20500
20500
  "superseded \u2014 ignore them unless investigating history."
20501
20501
  ].join("\n");
20502
20502
  var PRESERVE_PLACEHOLDER = "<!-- Add binding, hand-curated guidance here; it survives Verity regeneration. -->";
20503
- function* scanLines(text) {
20503
+ function* scanLines(text2) {
20504
20504
  let offset = 0;
20505
20505
  let inFence = false;
20506
- for (const line2 of text.split("\n")) {
20506
+ for (const line2 of text2.split("\n")) {
20507
20507
  const isFence = /^(`{3,}|~{3,})/.test(line2.trim());
20508
20508
  if (isFence) inFence = !inFence;
20509
20509
  yield { line: line2, start: offset, inFence: inFence || isFence };
20510
20510
  offset += line2.length + 1;
20511
20511
  }
20512
20512
  }
20513
- function findMarker(text, marker, from = 0) {
20514
- for (const { line: line2, start: start2, inFence } of scanLines(text)) {
20513
+ function findMarker(text2, marker, from = 0) {
20514
+ for (const { line: line2, start: start2, inFence } of scanLines(text2)) {
20515
20515
  if (!inFence && start2 >= from && line2.startsWith(marker)) {
20516
20516
  return start2;
20517
20517
  }
20518
20518
  }
20519
20519
  return -1;
20520
20520
  }
20521
- function hasLegacyMemoryBlock(text) {
20522
- return findMarker(text, LEGACY_MD_START) !== -1;
20521
+ function hasLegacyMemoryBlock(text2) {
20522
+ return findMarker(text2, LEGACY_MD_START) !== -1;
20523
20523
  }
20524
20524
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
20525
20525
  const claudeMdPath = (0, import_node_path19.join)(cwd, "CLAUDE.md");
@@ -20719,10 +20719,10 @@ var STOP = /* @__PURE__ */ new Set([
20719
20719
  "verify",
20720
20720
  "check"
20721
20721
  ]);
20722
- function pendingTokens(text) {
20723
- if (!text || typeof text !== "string") return [];
20722
+ function pendingTokens(text2) {
20723
+ if (!text2 || typeof text2 !== "string") return [];
20724
20724
  const out2 = /* @__PURE__ */ new Set();
20725
- for (const raw of text.toLowerCase().split(/[^a-z0-9]+/)) {
20725
+ for (const raw of text2.toLowerCase().split(/[^a-z0-9]+/)) {
20726
20726
  if (raw.length <= 3) continue;
20727
20727
  if (STOP.has(raw)) continue;
20728
20728
  out2.add(raw);
@@ -20737,8 +20737,8 @@ function overlapCoefficient(a, b) {
20737
20737
  for (const t of a) if (setB.has(t)) shared++;
20738
20738
  return shared / Math.min(a.length, b.length);
20739
20739
  }
20740
- function isRepeatOfAny(text, priorFingerprints, threshold = REPEAT_THRESHOLD) {
20741
- const tokens = pendingTokens(text);
20740
+ function isRepeatOfAny(text2, priorFingerprints, threshold = REPEAT_THRESHOLD) {
20741
+ const tokens = pendingTokens(text2);
20742
20742
  if (tokens.length === 0) return false;
20743
20743
  return priorFingerprints.some((prior) => overlapCoefficient(tokens, prior) >= threshold);
20744
20744
  }
@@ -21246,7 +21246,7 @@ function compactState(s) {
21246
21246
  // cached row.
21247
21247
  g: s.goal.map((g) => [g.seq, ms(g.at), g.hash, g.superseded_by, g.text ?? 0, g.text_len ?? 0, g.source ?? 0, g.status ?? 0, g.repeats ?? 0, g.truncated ? 1 : 0, g.collapsed ? 1 : 0, g.delivered ? ms(g.delivered.at) : 0, g.delivered?.seq ?? 0, g.delivered?.summary ?? 0]),
21248
21248
  a: s.authored?.map((a) => [a.path, a.origin, a.edits, a.hunks, a.adds, a.dels, a.hash_now, a.hash_at_last_verdict, a.first_seq, a.last_seq]) ?? null,
21249
- n: s.not_mine?.map((n) => [n.path, n.reason, ms(n.at), n.head_sha]) ?? null,
21249
+ n: s.not_mine?.map((n2) => [n2.path, n2.reason, ms(n2.at), n2.head_sha]) ?? null,
21250
21250
  t: s.statements.map((x) => [x.anchor_key, x.file, x.line, x.pattern_id, x.title_hash, x.register, x.line_sha, x.said_at_seq, ms(x.said_at), x.outcome, x.outcome_at ? ms(x.outcome_at) : 0, x.repeats, x.carried ? 1 : 0]),
21251
21251
  c: s.commands.map((c) => [c.cls, c.cmd_hash, c.head, c.last_status, ms(c.last_at), c.last_seq, c.streak, c.edits_since, c.runs]),
21252
21252
  d: [s.divergence.events.map((e) => [e.kind, e.path, ms(e.at)]), s.divergence.counts, s.divergence.seen],
@@ -21257,10 +21257,10 @@ function compactState(s) {
21257
21257
  }
21258
21258
  function expandState(raw) {
21259
21259
  try {
21260
- const iso = (n2) => new Date(n2).toISOString();
21260
+ const iso = (n3) => new Date(n3).toISOString();
21261
21261
  const g = raw.g;
21262
21262
  const a = raw.a;
21263
- const n = raw.n;
21263
+ const n2 = raw.n;
21264
21264
  const t = raw.t;
21265
21265
  const c = raw.c;
21266
21266
  const dv = raw.d;
@@ -21306,7 +21306,7 @@ function expandState(raw) {
21306
21306
  // which always folds the live log. If the cache is ever put on that path,
21307
21307
  // the full list has to be encoded — see the note on `authored_all`.
21308
21308
  authored_all: decodedAuthored ?? [],
21309
- not_mine: n?.map((x) => ({
21309
+ not_mine: n2?.map((x) => ({
21310
21310
  path: x[0],
21311
21311
  reason: x[1],
21312
21312
  at: iso(x[2]),
@@ -21428,8 +21428,8 @@ function assessContinuity(i2) {
21428
21428
  // src/lib/dossier/reanchor.ts
21429
21429
  var import_node_crypto8 = require("node:crypto");
21430
21430
  var import_node_fs25 = require("node:fs");
21431
- function lineSha(text) {
21432
- return (0, import_node_crypto8.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21431
+ function lineSha(text2) {
21432
+ return (0, import_node_crypto8.createHash)("sha256").update(text2.trim()).digest("hex").slice(0, HASH_WIDTH);
21433
21433
  }
21434
21434
  function fileHash(path) {
21435
21435
  try {
@@ -21553,7 +21553,7 @@ function projectMemory(state, opts) {
21553
21553
  }));
21554
21554
  }
21555
21555
  if (state.not_mine && state.not_mine.length > 0) {
21556
- p.not_mine = { n: state.not_mine.length, paths: state.not_mine.map((n) => n.path) };
21556
+ p.not_mine = { n: state.not_mine.length, paths: state.not_mine.map((n2) => n2.path) };
21557
21557
  } else if (state.not_mine === null) {
21558
21558
  p.not_mine = { n: -1, paths: [] };
21559
21559
  }
@@ -21647,8 +21647,8 @@ function stateProvenance(state, opts = {}) {
21647
21647
  for (const c of state.commands) {
21648
21648
  items.push({ key: `command:${c.cls}:${c.cmd_hash}`, kind: "command", owner: "agent", age: age(c.last_seq, false) });
21649
21649
  }
21650
- for (const n of state.not_mine ?? []) {
21651
- items.push({ key: `not_mine:${n.path}`, kind: "not_mine", owner: "git", age: "this_session" });
21650
+ for (const n2 of state.not_mine ?? []) {
21651
+ items.push({ key: `not_mine:${n2.path}`, kind: "not_mine", owner: "git", age: "this_session" });
21652
21652
  }
21653
21653
  for (const m of state.marks) {
21654
21654
  items.push({ key: `mark:${m.kind}:${m.seq}`, kind: "mark", owner: "agent", age: age(m.seq, false) });
@@ -21902,10 +21902,10 @@ function recordGoal(d, prompt, source2 = "prompt") {
21902
21902
  appendEvent(d, { k: "goal_continue", text: prompt.slice(0, 64) });
21903
21903
  return;
21904
21904
  }
21905
- const text = prompt.slice(0, MAX_GOAL_CHARS);
21905
+ const text2 = prompt.slice(0, MAX_GOAL_CHARS);
21906
21906
  appendEvent(d, {
21907
21907
  k: "goal",
21908
- text,
21908
+ text: text2,
21909
21909
  text_len: prompt.length,
21910
21910
  source: source2,
21911
21911
  ...prompt.length > MAX_GOAL_CHARS && { truncated: true }
@@ -21979,9 +21979,9 @@ function normaliseClass(cls) {
21979
21979
  const known = ["test", "build", "lint", "typecheck", "git", "other"];
21980
21980
  return known.includes(cls) ? cls : "other";
21981
21981
  }
21982
- function toStatus(n) {
21983
- if (n === 0) return "pass";
21984
- if (n === 1) return "fail";
21982
+ function toStatus(n2) {
21983
+ if (n2 === 0) return "pass";
21984
+ if (n2 === 1) return "fail";
21985
21985
  return "unknown";
21986
21986
  }
21987
21987
  function recordVerdict(d, v) {
@@ -22187,10 +22187,10 @@ function registerIntentCommands(program2) {
22187
22187
  arm: "injected",
22188
22188
  eligible: injection.eligible,
22189
22189
  tokens: injection.tokensUsed,
22190
- nodes: injection.nodes.map((n) => ({
22191
- id: n.nodeId,
22192
- score: Math.round(n.score * 1e3) / 1e3,
22193
- via: `${n.fileGlobs.length ? "g" : ""}${n.scope === "org" ? "o" : ""}x`
22190
+ nodes: injection.nodes.map((n2) => ({
22191
+ id: n2.nodeId,
22192
+ score: Math.round(n2.score * 1e3) / 1e3,
22193
+ via: `${n2.fileGlobs.length ? "g" : ""}${n2.scope === "org" ? "o" : ""}x`
22194
22194
  }))
22195
22195
  });
22196
22196
  }
@@ -23005,8 +23005,8 @@ function buildCompactionContext(session) {
23005
23005
  `${r.projection.fold.refused} earlier finding(s) were dropped because the code they pointed at no longer matches. They are resolved; do not revisit them.`
23006
23006
  );
23007
23007
  }
23008
- const text = lines.join("\n");
23009
- if (text.length <= MAX_CHARS) return text;
23008
+ const text2 = lines.join("\n");
23009
+ if (text2.length <= MAX_CHARS) return text2;
23010
23010
  const trimmed = [...lines.slice(0, 5), ...lines.slice(5, 5 + 2)].join("\n");
23011
23011
  return trimmed.length <= MAX_CHARS ? trimmed : null;
23012
23012
  }
@@ -23324,9 +23324,9 @@ function declaredDependencies(root, files) {
23324
23324
  for (const path of pythonManifests) {
23325
23325
  if (!(0, import_node_fs31.existsSync)(path)) continue;
23326
23326
  try {
23327
- const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23328
- for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
23329
- for (const line2 of text.split("\n")) {
23327
+ const text2 = (0, import_node_fs31.readFileSync)(path, "utf-8");
23328
+ for (const m of text2.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
23329
+ for (const line2 of text2.split("\n")) {
23330
23330
  if (!/dependencies\s*=/.test(line2)) continue;
23331
23331
  for (const m of line2.matchAll(/["']([A-Za-z][A-Za-z0-9._-]+)/g)) names2.push(m[1]);
23332
23332
  }
@@ -23340,8 +23340,8 @@ function declaredDependencies(root, files) {
23340
23340
  for (const path of goMods) {
23341
23341
  if (!(0, import_node_fs31.existsSync)(path)) continue;
23342
23342
  try {
23343
- const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23344
- for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
23343
+ const text2 = (0, import_node_fs31.readFileSync)(path, "utf-8");
23344
+ for (const m of text2.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
23345
23345
  names2.push(m[1].replace(/^github\.com\//, ""));
23346
23346
  }
23347
23347
  } catch {
@@ -23351,8 +23351,8 @@ function declaredDependencies(root, files) {
23351
23351
  const path = (0, import_node_path28.join)(root, file);
23352
23352
  if (!(0, import_node_fs31.existsSync)(path)) continue;
23353
23353
  try {
23354
- const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23355
- for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
23354
+ const text2 = (0, import_node_fs31.readFileSync)(path, "utf-8");
23355
+ for (const m of text2.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
23356
23356
  } catch {
23357
23357
  }
23358
23358
  }
@@ -24483,8 +24483,8 @@ function formatFindingsSummary(fc) {
24483
24483
  if (!fc) return "-";
24484
24484
  const parts2 = [];
24485
24485
  for (const [key, abbrev] of SEV_ABBREV) {
24486
- const n = fc[key] ?? 0;
24487
- if (n > 0) parts2.push(`${n} ${abbrev}`);
24486
+ const n2 = fc[key] ?? 0;
24487
+ if (n2 > 0) parts2.push(`${n2} ${abbrev}`);
24488
24488
  }
24489
24489
  return parts2.length > 0 ? parts2.join(", ") : "clean";
24490
24490
  }
@@ -24674,13 +24674,13 @@ function parseJsonState(raw) {
24674
24674
  }
24675
24675
  function parseLegacyState(raw) {
24676
24676
  const parts2 = raw.split(":");
24677
- const n = parseInt(parts2[0], 10);
24678
- if (isNaN(n)) return null;
24677
+ const n2 = parseInt(parts2[0], 10);
24678
+ if (isNaN(n2)) return null;
24679
24679
  return {
24680
- attempts: n,
24680
+ attempts: n2,
24681
24681
  // The old file has no separate block count; the old counter is the closest
24682
24682
  // honest answer, and it errs toward releasing sooner rather than later.
24683
- blocks: n,
24683
+ blocks: n2,
24684
24684
  fingerprint: parts2.slice(3).join(":") || null,
24685
24685
  commit: parts2[1] ?? "",
24686
24686
  ts: parseInt(parts2[2] ?? "0", 10)
@@ -24723,12 +24723,12 @@ function parseDuration(input) {
24723
24723
  if (!m) {
24724
24724
  return { ok: false, error: `Could not read "${input}" as a duration. Use 30m, 45s, or 1h.` };
24725
24725
  }
24726
- const n = parseInt(m[1], 10);
24727
- if (!Number.isFinite(n) || n <= 0) {
24726
+ const n2 = parseInt(m[1], 10);
24727
+ if (!Number.isFinite(n2) || n2 <= 0) {
24728
24728
  return { ok: false, error: `A duration must be a positive number of seconds, minutes or hours \u2014 got "${input}".` };
24729
24729
  }
24730
24730
  const unit = m[2] ?? "m";
24731
- const seconds = unit === "s" ? n : unit === "h" ? n * 3600 : n * 60;
24731
+ const seconds = unit === "s" ? n2 : unit === "h" ? n2 * 3600 : n2 * 60;
24732
24732
  if (seconds > MAX_WINDOW_SECONDS) {
24733
24733
  return {
24734
24734
  ok: false,
@@ -25060,9 +25060,9 @@ function readTextInput(value, flag, readStdin2 = () => (0, import_node_fs39.read
25060
25060
  if (raw.length > MAX_STDIN_BYTES) {
25061
25061
  return { ok: false, error: `${flag} from stdin is ${raw.length} bytes; the limit is ${MAX_STDIN_BYTES}.` };
25062
25062
  }
25063
- const text = raw.toString("utf8").replace(/\r?\n$/, "");
25064
- if (!text.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
25065
- return { ok: true, text };
25063
+ const text2 = raw.toString("utf8").replace(/\r?\n$/, "");
25064
+ if (!text2.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
25065
+ return { ok: true, text: text2 };
25066
25066
  }
25067
25067
 
25068
25068
  // src/lib/terminal-text.ts
@@ -25080,8 +25080,8 @@ function terminalUrl(value) {
25080
25080
  // src/commands/feedback.ts
25081
25081
  function registerFeedbackCommand(program2) {
25082
25082
  const feedbackCmd = program2.command("feedback").description("Send feedback to the Verity team");
25083
- feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text, opts) => {
25084
- await sendMessageArg(text, opts, program2.opts());
25083
+ feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text2, opts) => {
25084
+ await sendMessageArg(text2, opts, program2.opts());
25085
25085
  });
25086
25086
  feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.); a note of - is read from stdin").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action, inlineNote, opts) => {
25087
25087
  const globals = program2.opts();
@@ -25596,8 +25596,8 @@ function extractFileSymbols(path, content, signals) {
25596
25596
  add(declNameOn(deleted, rules));
25597
25597
  }
25598
25598
  for (const [start2, end] of signals.addedRanges) {
25599
- for (let n = start2; n <= Math.min(end, lines.length); n++) {
25600
- add(declNameOn(lines[n - 1] ?? "", rules));
25599
+ for (let n2 = start2; n2 <= Math.min(end, lines.length); n2++) {
25600
+ add(declNameOn(lines[n2 - 1] ?? "", rules));
25601
25601
  }
25602
25602
  }
25603
25603
  const scanStarts = [
@@ -25606,8 +25606,8 @@ function extractFileSymbols(path, content, signals) {
25606
25606
  ];
25607
25607
  for (const start2 of scanStarts) {
25608
25608
  const floor = Math.max(1, start2 - ENCLOSING_SCAN_LINES);
25609
- for (let n = Math.min(start2, lines.length); n >= floor; n--) {
25610
- const name2 = declNameOn(lines[n - 1] ?? "", rules);
25609
+ for (let n2 = Math.min(start2, lines.length); n2 >= floor; n2--) {
25610
+ const name2 = declNameOn(lines[n2 - 1] ?? "", rules);
25611
25611
  if (acceptable(name2)) {
25612
25612
  add(name2);
25613
25613
  break;
@@ -25681,33 +25681,33 @@ function parseRgLine(line2) {
25681
25681
  if (first <= 0) return null;
25682
25682
  const second = line2.indexOf(":", first + 1);
25683
25683
  if (second < 0) return null;
25684
- const n = parseInt(line2.slice(first + 1, second), 10);
25685
- if (!Number.isFinite(n) || n < 1) return null;
25686
- return { file: line2.slice(0, first), line: n, text: line2.slice(second + 1) };
25684
+ const n2 = parseInt(line2.slice(first + 1, second), 10);
25685
+ if (!Number.isFinite(n2) || n2 < 1) return null;
25686
+ return { file: line2.slice(0, first), line: n2, text: line2.slice(second + 1) };
25687
25687
  }
25688
25688
  var isWordChar = (c) => c !== void 0 && /[A-Za-z0-9_]/.test(c);
25689
- function wordHit(text, symbol) {
25689
+ function wordHit(text2, symbol) {
25690
25690
  let from = 0;
25691
25691
  for (; ; ) {
25692
- const at = text.indexOf(symbol, from);
25692
+ const at = text2.indexOf(symbol, from);
25693
25693
  if (at < 0) return false;
25694
- const before = at === 0 ? void 0 : text[at - 1];
25695
- const after = text[at + symbol.length];
25694
+ const before = at === 0 ? void 0 : text2[at - 1];
25695
+ const after = text2[at + symbol.length];
25696
25696
  if (!isWordChar(before) && !isWordChar(after)) return true;
25697
25697
  from = at + 1;
25698
25698
  }
25699
25699
  }
25700
- function isContractLine(text, symbol) {
25700
+ function isContractLine(text2, symbol) {
25701
25701
  for (const kw of ["implements", "extends"]) {
25702
25702
  let from = 0;
25703
25703
  for (; ; ) {
25704
- const at = text.indexOf(kw, from);
25704
+ const at = text2.indexOf(kw, from);
25705
25705
  if (at < 0) break;
25706
25706
  from = at + 1;
25707
- const before = at === 0 ? void 0 : text[at - 1];
25708
- const after = text[at + kw.length];
25707
+ const before = at === 0 ? void 0 : text2[at - 1];
25708
+ const after = text2[at + kw.length];
25709
25709
  if (isWordChar(before) || isWordChar(after)) continue;
25710
- let clause = text.slice(at + kw.length);
25710
+ let clause = text2.slice(at + kw.length);
25711
25711
  const stop2 = Math.min(
25712
25712
  ...[clause.indexOf(";"), clause.indexOf("{")].filter((i2) => i2 >= 0)
25713
25713
  );
@@ -25739,29 +25739,29 @@ function partitionSites(rgLines, symbols, opts) {
25739
25739
  if (opts.sentPaths.has(h.file)) continue;
25740
25740
  if (opts.isExcluded(h.file)) continue;
25741
25741
  if (!isCodeSiteFile(h.file)) continue;
25742
- const text = h.text.trim();
25743
- if (text.length === 0 || IMPORT_LINE.test(h.text)) continue;
25744
- if (COMMENT_LINE.test(text)) continue;
25745
- if (BARE_MEMBER_LINE.test(text) || GO_IMPORT_PATH_LINE.test(text)) continue;
25746
- const n = perFile.get(h.file) ?? 0;
25747
- if (n >= MAX_SITES_PER_FILE) continue;
25742
+ const text2 = h.text.trim();
25743
+ if (text2.length === 0 || IMPORT_LINE.test(h.text)) continue;
25744
+ if (COMMENT_LINE.test(text2)) continue;
25745
+ if (BARE_MEMBER_LINE.test(text2) || GO_IMPORT_PATH_LINE.test(text2)) continue;
25746
+ const n2 = perFile.get(h.file) ?? 0;
25747
+ if (n2 >= MAX_SITES_PER_FILE) continue;
25748
25748
  const site = {
25749
25749
  file: h.file,
25750
25750
  line: h.line,
25751
- text: text.slice(0, SITE_TEXT_MAX),
25751
+ text: text2.slice(0, SITE_TEXT_MAX),
25752
25752
  symbol: h.symbol,
25753
25753
  // R2 falls out of R1 for free: a word search for `Sym` already matches
25754
25754
  // `implements Sym` / `extends Sym` lines — classification is all R2 is.
25755
- ...isContractLine(text, h.symbol) ? { kind: "contract" } : {}
25755
+ ...isContractLine(text2, h.symbol) ? { kind: "contract" } : {}
25756
25756
  };
25757
25757
  if (isTestPath(h.file)) {
25758
25758
  if (tests.length < MAX_TEST_SLOTS) {
25759
25759
  tests.push(site);
25760
- perFile.set(h.file, n + 1);
25760
+ perFile.set(h.file, n2 + 1);
25761
25761
  }
25762
25762
  } else if (callers.length + tests.length < MAX_SITES) {
25763
25763
  callers.push(site);
25764
- perFile.set(h.file, n + 1);
25764
+ perFile.set(h.file, n2 + 1);
25765
25765
  }
25766
25766
  }
25767
25767
  while (callers.length + tests.length > MAX_SITES) callers.pop();
@@ -25772,8 +25772,8 @@ var MAX_IMPORTERS_PER_FILE = 2;
25772
25772
  function moduleKey(path) {
25773
25773
  return path.replace(/\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/i, "").replace(/\/index$/, "");
25774
25774
  }
25775
- function importSpecifier(text) {
25776
- const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text);
25775
+ function importSpecifier(text2) {
25776
+ const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text2);
25777
25777
  return m?.[1] ?? null;
25778
25778
  }
25779
25779
  function resolveSpecifier(fromFile, spec) {
@@ -25809,9 +25809,9 @@ function partitionImporters(rgLines, changedPaths, opts) {
25809
25809
  if (!resolved) continue;
25810
25810
  const changed = changedByKey.get(resolved);
25811
25811
  if (!changed) continue;
25812
- const used = perFile.get(h.file) ?? 0;
25813
- if (used >= MAX_IMPORTERS_PER_FILE) continue;
25814
- perFile.set(h.file, used + 1);
25812
+ const used2 = perFile.get(h.file) ?? 0;
25813
+ if (used2 >= MAX_IMPORTERS_PER_FILE) continue;
25814
+ perFile.set(h.file, used2 + 1);
25815
25815
  out2.push({ file: h.file, line: h.line, text: h.text.trim().slice(0, SITE_TEXT_MAX), symbol: changed });
25816
25816
  }
25817
25817
  return out2;
@@ -25909,9 +25909,9 @@ function revisionSearch(root, rev) {
25909
25909
  const line2 = prefix && raw.startsWith(prefix) ? raw.slice(prefix.length) : raw;
25910
25910
  const hit = parseRgLine(line2);
25911
25911
  if (!hit) continue;
25912
- const n = perFile.get(hit.file) ?? 0;
25913
- if (n >= HITS_PER_FILE) continue;
25914
- perFile.set(hit.file, n + 1);
25912
+ const n2 = perFile.get(hit.file) ?? 0;
25913
+ if (n2 >= HITS_PER_FILE) continue;
25914
+ perFile.set(hit.file, n2 + 1);
25915
25915
  lines.push(`${hit.file}:${hit.line}:${hit.text.slice(0, HIT_TEXT_COLUMNS)}`);
25916
25916
  }
25917
25917
  return { ok: true, lines };
@@ -26030,9 +26030,9 @@ function extractEnclosingExcerpt(content, siteLine, path) {
26030
26030
  if (siteLine < 1 || siteLine > lines.length) return null;
26031
26031
  let declStart = null;
26032
26032
  const floor = Math.max(1, siteLine - EXCERPT_DECL_SCAN);
26033
- for (let n = siteLine; n >= floor; n--) {
26034
- if (declNameOn(lines[n - 1] ?? "", rules) !== null) {
26035
- declStart = n;
26033
+ for (let n2 = siteLine; n2 >= floor; n2--) {
26034
+ if (declNameOn(lines[n2 - 1] ?? "", rules) !== null) {
26035
+ declStart = n2;
26036
26036
  break;
26037
26037
  }
26038
26038
  }
@@ -26043,8 +26043,8 @@ function extractEnclosingExcerpt(content, siteLine, path) {
26043
26043
  start2 = Math.max(1, siteLine - (EXCERPT_MAX_LINES - 6));
26044
26044
  }
26045
26045
  const end = Math.min(lines.length, start2 + EXCERPT_MAX_LINES - 1);
26046
- const text = lines.slice(start2 - 1, end).join("\n").slice(0, EXCERPT_MAX_CHARS);
26047
- return { start_line: start2, text };
26046
+ const text2 = lines.slice(start2 - 1, end).join("\n").slice(0, EXCERPT_MAX_CHARS);
26047
+ return { start_line: start2, text: text2 };
26048
26048
  }
26049
26049
  function upgradeToExcerpts(rc, opts) {
26050
26050
  if (rc.state !== "ok") return;
@@ -26059,8 +26059,8 @@ function upgradeToExcerpts(rc, opts) {
26059
26059
  let totalBytes = 0;
26060
26060
  for (const site of ranked) {
26061
26061
  if (excerpts.length >= MAX_EXCERPTS) break;
26062
- const used = perFile.get(site.file) ?? 0;
26063
- if (used >= MAX_EXCERPTS_PER_FILE) continue;
26062
+ const used2 = perFile.get(site.file) ?? 0;
26063
+ if (used2 >= MAX_EXCERPTS_PER_FILE) continue;
26064
26064
  if (!contentCache.has(site.file)) contentCache.set(site.file, opts.readFile(site.file));
26065
26065
  const content = contentCache.get(site.file);
26066
26066
  if (content === null || content === void 0) continue;
@@ -26076,7 +26076,7 @@ function upgradeToExcerpts(rc, opts) {
26076
26076
  text: ex.text
26077
26077
  });
26078
26078
  totalBytes += ex.text.length;
26079
- perFile.set(site.file, used + 1);
26079
+ perFile.set(site.file, used2 + 1);
26080
26080
  }
26081
26081
  if (excerpts.length > 0) rc.excerpts = excerpts;
26082
26082
  }
@@ -27141,12 +27141,12 @@ function parseKnowledgeNote(raw) {
27141
27141
  if (!raw || typeof raw !== "object") return null;
27142
27142
  const o = raw;
27143
27143
  const node_id = typeof o.node_id === "string" ? o.node_id.trim() : "";
27144
- const text = typeof o.text === "string" ? o.text.trim() : "";
27145
- if (!node_id || !text) return null;
27146
- if (text.length > 1e3) return null;
27144
+ const text2 = typeof o.text === "string" ? o.text.trim() : "";
27145
+ if (!node_id || !text2) return null;
27146
+ if (text2.length > 1e3) return null;
27147
27147
  return {
27148
27148
  node_id,
27149
- text,
27149
+ text: text2,
27150
27150
  file: typeof o.file === "string" && o.file ? o.file : null,
27151
27151
  line: typeof o.line === "number" && Number.isFinite(o.line) && o.line > 0 ? Math.floor(o.line) : null
27152
27152
  };
@@ -27184,10 +27184,10 @@ function episodeForWire(e, humanSpoke) {
27184
27184
  var MAX_AGENT_CONTEXT_CHARS = 1500;
27185
27185
  var MAX_AGENT_ITEMS = 5;
27186
27186
  var REPORT_PREFIX = "Verity review (a report on the code just written \u2014 relay what matters to the user; it is not an instruction to you):";
27187
- function renderItem(label2, text, patternId, file, line2) {
27187
+ function renderItem(label2, text2, patternId, file, line2) {
27188
27188
  const where2 = file ? ` (${file}${line2 !== void 0 && line2 !== "" ? `:${line2}` : ""})` : "";
27189
27189
  const id = patternId ? ` [${patternId}]` : "";
27190
- return `- ${label2}${text}${where2}${id}`;
27190
+ return `- ${label2}${text2}${where2}${id}`;
27191
27191
  }
27192
27192
  function channelInputFrom(response, intentRepeat = 0, priorPendingFingerprints = []) {
27193
27193
  const metadata2 = response.metadata ?? {};
@@ -27269,11 +27269,11 @@ function buildAgentContext(input) {
27269
27269
  for (const p of input.pendingItems ?? []) {
27270
27270
  if (lines.length >= MAX_AGENT_ITEMS) break;
27271
27271
  if (p.pattern_id === "intent-misalignment") continue;
27272
- const text = p.description ?? p.title ?? p.reason;
27273
- if (!text) continue;
27274
- const seenBefore = isRepeatOfAny(text, input.priorPendingFingerprints ?? []);
27272
+ const text2 = p.description ?? p.title ?? p.reason;
27273
+ if (!text2) continue;
27274
+ const seenBefore = isRepeatOfAny(text2, input.priorPendingFingerprints ?? []);
27275
27275
  lines.push(
27276
- renderItem("", text, p.pattern_id, p.file, p.line) + (seenBefore ? "\n (raised earlier this session and still open \u2014 do not re-explain it; act on it or carry on)" : "")
27276
+ renderItem("", text2, p.pattern_id, p.file, p.line) + (seenBefore ? "\n (raised earlier this session and still open \u2014 do not re-explain it; act on it or carry on)" : "")
27277
27277
  );
27278
27278
  }
27279
27279
  if (lines.length === 0) return null;
@@ -27281,11 +27281,11 @@ function buildAgentContext(input) {
27281
27281
  ${lines.slice(0, MAX_AGENT_ITEMS).join("\n")}`;
27282
27282
  return truncateToCap(body2);
27283
27283
  }
27284
- function truncateToCap(text) {
27285
- if (text.length <= MAX_AGENT_CONTEXT_CHARS) return text;
27284
+ function truncateToCap(text2) {
27285
+ if (text2.length <= MAX_AGENT_CONTEXT_CHARS) return text2;
27286
27286
  const marker = "\n- (truncated)";
27287
27287
  const budget = MAX_AGENT_CONTEXT_CHARS - marker.length;
27288
- const lines = text.slice(0, budget).split("\n");
27288
+ const lines = text2.slice(0, budget).split("\n");
27289
27289
  lines.pop();
27290
27290
  return `${lines.join("\n")}${marker}`;
27291
27291
  }
@@ -27313,7 +27313,7 @@ function channelSilence(input) {
27313
27313
  // src/lib/cli-version.ts
27314
27314
  function cliVersion() {
27315
27315
  try {
27316
- return true ? "0.34.2" : "dev";
27316
+ return true ? "0.34.4" : "dev";
27317
27317
  } catch {
27318
27318
  return "dev";
27319
27319
  }
@@ -27668,10 +27668,10 @@ function interpretAnalyzerRun(run4) {
27668
27668
  function reconcileCoverage(changed, coverage) {
27669
27669
  const changedSet = new Set(changed);
27670
27670
  const reviewed = coverage.reviewed.filter((p) => changedSet.has(p));
27671
- const claimed = /* @__PURE__ */ new Set([...reviewed, ...coverage.notReviewed.map((n) => n.path)]);
27671
+ const claimed = /* @__PURE__ */ new Set([...reviewed, ...coverage.notReviewed.map((n2) => n2.path)]);
27672
27672
  const unaccounted = [...changedSet].filter((p) => !claimed.has(p)).sort();
27673
27673
  const notReviewed = [
27674
- ...coverage.notReviewed.filter((n) => changedSet.has(n.path)),
27674
+ ...coverage.notReviewed.filter((n2) => changedSet.has(n2.path)),
27675
27675
  ...unaccounted.map((path) => ({
27676
27676
  path,
27677
27677
  reason: "unaccounted",
@@ -27692,18 +27692,18 @@ function reconcileCoverage(changed, coverage) {
27692
27692
  }
27693
27693
  function resolveVerdict(proposed, coverage) {
27694
27694
  if (proposed === "FAIL") return "FAIL";
27695
- const blocking = coverage.notReviewed.filter((n) => (n.kind ?? "capacity") !== "policy");
27695
+ const blocking = coverage.notReviewed.filter((n2) => (n2.kind ?? "capacity") !== "policy");
27696
27696
  if (blocking.length === 0) return proposed;
27697
27697
  return "WARN";
27698
27698
  }
27699
27699
  function describeCoverage(coverage, maxPaths = 5) {
27700
- const relevant = coverage.notReviewed.filter((n) => (n.kind ?? "capacity") !== "policy");
27700
+ const relevant = coverage.notReviewed.filter((n2) => (n2.kind ?? "capacity") !== "policy");
27701
27701
  if (relevant.length === 0) return null;
27702
27702
  const byReason = /* @__PURE__ */ new Map();
27703
- for (const n of relevant) {
27704
- const key = `${n.reason}`;
27703
+ for (const n2 of relevant) {
27704
+ const key = `${n2.reason}`;
27705
27705
  const list2 = byReason.get(key) ?? [];
27706
- list2.push(n.path);
27706
+ list2.push(n2.path);
27707
27707
  byReason.set(key, list2);
27708
27708
  }
27709
27709
  const lines = [];
@@ -29145,10 +29145,10 @@ var MAX_WITHIN = 6;
29145
29145
  var PLACEHOLDER = "${\u2026}";
29146
29146
  var MAX_PARAMS = 12;
29147
29147
  var PY_LOCK_ITEM = /(?:lock|Lock|mutex|Mutex|semaphore|Semaphore)\b/;
29148
- var line = (n) => n.startPosition.row + 1;
29149
- var cap = (s, n) => {
29148
+ var line = (n2) => n2.startPosition.row + 1;
29149
+ var cap = (s, n2) => {
29150
29150
  const flat = s.replace(/\s+/g, " ");
29151
- return flat.length > n ? `${flat.slice(0, n)}\u2026` : flat;
29151
+ return flat.length > n2 ? `${flat.slice(0, n2)}\u2026` : flat;
29152
29152
  };
29153
29153
  function qualifierOf(node, spec) {
29154
29154
  if (spec.id === "go" && node.type === "method_declaration") {
@@ -29174,38 +29174,38 @@ function definitionsIn(root, spec) {
29174
29174
  const q = qualifierOf(owner, spec);
29175
29175
  out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind: kind2, extent, last, fn });
29176
29176
  };
29177
- const visit = (n) => {
29178
- const kind2 = spec.definitions[n.type];
29179
- if (kind2 && n.childForFieldName("body")) {
29180
- const nameNode = n.childForFieldName("name");
29177
+ const visit = (n2) => {
29178
+ const kind2 = spec.definitions[n2.type];
29179
+ if (kind2 && n2.childForFieldName("body")) {
29180
+ const nameNode = n2.childForFieldName("name");
29181
29181
  if (nameNode && nameNode.type !== "computed_property_name") {
29182
- const inClass = qualifierOf(n, spec) !== null;
29182
+ const inClass = qualifierOf(n2, spec) !== null;
29183
29183
  const k = spec.id === "python" ? inClass ? "method" : "function" : kind2;
29184
- add(nameNode.text, k, extentOf(n), n, n, n.parent?.type === "decorated_definition" ? n.parent : n);
29184
+ add(nameNode.text, k, extentOf(n2), n2, n2, n2.parent?.type === "decorated_definition" ? n2.parent : n2);
29185
29185
  }
29186
- } else if (spec.functionValues.has(n.type) && n.parent) {
29187
- const p = n.parent;
29188
- const kind3 = n.type === "arrow_function" ? "arrow" : n.type === "lambda" || n.type === "lambda_expression" ? "lambda" : "function";
29189
- const bound = p.childForFieldName("value")?.id === n.id;
29186
+ } else if (spec.functionValues.has(n2.type) && n2.parent) {
29187
+ const p = n2.parent;
29188
+ const kind3 = n2.type === "arrow_function" ? "arrow" : n2.type === "lambda" || n2.type === "lambda_expression" ? "lambda" : "function";
29189
+ const bound = p.childForFieldName("value")?.id === n2.id;
29190
29190
  if (bound && p.type === "variable_declarator" && p.childForFieldName("name")?.type === "identifier") {
29191
29191
  const decl = p.parent && p.parent.namedChildren.filter((c) => c.type === "variable_declarator").length === 1 ? p.parent : p;
29192
- add(p.childForFieldName("name").text, kind3, decl, n, p);
29192
+ add(p.childForFieldName("name").text, kind3, decl, n2, p);
29193
29193
  } else if (bound && (p.type === "public_field_definition" || p.type === "field_definition")) {
29194
29194
  const nameNode = p.childForFieldName("name") ?? p.childForFieldName("property");
29195
- if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind3, extentOf(p), n, p, p);
29195
+ if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind3, extentOf(p), n2, p, p);
29196
29196
  } else if (bound && p.type === "pair") {
29197
29197
  const key = p.childForFieldName("key");
29198
- if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind3, p, n, p);
29198
+ if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind3, p, n2, p);
29199
29199
  } else if (p.type === "arguments" && moduleCall(p.parent)) {
29200
29200
  const call = p.parent;
29201
29201
  const route = p.namedChildren[0];
29202
- const quoted = route && route.id !== n.id && route.type === "string" ? unquote2(route.text) : null;
29202
+ const quoted = route && route.id !== n2.id && route.type === "string" ? unquote2(route.text) : null;
29203
29203
  const path = quoted && /^[\w/:.{}*-]{1,60}$/.test(quoted) ? quoted : null;
29204
29204
  const callee = call.childForFieldName("function").text;
29205
- add(path ? `${callee} ${path}` : callee, kind3, call.parent, n, call);
29205
+ add(path ? `${callee} ${path}` : callee, kind3, call.parent, n2, call);
29206
29206
  }
29207
29207
  }
29208
- for (const c of n.namedChildren) visit(c);
29208
+ for (const c of n2.namedChildren) visit(c);
29209
29209
  };
29210
29210
  visit(root);
29211
29211
  return out2;
@@ -29219,10 +29219,10 @@ function unquote2(s) {
29219
29219
  const q3 = body2.startsWith('"""') || body2.startsWith("'''");
29220
29220
  return q3 ? body2.slice(3, -3) : body2.slice(1, -1);
29221
29221
  }
29222
- function callParts(n, spec) {
29223
- const args2 = n.childForFieldName("arguments");
29224
- if (spec.id === "java") return { receiver: n.childForFieldName("object"), name: n.childForFieldName("name")?.text ?? null, args: args2 };
29225
- let f = n.childForFieldName("function");
29222
+ function callParts(n2, spec) {
29223
+ const args2 = n2.childForFieldName("arguments");
29224
+ if (spec.id === "java") return { receiver: n2.childForFieldName("object"), name: n2.childForFieldName("name")?.text ?? null, args: args2 };
29225
+ let f = n2.childForFieldName("function");
29226
29226
  if (f?.type === "await_expression") f = f.namedChildren[0] ?? null;
29227
29227
  if (!f) return { receiver: null, name: null, args: args2 };
29228
29228
  if (f.type === "identifier") return { receiver: null, name: f.text, args: args2 };
@@ -29252,14 +29252,14 @@ function withLabel(item) {
29252
29252
  if (value.type === "attribute") return value.childForFieldName("attribute")?.text ?? null;
29253
29253
  return value.text;
29254
29254
  }
29255
- function isChained(n) {
29256
- const p = n.parent;
29255
+ function isChained(n2) {
29256
+ const p = n2.parent;
29257
29257
  if (!p) return false;
29258
29258
  const object = p.childForFieldName("object") ?? p.childForFieldName("operand");
29259
- return object?.id === n.id && (p.type === "member_expression" || p.type === "attribute" || p.type === "selector_expression" || p.type === "method_invocation");
29259
+ return object?.id === n2.id && (p.type === "member_expression" || p.type === "attribute" || p.type === "selector_expression" || p.type === "method_invocation");
29260
29260
  }
29261
- function isAwaited(n) {
29262
- let p = n.parent;
29261
+ function isAwaited(n2) {
29262
+ let p = n2.parent;
29263
29263
  while (p && p.type === "parenthesized_expression") p = p.parent;
29264
29264
  return !!p && (p.type === "await_expression" || p.type === "await");
29265
29265
  }
@@ -29283,17 +29283,17 @@ function factsOf(def, spec, defs, path) {
29283
29283
  const tries = [];
29284
29284
  const locks = [];
29285
29285
  const bindings = {};
29286
- const bind = (n) => {
29286
+ const bind = (n2) => {
29287
29287
  let name2 = null;
29288
29288
  let value = null;
29289
- if (n.type === "variable_declarator") {
29290
- name2 = n.childForFieldName("name");
29291
- value = n.childForFieldName("value");
29292
- } else if (n.type === "assignment" && spec.id === "python") {
29293
- name2 = n.childForFieldName("left");
29294
- value = n.childForFieldName("right");
29295
- } else if (n.type === "short_var_declaration") {
29296
- const l = n.childForFieldName("left"), r = n.childForFieldName("right");
29289
+ if (n2.type === "variable_declarator") {
29290
+ name2 = n2.childForFieldName("name");
29291
+ value = n2.childForFieldName("value");
29292
+ } else if (n2.type === "assignment" && spec.id === "python") {
29293
+ name2 = n2.childForFieldName("left");
29294
+ value = n2.childForFieldName("right");
29295
+ } else if (n2.type === "short_var_declaration") {
29296
+ const l = n2.childForFieldName("left"), r = n2.childForFieldName("right");
29297
29297
  if (l?.namedChildren.length === 1 && r?.namedChildren.length === 1) {
29298
29298
  name2 = l.namedChildren[0];
29299
29299
  value = r.namedChildren[0];
@@ -29301,68 +29301,68 @@ function factsOf(def, spec, defs, path) {
29301
29301
  }
29302
29302
  if (name2?.type === "identifier" && value && Object.keys(bindings).length < 40 && !(name2.text in bindings)) bindings[name2.text] = cap(value.text, TEXT_CAP);
29303
29303
  };
29304
- const throwsIn = (n) => {
29305
- if (spec.throws.has(n.type)) return true;
29306
- if (defs.has(n.id) || spec.functionValues.has(n.type)) return false;
29307
- return n.namedChildren.some(throwsIn);
29304
+ const throwsIn = (n2) => {
29305
+ if (spec.throws.has(n2.type)) return true;
29306
+ if (defs.has(n2.id) || spec.functionValues.has(n2.type)) return false;
29307
+ return n2.namedChildren.some(throwsIn);
29308
29308
  };
29309
- const walk2 = (n, ctx) => {
29310
- const anonymousMember = n.parent?.type === "class_body" && n.parent.parent?.type === "object_creation_expression";
29311
- if (n.id !== def.fn.id && !anonymousMember && (defs.has(n.id) || spec.classes.has(n.type) || spec.definitions[n.type])) return;
29312
- const t = n.type;
29313
- bind(n);
29309
+ const walk2 = (n2, ctx) => {
29310
+ const anonymousMember = n2.parent?.type === "class_body" && n2.parent.parent?.type === "object_creation_expression";
29311
+ if (n2.id !== def.fn.id && !anonymousMember && (defs.has(n2.id) || spec.classes.has(n2.type) || spec.definitions[n2.type])) return;
29312
+ const t = n2.type;
29313
+ bind(n2);
29314
29314
  const down = (c, next = ctx) => walk2(c, next);
29315
29315
  if (spec.calls.has(t)) {
29316
- const { receiver, name: name2, args: args2 } = callParts(n, spec);
29316
+ const { receiver, name: name2, args: args2 } = callParts(n2, spec);
29317
29317
  if (name2) {
29318
29318
  calls.push({
29319
- line: line(n),
29320
- col: n.startPosition.column,
29319
+ line: line(n2),
29320
+ col: n2.startPosition.column,
29321
29321
  receiver: receiver ? cap(receiver.text, TEXT_CAP) : null,
29322
29322
  name: name2,
29323
29323
  args: argsOf(args2, spec),
29324
- awaited: isAwaited(n) || n.childForFieldName("function")?.type === "await_expression",
29325
- chained: isChained(n),
29324
+ awaited: isAwaited(n2) || n2.childForFieldName("function")?.type === "await_expression",
29325
+ chained: isChained(n2),
29326
29326
  inLoop: ctx.inLoop,
29327
29327
  inTry: ctx.tryAt !== null,
29328
29328
  tryAt: ctx.tryAt,
29329
29329
  within: ctx.within.slice(-MAX_WITHIN)
29330
29330
  });
29331
- if (spec.lockCalls.has(name2)) locks.push(line(n));
29332
- for (const c of n.namedChildren) down(c, c.id === args2?.id ? { ...ctx, within: [...ctx.within, name2] } : ctx);
29331
+ if (spec.lockCalls.has(name2)) locks.push(line(n2));
29332
+ for (const c of n2.namedChildren) down(c, c.id === args2?.id ? { ...ctx, within: [...ctx.within, name2] } : ctx);
29333
29333
  return;
29334
29334
  }
29335
29335
  }
29336
- if (spec.awaits.has(t)) awaits.push(line(n));
29336
+ if (spec.awaits.has(t)) awaits.push(line(n2));
29337
29337
  if (t === "defer_statement") {
29338
- for (const c of n.namedChildren) down(c, { ...ctx, within: [...ctx.within, "defer"] });
29338
+ for (const c of n2.namedChildren) down(c, { ...ctx, within: [...ctx.within, "defer"] });
29339
29339
  return;
29340
29340
  }
29341
29341
  if (spec.lockNodes.has(t)) {
29342
- locks.push(line(n));
29343
- for (const c of n.namedChildren) down(c, { ...ctx, within: [...ctx.within, "synchronized"] });
29342
+ locks.push(line(n2));
29343
+ for (const c of n2.namedChildren) down(c, { ...ctx, within: [...ctx.within, "synchronized"] });
29344
29344
  return;
29345
29345
  }
29346
29346
  if (t === "with_statement") {
29347
- const item = n.namedChildren[0];
29348
- if (PY_LOCK_ITEM.test(item?.text ?? "")) locks.push(line(n));
29347
+ const item = n2.namedChildren[0];
29348
+ if (PY_LOCK_ITEM.test(item?.text ?? "")) locks.push(line(n2));
29349
29349
  const label2 = withLabel(item);
29350
- for (const c of n.namedChildren) down(c, c.type === "block" && label2 ? { ...ctx, within: [...ctx.within, label2] } : ctx);
29350
+ for (const c of n2.namedChildren) down(c, c.type === "block" && label2 ? { ...ctx, within: [...ctx.within, label2] } : ctx);
29351
29351
  return;
29352
29352
  }
29353
29353
  if (spec.loops.has(t)) {
29354
- loops.push(line(n));
29355
- for (const c of n.namedChildren) down(c, { ...ctx, inLoop: true });
29354
+ loops.push(line(n2));
29355
+ for (const c of n2.namedChildren) down(c, { ...ctx, inLoop: true });
29356
29356
  return;
29357
29357
  }
29358
29358
  if (spec.tries.has(t)) {
29359
- const handlers = n.namedChildren.filter((c) => spec.handlers.has(c.type));
29360
- tries.push({ line: line(n), end: n.endPosition.row + 1, catches: handlers.length > 0, rethrows: handlers.some(throwsIn) });
29361
- const body2 = n.childForFieldName("body");
29362
- for (const c of n.namedChildren) down(c, c.id === body2?.id ? { ...ctx, tryAt: line(n) } : ctx);
29359
+ const handlers = n2.namedChildren.filter((c) => spec.handlers.has(c.type));
29360
+ tries.push({ line: line(n2), end: n2.endPosition.row + 1, catches: handlers.length > 0, rethrows: handlers.some(throwsIn) });
29361
+ const body2 = n2.childForFieldName("body");
29362
+ for (const c of n2.namedChildren) down(c, c.id === body2?.id ? { ...ctx, tryAt: line(n2) } : ctx);
29363
29363
  return;
29364
29364
  }
29365
- for (const c of n.namedChildren) down(c);
29365
+ for (const c of n2.namedChildren) down(c);
29366
29366
  };
29367
29367
  const synchronizedMethod = spec.id === "java" && /\bsynchronized\b/.test(def.fn.namedChildren.find((c) => c.type === "modifiers")?.text ?? "");
29368
29368
  walk2(def.fn, { inLoop: false, tryAt: null, within: synchronizedMethod ? ["synchronized"] : [] });
@@ -29432,11 +29432,11 @@ function regionOf(rt, path, content, fn, changed, maxLines, deadlineAt) {
29432
29432
  if (!tree) return { source: "fallback", reason: "deadline", elapsedMs: Date.now() - started };
29433
29433
  try {
29434
29434
  const lines = content.split("\n");
29435
- let n = tree.rootNode.descendantForPosition({ row: from - 1, column: 0 }, { row: to - 1, column: (lines[to - 1] ?? "").length });
29435
+ let n2 = tree.rootNode.descendantForPosition({ row: from - 1, column: 0 }, { row: to - 1, column: (lines[to - 1] ?? "").length });
29436
29436
  let block = null;
29437
- for (; n && line(n) >= fn.start.line; n = n.parent) {
29438
- if (BLOCKS.has(n.type) && n.endPosition.row + 1 - line(n) + 1 > maxLines) {
29439
- block = n;
29437
+ for (; n2 && line(n2) >= fn.start.line; n2 = n2.parent) {
29438
+ if (BLOCKS.has(n2.type) && n2.endPosition.row + 1 - line(n2) + 1 > maxLines) {
29439
+ block = n2;
29440
29440
  break;
29441
29441
  }
29442
29442
  }
@@ -29482,15 +29482,15 @@ var STABLE_EXPRESSION = (t) => {
29482
29482
  function argResource(kind2, arg) {
29483
29483
  if (!arg) return { kind: kind2, name: null, confidence: "unknown" };
29484
29484
  if (arg.literal !== null) {
29485
- const n = literalName(arg.literal);
29486
- return n ? { kind: kind2, name: n.name, confidence: n.confidence } : { kind: kind2, name: null, confidence: "unknown" };
29485
+ const n2 = literalName(arg.literal);
29486
+ return n2 ? { kind: kind2, name: n2.name, confidence: n2.confidence } : { kind: kind2, name: null, confidence: "unknown" };
29487
29487
  }
29488
29488
  if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind: kind2, name: arg.text, confidence: "expression" };
29489
29489
  const keyed = keyedCall(arg.text);
29490
29490
  return keyed ? { kind: kind2, name: keyed, confidence: "expression" } : { kind: kind2, name: null, confidence: "unknown" };
29491
29491
  }
29492
- function keyedCall(text) {
29493
- const t = text.trim();
29492
+ function keyedCall(text2) {
29493
+ const t = text2.trim();
29494
29494
  const open = t.indexOf("(");
29495
29495
  if (open <= 0 || !t.endsWith(")")) return null;
29496
29496
  const callee = t.slice(0, open);
@@ -29524,16 +29524,16 @@ var SQL_TABLE = [
29524
29524
  [/\bfrom\s+[`"[]?([\w.]+)/i, "read"]
29525
29525
  ];
29526
29526
  function sqlLiteral(c) {
29527
- const text = c.args.find((a) => a.literal !== null && SQL.test(a.literal))?.literal;
29528
- if (!text) return null;
29527
+ const text2 = c.args.find((a) => a.literal !== null && SQL.test(a.literal))?.literal;
29528
+ if (!text2) return null;
29529
29529
  for (const [re, op] of SQL_TABLE) {
29530
- const m = re.exec(text);
29530
+ const m = re.exec(text2);
29531
29531
  if (m) {
29532
29532
  const name2 = m[1].split(".").pop();
29533
- return { op, resource: table(name2), rule: "sql.literal", lock: op === "read" && /\bfor\s+(?:no\s+key\s+)?update\b/i.test(text) };
29533
+ return { op, resource: table(name2), rule: "sql.literal", lock: op === "read" && /\bfor\s+(?:no\s+key\s+)?update\b/i.test(text2) };
29534
29534
  }
29535
29535
  }
29536
- return { op: /^\s*select\b/i.test(text) ? "read" : "write", resource: { kind: "table", name: null, confidence: "unknown" }, rule: "sql.literal" };
29536
+ return { op: /^\s*select\b/i.test(text2) ? "read" : "write", resource: { kind: "table", name: null, confidence: "unknown" }, rule: "sql.literal" };
29537
29537
  }
29538
29538
  var SB_WRITE = /* @__PURE__ */ new Set(["insert", "update", "upsert", "delete"]);
29539
29539
  var SB_FROM = /\bfrom\(\s*(['"`])([\w.-]+)\1\s*\)\s*$/;
@@ -29832,7 +29832,7 @@ function accessMap(input) {
29832
29832
  const effects = effectsWithHelpers(target, fileFns, lang, 2, state);
29833
29833
  const byName = new Map(fileFns.map((f) => [f.name, f]));
29834
29834
  const helperNames = new Set(effects.flatMap((e) => e.via));
29835
- const helpers = [...helperNames].map((n) => byName.get(n)).filter((f) => !!f && f !== target && !inside(f, target)).slice(0, MAX_HELPERS);
29835
+ const helpers = [...helperNames].map((n2) => byName.get(n2)).filter((f) => !!f && f !== target && !inside(f, target)).slice(0, MAX_HELPERS);
29836
29836
  const named = effects.filter((e) => e.resource.name !== null && e.resource.confidence !== "unknown");
29837
29837
  const resources = [];
29838
29838
  for (const e of [...named.filter((x) => x.op === "write"), ...named.filter((x) => x.op === "read")]) {
@@ -29929,28 +29929,28 @@ var ALIAS_OF = "alias-of:";
29929
29929
  var FIELD_OF = "field-of:";
29930
29930
  var IDENT_CHAR = /[\w$]/;
29931
29931
  var isIdent = (s) => /^[A-Za-z_$][\w$]*$/.test(s);
29932
- function wordAt(text, word) {
29932
+ function wordAt(text2, word) {
29933
29933
  const out2 = [];
29934
- for (let i2 = text.indexOf(word); i2 >= 0; i2 = text.indexOf(word, i2 + 1)) {
29935
- if (IDENT_CHAR.test(text[i2 - 1] ?? "") || IDENT_CHAR.test(text[i2 + word.length] ?? "")) continue;
29934
+ for (let i2 = text2.indexOf(word); i2 >= 0; i2 = text2.indexOf(word, i2 + 1)) {
29935
+ if (IDENT_CHAR.test(text2[i2 - 1] ?? "") || IDENT_CHAR.test(text2[i2 + word.length] ?? "")) continue;
29936
29936
  out2.push(i2);
29937
29937
  }
29938
29938
  return out2;
29939
29939
  }
29940
29940
  var GO_NOT_TYPES = /* @__PURE__ */ new Set(["int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64", "complex64", "complex128", "string", "bool", "byte", "rune", "error", "any", "func", "chan", "map", "struct", "interface", "range", "make", "new", "nil", "true", "false"]);
29941
- function typeAt(text, i2, lang) {
29941
+ function typeAt(text2, i2, lang) {
29942
29942
  let j = i2;
29943
29943
  const skip = () => {
29944
- while (j < text.length && /[\s?*&]/.test(text[j])) j++;
29944
+ while (j < text2.length && /[\s?*&]/.test(text2[j])) j++;
29945
29945
  };
29946
29946
  skip();
29947
- for (const kw of ["new ", "readonly ", "await "]) if (text.startsWith(kw, j)) {
29947
+ for (const kw of ["new ", "readonly ", "await "]) if (text2.startsWith(kw, j)) {
29948
29948
  j += kw.length;
29949
29949
  skip();
29950
29950
  }
29951
29951
  let k = j;
29952
- while (k < text.length && /[\w$.]/.test(text[k])) k++;
29953
- const name2 = text.slice(j, k).split(".").pop() ?? "";
29952
+ while (k < text2.length && /[\w$.]/.test(text2[k])) k++;
29953
+ const name2 = text2.slice(j, k).split(".").pop() ?? "";
29954
29954
  if (lang === "go") return /^[A-Za-z_]\w*$/.test(name2) && !GO_NOT_TYPES.has(name2) ? name2 : null;
29955
29955
  return /^[A-Z][\w$]*$/.test(name2) ? name2 : null;
29956
29956
  }
@@ -29995,8 +29995,8 @@ function declaredType(scope2, v, lang) {
29995
29995
  function classesIn(content, lang) {
29996
29996
  const lines = content.split("\n");
29997
29997
  const out2 = [];
29998
- for (let n = 0; n < lines.length; n++) {
29999
- const l = lines[n];
29998
+ for (let n2 = 0; n2 < lines.length; n2++) {
29999
+ const l = lines[n2];
30000
30000
  let name2 = null, base = null, impl = [];
30001
30001
  if (lang === "python") {
30002
30002
  const m2 = /^(\s*)class\s+([A-Za-z_]\w*)\s*(?:\(([^)]*)\))?\s*:/.exec(l);
@@ -30004,17 +30004,17 @@ function classesIn(content, lang) {
30004
30004
  name2 = m2[2];
30005
30005
  base = (m2[3] ?? "").split(",").map((x) => x.trim().split(".").pop() ?? "").find((x) => /^[A-Z]/.test(x) && x !== "object") ?? null;
30006
30006
  const indent = m2[1].length;
30007
- let end2 = n + 1;
30007
+ let end2 = n2 + 1;
30008
30008
  while (end2 < lines.length && (lines[end2].trim() === "" || lines[end2].search(/\S/) > indent)) end2++;
30009
- out2.push({ name: name2, base, implementsList: [], start: n + 1, end: end2 });
30009
+ out2.push({ name: name2, base, implementsList: [], start: n2 + 1, end: end2 });
30010
30010
  continue;
30011
30011
  }
30012
30012
  if (lang === "go") {
30013
30013
  const m2 = /^\s*type\s+([A-Z_a-z]\w*)\s+(struct|interface)\s*\{/.exec(l);
30014
30014
  if (!m2) continue;
30015
- let end2 = n;
30015
+ let end2 = n2;
30016
30016
  while (end2 < lines.length && !/^\s*\}/.test(lines[end2])) end2++;
30017
- out2.push({ name: m2[1], base: null, implementsList: [], start: n + 1, end: end2 + 1 });
30017
+ out2.push({ name: m2[1], base: null, implementsList: [], start: n2 + 1, end: end2 + 1 });
30018
30018
  continue;
30019
30019
  }
30020
30020
  const m = /\b(?:class|interface)\s+([A-Za-z_$][\w$]*)(?:<[^{]*?>)?\s*(?:extends\s+([\w$.]+)(?:<[^{]*?>)?)?\s*(?:implements\s+([^{]+))?\{?/.exec(l);
@@ -30022,8 +30022,8 @@ function classesIn(content, lang) {
30022
30022
  name2 = m[1];
30023
30023
  base = m[2] ? m[2].split(".").pop() ?? null : null;
30024
30024
  impl = (m[3] ?? "").split(",").map((x) => x.trim().replace(/<.*$/, "").split(".").pop() ?? "").filter(isIdent);
30025
- let depth = 0, seen = false, end = n;
30026
- for (let k = n; k < lines.length; k++) {
30025
+ let depth = 0, seen = false, end = n2;
30026
+ for (let k = n2; k < lines.length; k++) {
30027
30027
  for (const ch of lines[k]) {
30028
30028
  if (ch === "{") {
30029
30029
  depth++;
@@ -30036,7 +30036,7 @@ function classesIn(content, lang) {
30036
30036
  }
30037
30037
  end = k;
30038
30038
  }
30039
- out2.push({ name: name2, base, implementsList: impl, start: n + 1, end: end + 1 });
30039
+ out2.push({ name: name2, base, implementsList: impl, start: n2 + 1, end: end + 1 });
30040
30040
  }
30041
30041
  return out2;
30042
30042
  }
@@ -30100,10 +30100,10 @@ function boundInGo(fnText, name2) {
30100
30100
  const brace = fnText.indexOf("{");
30101
30101
  return wordAt(brace < 0 ? fnText : fnText.slice(0, brace), name2).length > 0;
30102
30102
  }
30103
- function rebindsInGo(text, name2) {
30104
- for (const i2 of wordAt(text, name2)) {
30105
- const lineEnd = text.indexOf("\n", i2);
30106
- const rest = text.slice(i2 + name2.length, lineEnd < 0 ? void 0 : lineEnd);
30103
+ function rebindsInGo(text2, name2) {
30104
+ for (const i2 of wordAt(text2, name2)) {
30105
+ const lineEnd = text2.indexOf("\n", i2);
30106
+ const rest = text2.slice(i2 + name2.length, lineEnd < 0 ? void 0 : lineEnd);
30107
30107
  const decl = rest.indexOf(":=");
30108
30108
  if (decl >= 0 && /^[\s\w,]*$/.test(rest.slice(0, decl))) return true;
30109
30109
  }
@@ -30329,15 +30329,15 @@ function importOf(content, lang, name2, receiver) {
30329
30329
  return null;
30330
30330
  }
30331
30331
  var TS_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
30332
- function parseJsonc(text) {
30332
+ function parseJsonc(text2) {
30333
30333
  let out2 = "";
30334
30334
  let inString = false;
30335
- for (let i2 = 0; i2 < text.length; i2++) {
30336
- const c = text[i2];
30335
+ for (let i2 = 0; i2 < text2.length; i2++) {
30336
+ const c = text2[i2];
30337
30337
  if (inString) {
30338
30338
  out2 += c;
30339
30339
  if (c === "\\") {
30340
- out2 += text[++i2] ?? "";
30340
+ out2 += text2[++i2] ?? "";
30341
30341
  continue;
30342
30342
  }
30343
30343
  if (c === '"') inString = false;
@@ -30348,14 +30348,14 @@ function parseJsonc(text) {
30348
30348
  out2 += c;
30349
30349
  continue;
30350
30350
  }
30351
- if (c === "/" && text[i2 + 1] === "/") {
30352
- while (i2 < text.length && text[i2] !== "\n") i2++;
30351
+ if (c === "/" && text2[i2 + 1] === "/") {
30352
+ while (i2 < text2.length && text2[i2] !== "\n") i2++;
30353
30353
  out2 += "\n";
30354
30354
  continue;
30355
30355
  }
30356
- if (c === "/" && text[i2 + 1] === "*") {
30356
+ if (c === "/" && text2[i2 + 1] === "*") {
30357
30357
  i2 += 2;
30358
- while (i2 < text.length && !(text[i2] === "*" && text[i2 + 1] === "/")) i2++;
30358
+ while (i2 < text2.length && !(text2[i2] === "*" && text2[i2 + 1] === "/")) i2++;
30359
30359
  i2++;
30360
30360
  continue;
30361
30361
  }
@@ -30494,7 +30494,7 @@ function definitionOf(input) {
30494
30494
  const caller = at ? fns.filter((f) => f.start.line <= at && at <= f.end.line).sort((a, b) => a.end.line - a.start.line - (b.end.line - b.start.line))[0] ?? null : null;
30495
30495
  const tsCache = /* @__PURE__ */ new Map();
30496
30496
  const resolveImport = (spec, from) => moduleFiles(source2, spec, from, lang, tsCache);
30497
- const imports = (c, n) => importOf(c, lang, n, null);
30497
+ const imports = (c, n2) => importOf(c, lang, n2, null);
30498
30498
  let type = receiverType(content, lang, caller, receiver, at) ?? fieldChainType({ content, lang, caller, receiver, line: at, fromPath: path, source: source2, resolveImport, importOf: imports });
30499
30499
  if (type?.startsWith(RESULT_OF)) {
30500
30500
  const [fnName, idx] = type.slice(RESULT_OF.length).split("#");
@@ -30519,7 +30519,7 @@ function definitionOf(input) {
30519
30519
  source: source2,
30520
30520
  outline,
30521
30521
  resolveImport: (spec, from) => moduleFiles(source2, spec, from, lang, tsCache),
30522
- importOf: (c, n) => importOf(c, lang, n, null)
30522
+ importOf: (c, n2) => importOf(c, lang, n2, null)
30523
30523
  });
30524
30524
  for (const h of hits) add([h.fn], h.how === "class" ? "type" : h.how);
30525
30525
  }
@@ -30564,36 +30564,36 @@ function definitionOf(input) {
30564
30564
  }
30565
30565
  var MAX_CALLER_SCAN_FILES = 60;
30566
30566
  var isWordChar2 = (c) => c !== void 0 && /[\w$]/.test(c);
30567
- function callStarts(text, name2) {
30567
+ function callStarts(text2, name2) {
30568
30568
  const out2 = [];
30569
- for (let i2 = text.indexOf(name2); i2 >= 0; i2 = text.indexOf(name2, i2 + 1)) {
30569
+ for (let i2 = text2.indexOf(name2); i2 >= 0; i2 = text2.indexOf(name2, i2 + 1)) {
30570
30570
  let j = i2 + name2.length;
30571
- if (text[j] === "<") {
30571
+ if (text2[j] === "<") {
30572
30572
  let depth = 0;
30573
- for (; j < text.length; j++) {
30574
- if (text[j] === "<") depth++;
30575
- else if (text[j] === ">" && --depth === 0) break;
30573
+ for (; j < text2.length; j++) {
30574
+ if (text2[j] === "<") depth++;
30575
+ else if (text2[j] === ">" && --depth === 0) break;
30576
30576
  }
30577
30577
  j++;
30578
30578
  }
30579
- if (text[j] === "(") out2.push({ index: i2, open: j });
30579
+ if (text2[j] === "(") out2.push({ index: i2, open: j });
30580
30580
  }
30581
30581
  return out2;
30582
30582
  }
30583
- function callsName(text, name2) {
30584
- const t = text.trim();
30583
+ function callsName(text2, name2) {
30584
+ const t = text2.trim();
30585
30585
  if (t.startsWith("//") || t.startsWith("*") || t.startsWith("/*") || t.startsWith("#")) return false;
30586
- for (const at of callStarts(text, name2)) {
30586
+ for (const at of callStarts(text2, name2)) {
30587
30587
  const i2 = at.index;
30588
- const spread = text.slice(Math.max(0, i2 - 3), i2) === "...";
30589
- if (isWordChar2(text[i2 - 1]) || text[i2 - 1] === "." && !spread) continue;
30588
+ const spread = text2.slice(Math.max(0, i2 - 3), i2) === "...";
30589
+ if (isWordChar2(text2[i2 - 1]) || text2[i2 - 1] === "." && !spread) continue;
30590
30590
  let depth = 0;
30591
30591
  let j = at.open;
30592
- for (; j < text.length; j++) {
30593
- if (text[j] === "(") depth++;
30594
- else if (text[j] === ")" && --depth === 0) break;
30592
+ for (; j < text2.length; j++) {
30593
+ if (text2[j] === "(") depth++;
30594
+ else if (text2[j] === ")" && --depth === 0) break;
30595
30595
  }
30596
- const after = text.slice(j + 1).trimStart();
30596
+ const after = text2.slice(j + 1).trimStart();
30597
30597
  if (after.startsWith(":") || after.startsWith("{")) continue;
30598
30598
  return true;
30599
30599
  }
@@ -30663,7 +30663,7 @@ function callersOf(input) {
30663
30663
  let tie = fileTie;
30664
30664
  if (owner) {
30665
30665
  if (!c.receiver) continue;
30666
- const imports = (cc, n) => importOf(cc, lang, n, null);
30666
+ const imports = (cc, n2) => importOf(cc, lang, n2, null);
30667
30667
  const resolveImport = (spec, from) => moduleFiles(source2, spec, from, lang, cache);
30668
30668
  const type = receiverType(read2.content, lang, fn, c.receiver, c.line) ?? fieldChainType({ content: read2.content, lang, caller: fn, receiver: c.receiver, line: c.line, fromPath: p, source: source2, resolveImport, importOf: imports });
30669
30669
  if (type !== owner) continue;
@@ -30683,11 +30683,11 @@ function callersOf(input) {
30683
30683
  if (seen.has(line2) || declared.has(line2)) continue;
30684
30684
  const inside2 = r.value.some((f) => f.start.line <= line2 && line2 <= f.end.line && f.calls.some((c) => c.line === line2 && c.name === name2));
30685
30685
  if (inside2) continue;
30686
- const text = lines[line2 - 1] ?? "";
30687
- if (!callsName(text, name2) || /^\s*(?:export\s+)?(?:async\s+)?(?:function|def|func)\b/.test(text)) continue;
30686
+ const text2 = lines[line2 - 1] ?? "";
30687
+ if (!callsName(text2, name2) || /^\s*(?:export\s+)?(?:async\s+)?(?:function|def|func)\b/.test(text2)) continue;
30688
30688
  const enclosing = r.value.filter((f) => f.start.line <= line2 && line2 <= f.end.line).sort((a, b) => a.end.line - a.start.line - (b.end.line - b.start.line))[0];
30689
30689
  seen.add(line2);
30690
- callers.push({ path: p, caller: enclosing ? enclosing.qualified : null, line: line2, text: text.trim().slice(0, 200), provenance: fileTie });
30690
+ callers.push({ path: p, caller: enclosing ? enclosing.qualified : null, line: line2, text: text2.trim().slice(0, 200), provenance: fileTie });
30691
30691
  }
30692
30692
  }
30693
30693
  }
@@ -30809,8 +30809,8 @@ var SOURCE_EXTS = ["ts", "tsx", "mts", "cts", "js", "jsx", "mjs", "cjs", "py", "
30809
30809
  function parseHit(line2) {
30810
30810
  const m = /^(.+?):(\d+):(.*)$/.exec(line2);
30811
30811
  if (!m) return null;
30812
- const n = Number(m[2]);
30813
- return n >= 1 ? { path: m[1], line: n, text: m[3] } : null;
30812
+ const n2 = Number(m[2]);
30813
+ return n2 >= 1 ? { path: m[1], line: n2, text: m[3] } : null;
30814
30814
  }
30815
30815
  function capHits(lines, maxHits) {
30816
30816
  const hits = [];
@@ -30994,16 +30994,16 @@ ${m.accessors.map((x) => ` ${x.fn.path}:${x.fn.start.line} ${x.fn.qualified} \u
30994
30994
  return { ok: true, value: lines.join("\n") };
30995
30995
  };
30996
30996
  var KINDS = ["table", "cache", "file", "http", "queue", "service", "memory"];
30997
- function parseResource(text) {
30998
- const colon = text.indexOf(":");
30999
- const kind2 = colon > 0 ? text.slice(0, colon) : "";
31000
- if (KINDS.includes(kind2)) return { kinds: [kind2], name: text.slice(colon + 1) };
31001
- return { kinds: KINDS, name: text };
30997
+ function parseResource(text2) {
30998
+ const colon = text2.indexOf(":");
30999
+ const kind2 = colon > 0 ? text2.slice(0, colon) : "";
31000
+ if (KINDS.includes(kind2)) return { kinds: [kind2], name: text2.slice(colon + 1) };
31001
+ return { kinds: KINDS, name: text2 };
31002
31002
  }
31003
31003
  var writersOfTool = async (ctx, args2) => {
31004
- const text = str(args2.resource, 300, "resource");
31005
- if (!text.ok) return text;
31006
- const { kinds, name: name2 } = parseResource(text.value);
31004
+ const text2 = str(args2.resource, 300, "resource");
31005
+ if (!text2.ok) return text2;
31006
+ const { kinds, name: name2 } = parseResource(text2.value);
31007
31007
  if (name2.length < 2) return { ok: false, error: "resource name too short to search for" };
31008
31008
  const deadline = Date.now() + TOOL_MS;
31009
31009
  const src = source(ctx);
@@ -31042,7 +31042,7 @@ var writersOfTool = async (ctx, args2) => {
31042
31042
  if (files.size > 25) truncated = true;
31043
31043
  const list2 = (xs) => xs.length ? xs.slice(0, MAX_LIST).map((x) => ` ${x}`).join("\n") + (xs.length > MAX_LIST ? `
31044
31044
  \u2026 ${xs.length - MAX_LIST} more` : "") : " none found";
31045
- return { ok: true, value: `${text.value} (${where(ctx)}), heuristic${truncated ? ", search cut short" : ""}
31045
+ return { ok: true, value: `${text2.value} (${where(ctx)}), heuristic${truncated ? ", search cut short" : ""}
31046
31046
  writers:
31047
31047
  ${list2(writers)}
31048
31048
  readers:
@@ -31100,9 +31100,9 @@ function validateRepoPath(value, { allowRoot = false } = {}) {
31100
31100
  function lineNumber(value, fallback) {
31101
31101
  return typeof value === "number" && Number.isInteger(value) && value >= 1 ? value : fallback;
31102
31102
  }
31103
- function capOutput(text) {
31104
- return text.length > TOOL_LIMITS.outputChars ? `${text.slice(0, TOOL_LIMITS.outputChars)}
31105
- [truncated at ${TOOL_LIMITS.outputChars} characters]` : text;
31103
+ function capOutput(text2) {
31104
+ return text2.length > TOOL_LIMITS.outputChars ? `${text2.slice(0, TOOL_LIMITS.outputChars)}
31105
+ [truncated at ${TOOL_LIMITS.outputChars} characters]` : text2;
31106
31106
  }
31107
31107
  function git(ctx, args2, opts = {}) {
31108
31108
  return runGit(ctx.root, args2, { timeoutMs: opts.timeoutMs ?? TOOL_LIMITS.gitTimeoutMs, maxBuffer: opts.maxBuffer ?? TOOL_LIMITS.fileBytes });
@@ -31236,8 +31236,8 @@ var listFilesTool = async (ctx, args2) => {
31236
31236
  \u2026 ${more} more` : ""}` : "no matching files" };
31237
31237
  };
31238
31238
  var searchTool = async (ctx, args2) => {
31239
- const text = args2.text;
31240
- if (typeof text !== "string" || text.length === 0 || text.length > TOOL_LIMITS.textChars || /[\n\r]/.test(text)) {
31239
+ const text2 = args2.text;
31240
+ if (typeof text2 !== "string" || text2.length === 0 || text2.length > TOOL_LIMITS.textChars || /[\n\r]/.test(text2)) {
31241
31241
  return { ok: false, error: `text must be 1-${TOOL_LIMITS.textChars} characters on one line` };
31242
31242
  }
31243
31243
  const glob = typeof args2.path_glob === "string" && args2.path_glob.length > 0 ? args2.path_glob : null;
@@ -31246,7 +31246,7 @@ var searchTool = async (ctx, args2) => {
31246
31246
  }
31247
31247
  const pathspec = glob ? [`:(glob)${glob}`] : [];
31248
31248
  const revision = ctx.range.kind === "push" ? [ctx.range.head] : ["--cached"];
31249
- const res = await git(ctx, ["grep", "-n", "-I", "-F", "--no-color", ...revision.filter((r) => r === "--cached"), "-e", text, ...revision.filter((r) => r !== "--cached"), "--", ...pathspec]);
31249
+ const res = await git(ctx, ["grep", "-n", "-I", "-F", "--no-color", ...revision.filter((r) => r === "--cached"), "-e", text2, ...revision.filter((r) => r !== "--cached"), "--", ...pathspec]);
31250
31250
  if (!res.ok) {
31251
31251
  if (res.error === "failed" && res.stderr.trim() === "") return { ok: true, value: "no matches" };
31252
31252
  return { ok: false, error: gitFailure(res, "search") };
@@ -31284,7 +31284,7 @@ function makeToolExecutor(ctx) {
31284
31284
  const index = next++;
31285
31285
  const call = calls[index];
31286
31286
  const codeTool = ctx.codeMap && CODE_TOOL_NAMES.includes(call.name) ? CODE_TOOLS[call.name] : null;
31287
- const tool = codeTool ? (c, args2) => codeTool({ root: c.root, revision: c.range.kind === "push" ? c.range.head : null, codeMap: c.codeMap, validatePath: (v) => validateRepoPath(v), denied: isDeniedPath }, args2) : TOOLS[call.name] ?? null;
31287
+ const tool = codeTool ? (c, args2) => codeTool({ root: c.root, revision: c.range.kind === "push" ? c.range.head : null, codeMap: c.codeMap, validatePath: (v) => validateRepoPath(v), denied: isDeniedPath }, args2) : Object.hasOwn(TOOLS, call.name) ? TOOLS[call.name] : null;
31288
31288
  if (!tool) {
31289
31289
  results[index] = { call_id: call.call_id, ok: false, error: `unknown tool ${call.name}` };
31290
31290
  continue;
@@ -31374,16 +31374,16 @@ function functionWindow(codeMap, path, content, line2, maxLines) {
31374
31374
  }
31375
31375
  function writerExcerpts(codeMap, writers, read2, maxLines, maxChars, budget) {
31376
31376
  const out2 = [];
31377
- let used = 0;
31377
+ let used2 = 0;
31378
31378
  for (const w of writers) {
31379
31379
  const content = read2(w.file);
31380
31380
  if (content === null) continue;
31381
31381
  const win = functionWindow(codeMap, w.file, content, w.line, maxLines);
31382
31382
  if (!win) continue;
31383
- const text = content.split("\n").slice(win.start_line - 1, win.end_line).join("\n").slice(0, maxChars);
31384
- if (used + text.length > budget) break;
31385
- used += text.length;
31386
- out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text });
31383
+ const text2 = content.split("\n").slice(win.start_line - 1, win.end_line).join("\n").slice(0, maxChars);
31384
+ if (used2 + text2.length > budget) break;
31385
+ used2 += text2.length;
31386
+ out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text: text2 });
31387
31387
  }
31388
31388
  return out2;
31389
31389
  }
@@ -31509,7 +31509,7 @@ function splitClaudeMdSections(content) {
31509
31509
  }
31510
31510
  function classifyClaudeSection(heading) {
31511
31511
  const h = heading.toLowerCase();
31512
- const hasAny = (needles) => needles.some((n) => h.includes(n));
31512
+ const hasAny = (needles) => needles.some((n2) => h.includes(n2));
31513
31513
  if (hasAny(["security", "auth", "secret", "credential", "cwe", "vulnerabilit", "sanitiz"])) return "security";
31514
31514
  if (hasAny(["gotcha", "caveat", "pitfall", "footgun", "beware", "watch out", "known issue", "warning"])) return "gotcha";
31515
31515
  if (hasAny(["decision", "adr", "rationale", "why we", "chose", "trade-off", "tradeoff"])) return "decision";
@@ -31722,7 +31722,7 @@ async function serverSeedTitles(opts) {
31722
31722
  });
31723
31723
  if (!res.ok || !Array.isArray(res.data.nodes)) return null;
31724
31724
  const titles = /* @__PURE__ */ new Set();
31725
- for (const n of res.data.nodes) if (typeof n?.title === "string") titles.add(normalizeTitle(n.title));
31725
+ for (const n2 of res.data.nodes) if (typeof n2?.title === "string") titles.add(normalizeTitle(n2.title));
31726
31726
  return titles;
31727
31727
  }
31728
31728
  function renderNodeMarkdown(candidate, nodeId, createdAt) {
@@ -32508,7 +32508,7 @@ function redactRequest(body2) {
32508
32508
  undelivered: true,
32509
32509
  total_files: files.length,
32510
32510
  total_bytes: files.reduce(
32511
- (n, f) => n + (typeof f.content === "string" ? f.content.length : 0),
32511
+ (n2, f) => n2 + (typeof f.content === "string" ? f.content.length : 0),
32512
32512
  0
32513
32513
  ),
32514
32514
  // Paths only. A path is already visible in the repository; the content is not.
@@ -33027,10 +33027,10 @@ async function writePullState(state) {
33027
33027
  } catch {
33028
33028
  }
33029
33029
  }
33030
- function pullsAtSessionStart(auth2, source2) {
33030
+ function pullsAtSessionStart(auth3, source2) {
33031
33031
  if (source2 === "compact") return false;
33032
- if (auth2.source === "env" || auth2.source === "flag") return true;
33033
- return auth2.userId != null;
33032
+ if (auth3.source === "env" || auth3.source === "flag") return true;
33033
+ return auth3.userId != null;
33034
33034
  }
33035
33035
  function spawnBackgroundPull(deps = {}) {
33036
33036
  const d = {
@@ -33151,7 +33151,7 @@ async function render(run4) {
33151
33151
  const memoryNodesUsed = response.memory_nodes_used;
33152
33152
  const lessonsUsed = response.lessons_used;
33153
33153
  if (memoryNodesUsed && memoryNodesUsed.length > 0) {
33154
- const nodeRefs = memoryNodesUsed.slice(0, 5).map((n) => n.node_id).join(", ");
33154
+ const nodeRefs = memoryNodesUsed.slice(0, 5).map((n2) => n2.node_id).join(", ");
33155
33155
  process.stderr.write(`${DIM}Memory: ${memoryNodesUsed.length} nodes \u2014 ${nodeRefs}${NC}
33156
33156
  `);
33157
33157
  } else if (lessonsUsed && lessonsUsed.length > 0) {
@@ -34056,14 +34056,14 @@ function trackedSourceFiles(root, opts = {}) {
34056
34056
  return files.slice(0, opts.maxFiles ?? 5e3);
34057
34057
  }
34058
34058
  var EFFECT_LINE = /\bawait\b|\basync\s+with\b|\.then\(|\bsetTimeout\(|\bsetInterval\(|\bwith\s+\w[\w.]*\.(?:lock|acquire)\b|\bLock\(\)/;
34059
- function countEffects(text) {
34060
- let n = 0;
34061
- for (const line2 of text.split("\n")) if (EFFECT_LINE.test(line2)) n++;
34062
- return n;
34059
+ function countEffects(text2) {
34060
+ let n2 = 0;
34061
+ for (const line2 of text2.split("\n")) if (EFFECT_LINE.test(line2)) n2++;
34062
+ return n2;
34063
34063
  }
34064
- function scanRisk(text) {
34064
+ function scanRisk(text2) {
34065
34065
  const counts = Object.fromEntries(RISK_PATTERNS.map(([c]) => [c, 0]));
34066
- for (const line2 of text.split("\n")) {
34066
+ for (const line2 of text2.split("\n")) {
34067
34067
  for (const [category, re] of RISK_PATTERNS) {
34068
34068
  if (re.test(line2)) counts[category]++;
34069
34069
  }
@@ -34141,7 +34141,7 @@ function collectRiskSignals(root, opts = {}) {
34141
34141
  }
34142
34142
 
34143
34143
  // src/lib/prove/grounding.ts
34144
- var BASIS_RULES = ["conservation", "once", "no-lost-update", "fail-closed", "progress"];
34144
+ var BASIS_RULES = ["conservation", "once", "no-lost-update", "fail-closed", "progress", "isolation", "revocation", "flow-binding", "event-order", "check-use"];
34145
34145
  var RULE = /^rule:([a-z-]+)$/;
34146
34146
  var LINE = /^(?:([^\s:]+):)?L?(\d{1,6})(?::\s*|\s+)(?:comment\s+)?([\s\S]+)$/;
34147
34147
  var norm = (s) => s.replace(/\s+/g, " ").trim().toLowerCase();
@@ -34152,17 +34152,17 @@ function basisOf(source2, files) {
34152
34152
  const m = LINE.exec(s);
34153
34153
  if (!m) return { ok: false, why: s ? `"${s.slice(0, 60)}" is neither L<n>: <words> nor a rule` : "no source" };
34154
34154
  const path = m[1];
34155
- const n = Number(m[2]);
34155
+ const n2 = Number(m[2]);
34156
34156
  const quoted = m[3].trim().replace(/^["'`“”]+|["'`“”]+$/g, "");
34157
34157
  const fragments = quoted.split(/…|\.\.\./).map(norm).filter((f) => f.length >= 4);
34158
- if (fragments.length === 0) return { ok: false, why: `L${n}: too few words to find on the line` };
34158
+ if (fragments.length === 0) return { ok: false, why: `L${n2}: too few words to find on the line` };
34159
34159
  const pool = path ? [...files].filter(([f]) => f === path || f.endsWith(`/${path}`)).map(([, c]) => c) : [...files.values()];
34160
34160
  if (path && pool.length === 0) return { ok: false, why: `${path} is not one of the given files` };
34161
34161
  for (const content of pool) {
34162
- const line2 = content.split("\n")[n - 1];
34163
- if (line2 !== void 0 && fragments.every((f) => norm(line2).includes(f))) return { ok: true, basis: `L${n}: ${quoted.slice(0, 120)}` };
34162
+ const line2 = content.split("\n")[n2 - 1];
34163
+ if (line2 !== void 0 && fragments.every((f) => norm(line2).includes(f))) return { ok: true, basis: `L${n2}: ${quoted.slice(0, 120)}` };
34164
34164
  }
34165
- return { ok: false, why: `line ${n} does not contain "${quoted.slice(0, 60)}"` };
34165
+ return { ok: false, why: `line ${n2} does not contain "${quoted.slice(0, 60)}"` };
34166
34166
  }
34167
34167
  var NOT_A_MENTION = "(?<!\\b(?:even|including|also|or) )";
34168
34168
  var UNTIL_FIRST = "(?:(?!\\bor\\b)[^,.;:]){0,60}?";
@@ -34192,6 +34192,19 @@ var STRUCTURAL_CATALOGUE = [
34192
34192
  "check_then_act_is_atomic",
34193
34193
  "no_double_effect"
34194
34194
  ];
34195
+ var SECURITY_CATALOGUE = [
34196
+ "limit_holds_under_concurrency",
34197
+ "single_use",
34198
+ "no_cross_subject_leak",
34199
+ "revocation_holds",
34200
+ "flow_binding",
34201
+ "event_order_holds",
34202
+ "fails_closed",
34203
+ "checked_value_is_used",
34204
+ "idempotency_scoped"
34205
+ ];
34206
+ var MAX_HYPOTHESES = 3;
34207
+ var CATALOGUE = [...STRUCTURAL_CATALOGUE, ...SECURITY_CATALOGUE];
34195
34208
  function combineScore(c) {
34196
34209
  const f = (x) => Math.max(0.01, Math.min(1, x));
34197
34210
  return Math.round(Math.pow(f(c.hazard), 0.45) * Math.pow(f(c.critical), 0.35) * Math.pow(f(c.error_prone), 0.2) * 1e3) / 1e3;
@@ -34260,13 +34273,13 @@ function changedExcerpt(content, changed, bytes, context = 30) {
34260
34273
  else acc.push({ ...w });
34261
34274
  return acc;
34262
34275
  }, []);
34263
- const isChanged = (n) => changed.some((r) => n >= r.from && n <= r.to);
34276
+ const isChanged = (n2) => changed.some((r) => n2 >= r.from && n2 <= r.to);
34264
34277
  const out2 = [];
34265
34278
  let size = 0;
34266
34279
  for (const w of windows) {
34267
34280
  if (out2.length) out2.push(" \u2026");
34268
- for (let n = w.from; n <= w.to; n++) {
34269
- const line2 = `${String(n).padStart(5)}${isChanged(n) ? "*" : " "}| ${lines[n - 1] ?? ""}`;
34281
+ for (let n2 = w.from; n2 <= w.to; n2++) {
34282
+ const line2 = `${String(n2).padStart(5)}${isChanged(n2) ? "*" : " "}| ${lines[n2 - 1] ?? ""}`;
34270
34283
  size += line2.length + 1;
34271
34284
  if (size > bytes) {
34272
34285
  out2.push(" \u2026 (truncated)");
@@ -34294,9 +34307,11 @@ var LUNA_SCHEMA = {
34294
34307
  error_prone: { type: "number" },
34295
34308
  reasons: { type: "array", items: { type: "string" } },
34296
34309
  symbol: { type: "string" },
34297
- properties: { type: "array", items: { type: "string", enum: [...STRUCTURAL_CATALOGUE] } }
34310
+ properties: { type: "array", items: { type: "string", enum: [...STRUCTURAL_CATALOGUE, ...SECURITY_CATALOGUE] } },
34311
+ lens: { type: "string", enum: ["security", "reliability"] },
34312
+ hypotheses: { type: "array", items: { type: "string" } }
34298
34313
  },
34299
- required: ["file", "critical", "hazard", "error_prone", "reasons", "symbol", "properties"]
34314
+ required: ["file", "critical", "hazard", "error_prone", "reasons", "symbol", "properties", "lens", "hypotheses"]
34300
34315
  }
34301
34316
  }
34302
34317
  },
@@ -34309,7 +34324,9 @@ For each file you get its git-history signals (commits, fix commits), risk keywo
34309
34324
  - error_prone: fix commits in its history (the strongest evidence: this code has already been wrong), high churn, several branches or error paths, a concurrency primitive \u2014 a hazard nobody sees by reading the function once.
34310
34325
  Rate a criterion LOW (below 0.5) when it is missing: rendering, formatting, configuration, command registration, wiring, types, a single read, a single write with nothing before it, logging, or a function whose correctness is plain from reading it. A crash window alone (an external call, then a local write, where a re-run repairs the state and nothing is lost for good) is not enough for a high score. A model of a function longer than about 150 lines abstracts too much to find anything: name the smaller function inside it that holds the hazard, or score lower.
34311
34326
  Name the single symbol (function) most worth modelling, and the applicable properties from the catalogue only. Reasons: at most 3, each a short concrete sentence about THIS code \u2014 its hazard, what a mistake costs, its history \u2014 never about the change. Return every file you were given, exactly once.
34312
- When a file lists \`changed\` lines, this is a review of a push: the excerpt is numbered around the changes (changed lines starred). Name the function that CONTAINS a changed line, and score THAT FUNCTION'S CURRENT CODE as a whole, never the edit itself. A one-line change (a log line, a rename) to a function that meets all three still scores high: a latent bug in it is exactly what this is for. A large change to a function that misses one still scores low. An excerpt may open with "Functions this push changed:", from a parser: when it says a changed function "shares state with" another, judge the PAIR \u2014 a function that alone is a single write or an invalidation is error-prone when the other reads and repopulates, or also writes, the same state (a cache invalidated here and refilled there, two writers of one ledger or file); score it as that pair would be scored, but name ONE symbol \u2014 the changed function, never both ("a/b", "a and b" name nothing). "reads then writes" names a check-then-act the parser saw with no transaction or lock around it. "effects" lists the state the function reads and writes (a table, a file, a cache key, a queue, an outside service). "Fix commits that changed these lines" quotes the history of THIS code: each one is evidence it has been wrong before (error_prone), and its subject often says what a mistake cost (critical) \u2014 a subject about duplicates, lost writes, double charges or stuck jobs is a costly mistake that already happened.`;
34327
+ When a file lists \`changed\` lines, this is a review of a push: the excerpt is numbered around the changes (changed lines starred). Name the function that CONTAINS a changed line, and score THAT FUNCTION'S CURRENT CODE as a whole, never the edit itself. A one-line change (a log line, a rename) to a function that meets all three still scores high: a latent bug in it is exactly what this is for. A large change to a function that misses one still scores low. An excerpt may open with "Functions this push changed:", from a parser: when it says a changed function "shares state with" another, judge the PAIR \u2014 a function that alone is a single write or an invalidation is error-prone when the other reads and repopulates, or also writes, the same state (a cache invalidated here and refilled there, two writers of one ledger or file); score it as that pair would be scored, but name ONE symbol \u2014 the changed function, never both ("a/b", "a and b" name nothing). "reads then writes" names a check-then-act the parser saw with no transaction or lock around it. "effects" lists the state the function reads and writes (a table, a file, a cache key, a queue, an outside service). "Fix commits that changed these lines" quotes the history of THIS code: each one is evidence it has been wrong before (error_prone), and its subject often says what a mistake cost (critical) \u2014 a subject about duplicates, lost writes, double charges or stuck jobs is a costly mistake that already happened.
34328
+ SECURITY LENS. Also decide who can drive the hazard. Set lens to "security" when an attacker outside the trust boundary can drive it: another user, an anonymous caller, another tenant, a holder of a stolen or revoked credential, the sender of a replayed or delayed event, or the owner of a domain or URL the code fetches. Otherwise set lens to "reliability". For the security lens, critical includes what the attacker gains (money, data, rights, another user's or tenant's data, free service), and hazard includes the moves an attacker controls: many copies of one request at once; the steps of a multi-step flow skipped, repeated or reordered; a right revoked between two steps; an event duplicated, delayed or reordered; a dependency that fails, times out or is circuit-broken; state shared across requests, users or tenants (module variables, caches, fallback answers, idempotency keys); a value that changes between its check and its use (a DNS answer, a redirect, a path).
34329
+ HYPOTHESES. For the symbol you name, give up to 3 concrete hypotheses for the model to try to break. Each is one sentence about THIS code that says who acts, the two or more steps, and the harm (for example "two concurrent redeem requests by one user both pass the count check, so the credit is added twice"). When a file lists \`changed\` lines, at least one hypothesis is about what the change made possible. A hypothesis is a question for the model, not a verdict. Give none when you see no concrete one.`;
34313
34330
  var lunaRanker = {
34314
34331
  name: "luna",
34315
34332
  async rank(candidates2, ctx) {
@@ -34340,7 +34357,7 @@ var lunaRanker = {
34340
34357
  store: false,
34341
34358
  instructions: LUNA_INSTRUCTIONS,
34342
34359
  input: JSON.stringify({
34343
- catalogue: STRUCTURAL_CATALOGUE,
34360
+ catalogue: [...STRUCTURAL_CATALOGUE, ...SECURITY_CATALOGUE],
34344
34361
  ...ctx.hint ? { user_hint: `The user said what they want checked: "${ctx.hint.slice(0, 500)}". Score files and name symbols relevant to it higher; do not invent relevance.` } : {},
34345
34362
  files: payload
34346
34363
  }),
@@ -34357,13 +34374,13 @@ var lunaRanker = {
34357
34374
  signal: controller.signal
34358
34375
  });
34359
34376
  if (!res.ok) {
34360
- const text2 = await res.text().catch(() => "");
34361
- return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${text2.slice(0, 200)}`, ranked: fallback };
34377
+ const text3 = await res.text().catch(() => "");
34378
+ return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${text3.slice(0, 200)}`, ranked: fallback };
34362
34379
  }
34363
34380
  const data = await res.json();
34364
- const text = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
34365
- if (!text) return { ok: false, ranker: "luna", error: "no output_text in response", ranked: fallback };
34366
- const parsed = JSON.parse(text);
34381
+ const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
34382
+ if (!text2) return { ok: false, ranker: "luna", error: "no output_text in response", ranked: fallback };
34383
+ const parsed = JSON.parse(text2);
34367
34384
  const items = parsed.items.map((i2) => {
34368
34385
  const legacy = i2.critical === void 0 && i2.hazard === void 0 && i2.error_prone === void 0;
34369
34386
  const criteria = legacy ? { critical: Number(i2.score) || 0, hazard: Number(i2.score) || 0, error_prone: Number(i2.score) || 0 } : { critical: Number(i2.critical) || 0, hazard: Number(i2.hazard) || 0, error_prone: Number(i2.error_prone) || 0 };
@@ -34378,14 +34395,14 @@ var lunaRanker = {
34378
34395
  }
34379
34396
  }
34380
34397
  };
34381
- async function rankViaServer(candidates2, ctx, auth2) {
34398
+ async function rankViaServer(candidates2, ctx, auth3) {
34382
34399
  const fallback = deterministicOrder(candidates2);
34383
34400
  const excerptBytes = ctx.excerptBytes ?? 6 * 1024;
34384
34401
  const res = await apiRequest({
34385
34402
  method: "POST",
34386
34403
  path: "/prove/rank",
34387
- serviceUrl: auth2.serviceUrl,
34388
- token: auth2.token,
34404
+ serviceUrl: auth3.serviceUrl,
34405
+ token: auth3.token,
34389
34406
  body: {
34390
34407
  candidates: candidates2.map((c) => ({
34391
34408
  file: c.file,
@@ -34415,7 +34432,7 @@ function applyAnnotations(candidates2, items) {
34415
34432
  const annotated = candidates2.map((c) => {
34416
34433
  const a = byFile.get(c.file);
34417
34434
  if (!a) return { ...c, rank: 0 };
34418
- const properties = (a.properties ?? []).filter((p) => STRUCTURAL_CATALOGUE.includes(p));
34435
+ const properties = (a.properties ?? []).filter((p) => CATALOGUE.includes(p));
34419
34436
  const score = Math.max(0, Math.min(1, Number(a.score) || 0));
34420
34437
  const ai = { score, reasons: (a.reasons ?? []).slice(0, 3), properties };
34421
34438
  if (a.criteria && typeof a.criteria === "object") {
@@ -34424,6 +34441,9 @@ function applyAnnotations(candidates2, items) {
34424
34441
  }
34425
34442
  if (a.reasked) ai.reasked = true;
34426
34443
  if (a.symbol && a.symbol.trim()) ai.symbol = a.symbol.trim();
34444
+ if (a.lens === "security") ai.lens = "security";
34445
+ const hypotheses = (Array.isArray(a.hypotheses) ? a.hypotheses : []).filter((h) => typeof h === "string" && h.trim().length > 0).slice(0, MAX_HYPOTHESES).map((h) => h.trim().slice(0, 300));
34446
+ if (hypotheses.length) ai.hypotheses = hypotheses;
34427
34447
  return { ...c, rank: 0, ai };
34428
34448
  });
34429
34449
  annotated.sort((x, y) => {
@@ -34545,16 +34565,16 @@ function tokenizeLean(source2) {
34545
34565
  const out2 = [];
34546
34566
  const reasons = [];
34547
34567
  let i2 = 0;
34548
- const n = source2.length;
34568
+ const n2 = source2.length;
34549
34569
  const blank = (ch) => ch === "\n" ? "\n" : " ";
34550
- while (i2 < n) {
34570
+ while (i2 < n2) {
34551
34571
  const c = source2[i2];
34552
34572
  const next = source2[i2 + 1];
34553
34573
  if (c === "/" && next === "-") {
34554
34574
  let depth = 1;
34555
34575
  out2.push(" ");
34556
34576
  i2 += 2;
34557
- while (i2 < n && depth > 0) {
34577
+ while (i2 < n2 && depth > 0) {
34558
34578
  if (source2[i2] === "/" && source2[i2 + 1] === "-") {
34559
34579
  depth++;
34560
34580
  out2.push(" ");
@@ -34573,7 +34593,7 @@ function tokenizeLean(source2) {
34573
34593
  continue;
34574
34594
  }
34575
34595
  if (c === "-" && next === "-") {
34576
- while (i2 < n && source2[i2] !== "\n") {
34596
+ while (i2 < n2 && source2[i2] !== "\n") {
34577
34597
  out2.push(" ");
34578
34598
  i2++;
34579
34599
  }
@@ -34590,11 +34610,11 @@ function tokenizeLean(source2) {
34590
34610
  out2.push(" ".repeat(j + 1 - i2));
34591
34611
  i2 = j + 1;
34592
34612
  const close = '"' + "#".repeat(hashes);
34593
- while (i2 < n && source2.slice(i2, i2 + close.length) !== close) {
34613
+ while (i2 < n2 && source2.slice(i2, i2 + close.length) !== close) {
34594
34614
  out2.push(blank(source2[i2]));
34595
34615
  i2++;
34596
34616
  }
34597
- out2.push(" ".repeat(Math.min(close.length, n - i2)));
34617
+ out2.push(" ".repeat(Math.min(close.length, n2 - i2)));
34598
34618
  i2 += close.length;
34599
34619
  continue;
34600
34620
  }
@@ -34603,7 +34623,7 @@ function tokenizeLean(source2) {
34603
34623
  const interpolated = source2[i2 - 1] === "!" && source2[i2 - 2] === "s";
34604
34624
  out2.push(" ");
34605
34625
  i2++;
34606
- while (i2 < n && source2[i2] !== '"') {
34626
+ while (i2 < n2 && source2[i2] !== '"') {
34607
34627
  if (source2[i2] === "\\") {
34608
34628
  out2.push(" ");
34609
34629
  i2 += 2;
@@ -34612,7 +34632,7 @@ function tokenizeLean(source2) {
34612
34632
  if (interpolated && source2[i2] === "{") {
34613
34633
  let j = i2 + 1;
34614
34634
  let expr = "";
34615
- while (j < n && source2[j] !== "}" && source2[j] !== '"' && source2[j] !== "\n") expr += source2[j++];
34635
+ while (j < n2 && source2[j] !== "}" && source2[j] !== '"' && source2[j] !== "\n") expr += source2[j++];
34616
34636
  if (source2[j] !== "}") reasons.push(`string interpolation must close before a quote or line end: \`{${expr.trim().slice(0, 40)}\``);
34617
34637
  const words = expr.trim().split(/\s+/);
34618
34638
  if (words.length === 0 || words.some((w) => !/^[A-Za-z_][A-Za-z0-9_.']*$/.test(w))) {
@@ -34753,6 +34773,8 @@ var MAX_CO_ACCESSORS = 2;
34753
34773
  var MAX_HELPERS2 = 3;
34754
34774
  var MAX_CONTEXT_LINES = 120;
34755
34775
  var MAX_CALLERS2 = 3;
34776
+ var MAX_CHANGED_RANGES = 50;
34777
+ var MAX_HYPOTHESES2 = 3;
34756
34778
  var MAX_CALLER_LINES = 9;
34757
34779
  var MAX_HELPER_LINES = 80;
34758
34780
  var MAX_CONTEXT_BYTES = 48 * 1024;
@@ -34905,6 +34927,10 @@ def P1 : Property := { id := "parts_sum_to_total", kind := .structural, desc :=
34905
34927
  end Models.Split`;
34906
34928
  var RULES2 = `Write ONE Lean 4 model of the code below that could expose a real bug in it. Work in three steps.
34907
34929
 
34930
+ A PUSH. When the code below marks lines \`*|\`, this is the review of a push and those are the lines it changed. Look first for a bug the CHANGE introduced: what the changed lines made possible, removed or reordered \u2014 a check dropped, or moved after the write it guarded; a write moved before another; a new path that skips a dedup, a lock or a transaction; a new early return or exception that leaves state half-written; a new caller of shared state. Model the changed lines as actions (STEP 1). Among the properties (STEP 3), list FIRST those a trace through a changed line can break; a property that holds or fails the same without the change comes after them.
34931
+
34932
+ AN ATTACKER. When the input says SECURITY, model the environment as an ATTACKER, not as nature. The attacker controls: how many requests they send, when, and in which interleaving (many copies of the same request at once included); the order of their own steps in a multi-step flow (they may skip, repeat or reorder steps); which of their own accounts they use (they may hold several); the inputs they type, and the DNS of domains they own; and when they act relative to other users, to outages and to slow dependencies. The attacker does not control secrets, other users' credentials or the server code. A property counts only when the attacker can cause its violation and gains data, rights, money or service they must not get. The promises to check: limits, balances, counters, single-use tokens and "already done" checks hold for EVERY interleaving (\`rule:once\`, \`rule:no-lost-update\`); state shared across requests never lets one user or tenant read or act with another's data or rights (\`rule:isolation\`); a removed right is never kept or regained through a refresh, a cache or a copied claim (\`rule:revocation\`); every step of a multi-step flow is bound to the same subject and value an earlier step proved (\`rule:flow-binding\`); duplicated, late or reordered events end in the state of the order they were produced in (\`rule:event-order\`); a failing dependency yields deny, never another subject's answer (\`rule:fail-closed\`); the value checked is the value used (\`rule:check-use\`).
34933
+
34908
34934
  STEP 1 \u2014 Effects. The input lists the target's EFFECT SITES: awaits, calls on its dependencies, loops, try/catch, locks. Those are the only points where the real world can interleave, fail or crash. Each one that reads or writes shared state becomes an action, named after the real call and its line \u2014 "db.setBalance (L14)" \u2014 so a trace reads as a scenario someone can replay.
34909
34935
 
34910
34936
  STEP 2 \u2014 The environment's moves that exist in reality for THIS code, and only those:
@@ -34928,7 +34954,7 @@ STEP 3 \u2014 Properties: 2 to 4, in this order of priority:
34928
34954
  A counterexample must run the real function: a trace made only of environment moves (another writer, a clock) says nothing about this code. A promise about the END result (nothing lost, nothing charged twice, totals add up) is checked on states where every invocation has finished or crashed \u2014 guard the \`inv\` with the program counters, as exemplar 2's second property does; a violation that exists only while work is still pending is not a bug.
34929
34955
  A property is about an OUTCOME someone would call a bug \u2014 money, stock or records wrong, access granted, work lost or done twice, a job stuck forever \u2014 never about the mechanism's internals (a key's format, two timestamps being distinct, a lease's exact boundary tick). A comment that says HOW the code works ("make each attempt's key unique") is not the promise; the promise is what that mechanism is for.
34930
34956
  A comment that states a SAFE design choice ("a spent token presented again ends every session", "consumers dedupe, so publishing twice is harmless") is the design: never claim the opposite. A comment never makes an UNSAFE outcome safe: granting access on an error, losing or double-counting money, stock or records is a bug whatever the comment says ("don't block people when the permission service is flaky" describes a fail-open bug). Fail-open means an ACCESS decision: running WITHOUT an optional check when the check itself is unavailable, and saying so (a warning, a log line), is a stated degradation, not a fail-open \u2014 never claim it must fail closed.
34931
- Every property says what it rests on, in \`source\`: either \`L<n>: <words copied from that line>\` \u2014 a line of the numbered source above (a comment, docstring, check, error message or name) that states the promise \u2014 or one rule: \`rule:conservation\` (money, stock or counts add up), \`rule:once\` (no double effect: where the code dedups, or where the SAME input can arrive twice \u2014 an input that carries its own identity, such as an event, message, delivery or request id, redelivered or retried \u2014 even when the code has no dedup at all; a missing dedup is the bug, not a reason to drop the property. Two calls whose input carries no such identity are two operations: reserving a seat twice or creating a record twice from two requests is what the caller asked for, not a double effect), \`rule:no-lost-update\`, \`rule:fail-closed\` (an error in an access decision never grants access; an operation that failed is never reported as done), \`rule:progress\` (nothing stuck forever). A property that neither a line nor one of these rules supports is not a promise: do not state it. A property whose \`source\` is empty, or cites words its line does not contain, sends the model back.
34957
+ Every property says what it rests on, in \`source\`: either \`L<n>: <words copied from that line>\` \u2014 a line of the numbered source above (a comment, docstring, check, error message or name) that states the promise \u2014 or one rule: \`rule:conservation\` (money, stock or counts add up), \`rule:once\` (no double effect: where the code dedups, or where the SAME input can arrive twice \u2014 an input that carries its own identity, such as an event, message, delivery or request id, redelivered or retried \u2014 even when the code has no dedup at all; a missing dedup is the bug, not a reason to drop the property. Two calls whose input carries no such identity are two operations: reserving a seat twice or creating a record twice from two requests is what the caller asked for, not a double effect), \`rule:no-lost-update\`, \`rule:fail-closed\` (an error in an access decision never grants access; an operation that failed is never reported as done), \`rule:progress\` (nothing stuck forever); and for an attacker (SECURITY) \`rule:isolation\`, \`rule:revocation\`, \`rule:flow-binding\`, \`rule:event-order\`, \`rule:check-use\` (AN ATTACKER says what each means). A property that neither a line nor one of these rules supports is not a promise: do not state it. A property whose \`source\` is empty, or cites words its line does not contain, sends the model back.
34932
34958
  When the input lists where the function is called, a caller's guard bounds its inputs: never build a counterexample from an input no caller can pass (an empty list a caller refuses).
34933
34959
  Property ids name the promise in snake_case (refund_total_within_capture) \u2014 never P1. \`desc\` states the promise in the code's own terms and names the move the trace needs ("two concurrent calls \u2026", "after the charge succeeded and the call timed out \u2026").
34934
34960
  A PURE computation (no effect sites) is checked with \`Verity.checkData\` on small concrete inputs, including the edge cases (exemplar 3).
@@ -34998,19 +35024,19 @@ var PURE_METHODS2 = /* @__PURE__ */ new Set([
34998
35024
  "test",
34999
35025
  "match"
35000
35026
  ]);
35001
- function callsOn(text, name2) {
35027
+ function callsOn(text2, name2) {
35002
35028
  const needle = `${name2}.`;
35003
- for (let i2 = text.indexOf(needle); i2 >= 0; i2 = text.indexOf(needle, i2 + 1)) {
35004
- if (i2 > 0 && IDENT_CHAR2.test(text[i2 - 1])) continue;
35005
- const call = CALL_AFTER_DOT.exec(text.slice(i2 + needle.length));
35029
+ for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
35030
+ if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
35031
+ const call = CALL_AFTER_DOT.exec(text2.slice(i2 + needle.length));
35006
35032
  if (call && !PURE_METHODS2.has(call[1])) return true;
35007
35033
  }
35008
35034
  return false;
35009
35035
  }
35010
- function callsDirect(text, name2) {
35036
+ function callsDirect(text2, name2) {
35011
35037
  const needle = `${name2}(`;
35012
- for (let i2 = text.indexOf(needle); i2 >= 0; i2 = text.indexOf(needle, i2 + 1)) {
35013
- if (i2 > 0 && IDENT_CHAR2.test(text[i2 - 1])) continue;
35038
+ for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
35039
+ if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
35014
35040
  return true;
35015
35041
  }
35016
35042
  return false;
@@ -35042,17 +35068,44 @@ function effectSites(numbered2) {
35042
35068
  }
35043
35069
  return out2;
35044
35070
  }
35071
+ function starChanged(numbered2, changed) {
35072
+ const isChanged = (n2) => !!changed?.some((r) => n2 >= r.from && n2 <= r.to);
35073
+ const starred = [];
35074
+ let total = 0;
35075
+ const text2 = numbered2.split("\n").map((raw) => {
35076
+ const m = NUMBERED_LINE.exec(raw);
35077
+ if (!m) return raw;
35078
+ total++;
35079
+ const n2 = Number(m[1]);
35080
+ if (!isChanged(n2)) return raw;
35081
+ starred.push(n2);
35082
+ return raw.replace("|", "*|");
35083
+ }).join("\n");
35084
+ const runs = [];
35085
+ for (let i2 = 0; i2 < starred.length; i2++) {
35086
+ let j = i2;
35087
+ while (j + 1 < starred.length && starred[j + 1] === starred[j] + 1) j++;
35088
+ runs.push(i2 === j ? `${starred[i2]}` : `${starred[i2]}\u2013${starred[j]}`);
35089
+ i2 = j;
35090
+ }
35091
+ return { text: text2, ranges: runs.join(", "), count: starred.length, total };
35092
+ }
35045
35093
  function renderGenerateInput(t, previous) {
35046
35094
  const parts2 = [];
35047
35095
  parts2.push(`# Target: ${t.file} \u2014 \`${t.symbol}\`${t.lines ? ` (lines ${t.lines.from}\u2013${t.lines.to})` : ""}`);
35048
35096
  parts2.push(`Header values: file := "${t.file}", symbol := "${t.symbol}", sha256 := "${t.sha256}", lines := "${t.lines ? `${t.lines.from}-${t.lines.to}` : ""}"`);
35049
35097
  if (t.reasons.length) parts2.push(`Why it was selected: ${t.reasons.join(" \xB7 ")}`);
35050
35098
  if (t.properties.length) parts2.push(`Suggested properties: ${t.properties.join(", ")}`);
35099
+ if (t.lens === "security") parts2.push("SECURITY: an attacker outside the trust boundary can drive this code. Follow AN ATTACKER.");
35100
+ if (t.hypotheses?.length) parts2.push(`Hypotheses from the selector (questions to try, not verdicts):
35101
+ ${t.hypotheses.slice(0, MAX_HYPOTHESES2).map((h) => ` - ${h}`).join("\n")}`);
35051
35102
  const numbered2 = t.numbered.slice(0, MAX_NUMBERED_BYTES);
35052
35103
  const sites = effectSites(numbered2);
35104
+ const push = starChanged(numbered2, t.changed);
35105
+ if (push.count > 0) parts2.push(`A push: it changed ${push.count} of these ${push.total} lines (${push.ranges}), marked \`*|\` below. Look first for a bug the change introduced.`);
35053
35106
  parts2.push("", sites.length ? `Effect sites (STEP 1 \u2014 where the real world can interleave, fail or crash):
35054
35107
  ${sites.map((s) => ` ${s}`).join("\n")}` : "Effect sites: none \u2014 a pure computation (STEP 3: Verity.checkData on concrete inputs).");
35055
- parts2.push("", "```", numbered2, "```");
35108
+ parts2.push("", "```", push.count > 0 ? push.text : numbered2, "```");
35056
35109
  if (t.effects?.length) {
35057
35110
  parts2.push("", `State this function touches (from the parser; "via" names the helper that does it):
35058
35111
  ${t.effects.slice(0, MAX_CONTEXT_EFFECTS).map((e) => ` ${e}`).join("\n")}`);
@@ -35166,11 +35219,11 @@ async function generateModel(target, opts) {
35166
35219
  return { ok: false, error: name2 === "TimeoutError" || name2 === "AbortError" ? "timed out" : err2.message };
35167
35220
  }
35168
35221
  const usage = data.usage ? { inputTokens: Number(data.usage.input_tokens ?? 0), outputTokens: Number(data.usage.output_tokens ?? 0) } : null;
35169
- const text = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
35170
- if (!text) return { ok: false, error: "no output_text in response", usage };
35222
+ const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
35223
+ if (!text2) return { ok: false, error: "no output_text in response", usage };
35171
35224
  let parsed;
35172
35225
  try {
35173
- parsed = JSON.parse(text);
35226
+ parsed = JSON.parse(text2);
35174
35227
  } catch {
35175
35228
  return { ok: false, error: "answer was not JSON", usage };
35176
35229
  }
@@ -35180,8 +35233,8 @@ async function generateModel(target, opts) {
35180
35233
  // src/lib/prove/replay.ts
35181
35234
  var MAX_SOURCE_BYTES = 96 * 1024;
35182
35235
  var MAX_MODEL_BYTES = 32 * 1024;
35183
- function numberLines(text, from = 1) {
35184
- return text.split("\n").map((l, i2) => `${String(i2 + from).padStart(5)}| ${l}`).join("\n");
35236
+ function numberLines(text2, from = 1) {
35237
+ return text2.split("\n").map((l, i2) => `${String(i2 + from).padStart(5)}| ${l}`).join("\n");
35185
35238
  }
35186
35239
  var PY_DECL = /^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(/;
35187
35240
  var TS_DECLS = [
@@ -35255,9 +35308,9 @@ function extractSymbolBody(source2, symbol, file, range) {
35255
35308
  }
35256
35309
  return null;
35257
35310
  }
35258
- function significantLines(text) {
35311
+ function significantLines(text2) {
35259
35312
  const out2 = [];
35260
- for (const raw of text.split("\n")) {
35313
+ for (const raw of text2.split("\n")) {
35261
35314
  const l = raw.trim();
35262
35315
  if (l.length < 12) continue;
35263
35316
  if (/^(\/\/|\/\*|\*|#)/.test(l)) continue;
@@ -35282,14 +35335,14 @@ function isTrackedInRoot(root, file) {
35282
35335
  function buildReplayBrief(root, report, property, modelSource, readSource) {
35283
35336
  const sources = (report.header?.abstracts ?? []).map((a) => {
35284
35337
  const read2 = readSource ? readSource(a.file, MAX_SOURCE_BYTES) : isTrackedInRoot(root, a.file) ? readRegularFileInRoot(root, a.file, MAX_SOURCE_BYTES) : { ok: false, reason: "not tracked by git \u2014 models may only abstract tracked source" };
35285
- const text = read2.ok ? read2.content : "";
35338
+ const text2 = read2.ok ? read2.content : "";
35286
35339
  return {
35287
35340
  file: a.file,
35288
35341
  symbol: a.symbol,
35289
- numbered: text ? numberLines(text) : `(could not read ${a.file}: ${read2.ok ? "" : read2.reason})`,
35290
- symbolBody: text ? extractSymbolBody(text, a.symbol, a.file, a.lines) : null,
35342
+ numbered: text2 ? numberLines(text2) : `(could not read ${a.file}: ${read2.ok ? "" : read2.reason})`,
35343
+ symbolBody: text2 ? extractSymbolBody(text2, a.symbol, a.file, a.lines) : null,
35291
35344
  lines: a.lines,
35292
- content: text
35345
+ content: text2
35293
35346
  };
35294
35347
  });
35295
35348
  return { model: report.model, property, modelSource: modelSource.slice(0, MAX_MODEL_BYTES), sources };
@@ -35371,7 +35424,7 @@ function parseReplayOutput(output) {
35371
35424
  let executedCalls = 0;
35372
35425
  const shellTexts = [];
35373
35426
  const outputTexts = [];
35374
- let text = null;
35427
+ let text2 = null;
35375
35428
  for (const item of output) {
35376
35429
  if (item.type === "shell_call") {
35377
35430
  shellCalls++;
@@ -35387,13 +35440,13 @@ function parseReplayOutput(output) {
35387
35440
  }
35388
35441
  } else if (item.type === "message" && Array.isArray(item.content)) {
35389
35442
  const t = item.content.find((c) => c.type === "output_text")?.text;
35390
- if (typeof t === "string") text = t;
35443
+ if (typeof t === "string") text2 = t;
35391
35444
  }
35392
35445
  }
35393
35446
  let claim = null;
35394
- if (text) {
35447
+ if (text2) {
35395
35448
  try {
35396
- const o = JSON.parse(text);
35449
+ const o = JSON.parse(text2);
35397
35450
  const verdict = o.verdict;
35398
35451
  if (verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable") {
35399
35452
  claim = {
@@ -35614,14 +35667,14 @@ async function runReplayInContainer(brief, opts) {
35614
35667
  }
35615
35668
  }
35616
35669
  }
35617
- async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
35670
+ async function runReplayViaServer(brief, auth3, budgetMs = 24e4) {
35618
35671
  const started = Date.now();
35619
35672
  const budget = Math.max(2e4, Math.round(budgetMs));
35620
35673
  const res = await apiRequest({
35621
35674
  method: "POST",
35622
35675
  path: "/prove/replay",
35623
- serviceUrl: auth2.serviceUrl,
35624
- token: auth2.token,
35676
+ serviceUrl: auth3.serviceUrl,
35677
+ token: auth3.token,
35625
35678
  body: {
35626
35679
  model: brief.model,
35627
35680
  model_source: brief.modelSource,
@@ -36271,14 +36324,14 @@ function parseProperty(obj) {
36271
36324
  if (!model || !id || !kind2 || !result || source2 === null || desc === null) return null;
36272
36325
  const p = { model, id, kind: kind2, source: source2, desc, result };
36273
36326
  if (obj.bound !== void 0) {
36274
- const n = nat(obj.bound);
36275
- if (n === null) return null;
36276
- p.bound = n;
36327
+ const n2 = nat(obj.bound);
36328
+ if (n2 === null) return null;
36329
+ p.bound = n2;
36277
36330
  }
36278
36331
  if (obj.states !== void 0) {
36279
- const n = nat(obj.states);
36280
- if (n === null) return null;
36281
- p.states = n;
36332
+ const n2 = nat(obj.states);
36333
+ if (n2 === null) return null;
36334
+ p.states = n2;
36282
36335
  }
36283
36336
  if (obj.trace !== void 0) {
36284
36337
  const t = strArr(obj.trace, LIMITS.traceItems, LIMITS.traceItem);
@@ -36577,8 +36630,8 @@ function listModelFiles(root) {
36577
36630
  if (!(0, import_node_fs61.existsSync)(modelsAbs)) return [];
36578
36631
  return (0, import_node_fs61.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path48.join)(modelsAbs, f));
36579
36632
  }
36580
- function trimDiagnostics(text) {
36581
- return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36633
+ function trimDiagnostics(text2) {
36634
+ return text2.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36582
36635
  }
36583
36636
  function checkModel(tc, root, modelFile, opts = {}) {
36584
36637
  const proofsAbs = (0, import_node_path48.join)(root, PROOFS_DIR);
@@ -36646,33 +36699,70 @@ function writeResult(root, report) {
36646
36699
  function isCrashTrace(trace) {
36647
36700
  return trace.some((s) => /\b(crash\w*|kill\w*|restart\w*|interrupt\w*|power|abort\w*|process (dies|exit\w*)|lost (reply|response))\b/i.test(s));
36648
36701
  }
36702
+ function formalDisposition(f) {
36703
+ if (f.verdict !== "reproduced" || f.waived) return "none";
36704
+ const c = f.check;
36705
+ if (!c || c.outcome !== "answered") return "block";
36706
+ switch (c.verdict) {
36707
+ case "REAL":
36708
+ return c.introduced === "no" ? "report" : "block";
36709
+ case "REAL-LOW":
36710
+ return "report";
36711
+ case "PREVENTED":
36712
+ case "ARTIFACT":
36713
+ return "checked";
36714
+ default:
36715
+ return "block";
36716
+ }
36717
+ }
36718
+ var CAUTION = { block: 3, report: 2, checked: 1, none: 0 };
36719
+ function cautiousCheck(f, checks) {
36720
+ if (checks.length === 0) return void 0;
36721
+ let chosen = checks[0];
36722
+ for (const c of checks.slice(1)) if (CAUTION[formalDisposition({ ...f, check: c })] > CAUTION[formalDisposition({ ...f, check: chosen })]) chosen = c;
36723
+ return { ...chosen, votes: checks.map((c) => c.outcome === "answered" && c.verdict ? c.verdict : c.outcome), costUsd: checks.reduce((n2, c) => n2 + c.costUsd, 0), unpriced: checks.reduce((n2, c) => n2 + c.unpriced, 0) };
36724
+ }
36725
+ function checkLine(f) {
36726
+ const c = f.check;
36727
+ if (!c || c.outcome !== "answered" || !c.verdict) return "";
36728
+ const why = c.verdict === "PREVENTED" ? c.preventedBy || c.reason : c.reason;
36729
+ const from = c.trigger ? ` Reached from: ${c.trigger}.` : "";
36730
+ const pre = c.introduced === "no" ? " Already possible before this change." : "";
36731
+ const votes = c.votes && c.votes.length > 1 ? ` (${c.votes.length} checks: ${c.votes.join(", ")})` : "";
36732
+ return `Checked: ${c.verdict}${votes}.${from}${pre} ${why ?? ""}`.trim();
36733
+ }
36649
36734
  function mergeFormalFindings(response, outcome, pushedFiles) {
36650
- if (!outcome) return { blocking: 0 };
36735
+ if (!outcome) return { blocking: 0, reported: 0 };
36651
36736
  const norm3 = (p) => p.replace(/\\/g, "/");
36652
36737
  const pushed = new Set(pushedFiles.map(norm3));
36653
- const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm3(f.file)));
36654
- if (blocking.length === 0) return { blocking: 0 };
36738
+ const onPush = outcome.findings.filter((f) => pushed.has(norm3(f.file)));
36739
+ const blocking = onPush.filter((f) => formalDisposition(f) === "block");
36740
+ const reported = onPush.filter((f) => formalDisposition(f) === "report");
36741
+ if (blocking.length === 0 && reported.length === 0) return { blocking: 0, reported: 0 };
36655
36742
  const existing = Array.isArray(response.findings) ? response.findings : [];
36656
- response.findings = [
36657
- ...existing,
36658
- ...blocking.map((f) => ({
36743
+ const asFinding = (f, blocks) => {
36744
+ const checked = checkLine(f);
36745
+ return {
36659
36746
  pattern_id: "formal-counterexample",
36660
- severity: "high",
36661
- scope: "change",
36747
+ severity: blocks ? "high" : "medium",
36748
+ // A bug this change did not introduce is filed the way the gate files everything it will not block on.
36749
+ scope: f.check?.introduced === "no" && !blocks ? "pre-existing" : "change",
36662
36750
  file: f.file,
36663
36751
  line: outcome.target?.lines?.from ?? null,
36664
36752
  // Worded as the VIOLATION: the property text is what should hold, and
36665
36753
  // as a title it read backwards (e2e, 2026-09-26). A trace that needs a
36666
36754
  // crash between two writes is labelled: reproducing it means injecting
36667
36755
  // the crash, so it is a crash-consistency finding, not a race.
36668
- title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code`,
36669
- description: terminalText(f.reason ?? "", 2e3),
36756
+ title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code${f.check?.outcome === "answered" ? `, checked ${f.check.verdict}` : ""}`,
36757
+ description: terminalText([f.reason ?? "", checked].filter(Boolean).join(" "), 2e3),
36670
36758
  fix: { description: `Trace: ${terminalText(f.trace.join(" \u2192 ") || "(initial state)", 2e3)}. Replay: ${terminalText(f.reason ?? "reproduced in the container", 2e3)}` },
36671
36759
  source: "formal"
36672
- }))
36673
- ];
36674
- if (response.gate_decision !== "FAIL") response.gate_decision = "FAIL";
36675
- return { blocking: blocking.length };
36760
+ };
36761
+ };
36762
+ response.findings = [...existing, ...blocking.map((f) => asFinding(f, true)), ...reported.map((f) => asFinding(f, false))];
36763
+ if (blocking.length > 0) response.gate_decision = "FAIL";
36764
+ else if (response.gate_decision === "PASS") response.gate_decision = "WARN";
36765
+ return { blocking: blocking.length, reported: reported.length };
36676
36766
  }
36677
36767
 
36678
36768
  // src/lib/prove/scalpel.ts
@@ -36836,6 +36926,11 @@ function isEligible(s, largePush) {
36836
36926
  if (critical) return { ok: true, why: "domain-critical" };
36837
36927
  return { ok: false, why: "no effects, no risky shape, not domain-critical" };
36838
36928
  }
36929
+ function changedWithin(changed, lines) {
36930
+ if (!changed?.length) return [];
36931
+ const inside2 = lines ? changed.filter((r) => r.from <= lines.to && lines.from <= r.to).map((r) => ({ from: Math.max(r.from, lines.from), to: Math.min(r.to, lines.to) })) : changed;
36932
+ return inside2.slice(0, MAX_CHANGED_RANGES);
36933
+ }
36839
36934
  function intersects(a, ranges) {
36840
36935
  return ranges.some((b) => a.from <= b.to && b.from <= a.to);
36841
36936
  }
@@ -36887,14 +36982,14 @@ function readPersistedFindings(root) {
36887
36982
  function waiveFormalFindings(root, file, reason) {
36888
36983
  const all = readPersistedFindings(root);
36889
36984
  const at = (/* @__PURE__ */ new Date()).toISOString();
36890
- let n = 0;
36985
+ let n2 = 0;
36891
36986
  const next = all.map((f) => {
36892
36987
  if (f.file !== file || f.waived) return f;
36893
- n++;
36988
+ n2++;
36894
36989
  return { ...f, waived: { reason: reason.slice(0, 500), at } };
36895
36990
  });
36896
- if (n > 0) writePersistedFindings(root, next);
36897
- return n;
36991
+ if (n2 > 0) writePersistedFindings(root, next);
36992
+ return n2;
36898
36993
  }
36899
36994
  function writePersistedFindings(root, findings) {
36900
36995
  if (!isLocalState(root, FINDINGS_FILE)) return;
@@ -36909,6 +37004,8 @@ function bumpLedger(root) {
36909
37004
  }
36910
37005
  var REPLAY_RESERVE_MS = 45e3;
36911
37006
  var MAX_REPLAYS = 3;
37007
+ var MAX_CHECKS = 2;
37008
+ var CHECK_VOTES = 2;
36912
37009
  function isNetworkError(message) {
36913
37010
  return /Network error|fetch failed|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|socket hang up/i.test(message);
36914
37011
  }
@@ -36991,7 +37088,9 @@ async function runFormalPhase(input) {
36991
37088
  symbol: f.symbol,
36992
37089
  verdict: "reproduced",
36993
37090
  reason: f.waived ? `waived ${f.waived.at.slice(0, 10)}: ${f.waived.reason} (standing since ${f.at.slice(0, 10)}; the file has not changed)` : `${f.reason ?? "reproduced on the real code"} (standing since ${f.at.slice(0, 10)}; the file has not changed)`,
36994
- ...f.waived ? { waived: true } : {}
37091
+ ...f.waived ? { waived: true } : {},
37092
+ // Same bytes, same answer: the check is not paid for twice.
37093
+ ...f.check ? { check: { outcome: "answered", rounds: 0, costUsd: 0, unpriced: 0, durationMs: 0, ...f.check } } : {}
36995
37094
  });
36996
37095
  }
36997
37096
  }
@@ -37013,13 +37112,13 @@ async function runFormalPhase(input) {
37013
37112
  if (signals.length === 0) return done({ status: "skipped", skip: "no-source-files" });
37014
37113
  const largePush = signals.length >= LARGE_PUSH_FILES || files.length >= LARGE_PUSH_FILES * 2;
37015
37114
  const mapEligible = (file) => {
37016
- const changed = input.changedLines?.get(file);
37017
- if (!deps.codeMap || largePush || !changed?.length) return false;
37115
+ const changed2 = input.changedLines?.get(file);
37116
+ if (!deps.codeMap || largePush || !changed2?.length) return false;
37018
37117
  const read2 = readSrc(file, 96 * 1024);
37019
37118
  if (!read2.ok) return false;
37020
37119
  const outline = deps.codeMap.outline(file, read2.content);
37021
37120
  if (outline.source !== "tree-sitter") return false;
37022
- return outline.value.some((f) => changed.some((r) => f.start.line <= r.to && r.from <= f.end.line) && (() => {
37121
+ return outline.value.some((f) => changed2.some((r) => f.start.line <= r.to && r.from <= f.end.line) && (() => {
37023
37122
  const a = deps.codeMap.access(file, read2.content, f);
37024
37123
  return a.source === "tree-sitter" && a.value.effects.length >= 2;
37025
37124
  })());
@@ -37079,8 +37178,8 @@ async function runFormalPhase(input) {
37079
37178
  }
37080
37179
  if (d.resolved && d.resolved !== c.ai.symbol) c.ai.symbol = d.resolved;
37081
37180
  if (input.changedLines) {
37082
- const changed = input.changedLines.get(c.file) ?? [];
37083
- if (changed.length === 0) {
37181
+ const changed2 = input.changedLines.get(c.file) ?? [];
37182
+ if (changed2.length === 0) {
37084
37183
  note("symbol-not-in-push", `${c.file}: no changed lines in this push`);
37085
37184
  continue;
37086
37185
  }
@@ -37088,7 +37187,7 @@ async function runFormalPhase(input) {
37088
37187
  note("symbol-not-in-push", `${c.ai.symbol}: body not found, cannot tell whether the push touched it`);
37089
37188
  continue;
37090
37189
  }
37091
- if (!intersects(d.lines, changed)) {
37190
+ if (!intersects(d.lines, changed2)) {
37092
37191
  note("symbol-not-in-push", `${c.ai.symbol} (lines ${d.lines.from}\u2013${d.lines.to}) unchanged by this push`);
37093
37192
  continue;
37094
37193
  }
@@ -37146,7 +37245,8 @@ async function runFormalPhase(input) {
37146
37245
  if (!REPLAYABLE.test(top.file)) return done({ status: "skipped", skip: "replay-unsupported", detail: `${top.file}: replay supports TS/JS and Python`, target });
37147
37246
  if (timeLeft() < GENERATE_RESERVE_MS) return done({ status: "skipped", skip: "not-enough-time", detail: `${Math.round(timeLeft() / 1e3)} s left before generation`, target });
37148
37247
  bumpLedger(root);
37149
- const genTarget = { file: top.file, symbol: top.ai.symbol, lines, sha256: sha2562, numbered: numbered2, reasons: target.reasons, properties: top.ai.properties, ...chosen.context?.fields ?? {}, extentSource: chosen.extent };
37248
+ const changed = changedWithin(input.changedLines?.get(top.file), lines);
37249
+ const genTarget = { file: top.file, symbol: top.ai.symbol, lines, sha256: sha2562, numbered: numbered2, reasons: target.reasons, properties: top.ai.properties, ...chosen.context?.fields ?? {}, extentSource: chosen.extent, ...changed.length ? { changed } : {}, ...top.ai.lens === "security" ? { lens: "security" } : {}, ...top.ai.hypotheses?.length ? { hypotheses: top.ai.hypotheses } : {} };
37150
37250
  const headerFiles = /* @__PURE__ */ new Set([top.file, ...chosen.context?.files ?? []]);
37151
37251
  let previous;
37152
37252
  let report = null;
@@ -37267,13 +37367,40 @@ async function runFormalPhase(input) {
37267
37367
  const verdict = r.verdict === "reproduced" ? "reproduced" : r.verdict === "diverged" ? "diverged" : r.verdict === "unreplayable" ? "model-only" : "unverified";
37268
37368
  findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0 });
37269
37369
  }
37370
+ const toCheck = deps.verify && !cancelled() ? findings.filter((f) => f.verdict === "reproduced").slice(0, MAX_CHECKS) : [];
37371
+ if (toCheck.length > 0) {
37372
+ progress.step = "verify";
37373
+ const share = Math.max(0, costCap - usage.costUsd) / (toCheck.length * CHECK_VOTES);
37374
+ const failed = (error) => ({ outcome: "failed", verdict: null, introduced: "unknown", rounds: 0, costUsd: 0, unpriced: 0, durationMs: 0, error });
37375
+ await Promise.all(toCheck.map(async (f) => {
37376
+ const checks = await Promise.all(Array.from({ length: CHECK_VOTES }, () => deps.verify(f, { ...lines ? { lines } : {}, changedLines: input.changedLines?.get(f.file) ?? [], deadlineAt: input.deadlineAt, costLeftUsd: share }).catch((err2) => failed(String(err2?.message ?? err2).slice(0, 120)))));
37377
+ for (const c of checks) {
37378
+ if (c.costUsd > 0) spend({ costUsd: c.costUsd });
37379
+ for (let i2 = 0; i2 < c.unpriced; i2++) usage.unpriced++;
37380
+ }
37381
+ if (!cancelled()) f.check = cautiousCheck(f, checks);
37382
+ }));
37383
+ }
37270
37384
  const reproduced = findings.filter((f) => f.verdict === "reproduced");
37271
37385
  if (reproduced.length > 0 && !cancelled()) {
37272
37386
  const now = (/* @__PURE__ */ new Date()).toISOString();
37273
37387
  const others = readPersistedFindings(root).filter((f) => f.file !== top.file);
37274
37388
  writePersistedFindings(root, [
37275
37389
  ...others,
37276
- ...reproduced.map((f) => ({ file: f.file, symbol: f.symbol, sha256: sha2562, property: f.property, desc: f.desc, kind: f.kind, trace: f.trace, model: modelName, reason: f.reason, ...lines ? { lines } : {}, at: now }))
37390
+ ...reproduced.map((f) => ({
37391
+ file: f.file,
37392
+ symbol: f.symbol,
37393
+ sha256: sha2562,
37394
+ property: f.property,
37395
+ desc: f.desc,
37396
+ kind: f.kind,
37397
+ trace: f.trace,
37398
+ model: modelName,
37399
+ reason: f.reason,
37400
+ ...lines ? { lines } : {},
37401
+ at: now,
37402
+ ...f.check?.outcome === "answered" ? { check: { verdict: f.check.verdict, introduced: f.check.introduced, trigger: f.check.trigger, preventedBy: f.check.preventedBy, effect: f.check.effect, reason: f.check.reason, ...f.check.votes ? { votes: f.check.votes } : {} } } : {}
37403
+ }))
37277
37404
  ]);
37278
37405
  }
37279
37406
  const clean2 = findings.every((f) => f.verdict === "diverged");
@@ -37317,9 +37444,9 @@ function describeTarget(content, symbol, file, range, opts = {}) {
37317
37444
  }
37318
37445
  const body2 = extractSymbolBody(content, symbol, file);
37319
37446
  if (!body2) return { numbered: numberLines(content.slice(0, 24 * 1024)), extent };
37320
- const n = body2.split("\n").length;
37321
- const from = all.findIndex((_, i2) => all.slice(i2, i2 + n).join("\n") === body2) + 1;
37322
- return { lines: from > 0 ? { from, to: from + n - 1 } : void 0, numbered: numberLines(body2, from > 0 ? from : 1), extent };
37447
+ const n2 = body2.split("\n").length;
37448
+ const from = all.findIndex((_, i2) => all.slice(i2, i2 + n2).join("\n") === body2) + 1;
37449
+ return { lines: from > 0 ? { from, to: from + n2 - 1 } : void 0, numbered: numberLines(body2, from > 0 ? from : 1), extent };
37323
37450
  }
37324
37451
  async function generateAndCheck(root, req, opts) {
37325
37452
  const readSrc = opts.deps.readSource ?? workingTreeReader(root);
@@ -37333,7 +37460,7 @@ async function generateAndCheck(root, req, opts) {
37333
37460
  if (outline?.source === "tree-sitter") {
37334
37461
  const names2 = [...new Set(outline.value.filter((f) => f.name && f.kind !== "lambda").map((f) => f.qualified))];
37335
37462
  const last = (req.symbol.split(/[.#:]/).pop() ?? req.symbol).toLowerCase();
37336
- const close = names2.filter((n) => n.toLowerCase().includes(last));
37463
+ const close = names2.filter((n2) => n2.toLowerCase().includes(last));
37337
37464
  const shown = (close.length > 0 ? close : names2).slice(0, 12);
37338
37465
  return { ok: false, error: `no function \`${req.symbol}\` in ${req.file}${shown.length ? ` (it has: ${shown.join(", ")})` : ""}. Name one as ${req.file}#<name>, or pass --lines a-b`, rounds: 0, costUsd: 0 };
37339
37466
  }
@@ -37402,9 +37529,9 @@ async function generateAndCheck(root, req, opts) {
37402
37529
  function skippedOutcome(skip, detail) {
37403
37530
  return { status: "skipped", skip, ...detail ? { detail } : {}, findings: [], usage: { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 }, durationMs: 0 };
37404
37531
  }
37405
- async function prepareFormalPhase(root, env = process.env, auth2, readSource, codeSource) {
37532
+ async function prepareFormalPhase(root, env = process.env, auth3, readSource, codeSource) {
37406
37533
  const direct = env.VERITY_PROVE_DIRECT === "1" && !!env.OPENAI_API_KEY;
37407
- if (!auth2 && !direct) return { ok: false, skip: "not-logged-in" };
37534
+ if (!auth3 && !direct) return { ok: false, skip: "not-logged-in" };
37408
37535
  const apiKey = direct ? env.OPENAI_API_KEY : void 0;
37409
37536
  const toolchain = findToolchain(env);
37410
37537
  if (!toolchain) return { ok: false, skip: "no-toolchain" };
@@ -37418,7 +37545,7 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
37418
37545
  const build = await buildLibraryAsync(toolchain, root, 9e4);
37419
37546
  if (!build.ok) return { ok: false, skip: "library-build-failed", detail: build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).join(" ").slice(0, 200) };
37420
37547
  const code = await loadCodeContext(root, env, codeSource);
37421
- return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...code }), codeSource: code.codeSource } };
37548
+ return { ok: true, deps: { ...defaultDeps({ auth: auth3, apiKey, env, toolchain, readSource, ...code }), codeSource: code.codeSource } };
37422
37549
  }
37423
37550
  async function loadCodeContext(root, env = process.env, codeSource) {
37424
37551
  const loaded = await loadCodeMap(env);
@@ -37493,7 +37620,9 @@ function describeFormalOutcome(o) {
37493
37620
  if (o.status === "skipped") return `formal: skipped (${o.skip}${o.detail ? `: ${o.detail}` : ""})`;
37494
37621
  const parts2 = o.properties?.map((p) => {
37495
37622
  const f = o.findings.find((x) => x.property === p.id);
37496
- const tag = p.result === "counterexample" ? f ? f.verdict.toUpperCase() + (f.waived ? " (waived)" : "") : "counterexample" : p.result;
37623
+ const votes = f?.check?.votes && f.check.votes.length > 1 ? ` [${f.check.votes.join(", ")}]` : "";
37624
+ const checked = f?.check ? f.check.outcome === "answered" ? ` \u2192 checked ${f.check.verdict}${f.check.introduced === "no" ? " (pre-existing)" : ""}${votes}` : ` \u2192 not checked (${f.check.outcome})${votes}` : "";
37625
+ const tag = p.result === "counterexample" ? f ? f.verdict.toUpperCase() + (f.waived ? " (waived)" : "") + checked : "counterexample" : p.result;
37497
37626
  return `${p.id} ${tag}`;
37498
37627
  }) ?? [];
37499
37628
  const cost = o.usage.costUsd > 0 ? ` \xB7 $${o.usage.costUsd.toFixed(2)}` : "";
@@ -37501,6 +37630,105 @@ function describeFormalOutcome(o) {
37501
37630
  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}`;
37502
37631
  }
37503
37632
 
37633
+ // src/lib/prove/verify.ts
37634
+ var MIN_VERIFY_TURN_MS = 15e3;
37635
+ var MIN_VERIFY_START_MS = 45e3;
37636
+ var VERIFY_TURN_HOLD_USD = 0.1;
37637
+ var MAX_TURNS2 = 14;
37638
+ var VERDICTS = ["REAL", "REAL-LOW", "PREVENTED", "ARTIFACT", "UNSURE"];
37639
+ var verdictOf = (v) => typeof v === "string" && VERDICTS.includes(v) ? v : null;
37640
+ var introducedOf = (v) => v === "yes" || v === "no" ? v : "unknown";
37641
+ var text = (v, n2) => typeof v === "string" ? v.slice(0, n2) : "";
37642
+ function verifyPost(auth3) {
37643
+ return async (body2, timeoutMs) => {
37644
+ const res = await apiRequest({
37645
+ method: "POST",
37646
+ path: "/prove/verify",
37647
+ serviceUrl: auth3.serviceUrl,
37648
+ token: auth3.token,
37649
+ // Streamed with a heartbeat, like generate and replay (decision 53).
37650
+ extraHeaders: { "X-Verity-Keepalive": "1" },
37651
+ body: body2,
37652
+ timeout: timeoutMs,
37653
+ cmd: "prove-verify"
37654
+ });
37655
+ return res.ok ? { ok: true, data: res.data ?? {} } : { ok: false, error: res.error };
37656
+ };
37657
+ }
37658
+ function wellFormedCalls(raw, offered) {
37659
+ const calls = [];
37660
+ for (const c of raw) {
37661
+ if (!c || typeof c !== "object" || Array.isArray(c)) return null;
37662
+ const o = c;
37663
+ if (typeof o.call_id !== "string" || o.call_id.length === 0 || o.call_id.length > 200) return null;
37664
+ if (typeof o.name !== "string" || !offered.includes(o.name)) return null;
37665
+ const args2 = o.arguments ?? {};
37666
+ if (!args2 || typeof args2 !== "object" || Array.isArray(args2)) return null;
37667
+ calls.push({ call_id: o.call_id, name: o.name, arguments: args2 });
37668
+ }
37669
+ return calls;
37670
+ }
37671
+ async function verifyFinding(input, opts) {
37672
+ const now = opts.now ?? Date.now;
37673
+ const startedAt = now();
37674
+ const remaining = () => opts.deadlineAt - now();
37675
+ let rounds = 0;
37676
+ let costUsd = 0;
37677
+ let unpriced = 0;
37678
+ const end = (outcome, extra = {}) => ({ outcome, verdict: null, introduced: "unknown", rounds, costUsd, unpriced, durationMs: now() - startedAt, ...extra });
37679
+ if (remaining() < MIN_VERIFY_START_MS) return end("deadline", { error: "not enough time left" });
37680
+ let body2 = {
37681
+ target: {
37682
+ file: input.file,
37683
+ symbol: input.symbol,
37684
+ ...input.lines ? { lines: input.lines } : {},
37685
+ property: input.property,
37686
+ replay_reason: input.replayReason,
37687
+ changed_lines: input.changedLines.slice(0, 200)
37688
+ },
37689
+ local_tools: opts.localTools
37690
+ };
37691
+ for (let turn = 0; turn < MAX_TURNS2; turn++) {
37692
+ if (remaining() < MIN_VERIFY_TURN_MS) return end("deadline");
37693
+ if (costUsd + VERIFY_TURN_HOLD_USD > opts.costLeftUsd) return end("cost-cap");
37694
+ const res = await opts.post({ ...body2, remaining_ms: remaining() }, Math.max(1, remaining()));
37695
+ if (!res.ok) return end("failed", { error: res.error.slice(0, 200) });
37696
+ const d = res.data;
37697
+ if (d.enabled === false) return end("disabled", { error: text(d.reason, 60) });
37698
+ if (d.error && typeof d.error === "object") return end("failed", { error: text(d.error.code, 60) || "SERVICE_ERROR" });
37699
+ rounds = typeof d.round === "number" && Number.isInteger(d.round) && d.round >= 0 ? d.round : rounds + 1;
37700
+ if (typeof d.cost_usd === "number") {
37701
+ if (!Number.isFinite(d.cost_usd) || d.cost_usd < 0) return end("failed", { error: "invalid cost" });
37702
+ costUsd += d.cost_usd;
37703
+ } else unpriced++;
37704
+ if (d.done) {
37705
+ const a = d.answer;
37706
+ if (!a) return end("failed", { error: text(d.error, 60) || "no verdict" });
37707
+ const verdict = verdictOf(a.verdict);
37708
+ if (!verdict) return end("failed", { error: "unknown verdict" });
37709
+ return end("answered", {
37710
+ verdict,
37711
+ claimed: verdictOf(a.claimed),
37712
+ introduced: introducedOf(a.introduced),
37713
+ trigger: text(a.trigger, 400),
37714
+ preventedBy: typeof a.prevented_by === "string" ? a.prevented_by.slice(0, 600) : null,
37715
+ effect: text(a.effect, 600),
37716
+ reason: text(a.reason, 2e3),
37717
+ quotes: (Array.isArray(a.quotes) ? a.quotes : []).slice(0, 12).flatMap((q) => {
37718
+ const o = q ?? {};
37719
+ return typeof o.path === "string" && typeof o.text === "string" ? [{ path: o.path.slice(0, 400), text: o.text.slice(0, 600), witnessed: o.witnessed === true }] : [];
37720
+ })
37721
+ });
37722
+ }
37723
+ if (typeof d.state !== "string" || !Array.isArray(d.calls)) return end("failed", { error: "malformed turn" });
37724
+ const calls = wellFormedCalls(d.calls, opts.localTools);
37725
+ if (!calls) return end("failed", { error: "malformed tool calls" });
37726
+ const results = await opts.executeTools(calls);
37727
+ body2 = { state: d.state, results };
37728
+ }
37729
+ return end("failed", { error: "too many turns" });
37730
+ }
37731
+
37504
37732
  // src/lib/prove/record.ts
37505
37733
  var RECORD_TIMEOUT_MS = 8e3;
37506
37734
  var HOOK_EXIT_MARGIN_MS = 5e3;
@@ -37516,9 +37744,9 @@ function recordPostTimeout(now, deadlineAt, timeoutMs = RECORD_TIMEOUT_MS) {
37516
37744
  var norm2 = (p) => p.replace(/\\/g, "/");
37517
37745
  var SAFE_SEGMENT = /^[A-Za-z0-9._@+~$()[\]-]{1,255}$/;
37518
37746
  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;
37747
+ const n2 = norm2(p);
37748
+ if (!n2 || n2.length > 512 || n2.startsWith("/") || /^[A-Za-z]:\//.test(n2)) return null;
37749
+ return n2.split("/").every((s) => s !== "." && s !== ".." && SAFE_SEGMENT.test(s)) ? n2 : null;
37522
37750
  }
37523
37751
  var SYMBOL = /^[A-Za-z_$][\w$]*(?:[.#:][A-Za-z_$][\w$]*)*$/;
37524
37752
  var IDENT3 = /^[A-Za-z][\w]*$/;
@@ -37538,10 +37766,10 @@ function recordTrace(trace) {
37538
37766
  }
37539
37767
  var ident2 = (s, re, max) => typeof s === "string" && s.length <= max && re.test(s) ? s : null;
37540
37768
  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;
37769
+ 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(([, n2]) => typeof n2 === "number" && n2 > 0).slice(0, 16)) } : null;
37542
37770
  function buildPhaseRecord(outcome, ctx) {
37543
37771
  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));
37772
+ const blocks = (f) => ctx.moment === "push" && formalDisposition(f) === "block" && pushed.has(norm2(f.file));
37545
37773
  const symbol = (s) => ident2(s, SYMBOL, 200);
37546
37774
  return {
37547
37775
  moment: ctx.moment,
@@ -37581,7 +37809,9 @@ function buildPhaseRecord(outcome, ctx) {
37581
37809
  symbol: f.symbol,
37582
37810
  verdict: f.verdict,
37583
37811
  waived: f.waived === true,
37584
- blocked: blocks(f)
37812
+ blocked: blocks(f),
37813
+ // The check's closed codes only (decision 91): never its reason, trigger or quotes.
37814
+ check: f.check ? { outcome: f.check.outcome, verdict: f.check.verdict, introduced: f.check.introduced, rounds: f.check.rounds } : null
37585
37815
  })),
37586
37816
  grounding: outcome.grounding ? {
37587
37817
  sent_back: outcome.grounding.sentBack,
@@ -37763,17 +37993,17 @@ function parsePrIntent(command) {
37763
37993
  }
37764
37994
  var TRIVIAL_INTENT = /^(wip|tmp|temp|test|fix|chore|amend|\.+|fixup!.*|squash!.*|merge\b.*)$/i;
37765
37995
  var SHELL_PLUMBING = /\$\(|`|<<-?\s*['"]?[A-Za-z_]/;
37766
- function isSubstantiveIntent(text) {
37767
- if (!text) return false;
37768
- const t = text.trim();
37996
+ function isSubstantiveIntent(text2) {
37997
+ if (!text2) return false;
37998
+ const t = text2.trim();
37769
37999
  if (t.length < 12) return false;
37770
38000
  if (TRIVIAL_INTENT.test(t)) return false;
37771
38001
  if (SHELL_PLUMBING.test(t)) return false;
37772
38002
  return true;
37773
38003
  }
37774
38004
  function extractStatedIntent(moment, command, pushedMessages = null) {
37775
- const text = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
37776
- return isSubstantiveIntent(text) ? text : null;
38005
+ const text2 = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
38006
+ return isSubstantiveIntent(text2) ? text2 : null;
37777
38007
  }
37778
38008
  function hasBlockingFinding(response, sentFiles) {
37779
38009
  const findings = response.findings ?? [];
@@ -37938,7 +38168,7 @@ function startAgentReview(input) {
37938
38168
  diffs: await buildAgentDiffs(ctx, sentPaths),
37939
38169
  repo_context: input.requestBody.repo_context,
37940
38170
  static_results: input.requestBody.static_results,
37941
- one_shot_chars: input.codeDelta.files.reduce((n, f) => n + f.content.length, 0),
38171
+ one_shot_chars: input.codeDelta.files.reduce((n2, f) => n2 + f.content.length, 0),
37942
38172
  local_tools: offeredLocalTools(ctx)
37943
38173
  },
37944
38174
  oneShot: input.oneShot.then((r) => r.ok ? { ok: true, response: r.data } : { ok: false }),
@@ -37960,7 +38190,7 @@ function startFormalPhase(input) {
37960
38190
  for (const [path, sig] of rangeChangeSignals(input.frame, input.range, files)) {
37961
38191
  changedLines.set(path, [
37962
38192
  ...sig.addedRanges.map(([from, to]) => ({ from, to })),
37963
- ...sig.touchPoints.map((n) => ({ from: n, to: n }))
38193
+ ...sig.touchPoints.map((n2) => ({ from: n2, to: n2 }))
37964
38194
  ]);
37965
38195
  }
37966
38196
  } catch {
@@ -37976,6 +38206,14 @@ function startFormalPhase(input) {
37976
38206
  const run4 = async () => {
37977
38207
  const prep = await prepareFormalPhase(input.root, process.env, input.auth, readSource, withoutPaths(tip ? revisionSource(input.root, tip) : worktreeSource(input.root), isDeniedPath));
37978
38208
  if (!prep.ok) return skippedOutcome(prep.skip, prep.detail);
38209
+ if (process.env.VERITY_FORMAL_VERIFY !== "off") {
38210
+ const ctx = { root: input.root, range: input.range, codeMap: prep.deps.codeMap ?? null };
38211
+ const post = verifyPost(input.auth);
38212
+ prep.deps.verify = (f, v) => verifyFinding(
38213
+ { file: f.file, symbol: f.symbol, ...v.lines ? { lines: v.lines } : {}, property: { desc: f.desc, kind: f.kind, trace: f.trace }, replayReason: f.reason ?? "", changedLines: v.changedLines },
38214
+ { executeTools: makeToolExecutor(ctx), localTools: offeredLocalTools(ctx), deadlineAt: v.deadlineAt, costLeftUsd: v.costLeftUsd, post }
38215
+ );
38216
+ }
37979
38217
  return runFormalPhaseWithin({ root: input.root, files, changedLines, deadlineAt, deps: prep.deps });
37980
38218
  };
37981
38219
  return run4().catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200)));
@@ -38508,12 +38746,12 @@ function printBanner(opts) {
38508
38746
  const color = colorEnabled();
38509
38747
  const version = `v${cliVersion()}`;
38510
38748
  const art = [WORDMARK, WORDMARK_NARROW].find((a) => artWidth(a) <= columns) ?? null;
38511
- const dim = (text) => color ? `${DIM3}${text}${RESET2}` : text;
38749
+ const dim = (text2) => color ? `${DIM3}${text2}${RESET2}` : text2;
38512
38750
  process.stderr.write("\n");
38513
38751
  if (!art) {
38514
38752
  const candidates2 = [`Verity ${version}`, "Verity"];
38515
- const text = candidates2.find((c) => c.length + INDENT.length <= columns);
38516
- if (text) process.stderr.write(`${INDENT}${dim(text)}
38753
+ const text2 = candidates2.find((c) => c.length + INDENT.length <= columns);
38754
+ if (text2) process.stderr.write(`${INDENT}${dim(text2)}
38517
38755
  `);
38518
38756
  process.stderr.write("\n");
38519
38757
  return;
@@ -38534,11 +38772,11 @@ function printBanner(opts) {
38534
38772
  }
38535
38773
  process.stderr.write("\n");
38536
38774
  }
38537
- function printPhase(n, of, title, subtitle) {
38775
+ function printPhase(n2, of, title, subtitle) {
38538
38776
  const color = colorEnabled();
38539
38777
  const columns = process.stderr.columns ?? 72;
38540
38778
  const width = Math.min(columns, 72);
38541
- const label2 = `\u2500\u2500 Phase ${n} of ${of} \xB7 ${title} `;
38779
+ const label2 = `\u2500\u2500 Phase ${n2} of ${of} \xB7 ${title} `;
38542
38780
  const rule = label2 + "\u2500".repeat(Math.max(0, width - label2.length - 2));
38543
38781
  process.stderr.write("\n");
38544
38782
  process.stderr.write(color ? ` ${DIM3}${rule}${RESET2}
@@ -38915,7 +39153,7 @@ function registerDoctorCommand(program2) {
38915
39153
  if (report.next.length > 0) {
38916
39154
  console.log("");
38917
39155
  printWarn("Next:");
38918
- for (const n of report.next) printWarn(` - ${n}`);
39156
+ for (const n2 of report.next) printWarn(` - ${n2}`);
38919
39157
  } else {
38920
39158
  printInfo("Setup is complete.");
38921
39159
  }
@@ -39297,7 +39535,7 @@ var DIM4 = "\x1B[2m";
39297
39535
  var BOLD2 = "\x1B[1m";
39298
39536
  var RESET3 = "\x1B[0m";
39299
39537
  function renderSelect(question, choices, state, mode2, color = colorEnabled()) {
39300
- const paint = (text, code) => color ? `${code}${text}${RESET3}` : text;
39538
+ const paint = (text2, code) => color ? `${code}${text2}${RESET3}` : text2;
39301
39539
  const lines = ["", ` ${question}`];
39302
39540
  const labelOf = (c) => `${c.label}${c.recommended ? " (recommended)" : ""}`;
39303
39541
  const gutter = Math.max(...choices.map((c) => labelOf(c).length));
@@ -39306,8 +39544,8 @@ function renderSelect(question, choices, state, mode2, color = colorEnabled()) {
39306
39544
  const marker = state.chosen.has(i2) ? "\u25C9" : "\u25CB";
39307
39545
  const cursor = here ? "\u276F" : " ";
39308
39546
  const label2 = labelOf(choice);
39309
- const pad = choice.hint ? " ".repeat(gutter - label2.length) : "";
39310
- const hint = choice.hint ? `${pad} ${paint(choice.hint, DIM4)}` : "";
39547
+ const pad2 = choice.hint ? " ".repeat(gutter - label2.length) : "";
39548
+ const hint = choice.hint ? `${pad2} ${paint(choice.hint, DIM4)}` : "";
39311
39549
  lines.push(` ${cursor} ${marker} ${here ? paint(label2, BOLD2) : label2}${hint}`);
39312
39550
  });
39313
39551
  const keys = mode2 === "multi" ? "\u2191\u2193 move \xB7 space or number toggle \xB7 enter confirm" : "\u2191\u2193 move \xB7 number jumps \xB7 enter confirm";
@@ -39418,9 +39656,9 @@ function parseMultiSelect(answer, choices, fallback) {
39418
39656
  if (a === "") return { ids: [...fallback], recognized: true };
39419
39657
  const picked = /* @__PURE__ */ new Set();
39420
39658
  for (const part of a.split(",").map((s) => s.trim()).filter(Boolean)) {
39421
- const n = Number.parseInt(part, 10);
39422
- if (Number.isInteger(n) && n >= 1 && n <= choices.length) {
39423
- picked.add(choices[n - 1].id);
39659
+ const n2 = Number.parseInt(part, 10);
39660
+ if (Number.isInteger(n2) && n2 >= 1 && n2 <= choices.length) {
39661
+ picked.add(choices[n2 - 1].id);
39424
39662
  continue;
39425
39663
  }
39426
39664
  const byId = choices.find((c) => c.id.toLowerCase() === part || c.label.toLowerCase() === part);
@@ -39590,7 +39828,7 @@ function inPlaceProgress(label2, write = (s) => process.stderr.write(s)) {
39590
39828
  let active = false;
39591
39829
  let lastAt = 0;
39592
39830
  let lastPct = -1;
39593
- const mb = (n) => (n / 1048576).toFixed(0);
39831
+ const mb = (n2) => (n2 / 1048576).toFixed(0);
39594
39832
  return {
39595
39833
  update(seen, total) {
39596
39834
  const now = Date.now();
@@ -39625,7 +39863,7 @@ async function installLean(opts = {}) {
39625
39863
  const free = freeBytes(home);
39626
39864
  const needed = opts.minFreeBytes ?? LEAN_DISK_NEEDED_BYTES;
39627
39865
  if (free !== null && free < needed) {
39628
- const gb = (n) => (n / 1024 ** 3).toFixed(1);
39866
+ const gb = (n2) => (n2 / 1024 ** 3).toFixed(1);
39629
39867
  return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
39630
39868
  }
39631
39869
  const tmp = (0, import_node_path52.join)(home, ".tmp");
@@ -40636,7 +40874,7 @@ function registerInitCommand(program2) {
40636
40874
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
40637
40875
  init: {
40638
40876
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
40639
- cli_version: true ? "0.34.2" : "dev"
40877
+ cli_version: true ? "0.34.4" : "dev"
40640
40878
  }
40641
40879
  });
40642
40880
  } catch (err2) {
@@ -41077,11 +41315,11 @@ function resolve7(token, treePaths) {
41077
41315
  const matches = treePaths.filter((p) => p.endsWith(suffix));
41078
41316
  return matches.length === 1 ? matches[0] : null;
41079
41317
  }
41080
- function deriveFileGlobs(text, treePaths) {
41081
- if (!text || treePaths.length === 0) return [];
41318
+ function deriveFileGlobs(text2, treePaths) {
41319
+ if (!text2 || treePaths.length === 0) return [];
41082
41320
  const out2 = [];
41083
41321
  const seen = /* @__PURE__ */ new Set();
41084
- for (const raw of text.match(PATH_TOKEN) ?? []) {
41322
+ for (const raw of text2.match(PATH_TOKEN) ?? []) {
41085
41323
  const token = clean(raw);
41086
41324
  if (!token) continue;
41087
41325
  const path = resolve7(token, treePaths);
@@ -41616,6 +41854,148 @@ function registerTelemetryCommands(program2) {
41616
41854
  });
41617
41855
  }
41618
41856
 
41857
+ // src/commands/usage.ts
41858
+ var PLAN = { free: "Free", pro: "Pro", fleet: "Fleet" };
41859
+ var MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
41860
+ function n(v) {
41861
+ return v.toLocaleString("en-US");
41862
+ }
41863
+ function used(v, limit) {
41864
+ return limit === void 0 ? n(v) : `${n(v)} / ${n(limit)}`;
41865
+ }
41866
+ function secs(ms) {
41867
+ return ms === null ? "\u2014" : `${(ms / 1e3).toFixed(1)} s`;
41868
+ }
41869
+ function utcHm(iso) {
41870
+ const d = new Date(iso);
41871
+ return `${String(d.getUTCHours()).padStart(2, "0")}:${String(d.getUTCMinutes()).padStart(2, "0")} UTC`;
41872
+ }
41873
+ function utcDay(iso) {
41874
+ const d = new Date(iso);
41875
+ return `${d.getUTCDate()} ${MONTHS[d.getUTCMonth()]}`;
41876
+ }
41877
+ function inText(now, at) {
41878
+ const min = Math.max(0, Math.round((at.getTime() - now.getTime()) / 6e4));
41879
+ if (min < 60) return `${min} min`;
41880
+ const h = Math.floor(min / 60);
41881
+ return h < 48 ? `${h} h ${min % 60} min` : `${Math.floor(h / 24)} d ${h % 24} h`;
41882
+ }
41883
+ function pad(s, w) {
41884
+ return s.length >= w ? s : s + " ".repeat(w - s.length);
41885
+ }
41886
+ function renderSeatUsage(d, now = /* @__PURE__ */ new Date()) {
41887
+ const lim = d.plan?.limits;
41888
+ const pool = d.plan?.week_pool ?? null;
41889
+ const memberWeek = (m) => pool ? void 0 : lim?.[m].week;
41890
+ const lines = [];
41891
+ lines.push(`=== Verity usage \xB7 ${d.organization.name}${d.plan ? ` (${PLAN[d.plan.id] ?? d.plan.id})` : ""} ===`);
41892
+ lines.push(
41893
+ `Session ${utcHm(d.session.start)}\u2013${utcHm(d.session.resets_at)} (resets in ${inText(now, new Date(d.session.resets_at))}) \xB7 week from Mon ${utcDay(d.week.start)} (resets Mon ${utcDay(d.week.resets_at)}, 00:00 UTC)`
41894
+ );
41895
+ if (!d.plan) lines.push("No plan is set for this org: counts only. Plan limits apply from Nov 2.");
41896
+ else if (!d.enforced) lines.push("Limits are shown for information. They are not enforced before Nov 2.");
41897
+ const me = d.members.find((m) => m.me);
41898
+ if (me) {
41899
+ const w = me.weeks[0];
41900
+ lines.push("");
41901
+ lines.push(`You (${me.email ?? `user #${me.user_id}`})`);
41902
+ lines.push(` ${pad("Commit & push reviews", 24)}session ${pad(used(me.session.commit, lim?.commit.session), 12)}week ${pad(used(w.commit, memberWeek("commit")), 14)}busiest session ${n(w.peak_session.commit)}`);
41903
+ lines.push(` ${pad("Turn reviews", 24)}session ${pad(used(me.session.turn, lim?.turn.session), 12)}week ${pad(used(w.turn, memberWeek("turn")), 14)}busiest session ${n(w.peak_session.turn)}`);
41904
+ lines.push(` This week: ${n(w.blocked)} blocked, ${n(w.warned)} warned \xB7 review time p50 ${secs(w.latency_ms.p50)}, p90 ${secs(w.latency_ms.p90)}`);
41905
+ }
41906
+ const t = d.totals.weeks[0];
41907
+ lines.push("");
41908
+ lines.push(`Team \xB7 ${n(d.totals.active_members)} active this week`);
41909
+ if (pool && lim) {
41910
+ lines.push(
41911
+ ` Week pool: ${n(t.commit)} / ${n(pool.commit)} commit & push, ${n(t.turn)} / ${n(pool.turn)} turn (${n(pool.members)} members \xD7 ${n(lim.commit.week)} and ${n(lim.turn.week)}; the session limit is each member's)`
41912
+ );
41913
+ }
41914
+ if (d.viewer !== "member" && d.members.length > 0) {
41915
+ const rows = d.members.map((m) => [
41916
+ `${m.email ?? `user #${m.user_id}`}${m.me ? " (you)" : ""}`,
41917
+ used(m.session.commit, lim?.commit.session),
41918
+ used(m.weeks[0].commit, memberWeek("commit")),
41919
+ n(m.weeks[0].peak_session.commit),
41920
+ used(m.session.turn, lim?.turn.session),
41921
+ used(m.weeks[0].turn, memberWeek("turn")),
41922
+ n(m.weeks[0].blocked),
41923
+ `${secs(m.weeks[0].latency_ms.p50)} / ${secs(m.weeks[0].latency_ms.p90)}`
41924
+ ]);
41925
+ const head = ["Member", "C&P session", "C&P week", "C&P peak", "Turn session", "Turn week", "Blocked", "p50 / p90"];
41926
+ const total = [
41927
+ "Team total",
41928
+ n(d.totals.session.commit),
41929
+ used(t.commit, pool?.commit),
41930
+ n(t.peak_session.commit),
41931
+ n(d.totals.session.turn),
41932
+ used(t.turn, pool?.turn),
41933
+ n(t.blocked),
41934
+ `${secs(t.latency_ms.p50)} / ${secs(t.latency_ms.p90)}`
41935
+ ];
41936
+ const widths = head.map((h, i2) => Math.max(h.length, ...rows.map((r) => r[i2].length), total[i2].length) + 2);
41937
+ lines.push(" " + head.map((h, i2) => pad(h, widths[i2])).join("").trimEnd());
41938
+ for (const r of rows) lines.push(" " + r.map((c, i2) => pad(c, widths[i2])).join("").trimEnd());
41939
+ lines.push(" " + total.map((c, i2) => pad(c, widths[i2])).join("").trimEnd());
41940
+ } else {
41941
+ lines.push(` This week: ${n(t.commit)} commit & push reviews, ${n(t.turn)} turn reviews, ${n(t.blocked)} blocked.`);
41942
+ if (d.viewer === "member") lines.push(` Only the admins of ${d.organization.name} see every member.`);
41943
+ }
41944
+ if (d.truncated) lines.push(" (Partial: the org has more reviews than one report reads.)");
41945
+ lines.push("");
41946
+ lines.push(`Counted: ${d.counting}`);
41947
+ return lines;
41948
+ }
41949
+ async function auth2(globals) {
41950
+ const tokenResult = await resolveToken(globals.token);
41951
+ if (!tokenResult.ok) {
41952
+ printError(tokenResult.error);
41953
+ process.exit(1);
41954
+ }
41955
+ const urlResult = await resolveServiceUrl(globals.serviceUrl);
41956
+ if (!urlResult.ok) {
41957
+ printError(urlResult.error);
41958
+ process.exit(1);
41959
+ }
41960
+ return { token: tokenResult.data.token, serviceUrl: urlResult.data };
41961
+ }
41962
+ function registerUsageCommand(program2) {
41963
+ program2.command("usage").description("Show reviews per member of this org, this session and this week, against the plan limits").option("--org <name>", "The org to show (default: the org of this repository)").option("--weeks <n>", "Weeks of history in --json (1-12)", "4").option("--json", "Machine-readable output").action(async (opts) => {
41964
+ const globals = program2.opts();
41965
+ const { token, serviceUrl } = await auth2(globals);
41966
+ const weeks = Math.min(12, Math.max(1, Number.parseInt(opts.weeks ?? "4", 10) || 4));
41967
+ const query = `weeks=${weeks}${opts.org ? `&org=${encodeURIComponent(opts.org)}` : ""}`;
41968
+ const res = await apiRequest({
41969
+ method: "GET",
41970
+ path: `/usage/seats?${query}`,
41971
+ serviceUrl,
41972
+ token,
41973
+ verbose: globals.verbose,
41974
+ cmd: "usage"
41975
+ });
41976
+ if (!res.ok) {
41977
+ const denial = authDenialRemedy(res.error);
41978
+ printError(denial && denial.code !== "FORBIDDEN" ? denial.remedy : res.error);
41979
+ process.exit(1);
41980
+ }
41981
+ if (opts.json) {
41982
+ printJson(res.data);
41983
+ return;
41984
+ }
41985
+ if ("orgs" in res.data) {
41986
+ const orgs = res.data.orgs;
41987
+ if (orgs.length === 0) {
41988
+ printInfo("You have no repository in an org that Verity knows yet. Run a review in one first.");
41989
+ return;
41990
+ }
41991
+ printInfo("Choose an org: verity usage --org <name>");
41992
+ for (const o of orgs) printInfo(` ${o.name}${o.viewer === "admin" ? " (admin)" : ""}`);
41993
+ return;
41994
+ }
41995
+ for (const line2 of renderSeatUsage(res.data)) printInfo(line2);
41996
+ });
41997
+ }
41998
+
41619
41999
  // src/commands/prove.ts
41620
42000
  var import_node_fs73 = require("node:fs");
41621
42001
  var import_node_path57 = require("node:path");
@@ -41871,8 +42251,8 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41871
42251
  });
41872
42252
  prove.command("replay <model>").description("Replay a model's counterexample on the real code in an OpenAI container (network off) \u2014 reproduced / diverged").option("--property <id>", "Only this property (default: every counterexample)").option("--model-name <name>", "OpenAI model for the replay", "gpt-5.6-terra").option("--timeout <ms>", "Per-property timeout in ms", "240000").option("--json", "Machine-readable output").action(async (model, opts) => {
41873
42253
  const root = repoRoot();
41874
- const auth2 = await proveAuth(program2);
41875
- if (!auth2 && !(process.env.VERITY_PROVE_DIRECT === "1" && process.env.OPENAI_API_KEY)) {
42254
+ const auth3 = await proveAuth(program2);
42255
+ if (!auth3 && !(process.env.VERITY_PROVE_DIRECT === "1" && process.env.OPENAI_API_KEY)) {
41876
42256
  printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
41877
42257
  process.exit(2);
41878
42258
  }
@@ -41911,7 +42291,7 @@ ${report.error ?? ""}`);
41911
42291
  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`);
41912
42292
  const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
41913
42293
  const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
41914
- const outcome = await runReplay(brief, { auth: auth2 ?? void 0, apiKey: process.env.OPENAI_API_KEY, model: opts.modelName, timeoutMs: Math.max(1e4, Number(opts.timeout) || 24e4) });
42294
+ const outcome = await runReplay(brief, { auth: auth3 ?? void 0, apiKey: process.env.OPENAI_API_KEY, model: opts.modelName, timeoutMs: Math.max(1e4, Number(opts.timeout) || 24e4) });
41915
42295
  if (!opts.json) process.stdout.write(renderReplay(model, p, outcome) + "\n");
41916
42296
  try {
41917
42297
  writeReplayResult(root, report.model, p.id, outcome);
@@ -41937,10 +42317,10 @@ ${report.error ?? ""}`);
41937
42317
  printInfo("No changed files to consider (nothing ahead of upstream). Pass paths explicitly.");
41938
42318
  return;
41939
42319
  }
41940
- const auth2 = await proveAuth(program2);
41941
- const prep = await prepareFormalPhase(root, process.env, auth2 ?? void 0);
42320
+ const auth3 = await proveAuth(program2);
42321
+ const prep = await prepareFormalPhase(root, process.env, auth3 ?? void 0);
41942
42322
  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);
42323
+ if (auth3) await postPhaseRecord(outcome, { moment: "on-demand", parentRunId: null, pushedFiles: [] }, auth3);
41944
42324
  if (opts.json) {
41945
42325
  printJson(outcome);
41946
42326
  } else {
@@ -41972,8 +42352,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41972
42352
  opts[flag] = input.text;
41973
42353
  }
41974
42354
  const root = repoRoot();
41975
- const auth2 = await proveAuth(program2);
41976
- if (!auth2 && !(process.env.VERITY_PROVE_DIRECT === "1" && process.env.OPENAI_API_KEY)) {
42355
+ const auth3 = await proveAuth(program2);
42356
+ if (!auth3 && !(process.env.VERITY_PROVE_DIRECT === "1" && process.env.OPENAI_API_KEY)) {
41977
42357
  printError("Not logged in \u2014 models are written by the Verity service. Run `verity login` first.");
41978
42358
  process.exit(2);
41979
42359
  }
@@ -42014,7 +42394,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
42014
42394
  printError("Verity library did not build");
42015
42395
  process.exit(2);
42016
42396
  }
42017
- const deps = await onDemandDeps(root, { auth: auth2 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc });
42397
+ const deps = await onDemandDeps(root, { auth: auth3 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc });
42018
42398
  if (!opts.json) printInfo(`asking the Verity service for a model of ${symbol || `${file}:${opts.lines}`} \u2026`);
42019
42399
  const out2 = await generateAndCheck(root, { file, symbol: symbol || `${file}:${opts.lines}`, lines, hint: opts.hint, revise }, { deps, maxRounds: 3 });
42020
42400
  if (!out2.ok) {
@@ -42052,9 +42432,9 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
42052
42432
  printWarn(`No remembered formal finding on ${rel}. A finding is remembered only after a REPRODUCED replay at push.`);
42053
42433
  process.exit(1);
42054
42434
  }
42055
- const n = waiveFormalFindings(root, rel, opts.reason);
42056
- logEvent("formal_waive", { file: rel, waived: n });
42057
- printInfo(`Waived ${n} formal finding(s) on ${rel} for its current bytes; the waive voids when the file changes. Reason recorded: ${terminalText(opts.reason, 200)}`);
42435
+ const n2 = waiveFormalFindings(root, rel, opts.reason);
42436
+ logEvent("formal_waive", { file: rel, waived: n2 });
42437
+ printInfo(`Waived ${n2} formal finding(s) on ${rel} for its current bytes; the waive voids when the file changes. Reason recorded: ${terminalText(opts.reason, 200)}`);
42058
42438
  });
42059
42439
  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) => {
42060
42440
  const root = repoRoot();
@@ -42177,8 +42557,8 @@ function registerLeanCommand(program2) {
42177
42557
  }
42178
42558
 
42179
42559
  // src/cli.ts
42180
- program.name("verity").description("CLI for Verity quality gate service").version("0.34.2").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.2");
42560
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.4").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) => {
42561
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.4");
42182
42562
  setUserNamedServiceUrl(program.opts().serviceUrl);
42183
42563
  try {
42184
42564
  await foldLegacyLocalCredential();
@@ -42213,6 +42593,7 @@ registerMemoryCommand(program);
42213
42593
  registerRunCommand(program);
42214
42594
  registerMigrateCommand(program);
42215
42595
  registerTelemetryCommands(program);
42596
+ registerUsageCommand(program);
42216
42597
  registerProveCommand(program);
42217
42598
  registerLeanCommand(program);
42218
42599
  program.parseAsync().catch((err2) => {