@codacy/verity-cli 0.34.1 → 0.34.2-experimental.2cad220

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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}
@@ -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;
@@ -6975,10 +6975,10 @@ var require_resolve_block_map = __commonJS2({
6975
6975
  let offset = bm.offset;
6976
6976
  let commentEnd = null;
6977
6977
  for (const collItem of bm.items) {
6978
- const { start: start2, key, sep: sep6, value } = collItem;
6978
+ const { start: start2, key, sep: sep7, value } = collItem;
6979
6979
  const keyProps = resolveProps.resolveProps(start2, {
6980
6980
  indicator: "explicit-key-ind",
6981
- next: key ?? sep6?.[0],
6981
+ next: key ?? sep7?.[0],
6982
6982
  offset,
6983
6983
  onError,
6984
6984
  parentIndent: bm.indent,
@@ -6992,7 +6992,7 @@ var require_resolve_block_map = __commonJS2({
6992
6992
  else if ("indent" in key && key.indent !== bm.indent)
6993
6993
  onError(offset, "BAD_INDENT", startColMsg);
6994
6994
  }
6995
- if (!keyProps.anchor && !keyProps.tag && !sep6) {
6995
+ if (!keyProps.anchor && !keyProps.tag && !sep7) {
6996
6996
  commentEnd = keyProps.end;
6997
6997
  if (keyProps.comment) {
6998
6998
  if (map.comment)
@@ -7016,7 +7016,7 @@ var require_resolve_block_map = __commonJS2({
7016
7016
  ctx.atKey = false;
7017
7017
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
7018
7018
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
7019
- const valueProps = resolveProps.resolveProps(sep6 ?? [], {
7019
+ const valueProps = resolveProps.resolveProps(sep7 ?? [], {
7020
7020
  indicator: "map-value-ind",
7021
7021
  next: value,
7022
7022
  offset: keyNode.range[2],
@@ -7032,7 +7032,7 @@ var require_resolve_block_map = __commonJS2({
7032
7032
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
7033
7033
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
7034
7034
  }
7035
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep6, null, valueProps, onError);
7035
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep7, null, valueProps, onError);
7036
7036
  if (ctx.schema.compat)
7037
7037
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
7038
7038
  offset = valueNode.range[2];
@@ -7123,7 +7123,7 @@ var require_resolve_end = __commonJS2({
7123
7123
  let comment = "";
7124
7124
  if (end) {
7125
7125
  let hasSpace = false;
7126
- let sep6 = "";
7126
+ let sep7 = "";
7127
7127
  for (const token of end) {
7128
7128
  const { source: source2, type } = token;
7129
7129
  switch (type) {
@@ -7137,13 +7137,13 @@ var require_resolve_end = __commonJS2({
7137
7137
  if (!comment)
7138
7138
  comment = cb;
7139
7139
  else
7140
- comment += sep6 + cb;
7141
- sep6 = "";
7140
+ comment += sep7 + cb;
7141
+ sep7 = "";
7142
7142
  break;
7143
7143
  }
7144
7144
  case "newline":
7145
7145
  if (comment)
7146
- sep6 += source2;
7146
+ sep7 += source2;
7147
7147
  hasSpace = true;
7148
7148
  break;
7149
7149
  default:
@@ -7186,18 +7186,18 @@ var require_resolve_flow_collection = __commonJS2({
7186
7186
  let offset = fc.offset + fc.start.source.length;
7187
7187
  for (let i2 = 0; i2 < fc.items.length; ++i2) {
7188
7188
  const collItem = fc.items[i2];
7189
- const { start: start2, key, sep: sep6, value } = collItem;
7189
+ const { start: start2, key, sep: sep7, value } = collItem;
7190
7190
  const props = resolveProps.resolveProps(start2, {
7191
7191
  flow: fcName,
7192
7192
  indicator: "explicit-key-ind",
7193
- next: key ?? sep6?.[0],
7193
+ next: key ?? sep7?.[0],
7194
7194
  offset,
7195
7195
  onError,
7196
7196
  parentIndent: fc.indent,
7197
7197
  startOnNewline: false
7198
7198
  });
7199
7199
  if (!props.found) {
7200
- if (!props.anchor && !props.tag && !sep6 && !value) {
7200
+ if (!props.anchor && !props.tag && !sep7 && !value) {
7201
7201
  if (i2 === 0 && props.comma)
7202
7202
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
7203
7203
  else if (i2 < fc.items.length - 1)
@@ -7251,8 +7251,8 @@ var require_resolve_flow_collection = __commonJS2({
7251
7251
  }
7252
7252
  }
7253
7253
  }
7254
- if (!isMap && !sep6 && !props.found) {
7255
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep6, null, props, onError);
7254
+ if (!isMap && !sep7 && !props.found) {
7255
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep7, null, props, onError);
7256
7256
  coll.items.push(valueNode);
7257
7257
  offset = valueNode.range[2];
7258
7258
  if (isBlock(value))
@@ -7264,7 +7264,7 @@ var require_resolve_flow_collection = __commonJS2({
7264
7264
  if (isBlock(key))
7265
7265
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
7266
7266
  ctx.atKey = false;
7267
- const valueProps = resolveProps.resolveProps(sep6 ?? [], {
7267
+ const valueProps = resolveProps.resolveProps(sep7 ?? [], {
7268
7268
  flow: fcName,
7269
7269
  indicator: "map-value-ind",
7270
7270
  next: value,
@@ -7275,8 +7275,8 @@ var require_resolve_flow_collection = __commonJS2({
7275
7275
  });
7276
7276
  if (valueProps.found) {
7277
7277
  if (!isMap && !props.found && ctx.options.strict) {
7278
- if (sep6)
7279
- for (const st of sep6) {
7278
+ if (sep7)
7279
+ for (const st of sep7) {
7280
7280
  if (st === valueProps.found)
7281
7281
  break;
7282
7282
  if (st.type === "newline") {
@@ -7293,7 +7293,7 @@ var require_resolve_flow_collection = __commonJS2({
7293
7293
  else
7294
7294
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
7295
7295
  }
7296
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep6, null, valueProps, onError) : null;
7296
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep7, null, valueProps, onError) : null;
7297
7297
  if (valueNode) {
7298
7298
  if (isBlock(value))
7299
7299
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -7473,7 +7473,7 @@ var require_resolve_block_scalar = __commonJS2({
7473
7473
  chompStart = i2 + 1;
7474
7474
  }
7475
7475
  let value = "";
7476
- let sep6 = "";
7476
+ let sep7 = "";
7477
7477
  let prevMoreIndented = false;
7478
7478
  for (let i2 = 0; i2 < contentStart; ++i2)
7479
7479
  value += lines[i2][0].slice(trimIndent) + "\n";
@@ -7490,24 +7490,24 @@ var require_resolve_block_scalar = __commonJS2({
7490
7490
  indent = "";
7491
7491
  }
7492
7492
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
7493
- value += sep6 + indent.slice(trimIndent) + content;
7494
- sep6 = "\n";
7493
+ value += sep7 + indent.slice(trimIndent) + content;
7494
+ sep7 = "\n";
7495
7495
  } else if (indent.length > trimIndent || content[0] === " ") {
7496
- if (sep6 === " ")
7497
- sep6 = "\n";
7498
- else if (!prevMoreIndented && sep6 === "\n")
7499
- sep6 = "\n\n";
7500
- value += sep6 + indent.slice(trimIndent) + content;
7501
- sep6 = "\n";
7496
+ if (sep7 === " ")
7497
+ sep7 = "\n";
7498
+ else if (!prevMoreIndented && sep7 === "\n")
7499
+ sep7 = "\n\n";
7500
+ value += sep7 + indent.slice(trimIndent) + content;
7501
+ sep7 = "\n";
7502
7502
  prevMoreIndented = true;
7503
7503
  } else if (content === "") {
7504
- if (sep6 === "\n")
7504
+ if (sep7 === "\n")
7505
7505
  value += "\n";
7506
7506
  else
7507
- sep6 = "\n";
7507
+ sep7 = "\n";
7508
7508
  } else {
7509
- value += sep6 + content;
7510
- sep6 = " ";
7509
+ value += sep7 + content;
7510
+ sep7 = " ";
7511
7511
  prevMoreIndented = false;
7512
7512
  }
7513
7513
  }
@@ -7689,25 +7689,25 @@ var require_resolve_flow_scalar = __commonJS2({
7689
7689
  if (!match)
7690
7690
  return source2;
7691
7691
  let res = match[1];
7692
- let sep6 = " ";
7692
+ let sep7 = " ";
7693
7693
  let pos = first.lastIndex;
7694
7694
  line2.lastIndex = pos;
7695
7695
  while (match = line2.exec(source2)) {
7696
7696
  if (match[1] === "") {
7697
- if (sep6 === "\n")
7698
- res += sep6;
7697
+ if (sep7 === "\n")
7698
+ res += sep7;
7699
7699
  else
7700
- sep6 = "\n";
7700
+ sep7 = "\n";
7701
7701
  } else {
7702
- res += sep6 + match[1];
7703
- sep6 = " ";
7702
+ res += sep7 + match[1];
7703
+ sep7 = " ";
7704
7704
  }
7705
7705
  pos = line2.lastIndex;
7706
7706
  }
7707
7707
  const last = /[ \t]*(.*)/sy;
7708
7708
  last.lastIndex = pos;
7709
7709
  match = last.exec(source2);
7710
- return res + sep6 + (match?.[1] ?? "");
7710
+ return res + sep7 + (match?.[1] ?? "");
7711
7711
  }
7712
7712
  function doubleQuotedValue(source2, onError) {
7713
7713
  let res = "";
@@ -8514,14 +8514,14 @@ var require_cst_stringify = __commonJS2({
8514
8514
  }
8515
8515
  }
8516
8516
  }
8517
- function stringifyItem({ start: start2, key, sep: sep6, value }) {
8517
+ function stringifyItem({ start: start2, key, sep: sep7, value }) {
8518
8518
  let res = "";
8519
8519
  for (const st of start2)
8520
8520
  res += st.source;
8521
8521
  if (key)
8522
8522
  res += stringifyToken(key);
8523
- if (sep6)
8524
- for (const st of sep6)
8523
+ if (sep7)
8524
+ for (const st of sep7)
8525
8525
  res += st.source;
8526
8526
  if (value)
8527
8527
  res += stringifyToken(value);
@@ -9671,18 +9671,18 @@ var require_parser = __commonJS2({
9671
9671
  if (this.type === "map-value-ind") {
9672
9672
  const prev = getPrevProps(this.peek(2));
9673
9673
  const start2 = getFirstKeyStartProps(prev);
9674
- let sep6;
9674
+ let sep7;
9675
9675
  if (scalar.end) {
9676
- sep6 = scalar.end;
9677
- sep6.push(this.sourceToken);
9676
+ sep7 = scalar.end;
9677
+ sep7.push(this.sourceToken);
9678
9678
  delete scalar.end;
9679
9679
  } else
9680
- sep6 = [this.sourceToken];
9680
+ sep7 = [this.sourceToken];
9681
9681
  const map = {
9682
9682
  type: "block-map",
9683
9683
  offset: scalar.offset,
9684
9684
  indent: scalar.indent,
9685
- items: [{ start: start2, key: scalar, sep: sep6 }]
9685
+ items: [{ start: start2, key: scalar, sep: sep7 }]
9686
9686
  };
9687
9687
  this.onKeyLine = true;
9688
9688
  this.stack[this.stack.length - 1] = map;
@@ -9835,15 +9835,15 @@ var require_parser = __commonJS2({
9835
9835
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
9836
9836
  const start3 = getFirstKeyStartProps(it.start);
9837
9837
  const key = it.key;
9838
- const sep6 = it.sep;
9839
- sep6.push(this.sourceToken);
9838
+ const sep7 = it.sep;
9839
+ sep7.push(this.sourceToken);
9840
9840
  delete it.key;
9841
9841
  delete it.sep;
9842
9842
  this.stack.push({
9843
9843
  type: "block-map",
9844
9844
  offset: this.offset,
9845
9845
  indent: this.indent,
9846
- items: [{ start: start3, key, sep: sep6 }]
9846
+ items: [{ start: start3, key, sep: sep7 }]
9847
9847
  });
9848
9848
  } else if (start2.length > 0) {
9849
9849
  it.sep = it.sep.concat(start2, this.sourceToken);
@@ -10037,13 +10037,13 @@ var require_parser = __commonJS2({
10037
10037
  const prev = getPrevProps(parent);
10038
10038
  const start2 = getFirstKeyStartProps(prev);
10039
10039
  fixFlowSeqItems(fc);
10040
- const sep6 = fc.end.splice(1, fc.end.length);
10041
- sep6.push(this.sourceToken);
10040
+ const sep7 = fc.end.splice(1, fc.end.length);
10041
+ sep7.push(this.sourceToken);
10042
10042
  const map = {
10043
10043
  type: "block-map",
10044
10044
  offset: fc.offset,
10045
10045
  indent: fc.indent,
10046
- items: [{ start: start2, key: fc, sep: sep6 }]
10046
+ items: [{ start: start2, key: fc, sep: sep7 }]
10047
10047
  };
10048
10048
  this.onKeyLine = true;
10049
10049
  this.stack[this.stack.length - 1] = map;
@@ -13782,9 +13782,9 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13782
13782
  PatternStructure: 5
13783
13783
  };
13784
13784
  var QueryError = class _QueryError extends Error {
13785
- constructor(kind, info2, index, length) {
13786
- super(_QueryError.formatMessage(kind, info2));
13787
- this.kind = kind;
13785
+ constructor(kind2, info2, index, length) {
13786
+ super(_QueryError.formatMessage(kind2, info2));
13787
+ this.kind = kind2;
13788
13788
  this.info = info2;
13789
13789
  this.index = index;
13790
13790
  this.length = length;
@@ -13798,8 +13798,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13798
13798
  __name(this, "QueryError");
13799
13799
  }
13800
13800
  /** Formats an error message based on the error kind and info */
13801
- static formatMessage(kind, info2) {
13802
- switch (kind) {
13801
+ static formatMessage(kind2, info2) {
13802
+ switch (kind2) {
13803
13803
  case QueryErrorKind.NodeName:
13804
13804
  return `Bad node name '${info2.word}'`;
13805
13805
  case QueryErrorKind.FieldName:
@@ -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");
@@ -14726,7 +14726,7 @@ var SECURITY_PATTERNS = [
14726
14726
  /Dockerfile/
14727
14727
  ];
14728
14728
  var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
14729
- var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
14729
+ var DEFAULT_SERVICE_URL = "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1".length > 0 ? "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1" : PROD_SERVICE_URL;
14730
14730
  var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
14731
14731
  var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
14732
14732
  var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
@@ -15172,8 +15172,8 @@ function filterReviewable(files) {
15172
15172
  const ext = (0, import_node_path4.extname)(f).slice(1);
15173
15173
  if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
15174
15174
  if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
15175
- const basename9 = f.split("/").pop() ?? "";
15176
- if (REVIEWABLE_FILENAMES.has(basename9)) return true;
15175
+ const basename11 = f.split("/").pop() ?? "";
15176
+ if (REVIEWABLE_FILENAMES.has(basename11)) return true;
15177
15177
  if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
15178
15178
  return false;
15179
15179
  });
@@ -15712,11 +15712,11 @@ function startSpinner(label2, opts = {}) {
15712
15712
  },
15713
15713
  succeed(message) {
15714
15714
  finish(() => {
15715
- const 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
  });
@@ -16278,8 +16278,8 @@ async function reportLoginOutcome(out2, opts = {}) {
16278
16278
  printWarn(" repository will report that account. Remove its line from ~/.verity/credentials");
16279
16279
  printWarn(" only if you want this repository on the login you just completed.");
16280
16280
  } else {
16281
- const kind = rec.userId != null ? "superseded per-repository" : "anonymous project-specific";
16282
- printWarn(` Note: this repository has a ${kind} credential that takes`);
16281
+ const kind2 = rec.userId != null ? "superseded per-repository" : "anonymous project-specific";
16282
+ printWarn(` Note: this repository has a ${kind2} credential that takes`);
16283
16283
  printWarn(" precedence here. Remove its line from ~/.verity/credentials to use your login.");
16284
16284
  printWarn(' Until then, "verity login" in this repository re-runs the full GitHub flow');
16285
16285
  printWarn(" every time.");
@@ -16287,6 +16287,15 @@ async function reportLoginOutcome(out2, opts = {}) {
16287
16287
  }
16288
16288
  }
16289
16289
 
16290
+ // src/lib/session-env.ts
16291
+ function envSessionId(env = process.env) {
16292
+ for (const name2 of ["CLAUDE_SESSION_ID", "CLAUDE_CODE_SESSION_ID"]) {
16293
+ const value = env[name2];
16294
+ if (value) return value;
16295
+ }
16296
+ return void 0;
16297
+ }
16298
+
16290
16299
  // src/commands/login.ts
16291
16300
  function registerLoginCommand(program2) {
16292
16301
  program2.command("login").description("Log in to Verity (one GitHub login grants access to all your repositories)").option("--force", "Re-authenticate even if already logged in").option("--start", "Show the GitHub code and return at once (finish with --finish); prints JSON").option("--finish", "Wait for approval of the code --start showed, then log in; prints JSON").option("--wait <seconds>", "With --finish: how long to wait for approval before returning", "100").option("--cancel", "Discard a code --start showed that will not be approved").action(async (opts) => {
@@ -16303,7 +16312,7 @@ function registerLoginCommand(program2) {
16303
16312
  return;
16304
16313
  }
16305
16314
  const split = !!(opts.start || opts.finish);
16306
- if (!split && !process.stdin.isTTY && (process.env.CLAUDECODE || process.env.CLAUDE_SESSION_ID)) {
16315
+ if (!split && !process.stdin.isTTY && (process.env.CLAUDECODE || envSessionId())) {
16307
16316
  printWarn("Inside a Claude Code session the code below may not be visible until this command ends.");
16308
16317
  printWarn(' Use "verity login --start", then "verity login --finish" once it is approved.');
16309
16318
  }
@@ -16851,6 +16860,7 @@ var VERITY_SESSION_END_HOOK = {
16851
16860
  command: "verity session end"
16852
16861
  };
16853
16862
  var GUARD_TIMEOUT = 300;
16863
+ var GUARD_TIMEOUT_MS = GUARD_TIMEOUT * 1e3;
16854
16864
  function buildGuardHook(on) {
16855
16865
  return {
16856
16866
  type: "command",
@@ -17434,13 +17444,13 @@ function scrub(s) {
17434
17444
  var installed = false;
17435
17445
  var wroteBanner = false;
17436
17446
  var banner = "";
17437
- function append(text) {
17447
+ function append(text2) {
17438
17448
  try {
17439
17449
  const dir = projectPath(DEBUG_LOG_DIR);
17440
17450
  const file = projectPath(STDERR_LOG_FILE);
17441
17451
  (0, import_node_fs9.mkdirSync)(dir, { recursive: true });
17442
17452
  rotateIfNeeded(file);
17443
- (0, import_node_fs9.appendFileSync)(file, text);
17453
+ (0, import_node_fs9.appendFileSync)(file, text2);
17444
17454
  } catch {
17445
17455
  }
17446
17456
  }
@@ -17462,19 +17472,19 @@ function installStderrLog(cmd, argv, version) {
17462
17472
  const result = original(...args2);
17463
17473
  try {
17464
17474
  const chunk = args2[0];
17465
- 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);
17466
17476
  ensureBanner();
17467
- append(scrub(text));
17477
+ append(scrub(text2));
17468
17478
  } catch {
17469
17479
  }
17470
17480
  return result;
17471
17481
  };
17472
17482
  process.stderr.write = tee;
17473
17483
  }
17474
- function logToFileOnly(text) {
17484
+ function logToFileOnly(text2) {
17475
17485
  if (!installed) return;
17476
17486
  ensureBanner();
17477
- append(text.endsWith("\n") ? text : `${text}
17487
+ append(text2.endsWith("\n") ? text2 : `${text2}
17478
17488
  `);
17479
17489
  }
17480
17490
 
@@ -17606,9 +17616,9 @@ function pointsAtVerity(src) {
17606
17616
  }
17607
17617
  function describeSource(src) {
17608
17618
  if (!src || typeof src !== "object") return "an unrecognised source";
17609
- const kind = typeof src.source === "string" ? src.source : "unknown";
17619
+ const kind2 = typeof src.source === "string" ? src.source : "unknown";
17610
17620
  const target = typeof src.repo === "string" && src.repo || typeof src.url === "string" && src.url || typeof src.path === "string" && src.path || "";
17611
- return target ? `${kind} \u2192 ${target}` : kind;
17621
+ return target ? `${kind2} \u2192 ${target}` : kind2;
17612
17622
  }
17613
17623
  function legacyMarketplaceInstall() {
17614
17624
  const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
@@ -18045,8 +18055,8 @@ var import_promises5 = require("node:fs/promises");
18045
18055
  var import_node_fs12 = require("node:fs");
18046
18056
  var import_node_child_process6 = require("node:child_process");
18047
18057
  var import_node_crypto2 = require("node:crypto");
18048
- function stripImageReferences(text) {
18049
- 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]");
18050
18060
  }
18051
18061
  function bufferTmpPath() {
18052
18062
  return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto2.randomBytes)(4).toString("hex")}.tmp`;
@@ -18532,8 +18542,8 @@ function slugify(s) {
18532
18542
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
18533
18543
  }
18534
18544
  function orgNodePath(node) {
18535
- const kind = ORG_KINDS.includes(node.kind) ? node.kind : "domain";
18536
- return `${kind}/${slugify(node.title) || "claim"}-${node.tag_id.replace(/-/g, "").slice(0, 8)}.md`;
18545
+ const kind2 = ORG_KINDS.includes(node.kind) ? node.kind : "domain";
18546
+ return `${kind2}/${slugify(node.title) || "claim"}-${node.tag_id.replace(/-/g, "").slice(0, 8)}.md`;
18537
18547
  }
18538
18548
  function renderOrgNode(node, orgName) {
18539
18549
  const fm = [
@@ -18622,10 +18632,10 @@ function renderIndex(orgName, nodes) {
18622
18632
  ];
18623
18633
  const byKind = /* @__PURE__ */ new Map();
18624
18634
  for (const n of nodes) byKind.set(n.kind, [...byKind.get(n.kind) ?? [], n]);
18625
- for (const kind of ORG_KINDS) {
18626
- const list2 = byKind.get(kind);
18635
+ for (const kind2 of ORG_KINDS) {
18636
+ const list2 = byKind.get(kind2);
18627
18637
  if (!list2?.length) continue;
18628
- lines.push(`## ${kind}/ (${list2.length})`);
18638
+ lines.push(`## ${kind2}/ (${list2.length})`);
18629
18639
  for (const n of list2) lines.push(`- [[${orgNodePath(n).split("/")[1].replace(/\.md$/, "")}]] \u2014 ${n.title} \xB7 ${n.origin}`);
18630
18640
  lines.push("");
18631
18641
  }
@@ -18684,8 +18694,8 @@ async function readOrgMirror(remote = requestRemote()) {
18684
18694
  const dir = orgMirrorDir(remote);
18685
18695
  if (!dir || !(0, import_node_fs14.existsSync)(dir)) return [];
18686
18696
  const out2 = [];
18687
- for (const kind of ORG_KINDS) {
18688
- const kindDir = (0, import_node_path14.join)(dir, kind);
18697
+ for (const kind2 of ORG_KINDS) {
18698
+ const kindDir = (0, import_node_path14.join)(dir, kind2);
18689
18699
  if (!(0, import_node_fs14.existsSync)(kindDir)) continue;
18690
18700
  let files;
18691
18701
  try {
@@ -18912,9 +18922,9 @@ var STOPWORDS = /* @__PURE__ */ new Set([
18912
18922
  "within",
18913
18923
  "without"
18914
18924
  ]);
18915
- function tokenize(text) {
18925
+ function tokenize(text2) {
18916
18926
  return new Set(
18917
- 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))
18918
18928
  );
18919
18929
  }
18920
18930
  function jaccardKeywords(a, b) {
@@ -18953,16 +18963,16 @@ function relevance(node, ctx) {
18953
18963
  return { score, via: { glob: globHit, tag: tagScore, text: textScore } };
18954
18964
  }
18955
18965
  var KIND_POOL_STRENGTH = 20;
18956
- function priorFor(kind, pooled) {
18957
- const base = KIND_PRIOR_MEAN[kind] ?? DEFAULT_PRIOR_MEAN;
18966
+ function priorFor(kind2, pooled) {
18967
+ const base = KIND_PRIOR_MEAN[kind2] ?? DEFAULT_PRIOR_MEAN;
18958
18968
  const a = pooled ? Math.max(0, pooled.alpha) : 0;
18959
18969
  const b = pooled ? Math.max(0, pooled.beta) : 0;
18960
- const mean = pooled && kind !== "integration" ? (KIND_POOL_STRENGTH * base + a) / (KIND_POOL_STRENGTH + a + b) : base;
18970
+ const mean = pooled && kind2 !== "integration" ? (KIND_POOL_STRENGTH * base + a) / (KIND_POOL_STRENGTH + a + b) : base;
18961
18971
  return { alpha: mean * PRIOR_STRENGTH, beta: (1 - mean) * PRIOR_STRENGTH };
18962
18972
  }
18963
- function posteriorFor(kind, own, pooled) {
18964
- const p = priorFor(kind, pooled);
18965
- if (!own || kind === "integration") return p;
18973
+ function posteriorFor(kind2, own, pooled) {
18974
+ const p = priorFor(kind2, pooled);
18975
+ if (!own || kind2 === "integration") return p;
18966
18976
  return { alpha: p.alpha + Math.max(0, own.alpha), beta: p.beta + Math.max(0, own.beta) };
18967
18977
  }
18968
18978
  function posteriorMean(p) {
@@ -18991,9 +19001,9 @@ var MAX_BUDGET_TOKENS = 4e3;
18991
19001
  var MAX_NODE_FILE_BYTES = 64 * 1024;
18992
19002
  var MIN_SCORE = RELEVANCE_FLOOR * 0.5;
18993
19003
  var ORG_MIN_SHARED_TERMS = 2;
18994
- function orgTerms(text) {
19004
+ function orgTerms(text2) {
18995
19005
  return new Set(
18996
- 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)
18997
19007
  );
18998
19008
  }
18999
19009
  function sharedTerms(a, b) {
@@ -19276,15 +19286,15 @@ function runHook(hooks) {
19276
19286
  return false;
19277
19287
  }
19278
19288
  }
19279
- function appendInRoot(root, name2, text, hooks = {}) {
19289
+ function appendInRoot(root, name2, text2, hooks = {}) {
19280
19290
  return writeVerified(root, name2, hooks, true, (fd) => {
19281
- (0, import_node_fs17.writeSync)(fd, text);
19291
+ (0, import_node_fs17.writeSync)(fd, text2);
19282
19292
  });
19283
19293
  }
19284
- function replaceInRoot(root, name2, text, hooks = {}) {
19294
+ function replaceInRoot(root, name2, text2, hooks = {}) {
19285
19295
  return writeVerified(root, name2, hooks, false, (fd) => {
19286
19296
  (0, import_node_fs17.ftruncateSync)(fd, 0);
19287
- (0, import_node_fs17.writeSync)(fd, text, 0);
19297
+ (0, import_node_fs17.writeSync)(fd, text2, 0);
19288
19298
  });
19289
19299
  }
19290
19300
 
@@ -19474,12 +19484,12 @@ function ensureVerityGitignore() {
19474
19484
  if (hasSupersededMemory && !memoryIsCommitted) {
19475
19485
  next = fenceMemoryLines(next);
19476
19486
  }
19477
- let text = next.join("\n");
19487
+ let text2 = next.join("\n");
19478
19488
  if (!hasMarker) {
19479
- const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19480
- text = text + sep6 + VERITY_GITIGNORE_BLOCK;
19489
+ const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
19490
+ text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
19481
19491
  }
19482
- if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
19492
+ if (text2 !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text2);
19483
19493
  return verified(
19484
19494
  memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
19485
19495
  );
@@ -19505,13 +19515,13 @@ function writeFencedBlock() {
19505
19515
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
19506
19516
  let lines = content.split("\n").map((l) => BREAKING_ENTRIES.has(l.trim()) ? ".verity/*" : l);
19507
19517
  lines = fenceMemoryLines(lines);
19508
- let text = lines.join("\n");
19518
+ let text2 = lines.join("\n");
19509
19519
  if (!hasMarker) {
19510
- const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19511
- text = text + sep6 + VERITY_GITIGNORE_BLOCK;
19520
+ const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
19521
+ text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
19512
19522
  }
19513
19523
  try {
19514
- (0, import_node_fs19.writeFileSync)(".gitignore", text);
19524
+ (0, import_node_fs19.writeFileSync)(".gitignore", text2);
19515
19525
  return true;
19516
19526
  } catch {
19517
19527
  return false;
@@ -19558,8 +19568,8 @@ function keepMemoryTracked() {
19558
19568
  }
19559
19569
  if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
19560
19570
  try {
19561
- const sep6 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
19562
- (0, import_node_fs19.writeFileSync)(".gitignore", content + sep6 + MEMORY_OPT_OUT_STANZA);
19571
+ const sep7 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
19572
+ (0, import_node_fs19.writeFileSync)(".gitignore", content + sep7 + MEMORY_OPT_OUT_STANZA);
19563
19573
  } catch {
19564
19574
  return "failed";
19565
19575
  }
@@ -20002,7 +20012,7 @@ async function regenerateIndex() {
20002
20012
  try {
20003
20013
  const content = await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8");
20004
20014
  const title = pickFrontmatter(content, "title") ?? slug;
20005
- const kind = pickFrontmatter(content, "kind") ?? "-";
20015
+ const kind2 = pickFrontmatter(content, "kind") ?? "-";
20006
20016
  const confidence = pickFrontmatter(content, "confidence");
20007
20017
  const globs = pickFrontmatterArray(content, "file_globs");
20008
20018
  const status = pickFrontmatter(content, "status") ?? "active";
@@ -20010,7 +20020,7 @@ async function regenerateIndex() {
20010
20020
  const globPart = globs.length > 0 ? ` \xB7 scope: \`${globs.slice(0, 3).join("`, `")}\`` : "";
20011
20021
  const statusPart = status !== "active" ? ` \xB7 *${status}*` : "";
20012
20022
  lines.push(`- [[${slug}]] \u2014 **${title}**`);
20013
- lines.push(` *${kind}*${confPart}${globPart}${statusPart}`);
20023
+ lines.push(` *${kind2}*${confPart}${globPart}${statusPart}`);
20014
20024
  } catch {
20015
20025
  lines.push(`- [[${slug}]]`);
20016
20026
  }
@@ -20490,26 +20500,26 @@ var CLAUDE_MD_PROSE_LEGACY = [
20490
20500
  "superseded \u2014 ignore them unless investigating history."
20491
20501
  ].join("\n");
20492
20502
  var PRESERVE_PLACEHOLDER = "<!-- Add binding, hand-curated guidance here; it survives Verity regeneration. -->";
20493
- function* scanLines(text) {
20503
+ function* scanLines(text2) {
20494
20504
  let offset = 0;
20495
20505
  let inFence = false;
20496
- for (const line2 of text.split("\n")) {
20506
+ for (const line2 of text2.split("\n")) {
20497
20507
  const isFence = /^(`{3,}|~{3,})/.test(line2.trim());
20498
20508
  if (isFence) inFence = !inFence;
20499
20509
  yield { line: line2, start: offset, inFence: inFence || isFence };
20500
20510
  offset += line2.length + 1;
20501
20511
  }
20502
20512
  }
20503
- function findMarker(text, marker, from = 0) {
20504
- 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)) {
20505
20515
  if (!inFence && start2 >= from && line2.startsWith(marker)) {
20506
20516
  return start2;
20507
20517
  }
20508
20518
  }
20509
20519
  return -1;
20510
20520
  }
20511
- function hasLegacyMemoryBlock(text) {
20512
- return findMarker(text, LEGACY_MD_START) !== -1;
20521
+ function hasLegacyMemoryBlock(text2) {
20522
+ return findMarker(text2, LEGACY_MD_START) !== -1;
20513
20523
  }
20514
20524
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
20515
20525
  const claudeMdPath = (0, import_node_path19.join)(cwd, "CLAUDE.md");
@@ -20709,10 +20719,10 @@ var STOP = /* @__PURE__ */ new Set([
20709
20719
  "verify",
20710
20720
  "check"
20711
20721
  ]);
20712
- function pendingTokens(text) {
20713
- if (!text || typeof text !== "string") return [];
20722
+ function pendingTokens(text2) {
20723
+ if (!text2 || typeof text2 !== "string") return [];
20714
20724
  const out2 = /* @__PURE__ */ new Set();
20715
- for (const raw of text.toLowerCase().split(/[^a-z0-9]+/)) {
20725
+ for (const raw of text2.toLowerCase().split(/[^a-z0-9]+/)) {
20716
20726
  if (raw.length <= 3) continue;
20717
20727
  if (STOP.has(raw)) continue;
20718
20728
  out2.add(raw);
@@ -20727,8 +20737,8 @@ function overlapCoefficient(a, b) {
20727
20737
  for (const t of a) if (setB.has(t)) shared++;
20728
20738
  return shared / Math.min(a.length, b.length);
20729
20739
  }
20730
- function isRepeatOfAny(text, priorFingerprints, threshold = REPEAT_THRESHOLD) {
20731
- const tokens = pendingTokens(text);
20740
+ function isRepeatOfAny(text2, priorFingerprints, threshold = REPEAT_THRESHOLD) {
20741
+ const tokens = pendingTokens(text2);
20732
20742
  if (tokens.length === 0) return false;
20733
20743
  return priorFingerprints.some((prior) => overlapCoefficient(tokens, prior) >= threshold);
20734
20744
  }
@@ -21418,8 +21428,8 @@ function assessContinuity(i2) {
21418
21428
  // src/lib/dossier/reanchor.ts
21419
21429
  var import_node_crypto8 = require("node:crypto");
21420
21430
  var import_node_fs25 = require("node:fs");
21421
- function lineSha(text) {
21422
- 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);
21423
21433
  }
21424
21434
  function fileHash(path) {
21425
21435
  try {
@@ -21892,10 +21902,10 @@ function recordGoal(d, prompt, source2 = "prompt") {
21892
21902
  appendEvent(d, { k: "goal_continue", text: prompt.slice(0, 64) });
21893
21903
  return;
21894
21904
  }
21895
- const text = prompt.slice(0, MAX_GOAL_CHARS);
21905
+ const text2 = prompt.slice(0, MAX_GOAL_CHARS);
21896
21906
  appendEvent(d, {
21897
21907
  k: "goal",
21898
- text,
21908
+ text: text2,
21899
21909
  text_len: prompt.length,
21900
21910
  source: source2,
21901
21911
  ...prompt.length > MAX_GOAL_CHARS && { truncated: true }
@@ -22053,8 +22063,8 @@ function toRegister(severity) {
22053
22063
  return "NOTE";
22054
22064
  }
22055
22065
  }
22056
- function recordMark(d, kind, from, to) {
22057
- appendEvent(d, { k: "mark", kind, from: from ?? null, to: to ?? null });
22066
+ function recordMark(d, kind2, from, to) {
22067
+ appendEvent(d, { k: "mark", kind: kind2, from: from ?? null, to: to ?? null });
22058
22068
  }
22059
22069
  function recordCapabilities(d, c, known) {
22060
22070
  const put = (field, value, tier) => {
@@ -22149,13 +22159,13 @@ function registerIntentCommands(program2) {
22149
22159
  if (!prompt) {
22150
22160
  process.exit(0);
22151
22161
  }
22152
- if (deferredToPlugin("intent capture", event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null)) {
22162
+ if (deferredToPlugin("intent capture", event.session_id ?? envSessionId() ?? null)) {
22153
22163
  process.exit(0);
22154
22164
  }
22155
22165
  const isPrimitive = isSlashCommand(prompt);
22156
22166
  const authForScope = await resolveToken(program2.opts().token);
22157
22167
  const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
22158
- const scopeSession = event.session_id || process.env.CLAUDE_SESSION_ID || "";
22168
+ const scopeSession = event.session_id || envSessionId() || "";
22159
22169
  if (!isPrimitive) await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
22160
22170
  if (!isPrimitive) {
22161
22171
  try {
@@ -22875,7 +22885,12 @@ function registerLifecycleCommands(program2) {
22875
22885
  }
22876
22886
  if (!verityConfigured()) process.exit(0);
22877
22887
  const event = await readHookStdin();
22878
- const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
22888
+ const resolved = resolveHookSession(opts.sessionId, event, envSessionId());
22889
+ if (!resolved.ok) {
22890
+ logEvent("lifecycle_session_flag_refused", { command: "compact" });
22891
+ process.exit(0);
22892
+ }
22893
+ const sessionId = resolved.sessionId;
22879
22894
  if (deferredToPlugin("compact", sessionId)) process.exit(0);
22880
22895
  const globals = program2.opts();
22881
22896
  const tok = await resolveToken(globals.token);
@@ -22904,9 +22919,14 @@ function registerLifecycleCommands(program2) {
22904
22919
  }
22905
22920
  if (!verityConfigured()) process.exit(0);
22906
22921
  const event = await readHookStdin();
22907
- const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
22922
+ const resolved = resolveHookSession(opts.sessionId, event, envSessionId());
22923
+ if (!resolved.ok) {
22924
+ logEvent("lifecycle_session_flag_refused", { command: "session end" });
22925
+ process.exit(0);
22926
+ }
22927
+ const sessionId = resolved.sessionId;
22908
22928
  if (deferredToPlugin("session end", sessionId)) process.exit(0);
22909
- const reason = opts.reason ?? event.session_end_reason ?? event.reason ?? "other";
22929
+ const reason = hookWord(opts.reason) ?? event.session_end_reason ?? event.reason ?? "other";
22910
22930
  if (reason === "clear") {
22911
22931
  writeCarry(sessionId ?? void 0, getCurrentCommit());
22912
22932
  }
@@ -22985,25 +23005,61 @@ function buildCompactionContext(session) {
22985
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.`
22986
23006
  );
22987
23007
  }
22988
- const text = lines.join("\n");
22989
- if (text.length <= MAX_CHARS) return text;
23008
+ const text2 = lines.join("\n");
23009
+ if (text2.length <= MAX_CHARS) return text2;
22990
23010
  const trimmed = [...lines.slice(0, 5), ...lines.slice(5, 5 + 2)].join("\n");
22991
23011
  return trimmed.length <= MAX_CHARS ? trimmed : null;
22992
23012
  }
23013
+ var MAX_HOOK_EVENT_BYTES = 64 * 1024;
23014
+ var SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
23015
+ var HOOK_WORD = /^[a-z][a-z_]{0,63}$/;
23016
+ function isHookSessionId(value) {
23017
+ return typeof value === "string" && SESSION_ID.test(value);
23018
+ }
23019
+ function hookWord(value) {
23020
+ return typeof value === "string" && HOOK_WORD.test(value) ? value : void 0;
23021
+ }
23022
+ function resolveHookSession(flag, event, env) {
23023
+ if (flag !== void 0) return isHookSessionId(flag) ? { ok: true, sessionId: flag } : { ok: false };
23024
+ if (event.session_id) return { ok: true, sessionId: event.session_id };
23025
+ return { ok: true, sessionId: isHookSessionId(env) ? env : null };
23026
+ }
23027
+ function parseHookEvent(raw) {
23028
+ let data;
23029
+ try {
23030
+ data = JSON.parse(raw.trim() || "{}");
23031
+ } catch {
23032
+ return {};
23033
+ }
23034
+ if (!data || typeof data !== "object" || Array.isArray(data)) return {};
23035
+ const o = data;
23036
+ const event = {};
23037
+ if (isHookSessionId(o.session_id)) event.session_id = o.session_id;
23038
+ const compaction = hookWord(o.compaction_type);
23039
+ if (compaction) event.compaction_type = compaction;
23040
+ const endReason = hookWord(o.session_end_reason);
23041
+ if (endReason) event.session_end_reason = endReason;
23042
+ const reason = hookWord(o.reason);
23043
+ if (reason) event.reason = reason;
23044
+ return event;
23045
+ }
22993
23046
  async function readHookStdin() {
22994
23047
  try {
22995
23048
  if (process.stdin.isTTY) return {};
22996
23049
  const chunks = [];
23050
+ let size = 0;
22997
23051
  const timeout = new Promise((resolve9) => setTimeout(() => resolve9({}), 500));
22998
23052
  const read2 = new Promise((resolve9) => {
22999
- process.stdin.on("data", (c) => chunks.push(c));
23000
- process.stdin.on("end", () => {
23001
- try {
23002
- resolve9(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
23003
- } catch {
23053
+ process.stdin.on("data", (c) => {
23054
+ size += c.length;
23055
+ if (size > MAX_HOOK_EVENT_BYTES) {
23056
+ process.stdin.destroy();
23004
23057
  resolve9({});
23058
+ return;
23005
23059
  }
23060
+ chunks.push(c);
23006
23061
  });
23062
+ process.stdin.on("end", () => resolve9(parseHookEvent(Buffer.concat(chunks).toString("utf-8"))));
23007
23063
  process.stdin.on("error", () => resolve9({}));
23008
23064
  process.stdin.resume();
23009
23065
  });
@@ -23268,9 +23324,9 @@ function declaredDependencies(root, files) {
23268
23324
  for (const path of pythonManifests) {
23269
23325
  if (!(0, import_node_fs31.existsSync)(path)) continue;
23270
23326
  try {
23271
- const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23272
- for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
23273
- 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")) {
23274
23330
  if (!/dependencies\s*=/.test(line2)) continue;
23275
23331
  for (const m of line2.matchAll(/["']([A-Za-z][A-Za-z0-9._-]+)/g)) names2.push(m[1]);
23276
23332
  }
@@ -23284,8 +23340,8 @@ function declaredDependencies(root, files) {
23284
23340
  for (const path of goMods) {
23285
23341
  if (!(0, import_node_fs31.existsSync)(path)) continue;
23286
23342
  try {
23287
- const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23288
- 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)) {
23289
23345
  names2.push(m[1].replace(/^github\.com\//, ""));
23290
23346
  }
23291
23347
  } catch {
@@ -23295,8 +23351,8 @@ function declaredDependencies(root, files) {
23295
23351
  const path = (0, import_node_path28.join)(root, file);
23296
23352
  if (!(0, import_node_fs31.existsSync)(path)) continue;
23297
23353
  try {
23298
- const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23299
- 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]);
23300
23356
  } catch {
23301
23357
  }
23302
23358
  }
@@ -23827,8 +23883,8 @@ async function correctVerityMdVersion(opts) {
23827
23883
  origin: { kind: "synthesized", tools: opts.tools }
23828
23884
  }));
23829
23885
  }
23830
- async function writeFileTo(relative6, body2) {
23831
- const target = projectPath(relative6);
23886
+ async function writeFileTo(relative7, body2) {
23887
+ const target = projectPath(relative7);
23832
23888
  await (0, import_promises10.mkdir)((0, import_node_path29.dirname)(target), { recursive: true });
23833
23889
  await (0, import_promises10.writeFile)(target, body2);
23834
23890
  }
@@ -24907,7 +24963,7 @@ function registerStatusCommand(program2) {
24907
24963
  {
24908
24964
  const tokenForScope = tokenResult.data.token;
24909
24965
  const found = resolveIgnoreState(
24910
- ignoreStateKeys(tokenForScope, process.env.CLAUDE_SESSION_ID || void 0)
24966
+ ignoreStateKeys(tokenForScope, envSessionId())
24911
24967
  );
24912
24968
  const now = Math.floor(Date.now() / 1e3);
24913
24969
  const active = resolveActive(found?.state ?? null, now);
@@ -25004,9 +25060,9 @@ function readTextInput(value, flag, readStdin2 = () => (0, import_node_fs39.read
25004
25060
  if (raw.length > MAX_STDIN_BYTES) {
25005
25061
  return { ok: false, error: `${flag} from stdin is ${raw.length} bytes; the limit is ${MAX_STDIN_BYTES}.` };
25006
25062
  }
25007
- const text = raw.toString("utf8").replace(/\r?\n$/, "");
25008
- if (!text.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
25009
- return { ok: true, text };
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 };
25010
25066
  }
25011
25067
 
25012
25068
  // src/lib/terminal-text.ts
@@ -25024,8 +25080,8 @@ function terminalUrl(value) {
25024
25080
  // src/commands/feedback.ts
25025
25081
  function registerFeedbackCommand(program2) {
25026
25082
  const feedbackCmd = program2.command("feedback").description("Send feedback to the Verity team");
25027
- feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text, opts) => {
25028
- await sendMessageArg(text, opts, program2.opts());
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());
25029
25085
  });
25030
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) => {
25031
25087
  const globals = program2.opts();
@@ -25100,7 +25156,7 @@ async function sendGeneralFeedback(message, opts, globals) {
25100
25156
  process.exit(1);
25101
25157
  }
25102
25158
  const body2 = { message };
25103
- const sessionId = opts.sessionId ?? process.env.CLAUDE_SESSION_ID;
25159
+ const sessionId = opts.sessionId ?? envSessionId();
25104
25160
  const model = opts.model ?? process.env.CLAUDE_MODEL ?? "unknown";
25105
25161
  if (sessionId) body2.session_id = sessionId;
25106
25162
  if (model) body2.agent_model = model;
@@ -25630,28 +25686,28 @@ function parseRgLine(line2) {
25630
25686
  return { file: line2.slice(0, first), line: n, text: line2.slice(second + 1) };
25631
25687
  }
25632
25688
  var isWordChar = (c) => c !== void 0 && /[A-Za-z0-9_]/.test(c);
25633
- function wordHit(text, symbol) {
25689
+ function wordHit(text2, symbol) {
25634
25690
  let from = 0;
25635
25691
  for (; ; ) {
25636
- const at = text.indexOf(symbol, from);
25692
+ const at = text2.indexOf(symbol, from);
25637
25693
  if (at < 0) return false;
25638
- const before = at === 0 ? void 0 : text[at - 1];
25639
- const after = text[at + symbol.length];
25694
+ const before = at === 0 ? void 0 : text2[at - 1];
25695
+ const after = text2[at + symbol.length];
25640
25696
  if (!isWordChar(before) && !isWordChar(after)) return true;
25641
25697
  from = at + 1;
25642
25698
  }
25643
25699
  }
25644
- function isContractLine(text, symbol) {
25700
+ function isContractLine(text2, symbol) {
25645
25701
  for (const kw of ["implements", "extends"]) {
25646
25702
  let from = 0;
25647
25703
  for (; ; ) {
25648
- const at = text.indexOf(kw, from);
25704
+ const at = text2.indexOf(kw, from);
25649
25705
  if (at < 0) break;
25650
25706
  from = at + 1;
25651
- const before = at === 0 ? void 0 : text[at - 1];
25652
- const after = text[at + kw.length];
25707
+ const before = at === 0 ? void 0 : text2[at - 1];
25708
+ const after = text2[at + kw.length];
25653
25709
  if (isWordChar(before) || isWordChar(after)) continue;
25654
- let clause = text.slice(at + kw.length);
25710
+ let clause = text2.slice(at + kw.length);
25655
25711
  const stop2 = Math.min(
25656
25712
  ...[clause.indexOf(";"), clause.indexOf("{")].filter((i2) => i2 >= 0)
25657
25713
  );
@@ -25683,20 +25739,20 @@ function partitionSites(rgLines, symbols, opts) {
25683
25739
  if (opts.sentPaths.has(h.file)) continue;
25684
25740
  if (opts.isExcluded(h.file)) continue;
25685
25741
  if (!isCodeSiteFile(h.file)) continue;
25686
- const text = h.text.trim();
25687
- if (text.length === 0 || IMPORT_LINE.test(h.text)) continue;
25688
- if (COMMENT_LINE.test(text)) continue;
25689
- if (BARE_MEMBER_LINE.test(text) || GO_IMPORT_PATH_LINE.test(text)) 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;
25690
25746
  const n = perFile.get(h.file) ?? 0;
25691
25747
  if (n >= MAX_SITES_PER_FILE) continue;
25692
25748
  const site = {
25693
25749
  file: h.file,
25694
25750
  line: h.line,
25695
- text: text.slice(0, SITE_TEXT_MAX),
25751
+ text: text2.slice(0, SITE_TEXT_MAX),
25696
25752
  symbol: h.symbol,
25697
25753
  // R2 falls out of R1 for free: a word search for `Sym` already matches
25698
25754
  // `implements Sym` / `extends Sym` lines — classification is all R2 is.
25699
- ...isContractLine(text, h.symbol) ? { kind: "contract" } : {}
25755
+ ...isContractLine(text2, h.symbol) ? { kind: "contract" } : {}
25700
25756
  };
25701
25757
  if (isTestPath(h.file)) {
25702
25758
  if (tests.length < MAX_TEST_SLOTS) {
@@ -25716,8 +25772,8 @@ var MAX_IMPORTERS_PER_FILE = 2;
25716
25772
  function moduleKey(path) {
25717
25773
  return path.replace(/\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/i, "").replace(/\/index$/, "");
25718
25774
  }
25719
- function importSpecifier(text) {
25720
- 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);
25721
25777
  return m?.[1] ?? null;
25722
25778
  }
25723
25779
  function resolveSpecifier(fromFile, spec) {
@@ -25987,8 +26043,8 @@ function extractEnclosingExcerpt(content, siteLine, path) {
25987
26043
  start2 = Math.max(1, siteLine - (EXCERPT_MAX_LINES - 6));
25988
26044
  }
25989
26045
  const end = Math.min(lines.length, start2 + EXCERPT_MAX_LINES - 1);
25990
- const text = lines.slice(start2 - 1, end).join("\n").slice(0, EXCERPT_MAX_CHARS);
25991
- 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 };
25992
26048
  }
25993
26049
  function upgradeToExcerpts(rc, opts) {
25994
26050
  if (rc.state !== "ok") return;
@@ -26344,7 +26400,7 @@ function resolveFrame(input) {
26344
26400
  const hookDirUsable = !!input.hookCwd && (0, import_node_fs40.existsSync)(input.hookCwd);
26345
26401
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
26346
26402
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
26347
- const refuse = (refusal) => ({
26403
+ const refuse2 = (refusal) => ({
26348
26404
  moment: found?.moment ?? null,
26349
26405
  frame: { worktreeRoot: null, gitDir: null, commonDir: null, isLinkedWorktree: false, branch: null, anchor, refusal }
26350
26406
  });
@@ -26358,19 +26414,19 @@ function resolveFrame(input) {
26358
26414
  if (!kindRes.some((re) => re.test(segments[i2]))) continue;
26359
26415
  const target = extractCommandTarget(input.command, i2, baseDir);
26360
26416
  if (target.named) anchor = "command-target";
26361
- if (target.unresolvable) return refuse(`target:${target.unresolvable}`);
26417
+ if (target.unresolvable) return refuse2(`target:${target.unresolvable}`);
26362
26418
  dirs.add(target.dir ?? baseDir);
26363
26419
  }
26364
- if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
26420
+ if (dirs.size > 1) return refuse2(`target:multiple ${found.moment} targets in one command`);
26365
26421
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
26366
26422
  if (targetDir !== baseDir) {
26367
- if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26423
+ if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse2(`target:directory does not exist: ${targetDir}`);
26368
26424
  dir = targetDir;
26369
26425
  }
26370
26426
  }
26371
26427
  const toplevel = gitAt(dir, ["rev-parse", "--show-toplevel"]);
26372
26428
  if (!toplevel) {
26373
- return refuse(anchor === "command-target" ? `target:not a git repository: ${dir}` : `anchor:not a git repository: ${dir}`);
26429
+ return refuse2(anchor === "command-target" ? `target:not a git repository: ${dir}` : `anchor:not a git repository: ${dir}`);
26374
26430
  }
26375
26431
  const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
26376
26432
  const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
@@ -26966,7 +27022,7 @@ function sanitizeCommandWithLoss(rawCmd) {
26966
27022
  const lost = lines.slice(1).some((l) => l.trim().length > 0);
26967
27023
  const first = lines[0];
26968
27024
  const cmd = sanitizeCommand(first);
26969
- const hadSeparator = SEPARATORS.some((sep6) => first.indexOf(sep6) > 0);
27025
+ const hadSeparator = SEPARATORS.some((sep7) => first.indexOf(sep7) > 0);
26970
27026
  return { cmd, lost: lost || !hadSeparator && first.length > MAX_COMMAND_CHARS };
26971
27027
  }
26972
27028
  var SEPARATORS = [" | ", " > ", " >> ", " 2>", " && ", " ; "];
@@ -26975,11 +27031,11 @@ function sanitizeCommand(rawCmd) {
26975
27031
  let cmd = rawCmd.split("\n")[0];
26976
27032
  let cut = -1;
26977
27033
  let marker = "";
26978
- for (const sep6 of SEPARATORS) {
26979
- const idx = cmd.indexOf(sep6);
27034
+ for (const sep7 of SEPARATORS) {
27035
+ const idx = cmd.indexOf(sep7);
26980
27036
  if (idx > 0 && (cut === -1 || idx < cut)) {
26981
27037
  cut = idx;
26982
- marker = sep6.trim();
27038
+ marker = sep7.trim();
26983
27039
  }
26984
27040
  }
26985
27041
  if (cut > -1) cmd = cmd.slice(0, cut);
@@ -27046,13 +27102,13 @@ async function bootstrap(run4) {
27046
27102
  isTTY: process.stdout.isTTY === true
27047
27103
  });
27048
27104
  const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
27049
- if (deferredToPlugin("analyze", sessionId ?? process.env.CLAUDE_SESSION_ID ?? null)) {
27105
+ if (deferredToPlugin("analyze", sessionId ?? envSessionId() ?? null)) {
27050
27106
  process.exit(0);
27051
27107
  }
27052
27108
  const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
27053
27109
  const tokenResult = await resolveToken(globals.token);
27054
27110
  const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
27055
- const rawSessionId = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
27111
+ const rawSessionId = sessionId || envSessionId();
27056
27112
  const baselineSessionId = sessionScopeKey(scopeToken, rawSessionId);
27057
27113
  if (tokenResult.ok) {
27058
27114
  run4.beacon = {
@@ -27085,12 +27141,12 @@ function parseKnowledgeNote(raw) {
27085
27141
  if (!raw || typeof raw !== "object") return null;
27086
27142
  const o = raw;
27087
27143
  const node_id = typeof o.node_id === "string" ? o.node_id.trim() : "";
27088
- const text = typeof o.text === "string" ? o.text.trim() : "";
27089
- if (!node_id || !text) return null;
27090
- 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;
27091
27147
  return {
27092
27148
  node_id,
27093
- text,
27149
+ text: text2,
27094
27150
  file: typeof o.file === "string" && o.file ? o.file : null,
27095
27151
  line: typeof o.line === "number" && Number.isFinite(o.line) && o.line > 0 ? Math.floor(o.line) : null
27096
27152
  };
@@ -27128,10 +27184,10 @@ function episodeForWire(e, humanSpoke) {
27128
27184
  var MAX_AGENT_CONTEXT_CHARS = 1500;
27129
27185
  var MAX_AGENT_ITEMS = 5;
27130
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):";
27131
- function renderItem(label2, text, patternId, file, line2) {
27187
+ function renderItem(label2, text2, patternId, file, line2) {
27132
27188
  const where2 = file ? ` (${file}${line2 !== void 0 && line2 !== "" ? `:${line2}` : ""})` : "";
27133
27189
  const id = patternId ? ` [${patternId}]` : "";
27134
- return `- ${label2}${text}${where2}${id}`;
27190
+ return `- ${label2}${text2}${where2}${id}`;
27135
27191
  }
27136
27192
  function channelInputFrom(response, intentRepeat = 0, priorPendingFingerprints = []) {
27137
27193
  const metadata2 = response.metadata ?? {};
@@ -27213,11 +27269,11 @@ function buildAgentContext(input) {
27213
27269
  for (const p of input.pendingItems ?? []) {
27214
27270
  if (lines.length >= MAX_AGENT_ITEMS) break;
27215
27271
  if (p.pattern_id === "intent-misalignment") continue;
27216
- const text = p.description ?? p.title ?? p.reason;
27217
- if (!text) continue;
27218
- 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 ?? []);
27219
27275
  lines.push(
27220
- 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)" : "")
27221
27277
  );
27222
27278
  }
27223
27279
  if (lines.length === 0) return null;
@@ -27225,11 +27281,11 @@ function buildAgentContext(input) {
27225
27281
  ${lines.slice(0, MAX_AGENT_ITEMS).join("\n")}`;
27226
27282
  return truncateToCap(body2);
27227
27283
  }
27228
- function truncateToCap(text) {
27229
- if (text.length <= MAX_AGENT_CONTEXT_CHARS) return text;
27284
+ function truncateToCap(text2) {
27285
+ if (text2.length <= MAX_AGENT_CONTEXT_CHARS) return text2;
27230
27286
  const marker = "\n- (truncated)";
27231
27287
  const budget = MAX_AGENT_CONTEXT_CHARS - marker.length;
27232
- const lines = text.slice(0, budget).split("\n");
27288
+ const lines = text2.slice(0, budget).split("\n");
27233
27289
  lines.pop();
27234
27290
  return `${lines.join("\n")}${marker}`;
27235
27291
  }
@@ -27257,7 +27313,7 @@ function channelSilence(input) {
27257
27313
  // src/lib/cli-version.ts
27258
27314
  function cliVersion() {
27259
27315
  try {
27260
- return true ? "0.34.1" : "dev";
27316
+ return true ? "0.34.2-experimental.2cad220" : "dev";
27261
27317
  } catch {
27262
27318
  return "dev";
27263
27319
  }
@@ -27497,10 +27553,10 @@ var EMPTY_RESULT = {
27497
27553
  findings: [],
27498
27554
  summary: { total_findings: 0, by_severity: {}, tools_run: [] }
27499
27555
  };
27500
- function withFailure(kind, detail) {
27556
+ function withFailure(kind2, detail) {
27501
27557
  return {
27502
27558
  ...EMPTY_RESULT,
27503
- summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
27559
+ summary: { ...EMPTY_RESULT.summary, failure: { kind: kind2, detail: detail.slice(0, 300) } }
27504
27560
  };
27505
27561
  }
27506
27562
  function runCodacyAnalysisIfAvailable(files) {
@@ -28058,7 +28114,7 @@ async function connect(run4) {
28058
28114
  async function mode(run4) {
28059
28115
  const { opts, globals } = run4;
28060
28116
  const { actionSummary, allForReview, assistantResponse, baseline, conversation, memory: memory2, noFilesChanged, serviceUrl, sessionId, token, turnAuthoredCode } = run4;
28061
- const sessionIdForMemory = sessionId || process.env.CLAUDE_SESSION_ID || "";
28117
+ const sessionIdForMemory = sessionId || envSessionId() || "";
28062
28118
  let predictedMode;
28063
28119
  try {
28064
28120
  const memoryPath2 = sessionIdForMemory ? `/memory?session_id=${encodeURIComponent(sessionIdForMemory)}` : "/memory";
@@ -28259,11 +28315,11 @@ var rootCandidateCache = /* @__PURE__ */ new Map();
28259
28315
  function candidateRoots(repoRoot2) {
28260
28316
  const cached2 = rootCandidateCache.get(repoRoot2);
28261
28317
  if (cached2) return cached2;
28262
- const norm2 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
28263
- const out2 = [norm2];
28318
+ const norm3 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
28319
+ const out2 = [norm3];
28264
28320
  try {
28265
- const real = import_node_fs44.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
28266
- if (real !== norm2) out2.push(real);
28321
+ const real = import_node_fs44.realpathSync.native(norm3).replace(/\\/g, "/").replace(/\/+$/, "");
28322
+ if (real !== norm3) out2.push(real);
28267
28323
  } catch {
28268
28324
  }
28269
28325
  for (const r of [...out2]) {
@@ -29114,39 +29170,39 @@ function extentOf(node) {
29114
29170
  }
29115
29171
  function definitionsIn(root, spec) {
29116
29172
  const out2 = [];
29117
- const add = (name2, kind, extent, fn, owner, last = extent) => {
29173
+ const add = (name2, kind2, extent, fn, owner, last = extent) => {
29118
29174
  const q = qualifierOf(owner, spec);
29119
- out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind, extent, last, fn });
29175
+ out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind: kind2, extent, last, fn });
29120
29176
  };
29121
29177
  const visit = (n) => {
29122
- const kind = spec.definitions[n.type];
29123
- if (kind && n.childForFieldName("body")) {
29178
+ const kind2 = spec.definitions[n.type];
29179
+ if (kind2 && n.childForFieldName("body")) {
29124
29180
  const nameNode = n.childForFieldName("name");
29125
29181
  if (nameNode && nameNode.type !== "computed_property_name") {
29126
29182
  const inClass = qualifierOf(n, spec) !== null;
29127
- const k = spec.id === "python" ? inClass ? "method" : "function" : kind;
29183
+ const k = spec.id === "python" ? inClass ? "method" : "function" : kind2;
29128
29184
  add(nameNode.text, k, extentOf(n), n, n, n.parent?.type === "decorated_definition" ? n.parent : n);
29129
29185
  }
29130
29186
  } else if (spec.functionValues.has(n.type) && n.parent) {
29131
29187
  const p = n.parent;
29132
- const kind2 = n.type === "arrow_function" ? "arrow" : n.type === "lambda" || n.type === "lambda_expression" ? "lambda" : "function";
29188
+ const kind3 = n.type === "arrow_function" ? "arrow" : n.type === "lambda" || n.type === "lambda_expression" ? "lambda" : "function";
29133
29189
  const bound = p.childForFieldName("value")?.id === n.id;
29134
29190
  if (bound && p.type === "variable_declarator" && p.childForFieldName("name")?.type === "identifier") {
29135
29191
  const decl = p.parent && p.parent.namedChildren.filter((c) => c.type === "variable_declarator").length === 1 ? p.parent : p;
29136
- add(p.childForFieldName("name").text, kind2, decl, n, p);
29192
+ add(p.childForFieldName("name").text, kind3, decl, n, p);
29137
29193
  } else if (bound && (p.type === "public_field_definition" || p.type === "field_definition")) {
29138
29194
  const nameNode = p.childForFieldName("name") ?? p.childForFieldName("property");
29139
- if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind2, extentOf(p), n, p, p);
29195
+ if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind3, extentOf(p), n, p, p);
29140
29196
  } else if (bound && p.type === "pair") {
29141
29197
  const key = p.childForFieldName("key");
29142
- if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind2, p, n, p);
29198
+ if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind3, p, n, p);
29143
29199
  } else if (p.type === "arguments" && moduleCall(p.parent)) {
29144
29200
  const call = p.parent;
29145
29201
  const route = p.namedChildren[0];
29146
29202
  const quoted = route && route.id !== n.id && route.type === "string" ? unquote2(route.text) : null;
29147
29203
  const path = quoted && /^[\w/:.{}*-]{1,60}$/.test(quoted) ? quoted : null;
29148
29204
  const callee = call.childForFieldName("function").text;
29149
- add(path ? `${callee} ${path}` : callee, kind2, call.parent, n, call);
29205
+ add(path ? `${callee} ${path}` : callee, kind3, call.parent, n, call);
29150
29206
  }
29151
29207
  }
29152
29208
  for (const c of n.namedChildren) visit(c);
@@ -29423,18 +29479,18 @@ var STABLE_EXPRESSION = (t) => {
29423
29479
  const root = t.split(".")[0];
29424
29480
  return root === "this" || root === "self" || /^[A-Z]/.test(root);
29425
29481
  };
29426
- function argResource(kind, arg) {
29427
- if (!arg) return { kind, name: null, confidence: "unknown" };
29482
+ function argResource(kind2, arg) {
29483
+ if (!arg) return { kind: kind2, name: null, confidence: "unknown" };
29428
29484
  if (arg.literal !== null) {
29429
29485
  const n = literalName(arg.literal);
29430
- return n ? { kind, name: n.name, confidence: n.confidence } : { kind, name: null, confidence: "unknown" };
29486
+ return n ? { kind: kind2, name: n.name, confidence: n.confidence } : { kind: kind2, name: null, confidence: "unknown" };
29431
29487
  }
29432
- if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind, name: arg.text, confidence: "expression" };
29488
+ if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind: kind2, name: arg.text, confidence: "expression" };
29433
29489
  const keyed = keyedCall(arg.text);
29434
- return keyed ? { kind, name: keyed, confidence: "expression" } : { kind, name: null, confidence: "unknown" };
29490
+ return keyed ? { kind: kind2, name: keyed, confidence: "expression" } : { kind: kind2, name: null, confidence: "unknown" };
29435
29491
  }
29436
- function keyedCall(text) {
29437
- const t = text.trim();
29492
+ function keyedCall(text2) {
29493
+ const t = text2.trim();
29438
29494
  const open = t.indexOf("(");
29439
29495
  if (open <= 0 || !t.endsWith(")")) return null;
29440
29496
  const callee = t.slice(0, open);
@@ -29468,16 +29524,16 @@ var SQL_TABLE = [
29468
29524
  [/\bfrom\s+[`"[]?([\w.]+)/i, "read"]
29469
29525
  ];
29470
29526
  function sqlLiteral(c) {
29471
- const text = c.args.find((a) => a.literal !== null && SQL.test(a.literal))?.literal;
29472
- if (!text) return null;
29527
+ const text2 = c.args.find((a) => a.literal !== null && SQL.test(a.literal))?.literal;
29528
+ if (!text2) return null;
29473
29529
  for (const [re, op] of SQL_TABLE) {
29474
- const m = re.exec(text);
29530
+ const m = re.exec(text2);
29475
29531
  if (m) {
29476
29532
  const name2 = m[1].split(".").pop();
29477
- 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) };
29478
29534
  }
29479
29535
  }
29480
- 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" };
29481
29537
  }
29482
29538
  var SB_WRITE = /* @__PURE__ */ new Set(["insert", "update", "upsert", "delete"]);
29483
29539
  var SB_FROM = /\bfrom\(\s*(['"`])([\w.-]+)\1\s*\)\s*$/;
@@ -29873,28 +29929,28 @@ var ALIAS_OF = "alias-of:";
29873
29929
  var FIELD_OF = "field-of:";
29874
29930
  var IDENT_CHAR = /[\w$]/;
29875
29931
  var isIdent = (s) => /^[A-Za-z_$][\w$]*$/.test(s);
29876
- function wordAt(text, word) {
29932
+ function wordAt(text2, word) {
29877
29933
  const out2 = [];
29878
- for (let i2 = text.indexOf(word); i2 >= 0; i2 = text.indexOf(word, i2 + 1)) {
29879
- 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;
29880
29936
  out2.push(i2);
29881
29937
  }
29882
29938
  return out2;
29883
29939
  }
29884
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"]);
29885
- function typeAt(text, i2, lang) {
29941
+ function typeAt(text2, i2, lang) {
29886
29942
  let j = i2;
29887
29943
  const skip = () => {
29888
- while (j < text.length && /[\s?*&]/.test(text[j])) j++;
29944
+ while (j < text2.length && /[\s?*&]/.test(text2[j])) j++;
29889
29945
  };
29890
29946
  skip();
29891
- 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)) {
29892
29948
  j += kw.length;
29893
29949
  skip();
29894
29950
  }
29895
29951
  let k = j;
29896
- while (k < text.length && /[\w$.]/.test(text[k])) k++;
29897
- 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() ?? "";
29898
29954
  if (lang === "go") return /^[A-Za-z_]\w*$/.test(name2) && !GO_NOT_TYPES.has(name2) ? name2 : null;
29899
29955
  return /^[A-Z][\w$]*$/.test(name2) ? name2 : null;
29900
29956
  }
@@ -30044,10 +30100,10 @@ function boundInGo(fnText, name2) {
30044
30100
  const brace = fnText.indexOf("{");
30045
30101
  return wordAt(brace < 0 ? fnText : fnText.slice(0, brace), name2).length > 0;
30046
30102
  }
30047
- function rebindsInGo(text, name2) {
30048
- for (const i2 of wordAt(text, name2)) {
30049
- const lineEnd = text.indexOf("\n", i2);
30050
- 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);
30051
30107
  const decl = rest.indexOf(":=");
30052
30108
  if (decl >= 0 && /^[\s\w,]*$/.test(rest.slice(0, decl))) return true;
30053
30109
  }
@@ -30273,15 +30329,15 @@ function importOf(content, lang, name2, receiver) {
30273
30329
  return null;
30274
30330
  }
30275
30331
  var TS_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
30276
- function parseJsonc(text) {
30332
+ function parseJsonc(text2) {
30277
30333
  let out2 = "";
30278
30334
  let inString = false;
30279
- for (let i2 = 0; i2 < text.length; i2++) {
30280
- const c = text[i2];
30335
+ for (let i2 = 0; i2 < text2.length; i2++) {
30336
+ const c = text2[i2];
30281
30337
  if (inString) {
30282
30338
  out2 += c;
30283
30339
  if (c === "\\") {
30284
- out2 += text[++i2] ?? "";
30340
+ out2 += text2[++i2] ?? "";
30285
30341
  continue;
30286
30342
  }
30287
30343
  if (c === '"') inString = false;
@@ -30292,14 +30348,14 @@ function parseJsonc(text) {
30292
30348
  out2 += c;
30293
30349
  continue;
30294
30350
  }
30295
- if (c === "/" && text[i2 + 1] === "/") {
30296
- while (i2 < text.length && text[i2] !== "\n") i2++;
30351
+ if (c === "/" && text2[i2 + 1] === "/") {
30352
+ while (i2 < text2.length && text2[i2] !== "\n") i2++;
30297
30353
  out2 += "\n";
30298
30354
  continue;
30299
30355
  }
30300
- if (c === "/" && text[i2 + 1] === "*") {
30356
+ if (c === "/" && text2[i2 + 1] === "*") {
30301
30357
  i2 += 2;
30302
- while (i2 < text.length && !(text[i2] === "*" && text[i2 + 1] === "/")) i2++;
30358
+ while (i2 < text2.length && !(text2[i2] === "*" && text2[i2 + 1] === "/")) i2++;
30303
30359
  i2++;
30304
30360
  continue;
30305
30361
  }
@@ -30508,36 +30564,36 @@ function definitionOf(input) {
30508
30564
  }
30509
30565
  var MAX_CALLER_SCAN_FILES = 60;
30510
30566
  var isWordChar2 = (c) => c !== void 0 && /[\w$]/.test(c);
30511
- function callStarts(text, name2) {
30567
+ function callStarts(text2, name2) {
30512
30568
  const out2 = [];
30513
- 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)) {
30514
30570
  let j = i2 + name2.length;
30515
- if (text[j] === "<") {
30571
+ if (text2[j] === "<") {
30516
30572
  let depth = 0;
30517
- for (; j < text.length; j++) {
30518
- if (text[j] === "<") depth++;
30519
- 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;
30520
30576
  }
30521
30577
  j++;
30522
30578
  }
30523
- if (text[j] === "(") out2.push({ index: i2, open: j });
30579
+ if (text2[j] === "(") out2.push({ index: i2, open: j });
30524
30580
  }
30525
30581
  return out2;
30526
30582
  }
30527
- function callsName(text, name2) {
30528
- const t = text.trim();
30583
+ function callsName(text2, name2) {
30584
+ const t = text2.trim();
30529
30585
  if (t.startsWith("//") || t.startsWith("*") || t.startsWith("/*") || t.startsWith("#")) return false;
30530
- for (const at of callStarts(text, name2)) {
30586
+ for (const at of callStarts(text2, name2)) {
30531
30587
  const i2 = at.index;
30532
- const spread = text.slice(Math.max(0, i2 - 3), i2) === "...";
30533
- 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;
30534
30590
  let depth = 0;
30535
30591
  let j = at.open;
30536
- for (; j < text.length; j++) {
30537
- if (text[j] === "(") depth++;
30538
- 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;
30539
30595
  }
30540
- const after = text.slice(j + 1).trimStart();
30596
+ const after = text2.slice(j + 1).trimStart();
30541
30597
  if (after.startsWith(":") || after.startsWith("{")) continue;
30542
30598
  return true;
30543
30599
  }
@@ -30627,11 +30683,11 @@ function callersOf(input) {
30627
30683
  if (seen.has(line2) || declared.has(line2)) continue;
30628
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));
30629
30685
  if (inside2) continue;
30630
- const text = lines[line2 - 1] ?? "";
30631
- 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;
30632
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];
30633
30689
  seen.add(line2);
30634
- 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 });
30635
30691
  }
30636
30692
  }
30637
30693
  }
@@ -30938,16 +30994,16 @@ ${m.accessors.map((x) => ` ${x.fn.path}:${x.fn.start.line} ${x.fn.qualified} \u
30938
30994
  return { ok: true, value: lines.join("\n") };
30939
30995
  };
30940
30996
  var KINDS = ["table", "cache", "file", "http", "queue", "service", "memory"];
30941
- function parseResource(text) {
30942
- const colon = text.indexOf(":");
30943
- const kind = colon > 0 ? text.slice(0, colon) : "";
30944
- if (KINDS.includes(kind)) return { kinds: [kind], name: text.slice(colon + 1) };
30945
- 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 };
30946
31002
  }
30947
31003
  var writersOfTool = async (ctx, args2) => {
30948
- const text = str(args2.resource, 300, "resource");
30949
- if (!text.ok) return text;
30950
- 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);
30951
31007
  if (name2.length < 2) return { ok: false, error: "resource name too short to search for" };
30952
31008
  const deadline = Date.now() + TOOL_MS;
30953
31009
  const src = source(ctx);
@@ -30986,7 +31042,7 @@ var writersOfTool = async (ctx, args2) => {
30986
31042
  if (files.size > 25) truncated = true;
30987
31043
  const list2 = (xs) => xs.length ? xs.slice(0, MAX_LIST).map((x) => ` ${x}`).join("\n") + (xs.length > MAX_LIST ? `
30988
31044
  \u2026 ${xs.length - MAX_LIST} more` : "") : " none found";
30989
- 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" : ""}
30990
31046
  writers:
30991
31047
  ${list2(writers)}
30992
31048
  readers:
@@ -31044,9 +31100,9 @@ function validateRepoPath(value, { allowRoot = false } = {}) {
31044
31100
  function lineNumber(value, fallback) {
31045
31101
  return typeof value === "number" && Number.isInteger(value) && value >= 1 ? value : fallback;
31046
31102
  }
31047
- function capOutput(text) {
31048
- return text.length > TOOL_LIMITS.outputChars ? `${text.slice(0, TOOL_LIMITS.outputChars)}
31049
- [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;
31050
31106
  }
31051
31107
  function git(ctx, args2, opts = {}) {
31052
31108
  return runGit(ctx.root, args2, { timeoutMs: opts.timeoutMs ?? TOOL_LIMITS.gitTimeoutMs, maxBuffer: opts.maxBuffer ?? TOOL_LIMITS.fileBytes });
@@ -31180,8 +31236,8 @@ var listFilesTool = async (ctx, args2) => {
31180
31236
  \u2026 ${more} more` : ""}` : "no matching files" };
31181
31237
  };
31182
31238
  var searchTool = async (ctx, args2) => {
31183
- const text = args2.text;
31184
- 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)) {
31185
31241
  return { ok: false, error: `text must be 1-${TOOL_LIMITS.textChars} characters on one line` };
31186
31242
  }
31187
31243
  const glob = typeof args2.path_glob === "string" && args2.path_glob.length > 0 ? args2.path_glob : null;
@@ -31190,7 +31246,7 @@ var searchTool = async (ctx, args2) => {
31190
31246
  }
31191
31247
  const pathspec = glob ? [`:(glob)${glob}`] : [];
31192
31248
  const revision = ctx.range.kind === "push" ? [ctx.range.head] : ["--cached"];
31193
- 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]);
31194
31250
  if (!res.ok) {
31195
31251
  if (res.error === "failed" && res.stderr.trim() === "") return { ok: true, value: "no matches" };
31196
31252
  return { ok: false, error: gitFailure(res, "search") };
@@ -31324,10 +31380,10 @@ function writerExcerpts(codeMap, writers, read2, maxLines, maxChars, budget) {
31324
31380
  if (content === null) continue;
31325
31381
  const win = functionWindow(codeMap, w.file, content, w.line, maxLines);
31326
31382
  if (!win) continue;
31327
- const text = content.split("\n").slice(win.start_line - 1, win.end_line).join("\n").slice(0, maxChars);
31328
- if (used + text.length > budget) break;
31329
- used += text.length;
31330
- out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text });
31383
+ const text2 = content.split("\n").slice(win.start_line - 1, win.end_line).join("\n").slice(0, maxChars);
31384
+ if (used + text2.length > budget) break;
31385
+ used += text2.length;
31386
+ out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text: text2 });
31331
31387
  }
31332
31388
  return out2;
31333
31389
  }
@@ -31951,7 +32007,7 @@ async function workingMemory(run4) {
31951
32007
  const { opts } = run4;
31952
32008
  const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run4;
31953
32009
  let { reachability } = run4;
31954
- const memorySession = sessionDossier(token, sessionId ?? process.env.CLAUDE_SESSION_ID ?? null);
32010
+ const memorySession = sessionDossier(token, sessionId ?? envSessionId() ?? null);
31955
32011
  let memory2 = null;
31956
32012
  let incrementReport = null;
31957
32013
  if (memorySession) {
@@ -32224,7 +32280,7 @@ async function buildRequest(run4) {
32224
32280
  context: {
32225
32281
  agent_model: process.env.CLAUDE_MODEL ?? "unknown",
32226
32282
  agent_harness: "claude-code",
32227
- session_id: sessionId || process.env.CLAUDE_SESSION_ID || "unknown",
32283
+ session_id: sessionId || envSessionId() || "unknown",
32228
32284
  iteration,
32229
32285
  // Makes fleet composition falsifiable — without it, no adoption-gated
32230
32286
  // rollout decision can be checked against anything.
@@ -33434,12 +33490,41 @@ async function runAnalyze(opts, globals) {
33434
33490
  }
33435
33491
 
33436
33492
  // src/commands/baseline.ts
33437
- var import_node_fs55 = require("node:fs");
33438
- var import_node_path42 = require("node:path");
33493
+ var import_node_fs56 = require("node:fs");
33494
+ var import_node_path43 = require("node:path");
33439
33495
 
33440
- // src/lib/project-skills.ts
33496
+ // src/lib/skew-notice.ts
33441
33497
  var import_node_fs54 = require("node:fs");
33442
33498
  var import_node_path41 = require("node:path");
33499
+ var MARKER = ".skew-notice.json";
33500
+ function markerPath2() {
33501
+ return (0, import_node_path41.join)(verityHome(), MARKER);
33502
+ }
33503
+ function today(now) {
33504
+ const y = now.getFullYear();
33505
+ const m = String(now.getMonth() + 1).padStart(2, "0");
33506
+ const d = String(now.getDate()).padStart(2, "0");
33507
+ return `${y}-${m}-${d}`;
33508
+ }
33509
+ function skewNoticeDue(skew, now = /* @__PURE__ */ new Date()) {
33510
+ try {
33511
+ const seen = JSON.parse((0, import_node_fs54.readFileSync)(markerPath2(), "utf-8"));
33512
+ return !(seen.global === skew.global && seen.hooks === skew.hooks && seen.day === today(now));
33513
+ } catch {
33514
+ return true;
33515
+ }
33516
+ }
33517
+ function recordSkewNotice(skew, now = /* @__PURE__ */ new Date()) {
33518
+ try {
33519
+ (0, import_node_fs54.mkdirSync)(verityHome(), { recursive: true, mode: 448 });
33520
+ (0, import_node_fs54.writeFileSync)(markerPath2(), JSON.stringify({ global: skew.global, hooks: skew.hooks, day: today(now) }) + "\n");
33521
+ } catch {
33522
+ }
33523
+ }
33524
+
33525
+ // src/lib/project-skills.ts
33526
+ var import_node_fs55 = require("node:fs");
33527
+ var import_node_path42 = require("node:path");
33443
33528
  var PROJECT_SKILL_NAMES = [
33444
33529
  "verity-setup",
33445
33530
  "verity-analyze",
@@ -33465,14 +33550,14 @@ var LEGACY_SKILL_NAMES = [
33465
33550
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
33466
33551
  function staleProjectSkills() {
33467
33552
  const root = projectPath(".claude/skills");
33468
- if (!(0, import_node_fs54.existsSync)(root)) return [];
33469
- return ALL.filter((name2) => (0, import_node_fs54.existsSync)((0, import_node_path41.join)(root, name2)));
33553
+ if (!(0, import_node_fs55.existsSync)(root)) return [];
33554
+ return ALL.filter((name2) => (0, import_node_fs55.existsSync)((0, import_node_path42.join)(root, name2)));
33470
33555
  }
33471
33556
  function removeProjectSkills() {
33472
33557
  const root = projectPath(".claude/skills");
33473
33558
  const removed = [];
33474
33559
  for (const name2 of staleProjectSkills()) {
33475
- (0, import_node_fs54.rmSync)((0, import_node_path41.join)(root, name2), { recursive: true, force: true });
33560
+ (0, import_node_fs55.rmSync)((0, import_node_path42.join)(root, name2), { recursive: true, force: true });
33476
33561
  removed.push(name2);
33477
33562
  }
33478
33563
  return removed;
@@ -33492,20 +33577,22 @@ function registerBaselineCommands(program2) {
33492
33577
  if (!process.stdin.isTTY) {
33493
33578
  const input = (await readStdin()).trim();
33494
33579
  if (input) {
33495
- const event = parseHookEvent(input);
33580
+ const event = parseHookEvent2(input);
33496
33581
  if (opts.sessionId === void 0) sessionId = event.sessionId;
33497
33582
  if (opts.source === void 0) source2 = event.source;
33498
33583
  }
33499
33584
  }
33500
- const session = sessionId ?? validSessionId(process.env.CLAUDE_SESSION_ID);
33585
+ const session = sessionId ?? validSessionId(envSessionId());
33501
33586
  const cli = pluginCliInvocation();
33502
33587
  const skew = cliVersionSkew();
33503
33588
  const why = skew ? `the \`verity\` on PATH is ${skew.global} but the hooks run ${skew.hooks}, so it is not the CLI they use` : verityOnPath() ? "the `verity` on PATH is a separate install whose version could not be read" : "this machine has no `verity` on PATH \u2014 the plugin carries its own copy";
33504
33589
  const cliLine = cli ? `Verity CLI: ${why}. When a Verity skill tells you to run \`verity <args>\`, run \`${cli} <args>\` instead. Everything else about the command is identical.` : null;
33505
- const skewMsg = skew ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
33506
- const skewNote = skew ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. Until they have, do not send them to run \`verity login\` in a terminal: that runs the global one, which can sign this machine in to a different server.` : null;
33590
+ const skewLoud = !!skew && skewNoticeDue(skew);
33591
+ const skewMsg = skew && skewLoud ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
33592
+ const loginWarning = "Until they have, do not send them to run `verity login` in a terminal: that runs the global one, which can sign this machine in to a different server.";
33593
+ const skewNote = !skew ? null : skewLoud ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. ${loginWarning}` : `The user's global \`verity\` is ${skew.global} and the hooks run ${skew.hooks}; \`${skew.remedy}\` fixes it. They were already told today, so do not repeat it unprompted \u2014 mention it only where it matters, such as before suggesting a \`verity\` command for their terminal. ${loginWarning}`;
33507
33594
  if (!verityConfigured()) {
33508
- if (isMachineStore((0, import_node_path42.join)(repoRoot(), VERITY_DIR))) process.exit(0);
33595
+ if (isMachineStore((0, import_node_path43.join)(repoRoot(), VERITY_DIR))) process.exit(0);
33509
33596
  const how = isPluginInvocation() ? "Tell the user to run /verity:init \u2014 they type it; you cannot invoke it." : "Tell the user to run `verity init` in their terminal.";
33510
33597
  const lines = [
33511
33598
  `Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
@@ -33532,19 +33619,20 @@ function registerBaselineCommands(program2) {
33532
33619
  }
33533
33620
  }) + "\n"
33534
33621
  );
33622
+ if (skew && skewMsg) recordSkewNotice(skew);
33535
33623
  process.exit(0);
33536
33624
  }
33537
33625
  const realStart = source2 === void 0 || source2 === "startup" || source2 === "clear";
33538
33626
  let memoryMsg = null;
33539
33627
  let memoryAgentLine = null;
33540
33628
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
33541
- if (realStart && !(0, import_node_fs55.existsSync)(memoryNotice)) {
33629
+ if (realStart && !(0, import_node_fs56.existsSync)(memoryNotice)) {
33542
33630
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
33543
33631
  if (trackedGraph > 0) {
33544
33632
  memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
33545
33633
  memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
33546
33634
  try {
33547
- (0, import_node_fs55.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33635
+ (0, import_node_fs56.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33548
33636
  } catch {
33549
33637
  }
33550
33638
  }
@@ -33572,7 +33660,7 @@ function registerBaselineCommands(program2) {
33572
33660
  }
33573
33661
  }
33574
33662
  if (memoryAgentLine) notices.push(memoryAgentLine);
33575
- if (notices.length > 0) {
33663
+ if (notices.length > 0 || skewMsg) {
33576
33664
  process.stdout.write(
33577
33665
  JSON.stringify({
33578
33666
  ...userMsg || skewMsg || memoryMsg ? { systemMessage: [skewMsg, userMsg, memoryMsg].filter(Boolean).join("\n") } : {},
@@ -33582,6 +33670,7 @@ function registerBaselineCommands(program2) {
33582
33670
  }
33583
33671
  }) + "\n"
33584
33672
  );
33673
+ if (skew && skewMsg) recordSkewNotice(skew);
33585
33674
  }
33586
33675
  } else if (memoryMsg) {
33587
33676
  process.stdout.write(
@@ -33613,7 +33702,7 @@ function registerBaselineCommands(program2) {
33613
33702
  process.exit(0);
33614
33703
  });
33615
33704
  }
33616
- var MAX_HOOK_EVENT_BYTES = 64 * 1024;
33705
+ var MAX_HOOK_EVENT_BYTES2 = 64 * 1024;
33617
33706
  var HOOK_SOURCES = /* @__PURE__ */ new Set(["startup", "resume", "clear", "compact"]);
33618
33707
  var SESSION_ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
33619
33708
  async function readStdin() {
@@ -33621,11 +33710,11 @@ async function readStdin() {
33621
33710
  let size = 0;
33622
33711
  for await (const chunk of process.stdin) {
33623
33712
  size += chunk.length;
33624
- if (size <= MAX_HOOK_EVENT_BYTES) chunks.push(chunk);
33713
+ if (size <= MAX_HOOK_EVENT_BYTES2) chunks.push(chunk);
33625
33714
  }
33626
- return size > MAX_HOOK_EVENT_BYTES ? "" : Buffer.concat(chunks).toString("utf-8");
33715
+ return size > MAX_HOOK_EVENT_BYTES2 ? "" : Buffer.concat(chunks).toString("utf-8");
33627
33716
  }
33628
- function parseHookEvent(input) {
33717
+ function parseHookEvent2(input) {
33629
33718
  let event;
33630
33719
  try {
33631
33720
  event = JSON.parse(input);
@@ -33645,7 +33734,35 @@ function hookSource(value) {
33645
33734
  }
33646
33735
 
33647
33736
  // src/commands/review.ts
33648
- var import_node_fs56 = require("node:fs");
33737
+ var import_node_fs57 = require("node:fs");
33738
+ var import_node_path44 = require("node:path");
33739
+ function containReviewPaths(paths, base) {
33740
+ const kept = [];
33741
+ const refused2 = [];
33742
+ for (const raw of paths) {
33743
+ const candidate = (0, import_node_path44.isAbsolute)(raw) ? relativeForm(base, raw) : raw;
33744
+ if (candidate === "" || resolveInside(base, candidate) === null) refused2.push(raw);
33745
+ else kept.push(candidate);
33746
+ }
33747
+ return { kept, refused: refused2 };
33748
+ }
33749
+ function relativeForm(base, abs) {
33750
+ const lexical = (0, import_node_path44.relative)(base, abs);
33751
+ if (!(lexical === ".." || lexical.startsWith(`..${import_node_path44.sep}`) || (0, import_node_path44.isAbsolute)(lexical))) return lexical;
33752
+ try {
33753
+ let dir = (0, import_node_path44.dirname)(abs);
33754
+ let rest = (0, import_node_path44.basename)(abs);
33755
+ while (!(0, import_node_fs57.existsSync)(dir)) {
33756
+ const up = (0, import_node_path44.dirname)(dir);
33757
+ if (up === dir) return lexical;
33758
+ rest = (0, import_node_path44.join)((0, import_node_path44.basename)(dir), rest);
33759
+ dir = up;
33760
+ }
33761
+ return (0, import_node_path44.relative)((0, import_node_fs57.realpathSync)(base), (0, import_node_path44.join)((0, import_node_fs57.realpathSync)(dir), rest));
33762
+ } catch {
33763
+ return lexical;
33764
+ }
33765
+ }
33649
33766
  function registerReviewCommand(program2) {
33650
33767
  program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars); - reads it from stdin, so the words never pass through shell quoting").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
33651
33768
  const globals = program2.opts();
@@ -33664,11 +33781,23 @@ function registerReviewCommand(program2) {
33664
33781
  });
33665
33782
  }
33666
33783
  async function runReview(opts, globals) {
33667
- const allFiles = opts.files.split(",").map((f) => f.trim()).filter(Boolean);
33668
- const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
33784
+ const base = process.cwd();
33785
+ const files = containReviewPaths(opts.files.split(",").map((f) => f.trim()).filter(Boolean), base);
33786
+ const changed = opts.changed ? containReviewPaths(opts.changed.split(",").map((f) => f.trim()).filter(Boolean), base) : files;
33787
+ const refused2 = Array.from(/* @__PURE__ */ new Set([...files.refused, ...changed.refused]));
33788
+ if (refused2.length > 0) {
33789
+ printJsonCompact({
33790
+ gate_decision: "WARN",
33791
+ systemMessage: `Verity: refused ${refused2.length} path(s) outside this repository \u2014 nothing was reviewed. Pass paths inside the repository you run \`verity review\` from.`,
33792
+ refused_paths: refused2
33793
+ });
33794
+ process.exit(0);
33795
+ }
33796
+ const allFiles = files.kept;
33797
+ const changedFiles = changed.kept;
33669
33798
  const analyzable = filterAnalyzable(allFiles);
33670
33799
  const securityFiles = filterSecurity(allFiles);
33671
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs56.existsSync)(f) || resolveFile(f) !== null);
33800
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs57.existsSync)(f) || resolveFile(f) !== null);
33672
33801
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
33673
33802
  const codeDelta = collectCodeDelta(allFiles);
33674
33803
  const tokenResult = await resolveToken(globals.token);
@@ -33693,7 +33822,7 @@ async function runReview(opts, globals) {
33693
33822
  context: {
33694
33823
  agent_model: process.env.CLAUDE_MODEL ?? "unknown",
33695
33824
  agent_harness: "claude-code",
33696
- session_id: process.env.CLAUDE_SESSION_ID ?? "unknown",
33825
+ session_id: envSessionId() ?? "unknown",
33697
33826
  trigger: "review",
33698
33827
  iteration: 1
33699
33828
  }
@@ -33734,12 +33863,12 @@ async function runReview(opts, globals) {
33734
33863
  }
33735
33864
 
33736
33865
  // src/commands/guard.ts
33737
- var import_node_fs61 = require("node:fs");
33738
- var import_node_path48 = require("node:path");
33866
+ var import_node_fs63 = require("node:fs");
33867
+ var import_node_path51 = require("node:path");
33739
33868
 
33740
33869
  // src/lib/vendored.ts
33741
- var import_node_fs57 = require("node:fs");
33742
- var import_node_path43 = require("node:path");
33870
+ var import_node_fs58 = require("node:fs");
33871
+ var import_node_path45 = require("node:path");
33743
33872
  var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
33744
33873
  function dataDirOrNull() {
33745
33874
  try {
@@ -33754,7 +33883,7 @@ function shippedSkillFile(path, dataDir = dataDirOrNull()) {
33754
33883
  const [, skill, rel] = m;
33755
33884
  if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
33756
33885
  try {
33757
- return (0, import_node_fs57.readFileSync)((0, import_node_path43.join)(dataDir, "skills", skill, rel), "utf8");
33886
+ return (0, import_node_fs58.readFileSync)((0, import_node_path45.join)(dataDir, "skills", skill, rel), "utf8");
33758
33887
  } catch {
33759
33888
  return null;
33760
33889
  }
@@ -33863,8 +33992,33 @@ async function runAgentReview(options) {
33863
33992
  return { kind: "finished", response: finished.data };
33864
33993
  }
33865
33994
 
33995
+ // src/lib/effort.ts
33996
+ var import_node_fs59 = require("node:fs");
33997
+ var import_node_path46 = require("node:path");
33998
+ var import_yaml5 = __toESM2(require_dist());
33999
+ var EFFORT_PROFILES = {
34000
+ default: { pushDeadlineMs: 18e4, formal: { tier: "fast", maxRounds: 2, minScore: 0.7, costCapUsd: 1, maxTargets: 1, relaxedGates: false, dailyModels: 5, dailyCostUsd: 5 } },
34001
+ high: { pushDeadlineMs: 22e4, formal: { tier: "deep", maxRounds: 2, minScore: 0.6, costCapUsd: 2, maxTargets: 2, relaxedGates: false, dailyModels: 15, dailyCostUsd: 15 } },
34002
+ max: { pushDeadlineMs: 27e4, formal: { tier: "deep", maxRounds: 3, minScore: 0.5, costCapUsd: 4, maxTargets: 3, relaxedGates: true, dailyModels: 30, dailyCostUsd: 30 } }
34003
+ };
34004
+ function asEffort(value) {
34005
+ return value === "high" || value === "max" ? value : "default";
34006
+ }
34007
+ function resolveEffort(root, env = process.env) {
34008
+ if (env.VERITY_EFFORT) return asEffort(env.VERITY_EFFORT);
34009
+ try {
34010
+ const standard = (0, import_yaml5.parse)((0, import_node_fs59.readFileSync)((0, import_node_path46.join)(root, STANDARD_FILE), "utf8"));
34011
+ return asEffort(standard?.process_constraints?.git_moment_effort);
34012
+ } catch {
34013
+ return "default";
34014
+ }
34015
+ }
34016
+ function effortProfile(root, env = process.env) {
34017
+ return EFFORT_PROFILES[resolveEffort(root, env)];
34018
+ }
34019
+
33866
34020
  // src/lib/prove/auto.ts
33867
- var import_node_path47 = require("node:path");
34021
+ var import_node_path50 = require("node:path");
33868
34022
  var import_node_crypto19 = require("node:crypto");
33869
34023
 
33870
34024
  // src/lib/prove/signals.ts
@@ -33927,14 +34081,14 @@ function trackedSourceFiles(root, opts = {}) {
33927
34081
  return files.slice(0, opts.maxFiles ?? 5e3);
33928
34082
  }
33929
34083
  var EFFECT_LINE = /\bawait\b|\basync\s+with\b|\.then\(|\bsetTimeout\(|\bsetInterval\(|\bwith\s+\w[\w.]*\.(?:lock|acquire)\b|\bLock\(\)/;
33930
- function countEffects(text) {
34084
+ function countEffects(text2) {
33931
34085
  let n = 0;
33932
- for (const line2 of text.split("\n")) if (EFFECT_LINE.test(line2)) n++;
34086
+ for (const line2 of text2.split("\n")) if (EFFECT_LINE.test(line2)) n++;
33933
34087
  return n;
33934
34088
  }
33935
- function scanRisk(text) {
34089
+ function scanRisk(text2) {
33936
34090
  const counts = Object.fromEntries(RISK_PATTERNS.map(([c]) => [c, 0]));
33937
- for (const line2 of text.split("\n")) {
34091
+ for (const line2 of text2.split("\n")) {
33938
34092
  for (const [category, re] of RISK_PATTERNS) {
33939
34093
  if (re.test(line2)) counts[category]++;
33940
34094
  }
@@ -34228,13 +34382,13 @@ var lunaRanker = {
34228
34382
  signal: controller.signal
34229
34383
  });
34230
34384
  if (!res.ok) {
34231
- const text2 = await res.text().catch(() => "");
34232
- return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${text2.slice(0, 200)}`, ranked: fallback };
34385
+ const text3 = await res.text().catch(() => "");
34386
+ return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${text3.slice(0, 200)}`, ranked: fallback };
34233
34387
  }
34234
34388
  const data = await res.json();
34235
- const text = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
34236
- if (!text) return { ok: false, ranker: "luna", error: "no output_text in response", ranked: fallback };
34237
- const parsed = JSON.parse(text);
34389
+ const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
34390
+ if (!text2) return { ok: false, ranker: "luna", error: "no output_text in response", ranked: fallback };
34391
+ const parsed = JSON.parse(text2);
34238
34392
  const items = parsed.items.map((i2) => {
34239
34393
  const legacy = i2.critical === void 0 && i2.hazard === void 0 && i2.error_prone === void 0;
34240
34394
  const criteria = legacy ? { critical: Number(i2.score) || 0, hazard: Number(i2.score) || 0, error_prone: Number(i2.score) || 0 } : { critical: Number(i2.critical) || 0, hazard: Number(i2.hazard) || 0, error_prone: Number(i2.error_prone) || 0 };
@@ -34869,19 +35023,19 @@ var PURE_METHODS2 = /* @__PURE__ */ new Set([
34869
35023
  "test",
34870
35024
  "match"
34871
35025
  ]);
34872
- function callsOn(text, name2) {
35026
+ function callsOn(text2, name2) {
34873
35027
  const needle = `${name2}.`;
34874
- for (let i2 = text.indexOf(needle); i2 >= 0; i2 = text.indexOf(needle, i2 + 1)) {
34875
- if (i2 > 0 && IDENT_CHAR2.test(text[i2 - 1])) continue;
34876
- const call = CALL_AFTER_DOT.exec(text.slice(i2 + needle.length));
35028
+ for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
35029
+ if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
35030
+ const call = CALL_AFTER_DOT.exec(text2.slice(i2 + needle.length));
34877
35031
  if (call && !PURE_METHODS2.has(call[1])) return true;
34878
35032
  }
34879
35033
  return false;
34880
35034
  }
34881
- function callsDirect(text, name2) {
35035
+ function callsDirect(text2, name2) {
34882
35036
  const needle = `${name2}(`;
34883
- for (let i2 = text.indexOf(needle); i2 >= 0; i2 = text.indexOf(needle, i2 + 1)) {
34884
- if (i2 > 0 && IDENT_CHAR2.test(text[i2 - 1])) continue;
35037
+ for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
35038
+ if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
34885
35039
  return true;
34886
35040
  }
34887
35041
  return false;
@@ -34906,9 +35060,9 @@ function effectSites(numbered2) {
34906
35060
  const t = r.text.trim();
34907
35061
  if (!t || t.startsWith("//") || t.startsWith("#") || t.startsWith("*")) continue;
34908
35062
  const onParam = [...params].some((p) => callsOn(t, p) || callsDirect(t, p));
34909
- const kind = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
34910
- if (!kind) continue;
34911
- out2.push(`L${r.n} [${kind}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
35063
+ const kind2 = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
35064
+ if (!kind2) continue;
35065
+ out2.push(`L${r.n} [${kind2}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
34912
35066
  if (out2.length >= MAX_EFFECT_SITES) break;
34913
35067
  }
34914
35068
  return out2;
@@ -35037,11 +35191,11 @@ async function generateModel(target, opts) {
35037
35191
  return { ok: false, error: name2 === "TimeoutError" || name2 === "AbortError" ? "timed out" : err2.message };
35038
35192
  }
35039
35193
  const usage = data.usage ? { inputTokens: Number(data.usage.input_tokens ?? 0), outputTokens: Number(data.usage.output_tokens ?? 0) } : null;
35040
- const text = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
35041
- if (!text) return { ok: false, error: "no output_text in response", usage };
35194
+ const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
35195
+ if (!text2) return { ok: false, error: "no output_text in response", usage };
35042
35196
  let parsed;
35043
35197
  try {
35044
- parsed = JSON.parse(text);
35198
+ parsed = JSON.parse(text2);
35045
35199
  } catch {
35046
35200
  return { ok: false, error: "answer was not JSON", usage };
35047
35201
  }
@@ -35051,8 +35205,8 @@ async function generateModel(target, opts) {
35051
35205
  // src/lib/prove/replay.ts
35052
35206
  var MAX_SOURCE_BYTES = 96 * 1024;
35053
35207
  var MAX_MODEL_BYTES = 32 * 1024;
35054
- function numberLines(text, from = 1) {
35055
- return text.split("\n").map((l, i2) => `${String(i2 + from).padStart(5)}| ${l}`).join("\n");
35208
+ function numberLines(text2, from = 1) {
35209
+ return text2.split("\n").map((l, i2) => `${String(i2 + from).padStart(5)}| ${l}`).join("\n");
35056
35210
  }
35057
35211
  var PY_DECL = /^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(/;
35058
35212
  var TS_DECLS = [
@@ -35126,9 +35280,9 @@ function extractSymbolBody(source2, symbol, file, range) {
35126
35280
  }
35127
35281
  return null;
35128
35282
  }
35129
- function significantLines(text) {
35283
+ function significantLines(text2) {
35130
35284
  const out2 = [];
35131
- for (const raw of text.split("\n")) {
35285
+ for (const raw of text2.split("\n")) {
35132
35286
  const l = raw.trim();
35133
35287
  if (l.length < 12) continue;
35134
35288
  if (/^(\/\/|\/\*|\*|#)/.test(l)) continue;
@@ -35153,14 +35307,14 @@ function isTrackedInRoot(root, file) {
35153
35307
  function buildReplayBrief(root, report, property, modelSource, readSource) {
35154
35308
  const sources = (report.header?.abstracts ?? []).map((a) => {
35155
35309
  const read2 = readSource ? readSource(a.file, MAX_SOURCE_BYTES) : isTrackedInRoot(root, a.file) ? readRegularFileInRoot(root, a.file, MAX_SOURCE_BYTES) : { ok: false, reason: "not tracked by git \u2014 models may only abstract tracked source" };
35156
- const text = read2.ok ? read2.content : "";
35310
+ const text2 = read2.ok ? read2.content : "";
35157
35311
  return {
35158
35312
  file: a.file,
35159
35313
  symbol: a.symbol,
35160
- numbered: text ? numberLines(text) : `(could not read ${a.file}: ${read2.ok ? "" : read2.reason})`,
35161
- symbolBody: text ? extractSymbolBody(text, a.symbol, a.file, a.lines) : null,
35314
+ numbered: text2 ? numberLines(text2) : `(could not read ${a.file}: ${read2.ok ? "" : read2.reason})`,
35315
+ symbolBody: text2 ? extractSymbolBody(text2, a.symbol, a.file, a.lines) : null,
35162
35316
  lines: a.lines,
35163
- content: text
35317
+ content: text2
35164
35318
  };
35165
35319
  });
35166
35320
  return { model: report.model, property, modelSource: modelSource.slice(0, MAX_MODEL_BYTES), sources };
@@ -35242,7 +35396,7 @@ function parseReplayOutput(output) {
35242
35396
  let executedCalls = 0;
35243
35397
  const shellTexts = [];
35244
35398
  const outputTexts = [];
35245
- let text = null;
35399
+ let text2 = null;
35246
35400
  for (const item of output) {
35247
35401
  if (item.type === "shell_call") {
35248
35402
  shellCalls++;
@@ -35258,13 +35412,13 @@ function parseReplayOutput(output) {
35258
35412
  }
35259
35413
  } else if (item.type === "message" && Array.isArray(item.content)) {
35260
35414
  const t = item.content.find((c) => c.type === "output_text")?.text;
35261
- if (typeof t === "string") text = t;
35415
+ if (typeof t === "string") text2 = t;
35262
35416
  }
35263
35417
  }
35264
35418
  let claim = null;
35265
- if (text) {
35419
+ if (text2) {
35266
35420
  try {
35267
- const o = JSON.parse(text);
35421
+ const o = JSON.parse(text2);
35268
35422
  const verdict = o.verdict;
35269
35423
  if (verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable") {
35270
35424
  claim = {
@@ -35551,9 +35705,9 @@ async function runReplay(brief, opts) {
35551
35705
  if (opts.auth) return runReplayViaServer(brief, opts.auth, opts.timeoutMs);
35552
35706
  const env = opts.env ?? process.env;
35553
35707
  const none = { covered: 0, total: 0, ratio: 0, basis: "none" };
35554
- const refuse = (error) => ({ claimed: null, verdict: "unverified", reason: "", downgrade: error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: 0, containerId: null, error });
35555
- if (env.VERITY_PROVE_DIRECT !== "1") return refuse("not logged in (run `verity login`); replays run on the Verity service");
35556
- if (!opts.apiKey) return refuse("OPENAI_API_KEY is not set");
35708
+ const refuse2 = (error) => ({ claimed: null, verdict: "unverified", reason: "", downgrade: error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: 0, containerId: null, error });
35709
+ if (env.VERITY_PROVE_DIRECT !== "1") return refuse2("not logged in (run `verity login`); replays run on the Verity service");
35710
+ if (!opts.apiKey) return refuse2("OPENAI_API_KEY is not set");
35557
35711
  return runReplayInContainer(brief, { apiKey: opts.apiKey, model: opts.model, timeoutMs: opts.timeoutMs, maxRounds: opts.maxRounds, fetchImpl: opts.fetchImpl });
35558
35712
  }
35559
35713
  function renderReplay(model, property, r) {
@@ -35591,18 +35745,18 @@ function renderReplay(model, property, r) {
35591
35745
  // src/lib/prove/runner.ts
35592
35746
  var import_node_child_process15 = require("node:child_process");
35593
35747
  var import_node_os8 = require("node:os");
35594
- var import_node_fs60 = require("node:fs");
35748
+ var import_node_fs62 = require("node:fs");
35595
35749
  var import_node_os9 = require("node:os");
35596
- var import_node_path46 = require("node:path");
35750
+ var import_node_path49 = require("node:path");
35597
35751
 
35598
35752
  // src/lib/prove/scaffold.ts
35599
- var import_node_fs59 = require("node:fs");
35600
- var import_node_path45 = require("node:path");
35753
+ var import_node_fs61 = require("node:fs");
35754
+ var import_node_path48 = require("node:path");
35601
35755
 
35602
35756
  // src/lib/prove/safe-write.ts
35603
- var import_node_fs58 = require("node:fs");
35757
+ var import_node_fs60 = require("node:fs");
35604
35758
  var import_node_crypto15 = require("node:crypto");
35605
- var import_node_path44 = require("node:path");
35759
+ var import_node_path47 = require("node:path");
35606
35760
  var SafeWriteError = class extends Error {
35607
35761
  constructor(reason, path) {
35608
35762
  super(`refusing to write ${path}: ${reason}`);
@@ -35611,10 +35765,10 @@ var SafeWriteError = class extends Error {
35611
35765
  this.name = "SafeWriteError";
35612
35766
  }
35613
35767
  };
35614
- var FLAGS3 = import_node_fs58.constants;
35768
+ var FLAGS3 = import_node_fs60.constants;
35615
35769
  var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
35616
35770
  function assertPlainRelative(rel) {
35617
- if (!rel || (0, import_node_path44.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35771
+ if (!rel || (0, import_node_path47.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35618
35772
  for (const part of rel.split(/[\\/]/)) {
35619
35773
  if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
35620
35774
  }
@@ -35623,34 +35777,34 @@ function ensureDirsNoFollow(root, rel) {
35623
35777
  const parts2 = rel.split(/[\\/]/);
35624
35778
  let cur = root;
35625
35779
  for (const part of parts2.slice(0, -1)) {
35626
- cur = (0, import_node_path44.join)(cur, part);
35780
+ cur = (0, import_node_path47.join)(cur, part);
35627
35781
  let st;
35628
35782
  try {
35629
- st = (0, import_node_fs58.lstatSync)(cur);
35783
+ st = (0, import_node_fs60.lstatSync)(cur);
35630
35784
  } catch {
35631
- (0, import_node_fs58.mkdirSync)(cur);
35785
+ (0, import_node_fs60.mkdirSync)(cur);
35632
35786
  continue;
35633
35787
  }
35634
35788
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
35635
35789
  if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
35636
35790
  }
35637
- return (0, import_node_path44.join)(root, rel);
35791
+ return (0, import_node_path47.join)(root, rel);
35638
35792
  }
35639
35793
  function insideRoot(realRoot, realPath) {
35640
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path44.sep) ? realRoot : realRoot + import_node_path44.sep);
35794
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path47.sep) ? realRoot : realRoot + import_node_path47.sep);
35641
35795
  }
35642
35796
  function removeQuietly(path) {
35643
35797
  try {
35644
- (0, import_node_fs58.unlinkSync)(path);
35798
+ (0, import_node_fs60.unlinkSync)(path);
35645
35799
  } catch {
35646
35800
  }
35647
35801
  }
35648
35802
  function writeFileInRootNoFollow(root, rel, content) {
35649
35803
  assertPlainRelative(rel);
35650
35804
  const dest = ensureDirsNoFollow(root, rel);
35651
- const dir = (0, import_node_path44.dirname)(dest);
35805
+ const dir = (0, import_node_path47.dirname)(dest);
35652
35806
  try {
35653
- const st = (0, import_node_fs58.lstatSync)(dest);
35807
+ const st = (0, import_node_fs60.lstatSync)(dest);
35654
35808
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
35655
35809
  if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
35656
35810
  } catch (err2) {
@@ -35658,41 +35812,41 @@ function writeFileInRootNoFollow(root, rel, content) {
35658
35812
  }
35659
35813
  let realRoot;
35660
35814
  try {
35661
- realRoot = (0, import_node_fs58.realpathSync)(root);
35815
+ realRoot = (0, import_node_fs60.realpathSync)(root);
35662
35816
  } catch {
35663
35817
  throw new SafeWriteError("unwritable", root);
35664
35818
  }
35665
- const tmp = (0, import_node_path44.join)(dir, `.${(0, import_node_path44.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35819
+ const tmp = (0, import_node_path47.join)(dir, `.${(0, import_node_path47.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35666
35820
  let fd;
35667
35821
  try {
35668
- fd = (0, import_node_fs58.openSync)(tmp, import_node_fs58.constants.O_WRONLY | import_node_fs58.constants.O_CREAT | import_node_fs58.constants.O_EXCL | NOFOLLOW2, 420);
35822
+ fd = (0, import_node_fs60.openSync)(tmp, import_node_fs60.constants.O_WRONLY | import_node_fs60.constants.O_CREAT | import_node_fs60.constants.O_EXCL | NOFOLLOW2, 420);
35669
35823
  } catch {
35670
35824
  throw new SafeWriteError("unwritable", tmp);
35671
35825
  }
35672
35826
  try {
35673
- const opened = (0, import_node_fs58.fstatSync)(fd, { bigint: true });
35827
+ const opened = (0, import_node_fs60.fstatSync)(fd, { bigint: true });
35674
35828
  let realTmp;
35675
35829
  try {
35676
- realTmp = (0, import_node_fs58.realpathSync)(tmp);
35830
+ realTmp = (0, import_node_fs60.realpathSync)(tmp);
35677
35831
  } catch {
35678
35832
  throw new SafeWriteError("escaped", tmp);
35679
35833
  }
35680
- const there = (0, import_node_fs58.lstatSync)(realTmp, { bigint: true });
35834
+ const there = (0, import_node_fs60.lstatSync)(realTmp, { bigint: true });
35681
35835
  if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
35682
35836
  throw new SafeWriteError("escaped", tmp);
35683
35837
  }
35684
35838
  const buf = Buffer.from(content, "utf-8");
35685
35839
  let off = 0;
35686
- while (off < buf.length) off += (0, import_node_fs58.writeSync)(fd, buf, off, buf.length - off);
35840
+ while (off < buf.length) off += (0, import_node_fs60.writeSync)(fd, buf, off, buf.length - off);
35687
35841
  } catch (err2) {
35688
- (0, import_node_fs58.closeSync)(fd);
35842
+ (0, import_node_fs60.closeSync)(fd);
35689
35843
  removeQuietly(tmp);
35690
35844
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
35691
35845
  }
35692
- (0, import_node_fs58.closeSync)(fd);
35846
+ (0, import_node_fs60.closeSync)(fd);
35693
35847
  try {
35694
- if (!insideRoot(realRoot, (0, import_node_fs58.realpathSync)(dir)) || (0, import_node_fs58.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35695
- (0, import_node_fs58.renameSync)(tmp, dest);
35848
+ if (!insideRoot(realRoot, (0, import_node_fs60.realpathSync)(dir)) || (0, import_node_fs60.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35849
+ (0, import_node_fs60.renameSync)(tmp, dest);
35696
35850
  } catch (err2) {
35697
35851
  removeQuietly(tmp);
35698
35852
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
@@ -35706,9 +35860,9 @@ function pathHasNoLink(root, rel) {
35706
35860
  }
35707
35861
  let cur = root;
35708
35862
  for (const part of rel.split(/[\\/]/)) {
35709
- cur = cur + import_node_path44.sep + part;
35863
+ cur = cur + import_node_path47.sep + part;
35710
35864
  try {
35711
- if ((0, import_node_fs58.lstatSync)(cur).isSymbolicLink()) return false;
35865
+ if ((0, import_node_fs60.lstatSync)(cur).isSymbolicLink()) return false;
35712
35866
  } catch {
35713
35867
  return true;
35714
35868
  }
@@ -36018,20 +36172,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
36018
36172
  never committed; what reaches the team is the bug report and the fix.
36019
36173
  `;
36020
36174
  function scaffoldProofs(root) {
36021
- const proofsDir = (0, import_node_path45.join)(root, PROOFS_DIR);
36175
+ const proofsDir = (0, import_node_path48.join)(root, PROOFS_DIR);
36022
36176
  const written = [];
36023
36177
  const kept = [];
36024
36178
  for (const stray of ["lakefile.lean"]) {
36025
36179
  const rel = `${PROOFS_DIR}/${stray}`;
36026
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36180
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
36027
36181
  try {
36028
- (0, import_node_fs59.rmSync)((0, import_node_path45.join)(root, rel), { force: true });
36182
+ (0, import_node_fs61.rmSync)((0, import_node_path48.join)(root, rel), { force: true });
36029
36183
  } catch {
36030
36184
  }
36031
36185
  }
36032
36186
  for (const f of PROOFS_TEMPLATE_FILES) {
36033
36187
  const rel = `${PROOFS_DIR}/${f.path}`;
36034
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36188
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
36035
36189
  const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
36036
36190
  if (current.ok && current.content === f.content) {
36037
36191
  kept.push(rel);
@@ -36044,8 +36198,8 @@ function scaffoldProofs(root) {
36044
36198
  [`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
36045
36199
  [`${MODELS_DIR}/README.md`, MODELS_README]
36046
36200
  ]) {
36047
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36048
- if (existsNoFollow((0, import_node_path45.join)(root, rel))) {
36201
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
36202
+ if (existsNoFollow((0, import_node_path48.join)(root, rel))) {
36049
36203
  kept.push(rel);
36050
36204
  continue;
36051
36205
  }
@@ -36056,7 +36210,7 @@ function scaffoldProofs(root) {
36056
36210
  }
36057
36211
  function existsNoFollow(abs) {
36058
36212
  try {
36059
- (0, import_node_fs59.lstatSync)(abs);
36213
+ (0, import_node_fs61.lstatSync)(abs);
36060
36214
  return true;
36061
36215
  } catch {
36062
36216
  return false;
@@ -36135,12 +36289,12 @@ function parseHeader(obj) {
36135
36289
  function parseProperty(obj) {
36136
36290
  const model = ident(obj.model);
36137
36291
  const id = ident(obj.id);
36138
- const kind = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
36292
+ const kind2 = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
36139
36293
  const result = typeof obj.result === "string" && RESULTS.has(obj.result) ? obj.result : null;
36140
36294
  const source2 = obj.source === void 0 ? "" : str2(obj.source, LIMITS.text);
36141
36295
  const desc = obj.desc === void 0 ? "" : str2(obj.desc, LIMITS.text);
36142
- if (!model || !id || !kind || !result || source2 === null || desc === null) return null;
36143
- const p = { model, id, kind, source: source2, desc, result };
36296
+ if (!model || !id || !kind2 || !result || source2 === null || desc === null) return null;
36297
+ const p = { model, id, kind: kind2, source: source2, desc, result };
36144
36298
  if (obj.bound !== void 0) {
36145
36299
  const n = nat(obj.bound);
36146
36300
  if (n === null) return null;
@@ -36314,17 +36468,17 @@ function renderReport(r) {
36314
36468
 
36315
36469
  // src/lib/prove/runner.ts
36316
36470
  function verityLeanHome(env = process.env) {
36317
- return env.VERITY_LEAN_HOME ?? (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36471
+ return env.VERITY_LEAN_HOME ?? (0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36318
36472
  }
36319
36473
  function findToolchain(env = process.env) {
36320
- const managedBin = (0, import_node_path46.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
36321
- const elanBin = (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
36322
- const elanHas = (0, import_node_fs60.existsSync)((0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
36323
- const userPath = (env.PATH ?? "").split(import_node_path46.delimiter).filter((d) => d && (elanHas || (0, import_node_path46.resolve)(d) !== (0, import_node_path46.resolve)(elanBin)));
36324
- const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path46.delimiter);
36474
+ const managedBin = (0, import_node_path49.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
36475
+ const elanBin = (0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
36476
+ const elanHas = (0, import_node_fs62.existsSync)((0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
36477
+ const userPath = (env.PATH ?? "").split(import_node_path49.delimiter).filter((d) => d && (elanHas || (0, import_node_path49.resolve)(d) !== (0, import_node_path49.resolve)(elanBin)));
36478
+ const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path49.delimiter);
36325
36479
  const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
36326
36480
  const exe = process.platform === "win32" ? "lake.exe" : "lake";
36327
- const candidates2 = [(0, import_node_path46.join)(managedBin, exe), ...elanHas ? [(0, import_node_path46.join)(elanBin, exe)] : [], exe];
36481
+ const candidates2 = [(0, import_node_path49.join)(managedBin, exe), ...elanHas ? [(0, import_node_path49.join)(elanBin, exe)] : [], exe];
36328
36482
  for (const candidate of candidates2) {
36329
36483
  try {
36330
36484
  (0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
@@ -36403,7 +36557,7 @@ function proofsWorkspaceProblem(root) {
36403
36557
  for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
36404
36558
  let st;
36405
36559
  try {
36406
- st = (0, import_node_fs60.lstatSync)((0, import_node_path46.join)(root, rel));
36560
+ st = (0, import_node_fs62.lstatSync)((0, import_node_path49.join)(root, rel));
36407
36561
  } catch {
36408
36562
  break;
36409
36563
  }
@@ -36423,44 +36577,44 @@ function refused(problem) {
36423
36577
  function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36424
36578
  const problem = proofsWorkspaceProblem(root);
36425
36579
  if (problem) return refused(problem);
36426
- return run2(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36580
+ return run2(tc, (0, import_node_path49.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36427
36581
  }
36428
36582
  async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36429
36583
  const problem = proofsWorkspaceProblem(root);
36430
36584
  if (problem) return refused(problem);
36431
- return runAsync(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36585
+ return runAsync(tc, (0, import_node_path49.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36432
36586
  }
36433
36587
  function isModelInRoot(modelsAbs, rel) {
36434
- if (!rel.endsWith(".lean") || (0, import_node_path46.isAbsolute)(rel) || rel.startsWith("..")) return false;
36588
+ if (!rel.endsWith(".lean") || (0, import_node_path49.isAbsolute)(rel) || rel.startsWith("..")) return false;
36435
36589
  return statRegularInRoot(modelsAbs, rel).ok;
36436
36590
  }
36437
36591
  function resolveModelFile(root, arg) {
36438
- const modelsAbs = (0, import_node_path46.join)(root, MODELS_DIR);
36439
- const asPath = (0, import_node_path46.relative)(modelsAbs, (0, import_node_path46.isAbsolute)(arg) ? arg : (0, import_node_path46.resolve)(root, arg));
36592
+ const modelsAbs = (0, import_node_path49.join)(root, MODELS_DIR);
36593
+ const asPath = (0, import_node_path49.relative)(modelsAbs, (0, import_node_path49.isAbsolute)(arg) ? arg : (0, import_node_path49.resolve)(root, arg));
36440
36594
  const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
36441
36595
  for (const rel of candidates2) {
36442
- if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path46.join)(modelsAbs, rel);
36596
+ if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path49.join)(modelsAbs, rel);
36443
36597
  }
36444
36598
  return null;
36445
36599
  }
36446
36600
  function listModelFiles(root) {
36447
- const modelsAbs = (0, import_node_path46.join)(root, MODELS_DIR);
36448
- if (!(0, import_node_fs60.existsSync)(modelsAbs)) return [];
36449
- return (0, import_node_fs60.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path46.join)(modelsAbs, f));
36601
+ const modelsAbs = (0, import_node_path49.join)(root, MODELS_DIR);
36602
+ if (!(0, import_node_fs62.existsSync)(modelsAbs)) return [];
36603
+ return (0, import_node_fs62.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path49.join)(modelsAbs, f));
36450
36604
  }
36451
- function trimDiagnostics(text) {
36452
- return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36605
+ function trimDiagnostics(text2) {
36606
+ return text2.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36453
36607
  }
36454
36608
  function checkModel(tc, root, modelFile, opts = {}) {
36455
- const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36456
- const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36609
+ const proofsAbs = (0, import_node_path49.join)(root, PROOFS_DIR);
36610
+ const rel = (0, import_node_path49.relative)(proofsAbs, modelFile);
36457
36611
  const problem = proofsWorkspaceProblem(root);
36458
36612
  const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36459
36613
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36460
36614
  }
36461
36615
  async function checkModelAsync(tc, root, modelFile, opts = {}) {
36462
- const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36463
- const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36616
+ const proofsAbs = (0, import_node_path49.join)(root, PROOFS_DIR);
36617
+ const rel = (0, import_node_path49.relative)(proofsAbs, modelFile);
36464
36618
  const problem = proofsWorkspaceProblem(root);
36465
36619
  const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36466
36620
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
@@ -36469,10 +36623,10 @@ function toReport(res, root, modelFile, timeoutMs) {
36469
36623
  const parsed = parseVerityLines(res.stdout);
36470
36624
  const combined = `${res.stdout}
36471
36625
  ${res.stderr}`;
36472
- const name2 = parsed.header?.model ?? (0, import_node_path46.basename)(modelFile, ".lean");
36626
+ const name2 = parsed.header?.model ?? (0, import_node_path49.basename)(modelFile, ".lean");
36473
36627
  const report = {
36474
36628
  model: name2,
36475
- file: (0, import_node_path46.relative)(root, modelFile),
36629
+ file: (0, import_node_path49.relative)(root, modelFile),
36476
36630
  ok: res.ok,
36477
36631
  header: parsed.header,
36478
36632
  properties: parsed.properties,
@@ -36517,33 +36671,70 @@ function writeResult(root, report) {
36517
36671
  function isCrashTrace(trace) {
36518
36672
  return trace.some((s) => /\b(crash\w*|kill\w*|restart\w*|interrupt\w*|power|abort\w*|process (dies|exit\w*)|lost (reply|response))\b/i.test(s));
36519
36673
  }
36674
+ function formalDisposition(f) {
36675
+ if (f.verdict !== "reproduced" || f.waived) return "none";
36676
+ const c = f.check;
36677
+ if (!c || c.outcome !== "answered") return "block";
36678
+ switch (c.verdict) {
36679
+ case "REAL":
36680
+ return c.introduced === "no" ? "report" : "block";
36681
+ case "REAL-LOW":
36682
+ return "report";
36683
+ case "PREVENTED":
36684
+ case "ARTIFACT":
36685
+ return "checked";
36686
+ default:
36687
+ return "block";
36688
+ }
36689
+ }
36690
+ var CAUTION = { block: 3, report: 2, checked: 1, none: 0 };
36691
+ function cautiousCheck(f, checks) {
36692
+ if (checks.length === 0) return void 0;
36693
+ let chosen = checks[0];
36694
+ for (const c of checks.slice(1)) if (CAUTION[formalDisposition({ ...f, check: c })] > CAUTION[formalDisposition({ ...f, check: chosen })]) chosen = c;
36695
+ return { ...chosen, votes: checks.map((c) => c.outcome === "answered" && c.verdict ? c.verdict : c.outcome), costUsd: checks.reduce((n, c) => n + c.costUsd, 0), unpriced: checks.reduce((n, c) => n + c.unpriced, 0) };
36696
+ }
36697
+ function checkLine(f) {
36698
+ const c = f.check;
36699
+ if (!c || c.outcome !== "answered" || !c.verdict) return "";
36700
+ const why = c.verdict === "PREVENTED" ? c.preventedBy || c.reason : c.reason;
36701
+ const from = c.trigger ? ` Reached from: ${c.trigger}.` : "";
36702
+ const pre = c.introduced === "no" ? " Already possible before this change." : "";
36703
+ const votes = c.votes && c.votes.length > 1 ? ` (${c.votes.length} checks: ${c.votes.join(", ")})` : "";
36704
+ return `Checked: ${c.verdict}${votes}.${from}${pre} ${why ?? ""}`.trim();
36705
+ }
36520
36706
  function mergeFormalFindings(response, outcome, pushedFiles) {
36521
- if (!outcome) return { blocking: 0 };
36522
- const norm2 = (p) => p.replace(/\\/g, "/");
36523
- const pushed = new Set(pushedFiles.map(norm2));
36524
- const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
36525
- if (blocking.length === 0) return { blocking: 0 };
36707
+ if (!outcome) return { blocking: 0, reported: 0 };
36708
+ const norm3 = (p) => p.replace(/\\/g, "/");
36709
+ const pushed = new Set(pushedFiles.map(norm3));
36710
+ const onPush = outcome.findings.filter((f) => pushed.has(norm3(f.file)));
36711
+ const blocking = onPush.filter((f) => formalDisposition(f) === "block");
36712
+ const reported = onPush.filter((f) => formalDisposition(f) === "report");
36713
+ if (blocking.length === 0 && reported.length === 0) return { blocking: 0, reported: 0 };
36526
36714
  const existing = Array.isArray(response.findings) ? response.findings : [];
36527
- response.findings = [
36528
- ...existing,
36529
- ...blocking.map((f) => ({
36715
+ const asFinding = (f, blocks) => {
36716
+ const checked = checkLine(f);
36717
+ return {
36530
36718
  pattern_id: "formal-counterexample",
36531
- severity: "high",
36532
- scope: "change",
36719
+ severity: blocks ? "high" : "medium",
36720
+ // A bug this change did not introduce is filed the way the gate files everything it will not block on.
36721
+ scope: f.check?.introduced === "no" && !blocks ? "pre-existing" : "change",
36533
36722
  file: f.file,
36534
36723
  line: outcome.target?.lines?.from ?? null,
36535
36724
  // Worded as the VIOLATION: the property text is what should hold, and
36536
36725
  // as a title it read backwards (e2e, 2026-09-26). A trace that needs a
36537
36726
  // crash between two writes is labelled: reproducing it means injecting
36538
36727
  // the crash, so it is a crash-consistency finding, not a race.
36539
- 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`,
36540
- description: terminalText(f.reason ?? "", 2e3),
36728
+ title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code${f.check?.outcome === "answered" ? `, checked ${f.check.verdict}` : ""}`,
36729
+ description: terminalText([f.reason ?? "", checked].filter(Boolean).join(" "), 2e3),
36541
36730
  fix: { description: `Trace: ${terminalText(f.trace.join(" \u2192 ") || "(initial state)", 2e3)}. Replay: ${terminalText(f.reason ?? "reproduced in the container", 2e3)}` },
36542
36731
  source: "formal"
36543
- }))
36544
- ];
36545
- if (response.gate_decision !== "FAIL") response.gate_decision = "FAIL";
36546
- return { blocking: blocking.length };
36732
+ };
36733
+ };
36734
+ response.findings = [...existing, ...blocking.map((f) => asFinding(f, true)), ...reported.map((f) => asFinding(f, false))];
36735
+ if (blocking.length > 0) response.gate_decision = "FAIL";
36736
+ else if (response.gate_decision === "PASS") response.gate_decision = "WARN";
36737
+ return { blocking: blocking.length, reported: reported.length };
36547
36738
  }
36548
36739
 
36549
36740
  // src/lib/prove/scalpel.ts
@@ -36717,15 +36908,15 @@ function nonNegative(v) {
36717
36908
  return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
36718
36909
  }
36719
36910
  function readLedger(root) {
36720
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
36721
- const empty = { day: today, models: 0, costUsd: 0 };
36911
+ const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
36912
+ const empty = { day: today2, models: 0, costUsd: 0 };
36722
36913
  if (!isLocalState(root, AUTO_LEDGER)) return empty;
36723
36914
  const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
36724
36915
  if (!read2.ok) return empty;
36725
36916
  try {
36726
36917
  const o = JSON.parse(read2.content);
36727
- if (o.day !== today || typeof o.models !== "number") return empty;
36728
- return { day: today, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
36918
+ if (o.day !== today2 || typeof o.models !== "number") return empty;
36919
+ return { day: today2, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
36729
36920
  } catch {
36730
36921
  return empty;
36731
36922
  }
@@ -36780,6 +36971,8 @@ function bumpLedger(root) {
36780
36971
  }
36781
36972
  var REPLAY_RESERVE_MS = 45e3;
36782
36973
  var MAX_REPLAYS = 3;
36974
+ var MAX_CHECKS = 2;
36975
+ var CHECK_VOTES = 2;
36783
36976
  function isNetworkError(message) {
36784
36977
  return /Network error|fetch failed|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EAI_AGAIN|socket hang up/i.test(message);
36785
36978
  }
@@ -36862,12 +37055,14 @@ async function runFormalPhase(input) {
36862
37055
  symbol: f.symbol,
36863
37056
  verdict: "reproduced",
36864
37057
  reason: f.waived ? `waived ${f.waived.at.slice(0, 10)}: ${f.waived.reason} (standing since ${f.at.slice(0, 10)}; the file has not changed)` : `${f.reason ?? "reproduced on the real code"} (standing since ${f.at.slice(0, 10)}; the file has not changed)`,
36865
- ...f.waived ? { waived: true } : {}
37058
+ ...f.waived ? { waived: true } : {},
37059
+ // Same bytes, same answer: the check is not paid for twice.
37060
+ ...f.check ? { check: { outcome: "answered", rounds: 0, costUsd: 0, unpriced: 0, durationMs: 0, ...f.check } } : {}
36866
37061
  });
36867
37062
  }
36868
37063
  }
36869
37064
  if (kept.length !== persisted.length) writePersistedFindings(root, kept);
36870
- if (standing.length > 0) {
37065
+ if (standing.length > 0 && !input.skipStanding) {
36871
37066
  const first = kept.find((f) => f.file === standing[0].file);
36872
37067
  return done({
36873
37068
  status: "checked",
@@ -36895,7 +37090,7 @@ async function runFormalPhase(input) {
36895
37090
  return a.source === "tree-sitter" && a.value.effects.length >= 2;
36896
37091
  })());
36897
37092
  };
36898
- const eligible = signals.filter((s) => isEligible(s, largePush).ok || mapEligible(s.file)).slice(0, 5);
37093
+ const eligible = signals.filter((s) => input.relaxedGates || isEligible(s, largePush).ok || mapEligible(s.file)).slice(0, 5);
36899
37094
  if (eligible.length === 0) {
36900
37095
  const best = signals[0];
36901
37096
  return done({ status: "skipped", skip: "not-eligible", detail: `${best.file}: ${isEligible(best, largePush).why}` });
@@ -36903,7 +37098,7 @@ async function runFormalPhase(input) {
36903
37098
  const ranked = await deps.rank(eligible, root, input.changedLines);
36904
37099
  if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
36905
37100
  if (ranked.ok) spend(ranked);
36906
- candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
37101
+ candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)), commits: c.commits, fixCommits: c.fixCommits, risk: c.risk }));
36907
37102
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
36908
37103
  const minScore = input.minScore ?? DEFAULT_MIN_SCORE;
36909
37104
  let qualified = ranked.ranked.filter((c) => c.ai && c.ai.score >= minScore);
@@ -36949,6 +37144,10 @@ async function runFormalPhase(input) {
36949
37144
  }
36950
37145
  }
36951
37146
  if (d.resolved && d.resolved !== c.ai.symbol) c.ai.symbol = d.resolved;
37147
+ if (input.exclude?.has(`${c.file}#${c.ai.symbol}`)) {
37148
+ note("verified", `${c.ai.symbol}: modelled earlier in this push`);
37149
+ continue;
37150
+ }
36952
37151
  if (input.changedLines) {
36953
37152
  const changed = input.changedLines.get(c.file) ?? [];
36954
37153
  if (changed.length === 0) {
@@ -36990,7 +37189,7 @@ async function runFormalPhase(input) {
36990
37189
  const hazard = hasHazard(functionHazard(d.numbered));
36991
37190
  const shared = contextHazard(context);
36992
37191
  const judged = (c.ai.criteria?.hazard ?? 0) >= 0.8;
36993
- if (!hazard.ok && !shared?.ok && !judged) {
37192
+ if (!input.relaxedGates && !hazard.ok && !shared?.ok && !judged) {
36994
37193
  note("no-hazard", `${c.ai.symbol}: ${hazard.why}`);
36995
37194
  continue;
36996
37195
  }
@@ -37012,7 +37211,7 @@ async function runFormalPhase(input) {
37012
37211
  const sha2562 = sha256Of(chosen.content);
37013
37212
  const chosenContent = chosen.content;
37014
37213
  const { lines, numbered: numbered2 } = chosen;
37015
- const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {} };
37214
+ const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {}, signals: { commits: top.commits, fixCommits: top.fixCommits, risk: top.risk } };
37016
37215
  progress.target = target;
37017
37216
  if (!REPLAYABLE.test(top.file)) return done({ status: "skipped", skip: "replay-unsupported", detail: `${top.file}: replay supports TS/JS and Python`, target });
37018
37217
  if (timeLeft() < GENERATE_RESERVE_MS) return done({ status: "skipped", skip: "not-enough-time", detail: `${Math.round(timeLeft() / 1e3)} s left before generation`, target });
@@ -37023,7 +37222,7 @@ async function runFormalPhase(input) {
37023
37222
  let report = null;
37024
37223
  let modelName = "";
37025
37224
  let rounds = 0;
37026
- for (let round = 1; round <= 2; round++) {
37225
+ for (let round = 1; round <= (input.maxRounds ?? 2); round++) {
37027
37226
  if (round > 1 && overCap()) return done({ status: "skipped", skip: "cost-cap", detail: `$${usage.costUsd.toFixed(2)} spent, cap $${costCap.toFixed(2)}; no retry`, target, model: { name: modelName, file: `${AUTO_MODELS_DIR}/${modelName}.lean`, rounds } });
37028
37227
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off before generation", target });
37029
37228
  rounds = round;
@@ -37042,7 +37241,7 @@ async function runFormalPhase(input) {
37042
37241
  modelName = gen.name;
37043
37242
  const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
37044
37243
  writeFileInRootNoFollow(root, rel, gen.source);
37045
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
37244
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path50.join)(root, rel);
37046
37245
  progress.model = { name: gen.name, file: rel, rounds: round };
37047
37246
  progress.step = "check";
37048
37247
  report = await deps.check(root, abs);
@@ -37138,13 +37337,40 @@ async function runFormalPhase(input) {
37138
37337
  const verdict = r.verdict === "reproduced" ? "reproduced" : r.verdict === "diverged" ? "diverged" : r.verdict === "unreplayable" ? "model-only" : "unverified";
37139
37338
  findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0 });
37140
37339
  }
37340
+ const toCheck = deps.verify && !cancelled() ? findings.filter((f) => f.verdict === "reproduced").slice(0, MAX_CHECKS) : [];
37341
+ if (toCheck.length > 0) {
37342
+ progress.step = "verify";
37343
+ const share = Math.max(0, costCap - usage.costUsd) / (toCheck.length * CHECK_VOTES);
37344
+ const failed = (error) => ({ outcome: "failed", verdict: null, introduced: "unknown", rounds: 0, costUsd: 0, unpriced: 0, durationMs: 0, error });
37345
+ await Promise.all(toCheck.map(async (f) => {
37346
+ const checks = await Promise.all(Array.from({ length: CHECK_VOTES }, () => deps.verify(f, { ...lines ? { lines } : {}, changedLines: input.changedLines?.get(f.file) ?? [], deadlineAt: input.deadlineAt, costLeftUsd: share }).catch((err2) => failed(String(err2?.message ?? err2).slice(0, 120)))));
37347
+ for (const c of checks) {
37348
+ if (c.costUsd > 0) spend({ costUsd: c.costUsd });
37349
+ for (let i2 = 0; i2 < c.unpriced; i2++) usage.unpriced++;
37350
+ }
37351
+ if (!cancelled()) f.check = cautiousCheck(f, checks);
37352
+ }));
37353
+ }
37141
37354
  const reproduced = findings.filter((f) => f.verdict === "reproduced");
37142
37355
  if (reproduced.length > 0 && !cancelled()) {
37143
37356
  const now = (/* @__PURE__ */ new Date()).toISOString();
37144
37357
  const others = readPersistedFindings(root).filter((f) => f.file !== top.file);
37145
37358
  writePersistedFindings(root, [
37146
37359
  ...others,
37147
- ...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 }))
37360
+ ...reproduced.map((f) => ({
37361
+ file: f.file,
37362
+ symbol: f.symbol,
37363
+ sha256: sha2562,
37364
+ property: f.property,
37365
+ desc: f.desc,
37366
+ kind: f.kind,
37367
+ trace: f.trace,
37368
+ model: modelName,
37369
+ reason: f.reason,
37370
+ ...lines ? { lines } : {},
37371
+ at: now,
37372
+ ...f.check?.outcome === "answered" ? { check: { verdict: f.check.verdict, introduced: f.check.introduced, trigger: f.check.trigger, preventedBy: f.check.preventedBy, effect: f.check.effect, reason: f.check.reason, ...f.check.votes ? { votes: f.check.votes } : {} } } : {}
37373
+ }))
37148
37374
  ]);
37149
37375
  }
37150
37376
  const clean2 = findings.every((f) => f.verdict === "diverged");
@@ -37164,7 +37390,7 @@ async function runFormalPhase(input) {
37164
37390
  return done({
37165
37391
  status: "checked",
37166
37392
  target,
37167
- model: { name: modelName, file: (0, import_node_path47.relative)(root, (0, import_node_path47.join)(root, modelFile)), rounds },
37393
+ model: { name: modelName, file: (0, import_node_path50.relative)(root, (0, import_node_path50.join)(root, modelFile)), rounds },
37168
37394
  properties: report.properties,
37169
37395
  findings
37170
37396
  });
@@ -37197,7 +37423,19 @@ async function generateAndCheck(root, req, opts) {
37197
37423
  const read2 = readSrc(req.file, 96 * 1024);
37198
37424
  if (!read2.ok) return { ok: false, error: `${req.file}: ${read2.reason}`, rounds: 0, costUsd: 0 };
37199
37425
  const sha2562 = sha256Of(read2.content);
37200
- const { lines, numbered: numbered2 } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
37426
+ const { lines, numbered: numbered2, extent } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
37427
+ let warning;
37428
+ if (!lines) {
37429
+ const outline = extent === "fallback:not-found" ? opts.deps.codeMap?.outline(req.file, read2.content) : void 0;
37430
+ if (outline?.source === "tree-sitter") {
37431
+ const names2 = [...new Set(outline.value.filter((f) => f.name && f.kind !== "lambda").map((f) => f.qualified))];
37432
+ const last = (req.symbol.split(/[.#:]/).pop() ?? req.symbol).toLowerCase();
37433
+ const close = names2.filter((n) => n.toLowerCase().includes(last));
37434
+ const shown = (close.length > 0 ? close : names2).slice(0, 12);
37435
+ 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 };
37436
+ }
37437
+ warning = `could not find the lines of \`${req.symbol}\` in ${req.file} (${extent}): the model is written from the start of the file, and a replay must copy half of the whole file. Pass --lines a-b to name the code.`;
37438
+ }
37201
37439
  const target = {
37202
37440
  file: req.file,
37203
37441
  symbol: req.symbol,
@@ -37205,7 +37443,9 @@ async function generateAndCheck(root, req, opts) {
37205
37443
  sha256: sha2562,
37206
37444
  numbered: numbered2,
37207
37445
  reasons: req.hint ? [`the user's worry, in their words: ${req.hint.slice(0, 280)}`] : [],
37208
- properties: []
37446
+ properties: [],
37447
+ // The run row records which extractor answered, as at push.
37448
+ extentSource: extent
37209
37449
  };
37210
37450
  const context = opts.deps.codeMap && !req.lines ? targetContext({ codeMap: opts.deps.codeMap, codeSource: opts.deps.codeSource, readSource: readSrc, file: req.file, content: read2.content, symbol: req.symbol }) : null;
37211
37451
  Object.assign(target, context?.fields ?? {});
@@ -37227,7 +37467,7 @@ async function generateAndCheck(root, req, opts) {
37227
37467
  }
37228
37468
  const rel = `${dir}/${gen.name}.lean`;
37229
37469
  writeFileInRootNoFollow(root, rel, gen.source);
37230
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
37470
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path50.join)(root, rel);
37231
37471
  const report = await opts.deps.check(root, abs);
37232
37472
  const abstracts = report.header?.abstracts ?? [];
37233
37473
  const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
@@ -37241,14 +37481,14 @@ async function generateAndCheck(root, req, opts) {
37241
37481
  const g = basisOf(p.source, files);
37242
37482
  return g.ok ? [] : [`${p.id}: ${g.why}`];
37243
37483
  });
37244
- if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd };
37484
+ if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd, ...warning ? { warning } : {} };
37245
37485
  lastError = ungroundedMessage(bad.join("; "));
37246
37486
  if (round < maxRounds) {
37247
37487
  previous = { source: gen.source, error: lastError };
37248
37488
  continue;
37249
37489
  }
37250
37490
  const grounded = report.properties.filter((p) => basisOf(p.source, files).ok);
37251
- if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd };
37491
+ if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd, ...warning ? { warning } : {} };
37252
37492
  break;
37253
37493
  }
37254
37494
  lastError = stray ? `the model abstracts ${stray.file}, not ${req.file}` : report.error ?? (report.malformed ? "the model printed malformed VERITY lines" : "the model reported no property");
@@ -37259,7 +37499,7 @@ async function generateAndCheck(root, req, opts) {
37259
37499
  function skippedOutcome(skip, detail) {
37260
37500
  return { status: "skipped", skip, ...detail ? { detail } : {}, findings: [], usage: { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 }, durationMs: 0 };
37261
37501
  }
37262
- async function prepareFormalPhase(root, env = process.env, auth2, readSource, codeSource) {
37502
+ async function prepareFormalPhase(root, env = process.env, auth2, readSource, codeSource, opts = {}) {
37263
37503
  const direct = env.VERITY_PROVE_DIRECT === "1" && !!env.OPENAI_API_KEY;
37264
37504
  if (!auth2 && !direct) return { ok: false, skip: "not-logged-in" };
37265
37505
  const apiKey = direct ? env.OPENAI_API_KEY : void 0;
@@ -37274,9 +37514,16 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
37274
37514
  }
37275
37515
  const build = await buildLibraryAsync(toolchain, root, 9e4);
37276
37516
  if (!build.ok) return { ok: false, skip: "library-build-failed", detail: build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).join(" ").slice(0, 200) };
37517
+ const code = await loadCodeContext(root, env, codeSource);
37518
+ return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...opts.tier ? { tier: opts.tier } : {}, ...code }), codeSource: code.codeSource } };
37519
+ }
37520
+ async function loadCodeContext(root, env = process.env, codeSource) {
37277
37521
  const loaded = await loadCodeMap(env);
37278
- const source2 = codeSource ?? withoutPaths(worktreeSource(root), isDeniedPath);
37279
- return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, codeMap: loaded.ok ? loaded.map : null, codeSource: source2 }), codeSource: source2 } };
37522
+ return { codeMap: loaded.ok ? loaded.map : null, codeSource: codeSource ?? withoutPaths(worktreeSource(root), isDeniedPath) };
37523
+ }
37524
+ async function onDemandDeps(root, opts) {
37525
+ const code = await loadCodeContext(root, opts.env);
37526
+ return { ...defaultDeps({ ...opts, tier: "deep", ...code }), codeSource: code.codeSource };
37280
37527
  }
37281
37528
  function changedFunction(codeMap, file, content, changed) {
37282
37529
  const outline = codeMap.outline(file, content);
@@ -37321,10 +37568,52 @@ function runFormalPhaseWithin(input) {
37321
37568
  resolve9(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
37322
37569
  }, left);
37323
37570
  });
37324
- return Promise.race([runFormalPhase({ ...input, progress }), cutoff]).finally(() => {
37571
+ return Promise.race([runFormalPhaseTargets({ ...input, progress }), cutoff]).finally(() => {
37325
37572
  if (timer) clearTimeout(timer);
37326
37573
  });
37327
37574
  }
37575
+ var NOTHING_ELSE_QUALIFIES = /* @__PURE__ */ new Set(["no-source-files", "not-eligible", "no-candidate", "no-symbol", "symbol-not-in-push", "verified", "no-hazard", "too-large"]);
37576
+ async function runFormalPhaseTargets(input) {
37577
+ const first = await runFormalPhase(input);
37578
+ const max = Math.max(1, Math.floor(input.maxTargets ?? 1));
37579
+ if (max === 1 || first.status !== "checked" || !first.target) return first;
37580
+ const outcomes = [first];
37581
+ const exclude = /* @__PURE__ */ new Set([`${first.target.file}#${first.target.symbol}`]);
37582
+ const cap2 = input.costCapUsd ?? PUSH_COST_CAP_USD;
37583
+ let stoppedAt;
37584
+ while (outcomes.length < max) {
37585
+ if (input.progress?.cancelled) {
37586
+ stoppedAt = { skip: "deadline", detail: "cut off between targets" };
37587
+ break;
37588
+ }
37589
+ const left = input.deadlineAt - input.deps.now();
37590
+ if (left < GENERATE_RESERVE_MS + REPLAY_RESERVE_MS) {
37591
+ stoppedAt = { skip: "not-enough-time", detail: `${Math.round(left / 1e3)} s left before target ${outcomes.length + 1}` };
37592
+ break;
37593
+ }
37594
+ const spent = outcomes.reduce((sum, o) => sum + o.usage.costUsd, 0);
37595
+ if (spent >= cap2) {
37596
+ stoppedAt = { skip: "cost-cap", detail: `$${spent.toFixed(2)} spent, cap $${cap2.toFixed(2)}` };
37597
+ break;
37598
+ }
37599
+ const next = await runFormalPhase({ ...input, exclude, skipStanding: true, costCapUsd: cap2 - spent, progress: {} });
37600
+ if (next.status !== "checked" && next.skip && !NOTHING_ELSE_QUALIFIES.has(next.skip)) stoppedAt = { skip: next.skip, ...next.detail ? { detail: next.detail } : {} };
37601
+ if (!next.target || next.status !== "checked" && exclude.has(`${next.target.file}#${next.target.symbol}`)) break;
37602
+ exclude.add(`${next.target.file}#${next.target.symbol}`);
37603
+ outcomes.push(next);
37604
+ if (next.status !== "checked") break;
37605
+ }
37606
+ if (outcomes.length === 1) return stoppedAt ? { ...first, stoppedAt } : first;
37607
+ return {
37608
+ ...first,
37609
+ ...stoppedAt ? { stoppedAt } : {},
37610
+ findings: outcomes.flatMap((o) => o.findings),
37611
+ properties: outcomes.flatMap((o) => o.properties ?? []),
37612
+ targets: outcomes.flatMap((o) => o.target ? [{ file: o.target.file, symbol: o.target.symbol, status: o.status, ...o.skip ? { skip: o.skip } : {}, findings: o.findings.length }] : []),
37613
+ usage: outcomes.reduce((u, o) => ({ inputTokens: u.inputTokens + o.usage.inputTokens, outputTokens: u.outputTokens + o.usage.outputTokens, costUsd: Math.round((u.costUsd + o.usage.costUsd) * 1e6) / 1e6, unpriced: u.unpriced + o.usage.unpriced }), { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 }),
37614
+ durationMs: outcomes.reduce((sum, o) => sum + o.durationMs, 0)
37615
+ };
37616
+ }
37328
37617
  function cutOffOutcome(p, detail, elapsedMs) {
37329
37618
  const usage = p.usage ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 };
37330
37619
  if (!p.report || !p.target || !p.model) {
@@ -37343,7 +37632,9 @@ function describeFormalOutcome(o) {
37343
37632
  if (o.status === "skipped") return `formal: skipped (${o.skip}${o.detail ? `: ${o.detail}` : ""})`;
37344
37633
  const parts2 = o.properties?.map((p) => {
37345
37634
  const f = o.findings.find((x) => x.property === p.id);
37346
- const tag = p.result === "counterexample" ? f ? f.verdict.toUpperCase() + (f.waived ? " (waived)" : "") : "counterexample" : p.result;
37635
+ const votes = f?.check?.votes && f.check.votes.length > 1 ? ` [${f.check.votes.join(", ")}]` : "";
37636
+ const checked = f?.check ? f.check.outcome === "answered" ? ` \u2192 checked ${f.check.verdict}${f.check.introduced === "no" ? " (pre-existing)" : ""}${votes}` : ` \u2192 not checked (${f.check.outcome})${votes}` : "";
37637
+ const tag = p.result === "counterexample" ? f ? f.verdict.toUpperCase() + (f.waived ? " (waived)" : "") + checked : "counterexample" : p.result;
37347
37638
  return `${p.id} ${tag}`;
37348
37639
  }) ?? [];
37349
37640
  const cost = o.usage.costUsd > 0 ? ` \xB7 $${o.usage.costUsd.toFixed(2)}` : "";
@@ -37351,13 +37642,222 @@ function describeFormalOutcome(o) {
37351
37642
  return `formal: ${o.model?.name ?? "?"} on ${o.target?.file ?? "?"}#${o.target?.symbol ?? "?"} (${o.model?.rounds ?? 1} round${o.model?.rounds === 1 ? "" : "s"}) \xB7 ${parts2.join(" \xB7 ")} \xB7 ${Math.round(o.durationMs / 1e3)} s${cost}${cut}`;
37352
37643
  }
37353
37644
 
37645
+ // src/lib/prove/verify.ts
37646
+ var MIN_VERIFY_TURN_MS = 15e3;
37647
+ var MIN_VERIFY_START_MS = 45e3;
37648
+ var VERIFY_TURN_HOLD_USD = 0.1;
37649
+ var MAX_TURNS2 = 14;
37650
+ var VERDICTS = ["REAL", "REAL-LOW", "PREVENTED", "ARTIFACT", "UNSURE"];
37651
+ var verdictOf = (v) => typeof v === "string" && VERDICTS.includes(v) ? v : null;
37652
+ var introducedOf = (v) => v === "yes" || v === "no" ? v : "unknown";
37653
+ var text = (v, n) => typeof v === "string" ? v.slice(0, n) : "";
37654
+ function verifyPost(auth2) {
37655
+ return async (body2, timeoutMs) => {
37656
+ const res = await apiRequest({
37657
+ method: "POST",
37658
+ path: "/prove/verify",
37659
+ serviceUrl: auth2.serviceUrl,
37660
+ token: auth2.token,
37661
+ // Streamed with a heartbeat, like generate and replay (decision 53).
37662
+ extraHeaders: { "X-Verity-Keepalive": "1" },
37663
+ body: body2,
37664
+ timeout: timeoutMs,
37665
+ cmd: "prove-verify"
37666
+ });
37667
+ return res.ok ? { ok: true, data: res.data ?? {} } : { ok: false, error: res.error };
37668
+ };
37669
+ }
37670
+ async function verifyFinding(input, opts) {
37671
+ const now = opts.now ?? Date.now;
37672
+ const startedAt = now();
37673
+ const remaining = () => opts.deadlineAt - now();
37674
+ let rounds = 0;
37675
+ let costUsd = 0;
37676
+ let unpriced = 0;
37677
+ const end = (outcome, extra = {}) => ({ outcome, verdict: null, introduced: "unknown", rounds, costUsd, unpriced, durationMs: now() - startedAt, ...extra });
37678
+ if (remaining() < MIN_VERIFY_START_MS) return end("deadline", { error: "not enough time left" });
37679
+ let body2 = {
37680
+ target: {
37681
+ file: input.file,
37682
+ symbol: input.symbol,
37683
+ ...input.lines ? { lines: input.lines } : {},
37684
+ property: input.property,
37685
+ replay_reason: input.replayReason,
37686
+ changed_lines: input.changedLines.slice(0, 200)
37687
+ },
37688
+ local_tools: opts.localTools
37689
+ };
37690
+ for (let turn = 0; turn < MAX_TURNS2; turn++) {
37691
+ if (remaining() < MIN_VERIFY_TURN_MS) return end("deadline");
37692
+ if (costUsd + VERIFY_TURN_HOLD_USD > opts.costLeftUsd) return end("cost-cap");
37693
+ const res = await opts.post({ ...body2, remaining_ms: remaining() }, Math.max(1, remaining()));
37694
+ if (!res.ok) return end("failed", { error: res.error.slice(0, 200) });
37695
+ const d = res.data;
37696
+ if (d.enabled === false) return end("disabled", { error: text(d.reason, 60) });
37697
+ if (d.error && typeof d.error === "object") return end("failed", { error: text(d.error.code, 60) || "SERVICE_ERROR" });
37698
+ rounds = typeof d.round === "number" ? d.round : rounds + 1;
37699
+ if (typeof d.cost_usd === "number") costUsd += d.cost_usd;
37700
+ else unpriced++;
37701
+ if (d.done) {
37702
+ const a = d.answer;
37703
+ if (!a) return end("failed", { error: text(d.error, 60) || "no verdict" });
37704
+ const verdict = verdictOf(a.verdict);
37705
+ if (!verdict) return end("failed", { error: "unknown verdict" });
37706
+ return end("answered", {
37707
+ verdict,
37708
+ claimed: verdictOf(a.claimed),
37709
+ introduced: introducedOf(a.introduced),
37710
+ trigger: text(a.trigger, 400),
37711
+ preventedBy: typeof a.prevented_by === "string" ? a.prevented_by.slice(0, 600) : null,
37712
+ effect: text(a.effect, 600),
37713
+ reason: text(a.reason, 2e3),
37714
+ quotes: (Array.isArray(a.quotes) ? a.quotes : []).slice(0, 12).flatMap((q) => {
37715
+ const o = q ?? {};
37716
+ return typeof o.path === "string" && typeof o.text === "string" ? [{ path: o.path.slice(0, 400), text: o.text.slice(0, 600), witnessed: o.witnessed === true }] : [];
37717
+ })
37718
+ });
37719
+ }
37720
+ if (typeof d.state !== "string" || !Array.isArray(d.calls)) return end("failed", { error: "malformed turn" });
37721
+ const results = await opts.executeTools(d.calls);
37722
+ body2 = { state: d.state, results };
37723
+ }
37724
+ return end("failed", { error: "too many turns" });
37725
+ }
37726
+
37727
+ // src/lib/prove/record.ts
37728
+ var RECORD_TIMEOUT_MS = 8e3;
37729
+ var HOOK_EXIT_MARGIN_MS = 5e3;
37730
+ var MIN_RECORD_POST_MS = 1e3;
37731
+ function guardRecordDeadline(hookStartedAt) {
37732
+ return hookStartedAt + GUARD_TIMEOUT_MS - HOOK_EXIT_MARGIN_MS;
37733
+ }
37734
+ function recordPostTimeout(now, deadlineAt, timeoutMs = RECORD_TIMEOUT_MS) {
37735
+ if (deadlineAt === void 0) return timeoutMs;
37736
+ const left = deadlineAt - now;
37737
+ return left < MIN_RECORD_POST_MS ? null : Math.min(timeoutMs, left);
37738
+ }
37739
+ var norm2 = (p) => p.replace(/\\/g, "/");
37740
+ var SAFE_SEGMENT = /^[A-Za-z0-9._@+~$()[\]-]{1,255}$/;
37741
+ function safeRepoPath(p) {
37742
+ const n = norm2(p);
37743
+ if (!n || n.length > 512 || n.startsWith("/") || /^[A-Za-z]:\//.test(n)) return null;
37744
+ return n.split("/").every((s) => s !== "." && s !== ".." && SAFE_SEGMENT.test(s)) ? n : null;
37745
+ }
37746
+ var SYMBOL = /^[A-Za-z_$][\w$]*(?:[.#:][A-Za-z_$][\w$]*)*$/;
37747
+ var IDENT3 = /^[A-Za-z][\w]*$/;
37748
+ var TRACE_STEP = /^[A-Za-z_]\w{0,63}$/;
37749
+ var ELIDED_STEP = "\u2026";
37750
+ function recordBasis(source2) {
37751
+ if (typeof source2 !== "string") return "";
37752
+ if (/^rule:[a-z-]+$/.test(source2)) return source2;
37753
+ const m = /^(?:([^:\s]+):)?L(\d+)(?::|$)/.exec(source2);
37754
+ return m ? m[1] ? `${norm2(m[1])}:L${m[2]}` : `L${m[2]}` : "";
37755
+ }
37756
+ function recordTrace(trace) {
37757
+ return trace.slice(0, 16).map((s) => {
37758
+ const name2 = (s.trim().split(/[\s(]/, 1)[0] ?? "").split(".").pop() ?? "";
37759
+ return TRACE_STEP.test(name2) ? name2 : ELIDED_STEP;
37760
+ });
37761
+ }
37762
+ var ident2 = (s, re, max) => typeof s === "string" && s.length <= max && re.test(s) ? s : null;
37763
+ var kind = (k) => k === "intent" ? "intent" : "structural";
37764
+ var signalsOf = (c) => c && typeof c.commits === "number" && typeof c.fixCommits === "number" ? { commits: c.commits, fix_commits: c.fixCommits, risk: Object.fromEntries(Object.entries(c.risk ?? {}).filter(([, n]) => typeof n === "number" && n > 0).slice(0, 16)) } : null;
37765
+ function buildPhaseRecord(outcome, ctx) {
37766
+ const pushed = new Set(ctx.pushedFiles.map(norm2));
37767
+ const blocks = (f) => ctx.moment === "push" && formalDisposition(f) === "block" && pushed.has(norm2(f.file));
37768
+ const symbol = (s) => ident2(s, SYMBOL, 200);
37769
+ return {
37770
+ moment: ctx.moment,
37771
+ status: outcome.status,
37772
+ skip: outcome.skip ?? null,
37773
+ parent_run_id: ctx.parentRunId,
37774
+ target: outcome.target && symbol(outcome.target.symbol) && safeRepoPath(outcome.target.file) ? {
37775
+ file: safeRepoPath(outcome.target.file),
37776
+ symbol: symbol(outcome.target.symbol),
37777
+ lines: outcome.target.lines ?? null,
37778
+ score: Math.max(0, Math.min(1, outcome.target.score)),
37779
+ extent: ident2(outcome.target.extent, /^[a-z-]+(?::[a-z-]+)?$/, 60),
37780
+ signals: signalsOf(outcome.target.signals)
37781
+ } : null,
37782
+ candidates: (outcome.candidates ?? []).filter((c) => safeRepoPath(c.file)).slice(0, 12).map((c) => ({
37783
+ file: safeRepoPath(c.file),
37784
+ symbol: c.symbol === null ? null : symbol(c.symbol),
37785
+ score: c.score === null ? null : Math.max(0, Math.min(1, c.score)),
37786
+ criteria: c.criteria,
37787
+ reasked: c.reasked,
37788
+ signals: signalsOf(c)
37789
+ })),
37790
+ model: outcome.model && ident2(outcome.model.name, /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)*$/, 120) ? { name: outcome.model.name, rounds: Math.max(0, Math.min(20, outcome.model.rounds)) } : null,
37791
+ properties: (outcome.properties ?? []).filter((p) => ident2(p.id, IDENT3, 120)).slice(0, 16).map((p) => ({
37792
+ id: p.id,
37793
+ kind: kind(p.kind),
37794
+ basis: recordBasis(p.source),
37795
+ result: p.result,
37796
+ bound: p.bound ?? null,
37797
+ states: p.states ?? null
37798
+ })),
37799
+ findings: outcome.findings.filter((f) => ident2(f.property, IDENT3, 120) && symbol(f.symbol) && safeRepoPath(f.file)).slice(0, 8).map((f) => ({
37800
+ property: f.property,
37801
+ kind: kind(f.kind),
37802
+ trace: recordTrace(f.trace),
37803
+ file: safeRepoPath(f.file),
37804
+ symbol: f.symbol,
37805
+ verdict: f.verdict,
37806
+ waived: f.waived === true,
37807
+ blocked: blocks(f),
37808
+ // The check's closed codes only (decision 91): never its reason, trigger or quotes.
37809
+ check: f.check ? { outcome: f.check.outcome, verdict: f.check.verdict, introduced: f.check.introduced, rounds: f.check.rounds } : null
37810
+ })),
37811
+ grounding: outcome.grounding ? {
37812
+ sent_back: outcome.grounding.sentBack,
37813
+ dropped: outcome.grounding.dropped.filter((id) => ident2(id, IDENT3, 120)).slice(0, 16),
37814
+ trigger_missing: (outcome.grounding.triggerMissing ?? []).filter((id) => ident2(id, IDENT3, 120)).slice(0, 16)
37815
+ } : null,
37816
+ usage: {
37817
+ input_tokens: outcome.usage.inputTokens,
37818
+ output_tokens: outcome.usage.outputTokens,
37819
+ cost_usd: outcome.usage.costUsd,
37820
+ unpriced: outcome.usage.unpriced
37821
+ },
37822
+ duration_ms: Math.round(outcome.durationMs)
37823
+ };
37824
+ }
37825
+ async function postPhaseRecord(outcome, ctx, post) {
37826
+ try {
37827
+ const timeout = recordPostTimeout((post.now ?? Date.now)(), post.deadlineAt, post.timeoutMs ?? RECORD_TIMEOUT_MS);
37828
+ if (timeout === null) {
37829
+ logEvent("formal_record_skipped", { moment: ctx.moment, reason: "hook-deadline" });
37830
+ return null;
37831
+ }
37832
+ const res = await apiRequest({
37833
+ method: "POST",
37834
+ path: "/prove/record",
37835
+ serviceUrl: post.serviceUrl,
37836
+ token: post.token,
37837
+ body: buildPhaseRecord(outcome, ctx),
37838
+ timeout,
37839
+ cmd: "prove-record"
37840
+ });
37841
+ if (!res.ok) {
37842
+ logEvent("formal_record_failed", { moment: ctx.moment, category: res.category ?? "unknown", http_status: res.http_status ?? null });
37843
+ return null;
37844
+ }
37845
+ const runId = typeof res.data?.run_id === "string" ? res.data.run_id : null;
37846
+ logEvent("formal_record", { moment: ctx.moment, run_id: runId });
37847
+ return runId;
37848
+ } catch (err2) {
37849
+ logEvent("formal_record_failed", { moment: ctx.moment, category: "exception", name: err2?.constructor?.name ?? "Error" });
37850
+ return null;
37851
+ }
37852
+ }
37853
+
37354
37854
  // src/commands/guard.ts
37355
37855
  var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
37356
37856
  var WRITERS_BUDGET_MS = 1500;
37357
37857
  var EXCERPT_MAX_LINES2 = 30;
37358
37858
  var VENDORED_READ_MAX_BYTES = 256 * 1024;
37359
37859
  var GUARD_BLOCK_CAP = 2;
37360
- var GUARD_ITER_FILE = (0, import_node_path48.join)(VERITY_DIR, ".guard-iteration");
37860
+ var GUARD_ITER_FILE = (0, import_node_path51.join)(VERITY_DIR, ".guard-iteration");
37361
37861
  function readPreToolUseStdin() {
37362
37862
  const empty = { command: "", cwd: null, sessionId: null };
37363
37863
  return new Promise((resolve9) => {
@@ -37402,7 +37902,7 @@ function readPreToolUseStdin() {
37402
37902
  }
37403
37903
  function readIterMap() {
37404
37904
  try {
37405
- const raw = JSON.parse((0, import_node_fs61.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37905
+ const raw = JSON.parse((0, import_node_fs63.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37406
37906
  if (raw && typeof raw === "object") {
37407
37907
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
37408
37908
  return { [raw.moment]: raw.count };
@@ -37422,10 +37922,10 @@ function readIter(moment) {
37422
37922
  }
37423
37923
  function writeIter(moment, count) {
37424
37924
  try {
37425
- (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37925
+ (0, import_node_fs63.mkdirSync)(VERITY_DIR, { recursive: true });
37426
37926
  const map = readIterMap();
37427
37927
  map[moment] = count;
37428
- (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37928
+ (0, import_node_fs63.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37429
37929
  } catch {
37430
37930
  }
37431
37931
  }
@@ -37435,10 +37935,10 @@ function resetIter(moment) {
37435
37935
  if (!(moment in map)) return;
37436
37936
  delete map[moment];
37437
37937
  if (Object.keys(map).length === 0) {
37438
- if ((0, import_node_fs61.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs61.unlinkSync)(GUARD_ITER_FILE);
37938
+ if ((0, import_node_fs63.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs63.unlinkSync)(GUARD_ITER_FILE);
37439
37939
  } else {
37440
- (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37441
- (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37940
+ (0, import_node_fs63.mkdirSync)(VERITY_DIR, { recursive: true });
37941
+ (0, import_node_fs63.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37442
37942
  }
37443
37943
  } catch {
37444
37944
  }
@@ -37488,17 +37988,17 @@ function parsePrIntent(command) {
37488
37988
  }
37489
37989
  var TRIVIAL_INTENT = /^(wip|tmp|temp|test|fix|chore|amend|\.+|fixup!.*|squash!.*|merge\b.*)$/i;
37490
37990
  var SHELL_PLUMBING = /\$\(|`|<<-?\s*['"]?[A-Za-z_]/;
37491
- function isSubstantiveIntent(text) {
37492
- if (!text) return false;
37493
- const t = text.trim();
37991
+ function isSubstantiveIntent(text2) {
37992
+ if (!text2) return false;
37993
+ const t = text2.trim();
37494
37994
  if (t.length < 12) return false;
37495
37995
  if (TRIVIAL_INTENT.test(t)) return false;
37496
37996
  if (SHELL_PLUMBING.test(t)) return false;
37497
37997
  return true;
37498
37998
  }
37499
37999
  function extractStatedIntent(moment, command, pushedMessages = null) {
37500
- const text = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
37501
- return isSubstantiveIntent(text) ? text : null;
38000
+ const text2 = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
38001
+ return isSubstantiveIntent(text2) ? text2 : null;
37502
38002
  }
37503
38003
  function hasBlockingFinding(response, sentFiles) {
37504
38004
  const findings = response.findings ?? [];
@@ -37508,7 +38008,7 @@ function hasBlockingFinding(response, sentFiles) {
37508
38008
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
37509
38009
  const analyzable = filterAnalyzable(files);
37510
38010
  const securityFiles = filterSecurity(files);
37511
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs61.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
38011
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs63.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
37512
38012
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
37513
38013
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
37514
38014
  const requestBody = {
@@ -37521,7 +38021,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
37521
38021
  agent_harness: "claude-code",
37522
38022
  // Prefer the session id Claude Code passes on the hook payload; fall back
37523
38023
  // to the env var, then 'unknown'.
37524
- session_id: sessionId ?? process.env.CLAUDE_SESSION_ID ?? "unknown",
38024
+ session_id: sessionId ?? envSessionId() ?? "unknown",
37525
38025
  trigger,
37526
38026
  iteration: iter + 1
37527
38027
  }
@@ -37589,6 +38089,14 @@ function oneShotLostOutcome(input) {
37589
38089
  return input.agentGate === "FAIL" && input.agentBlocking ? "block" : "allow-without-review";
37590
38090
  }
37591
38091
  function withAgentVerdict(oneShot, agent) {
38092
+ if (agent.one_shot_source === "none" && agent.findings_mode === "agent" && agent.gate_decision !== null) {
38093
+ return {
38094
+ ...oneShot,
38095
+ gate_decision: worstGate(agent.gate_decision, "WARN", "WARN"),
38096
+ findings: agent.findings.filter((f) => f.agent_added === true),
38097
+ agent_review: { ...agent.agent_review, gate_decision_before: oneShot.gate_decision ?? null, one_shot_source: "none", cleared: [], downgraded: [] }
38098
+ };
38099
+ }
37592
38100
  if (agent.one_shot_source === "none" && typeof oneShot.gate_decision === "string") {
37593
38101
  const added = agent.findings.filter((f) => f.agent_added === true);
37594
38102
  return {
@@ -37652,7 +38160,8 @@ function startAgentReview(input) {
37652
38160
  http: http2,
37653
38161
  executeTools: makeToolExecutor(ctx),
37654
38162
  startedAt: input.hookStartedAt,
37655
- deadlineMs: AGENT_DEADLINE_MS[input.moment],
38163
+ // The push's deadline follows the review effort (lib/effort.ts); the commit's never does.
38164
+ deadlineMs: input.moment === "pre-push" ? effortProfile(input.root).pushDeadlineMs : AGENT_DEADLINE_MS[input.moment],
37656
38165
  start: {
37657
38166
  moment: input.moment,
37658
38167
  iteration: input.iteration,
@@ -37677,7 +38186,8 @@ function startFormalPhase(input) {
37677
38186
  const env = process.env.VERITY_GIT_MOMENT_FORMAL;
37678
38187
  if (env === "off") return null;
37679
38188
  if (env !== "push" && readProjectConfig().formal !== "push") return null;
37680
- const deadlineAt = input.hookStartedAt + AGENT_DEADLINE_MS["pre-push"] - 1e4;
38189
+ const profile = effortProfile(input.root);
38190
+ const deadlineAt = input.hookStartedAt + profile.pushDeadlineMs - 1e4;
37681
38191
  const ig = loadVerityIgnore();
37682
38192
  const files = input.files.filter((f) => !isVerityOwnedPath(f) && !isIgnored3(ig, f));
37683
38193
  let changedLines = /* @__PURE__ */ new Map();
@@ -37699,9 +38209,17 @@ function startFormalPhase(input) {
37699
38209
  return { ok: true, content };
37700
38210
  } : void 0;
37701
38211
  const run4 = async () => {
37702
- const prep = await prepareFormalPhase(input.root, process.env, input.auth, readSource, withoutPaths(tip ? revisionSource(input.root, tip) : worktreeSource(input.root), isDeniedPath));
38212
+ const prep = await prepareFormalPhase(input.root, process.env, input.auth, readSource, withoutPaths(tip ? revisionSource(input.root, tip) : worktreeSource(input.root), isDeniedPath), { tier: profile.formal.tier });
37703
38213
  if (!prep.ok) return skippedOutcome(prep.skip, prep.detail);
37704
- return runFormalPhaseWithin({ root: input.root, files, changedLines, deadlineAt, deps: prep.deps });
38214
+ if (process.env.VERITY_FORMAL_VERIFY !== "off") {
38215
+ const ctx = { root: input.root, range: input.range, codeMap: prep.deps.codeMap ?? null };
38216
+ const post = verifyPost(input.auth);
38217
+ prep.deps.verify = (f, v) => verifyFinding(
38218
+ { file: f.file, symbol: f.symbol, ...v.lines ? { lines: v.lines } : {}, property: { desc: f.desc, kind: f.kind, trace: f.trace }, replayReason: f.reason ?? "", changedLines: v.changedLines },
38219
+ { executeTools: makeToolExecutor(ctx), localTools: offeredLocalTools(ctx), deadlineAt: v.deadlineAt, costLeftUsd: v.costLeftUsd, post }
38220
+ );
38221
+ }
38222
+ return runFormalPhaseWithin({ root: input.root, files, changedLines, deadlineAt, deps: prep.deps, minScore: profile.formal.minScore, maxRounds: profile.formal.maxRounds, costCapUsd: profile.formal.costCapUsd, maxTargets: profile.formal.maxTargets, relaxedGates: profile.formal.relaxedGates, dailyCap: profile.formal.dailyModels, dailyCostCapUsd: profile.formal.dailyCostUsd });
37705
38223
  };
37706
38224
  return run4().catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200)));
37707
38225
  }
@@ -37893,6 +38411,9 @@ async function runGuard(opts, globals) {
37893
38411
  rounds: formalOutcome.model?.rounds ?? null,
37894
38412
  properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
37895
38413
  findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
38414
+ // Review effort "max" models more than one function: each one, and why the search stopped early.
38415
+ targets: (formalOutcome.targets ?? []).map((t) => `${t.file}#${t.symbol}:${t.status}${t.skip ? `(${t.skip})` : ""}`),
38416
+ stopped_at: formalOutcome.stoppedAt?.skip ?? null,
37896
38417
  // Decision 81: what each property rests on (a rule, or "line"), what was
37897
38418
  // sent back or dropped as ungrounded, and which counterexamples lack their
37898
38419
  // property's trigger (shadow). Ids and rule names only, never code.
@@ -37925,6 +38446,13 @@ async function runGuard(opts, globals) {
37925
38446
  const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
37926
38447
  mergeFormalFindings(response, formalOutcome, files);
37927
38448
  decision = response.gate_decision ?? "(unrecognised)";
38449
+ if (formalOutcome) {
38450
+ await postPhaseRecord(formalOutcome, {
38451
+ moment: "push",
38452
+ parentRunId: typeof response.run_id === "string" ? response.run_id : null,
38453
+ pushedFiles: files
38454
+ }, { serviceUrl: urlResult.data, token: tokenResult.data.token, deadlineAt: guardRecordDeadline(hookStartedAt) });
38455
+ }
37928
38456
  if (!result.ok) {
37929
38457
  const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
37930
38458
  if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
@@ -38042,7 +38570,7 @@ function writeBlockMessage(moment, response, covDetail) {
38042
38570
 
38043
38571
  // src/commands/ignore.ts
38044
38572
  function registerIgnoreCommand(program2) {
38045
- const ignore = program2.command("ignore").description("Declare the next turn (or a short window) as housekeeping \u2014 no review needed").option("--turn", "Cover the next turn only (the default)").option("--for <duration>", "Cover a window: 30m, 45s, 1h (max 60m)").option("--reason <reason>", "Why this window needs no review \u2014 required, and recorded").option("--agent", "Mark the declaration as agent-invoked (a ledger label, not a permission)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID)").option("--json", "Output raw JSON").action(async (opts) => {
38573
+ const ignore = program2.command("ignore").description("Declare the next turn (or a short window) as housekeeping \u2014 no review needed").option("--turn", "Cover the next turn only (the default)").option("--for <duration>", "Cover a window: 30m, 45s, 1h (max 60m)").option("--reason <reason>", "Why this window needs no review \u2014 required, and recorded").option("--agent", "Mark the declaration as agent-invoked (a ledger label, not a permission)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").option("--json", "Output raw JSON").action(async (opts) => {
38046
38574
  const globals = program2.opts();
38047
38575
  const now = Math.floor(Date.now() / 1e3);
38048
38576
  const reason = opts.reason?.trim();
@@ -38069,7 +38597,7 @@ function registerIgnoreCommand(program2) {
38069
38597
  }
38070
38598
  const tokenResult = await resolveToken(globals.token);
38071
38599
  const token = tokenResult.ok ? tokenResult.data.token : void 0;
38072
- const sessionId = opts.sessionId || process.env.CLAUDE_SESSION_ID || void 0;
38600
+ const sessionId = opts.sessionId || envSessionId();
38073
38601
  const keys = ignoreStateKeys(token, sessionId);
38074
38602
  const existing = resolveIgnoreState(keys);
38075
38603
  const spent = existing?.state.spent ?? 0;
@@ -38115,11 +38643,11 @@ function registerIgnoreCommand(program2) {
38115
38643
  printInfo(`Verity will skip ${window2} \u2014 "${reason}" (${spent + 1}/${IGNORE_BUDGET} this session).`);
38116
38644
  printInfo("It covers turns that author nothing. If anything is written, the declaration voids and the review runs.");
38117
38645
  });
38118
- ignore.command("clear").description("Cancel the active declaration (the spent budget is not refunded)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID)").action(async (opts) => {
38646
+ ignore.command("clear").description("Cancel the active declaration (the spent budget is not refunded)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").action(async (opts) => {
38119
38647
  const globals = program2.opts();
38120
38648
  const tokenResult = await resolveToken(globals.token);
38121
38649
  const token = tokenResult.ok ? tokenResult.data.token : void 0;
38122
- const sessionId = opts.sessionId || process.env.CLAUDE_SESSION_ID || void 0;
38650
+ const sessionId = opts.sessionId || envSessionId();
38123
38651
  const found = resolveIgnoreState(ignoreStateKeys(token, sessionId));
38124
38652
  const active = resolveActive(found?.state ?? null, Math.floor(Date.now() / 1e3));
38125
38653
  if (!found || !active) {
@@ -38134,7 +38662,7 @@ function registerIgnoreCommand(program2) {
38134
38662
 
38135
38663
  // src/commands/waive.ts
38136
38664
  var import_node_crypto20 = require("node:crypto");
38137
- var import_node_fs62 = require("node:fs");
38665
+ var import_node_fs64 = require("node:fs");
38138
38666
  function registerWaiveCommand(program2) {
38139
38667
  program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
38140
38668
  const globals = program2.opts();
@@ -38163,7 +38691,7 @@ function registerWaiveCommand(program2) {
38163
38691
  if (opts.file) {
38164
38692
  body2.file = opts.file;
38165
38693
  try {
38166
- body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs62.readFileSync)(opts.file)).digest("hex");
38694
+ body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs64.readFileSync)(opts.file)).digest("hex");
38167
38695
  } catch {
38168
38696
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
38169
38697
  process.exit(1);
@@ -38188,10 +38716,10 @@ function registerWaiveCommand(program2) {
38188
38716
  }
38189
38717
 
38190
38718
  // src/commands/init.ts
38191
- var import_node_fs67 = require("node:fs");
38719
+ var import_node_fs69 = require("node:fs");
38192
38720
  var import_promises20 = require("node:fs/promises");
38193
- var import_yaml6 = __toESM2(require_dist());
38194
- var import_node_path52 = require("node:path");
38721
+ var import_yaml7 = __toESM2(require_dist());
38722
+ var import_node_path55 = require("node:path");
38195
38723
  var import_node_os11 = require("node:os");
38196
38724
  var import_node_child_process19 = require("node:child_process");
38197
38725
 
@@ -38226,12 +38754,12 @@ function printBanner(opts) {
38226
38754
  const color = colorEnabled();
38227
38755
  const version = `v${cliVersion()}`;
38228
38756
  const art = [WORDMARK, WORDMARK_NARROW].find((a) => artWidth(a) <= columns) ?? null;
38229
- const dim = (text) => color ? `${DIM3}${text}${RESET2}` : text;
38757
+ const dim = (text2) => color ? `${DIM3}${text2}${RESET2}` : text2;
38230
38758
  process.stderr.write("\n");
38231
38759
  if (!art) {
38232
38760
  const candidates2 = [`Verity ${version}`, "Verity"];
38233
- const text = candidates2.find((c) => c.length + INDENT.length <= columns);
38234
- if (text) process.stderr.write(`${INDENT}${dim(text)}
38761
+ const text2 = candidates2.find((c) => c.length + INDENT.length <= columns);
38762
+ if (text2) process.stderr.write(`${INDENT}${dim(text2)}
38235
38763
  `);
38236
38764
  process.stderr.write("\n");
38237
38765
  return;
@@ -38271,7 +38799,7 @@ function printPhase(n, of, title, subtitle) {
38271
38799
  }
38272
38800
 
38273
38801
  // src/commands/doctor.ts
38274
- var import_node_fs63 = require("node:fs");
38802
+ var import_node_fs65 = require("node:fs");
38275
38803
 
38276
38804
  // src/lib/prereqs.ts
38277
38805
  var import_node_child_process16 = require("node:child_process");
@@ -38479,11 +39007,11 @@ async function buildReport() {
38479
39007
  const hooks = wiring.status;
38480
39008
  const provenance = cliProvenance();
38481
39009
  const telemetry = await checkTelemetry();
38482
- const hasConfig = (0, import_node_fs63.existsSync)(projectPath(CODACY_CONFIG_FILE));
39010
+ const hasConfig = (0, import_node_fs65.existsSync)(projectPath(CODACY_CONFIG_FILE));
38483
39011
  const artifacts = {
38484
- standard: (0, import_node_fs63.existsSync)(projectPath(STANDARD_FILE)),
39012
+ standard: (0, import_node_fs65.existsSync)(projectPath(STANDARD_FILE)),
38485
39013
  analysisConfig: hasConfig,
38486
- verityMd: (0, import_node_fs63.existsSync)(projectPath(VERITY_MD_FILE)),
39014
+ verityMd: (0, import_node_fs65.existsSync)(projectPath(VERITY_MD_FILE)),
38487
39015
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
38488
39016
  };
38489
39017
  const next = [];
@@ -38642,8 +39170,8 @@ function registerDoctorCommand(program2) {
38642
39170
  }
38643
39171
 
38644
39172
  // src/commands/migrate.ts
38645
- var import_node_fs64 = require("node:fs");
38646
- var import_node_path49 = require("node:path");
39173
+ var import_node_fs66 = require("node:fs");
39174
+ var import_node_path52 = require("node:path");
38647
39175
  var import_node_child_process17 = require("node:child_process");
38648
39176
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
38649
39177
  function defaultNpmRemover(pkg) {
@@ -38680,12 +39208,12 @@ async function runMigration(opts = {}) {
38680
39208
  return { actions, migrated: actions.length > 0 };
38681
39209
  }
38682
39210
  function migrateProjectDir(root, actions) {
38683
- const gateDir = (0, import_node_path49.join)(root, ".gate");
38684
- const verityDir = (0, import_node_path49.join)(root, ".verity");
38685
- if ((0, import_node_fs64.existsSync)(gateDir) && !(0, import_node_fs64.existsSync)(verityDir)) {
39211
+ const gateDir = (0, import_node_path52.join)(root, ".gate");
39212
+ const verityDir = (0, import_node_path52.join)(root, ".verity");
39213
+ if ((0, import_node_fs66.existsSync)(gateDir) && !(0, import_node_fs66.existsSync)(verityDir)) {
38686
39214
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
38687
39215
  }
38688
- if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
39216
+ if ((0, import_node_fs66.existsSync)(gateDir) && (0, import_node_fs66.existsSync)(verityDir)) {
38689
39217
  return migrateProjectDirCarry(gateDir, verityDir, actions);
38690
39218
  }
38691
39219
  return false;
@@ -38706,13 +39234,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
38706
39234
  }
38707
39235
  }
38708
39236
  if (moved) {
38709
- if ((0, import_node_fs64.existsSync)(gateDir)) {
39237
+ if ((0, import_node_fs66.existsSync)(gateDir)) {
38710
39238
  const carried = carryLegacyContents(gateDir, verityDir);
38711
39239
  if (carried > 0) {
38712
39240
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
38713
39241
  }
38714
39242
  try {
38715
- (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
39243
+ (0, import_node_fs66.rmSync)(gateDir, { recursive: true, force: true });
38716
39244
  } catch {
38717
39245
  }
38718
39246
  }
@@ -38728,18 +39256,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
38728
39256
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
38729
39257
  }
38730
39258
  try {
38731
- (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
39259
+ (0, import_node_fs66.rmSync)(gateDir, { recursive: true, force: true });
38732
39260
  } catch {
38733
39261
  }
38734
39262
  return carried > 0;
38735
39263
  }
38736
39264
  function migrateGlobalCredentials(home, actions) {
38737
39265
  if (!home) return;
38738
- const gateCreds = (0, import_node_path49.join)(home, ".gate", "credentials");
38739
- const verityCreds = (0, import_node_path49.join)(home, ".verity", "credentials");
38740
- if (!(0, import_node_fs64.existsSync)(gateCreds)) return;
38741
- if (!(0, import_node_fs64.existsSync)(verityCreds)) {
38742
- (0, import_node_fs64.mkdirSync)((0, import_node_path49.join)(home, ".verity"), { recursive: true });
39266
+ const gateCreds = (0, import_node_path52.join)(home, ".gate", "credentials");
39267
+ const verityCreds = (0, import_node_path52.join)(home, ".verity", "credentials");
39268
+ if (!(0, import_node_fs66.existsSync)(gateCreds)) return;
39269
+ if (!(0, import_node_fs66.existsSync)(verityCreds)) {
39270
+ (0, import_node_fs66.mkdirSync)((0, import_node_path52.join)(home, ".verity"), { recursive: true });
38743
39271
  moveFile(gateCreds, verityCreds);
38744
39272
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
38745
39273
  return;
@@ -38761,8 +39289,8 @@ async function migrateLegacyHooks(root, actions) {
38761
39289
  }
38762
39290
  }
38763
39291
  async function migrateClaudeMd(root, actions) {
38764
- const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38765
- const hadLegacyBlock = (0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
39292
+ const claudeMd = (0, import_node_path52.join)(root, "CLAUDE.md");
39293
+ const hadLegacyBlock = (0, import_node_fs66.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38766
39294
  if (!hadLegacyBlock) return;
38767
39295
  try {
38768
39296
  await ensureClaudeMdPointer(root);
@@ -38772,9 +39300,9 @@ async function migrateClaudeMd(root, actions) {
38772
39300
  }
38773
39301
  }
38774
39302
  function migrateStandardFile(root, actions) {
38775
- const gateMd = (0, import_node_path49.join)(root, "GATE.md");
38776
- const verityMd = (0, import_node_path49.join)(root, "VERITY.md");
38777
- if (!(0, import_node_fs64.existsSync)(gateMd) || (0, import_node_fs64.existsSync)(verityMd)) return;
39303
+ const gateMd = (0, import_node_path52.join)(root, "GATE.md");
39304
+ const verityMd = (0, import_node_path52.join)(root, "VERITY.md");
39305
+ if (!(0, import_node_fs66.existsSync)(gateMd) || (0, import_node_fs66.existsSync)(verityMd)) return;
38778
39306
  let moved = false;
38779
39307
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
38780
39308
  try {
@@ -38786,12 +39314,12 @@ function migrateStandardFile(root, actions) {
38786
39314
  if (!moved) moveFile(gateMd, verityMd);
38787
39315
  const content = readFileSyncSafe(verityMd);
38788
39316
  const refreshed = content.split("GATE.md").join("VERITY.md");
38789
- if (refreshed !== content) (0, import_node_fs64.writeFileSync)(verityMd, refreshed);
39317
+ if (refreshed !== content) (0, import_node_fs66.writeFileSync)(verityMd, refreshed);
38790
39318
  actions.push("Renamed GATE.md \u2192 VERITY.md");
38791
39319
  }
38792
39320
  async function migrateTelemetryHeaders(root, actions) {
38793
- const file = (0, import_node_path49.join)(root, ".claude", "settings.local.json");
38794
- if (!(0, import_node_fs64.existsSync)(file)) return;
39321
+ const file = (0, import_node_path52.join)(root, ".claude", "settings.local.json");
39322
+ if (!(0, import_node_fs66.existsSync)(file)) return;
38795
39323
  let settings;
38796
39324
  try {
38797
39325
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -38838,15 +39366,15 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
38838
39366
  toAppend.push(line2.replace(/\r$/, ""));
38839
39367
  }
38840
39368
  if (toAppend.length > 0) {
38841
- const sep6 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
38842
- (0, import_node_fs64.writeFileSync)(verityCreds, verityContent + sep6 + toAppend.join("\n") + "\n");
39369
+ const sep7 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
39370
+ (0, import_node_fs66.writeFileSync)(verityCreds, verityContent + sep7 + toAppend.join("\n") + "\n");
38843
39371
  }
38844
- (0, import_node_fs64.rmSync)(gateCreds, { force: true });
39372
+ (0, import_node_fs66.rmSync)(gateCreds, { force: true });
38845
39373
  return toAppend.length;
38846
39374
  }
38847
39375
  function readFileSyncSafe(path) {
38848
39376
  try {
38849
- return (0, import_node_fs64.readFileSync)(path, "utf-8");
39377
+ return (0, import_node_fs66.readFileSync)(path, "utf-8");
38850
39378
  } catch {
38851
39379
  return "";
38852
39380
  }
@@ -38861,35 +39389,35 @@ function hasStagedChanges(root) {
38861
39389
  }
38862
39390
  function moveDir(from, to) {
38863
39391
  try {
38864
- (0, import_node_fs64.renameSync)(from, to);
39392
+ (0, import_node_fs66.renameSync)(from, to);
38865
39393
  } catch (err2) {
38866
39394
  if (err2.code !== "EXDEV") throw err2;
38867
- (0, import_node_fs64.cpSync)(from, to, { recursive: true });
38868
- (0, import_node_fs64.rmSync)(from, { recursive: true, force: true });
39395
+ (0, import_node_fs66.cpSync)(from, to, { recursive: true });
39396
+ (0, import_node_fs66.rmSync)(from, { recursive: true, force: true });
38869
39397
  }
38870
39398
  }
38871
39399
  function moveFile(from, to) {
38872
39400
  try {
38873
- (0, import_node_fs64.renameSync)(from, to);
39401
+ (0, import_node_fs66.renameSync)(from, to);
38874
39402
  } catch (err2) {
38875
39403
  if (err2.code !== "EXDEV") throw err2;
38876
- (0, import_node_fs64.cpSync)(from, to);
38877
- (0, import_node_fs64.rmSync)(from, { force: true });
39404
+ (0, import_node_fs66.cpSync)(from, to);
39405
+ (0, import_node_fs66.rmSync)(from, { force: true });
38878
39406
  }
38879
39407
  }
38880
39408
  function carryLegacyContents(gateDir, verityDir) {
38881
39409
  let copied = 0;
38882
39410
  const walk2 = (relDir) => {
38883
- const srcDir = (0, import_node_path49.join)(gateDir, relDir);
38884
- for (const entry of (0, import_node_fs64.readdirSync)(srcDir)) {
38885
- const rel = relDir ? (0, import_node_path49.join)(relDir, entry) : entry;
38886
- const src = (0, import_node_path49.join)(gateDir, rel);
38887
- const dest = (0, import_node_path49.join)(verityDir, rel);
38888
- if ((0, import_node_fs64.statSync)(src).isDirectory()) {
39411
+ const srcDir = (0, import_node_path52.join)(gateDir, relDir);
39412
+ for (const entry of (0, import_node_fs66.readdirSync)(srcDir)) {
39413
+ const rel = relDir ? (0, import_node_path52.join)(relDir, entry) : entry;
39414
+ const src = (0, import_node_path52.join)(gateDir, rel);
39415
+ const dest = (0, import_node_path52.join)(verityDir, rel);
39416
+ if ((0, import_node_fs66.statSync)(src).isDirectory()) {
38889
39417
  walk2(rel);
38890
- } else if (!(0, import_node_fs64.existsSync)(dest)) {
38891
- (0, import_node_fs64.mkdirSync)((0, import_node_path49.dirname)(dest), { recursive: true });
38892
- (0, import_node_fs64.cpSync)(src, dest);
39418
+ } else if (!(0, import_node_fs66.existsSync)(dest)) {
39419
+ (0, import_node_fs66.mkdirSync)((0, import_node_path52.dirname)(dest), { recursive: true });
39420
+ (0, import_node_fs66.cpSync)(src, dest);
38893
39421
  copied++;
38894
39422
  }
38895
39423
  }
@@ -38898,22 +39426,22 @@ function carryLegacyContents(gateDir, verityDir) {
38898
39426
  return copied;
38899
39427
  }
38900
39428
  async function needsMigration(root = repoRoot()) {
38901
- const gateDir = (0, import_node_path49.join)(root, ".gate");
38902
- const verityDir = (0, import_node_path49.join)(root, ".verity");
38903
- if ((0, import_node_fs64.existsSync)(gateDir) && !(0, import_node_fs64.existsSync)(verityDir)) return true;
38904
- if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
38905
- if ((0, import_node_fs64.existsSync)((0, import_node_path49.join)(gateDir, "credentials")) && !(0, import_node_fs64.existsSync)((0, import_node_path49.join)(verityDir, "credentials"))) {
39429
+ const gateDir = (0, import_node_path52.join)(root, ".gate");
39430
+ const verityDir = (0, import_node_path52.join)(root, ".verity");
39431
+ if ((0, import_node_fs66.existsSync)(gateDir) && !(0, import_node_fs66.existsSync)(verityDir)) return true;
39432
+ if ((0, import_node_fs66.existsSync)(gateDir) && (0, import_node_fs66.existsSync)(verityDir)) {
39433
+ if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(gateDir, "credentials")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(verityDir, "credentials"))) {
38906
39434
  return true;
38907
39435
  }
38908
- if ((0, import_node_fs64.existsSync)((0, import_node_path49.join)(gateDir, "memory")) && !(0, import_node_fs64.existsSync)((0, import_node_path49.join)(verityDir, "memory"))) {
39436
+ if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(gateDir, "memory")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(verityDir, "memory"))) {
38909
39437
  return true;
38910
39438
  }
38911
39439
  }
38912
- const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38913
- if ((0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
39440
+ const claudeMd = (0, import_node_path52.join)(root, "CLAUDE.md");
39441
+ if ((0, import_node_fs66.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38914
39442
  return true;
38915
39443
  }
38916
- if ((0, import_node_fs64.existsSync)((0, import_node_path49.join)(root, "GATE.md")) && !(0, import_node_fs64.existsSync)((0, import_node_path49.join)(root, "VERITY.md"))) {
39444
+ if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(root, "GATE.md")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(root, "VERITY.md"))) {
38917
39445
  return true;
38918
39446
  }
38919
39447
  if (await hasLegacyHooksAt(root)) return true;
@@ -39015,7 +39543,7 @@ var DIM4 = "\x1B[2m";
39015
39543
  var BOLD2 = "\x1B[1m";
39016
39544
  var RESET3 = "\x1B[0m";
39017
39545
  function renderSelect(question, choices, state, mode2, color = colorEnabled()) {
39018
- const paint = (text, code) => color ? `${code}${text}${RESET3}` : text;
39546
+ const paint = (text2, code) => color ? `${code}${text2}${RESET3}` : text2;
39019
39547
  const lines = ["", ` ${question}`];
39020
39548
  const labelOf = (c) => `${c.label}${c.recommended ? " (recommended)" : ""}`;
39021
39549
  const gutter = Math.max(...choices.map((c) => labelOf(c).length));
@@ -39194,11 +39722,11 @@ async function promptMultiSelect(question, choices, fallback) {
39194
39722
  }
39195
39723
 
39196
39724
  // src/lib/prove/lean-install.ts
39197
- var import_node_fs65 = require("node:fs");
39725
+ var import_node_fs67 = require("node:fs");
39198
39726
  var import_node_crypto21 = require("node:crypto");
39199
39727
  var import_node_child_process18 = require("node:child_process");
39200
39728
  var import_node_os10 = require("node:os");
39201
- var import_node_path50 = require("node:path");
39729
+ var import_node_path53 = require("node:path");
39202
39730
  var import_promises18 = require("node:stream/promises");
39203
39731
  var import_node_stream = require("node:stream");
39204
39732
  var RELEASES = "https://releases.lean-lang.org/lean4";
@@ -39209,10 +39737,10 @@ function freeBytes(dir) {
39209
39737
  let d = dir;
39210
39738
  for (let i2 = 0; i2 < 64; i2++) {
39211
39739
  try {
39212
- const st = (0, import_node_fs65.statfsSync)(d);
39740
+ const st = (0, import_node_fs67.statfsSync)(d);
39213
39741
  return Number(st.bavail) * Number(st.bsize);
39214
39742
  } catch {
39215
- const up = (0, import_node_path50.join)(d, "..");
39743
+ const up = (0, import_node_path53.join)(d, "..");
39216
39744
  if (up === d) return null;
39217
39745
  d = up;
39218
39746
  }
@@ -39234,7 +39762,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
39234
39762
  function sha256File(path) {
39235
39763
  return new Promise((resolve9, reject) => {
39236
39764
  const hash = (0, import_node_crypto21.createHash)("sha256");
39237
- (0, import_node_fs65.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
39765
+ (0, import_node_fs67.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
39238
39766
  });
39239
39767
  }
39240
39768
  async function verifyDownload(zip, asset, version = pinnedVersion()) {
@@ -39254,7 +39782,7 @@ function leanAssetName(version = pinnedVersion()) {
39254
39782
  return suffix ? `lean-${v}-${suffix}.zip` : null;
39255
39783
  }
39256
39784
  function pinnedVersionDir(env = process.env) {
39257
- return (0, import_node_path50.join)(verityLeanHome(env), pinnedVersion());
39785
+ return (0, import_node_path53.join)(verityLeanHome(env), pinnedVersion());
39258
39786
  }
39259
39787
  function lakeBinary() {
39260
39788
  return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
@@ -39265,12 +39793,12 @@ function unzip(zip, dest) {
39265
39793
  for (const [cmd, args2] of attempts) {
39266
39794
  try {
39267
39795
  (0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
39268
- if ((0, import_node_fs65.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
39796
+ if ((0, import_node_fs67.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
39269
39797
  errors.push(`${cmd}: produced nothing`);
39270
39798
  } catch (err2) {
39271
39799
  errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
39272
39800
  try {
39273
- for (const e of (0, import_node_fs65.readdirSync)(dest)) (0, import_node_fs65.rmSync)((0, import_node_path50.join)(dest, e), { recursive: true, force: true });
39801
+ for (const e of (0, import_node_fs67.readdirSync)(dest)) (0, import_node_fs67.rmSync)((0, import_node_path53.join)(dest, e), { recursive: true, force: true });
39274
39802
  } catch {
39275
39803
  }
39276
39804
  }
@@ -39296,7 +39824,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
39296
39824
  seen += chunk.length;
39297
39825
  onProgress(seen, total);
39298
39826
  });
39299
- await (0, import_promises18.pipeline)(stream, (0, import_node_fs65.createWriteStream)(dest), { signal: ctrl.signal });
39827
+ await (0, import_promises18.pipeline)(stream, (0, import_node_fs67.createWriteStream)(dest), { signal: ctrl.signal });
39300
39828
  } catch (err2) {
39301
39829
  if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
39302
39830
  throw err2;
@@ -39346,10 +39874,10 @@ async function installLean(opts = {}) {
39346
39874
  const gb = (n) => (n / 1024 ** 3).toFixed(1);
39347
39875
  return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
39348
39876
  }
39349
- const tmp = (0, import_node_path50.join)(home, ".tmp");
39350
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39351
- (0, import_node_fs65.mkdirSync)(tmp, { recursive: true });
39352
- const zip = (0, import_node_path50.join)(tmp, asset);
39877
+ const tmp = (0, import_node_path53.join)(home, ".tmp");
39878
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39879
+ (0, import_node_fs67.mkdirSync)(tmp, { recursive: true });
39880
+ const zip = (0, import_node_path53.join)(tmp, asset);
39353
39881
  say(`downloading ${url}`);
39354
39882
  let lastPct = -1;
39355
39883
  try {
@@ -39362,41 +39890,41 @@ async function installLean(opts = {}) {
39362
39890
  }
39363
39891
  });
39364
39892
  } catch (err2) {
39365
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39893
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39366
39894
  return { ok: false, error: err2.message };
39367
39895
  }
39368
39896
  say("verifying checksum");
39369
39897
  const verified = await verifyDownload(zip, asset);
39370
39898
  if (!verified.ok) {
39371
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39899
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39372
39900
  return { ok: false, error: verified.error };
39373
39901
  }
39374
39902
  say("unpacking (this takes a minute)");
39375
- const unpack = (0, import_node_path50.join)(tmp, "unpack");
39376
- (0, import_node_fs65.mkdirSync)(unpack);
39903
+ const unpack = (0, import_node_path53.join)(tmp, "unpack");
39904
+ (0, import_node_fs67.mkdirSync)(unpack);
39377
39905
  const unpacked = unzip(zip, unpack);
39378
39906
  if (!unpacked.ok) {
39379
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39907
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39380
39908
  return { ok: false, error: `unpack failed: ${unpacked.error}` };
39381
39909
  }
39382
- const entries = (0, import_node_fs65.readdirSync)(unpack);
39383
- const top = entries.length === 1 && (0, import_node_fs65.statSync)((0, import_node_path50.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path50.join)(unpack, entries[0]) : unpack;
39384
- if (!(0, import_node_fs65.existsSync)((0, import_node_path50.join)(top, "bin", lakeBinary()))) {
39385
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39910
+ const entries = (0, import_node_fs67.readdirSync)(unpack);
39911
+ const top = entries.length === 1 && (0, import_node_fs67.statSync)((0, import_node_path53.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path53.join)(unpack, entries[0]) : unpack;
39912
+ if (!(0, import_node_fs67.existsSync)((0, import_node_path53.join)(top, "bin", lakeBinary()))) {
39913
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39386
39914
  return { ok: false, error: "the archive did not contain bin/lake" };
39387
39915
  }
39388
- (0, import_node_fs65.rmSync)(dir, { recursive: true, force: true });
39389
- (0, import_node_fs65.mkdirSync)(home, { recursive: true });
39390
- (0, import_node_fs65.renameSync)(top, dir);
39391
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39916
+ (0, import_node_fs67.rmSync)(dir, { recursive: true, force: true });
39917
+ (0, import_node_fs67.mkdirSync)(home, { recursive: true });
39918
+ (0, import_node_fs67.renameSync)(top, dir);
39919
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39392
39920
  return { ok: true, dir };
39393
39921
  }
39394
39922
 
39395
39923
  // src/lib/remote-config.ts
39396
- var import_node_fs66 = require("node:fs");
39924
+ var import_node_fs68 = require("node:fs");
39397
39925
  var import_promises19 = require("node:fs/promises");
39398
- var import_node_path51 = require("node:path");
39399
- var import_yaml5 = __toESM2(require_dist());
39926
+ var import_node_path54 = require("node:path");
39927
+ var import_yaml6 = __toESM2(require_dist());
39400
39928
  var IGNORE_RIDER = "verityignore";
39401
39929
  async function fetchRemoteSetup(opts) {
39402
39930
  const standard = await apiRequest({
@@ -39436,11 +39964,11 @@ async function adoptRemoteSetup(found, opts) {
39436
39964
  const content = { ...found.standard.content };
39437
39965
  const rider = typeof content[IGNORE_RIDER] === "string" ? content[IGNORE_RIDER] : null;
39438
39966
  delete content[IGNORE_RIDER];
39439
- await writeOut(STANDARD_FILE, (0, import_yaml5.stringify)(content));
39967
+ await writeOut(STANDARD_FILE, (0, import_yaml6.stringify)(content));
39440
39968
  written.push(STANDARD_FILE);
39441
39969
  if (rider !== null) {
39442
39970
  const localIgnore = projectPath(VERITYIGNORE_FILE);
39443
- if (!(0, import_node_fs66.existsSync)(localIgnore)) {
39971
+ if (!(0, import_node_fs68.existsSync)(localIgnore)) {
39444
39972
  await writeOut(VERITYIGNORE_FILE, rider);
39445
39973
  written.push(VERITYIGNORE_FILE);
39446
39974
  } else {
@@ -39471,9 +39999,9 @@ async function adoptRemoteSetup(found, opts) {
39471
39999
  written.push(VERITY_MD_FILE);
39472
40000
  return { written, notes };
39473
40001
  }
39474
- async function writeOut(relative6, body2) {
39475
- const target = projectPath(relative6);
39476
- await (0, import_promises19.mkdir)((0, import_node_path51.dirname)(target), { recursive: true });
40002
+ async function writeOut(relative7, body2) {
40003
+ const target = projectPath(relative7);
40004
+ await (0, import_promises19.mkdir)((0, import_node_path54.dirname)(target), { recursive: true });
39477
40005
  await (0, import_promises19.writeFile)(target, body2);
39478
40006
  }
39479
40007
  function describeRemote(found) {
@@ -39590,15 +40118,15 @@ async function runOptionalAuth(resolution, opts = {}) {
39590
40118
  }
39591
40119
  function resolveDataDir2() {
39592
40120
  const candidates2 = [
39593
- (0, import_node_path52.join)(__dirname, "..", "data"),
40121
+ (0, import_node_path55.join)(__dirname, "..", "data"),
39594
40122
  // installed: node_modules/@codacy/verity-cli/data
39595
- (0, import_node_path52.join)(__dirname, "..", "..", "data"),
40123
+ (0, import_node_path55.join)(__dirname, "..", "..", "data"),
39596
40124
  // edge case: nested resolution
39597
- (0, import_node_path52.join)(process.cwd(), "cli", "data")
40125
+ (0, import_node_path55.join)(process.cwd(), "cli", "data")
39598
40126
  // local dev: running from repo root
39599
40127
  ];
39600
40128
  for (const candidate of candidates2) {
39601
- if ((0, import_node_fs67.existsSync)((0, import_node_path52.join)(candidate, "skills"))) {
40129
+ if ((0, import_node_fs69.existsSync)((0, import_node_path55.join)(candidate, "skills"))) {
39602
40130
  return candidate;
39603
40131
  }
39604
40132
  }
@@ -39614,9 +40142,9 @@ async function skillIsCurrent(src, dest) {
39614
40142
  const list2 = (dir) => {
39615
40143
  const out2 = [];
39616
40144
  const walk2 = (d, prefix) => {
39617
- for (const e of (0, import_node_fs67.readdirSync)(d, { withFileTypes: true })) {
40145
+ for (const e of (0, import_node_fs69.readdirSync)(d, { withFileTypes: true })) {
39618
40146
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
39619
- if (e.isDirectory()) walk2((0, import_node_path52.join)(d, e.name), rel);
40147
+ if (e.isDirectory()) walk2((0, import_node_path55.join)(d, e.name), rel);
39620
40148
  else if (e.isFile()) out2.push(rel);
39621
40149
  }
39622
40150
  };
@@ -39627,8 +40155,8 @@ async function skillIsCurrent(src, dest) {
39627
40155
  const shipped = list2(src);
39628
40156
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
39629
40157
  for (const rel of shipped) {
39630
- const a = await (0, import_promises20.readFile)((0, import_node_path52.join)(src, rel), "utf-8");
39631
- const b = await (0, import_promises20.readFile)((0, import_node_path52.join)(dest, rel), "utf-8");
40158
+ const a = await (0, import_promises20.readFile)((0, import_node_path55.join)(src, rel), "utf-8");
40159
+ const b = await (0, import_promises20.readFile)((0, import_node_path55.join)(dest, rel), "utf-8");
39632
40160
  if (a !== b) return false;
39633
40161
  }
39634
40162
  return true;
@@ -39724,7 +40252,7 @@ function parseTelemetryAnswer(raw) {
39724
40252
  return null;
39725
40253
  }
39726
40254
  function insideClaudeCode() {
39727
- return !!process.env.CLAUDECODE || !!process.env.CLAUDE_SESSION_ID;
40255
+ return !!process.env.CLAUDECODE || !!envSessionId();
39728
40256
  }
39729
40257
  function resumeDeferredPending(previous) {
39730
40258
  return previous?.telemetry === "deferred";
@@ -39831,13 +40359,13 @@ async function synthesizeLocally(opts) {
39831
40359
  async function healStaleAnalysisConfig(globals) {
39832
40360
  const configPath = projectPath(CODACY_CONFIG_FILE);
39833
40361
  const standardPath = projectPath(STANDARD_FILE);
39834
- if (!(0, import_node_fs67.existsSync)(configPath) || !(0, import_node_fs67.existsSync)(standardPath)) return;
40362
+ if (!(0, import_node_fs69.existsSync)(configPath) || !(0, import_node_fs69.existsSync)(standardPath)) return;
39835
40363
  const validation = validatePatternIds();
39836
40364
  if (validation.status !== "invalid") return;
39837
40365
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
39838
40366
  printWarn(" running silently with nothing enabled. Re-deriving it from your Standard\u2026");
39839
40367
  try {
39840
- const content = (0, import_yaml6.parse)(await (0, import_promises20.readFile)(standardPath, "utf-8"));
40368
+ const content = (0, import_yaml7.parse)(await (0, import_promises20.readFile)(standardPath, "utf-8"));
39841
40369
  const derived = await deriveConfigForStandard(content);
39842
40370
  for (const path of derived.written) printInfo(` ${path} \u2713 (re-derived)`);
39843
40371
  for (const note of derived.notes) printWarn(` ${note}`);
@@ -39928,17 +40456,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
39928
40456
  async function installSkills(force, step) {
39929
40457
  step("Installing skills");
39930
40458
  const dataDir = resolveDataDir2();
39931
- const skillsSource = (0, import_node_path52.join)(dataDir, "skills");
40459
+ const skillsSource = (0, import_node_path55.join)(dataDir, "skills");
39932
40460
  const skillsDest = ".claude/skills";
39933
40461
  let skillsInstalled = 0;
39934
40462
  for (const skill of SKILLS) {
39935
- const src = (0, import_node_path52.join)(skillsSource, skill);
39936
- const dest = (0, import_node_path52.join)(skillsDest, skill);
39937
- if (!(0, import_node_fs67.existsSync)(src)) {
40463
+ const src = (0, import_node_path55.join)(skillsSource, skill);
40464
+ const dest = (0, import_node_path55.join)(skillsDest, skill);
40465
+ if (!(0, import_node_fs69.existsSync)(src)) {
39938
40466
  printWarn(` Skill data not found: ${skill}`);
39939
40467
  continue;
39940
40468
  }
39941
- if ((0, import_node_fs67.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
40469
+ if ((0, import_node_fs69.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39942
40470
  skillsInstalled++;
39943
40471
  continue;
39944
40472
  }
@@ -40087,7 +40615,7 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
40087
40615
  if (!toolchain) {
40088
40616
  const dir = pinnedVersionDir();
40089
40617
  const home = (0, import_node_os11.homedir)();
40090
- const shown = dir.startsWith(home + import_node_path52.sep) ? `~${dir.slice(home.length)}` : dir;
40618
+ const shown = dir.startsWith(home + import_node_path55.sep) ? `~${dir.slice(home.length)}` : dir;
40091
40619
  console.log("");
40092
40620
  console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
40093
40621
  }
@@ -40146,7 +40674,7 @@ function registerInitCommand(program2) {
40146
40674
  const staleMarker = clearStalePluginMarker();
40147
40675
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
40148
40676
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
40149
- const isProject = projectMarkers.some((m) => (0, import_node_fs67.existsSync)(m));
40677
+ const isProject = projectMarkers.some((m) => (0, import_node_fs69.existsSync)(m));
40150
40678
  if (!isProject) {
40151
40679
  printError("No project detected in the current directory.");
40152
40680
  printInfo('Run "verity init" from your project root.');
@@ -40249,7 +40777,7 @@ function registerInitCommand(program2) {
40249
40777
  untrackMemory: opts.untrackMemory === true,
40250
40778
  untrackState: opts.untrackState === true
40251
40779
  });
40252
- const globalVerityDir = (0, import_node_path52.join)(process.env.HOME ?? "", ".verity");
40780
+ const globalVerityDir = (0, import_node_path55.join)(process.env.HOME ?? "", ".verity");
40253
40781
  await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
40254
40782
  console.log("");
40255
40783
  step("Wiring Claude Code hooks");
@@ -40324,7 +40852,7 @@ function registerInitCommand(program2) {
40324
40852
  }
40325
40853
  step("Your project's Standard");
40326
40854
  let haveStandard = false;
40327
- if ((0, import_node_fs67.existsSync)(projectPath(STANDARD_FILE))) {
40855
+ if ((0, import_node_fs69.existsSync)(projectPath(STANDARD_FILE))) {
40328
40856
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
40329
40857
  haveStandard = true;
40330
40858
  } else {
@@ -40354,7 +40882,7 @@ function registerInitCommand(program2) {
40354
40882
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
40355
40883
  init: {
40356
40884
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
40357
- cli_version: true ? "0.34.1" : "dev"
40885
+ cli_version: true ? "0.34.2-experimental.2cad220" : "dev"
40358
40886
  }
40359
40887
  });
40360
40888
  } catch (err2) {
@@ -40404,8 +40932,8 @@ function registerInitCommand(program2) {
40404
40932
  }
40405
40933
 
40406
40934
  // src/commands/uninstall.ts
40407
- var import_node_fs68 = require("node:fs");
40408
- var import_node_path53 = require("node:path");
40935
+ var import_node_fs70 = require("node:fs");
40936
+ var import_node_path56 = require("node:path");
40409
40937
  function registerUninstallCommand(program2) {
40410
40938
  program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
40411
40939
  const dryRun = opts.dryRun ?? false;
@@ -40414,11 +40942,11 @@ function registerUninstallCommand(program2) {
40414
40942
  const actions = [];
40415
40943
  const skillsRoot = projectPath(".claude/skills");
40416
40944
  for (const name2 of PROJECT_SKILL_NAMES) {
40417
- const dir = (0, import_node_path53.join)(skillsRoot, name2);
40418
- if ((0, import_node_fs68.existsSync)(dir)) {
40945
+ const dir = (0, import_node_path56.join)(skillsRoot, name2);
40946
+ if ((0, import_node_fs70.existsSync)(dir)) {
40419
40947
  actions.push({
40420
40948
  label: `Remove .claude/skills/${name2}/`,
40421
- apply: () => (0, import_node_fs68.rmSync)(dir, { recursive: true, force: true })
40949
+ apply: () => (0, import_node_fs70.rmSync)(dir, { recursive: true, force: true })
40422
40950
  });
40423
40951
  }
40424
40952
  }
@@ -40432,24 +40960,24 @@ function registerUninstallCommand(program2) {
40432
40960
  });
40433
40961
  }
40434
40962
  const verityDir = projectPath(VERITY_DIR);
40435
- if ((0, import_node_fs68.existsSync)(verityDir)) {
40963
+ if ((0, import_node_fs70.existsSync)(verityDir)) {
40436
40964
  actions.push({
40437
40965
  label: `Remove ${VERITY_DIR}/`,
40438
- apply: () => (0, import_node_fs68.rmSync)(verityDir, { recursive: true, force: true })
40966
+ apply: () => (0, import_node_fs70.rmSync)(verityDir, { recursive: true, force: true })
40439
40967
  });
40440
40968
  }
40441
40969
  if (!keepVerityMd) {
40442
40970
  const verityMd = projectPath(VERITY_MD_FILE);
40443
- if ((0, import_node_fs68.existsSync)(verityMd)) {
40971
+ if ((0, import_node_fs70.existsSync)(verityMd)) {
40444
40972
  actions.push({
40445
40973
  label: `Remove ${VERITY_MD_FILE}`,
40446
- apply: () => (0, import_node_fs68.rmSync)(verityMd, { force: true })
40974
+ apply: () => (0, import_node_fs70.rmSync)(verityMd, { force: true })
40447
40975
  });
40448
40976
  }
40449
40977
  }
40450
40978
  const cleanupEmptyDir = (path) => {
40451
- if ((0, import_node_fs68.existsSync)(path) && (0, import_node_fs68.statSync)(path).isDirectory() && (0, import_node_fs68.readdirSync)(path).length === 0) {
40452
- (0, import_node_fs68.rmdirSync)(path);
40979
+ if ((0, import_node_fs70.existsSync)(path) && (0, import_node_fs70.statSync)(path).isDirectory() && (0, import_node_fs70.readdirSync)(path).length === 0) {
40980
+ (0, import_node_fs70.rmdirSync)(path);
40453
40981
  }
40454
40982
  };
40455
40983
  actions.push({
@@ -40460,11 +40988,11 @@ function registerUninstallCommand(program2) {
40460
40988
  }
40461
40989
  });
40462
40990
  const home = process.env.HOME ?? "";
40463
- const globalVerityDir = (0, import_node_path53.join)(home, ".verity");
40464
- if (purgeGlobal && (0, import_node_fs68.existsSync)(globalVerityDir)) {
40991
+ const globalVerityDir = (0, import_node_path56.join)(home, ".verity");
40992
+ if (purgeGlobal && (0, import_node_fs70.existsSync)(globalVerityDir)) {
40465
40993
  actions.push({
40466
40994
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
40467
- apply: () => (0, import_node_fs68.rmSync)(globalVerityDir, { recursive: true, force: true })
40995
+ apply: () => (0, import_node_fs70.rmSync)(globalVerityDir, { recursive: true, force: true })
40468
40996
  });
40469
40997
  }
40470
40998
  if (actions.length === 0) {
@@ -40491,9 +41019,26 @@ function registerUninstallCommand(program2) {
40491
41019
 
40492
41020
  // src/commands/task.ts
40493
41021
  function memoryPath() {
40494
- const sid = process.env.CLAUDE_SESSION_ID;
41022
+ const sid = envSessionId();
40495
41023
  return sid ? `/memory?session_id=${encodeURIComponent(sid)}` : "/memory";
40496
41024
  }
41025
+ var TASK_STATUSES = ["active", "closed", "merged"];
41026
+ var TASK_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
41027
+ function isTaskId(value) {
41028
+ return typeof value === "string" && TASK_ID.test(value);
41029
+ }
41030
+ function taskListPath(status) {
41031
+ if (status === void 0) return "/tasks";
41032
+ if (!TASK_STATUSES.includes(status)) return null;
41033
+ return `/tasks?status=${encodeURIComponent(status)}`;
41034
+ }
41035
+ function taskActionPath(taskId, action) {
41036
+ return isTaskId(taskId) ? `/tasks/${encodeURIComponent(taskId)}/${action}` : null;
41037
+ }
41038
+ function refuse(message) {
41039
+ printError(message);
41040
+ process.exit(1);
41041
+ }
40497
41042
  function timeAgo2(isoDate) {
40498
41043
  const ms = Date.now() - new Date(isoDate).getTime();
40499
41044
  const mins = Math.floor(ms / 6e4);
@@ -40521,10 +41066,11 @@ function registerTaskCommands(program2) {
40521
41066
  task.command("list").description("List tasks").option("--status <status>", "Filter by status (active, closed, merged)").action(async (opts) => {
40522
41067
  const globals = program2.opts();
40523
41068
  const { token, serviceUrl } = await getAuth(globals);
40524
- const statusParam = opts.status ? `?status=${opts.status}` : "";
41069
+ const listPath = taskListPath(opts.status);
41070
+ if (!listPath) refuse(`Unknown status ${JSON.stringify(String(opts.status).slice(0, 40))} \u2014 use one of: ${TASK_STATUSES.join(", ")}`);
40525
41071
  const result = await apiRequest({
40526
41072
  method: "GET",
40527
- path: `/tasks${statusParam}`,
41073
+ path: listPath,
40528
41074
  serviceUrl,
40529
41075
  token,
40530
41076
  verbose: globals.verbose,
@@ -40573,9 +41119,11 @@ function registerTaskCommands(program2) {
40573
41119
  }
40574
41120
  taskId = ct.id;
40575
41121
  }
41122
+ const closePath = taskActionPath(taskId, "close");
41123
+ if (!closePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
40576
41124
  const result = await apiRequest({
40577
41125
  method: "POST",
40578
- path: `/tasks/${taskId}/close`,
41126
+ path: closePath,
40579
41127
  serviceUrl,
40580
41128
  token,
40581
41129
  verbose: globals.verbose,
@@ -40622,9 +41170,11 @@ function registerTaskCommands(program2) {
40622
41170
  }
40623
41171
  taskId = ct.id;
40624
41172
  }
41173
+ const renamePath = taskActionPath(taskId, "rename");
41174
+ if (!renamePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
40625
41175
  const result = await apiRequest({
40626
41176
  method: "POST",
40627
- path: `/tasks/${taskId}/rename`,
41177
+ path: renamePath,
40628
41178
  serviceUrl,
40629
41179
  token,
40630
41180
  body: { label: label2.slice(0, 120) },
@@ -40639,6 +41189,9 @@ function registerTaskCommands(program2) {
40639
41189
  });
40640
41190
  task.command("merge <source> <target>").description("Merge source task into target task").action(async (source2, target) => {
40641
41191
  const globals = program2.opts();
41192
+ if (!isTaskId(source2) || !isTaskId(target)) {
41193
+ refuse("task merge takes two task ids (UUIDs): `verity task merge <source> <target>`");
41194
+ }
40642
41195
  const { token, serviceUrl } = await getAuth(globals);
40643
41196
  const result = await apiRequest({
40644
41197
  method: "POST",
@@ -40658,8 +41211,8 @@ function registerTaskCommands(program2) {
40658
41211
  }
40659
41212
 
40660
41213
  // src/commands/reset.ts
40661
- var import_node_fs69 = require("node:fs");
40662
- var import_node_path54 = require("node:path");
41214
+ var import_node_fs71 = require("node:fs");
41215
+ var import_node_path57 = require("node:path");
40663
41216
  function registerResetCommand(program2) {
40664
41217
  program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
40665
41218
  const globals = program2.opts();
@@ -40668,78 +41221,95 @@ function registerResetCommand(program2) {
40668
41221
  const tokenResult = await resolveToken(globals.token);
40669
41222
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
40670
41223
  if (tokenResult.ok && urlResult.ok) {
41224
+ const sessionId = envSessionId();
40671
41225
  const mem = await apiRequest({
40672
41226
  method: "GET",
40673
- path: process.env.CLAUDE_SESSION_ID ? `/memory?session_id=${encodeURIComponent(process.env.CLAUDE_SESSION_ID)}` : "/memory",
41227
+ path: sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory",
40674
41228
  serviceUrl: urlResult.data,
40675
41229
  token: tokenResult.data.token,
40676
41230
  timeout: 1e4,
40677
41231
  cmd: "reset_lookup"
40678
41232
  });
40679
41233
  const ct = mem.ok ? mem.data.current_task : null;
40680
- if (ct?.id) {
41234
+ const closePath = ct?.id ? taskActionPath(ct.id, "close") : null;
41235
+ if (ct?.id && !closePath) {
41236
+ printError("The current task in the service response has a malformed id \u2014 not closing it.");
41237
+ }
41238
+ if (closePath) {
40681
41239
  const closeResult = await apiRequest({
40682
41240
  method: "POST",
40683
- path: `/tasks/${ct.id}/close`,
41241
+ path: closePath,
40684
41242
  serviceUrl: urlResult.data,
40685
41243
  token: tokenResult.data.token,
40686
41244
  timeout: 1e4,
40687
41245
  cmd: "reset_close"
40688
41246
  });
40689
41247
  if (closeResult.ok) {
40690
- printInfo(`Closed task: "${ct.label}"`);
41248
+ printInfo(`Closed task: "${terminalText(ct?.label, 200) || "(unnamed)"}"`);
40691
41249
  }
40692
41250
  }
40693
41251
  }
40694
41252
  } catch {
40695
41253
  }
40696
41254
  }
40697
- const cacheDir = projectPath(CACHE_DIR);
40698
- let purged = 0;
40699
- if ((0, import_node_fs69.existsSync)(cacheDir)) {
40700
- for (const entry of (0, import_node_fs69.readdirSync)(cacheDir)) {
40701
- if (entry.startsWith("pending-")) {
40702
- try {
40703
- (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(cacheDir, entry));
40704
- purged++;
40705
- } catch {
40706
- }
40707
- }
40708
- }
40709
- }
41255
+ const purged = purgeVerityDir((0, import_node_path57.basename)(CACHE_DIR), (name2) => name2.startsWith("pending-"));
41256
+ if (purged === null) printError(`Did not purge ${CACHE_DIR}: it is not a directory inside ${VERITY_DIR}.`);
41257
+ const stateDir2 = projectPath(VERITY_DIR);
40710
41258
  const filesToClear = [
40711
- projectPath(INTENT_FILE),
40712
- projectPath(HASH_FILE),
40713
- projectPath(BASELINE_SHA_FILE),
40714
- projectPath(`${VERITY_DIR}/.iteration-count`),
40715
- projectPath(`${VERITY_DIR}/.last-analysis`)
41259
+ (0, import_node_path57.basename)(INTENT_FILE),
41260
+ (0, import_node_path57.basename)(HASH_FILE),
41261
+ (0, import_node_path57.basename)(BASELINE_SHA_FILE),
41262
+ ".iteration-count",
41263
+ ".last-analysis"
40716
41264
  ];
40717
- for (const file of filesToClear) {
40718
- if ((0, import_node_fs69.existsSync)(file)) {
40719
- try {
40720
- (0, import_node_fs69.writeFileSync)(file, "");
40721
- } catch {
40722
- }
41265
+ for (const name2 of filesToClear) {
41266
+ if (lstatOrNull((0, import_node_path57.join)(stateDir2, name2)) && !replaceInRoot(stateDir2, name2, "")) {
41267
+ printError(`Did not clear ${VERITY_DIR}/${name2}: it is not a regular file inside ${VERITY_DIR}.`);
40723
41268
  }
40724
41269
  }
40725
41270
  if (opts.all) {
40726
- const logsDir = projectPath(`${VERITY_DIR}/.logs`);
40727
- if ((0, import_node_fs69.existsSync)(logsDir)) {
40728
- for (const entry of (0, import_node_fs69.readdirSync)(logsDir)) {
40729
- try {
40730
- (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(logsDir, entry));
40731
- } catch {
40732
- }
40733
- }
40734
- }
40735
- printInfo("Cleared diagnostic logs.");
41271
+ const logs = purgeVerityDir(".logs", () => true);
41272
+ if (logs === null) printError(`Did not clear ${VERITY_DIR}/.logs: it is not a directory inside ${VERITY_DIR}.`);
41273
+ else printInfo("Cleared diagnostic logs.");
40736
41274
  }
40737
- printInfo(`Reset complete. Purged ${purged} cached request${purged !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
41275
+ const count = purged ?? 0;
41276
+ printInfo(`Reset complete. Purged ${count} cached request${count !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
40738
41277
  });
40739
41278
  }
41279
+ function lstatOrNull(path) {
41280
+ try {
41281
+ return (0, import_node_fs71.lstatSync)(path);
41282
+ } catch {
41283
+ return null;
41284
+ }
41285
+ }
41286
+ function purgeVerityDir(child, select) {
41287
+ const verityDir = projectPath(VERITY_DIR);
41288
+ const dir = (0, import_node_path57.join)(verityDir, child);
41289
+ const parent = lstatOrNull(verityDir);
41290
+ const st = lstatOrNull(dir);
41291
+ if (!st) return 0;
41292
+ if (!parent || parent.isSymbolicLink() || !parent.isDirectory()) return null;
41293
+ if (st.isSymbolicLink() || !st.isDirectory()) return null;
41294
+ try {
41295
+ if ((0, import_node_fs71.realpathSync)(dir) !== (0, import_node_path57.join)((0, import_node_fs71.realpathSync)(verityDir), child)) return null;
41296
+ } catch {
41297
+ return null;
41298
+ }
41299
+ let removed = 0;
41300
+ for (const entry of (0, import_node_fs71.readdirSync)(dir, { withFileTypes: true })) {
41301
+ if (entry.isDirectory() || !select(entry.name)) continue;
41302
+ try {
41303
+ (0, import_node_fs71.unlinkSync)((0, import_node_path57.join)(dir, entry.name));
41304
+ removed++;
41305
+ } catch {
41306
+ }
41307
+ }
41308
+ return removed;
41309
+ }
40740
41310
 
40741
41311
  // src/commands/reflect.ts
40742
- var import_node_fs70 = require("node:fs");
41312
+ var import_node_fs72 = require("node:fs");
40743
41313
 
40744
41314
  // src/lib/reflection-globs.ts
40745
41315
  var MAX_GLOBS = 6;
@@ -40753,11 +41323,11 @@ function resolve7(token, treePaths) {
40753
41323
  const matches = treePaths.filter((p) => p.endsWith(suffix));
40754
41324
  return matches.length === 1 ? matches[0] : null;
40755
41325
  }
40756
- function deriveFileGlobs(text, treePaths) {
40757
- if (!text || treePaths.length === 0) return [];
41326
+ function deriveFileGlobs(text2, treePaths) {
41327
+ if (!text2 || treePaths.length === 0) return [];
40758
41328
  const out2 = [];
40759
41329
  const seen = /* @__PURE__ */ new Set();
40760
- for (const raw of text.match(PATH_TOKEN) ?? []) {
41330
+ for (const raw of text2.match(PATH_TOKEN) ?? []) {
40761
41331
  const token = clean(raw);
40762
41332
  if (!token) continue;
40763
41333
  const path = resolve7(token, treePaths);
@@ -40777,7 +41347,7 @@ async function writeNodeToDisk(args2) {
40777
41347
  { treePaths: listTrackedFiles(), recordBaseline: false }
40778
41348
  );
40779
41349
  if (written === 0) return false;
40780
- return (0, import_node_fs70.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
41350
+ return (0, import_node_fs72.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40781
41351
  } catch {
40782
41352
  return false;
40783
41353
  }
@@ -40808,7 +41378,7 @@ function registerReflectCommand(program2) {
40808
41378
  let taskResolution = "flag";
40809
41379
  let inheritedGlobs = [];
40810
41380
  if (!taskId) {
40811
- const sessionId = process.env.CLAUDE_SESSION_ID ?? "";
41381
+ const sessionId = envSessionId() ?? "";
40812
41382
  const memPath = sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory";
40813
41383
  const mem = await apiRequest({
40814
41384
  method: "GET",
@@ -40853,7 +41423,7 @@ function registerReflectCommand(program2) {
40853
41423
  const userInput = input.text;
40854
41424
  if (userInput) {
40855
41425
  const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
40856
- const kind = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
41426
+ const kind2 = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
40857
41427
  const confirmed = opts.confirmed === true;
40858
41428
  const source2 = confirmed ? "user" : "agent";
40859
41429
  const explicitGlobs = Array.isArray(opts.fileGlobs) ? opts.fileGlobs.map((g) => g.trim()).filter(Boolean) : [];
@@ -40865,7 +41435,7 @@ function registerReflectCommand(program2) {
40865
41435
  serviceUrl,
40866
41436
  token,
40867
41437
  body: {
40868
- kind,
41438
+ kind: kind2,
40869
41439
  title: userInput.slice(0, 200),
40870
41440
  body: userInput,
40871
41441
  domains: [],
@@ -41214,9 +41784,9 @@ function registerRunCommand(program2) {
41214
41784
  }
41215
41785
 
41216
41786
  // src/commands/telemetry.ts
41217
- var import_node_fs71 = require("node:fs");
41787
+ var import_node_fs73 = require("node:fs");
41218
41788
  async function recordTelemetryChoice(choice) {
41219
- if (!(0, import_node_fs71.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41789
+ if (!(0, import_node_fs73.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41220
41790
  try {
41221
41791
  if ((await readSetupState())?.telemetry === choice) return;
41222
41792
  await writeSetupState({ telemetry: choice });
@@ -41293,8 +41863,8 @@ function registerTelemetryCommands(program2) {
41293
41863
  }
41294
41864
 
41295
41865
  // src/commands/prove.ts
41296
- var import_node_fs72 = require("node:fs");
41297
- var import_node_path55 = require("node:path");
41866
+ var import_node_fs74 = require("node:fs");
41867
+ var import_node_path58 = require("node:path");
41298
41868
 
41299
41869
  // src/lib/prove/hint-pool.ts
41300
41870
  var STOP2 = /* @__PURE__ */ new Set([
@@ -41436,7 +42006,7 @@ function registerProveCommand(program2) {
41436
42006
  process.exit(2);
41437
42007
  }
41438
42008
  const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
41439
- let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)) || ".") });
42009
+ let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path58.relative)(root, (0, import_node_path58.resolve)(p)) || ".") });
41440
42010
  if (opts.hint && paths.length === 0) {
41441
42011
  const hit = hintMatches(root, opts.hint);
41442
42012
  if (hit.files.length > 0) {
@@ -41490,7 +42060,7 @@ function registerProveCommand(program2) {
41490
42060
  });
41491
42061
  prove.command("check [model]").description("Elaborate a model (or every model) with the local Lean toolchain and report each property").option("--timeout <ms>", "Per-model timeout in ms", "120000").option("--json", "Machine-readable output").action((model, opts) => {
41492
42062
  const root = repoRoot();
41493
- if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
42063
+ if (!(0, import_node_fs74.existsSync)((0, import_node_path58.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41494
42064
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41495
42065
  process.exit(2);
41496
42066
  }
@@ -41514,7 +42084,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41514
42084
  const reports = [];
41515
42085
  for (const f of files) {
41516
42086
  const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
41517
- report.file = (0, import_node_path55.relative)(root, f);
42087
+ report.file = (0, import_node_path58.relative)(root, f);
41518
42088
  reports.push(report);
41519
42089
  try {
41520
42090
  writeResult(root, report);
@@ -41552,7 +42122,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41552
42122
  printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
41553
42123
  process.exit(2);
41554
42124
  }
41555
- if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
42125
+ if (!(0, import_node_fs74.existsSync)((0, import_node_path58.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41556
42126
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41557
42127
  process.exit(2);
41558
42128
  }
@@ -41583,7 +42153,7 @@ ${report.error ?? ""}`);
41583
42153
  printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
41584
42154
  return;
41585
42155
  }
41586
- const modelSource = readRegularFileInRoot(root, (0, import_node_path55.relative)(root, file), 512 * 1024);
42156
+ const modelSource = readRegularFileInRoot(root, (0, import_node_path58.relative)(root, file), 512 * 1024);
41587
42157
  if (!opts.json) printInfo(`replaying ${targets.length} counterexample(s) of ${model} in network-less containers (${Math.min(targets.length, REPLAY_CONCURRENCY)} at a time)\u2026`);
41588
42158
  const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
41589
42159
  const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
@@ -41603,7 +42173,7 @@ ${report.error ?? ""}`);
41603
42173
  });
41604
42174
  prove.command("auto [files...]").description("The formal phase the pre-push guard runs: select one risky symbol among changed files, generate a model, check it, replay counterexamples (default files: the commits ahead of upstream)").option("--deadline <ms>", "Budget for the whole phase", "170000").option("--json", "Machine-readable output").action(async (paths, opts) => {
41605
42175
  const root = repoRoot();
41606
- let files = paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)));
42176
+ let files = paths.map((p) => (0, import_node_path58.relative)(root, (0, import_node_path58.resolve)(p)));
41607
42177
  if (files.length === 0) {
41608
42178
  const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
41609
42179
  const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
@@ -41613,8 +42183,10 @@ ${report.error ?? ""}`);
41613
42183
  printInfo("No changed files to consider (nothing ahead of upstream). Pass paths explicitly.");
41614
42184
  return;
41615
42185
  }
41616
- const prep = await prepareFormalPhase(root, process.env, await proveAuth(program2) ?? void 0);
42186
+ const auth2 = await proveAuth(program2);
42187
+ const prep = await prepareFormalPhase(root, process.env, auth2 ?? void 0);
41617
42188
  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);
42189
+ if (auth2) await postPhaseRecord(outcome, { moment: "on-demand", parentRunId: null, pushedFiles: [] }, auth2);
41618
42190
  if (opts.json) {
41619
42191
  printJson(outcome);
41620
42192
  } else {
@@ -41675,7 +42247,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41675
42247
  let revise;
41676
42248
  if (opts.revise) {
41677
42249
  const existing = resolveModelFile(root, opts.revise);
41678
- const src = existing ? readRegularFileInRoot(root, (0, import_node_path55.relative)(root, existing), 64 * 1024) : null;
42250
+ const src = existing ? readRegularFileInRoot(root, (0, import_node_path58.relative)(root, existing), 64 * 1024) : null;
41679
42251
  if (!src || !src.ok || !opts.note) {
41680
42252
  printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
41681
42253
  process.exit(2);
@@ -41688,21 +42260,22 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41688
42260
  printError("Verity library did not build");
41689
42261
  process.exit(2);
41690
42262
  }
41691
- const deps = defaultDeps({ auth: auth2 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc, tier: "deep" });
42263
+ const deps = await onDemandDeps(root, { auth: auth2 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc });
41692
42264
  if (!opts.json) printInfo(`asking the Verity service for a model of ${symbol || `${file}:${opts.lines}`} \u2026`);
41693
42265
  const out2 = await generateAndCheck(root, { file, symbol: symbol || `${file}:${opts.lines}`, lines, hint: opts.hint, revise }, { deps, maxRounds: 3 });
41694
42266
  if (!out2.ok) {
41695
42267
  if (opts.json) printJson(out2);
41696
- else printError(`${out2.error} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""}) \u2014 write the model by hand (Models/README.md) or narrow the target`);
42268
+ else printError(out2.rounds === 0 ? out2.error : `${out2.error} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""}) \u2014 write the model by hand (Models/README.md) or narrow the target`);
41697
42269
  process.exit(2);
41698
42270
  }
42271
+ if (out2.warning && !opts.json) printWarn(out2.warning);
41699
42272
  try {
41700
42273
  writeResult(root, out2.report);
41701
42274
  } catch (err2) {
41702
42275
  if (!(err2 instanceof SafeWriteError)) throw err2;
41703
42276
  }
41704
42277
  if (opts.json) {
41705
- printJson({ name: out2.name, file: out2.file, rounds: out2.rounds, cost_usd: out2.costUsd, report: { ...out2.report, passes: reportPasses(out2.report), summary: summarize(out2.report) } });
42278
+ printJson({ name: out2.name, file: out2.file, rounds: out2.rounds, cost_usd: out2.costUsd, ...out2.warning ? { warning: out2.warning } : {}, report: { ...out2.report, passes: reportPasses(out2.report), summary: summarize(out2.report) } });
41706
42279
  return;
41707
42280
  }
41708
42281
  printInfo(`wrote ${out2.file} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""})`);
@@ -41714,8 +42287,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41714
42287
  });
41715
42288
  prove.command("waive <file>").description("Dismiss the remembered formal finding(s) on a file for its current bytes \u2014 the accepted-risk path for a formal block").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action((file, opts) => {
41716
42289
  const root = repoRoot();
41717
- const rel0 = (0, import_node_path55.relative)(root, (0, import_node_path55.isAbsolute)(file) ? file : (0, import_node_path55.join)(root, file)).replace(/\\/g, "/");
41718
- const rel = rel0.startsWith("..") || (0, import_node_path55.isAbsolute)(rel0) ? null : rel0;
42290
+ const rel0 = (0, import_node_path58.relative)(root, (0, import_node_path58.isAbsolute)(file) ? file : (0, import_node_path58.join)(root, file)).replace(/\\/g, "/");
42291
+ const rel = rel0.startsWith("..") || (0, import_node_path58.isAbsolute)(rel0) ? null : rel0;
41719
42292
  if (!rel) {
41720
42293
  printError(`${file} is not inside this repository`);
41721
42294
  process.exit(2);
@@ -41731,8 +42304,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41731
42304
  });
41732
42305
  prove.command("hash <file>").description("Print the sha256 of a file, for a model header (Verity.model \u2026 sha256). Path is REPO-relative, as in the header").action((file) => {
41733
42306
  const root = repoRoot();
41734
- const rel = (0, import_node_path55.relative)(root, (0, import_node_path55.isAbsolute)(file) ? file : (0, import_node_path55.join)(root, file));
41735
- const digest = rel.startsWith("..") || (0, import_node_path55.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
42307
+ const rel = (0, import_node_path58.relative)(root, (0, import_node_path58.isAbsolute)(file) ? file : (0, import_node_path58.join)(root, file));
42308
+ const digest = rel.startsWith("..") || (0, import_node_path58.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
41736
42309
  if (!digest) {
41737
42310
  printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
41738
42311
  process.exit(2);
@@ -41766,10 +42339,10 @@ function refreshScaffold(root) {
41766
42339
  }
41767
42340
 
41768
42341
  // src/commands/lean.ts
41769
- var import_node_fs73 = require("node:fs");
42342
+ var import_node_fs75 = require("node:fs");
41770
42343
  var import_node_child_process20 = require("node:child_process");
41771
42344
  var import_node_os12 = require("node:os");
41772
- var import_node_path56 = require("node:path");
42345
+ var import_node_path59 = require("node:path");
41773
42346
  function registerLeanCommand(program2) {
41774
42347
  const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
41775
42348
  lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
@@ -41786,7 +42359,7 @@ function registerLeanCommand(program2) {
41786
42359
  const managed = pinnedVersionDir();
41787
42360
  const matches = version ? version.includes(pin) : false;
41788
42361
  if (opts.json) {
41789
- printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs73.existsSync)((0, import_node_path56.join)(managed, "bin")), asset: leanAssetName() });
42362
+ printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs75.existsSync)((0, import_node_path59.join)(managed, "bin")), asset: leanAssetName() });
41790
42363
  return;
41791
42364
  }
41792
42365
  printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
@@ -41804,7 +42377,7 @@ function registerLeanCommand(program2) {
41804
42377
  process.exit(2);
41805
42378
  }
41806
42379
  const dir = pinnedVersionDir();
41807
- if ((0, import_node_fs73.existsSync)((0, import_node_path56.join)(dir, "bin", "lake")) && !opts.force) {
42380
+ if ((0, import_node_fs75.existsSync)((0, import_node_path59.join)(dir, "bin", "lake")) && !opts.force) {
41808
42381
  printInfo(`already installed at ${dir}`);
41809
42382
  return;
41810
42383
  }
@@ -41840,18 +42413,18 @@ function registerLeanCommand(program2) {
41840
42413
  });
41841
42414
  lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
41842
42415
  const dir = pinnedVersionDir();
41843
- if (!(0, import_node_fs73.existsSync)(dir)) {
42416
+ if (!(0, import_node_fs75.existsSync)(dir)) {
41844
42417
  printInfo("nothing to remove");
41845
42418
  return;
41846
42419
  }
41847
- (0, import_node_fs73.rmSync)(dir, { recursive: true, force: true });
42420
+ (0, import_node_fs75.rmSync)(dir, { recursive: true, force: true });
41848
42421
  printInfo(`removed ${dir}`);
41849
42422
  });
41850
42423
  }
41851
42424
 
41852
42425
  // src/cli.ts
41853
- program.name("verity").description("CLI for Verity quality gate service").version("0.34.1").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) => {
41854
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.1");
42426
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.2-experimental.2cad220").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
42427
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.2-experimental.2cad220");
41855
42428
  setUserNamedServiceUrl(program.opts().serviceUrl);
41856
42429
  try {
41857
42430
  await foldLegacyLocalCredential();