@codacy/verity-cli 0.34.0-experimental.dc0010f → 0.34.0-experimental.e086ee3

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
@@ -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: sep5, value } = collItem;
6978
+ const { start: start2, key, sep: sep6, value } = collItem;
6979
6979
  const keyProps = resolveProps.resolveProps(start2, {
6980
6980
  indicator: "explicit-key-ind",
6981
- next: key ?? sep5?.[0],
6981
+ next: key ?? sep6?.[0],
6982
6982
  offset,
6983
6983
  onError,
6984
6984
  parentIndent: bm.indent,
@@ -6992,7 +6992,7 @@ var require_resolve_block_map = __commonJS2({
6992
6992
  else if ("indent" in key && key.indent !== bm.indent)
6993
6993
  onError(offset, "BAD_INDENT", startColMsg);
6994
6994
  }
6995
- if (!keyProps.anchor && !keyProps.tag && !sep5) {
6995
+ if (!keyProps.anchor && !keyProps.tag && !sep6) {
6996
6996
  commentEnd = keyProps.end;
6997
6997
  if (keyProps.comment) {
6998
6998
  if (map.comment)
@@ -7016,7 +7016,7 @@ var require_resolve_block_map = __commonJS2({
7016
7016
  ctx.atKey = false;
7017
7017
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
7018
7018
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
7019
- const valueProps = resolveProps.resolveProps(sep5 ?? [], {
7019
+ const valueProps = resolveProps.resolveProps(sep6 ?? [], {
7020
7020
  indicator: "map-value-ind",
7021
7021
  next: value,
7022
7022
  offset: keyNode.range[2],
@@ -7032,7 +7032,7 @@ var require_resolve_block_map = __commonJS2({
7032
7032
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
7033
7033
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
7034
7034
  }
7035
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep5, null, valueProps, onError);
7035
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep6, null, valueProps, onError);
7036
7036
  if (ctx.schema.compat)
7037
7037
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
7038
7038
  offset = valueNode.range[2];
@@ -7123,7 +7123,7 @@ var require_resolve_end = __commonJS2({
7123
7123
  let comment = "";
7124
7124
  if (end) {
7125
7125
  let hasSpace = false;
7126
- let sep5 = "";
7126
+ let sep6 = "";
7127
7127
  for (const token of end) {
7128
7128
  const { source: source2, type } = token;
7129
7129
  switch (type) {
@@ -7137,13 +7137,13 @@ var require_resolve_end = __commonJS2({
7137
7137
  if (!comment)
7138
7138
  comment = cb;
7139
7139
  else
7140
- comment += sep5 + cb;
7141
- sep5 = "";
7140
+ comment += sep6 + cb;
7141
+ sep6 = "";
7142
7142
  break;
7143
7143
  }
7144
7144
  case "newline":
7145
7145
  if (comment)
7146
- sep5 += source2;
7146
+ sep6 += source2;
7147
7147
  hasSpace = true;
7148
7148
  break;
7149
7149
  default:
@@ -7186,18 +7186,18 @@ var require_resolve_flow_collection = __commonJS2({
7186
7186
  let offset = fc.offset + fc.start.source.length;
7187
7187
  for (let i2 = 0; i2 < fc.items.length; ++i2) {
7188
7188
  const collItem = fc.items[i2];
7189
- const { start: start2, key, sep: sep5, value } = collItem;
7189
+ const { start: start2, key, sep: sep6, value } = collItem;
7190
7190
  const props = resolveProps.resolveProps(start2, {
7191
7191
  flow: fcName,
7192
7192
  indicator: "explicit-key-ind",
7193
- next: key ?? sep5?.[0],
7193
+ next: key ?? sep6?.[0],
7194
7194
  offset,
7195
7195
  onError,
7196
7196
  parentIndent: fc.indent,
7197
7197
  startOnNewline: false
7198
7198
  });
7199
7199
  if (!props.found) {
7200
- if (!props.anchor && !props.tag && !sep5 && !value) {
7200
+ if (!props.anchor && !props.tag && !sep6 && !value) {
7201
7201
  if (i2 === 0 && props.comma)
7202
7202
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
7203
7203
  else if (i2 < fc.items.length - 1)
@@ -7251,8 +7251,8 @@ var require_resolve_flow_collection = __commonJS2({
7251
7251
  }
7252
7252
  }
7253
7253
  }
7254
- if (!isMap && !sep5 && !props.found) {
7255
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep5, null, props, onError);
7254
+ if (!isMap && !sep6 && !props.found) {
7255
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep6, null, props, onError);
7256
7256
  coll.items.push(valueNode);
7257
7257
  offset = valueNode.range[2];
7258
7258
  if (isBlock(value))
@@ -7264,7 +7264,7 @@ var require_resolve_flow_collection = __commonJS2({
7264
7264
  if (isBlock(key))
7265
7265
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
7266
7266
  ctx.atKey = false;
7267
- const valueProps = resolveProps.resolveProps(sep5 ?? [], {
7267
+ const valueProps = resolveProps.resolveProps(sep6 ?? [], {
7268
7268
  flow: fcName,
7269
7269
  indicator: "map-value-ind",
7270
7270
  next: value,
@@ -7275,8 +7275,8 @@ var require_resolve_flow_collection = __commonJS2({
7275
7275
  });
7276
7276
  if (valueProps.found) {
7277
7277
  if (!isMap && !props.found && ctx.options.strict) {
7278
- if (sep5)
7279
- for (const st of sep5) {
7278
+ if (sep6)
7279
+ for (const st of sep6) {
7280
7280
  if (st === valueProps.found)
7281
7281
  break;
7282
7282
  if (st.type === "newline") {
@@ -7293,7 +7293,7 @@ var require_resolve_flow_collection = __commonJS2({
7293
7293
  else
7294
7294
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
7295
7295
  }
7296
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep5, null, valueProps, onError) : null;
7296
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep6, null, valueProps, onError) : null;
7297
7297
  if (valueNode) {
7298
7298
  if (isBlock(value))
7299
7299
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -7473,7 +7473,7 @@ var require_resolve_block_scalar = __commonJS2({
7473
7473
  chompStart = i2 + 1;
7474
7474
  }
7475
7475
  let value = "";
7476
- let sep5 = "";
7476
+ let sep6 = "";
7477
7477
  let prevMoreIndented = false;
7478
7478
  for (let i2 = 0; i2 < contentStart; ++i2)
7479
7479
  value += lines[i2][0].slice(trimIndent) + "\n";
@@ -7490,24 +7490,24 @@ var require_resolve_block_scalar = __commonJS2({
7490
7490
  indent = "";
7491
7491
  }
7492
7492
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
7493
- value += sep5 + indent.slice(trimIndent) + content;
7494
- sep5 = "\n";
7493
+ value += sep6 + indent.slice(trimIndent) + content;
7494
+ sep6 = "\n";
7495
7495
  } else if (indent.length > trimIndent || content[0] === " ") {
7496
- if (sep5 === " ")
7497
- sep5 = "\n";
7498
- else if (!prevMoreIndented && sep5 === "\n")
7499
- sep5 = "\n\n";
7500
- value += sep5 + indent.slice(trimIndent) + content;
7501
- sep5 = "\n";
7496
+ if (sep6 === " ")
7497
+ sep6 = "\n";
7498
+ else if (!prevMoreIndented && sep6 === "\n")
7499
+ sep6 = "\n\n";
7500
+ value += sep6 + indent.slice(trimIndent) + content;
7501
+ sep6 = "\n";
7502
7502
  prevMoreIndented = true;
7503
7503
  } else if (content === "") {
7504
- if (sep5 === "\n")
7504
+ if (sep6 === "\n")
7505
7505
  value += "\n";
7506
7506
  else
7507
- sep5 = "\n";
7507
+ sep6 = "\n";
7508
7508
  } else {
7509
- value += sep5 + content;
7510
- sep5 = " ";
7509
+ value += sep6 + content;
7510
+ sep6 = " ";
7511
7511
  prevMoreIndented = false;
7512
7512
  }
7513
7513
  }
@@ -7689,25 +7689,25 @@ var require_resolve_flow_scalar = __commonJS2({
7689
7689
  if (!match)
7690
7690
  return source2;
7691
7691
  let res = match[1];
7692
- let sep5 = " ";
7692
+ let sep6 = " ";
7693
7693
  let pos = first.lastIndex;
7694
7694
  line2.lastIndex = pos;
7695
7695
  while (match = line2.exec(source2)) {
7696
7696
  if (match[1] === "") {
7697
- if (sep5 === "\n")
7698
- res += sep5;
7697
+ if (sep6 === "\n")
7698
+ res += sep6;
7699
7699
  else
7700
- sep5 = "\n";
7700
+ sep6 = "\n";
7701
7701
  } else {
7702
- res += sep5 + match[1];
7703
- sep5 = " ";
7702
+ res += sep6 + match[1];
7703
+ sep6 = " ";
7704
7704
  }
7705
7705
  pos = line2.lastIndex;
7706
7706
  }
7707
7707
  const last = /[ \t]*(.*)/sy;
7708
7708
  last.lastIndex = pos;
7709
7709
  match = last.exec(source2);
7710
- return res + sep5 + (match?.[1] ?? "");
7710
+ return res + sep6 + (match?.[1] ?? "");
7711
7711
  }
7712
7712
  function doubleQuotedValue(source2, onError) {
7713
7713
  let res = "";
@@ -8514,14 +8514,14 @@ var require_cst_stringify = __commonJS2({
8514
8514
  }
8515
8515
  }
8516
8516
  }
8517
- function stringifyItem({ start: start2, key, sep: sep5, value }) {
8517
+ function stringifyItem({ start: start2, key, sep: sep6, value }) {
8518
8518
  let res = "";
8519
8519
  for (const st of start2)
8520
8520
  res += st.source;
8521
8521
  if (key)
8522
8522
  res += stringifyToken(key);
8523
- if (sep5)
8524
- for (const st of sep5)
8523
+ if (sep6)
8524
+ for (const st of sep6)
8525
8525
  res += st.source;
8526
8526
  if (value)
8527
8527
  res += stringifyToken(value);
@@ -9671,18 +9671,18 @@ var require_parser = __commonJS2({
9671
9671
  if (this.type === "map-value-ind") {
9672
9672
  const prev = getPrevProps(this.peek(2));
9673
9673
  const start2 = getFirstKeyStartProps(prev);
9674
- let sep5;
9674
+ let sep6;
9675
9675
  if (scalar.end) {
9676
- sep5 = scalar.end;
9677
- sep5.push(this.sourceToken);
9676
+ sep6 = scalar.end;
9677
+ sep6.push(this.sourceToken);
9678
9678
  delete scalar.end;
9679
9679
  } else
9680
- sep5 = [this.sourceToken];
9680
+ sep6 = [this.sourceToken];
9681
9681
  const map = {
9682
9682
  type: "block-map",
9683
9683
  offset: scalar.offset,
9684
9684
  indent: scalar.indent,
9685
- items: [{ start: start2, key: scalar, sep: sep5 }]
9685
+ items: [{ start: start2, key: scalar, sep: sep6 }]
9686
9686
  };
9687
9687
  this.onKeyLine = true;
9688
9688
  this.stack[this.stack.length - 1] = map;
@@ -9835,15 +9835,15 @@ var require_parser = __commonJS2({
9835
9835
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
9836
9836
  const start3 = getFirstKeyStartProps(it.start);
9837
9837
  const key = it.key;
9838
- const sep5 = it.sep;
9839
- sep5.push(this.sourceToken);
9838
+ const sep6 = it.sep;
9839
+ sep6.push(this.sourceToken);
9840
9840
  delete it.key;
9841
9841
  delete it.sep;
9842
9842
  this.stack.push({
9843
9843
  type: "block-map",
9844
9844
  offset: this.offset,
9845
9845
  indent: this.indent,
9846
- items: [{ start: start3, key, sep: sep5 }]
9846
+ items: [{ start: start3, key, sep: sep6 }]
9847
9847
  });
9848
9848
  } else if (start2.length > 0) {
9849
9849
  it.sep = it.sep.concat(start2, this.sourceToken);
@@ -10037,13 +10037,13 @@ var require_parser = __commonJS2({
10037
10037
  const prev = getPrevProps(parent);
10038
10038
  const start2 = getFirstKeyStartProps(prev);
10039
10039
  fixFlowSeqItems(fc);
10040
- const sep5 = fc.end.splice(1, fc.end.length);
10041
- sep5.push(this.sourceToken);
10040
+ const sep6 = fc.end.splice(1, fc.end.length);
10041
+ sep6.push(this.sourceToken);
10042
10042
  const map = {
10043
10043
  type: "block-map",
10044
10044
  offset: fc.offset,
10045
10045
  indent: fc.indent,
10046
- items: [{ start: start2, key: fc, sep: sep5 }]
10046
+ items: [{ start: start2, key: fc, sep: sep6 }]
10047
10047
  };
10048
10048
  this.onKeyLine = true;
10049
10049
  this.stack[this.stack.length - 1] = map;
@@ -10435,13 +10435,13 @@ var require_web_tree_sitter2 = __commonJS2({
10435
10435
  }
10436
10436
  readAsync = /* @__PURE__ */ __name(async (url) => {
10437
10437
  if (isFileURI(url)) {
10438
- return new Promise((resolve8, reject) => {
10438
+ return new Promise((resolve9, reject) => {
10439
10439
  var xhr = new XMLHttpRequest();
10440
10440
  xhr.open("GET", url, true);
10441
10441
  xhr.responseType = "arraybuffer";
10442
10442
  xhr.onload = () => {
10443
10443
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
10444
- resolve8(xhr.response);
10444
+ resolve9(xhr.response);
10445
10445
  return;
10446
10446
  }
10447
10447
  reject(xhr.status);
@@ -10634,9 +10634,9 @@ var require_web_tree_sitter2 = __commonJS2({
10634
10634
  __name(receiveInstantiationResult, "receiveInstantiationResult");
10635
10635
  var info2 = getWasmImports();
10636
10636
  if (Module["instantiateWasm"]) {
10637
- return new Promise((resolve8, reject) => {
10637
+ return new Promise((resolve9, reject) => {
10638
10638
  Module["instantiateWasm"](info2, (mod, inst) => {
10639
- resolve8(receiveInstance(mod, inst));
10639
+ resolve9(receiveInstance(mod, inst));
10640
10640
  });
10641
10641
  });
10642
10642
  }
@@ -11969,8 +11969,8 @@ var require_web_tree_sitter2 = __commonJS2({
11969
11969
  if (runtimeInitialized) {
11970
11970
  moduleRtn = Module;
11971
11971
  } else {
11972
- moduleRtn = new Promise((resolve8, reject) => {
11973
- readyPromiseResolve = resolve8;
11972
+ moduleRtn = new Promise((resolve9, reject) => {
11973
+ readyPromiseResolve = resolve9;
11974
11974
  readyPromiseReject = reject;
11975
11975
  });
11976
11976
  }
@@ -14447,8 +14447,87 @@ var import_node_child_process4 = require("node:child_process");
14447
14447
 
14448
14448
  // src/constants.ts
14449
14449
  var import_node_child_process = require("node:child_process");
14450
+ var import_node_fs2 = require("node:fs");
14451
+ var import_node_path2 = require("node:path");
14452
+
14453
+ // src/lib/context-identity.ts
14454
+ var import_node_crypto = require("node:crypto");
14450
14455
  var import_node_fs = require("node:fs");
14456
+ var import_node_os = require("node:os");
14451
14457
  var import_node_path = require("node:path");
14458
+ var SHARED_SENTINELS = /* @__PURE__ */ new Set([
14459
+ "",
14460
+ "-",
14461
+ "n/a",
14462
+ "na",
14463
+ "none",
14464
+ "null",
14465
+ "undefined",
14466
+ "unknown",
14467
+ "anon",
14468
+ "anonymous",
14469
+ "default",
14470
+ "_default"
14471
+ ]);
14472
+ function isSharedSentinel(value) {
14473
+ if (value == null) return true;
14474
+ return SHARED_SENTINELS.has(value.trim().toLowerCase());
14475
+ }
14476
+ var ephemeral = /* @__PURE__ */ new Map();
14477
+ function ephemeralId(slot, width) {
14478
+ let id = ephemeral.get(slot);
14479
+ if (!id) {
14480
+ id = `eph-${(0, import_node_crypto.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
14481
+ ephemeral.set(slot, id);
14482
+ }
14483
+ return id;
14484
+ }
14485
+ function contextIdentity(input) {
14486
+ const tokenUsable = !isSharedSentinel(input.token ?? null);
14487
+ const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
14488
+ const userKey = tokenUsable ? (0, import_node_crypto.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
14489
+ const sessionKey2 = sessionUsable ? (0, import_node_crypto.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
14490
+ let treeKey = "no-tree";
14491
+ const rawTree = input.treeRoot;
14492
+ if (rawTree && !isSharedSentinel(rawTree)) {
14493
+ let resolved = rawTree;
14494
+ try {
14495
+ resolved = import_node_fs.realpathSync.native(rawTree);
14496
+ } catch {
14497
+ }
14498
+ treeKey = (0, import_node_crypto.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
14499
+ }
14500
+ return {
14501
+ userKey,
14502
+ treeKey,
14503
+ sessionKey: sessionKey2,
14504
+ userKeySource: tokenUsable ? "token" : "ephemeral",
14505
+ sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
14506
+ ephemeral: !tokenUsable || !sessionUsable
14507
+ };
14508
+ }
14509
+ function verityHome() {
14510
+ const override = process.env.VERITY_HOME;
14511
+ return override && override.trim() ? (0, import_node_path.resolve)(override) : (0, import_node_path.join)((0, import_node_os.homedir)(), ".verity");
14512
+ }
14513
+ function dossierDir(identity) {
14514
+ return (0, import_node_path.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
14515
+ }
14516
+ function treeDir(identity) {
14517
+ return (0, import_node_path.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
14518
+ }
14519
+ function scopeIdentity(token, sessionId) {
14520
+ const t = (token ?? "").trim();
14521
+ const s = (sessionId ?? "").trim();
14522
+ const userKey = t.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
14523
+ const sessionKey2 = s.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
14524
+ return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
14525
+ }
14526
+ function sessionScopeKey(token, sessionId) {
14527
+ return scopeIdentity(token, sessionId).bucket;
14528
+ }
14529
+
14530
+ // src/constants.ts
14452
14531
  var _repoRoot = null;
14453
14532
  function repoRoot() {
14454
14533
  if (_repoRoot === null) {
@@ -14476,17 +14555,36 @@ function mainWorktreeRoot() {
14476
14555
  _mainRoot = null;
14477
14556
  return _mainRoot;
14478
14557
  }
14479
- const abs = common.startsWith("/") ? common : (0, import_node_path.join)(repoRoot(), common);
14480
- _mainRoot = (0, import_node_path.dirname)(abs);
14558
+ const abs = common.startsWith("/") ? common : (0, import_node_path2.join)(repoRoot(), common);
14559
+ _mainRoot = (0, import_node_path2.dirname)(abs);
14481
14560
  } catch {
14482
14561
  _mainRoot = null;
14483
14562
  }
14484
14563
  return _mainRoot;
14485
14564
  }
14486
14565
  function verityConfigured() {
14487
- if ((0, import_node_fs.existsSync)((0, import_node_path.join)(repoRoot(), VERITY_DIR))) return true;
14566
+ if (isProjectVerityDir((0, import_node_path2.join)(repoRoot(), VERITY_DIR))) return true;
14488
14567
  const main = mainWorktreeRoot();
14489
- return !!main && (0, import_node_fs.existsSync)((0, import_node_path.join)(main, VERITY_DIR));
14568
+ return !!main && isProjectVerityDir((0, import_node_path2.join)(main, VERITY_DIR));
14569
+ }
14570
+ function isProjectVerityDir(dir) {
14571
+ return (0, import_node_fs2.existsSync)(dir) && !isMachineStore(dir);
14572
+ }
14573
+ function isMachineStore(dir) {
14574
+ const here = canonicalPath(dir);
14575
+ const stores = [process.env.HOME ? (0, import_node_path2.join)(process.env.HOME, VERITY_DIR) : null, verityHome()];
14576
+ return stores.some((s) => s !== null && canonicalPath(s) === here);
14577
+ }
14578
+ function canonicalPath(p) {
14579
+ try {
14580
+ return import_node_fs2.realpathSync.native(p);
14581
+ } catch {
14582
+ }
14583
+ try {
14584
+ return (0, import_node_path2.join)(import_node_fs2.realpathSync.native((0, import_node_path2.dirname)(p)), (0, import_node_path2.basename)(p));
14585
+ } catch {
14586
+ return (0, import_node_path2.resolve)(p);
14587
+ }
14490
14588
  }
14491
14589
  var VERITY_DIR = ".verity";
14492
14590
  var CREDENTIALS_FILE = `${VERITY_DIR}/credentials`;
@@ -14507,7 +14605,7 @@ var MEMORY_DIR = `${VERITY_DIR}/memory`;
14507
14605
  var CODACY_CONFIG_FILE = ".codacy/codacy.config.json";
14508
14606
  var VERITYIGNORE_FILE = ".verityignore";
14509
14607
  function projectPath(relativePath) {
14510
- return (0, import_node_path.join)(repoRoot(), relativePath);
14608
+ return (0, import_node_path2.join)(repoRoot(), relativePath);
14511
14609
  }
14512
14610
  var MAX_DELTA_BYTES = 194560;
14513
14611
  var MAX_FILES = 40;
@@ -14681,7 +14779,7 @@ function printVerbose(msg, verbose) {
14681
14779
  }
14682
14780
 
14683
14781
  // src/lib/debug-log.ts
14684
- var import_node_fs2 = require("node:fs");
14782
+ var import_node_fs3 = require("node:fs");
14685
14783
  function isDebugEnabled() {
14686
14784
  const v = process.env.VERITY_DEBUG;
14687
14785
  if (v === "0" || v === "false" || v === "off") return false;
@@ -14699,24 +14797,24 @@ function writeLine(obj) {
14699
14797
  try {
14700
14798
  const dir = projectPath(DEBUG_LOG_DIR);
14701
14799
  const file = projectPath(DEBUG_LOG_FILE);
14702
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
14800
+ (0, import_node_fs3.mkdirSync)(dir, { recursive: true });
14703
14801
  rotateIfNeeded(file);
14704
- (0, import_node_fs2.appendFileSync)(file, JSON.stringify(obj) + "\n");
14802
+ (0, import_node_fs3.appendFileSync)(file, JSON.stringify(obj) + "\n");
14705
14803
  } catch {
14706
14804
  }
14707
14805
  }
14708
14806
  function rotateIfNeeded(file) {
14709
14807
  try {
14710
- const s = (0, import_node_fs2.statSync)(file);
14808
+ const s = (0, import_node_fs3.statSync)(file);
14711
14809
  if (s.size < DEBUG_LOG_MAX_BYTES) return;
14712
- (0, import_node_fs2.renameSync)(file, `${file}.1`);
14810
+ (0, import_node_fs3.renameSync)(file, `${file}.1`);
14713
14811
  } catch {
14714
14812
  }
14715
14813
  }
14716
14814
 
14717
14815
  // src/lib/credentials.ts
14718
14816
  var import_promises = require("node:fs/promises");
14719
- var import_node_path2 = require("node:path");
14817
+ var import_node_path3 = require("node:path");
14720
14818
  var import_node_child_process2 = require("node:child_process");
14721
14819
  function globalCredentialsPath() {
14722
14820
  return `${process.env.HOME}/.verity/credentials`;
@@ -14791,7 +14889,7 @@ async function readGlobalCredential(remote) {
14791
14889
  }
14792
14890
  async function upsertGlobalCredential(remote, rec) {
14793
14891
  const path = globalCredentialsPath();
14794
- await (0, import_promises.mkdir)((0, import_node_path2.dirname)(path), { recursive: true });
14892
+ await (0, import_promises.mkdir)((0, import_node_path3.dirname)(path), { recursive: true });
14795
14893
  let content = "";
14796
14894
  try {
14797
14895
  content = await (0, import_promises.readFile)(path, "utf-8");
@@ -14935,10 +15033,10 @@ async function foldLegacyLocalCredential(remoteArg) {
14935
15033
 
14936
15034
  // src/lib/git.ts
14937
15035
  var import_node_child_process3 = require("node:child_process");
14938
- var import_node_fs3 = require("node:fs");
14939
- var import_node_path3 = require("node:path");
15036
+ var import_node_fs4 = require("node:fs");
15037
+ var import_node_path4 = require("node:path");
14940
15038
  function resolveFile(relpath) {
14941
- return (0, import_node_fs3.existsSync)(relpath) ? relpath : null;
15039
+ return (0, import_node_fs4.existsSync)(relpath) ? relpath : null;
14942
15040
  }
14943
15041
  function execGit(cmd) {
14944
15042
  try {
@@ -14956,7 +15054,7 @@ function readBaselineSha() {
14956
15054
  if (sha === null) return null;
14957
15055
  if (!commitResolves(sha)) {
14958
15056
  try {
14959
- (0, import_node_fs3.unlinkSync)(BASELINE_SHA_FILE);
15057
+ (0, import_node_fs4.unlinkSync)(BASELINE_SHA_FILE);
14960
15058
  } catch {
14961
15059
  }
14962
15060
  return null;
@@ -14964,10 +15062,10 @@ function readBaselineSha() {
14964
15062
  return sha;
14965
15063
  }
14966
15064
  function readRawBaselineSha() {
14967
- if (!(0, import_node_fs3.existsSync)(BASELINE_SHA_FILE)) return null;
15065
+ if (!(0, import_node_fs4.existsSync)(BASELINE_SHA_FILE)) return null;
14968
15066
  let sha;
14969
15067
  try {
14970
- sha = (0, import_node_fs3.readFileSync)(BASELINE_SHA_FILE, "utf-8").trim();
15068
+ sha = (0, import_node_fs4.readFileSync)(BASELINE_SHA_FILE, "utf-8").trim();
14971
15069
  } catch {
14972
15070
  return null;
14973
15071
  }
@@ -14976,8 +15074,8 @@ function readRawBaselineSha() {
14976
15074
  function writeBaselineSha(sha) {
14977
15075
  if (!SHA_RE.test(sha)) return;
14978
15076
  try {
14979
- (0, import_node_fs3.mkdirSync)((0, import_node_path3.dirname)(BASELINE_SHA_FILE), { recursive: true });
14980
- (0, import_node_fs3.writeFileSync)(BASELINE_SHA_FILE, sha);
15077
+ (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(BASELINE_SHA_FILE), { recursive: true });
15078
+ (0, import_node_fs4.writeFileSync)(BASELINE_SHA_FILE, sha);
14981
15079
  } catch {
14982
15080
  }
14983
15081
  }
@@ -15065,17 +15163,17 @@ function showContentAtRef(ref, repoRelPath) {
15065
15163
  }
15066
15164
  function filterAnalyzable(files) {
15067
15165
  return files.filter((f) => {
15068
- const ext = (0, import_node_path3.extname)(f).slice(1);
15166
+ const ext = (0, import_node_path4.extname)(f).slice(1);
15069
15167
  return ANALYZABLE_EXTENSIONS.has(ext);
15070
15168
  });
15071
15169
  }
15072
15170
  function filterReviewable(files) {
15073
15171
  return files.filter((f) => {
15074
- const ext = (0, import_node_path3.extname)(f).slice(1);
15172
+ const ext = (0, import_node_path4.extname)(f).slice(1);
15075
15173
  if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
15076
15174
  if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
15077
- const basename8 = f.split("/").pop() ?? "";
15078
- if (REVIEWABLE_FILENAMES.has(basename8)) return true;
15175
+ const basename9 = f.split("/").pop() ?? "";
15176
+ if (REVIEWABLE_FILENAMES.has(basename9)) return true;
15079
15177
  if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
15080
15178
  return false;
15081
15179
  });
@@ -15550,7 +15648,7 @@ async function maybeHealServiceUrl(resolution, verbose) {
15550
15648
 
15551
15649
  // src/lib/register.ts
15552
15650
  var readline = __toESM2(require("node:readline/promises"));
15553
- var import_node_os = require("node:os");
15651
+ var import_node_os2 = require("node:os");
15554
15652
 
15555
15653
  // src/lib/spinner.ts
15556
15654
  var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -15638,7 +15736,7 @@ function startSpinner(label2, opts = {}) {
15638
15736
  }
15639
15737
 
15640
15738
  // src/lib/provider-auth.ts
15641
- var sleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
15739
+ var sleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
15642
15740
  var form = (fields) => new URLSearchParams(fields).toString();
15643
15741
  async function githubAccountId(owner) {
15644
15742
  try {
@@ -15903,7 +16001,7 @@ function deviceLabel() {
15903
16001
  const override = process.env.VERITY_DEVICE_LABEL?.trim();
15904
16002
  if (override) return override;
15905
16003
  try {
15906
- return (0, import_node_os.hostname)() || void 0;
16004
+ return (0, import_node_os2.hostname)() || void 0;
15907
16005
  } catch {
15908
16006
  return void 0;
15909
16007
  }
@@ -16061,8 +16159,8 @@ function registerAuthCommands(program2) {
16061
16159
  }
16062
16160
 
16063
16161
  // src/lib/pending-login.ts
16064
- var import_node_fs4 = require("node:fs");
16065
- var import_node_path4 = require("node:path");
16162
+ var import_node_fs5 = require("node:fs");
16163
+ var import_node_path5 = require("node:path");
16066
16164
  function pendingLoginPath() {
16067
16165
  return `${process.env.HOME}/.verity/pending-login.json`;
16068
16166
  }
@@ -16078,26 +16176,26 @@ function savePendingLogin(dc, serviceUrl, now = Date.now()) {
16078
16176
  created_at: new Date(now).toISOString()
16079
16177
  };
16080
16178
  const path = pendingLoginPath();
16081
- (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
16179
+ (0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(path), { recursive: true });
16082
16180
  clearPendingLogin();
16083
- (0, import_node_fs4.writeFileSync)(path, JSON.stringify(record, null, 2) + "\n", { mode: 384, flag: "wx" });
16181
+ (0, import_node_fs5.writeFileSync)(path, JSON.stringify(record, null, 2) + "\n", { mode: 384, flag: "wx" });
16084
16182
  try {
16085
- (0, import_node_fs4.chmodSync)(path, 384);
16183
+ (0, import_node_fs5.chmodSync)(path, 384);
16086
16184
  } catch {
16087
16185
  }
16088
16186
  return record;
16089
16187
  }
16090
16188
  function readPendingLogin(now = Date.now()) {
16091
16189
  const path = pendingLoginPath();
16092
- if (!(0, import_node_fs4.existsSync)(path)) return { status: "none" };
16190
+ if (!(0, import_node_fs5.existsSync)(path)) return { status: "none" };
16093
16191
  try {
16094
- if ((0, import_node_fs4.lstatSync)(path).isSymbolicLink()) return { status: "invalid", reason: "it is a symlink" };
16192
+ if ((0, import_node_fs5.lstatSync)(path).isSymbolicLink()) return { status: "invalid", reason: "it is a symlink" };
16095
16193
  } catch {
16096
16194
  return { status: "none" };
16097
16195
  }
16098
16196
  let parsed;
16099
16197
  try {
16100
- parsed = JSON.parse((0, import_node_fs4.readFileSync)(path, "utf-8"));
16198
+ parsed = JSON.parse((0, import_node_fs5.readFileSync)(path, "utf-8"));
16101
16199
  } catch {
16102
16200
  return { status: "invalid", reason: "it is not valid JSON" };
16103
16201
  }
@@ -16118,7 +16216,7 @@ function readPendingLogin(now = Date.now()) {
16118
16216
  }
16119
16217
  function clearPendingLogin() {
16120
16218
  try {
16121
- (0, import_node_fs4.unlinkSync)(pendingLoginPath());
16219
+ (0, import_node_fs5.unlinkSync)(pendingLoginPath());
16122
16220
  return true;
16123
16221
  } catch {
16124
16222
  return false;
@@ -16674,11 +16772,11 @@ function registerLogoutCommand(program2) {
16674
16772
 
16675
16773
  // src/lib/hooks.ts
16676
16774
  var import_promises4 = require("node:fs/promises");
16677
- var import_node_path6 = require("node:path");
16775
+ var import_node_path7 = require("node:path");
16678
16776
 
16679
16777
  // src/lib/json-file.ts
16680
16778
  var import_promises3 = require("node:fs/promises");
16681
- var import_node_path5 = require("node:path");
16779
+ var import_node_path6 = require("node:path");
16682
16780
  function jsonSemanticEqual(a, b) {
16683
16781
  if (a === b) return true;
16684
16782
  if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) {
@@ -16724,7 +16822,7 @@ async function writeJsonFilePreservingStyle(file, value) {
16724
16822
  const indent = currentRaw !== null ? detectJsonIndent(currentRaw) : 2;
16725
16823
  const next = JSON.stringify(value, null, indent) + "\n";
16726
16824
  if (next === currentRaw) return false;
16727
- await (0, import_promises3.mkdir)((0, import_node_path5.dirname)(file), { recursive: true });
16825
+ await (0, import_promises3.mkdir)((0, import_node_path6.dirname)(file), { recursive: true });
16728
16826
  await (0, import_promises3.writeFile)(file, next);
16729
16827
  return true;
16730
16828
  }
@@ -16909,13 +17007,13 @@ async function writeSettings(settings) {
16909
17007
  }
16910
17008
  async function readSettingsAt(root) {
16911
17009
  try {
16912
- return JSON.parse(await (0, import_promises4.readFile)((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
17010
+ return JSON.parse(await (0, import_promises4.readFile)((0, import_node_path7.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
16913
17011
  } catch {
16914
17012
  return {};
16915
17013
  }
16916
17014
  }
16917
17015
  async function writeSettingsAt(root, settings) {
16918
- await writeJsonFilePreservingStyle((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), settings);
17016
+ await writeJsonFilePreservingStyle((0, import_node_path7.join)(root, CLAUDE_SETTINGS_FILE), settings);
16919
17017
  }
16920
17018
  async function hasLegacyHooksAt(root) {
16921
17019
  const settings = await readSettingsAt(root);
@@ -17104,12 +17202,12 @@ async function applyMomentSelection(moments) {
17104
17202
  }
17105
17203
 
17106
17204
  // src/lib/project-config.ts
17107
- var import_node_fs6 = require("node:fs");
17108
- var import_node_path8 = require("node:path");
17205
+ var import_node_fs7 = require("node:fs");
17206
+ var import_node_path9 = require("node:path");
17109
17207
 
17110
17208
  // src/lib/repo-controlled.ts
17111
- var import_node_fs5 = require("node:fs");
17112
- var import_node_path7 = require("node:path");
17209
+ var import_node_fs6 = require("node:fs");
17210
+ var import_node_path8 = require("node:path");
17113
17211
 
17114
17212
  // src/lib/hardened-git.ts
17115
17213
  var import_node_child_process5 = require("node:child_process");
@@ -17190,7 +17288,7 @@ function repoControlled(worktree, rel) {
17190
17288
  for (let i2 = 1; i2 <= parts2.length; i2++) {
17191
17289
  let st;
17192
17290
  try {
17193
- st = (0, import_node_fs5.lstatSync)((0, import_node_path7.join)(worktree, ...parts2.slice(0, i2)));
17291
+ st = (0, import_node_fs6.lstatSync)((0, import_node_path8.join)(worktree, ...parts2.slice(0, i2)));
17194
17292
  } catch (err2) {
17195
17293
  const code = err2?.code;
17196
17294
  if (code === "ENOENT" || code === "ENOTDIR") return null;
@@ -17214,14 +17312,14 @@ function parseMoments(raw) {
17214
17312
  }
17215
17313
  function readConfigFile(path) {
17216
17314
  try {
17217
- if (!(0, import_node_fs6.existsSync)(path)) return null;
17218
- const raw = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf-8"));
17315
+ if (!(0, import_node_fs7.existsSync)(path)) return null;
17316
+ const raw = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf-8"));
17219
17317
  const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
17220
17318
  const source2 = raw.git_moments_source === "user" || raw.git_moments_source === "init" ? raw.git_moments_source : void 0;
17221
17319
  return {
17222
17320
  git_moments: [...new Set(moments)],
17223
17321
  ...source2 ? { git_moments_source: source2 } : {},
17224
- ...raw.formal === "push" ? { formal: "push" } : {}
17322
+ ...raw.formal === "push" || raw.formal === "off" ? { formal: raw.formal } : {}
17225
17323
  };
17226
17324
  } catch {
17227
17325
  return DEFAULTS;
@@ -17232,13 +17330,13 @@ function candidates() {
17232
17330
  const out2 = [{ path: local, source: "local" }];
17233
17331
  const main = mainWorktreeRoot();
17234
17332
  if (main) {
17235
- const inherited = (0, import_node_path8.join)(main, PROJECT_CONFIG_FILE);
17333
+ const inherited = (0, import_node_path9.join)(main, PROJECT_CONFIG_FILE);
17236
17334
  if (inherited !== local) out2.push({ path: inherited, source: "main-worktree" });
17237
17335
  }
17238
17336
  return out2;
17239
17337
  }
17240
17338
  function formalRefusal(path) {
17241
- return repoControlled((0, import_node_path8.dirname)((0, import_node_path8.dirname)(path)), PROJECT_CONFIG_FILE);
17339
+ return repoControlled((0, import_node_path9.dirname)((0, import_node_path9.dirname)(path)), PROJECT_CONFIG_FILE);
17242
17340
  }
17243
17341
  function readProjectConfigRaw() {
17244
17342
  for (const { path, source: source2 } of candidates()) {
@@ -17274,8 +17372,8 @@ function writeProjectConfig(patch) {
17274
17372
  ...patch
17275
17373
  };
17276
17374
  const target = projectPath(PROJECT_CONFIG_FILE);
17277
- (0, import_node_fs6.mkdirSync)((0, import_node_path8.dirname)(target), { recursive: true });
17278
- (0, import_node_fs6.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
17375
+ (0, import_node_fs7.mkdirSync)((0, import_node_path9.dirname)(target), { recursive: true });
17376
+ (0, import_node_fs7.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
17279
17377
  return next;
17280
17378
  }
17281
17379
  function resolveGuardMoments(explicit) {
@@ -17284,11 +17382,11 @@ function resolveGuardMoments(explicit) {
17284
17382
  }
17285
17383
 
17286
17384
  // src/lib/plugin-ownership.ts
17287
- var import_node_fs9 = require("node:fs");
17385
+ var import_node_fs10 = require("node:fs");
17288
17386
 
17289
17387
  // src/lib/which.ts
17290
- var import_node_fs7 = require("node:fs");
17291
- var import_node_path9 = require("node:path");
17388
+ var import_node_fs8 = require("node:fs");
17389
+ var import_node_path10 = require("node:path");
17292
17390
  function executableExtensions(platform4, pathext) {
17293
17391
  if (platform4 !== "win32") return [""];
17294
17392
  const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
@@ -17306,14 +17404,14 @@ function whichSync(bin, opts = {}) {
17306
17404
  if (!rawPath) return null;
17307
17405
  const exts = executableExtensions(platform4, opts.pathext ?? process.env.PATHEXT);
17308
17406
  const real = opts.real ?? true;
17309
- for (const dir of rawPath.split(import_node_path9.delimiter)) {
17407
+ for (const dir of rawPath.split(import_node_path10.delimiter)) {
17310
17408
  if (!dir) continue;
17311
17409
  for (const ext of exts) {
17312
- const candidate = (0, import_node_path9.join)(dir, bin + ext);
17410
+ const candidate = (0, import_node_path10.join)(dir, bin + ext);
17313
17411
  try {
17314
- if (!(0, import_node_fs7.statSync)(candidate).isFile()) continue;
17315
- if (platform4 !== "win32") (0, import_node_fs7.accessSync)(candidate, import_node_fs7.constants.X_OK);
17316
- return real ? (0, import_node_fs7.realpathSync)(candidate) : candidate;
17412
+ if (!(0, import_node_fs8.statSync)(candidate).isFile()) continue;
17413
+ if (platform4 !== "win32") (0, import_node_fs8.accessSync)(candidate, import_node_fs8.constants.X_OK);
17414
+ return real ? (0, import_node_fs8.realpathSync)(candidate) : candidate;
17317
17415
  } catch {
17318
17416
  continue;
17319
17417
  }
@@ -17323,11 +17421,11 @@ function whichSync(bin, opts = {}) {
17323
17421
  }
17324
17422
 
17325
17423
  // src/lib/plugin-ownership.ts
17326
- var import_node_os2 = require("node:os");
17327
- var import_node_path10 = require("node:path");
17424
+ var import_node_os3 = require("node:os");
17425
+ var import_node_path11 = require("node:path");
17328
17426
 
17329
17427
  // src/lib/stderr-log.ts
17330
- var import_node_fs8 = require("node:fs");
17428
+ var import_node_fs9 = require("node:fs");
17331
17429
  var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
17332
17430
  var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
17333
17431
  function scrub(s) {
@@ -17340,9 +17438,9 @@ function append(text) {
17340
17438
  try {
17341
17439
  const dir = projectPath(DEBUG_LOG_DIR);
17342
17440
  const file = projectPath(STDERR_LOG_FILE);
17343
- (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
17441
+ (0, import_node_fs9.mkdirSync)(dir, { recursive: true });
17344
17442
  rotateIfNeeded(file);
17345
- (0, import_node_fs8.appendFileSync)(file, text);
17443
+ (0, import_node_fs9.appendFileSync)(file, text);
17346
17444
  } catch {
17347
17445
  }
17348
17446
  }
@@ -17390,8 +17488,8 @@ function markerPath() {
17390
17488
  }
17391
17489
  function readMarker() {
17392
17490
  try {
17393
- if (!(0, import_node_fs9.existsSync)(markerPath())) return null;
17394
- const raw = JSON.parse((0, import_node_fs9.readFileSync)(markerPath(), "utf-8"));
17491
+ if (!(0, import_node_fs10.existsSync)(markerPath())) return null;
17492
+ const raw = JSON.parse((0, import_node_fs10.readFileSync)(markerPath(), "utf-8"));
17395
17493
  const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
17396
17494
  if (!pluginRoot || CONTROL_CHARS2.test(pluginRoot)) return null;
17397
17495
  const version = typeof raw.version === "string" && !CONTROL_CHARS2.test(raw.version) ? raw.version : null;
@@ -17409,23 +17507,23 @@ function recordPluginOwnership(sessionId) {
17409
17507
  const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
17410
17508
  if (!pluginRoot) return;
17411
17509
  try {
17412
- (0, import_node_fs9.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
17510
+ (0, import_node_fs10.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
17413
17511
  const marker = {
17414
17512
  session_id: sessionId,
17415
17513
  plugin_root: pluginRoot,
17416
17514
  version: process.env.VERITY_PLUGIN_VERSION || null,
17417
17515
  ts: Math.floor(Date.now() / 1e3)
17418
17516
  };
17419
- (0, import_node_fs9.writeFileSync)(markerPath(), JSON.stringify(marker));
17517
+ (0, import_node_fs10.writeFileSync)(markerPath(), JSON.stringify(marker));
17420
17518
  } catch {
17421
17519
  }
17422
17520
  }
17423
17521
  function claudeConfigDir() {
17424
- return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path10.join)((0, import_node_os2.homedir)(), ".claude");
17522
+ return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".claude");
17425
17523
  }
17426
17524
  function readJsonFile(path) {
17427
17525
  try {
17428
- const parsed = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf-8"));
17526
+ const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
17429
17527
  return parsed && typeof parsed === "object" ? parsed : null;
17430
17528
  } catch {
17431
17529
  return null;
@@ -17433,9 +17531,9 @@ function readJsonFile(path) {
17433
17531
  }
17434
17532
  function enabledPluginSetting(key) {
17435
17533
  const files = [
17436
- projectPath((0, import_node_path10.join)(".claude", "settings.local.json")),
17437
- projectPath((0, import_node_path10.join)(".claude", "settings.json")),
17438
- (0, import_node_path10.join)(claudeConfigDir(), "settings.json")
17534
+ projectPath((0, import_node_path11.join)(".claude", "settings.local.json")),
17535
+ projectPath((0, import_node_path11.join)(".claude", "settings.json")),
17536
+ (0, import_node_path11.join)(claudeConfigDir(), "settings.json")
17439
17537
  ];
17440
17538
  for (const file of files) {
17441
17539
  const map = readJsonFile(file)?.enabledPlugins;
@@ -17447,11 +17545,11 @@ function enabledPluginSetting(key) {
17447
17545
  }
17448
17546
  function marketplaceLocations() {
17449
17547
  const out2 = /* @__PURE__ */ new Map();
17450
- const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17548
+ const known = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17451
17549
  if (!known) return out2;
17452
17550
  for (const [name2, entry] of Object.entries(known)) {
17453
17551
  const loc2 = entry?.installLocation;
17454
- if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path10.resolve)(loc2));
17552
+ if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path11.resolve)(loc2));
17455
17553
  }
17456
17554
  return out2;
17457
17555
  }
@@ -17465,7 +17563,7 @@ function globalVerityVersion() {
17465
17563
  const entry = verityPathEntry();
17466
17564
  if (!entry) return null;
17467
17565
  try {
17468
- const pkg = readJsonFile((0, import_node_path10.join)((0, import_node_path10.dirname)((0, import_node_fs9.realpathSync)(entry)), "..", "package.json"));
17566
+ const pkg = readJsonFile((0, import_node_path11.join)((0, import_node_path11.dirname)((0, import_node_fs10.realpathSync)(entry)), "..", "package.json"));
17469
17567
  if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
17470
17568
  return pkg.version;
17471
17569
  } catch {
@@ -17482,7 +17580,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
17482
17580
  function marketplaceConflict() {
17483
17581
  const wanted = VERITY_MARKETPLACE;
17484
17582
  for (const file of ["settings.json", "settings.local.json"]) {
17485
- const path = (0, import_node_path10.join)(claudeConfigDir(), file);
17583
+ const path = (0, import_node_path11.join)(claudeConfigDir(), file);
17486
17584
  const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
17487
17585
  const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
17488
17586
  if (entry2 && typeof entry2 === "object") {
@@ -17492,7 +17590,7 @@ function marketplaceConflict() {
17492
17590
  }
17493
17591
  }
17494
17592
  }
17495
- const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17593
+ const known = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17496
17594
  const entry = known?.[wanted];
17497
17595
  if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
17498
17596
  return { name: wanted, declaredAs: describeSource(entry.source) };
@@ -17513,7 +17611,7 @@ function describeSource(src) {
17513
17611
  return target ? `${kind} \u2192 ${target}` : kind;
17514
17612
  }
17515
17613
  function legacyMarketplaceInstall() {
17516
- const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17614
+ const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17517
17615
  if (!plugins || typeof plugins !== "object") return null;
17518
17616
  for (const key of Object.keys(plugins)) {
17519
17617
  const at = key.lastIndexOf("@");
@@ -17525,13 +17623,13 @@ function legacyMarketplaceInstall() {
17525
17623
  }
17526
17624
  function realpathOr(p) {
17527
17625
  try {
17528
- return import_node_fs9.realpathSync.native(p);
17626
+ return import_node_fs10.realpathSync.native(p);
17529
17627
  } catch {
17530
- return (0, import_node_path10.resolve)(p);
17628
+ return (0, import_node_path11.resolve)(p);
17531
17629
  }
17532
17630
  }
17533
17631
  function isWithin(want, dir) {
17534
- return want === dir || want.startsWith(dir + import_node_path10.sep);
17632
+ return want === dir || want.startsWith(dir + import_node_path11.sep);
17535
17633
  }
17536
17634
  function entryAppliesHere(entry, here) {
17537
17635
  const e = entry;
@@ -17541,9 +17639,9 @@ function entryAppliesHere(entry, here) {
17541
17639
  return forProject === here;
17542
17640
  }
17543
17641
  function registrySays(pluginRoot) {
17544
- const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17642
+ const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17545
17643
  if (!plugins || typeof plugins !== "object") return "unverified";
17546
- const want = (0, import_node_path10.resolve)(pluginRoot);
17644
+ const want = (0, import_node_path11.resolve)(pluginRoot);
17547
17645
  const here = realpathOr(repoRoot());
17548
17646
  const markets = marketplaceLocations();
17549
17647
  for (const [key, value] of Object.entries(plugins)) {
@@ -17552,15 +17650,15 @@ function registrySays(pluginRoot) {
17552
17650
  const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
17553
17651
  const claims = applicable.some((entry) => {
17554
17652
  const installPath = entry?.installPath;
17555
- return typeof installPath === "string" && (0, import_node_path10.resolve)(installPath) === want;
17653
+ return typeof installPath === "string" && (0, import_node_path11.resolve)(installPath) === want;
17556
17654
  }) || source2 !== void 0 && applicable.length > 0 && isWithin(want, source2);
17557
17655
  if (claims) {
17558
17656
  if (enabledPluginSetting(key) === false) return "gone";
17559
- return (0, import_node_fs9.existsSync)(pluginRoot) ? "live" : "gone";
17657
+ return (0, import_node_fs10.existsSync)(pluginRoot) ? "live" : "gone";
17560
17658
  }
17561
17659
  }
17562
- const managed = (0, import_node_path10.resolve)((0, import_node_path10.join)(claudeConfigDir(), "plugins", "cache"));
17563
- return want === managed || want.startsWith(managed + import_node_path10.sep) ? "gone" : "unverified";
17660
+ const managed = (0, import_node_path11.resolve)((0, import_node_path11.join)(claudeConfigDir(), "plugins", "cache"));
17661
+ return want === managed || want.startsWith(managed + import_node_path11.sep) ? "gone" : "unverified";
17564
17662
  }
17565
17663
  var _live = /* @__PURE__ */ new Map();
17566
17664
  function pluginLiveness(pluginRoot) {
@@ -17574,7 +17672,7 @@ function clearStalePluginMarker() {
17574
17672
  const marker = readMarker();
17575
17673
  if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
17576
17674
  try {
17577
- (0, import_node_fs9.rmSync)(markerPath(), { force: true });
17675
+ (0, import_node_fs10.rmSync)(markerPath(), { force: true });
17578
17676
  } catch {
17579
17677
  return null;
17580
17678
  }
@@ -17602,7 +17700,7 @@ function pluginActiveHere() {
17602
17700
  return activePluginInstall() !== null;
17603
17701
  }
17604
17702
  function registeredVerityPlugin() {
17605
- const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17703
+ const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17606
17704
  if (!plugins || typeof plugins !== "object") return null;
17607
17705
  const here = realpathOr(repoRoot());
17608
17706
  for (const [key, value] of Object.entries(plugins)) {
@@ -17612,7 +17710,7 @@ function registeredVerityPlugin() {
17612
17710
  for (const entry of Array.isArray(value) ? value : []) {
17613
17711
  const e = entry;
17614
17712
  const installPath = typeof e.installPath === "string" ? e.installPath : "";
17615
- if (!installPath || !(0, import_node_fs9.existsSync)(installPath)) continue;
17713
+ if (!installPath || !(0, import_node_fs10.existsSync)(installPath)) continue;
17616
17714
  if (!entryAppliesHere(entry, here)) continue;
17617
17715
  return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
17618
17716
  }
@@ -17664,28 +17762,28 @@ async function resolveHookWiring() {
17664
17762
  }
17665
17763
 
17666
17764
  // src/lib/cli-provenance.ts
17667
- var import_node_fs10 = require("node:fs");
17668
- var import_node_os3 = require("node:os");
17669
- var import_node_path11 = require("node:path");
17765
+ var import_node_fs11 = require("node:fs");
17766
+ var import_node_os4 = require("node:os");
17767
+ var import_node_path12 = require("node:path");
17670
17768
  var CLI_PACKAGE = "@codacy/verity-cli";
17671
- var CLI_ENTRY = (0, import_node_path11.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
17769
+ var CLI_ENTRY = (0, import_node_path12.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
17672
17770
  function readJson(path) {
17673
17771
  try {
17674
- const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
17772
+ const parsed = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
17675
17773
  return parsed && typeof parsed === "object" ? parsed : null;
17676
17774
  } catch {
17677
17775
  return null;
17678
17776
  }
17679
17777
  }
17680
17778
  function versionUnder(base) {
17681
- const entry = (0, import_node_path11.join)(base, CLI_ENTRY);
17682
- if (!(0, import_node_fs10.existsSync)(entry)) return null;
17683
- const pkg = readJson((0, import_node_path11.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
17779
+ const entry = (0, import_node_path12.join)(base, CLI_ENTRY);
17780
+ if (!(0, import_node_fs11.existsSync)(entry)) return null;
17781
+ const pkg = readJson((0, import_node_path12.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
17684
17782
  return typeof pkg?.version === "string" ? pkg.version : null;
17685
17783
  }
17686
17784
  function versionForEntry(entry) {
17687
17785
  try {
17688
- const pkg = readJson((0, import_node_path11.join)((0, import_node_path11.dirname)((0, import_node_fs10.realpathSync)(entry)), "..", "package.json"));
17786
+ const pkg = readJson((0, import_node_path12.join)((0, import_node_path12.dirname)((0, import_node_fs11.realpathSync)(entry)), "..", "package.json"));
17689
17787
  return typeof pkg?.version === "string" ? pkg.version : null;
17690
17788
  } catch {
17691
17789
  return null;
@@ -17693,16 +17791,16 @@ function versionForEntry(entry) {
17693
17791
  }
17694
17792
  function resolveHooksCli(pluginRoot) {
17695
17793
  const override = process.env.VERITY_CLI_PATH;
17696
- if (override && (0, import_node_fs10.existsSync)(override)) {
17794
+ if (override && (0, import_node_fs11.existsSync)(override)) {
17697
17795
  return { version: versionForEntry(override), rung: "override" };
17698
17796
  }
17699
17797
  const fromPlugin = versionUnder(pluginRoot);
17700
17798
  if (fromPlugin !== null) return { version: fromPlugin, rung: "plugin" };
17701
- if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
17702
- const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".verity", "plugin-cli");
17799
+ if ((0, import_node_fs11.existsSync)((0, import_node_path12.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
17800
+ const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity", "plugin-cli");
17703
17801
  const fromData = versionUnder(dataDir);
17704
17802
  if (fromData !== null) return { version: fromData, rung: "plugin-data" };
17705
- if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
17803
+ if ((0, import_node_fs11.existsSync)((0, import_node_path12.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
17706
17804
  const global = globalVerityVersion();
17707
17805
  if (global !== null) return { version: global, rung: "global" };
17708
17806
  return null;
@@ -17804,7 +17902,7 @@ function pluginCliInvocation() {
17804
17902
  return resolverCommand(root);
17805
17903
  }
17806
17904
  function resolverCommand(root) {
17807
- return `node ${JSON.stringify((0, import_node_path11.join)(root, "scripts", "verity.mjs"))}`;
17905
+ return `node ${JSON.stringify((0, import_node_path12.join)(root, "scripts", "verity.mjs"))}`;
17808
17906
  }
17809
17907
 
17810
17908
  // src/commands/hooks.ts
@@ -17940,18 +18038,18 @@ function registerHooksCommands(program2) {
17940
18038
  }
17941
18039
 
17942
18040
  // src/commands/intent.ts
17943
- var import_node_crypto9 = require("node:crypto");
18041
+ var import_node_crypto10 = require("node:crypto");
17944
18042
 
17945
18043
  // src/lib/conversation-buffer.ts
17946
18044
  var import_promises5 = require("node:fs/promises");
17947
- var import_node_fs11 = require("node:fs");
18045
+ var import_node_fs12 = require("node:fs");
17948
18046
  var import_node_child_process6 = require("node:child_process");
17949
- var import_node_crypto = require("node:crypto");
18047
+ var import_node_crypto2 = require("node:crypto");
17950
18048
  function stripImageReferences(text) {
17951
18049
  return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
17952
18050
  }
17953
18051
  function bufferTmpPath() {
17954
- return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto.randomBytes)(4).toString("hex")}.tmp`;
18052
+ return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto2.randomBytes)(4).toString("hex")}.tmp`;
17955
18053
  }
17956
18054
  async function appendToConversationBuffer(prompt, sessionId) {
17957
18055
  try {
@@ -17980,7 +18078,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
17980
18078
  }
17981
18079
  async function readAndClearConversationBuffer(currentSessionId) {
17982
18080
  try {
17983
- if ((0, import_node_fs11.existsSync)(CONVERSATION_BUFFER_FILE)) {
18081
+ if ((0, import_node_fs12.existsSync)(CONVERSATION_BUFFER_FILE)) {
17984
18082
  const entries = await readBufferEntries();
17985
18083
  let mine = entries;
17986
18084
  let others = [];
@@ -18004,7 +18102,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
18004
18102
  };
18005
18103
  }
18006
18104
  }
18007
- if ((0, import_node_fs11.existsSync)(INTENT_FILE)) {
18105
+ if ((0, import_node_fs12.existsSync)(INTENT_FILE)) {
18008
18106
  try {
18009
18107
  const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
18010
18108
  await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
@@ -18295,83 +18393,6 @@ function isCommandOnlyTurn(input) {
18295
18393
  return commands.every(isNonAuthoringCommand);
18296
18394
  }
18297
18395
 
18298
- // src/lib/context-identity.ts
18299
- var import_node_crypto2 = require("node:crypto");
18300
- var import_node_fs12 = require("node:fs");
18301
- var import_node_os4 = require("node:os");
18302
- var import_node_path12 = require("node:path");
18303
- var SHARED_SENTINELS = /* @__PURE__ */ new Set([
18304
- "",
18305
- "-",
18306
- "n/a",
18307
- "na",
18308
- "none",
18309
- "null",
18310
- "undefined",
18311
- "unknown",
18312
- "anon",
18313
- "anonymous",
18314
- "default",
18315
- "_default"
18316
- ]);
18317
- function isSharedSentinel(value) {
18318
- if (value == null) return true;
18319
- return SHARED_SENTINELS.has(value.trim().toLowerCase());
18320
- }
18321
- var ephemeral = /* @__PURE__ */ new Map();
18322
- function ephemeralId(slot, width) {
18323
- let id = ephemeral.get(slot);
18324
- if (!id) {
18325
- id = `eph-${(0, import_node_crypto2.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
18326
- ephemeral.set(slot, id);
18327
- }
18328
- return id;
18329
- }
18330
- function contextIdentity(input) {
18331
- const tokenUsable = !isSharedSentinel(input.token ?? null);
18332
- const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
18333
- const userKey = tokenUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
18334
- const sessionKey2 = sessionUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
18335
- let treeKey = "no-tree";
18336
- const rawTree = input.treeRoot;
18337
- if (rawTree && !isSharedSentinel(rawTree)) {
18338
- let resolved = rawTree;
18339
- try {
18340
- resolved = import_node_fs12.realpathSync.native(rawTree);
18341
- } catch {
18342
- }
18343
- treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
18344
- }
18345
- return {
18346
- userKey,
18347
- treeKey,
18348
- sessionKey: sessionKey2,
18349
- userKeySource: tokenUsable ? "token" : "ephemeral",
18350
- sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
18351
- ephemeral: !tokenUsable || !sessionUsable
18352
- };
18353
- }
18354
- function verityHome() {
18355
- const override = process.env.VERITY_HOME;
18356
- return override && override.trim() ? (0, import_node_path12.resolve)(override) : (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity");
18357
- }
18358
- function dossierDir(identity) {
18359
- return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
18360
- }
18361
- function treeDir(identity) {
18362
- return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
18363
- }
18364
- function scopeIdentity(token, sessionId) {
18365
- const t = (token ?? "").trim();
18366
- const s = (sessionId ?? "").trim();
18367
- const userKey = t.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
18368
- const sessionKey2 = s.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
18369
- return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
18370
- }
18371
- function sessionScopeKey(token, sessionId) {
18372
- return scopeIdentity(token, sessionId).bucket;
18373
- }
18374
-
18375
18396
  // src/lib/task-context-buffer.ts
18376
18397
  var import_promises6 = require("node:fs/promises");
18377
18398
  var import_node_fs13 = require("node:fs");
@@ -19455,8 +19476,8 @@ function ensureVerityGitignore() {
19455
19476
  }
19456
19477
  let text = next.join("\n");
19457
19478
  if (!hasMarker) {
19458
- const sep5 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19459
- text = text + sep5 + VERITY_GITIGNORE_BLOCK;
19479
+ const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19480
+ text = text + sep6 + VERITY_GITIGNORE_BLOCK;
19460
19481
  }
19461
19482
  if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
19462
19483
  return verified(
@@ -19486,8 +19507,8 @@ function writeFencedBlock() {
19486
19507
  lines = fenceMemoryLines(lines);
19487
19508
  let text = lines.join("\n");
19488
19509
  if (!hasMarker) {
19489
- const sep5 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19490
- text = text + sep5 + VERITY_GITIGNORE_BLOCK;
19510
+ const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19511
+ text = text + sep6 + VERITY_GITIGNORE_BLOCK;
19491
19512
  }
19492
19513
  try {
19493
19514
  (0, import_node_fs19.writeFileSync)(".gitignore", text);
@@ -19537,8 +19558,8 @@ function keepMemoryTracked() {
19537
19558
  }
19538
19559
  if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
19539
19560
  try {
19540
- const sep5 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
19541
- (0, import_node_fs19.writeFileSync)(".gitignore", content + sep5 + MEMORY_OPT_OUT_STANZA);
19561
+ const sep6 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
19562
+ (0, import_node_fs19.writeFileSync)(".gitignore", content + sep6 + MEMORY_OPT_OUT_STANZA);
19542
19563
  } catch {
19543
19564
  return "failed";
19544
19565
  }
@@ -20076,9 +20097,16 @@ var CLAUDE_MD_PROSE = [
20076
20097
  "Then record it straight away. There is no confirm step, in any environment:",
20077
20098
  "",
20078
20099
  "```bash",
20079
- 'verity reflect --user-input "<your draft>" --kind <kind>',
20100
+ "verity reflect --user-input - --kind <kind> <<'VERITY_EOF_<random>'",
20101
+ "<your draft>",
20102
+ "VERITY_EOF_<random>",
20080
20103
  "```",
20081
20104
  "",
20105
+ 'The draft goes through the quoted heredoc, never inside `"\u2026"` on the command',
20106
+ 'line, where a `"` or `$(\u2026)` in it would run in the shell. Replace `<random>`',
20107
+ "with 8 random letters and digits that you pick for this call, the same at both",
20108
+ "ends. Text written before you picked them cannot end the heredoc early.",
20109
+ "",
20082
20110
  "Add `--confirmed` ONLY when the user authored or dictated the words. Without",
20083
20111
  "it the node is stored as `source: agent` \u2014 Verity thought this, nobody checked",
20084
20112
  "it. With it, `source: user` at full confidence \u2014 a person stands behind this.",
@@ -20087,7 +20115,7 @@ var CLAUDE_MD_PROSE = [
20087
20115
  "**Name the files in the text.** Verity scopes the reflection to the paths it",
20088
20116
  "cites, and a reflection that names no file in this repo is never retrieved for",
20089
20117
  "a later review \u2014 it is recorded and then invisible. The command says so when it",
20090
- 'happens; `--file-globs "<path or glob>"` is the fix when the prose cannot carry',
20118
+ "happens; `--file-globs '<path or glob>'` is the fix when the prose cannot carry",
20091
20119
  "the paths.",
20092
20120
  "",
20093
20121
  "Then tell the user, in one line, what you recorded and where: the command",
@@ -20120,7 +20148,7 @@ var CLAUDE_MD_PROSE = [
20120
20148
  "a finding. Declarations are budgeted per session and every one is recorded with",
20121
20149
  "its reason."
20122
20150
  ].join("\n");
20123
- var CLAUDE_MD_PROSE_PRE_ORG = [
20151
+ var CLAUDE_MD_PROSE_PRE_STDIN = [
20124
20152
  "## Project Memory",
20125
20153
  "",
20126
20154
  "This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
@@ -20131,6 +20159,11 @@ var CLAUDE_MD_PROSE_PRE_ORG = [
20131
20159
  "The graph is auto-maintained by Verity. Files at `.verity/memory/_archive/` are",
20132
20160
  "superseded \u2014 ignore them unless investigating history.",
20133
20161
  "",
20162
+ "Knowledge the organization's other repositories learned is mirrored outside the",
20163
+ "repo at `~/.verity/orgs/<host>/<owner>/memory/` (`verity memory org` lists it).",
20164
+ "Each claim says where it came from; one that is wrong here is demoted for",
20165
+ 'everyone with `verity memory demote <id> --reason "\u2026"`.',
20166
+ "",
20134
20167
  "## Quality gate: accepted risks",
20135
20168
  "",
20136
20169
  "When the Verity pre-commit/pre-push gate FAILs, fix the findings \u2014 that is the",
@@ -20199,7 +20232,7 @@ var CLAUDE_MD_PROSE_PRE_ORG = [
20199
20232
  "a finding. Declarations are budgeted per session and every one is recorded with",
20200
20233
  "its reason."
20201
20234
  ].join("\n");
20202
- var CLAUDE_MD_PROSE_PRE_AUTORECORD = [
20235
+ var CLAUDE_MD_PROSE_PRE_ORG = [
20203
20236
  "## Project Memory",
20204
20237
  "",
20205
20238
  "This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
@@ -20225,22 +20258,33 @@ var CLAUDE_MD_PROSE_PRE_AUTORECORD = [
20225
20258
  "## Post-task reflection",
20226
20259
  "",
20227
20260
  `When a task is complete (you've created a PR, the user says "done" or "ship it",`,
20228
- "or the work is clearly finished), **draft the reflection yourself first** \u2014 1\u20133",
20261
+ "or the work is clearly finished), **draft the reflection yourself** \u2014 1\u20133",
20229
20262
  "concrete things worth remembering (a decision, a gotcha, or a pattern), each",
20230
20263
  "cited with the files / PR / commands / error-signatures it came from. Skip",
20231
- "entirely if nothing non-obvious happened.",
20264
+ "entirely if nothing non-obvious happened \u2014 that judgement is the ONLY filter,",
20265
+ "because nothing reviews the reflection before it lands.",
20232
20266
  "",
20233
- "Then, depending on how the session is running:",
20267
+ "Then record it straight away. There is no confirm step, in any environment:",
20234
20268
  "",
20235
- "- **Interactive** (a person is at the keyboard): show your draft and ask one",
20236
- ` question before recording \u2014 "Here's my reflection draft for the project`,
20237
- " memory: <draft>. Anything to confirm, correct, or add before I record it?",
20238
- ` (Say 'skip' to drop it.)" Record the final text (with their corrections) via`,
20239
- ' `verity reflect --user-input "<final reflection>" --kind <kind>`. If they say',
20240
- ' "skip", do not record.',
20241
- "- **Autonomous** (headless / CI / cron, or `VERITY_AUTONOMOUS=1`): record your",
20242
- ' draft directly, never blocking \u2014 `verity reflect --user-input "<your draft>"',
20243
- " --kind <kind> --autonomous`.",
20269
+ "```bash",
20270
+ 'verity reflect --user-input "<your draft>" --kind <kind>',
20271
+ "```",
20272
+ "",
20273
+ "Add `--confirmed` ONLY when the user authored or dictated the words. Without",
20274
+ "it the node is stored as `source: agent` \u2014 Verity thought this, nobody checked",
20275
+ "it. With it, `source: user` at full confidence \u2014 a person stands behind this.",
20276
+ "Never claim the second for your own draft, however good it is.",
20277
+ "",
20278
+ "**Name the files in the text.** Verity scopes the reflection to the paths it",
20279
+ "cites, and a reflection that names no file in this repo is never retrieved for",
20280
+ "a later review \u2014 it is recorded and then invisible. The command says so when it",
20281
+ 'happens; `--file-globs "<path or glob>"` is the fix when the prose cannot carry',
20282
+ "the paths.",
20283
+ "",
20284
+ "Then tell the user, in one line, what you recorded and where: the command",
20285
+ "prints the node id, the path under `.verity/memory/`, and a dashboard link.",
20286
+ "They did not agree to it in advance, so say it happened \u2014 editing or deleting",
20287
+ "that file is how they correct it.",
20244
20288
  "",
20245
20289
  "> Durable, hand-curated guidance goes in the preserve region below (it survives",
20246
20290
  "> regeneration) or anywhere OUTSIDE these markers. Everything else between the",
@@ -20267,7 +20311,75 @@ var CLAUDE_MD_PROSE_PRE_AUTORECORD = [
20267
20311
  "a finding. Declarations are budgeted per session and every one is recorded with",
20268
20312
  "its reason."
20269
20313
  ].join("\n");
20270
- var CLAUDE_MD_PROSE_PRE_REFLECT = [
20314
+ var CLAUDE_MD_PROSE_PRE_AUTORECORD = [
20315
+ "## Project Memory",
20316
+ "",
20317
+ "This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
20318
+ "non-trivial work, scan `.verity/memory/index.md` for decisions, gotchas, and patterns",
20319
+ "that may apply to the change you are about to make. Open specific node files via",
20320
+ "the Read tool when the title or scope suggests relevance.",
20321
+ "",
20322
+ "The graph is auto-maintained by Verity. Files at `.verity/memory/_archive/` are",
20323
+ "superseded \u2014 ignore them unless investigating history.",
20324
+ "",
20325
+ "## Quality gate: accepted risks",
20326
+ "",
20327
+ "When the Verity pre-commit/pre-push gate FAILs, fix the findings \u2014 that is the",
20328
+ 'default. Use `verity waive <pattern-id> --file <path> --reason "\u2026"` ONLY to relay',
20329
+ "a risk a human has explicitly accepted: a named code-review finding, an ADR, or",
20330
+ "the user saying so in this conversation. The --reason must cite that source.",
20331
+ "",
20332
+ "Never waive on your own judgment, to get past a block, or pre-emptively. A waive",
20333
+ "binds to the file's current bytes and voids automatically when the file changes,",
20334
+ "and every waive is recorded in the run ledger. For a pattern-level false positive",
20335
+ "use `verity feedback finding <run-id> <pattern-id> false_positive` instead.",
20336
+ "",
20337
+ "## Post-task reflection",
20338
+ "",
20339
+ `When a task is complete (you've created a PR, the user says "done" or "ship it",`,
20340
+ "or the work is clearly finished), **draft the reflection yourself first** \u2014 1\u20133",
20341
+ "concrete things worth remembering (a decision, a gotcha, or a pattern), each",
20342
+ "cited with the files / PR / commands / error-signatures it came from. Skip",
20343
+ "entirely if nothing non-obvious happened.",
20344
+ "",
20345
+ "Then, depending on how the session is running:",
20346
+ "",
20347
+ "- **Interactive** (a person is at the keyboard): show your draft and ask one",
20348
+ ` question before recording \u2014 "Here's my reflection draft for the project`,
20349
+ " memory: <draft>. Anything to confirm, correct, or add before I record it?",
20350
+ ` (Say 'skip' to drop it.)" Record the final text (with their corrections) via`,
20351
+ ' `verity reflect --user-input "<final reflection>" --kind <kind>`. If they say',
20352
+ ' "skip", do not record.',
20353
+ "- **Autonomous** (headless / CI / cron, or `VERITY_AUTONOMOUS=1`): record your",
20354
+ ' draft directly, never blocking \u2014 `verity reflect --user-input "<your draft>"',
20355
+ " --kind <kind> --autonomous`.",
20356
+ "",
20357
+ "> Durable, hand-curated guidance goes in the preserve region below (it survives",
20358
+ "> regeneration) or anywhere OUTSIDE these markers. Everything else between the",
20359
+ "> markers is tool-owned and overwritten on each run.",
20360
+ "",
20361
+ "## Housekeeping Turns",
20362
+ "",
20363
+ "When a turn will be pure housekeeping \u2014 pulling, installing dependencies,",
20364
+ "rebasing, a formatting sweep you are not authoring \u2014 declare it BEFORE doing it:",
20365
+ "",
20366
+ "```bash",
20367
+ 'verity ignore --turn --agent --reason "pulling latest before starting"',
20368
+ "```",
20369
+ "",
20370
+ "This skips the review for that turn, which saves the turn Verity would",
20371
+ "otherwise spend saying it had nothing to say. Use `--for 30m` instead of",
20372
+ "`--turn` when a single piece of housekeeping spans several turns.",
20373
+ "",
20374
+ "**It is a claim about the turn, not a way to silence review.** The declaration",
20375
+ "is checked against what the turn actually did: if anything is authored \u2014 by you,",
20376
+ "by a subagent, or by a shell command that can write files \u2014 it voids, the review",
20377
+ "runs anyway, and the broken declaration is reported. So declare housekeeping you",
20378
+ "are about to do, never work you have already done, and never as a way to get past",
20379
+ "a finding. Declarations are budgeted per session and every one is recorded with",
20380
+ "its reason."
20381
+ ].join("\n");
20382
+ var CLAUDE_MD_PROSE_PRE_REFLECT = [
20271
20383
  "## Project Memory",
20272
20384
  "",
20273
20385
  "This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
@@ -20478,6 +20590,7 @@ function stripKnownProse(interior) {
20478
20590
  const trimmed = interior.replace(/^\n+/, "");
20479
20591
  for (const prose of [
20480
20592
  CLAUDE_MD_PROSE,
20593
+ CLAUDE_MD_PROSE_PRE_STDIN,
20481
20594
  CLAUDE_MD_PROSE_PRE_ORG,
20482
20595
  CLAUDE_MD_PROSE_PRE_AUTORECORD,
20483
20596
  CLAUDE_MD_PROSE_PRE_REFLECT,
@@ -20544,7 +20657,7 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
20544
20657
 
20545
20658
  // src/lib/dossier-session.ts
20546
20659
  var import_node_fs26 = require("node:fs");
20547
- var import_node_crypto8 = require("node:crypto");
20660
+ var import_node_crypto9 = require("node:crypto");
20548
20661
  var import_node_path22 = require("node:path");
20549
20662
 
20550
20663
  // src/lib/pending-repeat.ts
@@ -20621,6 +20734,7 @@ function isRepeatOfAny(text, priorFingerprints, threshold = REPEAT_THRESHOLD) {
20621
20734
  }
20622
20735
 
20623
20736
  // src/lib/dossier/bounds.ts
20737
+ var import_node_crypto5 = require("node:crypto");
20624
20738
  var MAX_LINE_BYTES = 4096;
20625
20739
  var MAX_GOAL_CHARS = 2e3;
20626
20740
  var GOAL_KEEP = 8;
@@ -20632,10 +20746,17 @@ var NOT_MINE_CAP = 300;
20632
20746
  var STATEMENTS_OPEN_CAP = 40;
20633
20747
  var COMMANDS_CAP = 12;
20634
20748
  var DIVERGENCE_CAP = 10;
20635
- var DIVERGENCE_SEEN_CAP = 300;
20749
+ var DIVERGENCE_BULK_AT = 300;
20750
+ var DIVERGENCE_KEYS_PER_LINE = 200;
20636
20751
  function divergenceKey(path, hash) {
20637
20752
  return `${path}@${hash ?? "unknown"}`;
20638
20753
  }
20754
+ function packedDivergenceDigest(key) {
20755
+ return (0, import_node_crypto5.createHash)("sha256").update(key).digest("hex").slice(0, 12);
20756
+ }
20757
+ function packedDivergenceKey(digest) {
20758
+ return `#${digest}`;
20759
+ }
20639
20760
  var MARKS_CAP = 50;
20640
20761
  var ROTATE_BYTES = 1048576;
20641
20762
  var ROTATE_KEEP = 2;
@@ -20649,7 +20770,7 @@ function statementAnchorKey(file, patternId) {
20649
20770
  }
20650
20771
 
20651
20772
  // src/lib/dossier/log.ts
20652
- var import_node_crypto5 = require("node:crypto");
20773
+ var import_node_crypto6 = require("node:crypto");
20653
20774
  var import_node_fs22 = require("node:fs");
20654
20775
  var import_node_path20 = require("node:path");
20655
20776
  var CRC_TABLE = (() => {
@@ -20691,7 +20812,7 @@ function nextSeq() {
20691
20812
  function encodeEvent(ev) {
20692
20813
  const full = {
20693
20814
  v: 1,
20694
- id: (0, import_node_crypto5.randomBytes)(4).toString("hex"),
20815
+ id: (0, import_node_crypto6.randomBytes)(4).toString("hex"),
20695
20816
  ...ev
20696
20817
  };
20697
20818
  let body2 = JSON.stringify(full);
@@ -20762,7 +20883,7 @@ function rotateIfNeeded2(d) {
20762
20883
  }
20763
20884
 
20764
20885
  // src/lib/dossier/fold-dossier.ts
20765
- var import_node_crypto6 = require("node:crypto");
20886
+ var import_node_crypto7 = require("node:crypto");
20766
20887
  var import_node_fs23 = require("node:fs");
20767
20888
  var import_node_path21 = require("node:path");
20768
20889
  var EMPTY_CAPABILITIES = () => ({
@@ -20854,7 +20975,7 @@ function reduce(state, events, now) {
20854
20975
  state.meta.seq = Math.max(state.meta.seq, ev.seq);
20855
20976
  switch (ev.k) {
20856
20977
  case "goal": {
20857
- const hash = (0, import_node_crypto6.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
20978
+ const hash = (0, import_node_crypto7.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
20858
20979
  const prev = state.goal[state.goal.length - 1];
20859
20980
  if (prev && prev.hash === hash) {
20860
20981
  prev.repeats = (prev.repeats ?? 0) + 1;
@@ -20982,12 +21103,13 @@ function reduce(state, events, now) {
20982
21103
  break;
20983
21104
  }
20984
21105
  case "divergence": {
20985
- state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
20986
21106
  state.divergence.events.push({ kind: ev.kind, path: ev.path, at: ev.at });
20987
- const key = divergenceKey(ev.path, ev.hash ?? null);
20988
- if (!seenDivergence.has(key)) {
21107
+ const keys = Array.isArray(ev.keys) ? ev.keys.filter((k) => typeof k === "string").map(packedDivergenceKey) : [divergenceKey(ev.path, ev.hash ?? null)];
21108
+ for (const key of keys) {
21109
+ if (seenDivergence.has(key)) continue;
20989
21110
  seenDivergence.add(key);
20990
- if (state.divergence.seen.length < DIVERGENCE_SEEN_CAP) state.divergence.seen.push(key);
21111
+ state.divergence.seen.push(key);
21112
+ state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
20991
21113
  }
20992
21114
  break;
20993
21115
  }
@@ -21294,14 +21416,14 @@ function assessContinuity(i2) {
21294
21416
  }
21295
21417
 
21296
21418
  // src/lib/dossier/reanchor.ts
21297
- var import_node_crypto7 = require("node:crypto");
21419
+ var import_node_crypto8 = require("node:crypto");
21298
21420
  var import_node_fs25 = require("node:fs");
21299
21421
  function lineSha(text) {
21300
- return (0, import_node_crypto7.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21422
+ return (0, import_node_crypto8.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21301
21423
  }
21302
21424
  function fileHash(path) {
21303
21425
  try {
21304
- return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21426
+ return (0, import_node_crypto8.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21305
21427
  } catch {
21306
21428
  return null;
21307
21429
  }
@@ -21798,7 +21920,7 @@ function recordTurn(d, t) {
21798
21920
  // Identity is the COMMAND, not its category — otherwise `npm test -- a` and
21799
21921
  // `npm test -- b` are one row and the streak counts two different commands
21800
21922
  // as a run of one.
21801
- cmd_hash: (0, import_node_crypto8.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
21923
+ cmd_hash: (0, import_node_crypto9.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
21802
21924
  head: c.head || c.class,
21803
21925
  status: toStatus(c.last_status)
21804
21926
  });
@@ -21816,10 +21938,23 @@ function recordTurn(d, t) {
21816
21938
  }
21817
21939
  }
21818
21940
  const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
21941
+ const fresh = [];
21819
21942
  for (const u of t.unobserved) {
21820
21943
  const hash = fileHash((0, import_node_path22.join)(root, u.p));
21821
- if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
21822
- appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
21944
+ const key = divergenceKey(u.p, hash);
21945
+ const digest = packedDivergenceDigest(key);
21946
+ if (seenDivergence.has(key) || seenDivergence.has(packedDivergenceKey(digest))) continue;
21947
+ fresh.push({ path: u.p, hash, digest });
21948
+ }
21949
+ if (fresh.length > DIVERGENCE_BULK_AT) {
21950
+ for (let i2 = 0; i2 < fresh.length; i2 += DIVERGENCE_KEYS_PER_LINE) {
21951
+ const slice2 = fresh.slice(i2, i2 + DIVERGENCE_KEYS_PER_LINE);
21952
+ appendEvent(d, { k: "divergence", kind: "external_mutation", path: slice2[0].path, keys: slice2.map((f) => f.digest) });
21953
+ }
21954
+ } else {
21955
+ for (const f of fresh) {
21956
+ appendEvent(d, { k: "divergence", kind: "external_mutation", path: f.path, hash: f.hash });
21957
+ }
21823
21958
  }
21824
21959
  const newCompactions = (t.compactions ?? 0) - (t.known?.compactions ?? 0);
21825
21960
  for (let i2 = 0; i2 < newCompactions; i2++) {
@@ -22084,7 +22219,7 @@ async function fireClassify(prompt, sessionId, globals) {
22084
22219
  logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
22085
22220
  return;
22086
22221
  }
22087
- const promptHash = (0, import_node_crypto9.createHash)("sha256").update(prompt).digest("hex");
22222
+ const promptHash = (0, import_node_crypto10.createHash)("sha256").update(prompt).digest("hex");
22088
22223
  const result = await apiRequest({
22089
22224
  method: "POST",
22090
22225
  path: "/classify-task",
@@ -22128,7 +22263,7 @@ var import_node_path26 = require("node:path");
22128
22263
  // src/lib/baseline.ts
22129
22264
  var import_node_fs28 = require("node:fs");
22130
22265
  var import_node_path25 = require("node:path");
22131
- var import_node_crypto10 = require("node:crypto");
22266
+ var import_node_crypto11 = require("node:crypto");
22132
22267
 
22133
22268
  // src/lib/snapshot.ts
22134
22269
  var import_node_fs27 = require("node:fs");
@@ -22397,7 +22532,7 @@ var MIRROR_MAX_BYTES = 2 * 1024 * 1024;
22397
22532
  var DEFAULT_SESSION_KEY = "_default";
22398
22533
  function sessionKey(sessionId) {
22399
22534
  if (!sessionId) return DEFAULT_SESSION_KEY;
22400
- return (0, import_node_crypto10.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
22535
+ return (0, import_node_crypto11.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
22401
22536
  }
22402
22537
  function sessionDir(key) {
22403
22538
  return (0, import_node_path25.join)(projectPath(BASELINE_DIR), key);
@@ -22859,17 +22994,17 @@ async function readHookStdin() {
22859
22994
  try {
22860
22995
  if (process.stdin.isTTY) return {};
22861
22996
  const chunks = [];
22862
- const timeout = new Promise((resolve8) => setTimeout(() => resolve8({}), 500));
22863
- const read2 = new Promise((resolve8) => {
22997
+ const timeout = new Promise((resolve9) => setTimeout(() => resolve9({}), 500));
22998
+ const read2 = new Promise((resolve9) => {
22864
22999
  process.stdin.on("data", (c) => chunks.push(c));
22865
23000
  process.stdin.on("end", () => {
22866
23001
  try {
22867
- resolve8(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
23002
+ resolve9(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
22868
23003
  } catch {
22869
- resolve8({});
23004
+ resolve9({});
22870
23005
  }
22871
23006
  });
22872
- process.stdin.on("error", () => resolve8({}));
23007
+ process.stdin.on("error", () => resolve9({}));
22873
23008
  process.stdin.resume();
22874
23009
  });
22875
23010
  return await Promise.race([read2, timeout]);
@@ -22929,6 +23064,41 @@ function setupDataPath(file) {
22929
23064
  var import_node_child_process9 = require("node:child_process");
22930
23065
  var import_node_fs31 = require("node:fs");
22931
23066
  var import_node_path28 = require("node:path");
23067
+
23068
+ // src/lib/self-scope.ts
23069
+ var LEGACY_GATE_SKILLS = /* @__PURE__ */ new Set([
23070
+ "gate-setup",
23071
+ "gate-analyze",
23072
+ "gate-review",
23073
+ "gate-status",
23074
+ "gate-feedback",
23075
+ "gate-insights",
23076
+ "gate-learn",
23077
+ "gate-memory",
23078
+ "gate-reflect"
23079
+ ]);
23080
+ function isVerityOwned(path) {
23081
+ const segments = path.replace(/\\/g, "/").split("/");
23082
+ for (let i2 = 0; i2 < segments.length; i2++) {
23083
+ const seg = segments[i2];
23084
+ if (seg === ".verity" || seg === ".codacy") return true;
23085
+ if (i2 === segments.length - 1 && (seg === "VERITY.md" || seg === "GATE.md")) return true;
23086
+ if (seg === ".claude" && segments[i2 + 1] === "skills" && typeof segments[i2 + 2] === "string") {
23087
+ const skill = segments[i2 + 2];
23088
+ if (skill.startsWith("verity-") || LEGACY_GATE_SKILLS.has(skill)) return true;
23089
+ }
23090
+ if (seg === ".claude" && segments[i2 + 1] === "settings.json") return true;
23091
+ }
23092
+ return false;
23093
+ }
23094
+ function partitionVerityOwned(paths) {
23095
+ const kept = [];
23096
+ const owned = [];
23097
+ for (const p of paths) (isVerityOwned(p) ? owned : kept).push(p);
23098
+ return { kept, owned };
23099
+ }
23100
+
23101
+ // src/lib/detect.ts
22932
23102
  var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
22933
23103
  "typescript",
22934
23104
  "javascript",
@@ -22963,19 +23133,22 @@ function isIgnored2(path) {
22963
23133
  const parts2 = path.split("/");
22964
23134
  return parts2.some((p) => IGNORED_SEGMENTS.includes(p));
22965
23135
  }
23136
+ function isProjectFile(path) {
23137
+ return !isIgnored2(path) && !isVerityOwned(path);
23138
+ }
22966
23139
  function listProjectFiles(root) {
22967
23140
  try {
22968
- const out2 = (0, import_node_child_process9.execSync)("git ls-files -z", {
23141
+ const out2 = (0, import_node_child_process9.execSync)("git ls-files -z --cached --others --exclude-standard", {
22969
23142
  cwd: root,
22970
23143
  encoding: "utf-8",
22971
23144
  maxBuffer: 32 * 1024 * 1024,
22972
23145
  stdio: ["pipe", "pipe", "pipe"]
22973
23146
  });
22974
- const tracked = out2.split("\0").filter(Boolean).filter((p) => !isIgnored2(p));
23147
+ const tracked = out2.split("\0").filter(Boolean).filter(isProjectFile);
22975
23148
  if (tracked.length > 0) return tracked;
22976
23149
  } catch {
22977
23150
  }
22978
- return walk(root);
23151
+ return walk(root).filter(isProjectFile);
22979
23152
  }
22980
23153
  var WALK_MAX_FILES = 2e4;
22981
23154
  var WALK_MAX_DEPTH = 8;
@@ -24152,7 +24325,7 @@ function registerConfigCommands(program2) {
24152
24325
  config.command("formal [state]").description('Get or set formal verification at push: "push" or "off" (needs Lean \u2014 verity lean status)').action((state) => {
24153
24326
  if (state === void 0) {
24154
24327
  const cfg = readProjectConfig();
24155
- process.stdout.write((cfg.formal ?? "off") + "\n");
24328
+ process.stdout.write((cfg.formal === "push" ? "push" : "off") + "\n");
24156
24329
  if (cfg.formal_refused) printWarn(formalRefusalMessage(cfg.formal_refused));
24157
24330
  return;
24158
24331
  }
@@ -24160,7 +24333,7 @@ function registerConfigCommands(program2) {
24160
24333
  printError(`Unrecognised state: ${state}. Use "push" or "off".`);
24161
24334
  process.exit(1);
24162
24335
  }
24163
- writeProjectConfig({ formal: state === "push" ? "push" : void 0 });
24336
+ writeProjectConfig({ formal: state === "push" ? "push" : "off" });
24164
24337
  const refused2 = state === "push" ? readProjectConfig().formal_refused : void 0;
24165
24338
  if (refused2) {
24166
24339
  printWarn(`Formal verification at push: still off \u2014 ${formalRefusalMessage(refused2)}`);
@@ -24317,10 +24490,10 @@ var import_node_fs38 = require("node:fs");
24317
24490
 
24318
24491
  // src/lib/debounce.ts
24319
24492
  var import_node_fs37 = require("node:fs");
24320
- var import_node_crypto11 = require("node:crypto");
24493
+ var import_node_crypto12 = require("node:crypto");
24321
24494
  function scopedFile(base, sessionId) {
24322
24495
  if (!sessionId) return base;
24323
- return `${base}.${(0, import_node_crypto11.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
24496
+ return `${base}.${(0, import_node_crypto12.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
24324
24497
  }
24325
24498
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
24326
24499
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
@@ -24361,7 +24534,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
24361
24534
  return "No files modified since last analysis";
24362
24535
  }
24363
24536
  function computeContentHash(files) {
24364
- const hash = (0, import_node_crypto11.createHash)("sha1");
24537
+ const hash = (0, import_node_crypto12.createHash)("sha1");
24365
24538
  const sorted = [...files].sort();
24366
24539
  for (const f of sorted) {
24367
24540
  const resolved = resolveFile(f) ?? f;
@@ -24817,20 +24990,56 @@ function registerStatusCommand(program2) {
24817
24990
  });
24818
24991
  }
24819
24992
 
24993
+ // src/lib/text-input.ts
24994
+ var import_node_fs39 = require("node:fs");
24995
+ var MAX_STDIN_BYTES = 64 * 1024;
24996
+ function readTextInput(value, flag, readStdin2 = () => (0, import_node_fs39.readFileSync)(0)) {
24997
+ if (value !== "-") return { ok: true, text: value };
24998
+ let raw;
24999
+ try {
25000
+ raw = readStdin2();
25001
+ } catch (err2) {
25002
+ return { ok: false, error: `Could not read ${flag} from stdin: ${err2.message}` };
25003
+ }
25004
+ if (raw.length > MAX_STDIN_BYTES) {
25005
+ return { ok: false, error: `${flag} from stdin is ${raw.length} bytes; the limit is ${MAX_STDIN_BYTES}.` };
25006
+ }
25007
+ const text = raw.toString("utf8").replace(/\r?\n$/, "");
25008
+ if (!text.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
25009
+ return { ok: true, text };
25010
+ }
25011
+
25012
+ // src/lib/terminal-text.ts
25013
+ var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
25014
+ function terminalText(value, max = 4e3) {
25015
+ if (typeof value !== "string") return "";
25016
+ const clean2 = value.replace(CONTROL, "");
25017
+ return clean2.length > max ? `${clean2.slice(0, max - 1)}\u2026` : clean2;
25018
+ }
25019
+ function terminalUrl(value) {
25020
+ const clean2 = terminalText(value, 2e3);
25021
+ return /^https?:\/\/\S+$/.test(clean2) ? clean2 : "";
25022
+ }
25023
+
24820
25024
  // src/commands/feedback.ts
24821
25025
  function registerFeedbackCommand(program2) {
24822
25026
  const feedbackCmd = program2.command("feedback").description("Send feedback to the Verity team");
24823
- feedbackCmd.command("message <text>").description("Send general feedback").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (message, opts) => {
24824
- const globals = program2.opts();
24825
- await sendGeneralFeedback(message, opts, globals);
25027
+ feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text, opts) => {
25028
+ await sendMessageArg(text, opts, program2.opts());
24826
25029
  });
24827
- feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.)").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action, note, opts) => {
25030
+ feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.); a note of - is read from stdin").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action, inlineNote, opts) => {
24828
25031
  const globals = program2.opts();
24829
25032
  const validActions = ["false_positive", "acknowledged", "will_fix_later", "wrong_severity", "useful"];
24830
25033
  if (!validActions.includes(action)) {
24831
25034
  printError(`Invalid action "${action}". Must be one of: ${validActions.join(", ")}`);
24832
25035
  process.exit(1);
24833
25036
  }
25037
+ const noteInput = readTextInput(inlineNote, "the note");
25038
+ if (!noteInput.ok) {
25039
+ printError(noteInput.error);
25040
+ process.exit(1);
25041
+ }
25042
+ const note = noteInput.text;
24834
25043
  const tokenResult = await resolveToken(globals.token);
24835
25044
  if (!tokenResult.ok) {
24836
25045
  printError(tokenResult.error);
@@ -24866,21 +25075,28 @@ function registerFeedbackCommand(program2) {
24866
25075
  });
24867
25076
  feedbackCmd.argument("[message]", "Feedback message (for backwards compat)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (message, opts) => {
24868
25077
  if (!message) return;
24869
- const globals = program2.opts();
24870
- await sendGeneralFeedback(message, opts, globals);
25078
+ await sendMessageArg(message, opts, program2.opts());
24871
25079
  });
24872
25080
  }
25081
+ async function sendMessageArg(arg, opts, globals) {
25082
+ const input = readTextInput(arg, "the message");
25083
+ if (!input.ok || !input.text) {
25084
+ printError(input.ok ? "Nothing to send." : input.error);
25085
+ process.exit(1);
25086
+ }
25087
+ await sendGeneralFeedback(input.text, opts, globals);
25088
+ }
24873
25089
  async function sendGeneralFeedback(message, opts, globals) {
24874
25090
  const tokenResult = await resolveToken(globals.token);
24875
25091
  if (!tokenResult.ok) {
24876
25092
  printError(tokenResult.error);
24877
- printInfo(`Your message: ${message}`);
25093
+ printInfo(`Your message: ${terminalText(message, message.length)}`);
24878
25094
  process.exit(1);
24879
25095
  }
24880
25096
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
24881
25097
  if (!urlResult.ok) {
24882
25098
  printError(urlResult.error);
24883
- printInfo(`Your message: ${message}`);
25099
+ printInfo(`Your message: ${terminalText(message, message.length)}`);
24884
25100
  process.exit(1);
24885
25101
  }
24886
25102
  const body2 = { message };
@@ -24898,7 +25114,7 @@ async function sendGeneralFeedback(message, opts, globals) {
24898
25114
  });
24899
25115
  if (!result.ok) {
24900
25116
  printError(`Couldn't send feedback: ${result.error}`);
24901
- printInfo(`Your message: ${message}`);
25117
+ printInfo(`Your message: ${terminalText(message, message.length)}`);
24902
25118
  process.exit(1);
24903
25119
  }
24904
25120
  printInfo("Thanks, feedback sent!");
@@ -24983,7 +25199,8 @@ function createRun(opts, globals) {
24983
25199
  }
24984
25200
 
24985
25201
  // src/commands/analyze/index.ts
24986
- var import_node_fs52 = require("node:fs");
25202
+ var import_node_fs53 = require("node:fs");
25203
+ var import_node_path40 = require("node:path");
24987
25204
 
24988
25205
  // src/lib/repo-context.ts
24989
25206
  var import_node_child_process11 = require("node:child_process");
@@ -25947,7 +26164,7 @@ function installRunEvidence(run4) {
25947
26164
  }
25948
26165
 
25949
26166
  // src/lib/git-frame.ts
25950
- var import_node_fs39 = require("node:fs");
26167
+ var import_node_fs40 = require("node:fs");
25951
26168
  var import_node_os6 = require("node:os");
25952
26169
  var import_node_path30 = require("node:path");
25953
26170
  var import_node_path31 = require("node:path");
@@ -26117,14 +26334,14 @@ function gitAt(dir, args2) {
26117
26334
  }
26118
26335
  function realpathOr2(p) {
26119
26336
  try {
26120
- return import_node_fs39.realpathSync.native(p);
26337
+ return import_node_fs40.realpathSync.native(p);
26121
26338
  } catch {
26122
26339
  return (0, import_node_path30.resolve)(p);
26123
26340
  }
26124
26341
  }
26125
26342
  function resolveFrame(input) {
26126
26343
  const found = findMomentSegment(input.command, input.on);
26127
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs39.existsSync)(input.hookCwd);
26344
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs40.existsSync)(input.hookCwd);
26128
26345
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
26129
26346
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
26130
26347
  const refuse = (refusal) => ({
@@ -26147,7 +26364,7 @@ function resolveFrame(input) {
26147
26364
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
26148
26365
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
26149
26366
  if (targetDir !== baseDir) {
26150
- if (!(0, import_node_fs39.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26367
+ if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26151
26368
  dir = targetDir;
26152
26369
  }
26153
26370
  }
@@ -26334,7 +26551,7 @@ function stagedRange(frame, command) {
26334
26551
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
26335
26552
  }
26336
26553
  const mergeHead = frame.gitDir ? (0, import_node_path31.join)(frame.gitDir, "MERGE_HEAD") : null;
26337
- if (mergeHead && (0, import_node_fs39.existsSync)(mergeHead)) {
26554
+ if (mergeHead && (0, import_node_fs40.existsSync)(mergeHead)) {
26338
26555
  const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
26339
26556
  const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
26340
26557
  const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
@@ -26468,7 +26685,7 @@ function truthy(v) {
26468
26685
  }
26469
26686
 
26470
26687
  // src/lib/transcript.ts
26471
- var import_node_fs40 = require("node:fs");
26688
+ var import_node_fs41 = require("node:fs");
26472
26689
  var MAX_READ_BYTES = 256 * 1024;
26473
26690
  var SMALL_FILE_BYTES = 64 * 1024;
26474
26691
  var MAX_FILES_LIST = 20;
@@ -26495,7 +26712,7 @@ async function extractActionSummary(transcriptPath) {
26495
26712
  function readTurnLines(transcriptPath) {
26496
26713
  let size;
26497
26714
  try {
26498
- size = (0, import_node_fs40.statSync)(transcriptPath).size;
26715
+ size = (0, import_node_fs41.statSync)(transcriptPath).size;
26499
26716
  } catch {
26500
26717
  return null;
26501
26718
  }
@@ -26503,7 +26720,7 @@ function readTurnLines(transcriptPath) {
26503
26720
  let raw;
26504
26721
  let windowed = false;
26505
26722
  if (size <= SMALL_FILE_BYTES) {
26506
- raw = (0, import_node_fs40.readFileSync)(transcriptPath, "utf-8");
26723
+ raw = (0, import_node_fs41.readFileSync)(transcriptPath, "utf-8");
26507
26724
  } else {
26508
26725
  windowed = true;
26509
26726
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -26749,7 +26966,7 @@ function sanitizeCommandWithLoss(rawCmd) {
26749
26966
  const lost = lines.slice(1).some((l) => l.trim().length > 0);
26750
26967
  const first = lines[0];
26751
26968
  const cmd = sanitizeCommand(first);
26752
- const hadSeparator = SEPARATORS.some((sep5) => first.indexOf(sep5) > 0);
26969
+ const hadSeparator = SEPARATORS.some((sep6) => first.indexOf(sep6) > 0);
26753
26970
  return { cmd, lost: lost || !hadSeparator && first.length > MAX_COMMAND_CHARS };
26754
26971
  }
26755
26972
  var SEPARATORS = [" | ", " > ", " >> ", " 2>", " && ", " ; "];
@@ -26758,11 +26975,11 @@ function sanitizeCommand(rawCmd) {
26758
26975
  let cmd = rawCmd.split("\n")[0];
26759
26976
  let cut = -1;
26760
26977
  let marker = "";
26761
- for (const sep5 of SEPARATORS) {
26762
- const idx = cmd.indexOf(sep5);
26978
+ for (const sep6 of SEPARATORS) {
26979
+ const idx = cmd.indexOf(sep6);
26763
26980
  if (idx > 0 && (cut === -1 || idx < cut)) {
26764
26981
  cut = idx;
26765
- marker = sep5.trim();
26982
+ marker = sep6.trim();
26766
26983
  }
26767
26984
  }
26768
26985
  if (cut > -1) cmd = cmd.slice(0, cut);
@@ -26786,28 +27003,28 @@ async function readStopHookStdin() {
26786
27003
  try {
26787
27004
  if (process.stdin.isTTY) return empty;
26788
27005
  const chunks = [];
26789
- const timeout = new Promise((resolve8) => setTimeout(() => resolve8(empty), 500));
26790
- const read2 = new Promise((resolve8) => {
27006
+ const timeout = new Promise((resolve9) => setTimeout(() => resolve9(empty), 500));
27007
+ const read2 = new Promise((resolve9) => {
26791
27008
  process.stdin.on("data", (chunk) => chunks.push(chunk));
26792
27009
  process.stdin.on("end", () => {
26793
27010
  const raw = Buffer.concat(chunks).toString("utf-8").trim();
26794
27011
  if (!raw) {
26795
- resolve8(empty);
27012
+ resolve9(empty);
26796
27013
  return;
26797
27014
  }
26798
27015
  try {
26799
27016
  const data = JSON.parse(raw);
26800
- resolve8({
27017
+ resolve9({
26801
27018
  assistantMessage: typeof data.last_assistant_message === "string" ? data.last_assistant_message : null,
26802
27019
  stopReason: typeof data.stop_reason === "string" ? data.stop_reason : null,
26803
27020
  transcriptPath: typeof data.transcript_path === "string" ? data.transcript_path : null,
26804
27021
  sessionId: typeof data.session_id === "string" ? data.session_id : null
26805
27022
  });
26806
27023
  } catch {
26807
- resolve8(empty);
27024
+ resolve9(empty);
26808
27025
  }
26809
27026
  });
26810
- process.stdin.on("error", () => resolve8(empty));
27027
+ process.stdin.on("error", () => resolve9(empty));
26811
27028
  process.stdin.resume();
26812
27029
  });
26813
27030
  return await Promise.race([read2, timeout]);
@@ -26861,39 +27078,6 @@ async function bootstrap(run4) {
26861
27078
  Object.assign(run4, { actionSummary, assistantResponse, baseline, baselineSessionId, reachability, sessionId, stopReason, tokenResult, transcriptPath, turnId });
26862
27079
  }
26863
27080
 
26864
- // src/lib/self-scope.ts
26865
- var LEGACY_GATE_SKILLS = /* @__PURE__ */ new Set([
26866
- "gate-setup",
26867
- "gate-analyze",
26868
- "gate-review",
26869
- "gate-status",
26870
- "gate-feedback",
26871
- "gate-insights",
26872
- "gate-learn",
26873
- "gate-memory",
26874
- "gate-reflect"
26875
- ]);
26876
- function isVerityOwned(path) {
26877
- const segments = path.replace(/\\/g, "/").split("/");
26878
- for (let i2 = 0; i2 < segments.length; i2++) {
26879
- const seg = segments[i2];
26880
- if (seg === ".verity" || seg === ".codacy") return true;
26881
- if (i2 === segments.length - 1 && (seg === "VERITY.md" || seg === "GATE.md")) return true;
26882
- if (seg === ".claude" && segments[i2 + 1] === "skills" && typeof segments[i2 + 2] === "string") {
26883
- const skill = segments[i2 + 2];
26884
- if (skill.startsWith("verity-") || LEGACY_GATE_SKILLS.has(skill)) return true;
26885
- }
26886
- if (seg === ".claude" && segments[i2 + 1] === "settings.json") return true;
26887
- }
26888
- return false;
26889
- }
26890
- function partitionVerityOwned(paths) {
26891
- const kept = [];
26892
- const owned = [];
26893
- for (const p of paths) (isVerityOwned(p) ? owned : kept).push(p);
26894
- return { kept, owned };
26895
- }
26896
-
26897
27081
  // src/lib/knowledge-note-state.ts
26898
27082
  var stateDir = () => projectPath(VERITY_DIR);
26899
27083
  var STATE_FILE2 = "knowledge-note-state.json";
@@ -27073,7 +27257,7 @@ function channelSilence(input) {
27073
27257
  // src/lib/cli-version.ts
27074
27258
  function cliVersion() {
27075
27259
  try {
27076
- return true ? "0.34.0-experimental.dc0010f" : "dev";
27260
+ return true ? "0.34.0-experimental.e086ee3" : "dev";
27077
27261
  } catch {
27078
27262
  return "dev";
27079
27263
  }
@@ -27114,7 +27298,171 @@ async function sendSkipBeacon(ctx, reason) {
27114
27298
 
27115
27299
  // src/lib/static-analysis.ts
27116
27300
  var import_node_child_process12 = require("node:child_process");
27117
- var import_node_fs41 = require("node:fs");
27301
+ var import_node_fs42 = require("node:fs");
27302
+
27303
+ // src/lib/environment-globals.ts
27304
+ var NODE = [
27305
+ "process",
27306
+ "Buffer",
27307
+ "global",
27308
+ "require",
27309
+ "module",
27310
+ "exports",
27311
+ "__dirname",
27312
+ "__filename",
27313
+ "console",
27314
+ "setTimeout",
27315
+ "clearTimeout",
27316
+ "setInterval",
27317
+ "clearInterval",
27318
+ "setImmediate",
27319
+ "clearImmediate",
27320
+ "queueMicrotask",
27321
+ "structuredClone",
27322
+ "performance",
27323
+ "fetch",
27324
+ "Request",
27325
+ "Response",
27326
+ "Headers",
27327
+ "FormData",
27328
+ "Blob",
27329
+ "File",
27330
+ "URL",
27331
+ "URLSearchParams",
27332
+ "TextEncoder",
27333
+ "TextDecoder",
27334
+ "TextEncoderStream",
27335
+ "TextDecoderStream",
27336
+ "AbortController",
27337
+ "AbortSignal",
27338
+ "Event",
27339
+ "EventTarget",
27340
+ "CustomEvent",
27341
+ "MessageChannel",
27342
+ "MessagePort",
27343
+ "MessageEvent",
27344
+ "BroadcastChannel",
27345
+ "WebSocket",
27346
+ "WebAssembly",
27347
+ "crypto",
27348
+ "Crypto",
27349
+ "CryptoKey",
27350
+ "SubtleCrypto",
27351
+ "atob",
27352
+ "btoa",
27353
+ "navigator",
27354
+ "DOMException",
27355
+ "ReadableStream",
27356
+ "WritableStream",
27357
+ "TransformStream",
27358
+ "CompressionStream",
27359
+ "DecompressionStream",
27360
+ "ByteLengthQueuingStrategy",
27361
+ "CountQueuingStrategy",
27362
+ "PerformanceObserver",
27363
+ "PerformanceEntry",
27364
+ "PerformanceMark",
27365
+ "PerformanceMeasure"
27366
+ ];
27367
+ var BROWSER = [
27368
+ "window",
27369
+ "self",
27370
+ "document",
27371
+ "location",
27372
+ "history",
27373
+ "localStorage",
27374
+ "sessionStorage",
27375
+ "screen",
27376
+ "alert",
27377
+ "confirm",
27378
+ "prompt",
27379
+ "requestAnimationFrame",
27380
+ "cancelAnimationFrame",
27381
+ "requestIdleCallback",
27382
+ "cancelIdleCallback",
27383
+ "getComputedStyle",
27384
+ "matchMedia",
27385
+ "getSelection",
27386
+ "scrollTo",
27387
+ "scrollBy",
27388
+ "innerWidth",
27389
+ "innerHeight",
27390
+ "outerWidth",
27391
+ "outerHeight",
27392
+ "devicePixelRatio",
27393
+ "visualViewport",
27394
+ "postMessage",
27395
+ "addEventListener",
27396
+ "removeEventListener",
27397
+ "dispatchEvent",
27398
+ "customElements",
27399
+ "indexedDB",
27400
+ "IDBKeyRange",
27401
+ "caches",
27402
+ "XMLHttpRequest",
27403
+ "EventSource",
27404
+ "FileReader",
27405
+ "Image",
27406
+ "Audio",
27407
+ "Worker",
27408
+ "SharedWorker",
27409
+ "Notification",
27410
+ "MutationObserver",
27411
+ "IntersectionObserver",
27412
+ "ResizeObserver",
27413
+ "DOMParser",
27414
+ "XMLSerializer",
27415
+ "Node",
27416
+ "Element",
27417
+ "HTMLElement",
27418
+ "SVGElement",
27419
+ "NodeList",
27420
+ "HTMLCollection",
27421
+ "DocumentFragment",
27422
+ "ShadowRoot",
27423
+ "Range",
27424
+ "Selection",
27425
+ "KeyboardEvent",
27426
+ "MouseEvent",
27427
+ "PointerEvent",
27428
+ "FocusEvent",
27429
+ "InputEvent",
27430
+ "TouchEvent",
27431
+ "UIEvent",
27432
+ "ErrorEvent",
27433
+ "ProgressEvent",
27434
+ "StorageEvent",
27435
+ "CloseEvent",
27436
+ "CSS",
27437
+ "CSSStyleSheet",
27438
+ "FontFace",
27439
+ "ImageData",
27440
+ "ImageBitmap",
27441
+ "createImageBitmap",
27442
+ "OffscreenCanvas",
27443
+ "Path2D",
27444
+ "CanvasRenderingContext2D",
27445
+ "AudioContext",
27446
+ "MediaStream",
27447
+ "MediaRecorder",
27448
+ "RTCPeerConnection",
27449
+ "ClipboardItem",
27450
+ "isSecureContext",
27451
+ "crossOriginIsolated",
27452
+ "reportError",
27453
+ "speechSynthesis"
27454
+ ];
27455
+ var ENVIRONMENT_GLOBALS = /* @__PURE__ */ new Set([...NODE, ...BROWSER]);
27456
+ var NOT_DEFINED = /^'([^']+)' is not defined\.?$/;
27457
+ var COMMONJS_ONLY = /* @__PURE__ */ new Set(["require", "module", "exports", "__dirname", "__filename"]);
27458
+ function isEnvironmentGlobalNoUndef(ruleId, message, filePath = "") {
27459
+ if (!/(^|_)no-undef$/.test(ruleId)) return false;
27460
+ const name2 = message.trim().match(NOT_DEFINED)?.[1];
27461
+ if (name2 === void 0 || !ENVIRONMENT_GLOBALS.has(name2)) return false;
27462
+ return !(COMMONJS_ONLY.has(name2) && /\.m[jt]s$/.test(filePath));
27463
+ }
27464
+
27465
+ // src/lib/static-analysis.ts
27118
27466
  var SEVERITY_ORDER = {
27119
27467
  Error: 0,
27120
27468
  Critical: 0,
@@ -27170,7 +27518,7 @@ function runCodacyAnalysis(files) {
27170
27518
  if (files.length === 0) return empty;
27171
27519
  const existingFiles = files.filter((f) => {
27172
27520
  try {
27173
- return (0, import_node_fs41.existsSync)(f);
27521
+ return (0, import_node_fs42.existsSync)(f);
27174
27522
  } catch {
27175
27523
  return false;
27176
27524
  }
@@ -27202,7 +27550,10 @@ function interpretAnalyzerRun(run4) {
27202
27550
  } catch {
27203
27551
  return withFailure("unparseable_output", output);
27204
27552
  }
27205
- const issues = parsed.issues ?? [];
27553
+ const reported = parsed.issues ?? [];
27554
+ const issues = reported.filter(
27555
+ (i2) => !isEnvironmentGlobalNoUndef(i2.patternId ?? "", i2.message ?? "", i2.filePath ?? "")
27556
+ );
27206
27557
  const findings = issues.map((issue) => ({
27207
27558
  rule_id: issue.patternId ?? "",
27208
27559
  tool: issue.toolId ?? "",
@@ -27225,7 +27576,7 @@ function interpretAnalyzerRun(run4) {
27225
27576
  );
27226
27577
  const analyzerErrors = parsed.errors ?? [];
27227
27578
  let failure;
27228
- if (findings.length === 0) {
27579
+ if (reported.length === 0) {
27229
27580
  if (analyzerErrors.length > 0) {
27230
27581
  const first = analyzerErrors[0];
27231
27582
  failure = {
@@ -27439,7 +27790,7 @@ async function scope(run4) {
27439
27790
  }
27440
27791
 
27441
27792
  // src/lib/specs.ts
27442
- var import_node_fs42 = require("node:fs");
27793
+ var import_node_fs43 = require("node:fs");
27443
27794
  var import_node_path32 = require("node:path");
27444
27795
  var SPEC_CANDIDATES = [
27445
27796
  "CLAUDE.md",
@@ -27481,7 +27832,7 @@ function discoverSpecs(consulted = []) {
27481
27832
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
27482
27833
  if (totalBytes >= totalCap) return false;
27483
27834
  if (seen.has(specPath)) return true;
27484
- if (!(0, import_node_fs42.existsSync)(specPath)) return true;
27835
+ if (!(0, import_node_fs43.existsSync)(specPath)) return true;
27485
27836
  seen.add(specPath);
27486
27837
  const remaining = totalCap - totalBytes;
27487
27838
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
@@ -27504,7 +27855,7 @@ function discoverSpecs(consulted = []) {
27504
27855
  if (!addSpec(candidate)) break;
27505
27856
  }
27506
27857
  for (const dir of ["spec", "docs"]) {
27507
- if (!(0, import_node_fs42.existsSync)(dir)) continue;
27858
+ if (!(0, import_node_fs43.existsSync)(dir)) continue;
27508
27859
  try {
27509
27860
  const mdFiles = findMdFiles(dir, 2).sort();
27510
27861
  for (const mdFile of mdFiles) {
@@ -27519,7 +27870,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
27519
27870
  if (depth >= maxDepth) return [];
27520
27871
  const result = [];
27521
27872
  try {
27522
- const entries = (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true });
27873
+ const entries = (0, import_node_fs43.readdirSync)(dir, { withFileTypes: true });
27523
27874
  for (const entry of entries) {
27524
27875
  const fullPath = (0, import_node_path32.join)(dir, entry.name);
27525
27876
  if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -27539,13 +27890,13 @@ function discoverPlans() {
27539
27890
  if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
27540
27891
  sources.push({ root: process.cwd(), prefix: (0, import_node_path32.join)(".claude", "plans") });
27541
27892
  }
27542
- if (home && (0, import_node_fs42.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
27893
+ if (home && (0, import_node_fs43.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
27543
27894
  const candidates2 = [];
27544
27895
  const seen = /* @__PURE__ */ new Set();
27545
27896
  for (const source2 of sources) {
27546
27897
  let names2;
27547
27898
  try {
27548
- names2 = (0, import_node_fs42.readdirSync)(source2.prefix ? (0, import_node_path32.join)(source2.root, source2.prefix) : source2.root);
27899
+ names2 = (0, import_node_fs43.readdirSync)(source2.prefix ? (0, import_node_path32.join)(source2.root, source2.prefix) : source2.root);
27549
27900
  } catch {
27550
27901
  continue;
27551
27902
  }
@@ -27572,7 +27923,7 @@ function isRealDirectoryChain(root, parts2) {
27572
27923
  for (const part of parts2) {
27573
27924
  current = (0, import_node_path32.join)(current, part);
27574
27925
  try {
27575
- if (!(0, import_node_fs42.lstatSync)(current).isDirectory()) return false;
27926
+ if (!(0, import_node_fs43.lstatSync)(current).isDirectory()) return false;
27576
27927
  } catch {
27577
27928
  return false;
27578
27929
  }
@@ -27587,7 +27938,7 @@ function discoverGuardDocs(rangeFiles2) {
27587
27938
  if (result.length >= MAX_SPEC_FILES) break;
27588
27939
  if (!GUARD_DOC_EXT.test(path)) continue;
27589
27940
  if (path.startsWith("/") || path.includes("..")) continue;
27590
- if (!(0, import_node_fs42.existsSync)(path)) continue;
27941
+ if (!(0, import_node_fs43.existsSync)(path)) continue;
27591
27942
  const opened = openRegularInRoot(process.cwd(), path);
27592
27943
  if (!opened.ok) continue;
27593
27944
  if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
@@ -27773,7 +28124,7 @@ async function mode(run4) {
27773
28124
  }
27774
28125
 
27775
28126
  // src/lib/fold.ts
27776
- var import_node_fs43 = require("node:fs");
28127
+ var import_node_fs44 = require("node:fs");
27777
28128
  var import_node_path33 = require("node:path");
27778
28129
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
27779
28130
  "user",
@@ -27911,7 +28262,7 @@ function candidateRoots(repoRoot2) {
27911
28262
  const norm2 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
27912
28263
  const out2 = [norm2];
27913
28264
  try {
27914
- const real = import_node_fs43.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
28265
+ const real = import_node_fs44.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
27915
28266
  if (real !== norm2) out2.push(real);
27916
28267
  } catch {
27917
28268
  }
@@ -27999,8 +28350,8 @@ function fold(transcriptPath, opts = {}) {
27999
28350
  }
28000
28351
  };
28001
28352
  try {
28002
- if (!(0, import_node_fs43.existsSync)(transcriptPath)) return result;
28003
- ingest((0, import_node_fs43.readFileSync)(transcriptPath, "utf8"), "agent");
28353
+ if (!(0, import_node_fs44.existsSync)(transcriptPath)) return result;
28354
+ ingest((0, import_node_fs44.readFileSync)(transcriptPath, "utf8"), "agent");
28004
28355
  result.coverage.complete = true;
28005
28356
  } catch {
28006
28357
  return result;
@@ -28011,19 +28362,19 @@ function fold(transcriptPath, opts = {}) {
28011
28362
  (0, import_node_path33.basename)(transcriptPath).replace(/\.jsonl$/, ""),
28012
28363
  "subagents"
28013
28364
  );
28014
- if ((0, import_node_fs43.existsSync)(sidecarDir)) {
28365
+ if ((0, import_node_fs44.existsSync)(sidecarDir)) {
28015
28366
  const maxFiles = opts.maxSidecars ?? 200;
28016
28367
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
28017
28368
  const found = [];
28018
28369
  const walk2 = (d, depth) => {
28019
28370
  if (depth > 4) return;
28020
- for (const e of (0, import_node_fs43.readdirSync)(d, { withFileTypes: true })) {
28371
+ for (const e of (0, import_node_fs44.readdirSync)(d, { withFileTypes: true })) {
28021
28372
  const p = (0, import_node_path33.join)(d, e.name);
28022
28373
  if (e.isDirectory()) {
28023
28374
  walk2(p, depth + 1);
28024
28375
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
28025
28376
  try {
28026
- const st = (0, import_node_fs43.statSync)(p);
28377
+ const st = (0, import_node_fs44.statSync)(p);
28027
28378
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
28028
28379
  } catch {
28029
28380
  result.coverage.malformed++;
@@ -28040,7 +28391,7 @@ function fold(transcriptPath, opts = {}) {
28040
28391
  continue;
28041
28392
  }
28042
28393
  try {
28043
- ingest((0, import_node_fs43.readFileSync)(f.path, "utf8"), "subagent");
28394
+ ingest((0, import_node_fs44.readFileSync)(f.path, "utf8"), "subagent");
28044
28395
  bytes += f.size;
28045
28396
  result.coverage.subagentFiles++;
28046
28397
  } catch {
@@ -28075,7 +28426,7 @@ function fold(transcriptPath, opts = {}) {
28075
28426
  }
28076
28427
  function classifyUnobserved(path) {
28077
28428
  try {
28078
- const st = (0, import_node_fs43.statSync)(path);
28429
+ const st = (0, import_node_fs44.statSync)(path);
28079
28430
  if (!st.isFile()) return "unreadable";
28080
28431
  } catch {
28081
28432
  return "unreadable";
@@ -28390,20 +28741,20 @@ async function evidence(run4) {
28390
28741
  }
28391
28742
 
28392
28743
  // src/lib/cache-cleanup.ts
28393
- var import_node_fs44 = require("node:fs");
28744
+ var import_node_fs45 = require("node:fs");
28394
28745
  var import_node_path34 = require("node:path");
28395
28746
  var CACHE_TTL_DAYS = 7;
28396
28747
  function pruneStaleCache() {
28397
28748
  try {
28398
28749
  const dir = projectPath(CACHE_DIR);
28399
28750
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
28400
- for (const entry of (0, import_node_fs44.readdirSync)(dir)) {
28751
+ for (const entry of (0, import_node_fs45.readdirSync)(dir)) {
28401
28752
  if (!entry.startsWith("pending-")) continue;
28402
28753
  const path = (0, import_node_path34.join)(dir, entry);
28403
28754
  try {
28404
- const stat3 = (0, import_node_fs44.statSync)(path);
28755
+ const stat3 = (0, import_node_fs45.statSync)(path);
28405
28756
  if (stat3.mtimeMs < cutoff) {
28406
- (0, import_node_fs44.unlinkSync)(path);
28757
+ (0, import_node_fs45.unlinkSync)(path);
28407
28758
  logEvent("cache_entry_pruned", {
28408
28759
  path: entry,
28409
28760
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -28417,7 +28768,7 @@ function pruneStaleCache() {
28417
28768
  }
28418
28769
 
28419
28770
  // src/lib/context-files.ts
28420
- var import_node_fs45 = require("node:fs");
28771
+ var import_node_fs46 = require("node:fs");
28421
28772
  var import_node_os7 = require("node:os");
28422
28773
  var MAX_CONTEXT_FILES = 10;
28423
28774
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -28475,7 +28826,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
28475
28826
  continue;
28476
28827
  }
28477
28828
  try {
28478
- const content = (0, import_node_fs45.readFileSync)(safePath, "utf8");
28829
+ const content = (0, import_node_fs46.readFileSync)(safePath, "utf8");
28479
28830
  const bytes = Buffer.byteLength(content);
28480
28831
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
28481
28832
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -28541,7 +28892,7 @@ async function contextFiles(run4) {
28541
28892
  }
28542
28893
 
28543
28894
  // src/lib/code/index.ts
28544
- var import_node_crypto12 = require("node:crypto");
28895
+ var import_node_crypto13 = require("node:crypto");
28545
28896
 
28546
28897
  // src/lib/code/languages.ts
28547
28898
  var JS_LIKE = {
@@ -28633,7 +28984,7 @@ function languageOf2(path) {
28633
28984
  }
28634
28985
 
28635
28986
  // src/lib/code/runtime.ts
28636
- var import_node_fs46 = require("node:fs");
28987
+ var import_node_fs47 = require("node:fs");
28637
28988
  var import_node_path35 = require("node:path");
28638
28989
  var import_web_tree_sitter2 = __toESM2(require_web_tree_sitter2());
28639
28990
 
@@ -28705,7 +29056,7 @@ function grammarCandidates(file, pkg, env = process.env) {
28705
29056
  }
28706
29057
  function locateGrammar(id, env = process.env) {
28707
29058
  const g = grammars_default[id];
28708
- return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs46.existsSync)(p)) ?? null;
29059
+ return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs47.existsSync)(p)) ?? null;
28709
29060
  }
28710
29061
  var loading = null;
28711
29062
  function loadRuntime(env = process.env) {
@@ -30319,7 +30670,7 @@ function byPath(fns, name2) {
30319
30670
  function makeCodeMap(rt) {
30320
30671
  const cache = /* @__PURE__ */ new Map();
30321
30672
  const outline = (path, content, deadlineAt = Date.now() + DEFAULT_PARSE_MS) => {
30322
- const key = `${path}\0${(0, import_node_crypto12.createHash)("sha1").update(content).digest("hex")}`;
30673
+ const key = `${path}\0${(0, import_node_crypto13.createHash)("sha1").update(content).digest("hex")}`;
30323
30674
  const hit = cache.get(key);
30324
30675
  if (hit) return { source: "tree-sitter", value: hit, elapsedMs: 0 };
30325
30676
  let r;
@@ -31034,7 +31385,7 @@ async function repoContext(run4) {
31034
31385
 
31035
31386
  // src/lib/seed-runner.ts
31036
31387
  var import_promises15 = require("node:fs/promises");
31037
- var import_node_fs47 = require("node:fs");
31388
+ var import_node_fs48 = require("node:fs");
31038
31389
  var import_node_path36 = require("node:path");
31039
31390
  var import_yaml4 = __toESM2(require_dist());
31040
31391
 
@@ -31259,7 +31610,7 @@ async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
31259
31610
  const titles = /* @__PURE__ */ new Set();
31260
31611
  for (const dir of NODE_DIRS) {
31261
31612
  const full = (0, import_node_path36.join)(memoryDir3, dir);
31262
- if (!(0, import_node_fs47.existsSync)(full)) continue;
31613
+ if (!(0, import_node_fs48.existsSync)(full)) continue;
31263
31614
  let files;
31264
31615
  try {
31265
31616
  files = await (0, import_promises15.readdir)(full);
@@ -31341,7 +31692,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
31341
31692
  return fm;
31342
31693
  }
31343
31694
  async function runSeed(opts) {
31344
- if (!(0, import_node_fs47.existsSync)(STANDARD_FILE)) {
31695
+ if (!(0, import_node_fs48.existsSync)(STANDARD_FILE)) {
31345
31696
  return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
31346
31697
  }
31347
31698
  let standardDoc;
@@ -31353,7 +31704,7 @@ async function runSeed(opts) {
31353
31704
  }
31354
31705
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
31355
31706
  let readmeContent;
31356
- if ((0, import_node_fs47.existsSync)("README.md")) {
31707
+ if ((0, import_node_fs48.existsSync)("README.md")) {
31357
31708
  try {
31358
31709
  readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
31359
31710
  } catch {
@@ -31361,7 +31712,7 @@ async function runSeed(opts) {
31361
31712
  }
31362
31713
  let claudeMdContent;
31363
31714
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
31364
- if ((0, import_node_fs47.existsSync)(p)) {
31715
+ if ((0, import_node_fs48.existsSync)(p)) {
31365
31716
  try {
31366
31717
  claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
31367
31718
  break;
@@ -31441,7 +31792,7 @@ async function runSeed(opts) {
31441
31792
  continue;
31442
31793
  }
31443
31794
  const deduplicated = res.data.deduplicated === true;
31444
- if (deduplicated && (0, import_node_fs47.existsSync)(targetPath)) {
31795
+ if (deduplicated && (0, import_node_fs48.existsSync)(targetPath)) {
31445
31796
  existing++;
31446
31797
  continue;
31447
31798
  }
@@ -31463,7 +31814,7 @@ async function runSeed(opts) {
31463
31814
  }
31464
31815
 
31465
31816
  // src/commands/analyze/phases/08-memory-manifest.ts
31466
- var import_node_fs48 = require("node:fs");
31817
+ var import_node_fs49 = require("node:fs");
31467
31818
  var import_node_path37 = require("node:path");
31468
31819
  async function memoryManifest(run4) {
31469
31820
  const { globals } = run4;
@@ -31475,8 +31826,8 @@ async function memoryManifest(run4) {
31475
31826
  try {
31476
31827
  await ensureMemoryDir();
31477
31828
  const seedMarker = (0, import_node_path37.join)(VERITY_DIR, ".seeded");
31478
- const hasStandard = (0, import_node_fs48.existsSync)(STANDARD_FILE);
31479
- const alreadyTried = (0, import_node_fs48.existsSync)(seedMarker);
31829
+ const hasStandard = (0, import_node_fs49.existsSync)(STANDARD_FILE);
31830
+ const alreadyTried = (0, import_node_fs49.existsSync)(seedMarker);
31480
31831
  if (hasStandard && !alreadyTried) {
31481
31832
  const preManifest = await buildManifest();
31482
31833
  if (preManifest.nodes.length === 0) {
@@ -31489,7 +31840,7 @@ async function memoryManifest(run4) {
31489
31840
  dryRun: false
31490
31841
  });
31491
31842
  if (seedResult.created > 0 || seedResult.existing > 0) {
31492
- (0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
31843
+ (0, import_node_fs49.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
31493
31844
  `);
31494
31845
  if (seedResult.created > 0) {
31495
31846
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
@@ -31500,7 +31851,7 @@ async function memoryManifest(run4) {
31500
31851
  failed: seedResult.failed
31501
31852
  });
31502
31853
  } else if (seedResult.skipped === "already_seeded") {
31503
- (0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
31854
+ (0, import_node_fs49.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
31504
31855
  `);
31505
31856
  } else {
31506
31857
  logEvent("auto_seed_noop", {
@@ -31688,8 +32039,24 @@ async function workingMemory(run4) {
31688
32039
  Object.assign(run4, { incrementReport, memory: memory2, memorySession, reachability });
31689
32040
  }
31690
32041
 
32042
+ // src/lib/payload-bounds.ts
32043
+ var MAX_WIRE_PATHS = 500;
32044
+ function boundPaths(paths, first, max = MAX_WIRE_PATHS) {
32045
+ if (paths.length <= max) return [...paths];
32046
+ const present = new Set(paths);
32047
+ const kept = /* @__PURE__ */ new Set();
32048
+ const out2 = [];
32049
+ for (const p of [...first, ...paths]) {
32050
+ if (out2.length >= max) break;
32051
+ if (!present.has(p) || kept.has(p)) continue;
32052
+ kept.add(p);
32053
+ out2.push(p);
32054
+ }
32055
+ return out2;
32056
+ }
32057
+
31691
32058
  // src/lib/note-budget.ts
31692
- var import_node_fs49 = require("node:fs");
32059
+ var import_node_fs50 = require("node:fs");
31693
32060
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
31694
32061
  var EPISODE_STALE_SECONDS = 30 * 60;
31695
32062
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -31711,9 +32078,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
31711
32078
  }
31712
32079
  function readAdvisoryEpisode(sessionId) {
31713
32080
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
31714
- if (!(0, import_node_fs49.existsSync)(file)) return null;
32081
+ if (!(0, import_node_fs50.existsSync)(file)) return null;
31715
32082
  try {
31716
- const o = JSON.parse((0, import_node_fs49.readFileSync)(file, "utf-8")) ?? {};
32083
+ const o = JSON.parse((0, import_node_fs50.readFileSync)(file, "utf-8")) ?? {};
31717
32084
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
31718
32085
  if (isNaN(delivered)) return null;
31719
32086
  return {
@@ -31727,8 +32094,8 @@ function readAdvisoryEpisode(sessionId) {
31727
32094
  }
31728
32095
  function writeAdvisoryEpisode(episode, sessionId) {
31729
32096
  try {
31730
- (0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
31731
- (0, import_node_fs49.writeFileSync)(
32097
+ (0, import_node_fs50.mkdirSync)(VERITY_DIR, { recursive: true });
32098
+ (0, import_node_fs50.writeFileSync)(
31732
32099
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
31733
32100
  JSON.stringify({ v: 1, ...episode })
31734
32101
  );
@@ -31802,6 +32169,7 @@ async function buildRequest(run4) {
31802
32169
  (conversation?.prompts?.length ?? 0) > 0
31803
32170
  );
31804
32171
  const noteConfirmation = peekNoteOutcome();
32172
+ const unobserved = foldResult?.unobserved ?? [];
31805
32173
  const excludedByReason = {};
31806
32174
  for (const e of codeDelta.excluded ?? []) {
31807
32175
  excludedByReason[e.reason] = (excludedByReason[e.reason] ?? 0) + 1;
@@ -31846,7 +32214,9 @@ async function buildRequest(run4) {
31846
32214
  coverage_telemetry: coverageTelemetry,
31847
32215
  static_results: staticResults,
31848
32216
  code_delta: codeDelta,
31849
- changed_files: allForReview,
32217
+ // Bounded, reviewed paths first — the server applies the same bound. The
32218
+ // full count is `coverage_telemetry.for_review`. VRT-242.
32219
+ changed_files: boundPaths(allForReview, codeDelta.files.map((f) => f.path)),
31850
32220
  standard_version: "latest",
31851
32221
  analysis_mode: analysisMode,
31852
32222
  plan_only: analysisMode === "plan",
@@ -31897,7 +32267,9 @@ async function buildRequest(run4) {
31897
32267
  // `hash_at_last_verdict` is frozen at each verdict and `hash_now` tracks
31898
32268
  // disk, so their inequality IS "changed since we last spoke".
31899
32269
  authored_since_verdict: memorySession ? foldDossier(memorySession.d).authored_all.filter((a) => a.hash_now !== a.hash_at_last_verdict).map((a) => a.path) : [],
31900
- unobserved: foldResult?.unobserved ?? [],
32270
+ // The server reads only how many; a bulk change sent every path. VRT-242.
32271
+ unobserved: unobserved.slice(0, MAX_WIRE_PATHS),
32272
+ ...unobserved.length > MAX_WIRE_PATHS && { unobserved_total: unobserved.length },
31901
32273
  commands: foldResult?.commands ?? [],
31902
32274
  tools: foldResult?.tools ?? [],
31903
32275
  tasks: foldResult?.tasks ?? [],
@@ -32060,14 +32432,14 @@ async function buildRequest(run4) {
32060
32432
  }
32061
32433
 
32062
32434
  // src/lib/offline.ts
32063
- var import_node_fs50 = require("node:fs");
32064
- var import_node_crypto13 = require("node:crypto");
32435
+ var import_node_fs51 = require("node:fs");
32436
+ var import_node_crypto14 = require("node:crypto");
32065
32437
  function cacheRequest(body2) {
32066
32438
  try {
32067
- (0, import_node_fs50.mkdirSync)(CACHE_DIR, { recursive: true });
32068
- const suffix = (0, import_node_crypto13.randomBytes)(4).toString("hex");
32439
+ (0, import_node_fs51.mkdirSync)(CACHE_DIR, { recursive: true });
32440
+ const suffix = (0, import_node_crypto14.randomBytes)(4).toString("hex");
32069
32441
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
32070
- (0, import_node_fs50.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
32442
+ (0, import_node_fs51.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
32071
32443
  } catch {
32072
32444
  }
32073
32445
  }
@@ -32108,8 +32480,10 @@ function buildOfflineFallback(reason, staticResults) {
32108
32480
  }
32109
32481
 
32110
32482
  // src/lib/retry.ts
32483
+ var WORKER_RESOURCE_LIMIT = 546;
32111
32484
  function shouldWarmRetryAnalyze(result) {
32112
32485
  if (result.ok) return false;
32486
+ if (result.http_status === WORKER_RESOURCE_LIMIT) return false;
32113
32487
  if (result.category === "network" || result.category === "timeout") return true;
32114
32488
  if (result.category === "http_5xx") return true;
32115
32489
  if (result.category === "invalid_json" && (result.http_status ?? 0) >= 500) return true;
@@ -32119,7 +32493,7 @@ function shouldWarmRetryAnalyze(result) {
32119
32493
  // src/commands/analyze/phases/12-transmit.ts
32120
32494
  async function transmit(run4) {
32121
32495
  const { globals } = run4;
32122
- const { codeDelta, requestBody, serviceUrl, staticResults, token } = run4;
32496
+ const { requestBody, serviceUrl, staticResults, token } = run4;
32123
32497
  const ANALYZE_TIMEOUT_MS = 1e5;
32124
32498
  let result = await analyzeRequest({
32125
32499
  serviceUrl,
@@ -32156,11 +32530,12 @@ async function transmit(run4) {
32156
32530
  }
32157
32531
  if (!result.ok) {
32158
32532
  cacheRequest(requestBody);
32533
+ const sentKb = () => Math.round(Buffer.byteLength(JSON.stringify(requestBody)) / 1024);
32159
32534
  let message;
32160
32535
  if (result.http_status === 413) {
32161
- const totalBytes = codeDelta.files.reduce((sum, f) => sum + f.content.length, 0);
32162
- const kb = Math.round(totalBytes / 1024);
32163
- message = `Verity: request rejected \u2014 payload too large (${kb}KB over the 190KB cap). Commit or stash pre-existing changes, or run with --mode skip if you didn't intend to submit code this turn.`;
32536
+ message = `Verity: request rejected \u2014 payload too large (${sentKb()} KB sent: ${result.error}). Commit or stash pre-existing changes, or run with --mode skip if you didn't intend to submit code this turn.`;
32537
+ } else if (result.http_status === WORKER_RESOURCE_LIMIT) {
32538
+ message = `Verity: the service ran out of CPU or memory on this request (HTTP 546, ${sentKb()} KB sent). This is not a cold start: the same change fails the same way, so it was not retried. Commit or stash unrelated changes to shrink the request (local analysis this run).`;
32164
32539
  } else if (result.category === "network" || result.category === "timeout") {
32165
32540
  message = `Verity offline \u2014 ${result.error}`;
32166
32541
  } else if (result.error.startsWith("STALE_VERIFICATION")) {
@@ -32186,7 +32561,7 @@ async function transmit(run4) {
32186
32561
  }
32187
32562
 
32188
32563
  // src/commands/analyze/phases/13-reconcile.ts
32189
- var import_node_fs51 = require("node:fs");
32564
+ var import_node_fs52 = require("node:fs");
32190
32565
  var import_node_path39 = require("node:path");
32191
32566
  async function reconcile(run4) {
32192
32567
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory: memory2, memorySession, response, reviewable, securityFiles, turnId } = run4;
@@ -32216,7 +32591,7 @@ async function reconcile(run4) {
32216
32591
  const st = foldDossier(memorySession.d);
32217
32592
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line2) => {
32218
32593
  try {
32219
- const src = (0, import_node_fs51.readFileSync)((0, import_node_path39.join)(repoRoot(), file), "utf8").split("\n");
32594
+ const src = (0, import_node_fs52.readFileSync)((0, import_node_path39.join)(repoRoot(), file), "utf8").split("\n");
32220
32595
  const at = src[line2 - 1];
32221
32596
  return at === void 0 ? null : lineSha(at);
32222
32597
  } catch {
@@ -33038,7 +33413,7 @@ function registerAnalyzeCommand(program2) {
33038
33413
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
33039
33414
  async function runAnalyze(opts, globals) {
33040
33415
  if (!verityConfigured()) {
33041
- (0, import_node_fs52.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
33416
+ (0, import_node_fs53.writeSync)(2, isMachineStore((0, import_node_path40.join)(repoRoot(), VERITY_DIR)) ? "[verity] nothing to review in your home directory \u2014 run Verity inside a project.\n" : '[verity] not set up in this project \u2014 run "verity init" first.\n');
33042
33417
  process.exit(0);
33043
33418
  }
33044
33419
  const run4 = createRun(opts, globals);
@@ -33059,11 +33434,12 @@ async function runAnalyze(opts, globals) {
33059
33434
  }
33060
33435
 
33061
33436
  // src/commands/baseline.ts
33062
- var import_node_fs54 = require("node:fs");
33437
+ var import_node_fs55 = require("node:fs");
33438
+ var import_node_path42 = require("node:path");
33063
33439
 
33064
33440
  // src/lib/project-skills.ts
33065
- var import_node_fs53 = require("node:fs");
33066
- var import_node_path40 = require("node:path");
33441
+ var import_node_fs54 = require("node:fs");
33442
+ var import_node_path41 = require("node:path");
33067
33443
  var PROJECT_SKILL_NAMES = [
33068
33444
  "verity-setup",
33069
33445
  "verity-analyze",
@@ -33089,14 +33465,14 @@ var LEGACY_SKILL_NAMES = [
33089
33465
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
33090
33466
  function staleProjectSkills() {
33091
33467
  const root = projectPath(".claude/skills");
33092
- if (!(0, import_node_fs53.existsSync)(root)) return [];
33093
- return ALL.filter((name2) => (0, import_node_fs53.existsSync)((0, import_node_path40.join)(root, name2)));
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)));
33094
33470
  }
33095
33471
  function removeProjectSkills() {
33096
33472
  const root = projectPath(".claude/skills");
33097
33473
  const removed = [];
33098
33474
  for (const name2 of staleProjectSkills()) {
33099
- (0, import_node_fs53.rmSync)((0, import_node_path40.join)(root, name2), { recursive: true, force: true });
33475
+ (0, import_node_fs54.rmSync)((0, import_node_path41.join)(root, name2), { recursive: true, force: true });
33100
33476
  removed.push(name2);
33101
33477
  }
33102
33478
  return removed;
@@ -33129,6 +33505,7 @@ function registerBaselineCommands(program2) {
33129
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;
33130
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;
33131
33507
  if (!verityConfigured()) {
33508
+ if (isMachineStore((0, import_node_path42.join)(repoRoot(), VERITY_DIR))) process.exit(0);
33132
33509
  const how = isPluginInvocation() ? "Tell the user to run /verity:init \u2014 they type it; you cannot invoke it." : "Tell the user to run `verity init` in their terminal.";
33133
33510
  const lines = [
33134
33511
  `Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
@@ -33161,13 +33538,13 @@ function registerBaselineCommands(program2) {
33161
33538
  let memoryMsg = null;
33162
33539
  let memoryAgentLine = null;
33163
33540
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
33164
- if (realStart && !(0, import_node_fs54.existsSync)(memoryNotice)) {
33541
+ if (realStart && !(0, import_node_fs55.existsSync)(memoryNotice)) {
33165
33542
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
33166
33543
  if (trackedGraph > 0) {
33167
33544
  memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
33168
33545
  memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
33169
33546
  try {
33170
- (0, import_node_fs54.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33547
+ (0, import_node_fs55.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33171
33548
  } catch {
33172
33549
  }
33173
33550
  }
@@ -33268,10 +33645,16 @@ function hookSource(value) {
33268
33645
  }
33269
33646
 
33270
33647
  // src/commands/review.ts
33271
- var import_node_fs55 = require("node:fs");
33648
+ var import_node_fs56 = require("node:fs");
33272
33649
  function registerReviewCommand(program2) {
33273
- program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars)").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
33650
+ program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars); - reads it from stdin, so the words never pass through shell quoting").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
33274
33651
  const globals = program2.opts();
33652
+ const intent = readTextInput(opts.intent, "--intent");
33653
+ if (!intent.ok) {
33654
+ printError(intent.error);
33655
+ process.exit(0);
33656
+ }
33657
+ opts.intent = intent.text;
33275
33658
  try {
33276
33659
  await runReview(opts, globals);
33277
33660
  } catch (err2) {
@@ -33285,7 +33668,7 @@ async function runReview(opts, globals) {
33285
33668
  const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
33286
33669
  const analyzable = filterAnalyzable(allFiles);
33287
33670
  const securityFiles = filterSecurity(allFiles);
33288
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs55.existsSync)(f) || resolveFile(f) !== null);
33671
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs56.existsSync)(f) || resolveFile(f) !== null);
33289
33672
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
33290
33673
  const codeDelta = collectCodeDelta(allFiles);
33291
33674
  const tokenResult = await resolveToken(globals.token);
@@ -33351,19 +33734,40 @@ async function runReview(opts, globals) {
33351
33734
  }
33352
33735
 
33353
33736
  // src/commands/guard.ts
33354
- var import_node_fs59 = require("node:fs");
33355
- var import_node_path45 = require("node:path");
33737
+ var import_node_fs61 = require("node:fs");
33738
+ var import_node_path48 = require("node:path");
33356
33739
 
33357
- // src/lib/terminal-text.ts
33358
- var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
33359
- function terminalText(value, max = 4e3) {
33360
- if (typeof value !== "string") return "";
33361
- const clean2 = value.replace(CONTROL, "");
33362
- return clean2.length > max ? `${clean2.slice(0, max - 1)}\u2026` : clean2;
33740
+ // src/lib/vendored.ts
33741
+ var import_node_fs57 = require("node:fs");
33742
+ var import_node_path43 = require("node:path");
33743
+ var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
33744
+ function dataDirOrNull() {
33745
+ try {
33746
+ return resolveDataDir();
33747
+ } catch {
33748
+ return null;
33749
+ }
33363
33750
  }
33364
- function terminalUrl(value) {
33365
- const clean2 = terminalText(value, 2e3);
33366
- return /^https?:\/\/\S+$/.test(clean2) ? clean2 : "";
33751
+ function shippedSkillFile(path, dataDir = dataDirOrNull()) {
33752
+ const m = path.replace(/\\/g, "/").match(INSTALLED_SKILL);
33753
+ if (!m || !dataDir) return null;
33754
+ const [, skill, rel] = m;
33755
+ if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
33756
+ try {
33757
+ return (0, import_node_fs57.readFileSync)((0, import_node_path43.join)(dataDir, "skills", skill, rel), "utf8");
33758
+ } catch {
33759
+ return null;
33760
+ }
33761
+ }
33762
+ function partitionVendored(files, read2, dataDir = dataDirOrNull()) {
33763
+ const review = [];
33764
+ const vendored = [];
33765
+ for (const f of files) {
33766
+ const shipped = shippedSkillFile(f, dataDir);
33767
+ if (shipped !== null && read2(f) === shipped) vendored.push(f);
33768
+ else review.push(f);
33769
+ }
33770
+ return { review, vendored };
33367
33771
  }
33368
33772
 
33369
33773
  // src/lib/agent-driver.ts
@@ -33445,7 +33849,7 @@ async function runAgentReview(options) {
33445
33849
  }
33446
33850
  if (!settled) {
33447
33851
  const wait = Math.max(0, remaining() - FINISH_TIMEOUT_MS);
33448
- await Promise.race([oneShotDone, new Promise((resolve8) => setTimeout(resolve8, wait))]);
33852
+ await Promise.race([oneShotDone, new Promise((resolve9) => setTimeout(resolve9, wait))]);
33449
33853
  }
33450
33854
  const finished = await options.http.post(
33451
33855
  "/agent-review/finish",
@@ -33460,8 +33864,8 @@ async function runAgentReview(options) {
33460
33864
  }
33461
33865
 
33462
33866
  // src/lib/prove/auto.ts
33463
- var import_node_path44 = require("node:path");
33464
- var import_node_crypto18 = require("node:crypto");
33867
+ var import_node_path47 = require("node:path");
33868
+ var import_node_crypto19 = require("node:crypto");
33465
33869
 
33466
33870
  // src/lib/prove/signals.ts
33467
33871
  var DEFAULT_SINCE = "180 days ago";
@@ -33869,6 +34273,11 @@ async function rankViaServer(candidates2, ctx, auth2) {
33869
34273
  cmd: "prove-rank"
33870
34274
  });
33871
34275
  if (!res.ok) return { ok: false, ranker: "luna", error: res.error, ranked: fallback };
34276
+ const off = res.data;
34277
+ if (off?.enabled === false) {
34278
+ const why = typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled";
34279
+ return { ok: false, ranker: "luna", error: `formal is off for this project (${why})`, ranked: fallback, disabled: why };
34280
+ }
33872
34281
  const items = Array.isArray(res.data?.items) ? res.data.items : [];
33873
34282
  return { ok: true, ranker: "luna", ranked: applyAnnotations(candidates2, items), costUsd: typeof res.data?.cost_usd === "number" ? res.data.cost_usd : null };
33874
34283
  }
@@ -34593,6 +35002,8 @@ async function generateModel(target, opts) {
34593
35002
  });
34594
35003
  if (!res.ok) return { ok: false, error: res.error };
34595
35004
  const d = res.data ?? {};
35005
+ const off = d;
35006
+ if (off.enabled === false) return { ok: false, error: `formal is off for this project (${typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled"})` };
34596
35007
  if (d.error && typeof d.error === "object") return { ok: false, error: `${d.error.code ?? "SERVICE_ERROR"}: ${d.error.message ?? "the service failed"}` };
34597
35008
  const usage2 = d.usage && typeof d.usage === "object" ? { inputTokens: Number(d.usage.inputTokens ?? 0), outputTokens: Number(d.usage.outputTokens ?? 0) } : null;
34598
35009
  return acceptAnswer(d, usage2, typeof d.cost_usd === "number" ? d.cost_usd : null);
@@ -34772,8 +35183,7 @@ Rules:
34772
35183
  5. Write the harness as ONE file and run it in the SAME shell call that writes it (a heredoc followed by the run). TypeScript: node --experimental-strip-types harness.ts (detect runtimes only if that fails: node --version, python3 --version); if strip-types is unavailable, remove type annotations ONLY on lines that are not part of the function under test's logic, and say so. Python: python3 harness.py.
34773
35184
  6. Nothing you run can reach the network. Do not try.
34774
35185
  7. Keep it under about eight shell calls. Output tokens are time.
34775
- 8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters), impact (one word, below).
34776
- 9. impact \u2014 AFTER the verdict, and never a reason to change it: what the violation you ran costs a user of this code, the most serious one the run showed. money: a balance, charge, refund, price or stock is wrong. access: someone gets access they should not have, or an auth check is bypassed. data: a user's records are lost, corrupted or wrongly duplicated. external: an effect outside the system happens twice or never (a charge, an email, a shipment, a webhook). count: a counter, metric or statistic is off. cache: a cached or derived value is stale until it refreshes. internal: the program's own bookkeeping is off, with no effect a user would see. none: the verdict is not reproduced.
35186
+ 8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters).
34777
35187
 
34778
35188
  "reproduced" means the real code, driven by the trace, reached the property violation the model describes. "diverged" means it did not \u2014 the model is wrong about the code, which is a useful answer. "unreplayable" means you could not run the real function faithfully; say why.`;
34779
35189
  var REPLAY_SCHEMA = {
@@ -34791,10 +35201,9 @@ var REPLAY_SCHEMA = {
34791
35201
  required: ["path", "lines"]
34792
35202
  }
34793
35203
  },
34794
- executed_output: { type: "string" },
34795
- impact: { type: "string", enum: ["money", "access", "data", "external", "count", "cache", "internal", "none"] }
35204
+ executed_output: { type: "string" }
34796
35205
  },
34797
- required: ["verdict", "reason", "harness_files", "executed_output", "impact"]
35206
+ required: ["verdict", "reason", "harness_files", "executed_output"]
34798
35207
  };
34799
35208
  function renderBriefInput(brief) {
34800
35209
  const p = brief.property;
@@ -34821,8 +35230,6 @@ function renderBriefInput(brief) {
34821
35230
  }
34822
35231
  return parts2.join("\n");
34823
35232
  }
34824
- var IMPACTS = ["money", "access", "data", "external", "count", "cache", "internal", "none"];
34825
- var isImpact = (v) => typeof v === "string" && IMPACTS.includes(v);
34826
35233
  function stringsIn(value, out2 = [], depth = 0) {
34827
35234
  if (depth > 8) return out2;
34828
35235
  if (typeof value === "string") out2.push(value);
@@ -34864,8 +35271,7 @@ function parseReplayOutput(output) {
34864
35271
  verdict,
34865
35272
  reason: typeof o.reason === "string" ? o.reason.slice(0, 2e3) : "",
34866
35273
  harness_files: Array.isArray(o.harness_files) ? o.harness_files.filter((f) => typeof f.path === "string").map((f) => ({ path: String(f.path).slice(0, 200), lines: Number.isInteger(f.lines) ? f.lines : 0 })) : [],
34867
- executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : "",
34868
- impact: isImpact(o.impact) ? o.impact : "none"
35274
+ executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : ""
34869
35275
  };
34870
35276
  }
34871
35277
  } catch {
@@ -34873,10 +35279,10 @@ function parseReplayOutput(output) {
34873
35279
  }
34874
35280
  return { claim, shellCalls, executedCalls, shellTexts, outputTexts };
34875
35281
  }
34876
- var RESULT_LINE = /REPLAY_RESULT=(reproduced|diverged)\b/;
35282
+ var RESULT_LINE = /REPLAY_RESULT=(reproduced|diverged)\b/g;
34877
35283
  function printedResult(outputTexts) {
34878
35284
  let last = null;
34879
- for (const t of outputTexts) for (const m of t.matchAll(new RegExp(RESULT_LINE.source, "g"))) last = m[1];
35285
+ for (const t of outputTexts) for (const m of t.matchAll(RESULT_LINE)) last = m[1];
34880
35286
  return last;
34881
35287
  }
34882
35288
  var RESULT_MISSING = "the harness never printed REPLAY_RESULT=reproduced on its own stdout \u2014 the verdict was the model's word, not the run's";
@@ -35066,7 +35472,6 @@ async function runReplayInContainer(brief, opts) {
35066
35472
  ...judged,
35067
35473
  executedCalls,
35068
35474
  shellCalls,
35069
- ...judged.verdict === "reproduced" && parsed.claim ? { impact: parsed.claim.impact } : {},
35070
35475
  executedOutput: parsed.claim?.executed_output ?? "",
35071
35476
  harnessFiles: parsed.claim?.harness_files ?? [],
35072
35477
  usage,
@@ -35113,6 +35518,11 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
35113
35518
  return { claimed: null, verdict: "unverified", reason: "", downgrade: res.error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: res.error };
35114
35519
  }
35115
35520
  const d = res.data ?? {};
35521
+ if (d.enabled === false) {
35522
+ const why = d.reason;
35523
+ const msg = `formal is off for this project (${typeof why === "string" ? why.slice(0, 40) : "disabled"})`;
35524
+ return { claimed: null, verdict: "unverified", reason: "", downgrade: msg, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: msg };
35525
+ }
35116
35526
  if (d.error && typeof d.error === "object") {
35117
35527
  const e = d.error;
35118
35528
  const msg = `${e.code ?? "SERVICE_ERROR"}: ${e.message ?? "the service failed"}`;
@@ -35125,7 +35535,6 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
35125
35535
  verdict: verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable" ? verdict : "unverified",
35126
35536
  reason: typeof d.reason === "string" ? d.reason : "",
35127
35537
  downgrade: typeof d.downgrade === "string" ? d.downgrade : null,
35128
- ...isImpact(d.impact) ? { impact: d.impact } : {},
35129
35538
  executedCalls: Number(d.executed_calls ?? 0),
35130
35539
  shellCalls: Number(d.shell_calls ?? 0),
35131
35540
  verbatim: { covered: Number(v.covered ?? 0), total: Number(v.total ?? 0), ratio: Number(v.ratio ?? 0), basis: v.basis === "symbol" || v.basis === "file" ? v.basis : "none" },
@@ -35182,18 +35591,18 @@ function renderReplay(model, property, r) {
35182
35591
  // src/lib/prove/runner.ts
35183
35592
  var import_node_child_process15 = require("node:child_process");
35184
35593
  var import_node_os8 = require("node:os");
35185
- var import_node_fs58 = require("node:fs");
35594
+ var import_node_fs60 = require("node:fs");
35186
35595
  var import_node_os9 = require("node:os");
35187
- var import_node_path43 = require("node:path");
35596
+ var import_node_path46 = require("node:path");
35188
35597
 
35189
35598
  // src/lib/prove/scaffold.ts
35190
- var import_node_fs57 = require("node:fs");
35191
- var import_node_path42 = require("node:path");
35599
+ var import_node_fs59 = require("node:fs");
35600
+ var import_node_path45 = require("node:path");
35192
35601
 
35193
35602
  // src/lib/prove/safe-write.ts
35194
- var import_node_fs56 = require("node:fs");
35195
- var import_node_crypto14 = require("node:crypto");
35196
- var import_node_path41 = require("node:path");
35603
+ var import_node_fs58 = require("node:fs");
35604
+ var import_node_crypto15 = require("node:crypto");
35605
+ var import_node_path44 = require("node:path");
35197
35606
  var SafeWriteError = class extends Error {
35198
35607
  constructor(reason, path) {
35199
35608
  super(`refusing to write ${path}: ${reason}`);
@@ -35202,10 +35611,10 @@ var SafeWriteError = class extends Error {
35202
35611
  this.name = "SafeWriteError";
35203
35612
  }
35204
35613
  };
35205
- var FLAGS3 = import_node_fs56.constants;
35614
+ var FLAGS3 = import_node_fs58.constants;
35206
35615
  var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
35207
35616
  function assertPlainRelative(rel) {
35208
- if (!rel || (0, import_node_path41.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35617
+ if (!rel || (0, import_node_path44.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35209
35618
  for (const part of rel.split(/[\\/]/)) {
35210
35619
  if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
35211
35620
  }
@@ -35214,34 +35623,34 @@ function ensureDirsNoFollow(root, rel) {
35214
35623
  const parts2 = rel.split(/[\\/]/);
35215
35624
  let cur = root;
35216
35625
  for (const part of parts2.slice(0, -1)) {
35217
- cur = (0, import_node_path41.join)(cur, part);
35626
+ cur = (0, import_node_path44.join)(cur, part);
35218
35627
  let st;
35219
35628
  try {
35220
- st = (0, import_node_fs56.lstatSync)(cur);
35629
+ st = (0, import_node_fs58.lstatSync)(cur);
35221
35630
  } catch {
35222
- (0, import_node_fs56.mkdirSync)(cur);
35631
+ (0, import_node_fs58.mkdirSync)(cur);
35223
35632
  continue;
35224
35633
  }
35225
35634
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
35226
35635
  if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
35227
35636
  }
35228
- return (0, import_node_path41.join)(root, rel);
35637
+ return (0, import_node_path44.join)(root, rel);
35229
35638
  }
35230
35639
  function insideRoot(realRoot, realPath) {
35231
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path41.sep) ? realRoot : realRoot + import_node_path41.sep);
35640
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path44.sep) ? realRoot : realRoot + import_node_path44.sep);
35232
35641
  }
35233
35642
  function removeQuietly(path) {
35234
35643
  try {
35235
- (0, import_node_fs56.unlinkSync)(path);
35644
+ (0, import_node_fs58.unlinkSync)(path);
35236
35645
  } catch {
35237
35646
  }
35238
35647
  }
35239
35648
  function writeFileInRootNoFollow(root, rel, content) {
35240
35649
  assertPlainRelative(rel);
35241
35650
  const dest = ensureDirsNoFollow(root, rel);
35242
- const dir = (0, import_node_path41.dirname)(dest);
35651
+ const dir = (0, import_node_path44.dirname)(dest);
35243
35652
  try {
35244
- const st = (0, import_node_fs56.lstatSync)(dest);
35653
+ const st = (0, import_node_fs58.lstatSync)(dest);
35245
35654
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
35246
35655
  if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
35247
35656
  } catch (err2) {
@@ -35249,41 +35658,41 @@ function writeFileInRootNoFollow(root, rel, content) {
35249
35658
  }
35250
35659
  let realRoot;
35251
35660
  try {
35252
- realRoot = (0, import_node_fs56.realpathSync)(root);
35661
+ realRoot = (0, import_node_fs58.realpathSync)(root);
35253
35662
  } catch {
35254
35663
  throw new SafeWriteError("unwritable", root);
35255
35664
  }
35256
- const tmp = (0, import_node_path41.join)(dir, `.${(0, import_node_path41.basename)(dest)}.${(0, import_node_crypto14.randomBytes)(6).toString("hex")}.tmp`);
35665
+ const tmp = (0, import_node_path44.join)(dir, `.${(0, import_node_path44.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35257
35666
  let fd;
35258
35667
  try {
35259
- fd = (0, import_node_fs56.openSync)(tmp, import_node_fs56.constants.O_WRONLY | import_node_fs56.constants.O_CREAT | import_node_fs56.constants.O_EXCL | NOFOLLOW2, 420);
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);
35260
35669
  } catch {
35261
35670
  throw new SafeWriteError("unwritable", tmp);
35262
35671
  }
35263
35672
  try {
35264
- const opened = (0, import_node_fs56.fstatSync)(fd, { bigint: true });
35673
+ const opened = (0, import_node_fs58.fstatSync)(fd, { bigint: true });
35265
35674
  let realTmp;
35266
35675
  try {
35267
- realTmp = (0, import_node_fs56.realpathSync)(tmp);
35676
+ realTmp = (0, import_node_fs58.realpathSync)(tmp);
35268
35677
  } catch {
35269
35678
  throw new SafeWriteError("escaped", tmp);
35270
35679
  }
35271
- const there = (0, import_node_fs56.lstatSync)(realTmp, { bigint: true });
35680
+ const there = (0, import_node_fs58.lstatSync)(realTmp, { bigint: true });
35272
35681
  if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
35273
35682
  throw new SafeWriteError("escaped", tmp);
35274
35683
  }
35275
35684
  const buf = Buffer.from(content, "utf-8");
35276
35685
  let off = 0;
35277
- while (off < buf.length) off += (0, import_node_fs56.writeSync)(fd, buf, off, buf.length - off);
35686
+ while (off < buf.length) off += (0, import_node_fs58.writeSync)(fd, buf, off, buf.length - off);
35278
35687
  } catch (err2) {
35279
- (0, import_node_fs56.closeSync)(fd);
35688
+ (0, import_node_fs58.closeSync)(fd);
35280
35689
  removeQuietly(tmp);
35281
35690
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
35282
35691
  }
35283
- (0, import_node_fs56.closeSync)(fd);
35692
+ (0, import_node_fs58.closeSync)(fd);
35284
35693
  try {
35285
- if (!insideRoot(realRoot, (0, import_node_fs56.realpathSync)(dir)) || (0, import_node_fs56.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35286
- (0, import_node_fs56.renameSync)(tmp, dest);
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);
35287
35696
  } catch (err2) {
35288
35697
  removeQuietly(tmp);
35289
35698
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
@@ -35297,9 +35706,9 @@ function pathHasNoLink(root, rel) {
35297
35706
  }
35298
35707
  let cur = root;
35299
35708
  for (const part of rel.split(/[\\/]/)) {
35300
- cur = cur + import_node_path41.sep + part;
35709
+ cur = cur + import_node_path44.sep + part;
35301
35710
  try {
35302
- if ((0, import_node_fs56.lstatSync)(cur).isSymbolicLink()) return false;
35711
+ if ((0, import_node_fs58.lstatSync)(cur).isSymbolicLink()) return false;
35303
35712
  } catch {
35304
35713
  return true;
35305
35714
  }
@@ -35609,20 +36018,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
35609
36018
  never committed; what reaches the team is the bug report and the fix.
35610
36019
  `;
35611
36020
  function scaffoldProofs(root) {
35612
- const proofsDir = (0, import_node_path42.join)(root, PROOFS_DIR);
36021
+ const proofsDir = (0, import_node_path45.join)(root, PROOFS_DIR);
35613
36022
  const written = [];
35614
36023
  const kept = [];
35615
36024
  for (const stray of ["lakefile.lean"]) {
35616
36025
  const rel = `${PROOFS_DIR}/${stray}`;
35617
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
36026
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
35618
36027
  try {
35619
- (0, import_node_fs57.rmSync)((0, import_node_path42.join)(root, rel), { force: true });
36028
+ (0, import_node_fs59.rmSync)((0, import_node_path45.join)(root, rel), { force: true });
35620
36029
  } catch {
35621
36030
  }
35622
36031
  }
35623
36032
  for (const f of PROOFS_TEMPLATE_FILES) {
35624
36033
  const rel = `${PROOFS_DIR}/${f.path}`;
35625
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
36034
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
35626
36035
  const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
35627
36036
  if (current.ok && current.content === f.content) {
35628
36037
  kept.push(rel);
@@ -35635,8 +36044,8 @@ function scaffoldProofs(root) {
35635
36044
  [`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
35636
36045
  [`${MODELS_DIR}/README.md`, MODELS_README]
35637
36046
  ]) {
35638
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
35639
- if (existsNoFollow((0, import_node_path42.join)(root, rel))) {
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))) {
35640
36049
  kept.push(rel);
35641
36050
  continue;
35642
36051
  }
@@ -35647,7 +36056,7 @@ function scaffoldProofs(root) {
35647
36056
  }
35648
36057
  function existsNoFollow(abs) {
35649
36058
  try {
35650
- (0, import_node_fs57.lstatSync)(abs);
36059
+ (0, import_node_fs59.lstatSync)(abs);
35651
36060
  return true;
35652
36061
  } catch {
35653
36062
  return false;
@@ -35655,7 +36064,7 @@ function existsNoFollow(abs) {
35655
36064
  }
35656
36065
 
35657
36066
  // src/lib/prove/report.ts
35658
- var import_node_crypto15 = require("node:crypto");
36067
+ var import_node_crypto16 = require("node:crypto");
35659
36068
  var IDENT2 = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$/;
35660
36069
  var SHA256 = /^(sha256:)?[0-9a-f]{64}$/;
35661
36070
  var KINDS2 = /* @__PURE__ */ new Set(["structural", "intent"]);
@@ -35803,7 +36212,7 @@ function sha256InRoot(root, file) {
35803
36212
  const opened = openRegularInRoot(root, file);
35804
36213
  if (!opened.ok) return null;
35805
36214
  try {
35806
- return (0, import_node_crypto15.createHash)("sha256").update(readOpened(opened.fd, opened.size)).digest("hex");
36215
+ return (0, import_node_crypto16.createHash)("sha256").update(readOpened(opened.fd, opened.size)).digest("hex");
35807
36216
  } catch {
35808
36217
  return null;
35809
36218
  }
@@ -35905,16 +36314,17 @@ function renderReport(r) {
35905
36314
 
35906
36315
  // src/lib/prove/runner.ts
35907
36316
  function verityLeanHome(env = process.env) {
35908
- return env.VERITY_LEAN_HOME ?? (0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36317
+ return env.VERITY_LEAN_HOME ?? (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
35909
36318
  }
35910
36319
  function findToolchain(env = process.env) {
35911
- const managedBin = (0, import_node_path43.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
35912
- const elanBin = (0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
35913
- const path = [managedBin, elanBin, env.PATH ?? ""].filter(Boolean).join(import_node_path43.delimiter);
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);
35914
36325
  const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
35915
- const elanHas = (0, import_node_fs58.existsSync)((0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
35916
36326
  const exe = process.platform === "win32" ? "lake.exe" : "lake";
35917
- const candidates2 = [(0, import_node_path43.join)(managedBin, exe), ...elanHas ? [(0, import_node_path43.join)(elanBin, exe)] : [], exe];
36327
+ const candidates2 = [(0, import_node_path46.join)(managedBin, exe), ...elanHas ? [(0, import_node_path46.join)(elanBin, exe)] : [], exe];
35918
36328
  for (const candidate of candidates2) {
35919
36329
  try {
35920
36330
  (0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
@@ -35952,7 +36362,7 @@ function run2(tc, cwd, args2, timeoutMs) {
35952
36362
  function runAsync(tc, cwd, args2, timeoutMs) {
35953
36363
  const started = Date.now();
35954
36364
  const MAX = 16 * 1024 * 1024;
35955
- return new Promise((resolve8) => {
36365
+ return new Promise((resolve9) => {
35956
36366
  const posix = (0, import_node_os8.platform)() !== "win32";
35957
36367
  const child = (0, import_node_child_process15.spawn)(tc.lake, args2, { cwd, env: tc.env, stdio: ["ignore", "pipe", "pipe"], detached: posix });
35958
36368
  let stdout = "";
@@ -35980,8 +36390,8 @@ function runAsync(tc, cwd, args2, timeoutMs) {
35980
36390
  if (settled) return;
35981
36391
  settled = true;
35982
36392
  clearTimeout(timer);
35983
- if (ok) resolve8({ ok: true, stdout, stderr: "", durationMs: Date.now() - started, timedOut: false });
35984
- else resolve8({ ok: false, stdout, stderr: stderr || message || "", durationMs: Date.now() - started, timedOut });
36393
+ if (ok) resolve9({ ok: true, stdout, stderr: "", durationMs: Date.now() - started, timedOut: false });
36394
+ else resolve9({ ok: false, stdout, stderr: stderr || message || "", durationMs: Date.now() - started, timedOut });
35985
36395
  };
35986
36396
  child.on("error", (err2) => finish(false, err2.message));
35987
36397
  child.on("close", (code) => finish(code === 0 && !timedOut));
@@ -35993,7 +36403,7 @@ function proofsWorkspaceProblem(root) {
35993
36403
  for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
35994
36404
  let st;
35995
36405
  try {
35996
- st = (0, import_node_fs58.lstatSync)((0, import_node_path43.join)(root, rel));
36406
+ st = (0, import_node_fs60.lstatSync)((0, import_node_path46.join)(root, rel));
35997
36407
  } catch {
35998
36408
  break;
35999
36409
  }
@@ -36013,44 +36423,44 @@ function refused(problem) {
36013
36423
  function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36014
36424
  const problem = proofsWorkspaceProblem(root);
36015
36425
  if (problem) return refused(problem);
36016
- return run2(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36426
+ return run2(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36017
36427
  }
36018
36428
  async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36019
36429
  const problem = proofsWorkspaceProblem(root);
36020
36430
  if (problem) return refused(problem);
36021
- return runAsync(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36431
+ return runAsync(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36022
36432
  }
36023
36433
  function isModelInRoot(modelsAbs, rel) {
36024
- if (!rel.endsWith(".lean") || (0, import_node_path43.isAbsolute)(rel) || rel.startsWith("..")) return false;
36434
+ if (!rel.endsWith(".lean") || (0, import_node_path46.isAbsolute)(rel) || rel.startsWith("..")) return false;
36025
36435
  return statRegularInRoot(modelsAbs, rel).ok;
36026
36436
  }
36027
36437
  function resolveModelFile(root, arg) {
36028
- const modelsAbs = (0, import_node_path43.join)(root, MODELS_DIR);
36029
- const asPath = (0, import_node_path43.relative)(modelsAbs, (0, import_node_path43.isAbsolute)(arg) ? arg : (0, import_node_path43.resolve)(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));
36030
36440
  const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
36031
36441
  for (const rel of candidates2) {
36032
- if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path43.join)(modelsAbs, rel);
36442
+ if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path46.join)(modelsAbs, rel);
36033
36443
  }
36034
36444
  return null;
36035
36445
  }
36036
36446
  function listModelFiles(root) {
36037
- const modelsAbs = (0, import_node_path43.join)(root, MODELS_DIR);
36038
- if (!(0, import_node_fs58.existsSync)(modelsAbs)) return [];
36039
- return (0, import_node_fs58.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path43.join)(modelsAbs, f));
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));
36040
36450
  }
36041
36451
  function trimDiagnostics(text) {
36042
36452
  return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36043
36453
  }
36044
36454
  function checkModel(tc, root, modelFile, opts = {}) {
36045
- const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
36046
- const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
36455
+ const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36456
+ const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36047
36457
  const problem = proofsWorkspaceProblem(root);
36048
36458
  const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36049
36459
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36050
36460
  }
36051
36461
  async function checkModelAsync(tc, root, modelFile, opts = {}) {
36052
- const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
36053
- const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
36462
+ const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36463
+ const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36054
36464
  const problem = proofsWorkspaceProblem(root);
36055
36465
  const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36056
36466
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
@@ -36059,10 +36469,10 @@ function toReport(res, root, modelFile, timeoutMs) {
36059
36469
  const parsed = parseVerityLines(res.stdout);
36060
36470
  const combined = `${res.stdout}
36061
36471
  ${res.stderr}`;
36062
- const name2 = parsed.header?.model ?? (0, import_node_path43.basename)(modelFile, ".lean");
36472
+ const name2 = parsed.header?.model ?? (0, import_node_path46.basename)(modelFile, ".lean");
36063
36473
  const report = {
36064
36474
  model: name2,
36065
- file: (0, import_node_path43.relative)(root, modelFile),
36475
+ file: (0, import_node_path46.relative)(root, modelFile),
36066
36476
  ok: res.ok,
36067
36477
  header: parsed.header,
36068
36478
  properties: parsed.properties,
@@ -36107,33 +36517,18 @@ function writeResult(root, report) {
36107
36517
  function isCrashTrace(trace) {
36108
36518
  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));
36109
36519
  }
36110
- var SEVERITY_BY_IMPACT = {
36111
- money: "high",
36112
- access: "high",
36113
- data: "high",
36114
- external: "high",
36115
- count: "medium",
36116
- cache: "medium",
36117
- internal: "medium",
36118
- // A reproduced finding always has a real code; 'none' here is a malformed answer, so it blocks.
36119
- none: "high"
36120
- };
36121
- function formalSeverity(f) {
36122
- return f.impact && SEVERITY_BY_IMPACT[f.impact] || "high";
36123
- }
36124
36520
  function mergeFormalFindings(response, outcome, pushedFiles) {
36125
- if (!outcome) return { blocking: 0, warning: 0 };
36521
+ if (!outcome) return { blocking: 0 };
36126
36522
  const norm2 = (p) => p.replace(/\\/g, "/");
36127
36523
  const pushed = new Set(pushedFiles.map(norm2));
36128
- const reproduced = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
36129
- if (reproduced.length === 0) return { blocking: 0, warning: 0 };
36130
- const blocking = reproduced.filter((f) => formalSeverity(f) === "high");
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 };
36131
36526
  const existing = Array.isArray(response.findings) ? response.findings : [];
36132
36527
  response.findings = [
36133
36528
  ...existing,
36134
- ...reproduced.map((f) => ({
36529
+ ...blocking.map((f) => ({
36135
36530
  pattern_id: "formal-counterexample",
36136
- severity: formalSeverity(f),
36531
+ severity: "high",
36137
36532
  scope: "change",
36138
36533
  file: f.file,
36139
36534
  line: outcome.target?.lines?.from ?? null,
@@ -36141,19 +36536,18 @@ function mergeFormalFindings(response, outcome, pushedFiles) {
36141
36536
  // as a title it read backwards (e2e, 2026-09-26). A trace that needs a
36142
36537
  // crash between two writes is labelled: reproducing it means injecting
36143
36538
  // the crash, so it is a crash-consistency finding, not a race.
36144
- 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.impact && f.impact !== "none" ? ` (impact: ${f.impact})` : ""}`,
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`,
36145
36540
  description: terminalText(f.reason ?? "", 2e3),
36146
36541
  fix: { description: `Trace: ${terminalText(f.trace.join(" \u2192 ") || "(initial state)", 2e3)}. Replay: ${terminalText(f.reason ?? "reproduced in the container", 2e3)}` },
36147
36542
  source: "formal"
36148
36543
  }))
36149
36544
  ];
36150
- if (blocking.length > 0) response.gate_decision = "FAIL";
36151
- else if (response.gate_decision === "PASS" || response.gate_decision == null) response.gate_decision = "WARN";
36152
- return { blocking: blocking.length, warning: reproduced.length - blocking.length };
36545
+ if (response.gate_decision !== "FAIL") response.gate_decision = "FAIL";
36546
+ return { blocking: blocking.length };
36153
36547
  }
36154
36548
 
36155
36549
  // src/lib/prove/scalpel.ts
36156
- var import_node_crypto16 = require("node:crypto");
36550
+ var import_node_crypto17 = require("node:crypto");
36157
36551
  var ARITHMETIC = /Math\.(?:round|floor|ceil|trunc)\(|\bround\(|\bdivmod\(|[\w)\]]\s*(?:\*|\/(?!\/)|%)\s*[\w(]/;
36158
36552
  function functionHazard(numbered2) {
36159
36553
  const sites = effectSites(numbered2);
@@ -36183,7 +36577,7 @@ function semanticFingerprint(numbered2) {
36183
36577
  if (LOG_LINE.test(t)) continue;
36184
36578
  kept.push(t.replace(/\s+/g, " "));
36185
36579
  }
36186
- return (0, import_node_crypto16.createHash)("sha256").update(kept.join("\n")).digest("hex");
36580
+ return (0, import_node_crypto17.createHash)("sha256").update(kept.join("\n")).digest("hex");
36187
36581
  }
36188
36582
  function readVerified(root, now = Date.now()) {
36189
36583
  const read2 = readRegularFileInRoot(root, VERIFIED_FILE, 256 * 1024);
@@ -36206,9 +36600,9 @@ function recordVerified(root, rec, now = Date.now()) {
36206
36600
  }
36207
36601
 
36208
36602
  // src/lib/prove/context.ts
36209
- var import_node_crypto17 = require("node:crypto");
36603
+ var import_node_crypto18 = require("node:crypto");
36210
36604
  var CONTEXT_BUDGET_MS = 2e3;
36211
- var sha256 = (s) => (0, import_node_crypto17.createHash)("sha256").update(s).digest("hex");
36605
+ var sha256 = (s) => (0, import_node_crypto18.createHash)("sha256").update(s).digest("hex");
36212
36606
  var TEST_PATH4 = /(^|\/)(tests?|__tests__|spec)\/|\.(test|spec)\.[a-z]+$/;
36213
36607
  function slice(content, f, maxLines) {
36214
36608
  const all = content.split("\n");
@@ -36397,7 +36791,7 @@ function workingTreeReader(root) {
36397
36791
  };
36398
36792
  }
36399
36793
  function sha256Of(content) {
36400
- return (0, import_node_crypto18.createHash)("sha256").update(content).digest("hex");
36794
+ return (0, import_node_crypto19.createHash)("sha256").update(content).digest("hex");
36401
36795
  }
36402
36796
  function defaultDeps(opts) {
36403
36797
  const env = opts.env ?? process.env;
@@ -36468,9 +36862,7 @@ async function runFormalPhase(input) {
36468
36862
  symbol: f.symbol,
36469
36863
  verdict: "reproduced",
36470
36864
  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)`,
36471
- ...f.waived ? { waived: true } : {},
36472
- // A hand-edited file cannot invent a code: unknown values read as absent (HIGH).
36473
- ...isImpact(f.impact) ? { impact: f.impact } : {}
36865
+ ...f.waived ? { waived: true } : {}
36474
36866
  });
36475
36867
  }
36476
36868
  }
@@ -36509,6 +36901,7 @@ async function runFormalPhase(input) {
36509
36901
  return done({ status: "skipped", skip: "not-eligible", detail: `${best.file}: ${isEligible(best, largePush).why}` });
36510
36902
  }
36511
36903
  const ranked = await deps.rank(eligible, root, input.changedLines);
36904
+ if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
36512
36905
  if (ranked.ok) spend(ranked);
36513
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)) }));
36514
36907
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
@@ -36649,7 +37042,7 @@ async function runFormalPhase(input) {
36649
37042
  modelName = gen.name;
36650
37043
  const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
36651
37044
  writeFileInRootNoFollow(root, rel, gen.source);
36652
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
37045
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
36653
37046
  progress.model = { name: gen.name, file: rel, rounds: round };
36654
37047
  progress.step = "check";
36655
37048
  report = await deps.check(root, abs);
@@ -36710,11 +37103,11 @@ async function runFormalPhase(input) {
36710
37103
  const budget = Math.max(2e4, timeLeft() - 5e3);
36711
37104
  const byId = /* @__PURE__ */ new Map();
36712
37105
  let stoppedEarly = false;
36713
- await new Promise((resolve8) => {
37106
+ await new Promise((resolve9) => {
36714
37107
  let left = toReplay.length;
36715
- if (left === 0) return resolve8();
37108
+ if (left === 0) return resolve9();
36716
37109
  const settle = () => {
36717
- if (--left === 0) resolve8();
37110
+ if (--left === 0) resolve9();
36718
37111
  };
36719
37112
  for (const p of toReplay) {
36720
37113
  void (async () => {
@@ -36727,7 +37120,7 @@ async function runFormalPhase(input) {
36727
37120
  if (!stoppedEarly) byId.set(p.id, r);
36728
37121
  if (r.verdict === "reproduced" && !stoppedEarly && !isCrash(p)) {
36729
37122
  stoppedEarly = true;
36730
- resolve8();
37123
+ resolve9();
36731
37124
  }
36732
37125
  })().catch(() => {
36733
37126
  byId.set(p.id, null);
@@ -36743,7 +37136,7 @@ async function runFormalPhase(input) {
36743
37136
  continue;
36744
37137
  }
36745
37138
  const verdict = r.verdict === "reproduced" ? "reproduced" : r.verdict === "diverged" ? "diverged" : r.verdict === "unreplayable" ? "model-only" : "unverified";
36746
- findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0, ...verdict === "reproduced" && r.impact ? { impact: r.impact } : {} });
37139
+ findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0 });
36747
37140
  }
36748
37141
  const reproduced = findings.filter((f) => f.verdict === "reproduced");
36749
37142
  if (reproduced.length > 0 && !cancelled()) {
@@ -36751,7 +37144,7 @@ async function runFormalPhase(input) {
36751
37144
  const others = readPersistedFindings(root).filter((f) => f.file !== top.file);
36752
37145
  writePersistedFindings(root, [
36753
37146
  ...others,
36754
- ...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, ...f.impact ? { impact: f.impact } : {}, ...lines ? { lines } : {}, at: now }))
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 }))
36755
37148
  ]);
36756
37149
  }
36757
37150
  const clean2 = findings.every((f) => f.verdict === "diverged");
@@ -36771,7 +37164,7 @@ async function runFormalPhase(input) {
36771
37164
  return done({
36772
37165
  status: "checked",
36773
37166
  target,
36774
- model: { name: modelName, file: (0, import_node_path44.relative)(root, (0, import_node_path44.join)(root, modelFile)), rounds },
37167
+ model: { name: modelName, file: (0, import_node_path47.relative)(root, (0, import_node_path47.join)(root, modelFile)), rounds },
36775
37168
  properties: report.properties,
36776
37169
  findings
36777
37170
  });
@@ -36834,7 +37227,7 @@ async function generateAndCheck(root, req, opts) {
36834
37227
  }
36835
37228
  const rel = `${dir}/${gen.name}.lean`;
36836
37229
  writeFileInRootNoFollow(root, rel, gen.source);
36837
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
37230
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
36838
37231
  const report = await opts.deps.check(root, abs);
36839
37232
  const abstracts = report.header?.abstracts ?? [];
36840
37233
  const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
@@ -36922,10 +37315,10 @@ function runFormalPhaseWithin(input) {
36922
37315
  if (left <= 0) return Promise.resolve(skippedOutcome("deadline", "no time left"));
36923
37316
  const progress = input.progress ?? {};
36924
37317
  let timer = null;
36925
- const cutoff = new Promise((resolve8) => {
37318
+ const cutoff = new Promise((resolve9) => {
36926
37319
  timer = setTimeout(() => {
36927
37320
  progress.cancelled = true;
36928
- resolve8(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
37321
+ resolve9(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
36929
37322
  }, left);
36930
37323
  });
36931
37324
  return Promise.race([runFormalPhase({ ...input, progress }), cutoff]).finally(() => {
@@ -36962,13 +37355,14 @@ function describeFormalOutcome(o) {
36962
37355
  var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
36963
37356
  var WRITERS_BUDGET_MS = 1500;
36964
37357
  var EXCERPT_MAX_LINES2 = 30;
37358
+ var VENDORED_READ_MAX_BYTES = 256 * 1024;
36965
37359
  var GUARD_BLOCK_CAP = 2;
36966
- var GUARD_ITER_FILE = (0, import_node_path45.join)(VERITY_DIR, ".guard-iteration");
37360
+ var GUARD_ITER_FILE = (0, import_node_path48.join)(VERITY_DIR, ".guard-iteration");
36967
37361
  function readPreToolUseStdin() {
36968
37362
  const empty = { command: "", cwd: null, sessionId: null };
36969
- return new Promise((resolve8) => {
37363
+ return new Promise((resolve9) => {
36970
37364
  try {
36971
- if (process.stdin.isTTY) return resolve8(empty);
37365
+ if (process.stdin.isTTY) return resolve9(empty);
36972
37366
  const chunks = [];
36973
37367
  let timer;
36974
37368
  let settled = false;
@@ -36981,7 +37375,7 @@ function readPreToolUseStdin() {
36981
37375
  process.stdin.removeListener("end", onEnd);
36982
37376
  process.stdin.removeListener("error", onError);
36983
37377
  process.stdin.pause();
36984
- resolve8(value);
37378
+ resolve9(value);
36985
37379
  };
36986
37380
  const onEnd = () => {
36987
37381
  try {
@@ -37002,13 +37396,13 @@ function readPreToolUseStdin() {
37002
37396
  process.stdin.on("error", onError);
37003
37397
  process.stdin.resume();
37004
37398
  } catch {
37005
- resolve8(empty);
37399
+ resolve9(empty);
37006
37400
  }
37007
37401
  });
37008
37402
  }
37009
37403
  function readIterMap() {
37010
37404
  try {
37011
- const raw = JSON.parse((0, import_node_fs59.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37405
+ const raw = JSON.parse((0, import_node_fs61.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37012
37406
  if (raw && typeof raw === "object") {
37013
37407
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
37014
37408
  return { [raw.moment]: raw.count };
@@ -37028,10 +37422,10 @@ function readIter(moment) {
37028
37422
  }
37029
37423
  function writeIter(moment, count) {
37030
37424
  try {
37031
- (0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
37425
+ (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37032
37426
  const map = readIterMap();
37033
37427
  map[moment] = count;
37034
- (0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37428
+ (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37035
37429
  } catch {
37036
37430
  }
37037
37431
  }
@@ -37041,10 +37435,10 @@ function resetIter(moment) {
37041
37435
  if (!(moment in map)) return;
37042
37436
  delete map[moment];
37043
37437
  if (Object.keys(map).length === 0) {
37044
- if ((0, import_node_fs59.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs59.unlinkSync)(GUARD_ITER_FILE);
37438
+ if ((0, import_node_fs61.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs61.unlinkSync)(GUARD_ITER_FILE);
37045
37439
  } else {
37046
- (0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
37047
- (0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37440
+ (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37441
+ (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37048
37442
  }
37049
37443
  } catch {
37050
37444
  }
@@ -37114,7 +37508,7 @@ function hasBlockingFinding(response, sentFiles) {
37114
37508
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
37115
37509
  const analyzable = filterAnalyzable(files);
37116
37510
  const securityFiles = filterSecurity(files);
37117
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs59.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
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);
37118
37512
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
37119
37513
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
37120
37514
  const requestBody = {
@@ -37351,7 +37745,15 @@ async function runGuard(opts, globals) {
37351
37745
  `Verity ${moment}: this command stages files as it runs and the resulting set could not be resolved (${range.refusal}); the ${verb} was allowed WITHOUT a Verity review. Stage first (\`git add \u2026\`) and re-run the ${verb} to have it reviewed.`
37352
37746
  );
37353
37747
  }
37354
- const files = rangeFiles(frame, range);
37748
+ const committed = revisionSource(
37749
+ frame.worktreeRoot ?? process.cwd(),
37750
+ range.kind === "push" && range.head !== "INDEX" ? range.head : null
37751
+ );
37752
+ const { review: files, vendored } = partitionVendored(rangeFiles(frame, range), (p) => {
37753
+ const read2 = committed.read(p, VENDORED_READ_MAX_BYTES);
37754
+ return read2.ok ? read2.content : null;
37755
+ });
37756
+ if (vendored.length > 0) logEvent("guard_vendored", { moment, n: vendored.length, paths: vendored.slice(0, 20) });
37355
37757
  if (files.length === 0) process.exit(0);
37356
37758
  const tokenResult = await resolveToken(globals.token);
37357
37759
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
@@ -37491,8 +37893,6 @@ async function runGuard(opts, globals) {
37491
37893
  rounds: formalOutcome.model?.rounds ?? null,
37492
37894
  properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
37493
37895
  findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
37494
- // Decision 82: the replay's impact code per reproduced finding; count/cache/internal warn, the rest block.
37495
- impacts: formalOutcome.findings.filter((f) => f.impact).map((f) => `${f.property}:${f.impact}`),
37496
37896
  // Decision 81: what each property rests on (a rule, or "line"), what was
37497
37897
  // sent back or dropped as ungrounded, and which counterexamples lack their
37498
37898
  // property's trigger (shadow). Ids and rule names only, never code.
@@ -37733,8 +38133,8 @@ function registerIgnoreCommand(program2) {
37733
38133
  }
37734
38134
 
37735
38135
  // src/commands/waive.ts
37736
- var import_node_crypto19 = require("node:crypto");
37737
- var import_node_fs60 = require("node:fs");
38136
+ var import_node_crypto20 = require("node:crypto");
38137
+ var import_node_fs62 = require("node:fs");
37738
38138
  function registerWaiveCommand(program2) {
37739
38139
  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) => {
37740
38140
  const globals = program2.opts();
@@ -37763,7 +38163,7 @@ function registerWaiveCommand(program2) {
37763
38163
  if (opts.file) {
37764
38164
  body2.file = opts.file;
37765
38165
  try {
37766
- body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0, import_node_fs60.readFileSync)(opts.file)).digest("hex");
38166
+ body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs62.readFileSync)(opts.file)).digest("hex");
37767
38167
  } catch {
37768
38168
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
37769
38169
  process.exit(1);
@@ -37788,10 +38188,11 @@ function registerWaiveCommand(program2) {
37788
38188
  }
37789
38189
 
37790
38190
  // src/commands/init.ts
37791
- var import_node_fs65 = require("node:fs");
38191
+ var import_node_fs67 = require("node:fs");
37792
38192
  var import_promises20 = require("node:fs/promises");
37793
38193
  var import_yaml6 = __toESM2(require_dist());
37794
- var import_node_path49 = require("node:path");
38194
+ var import_node_path52 = require("node:path");
38195
+ var import_node_os11 = require("node:os");
37795
38196
  var import_node_child_process19 = require("node:child_process");
37796
38197
 
37797
38198
  // src/lib/banner.ts
@@ -37870,7 +38271,7 @@ function printPhase(n, of, title, subtitle) {
37870
38271
  }
37871
38272
 
37872
38273
  // src/commands/doctor.ts
37873
- var import_node_fs61 = require("node:fs");
38274
+ var import_node_fs63 = require("node:fs");
37874
38275
 
37875
38276
  // src/lib/prereqs.ts
37876
38277
  var import_node_child_process16 = require("node:child_process");
@@ -37931,13 +38332,13 @@ function checkAnalysisCli() {
37931
38332
  }
37932
38333
  var INSTALL_TIMEOUT_MS = 12e4;
37933
38334
  function run3(command, args2, opts = {}) {
37934
- return new Promise((resolve8) => {
38335
+ return new Promise((resolve9) => {
37935
38336
  const child = (0, import_node_child_process16.spawn)(command, args2, {
37936
38337
  stdio: opts.inherit ? "inherit" : "pipe",
37937
38338
  timeout: INSTALL_TIMEOUT_MS
37938
38339
  });
37939
- child.on("error", () => resolve8(false));
37940
- child.on("close", (code) => resolve8(code === 0));
38340
+ child.on("error", () => resolve9(false));
38341
+ child.on("close", (code) => resolve9(code === 0));
37941
38342
  });
37942
38343
  }
37943
38344
  async function installAnalysisCli() {
@@ -38078,11 +38479,11 @@ async function buildReport() {
38078
38479
  const hooks = wiring.status;
38079
38480
  const provenance = cliProvenance();
38080
38481
  const telemetry = await checkTelemetry();
38081
- const hasConfig = (0, import_node_fs61.existsSync)(projectPath(CODACY_CONFIG_FILE));
38482
+ const hasConfig = (0, import_node_fs63.existsSync)(projectPath(CODACY_CONFIG_FILE));
38082
38483
  const artifacts = {
38083
- standard: (0, import_node_fs61.existsSync)(projectPath(STANDARD_FILE)),
38484
+ standard: (0, import_node_fs63.existsSync)(projectPath(STANDARD_FILE)),
38084
38485
  analysisConfig: hasConfig,
38085
- verityMd: (0, import_node_fs61.existsSync)(projectPath(VERITY_MD_FILE)),
38486
+ verityMd: (0, import_node_fs63.existsSync)(projectPath(VERITY_MD_FILE)),
38086
38487
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
38087
38488
  };
38088
38489
  const next = [];
@@ -38241,8 +38642,8 @@ function registerDoctorCommand(program2) {
38241
38642
  }
38242
38643
 
38243
38644
  // src/commands/migrate.ts
38244
- var import_node_fs62 = require("node:fs");
38245
- var import_node_path46 = require("node:path");
38645
+ var import_node_fs64 = require("node:fs");
38646
+ var import_node_path49 = require("node:path");
38246
38647
  var import_node_child_process17 = require("node:child_process");
38247
38648
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
38248
38649
  function defaultNpmRemover(pkg) {
@@ -38279,12 +38680,12 @@ async function runMigration(opts = {}) {
38279
38680
  return { actions, migrated: actions.length > 0 };
38280
38681
  }
38281
38682
  function migrateProjectDir(root, actions) {
38282
- const gateDir = (0, import_node_path46.join)(root, ".gate");
38283
- const verityDir = (0, import_node_path46.join)(root, ".verity");
38284
- if ((0, import_node_fs62.existsSync)(gateDir) && !(0, import_node_fs62.existsSync)(verityDir)) {
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)) {
38285
38686
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
38286
38687
  }
38287
- if ((0, import_node_fs62.existsSync)(gateDir) && (0, import_node_fs62.existsSync)(verityDir)) {
38688
+ if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
38288
38689
  return migrateProjectDirCarry(gateDir, verityDir, actions);
38289
38690
  }
38290
38691
  return false;
@@ -38305,13 +38706,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
38305
38706
  }
38306
38707
  }
38307
38708
  if (moved) {
38308
- if ((0, import_node_fs62.existsSync)(gateDir)) {
38709
+ if ((0, import_node_fs64.existsSync)(gateDir)) {
38309
38710
  const carried = carryLegacyContents(gateDir, verityDir);
38310
38711
  if (carried > 0) {
38311
38712
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
38312
38713
  }
38313
38714
  try {
38314
- (0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
38715
+ (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
38315
38716
  } catch {
38316
38717
  }
38317
38718
  }
@@ -38327,18 +38728,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
38327
38728
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
38328
38729
  }
38329
38730
  try {
38330
- (0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
38731
+ (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
38331
38732
  } catch {
38332
38733
  }
38333
38734
  return carried > 0;
38334
38735
  }
38335
38736
  function migrateGlobalCredentials(home, actions) {
38336
38737
  if (!home) return;
38337
- const gateCreds = (0, import_node_path46.join)(home, ".gate", "credentials");
38338
- const verityCreds = (0, import_node_path46.join)(home, ".verity", "credentials");
38339
- if (!(0, import_node_fs62.existsSync)(gateCreds)) return;
38340
- if (!(0, import_node_fs62.existsSync)(verityCreds)) {
38341
- (0, import_node_fs62.mkdirSync)((0, import_node_path46.join)(home, ".verity"), { recursive: true });
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 });
38342
38743
  moveFile(gateCreds, verityCreds);
38343
38744
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
38344
38745
  return;
@@ -38360,8 +38761,8 @@ async function migrateLegacyHooks(root, actions) {
38360
38761
  }
38361
38762
  }
38362
38763
  async function migrateClaudeMd(root, actions) {
38363
- const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
38364
- const hadLegacyBlock = (0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38764
+ const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38765
+ const hadLegacyBlock = (0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38365
38766
  if (!hadLegacyBlock) return;
38366
38767
  try {
38367
38768
  await ensureClaudeMdPointer(root);
@@ -38371,9 +38772,9 @@ async function migrateClaudeMd(root, actions) {
38371
38772
  }
38372
38773
  }
38373
38774
  function migrateStandardFile(root, actions) {
38374
- const gateMd = (0, import_node_path46.join)(root, "GATE.md");
38375
- const verityMd = (0, import_node_path46.join)(root, "VERITY.md");
38376
- if (!(0, import_node_fs62.existsSync)(gateMd) || (0, import_node_fs62.existsSync)(verityMd)) return;
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;
38377
38778
  let moved = false;
38378
38779
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
38379
38780
  try {
@@ -38385,12 +38786,12 @@ function migrateStandardFile(root, actions) {
38385
38786
  if (!moved) moveFile(gateMd, verityMd);
38386
38787
  const content = readFileSyncSafe(verityMd);
38387
38788
  const refreshed = content.split("GATE.md").join("VERITY.md");
38388
- if (refreshed !== content) (0, import_node_fs62.writeFileSync)(verityMd, refreshed);
38789
+ if (refreshed !== content) (0, import_node_fs64.writeFileSync)(verityMd, refreshed);
38389
38790
  actions.push("Renamed GATE.md \u2192 VERITY.md");
38390
38791
  }
38391
38792
  async function migrateTelemetryHeaders(root, actions) {
38392
- const file = (0, import_node_path46.join)(root, ".claude", "settings.local.json");
38393
- if (!(0, import_node_fs62.existsSync)(file)) return;
38793
+ const file = (0, import_node_path49.join)(root, ".claude", "settings.local.json");
38794
+ if (!(0, import_node_fs64.existsSync)(file)) return;
38394
38795
  let settings;
38395
38796
  try {
38396
38797
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -38437,15 +38838,15 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
38437
38838
  toAppend.push(line2.replace(/\r$/, ""));
38438
38839
  }
38439
38840
  if (toAppend.length > 0) {
38440
- const sep5 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
38441
- (0, import_node_fs62.writeFileSync)(verityCreds, verityContent + sep5 + toAppend.join("\n") + "\n");
38841
+ const sep6 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
38842
+ (0, import_node_fs64.writeFileSync)(verityCreds, verityContent + sep6 + toAppend.join("\n") + "\n");
38442
38843
  }
38443
- (0, import_node_fs62.rmSync)(gateCreds, { force: true });
38844
+ (0, import_node_fs64.rmSync)(gateCreds, { force: true });
38444
38845
  return toAppend.length;
38445
38846
  }
38446
38847
  function readFileSyncSafe(path) {
38447
38848
  try {
38448
- return (0, import_node_fs62.readFileSync)(path, "utf-8");
38849
+ return (0, import_node_fs64.readFileSync)(path, "utf-8");
38449
38850
  } catch {
38450
38851
  return "";
38451
38852
  }
@@ -38460,35 +38861,35 @@ function hasStagedChanges(root) {
38460
38861
  }
38461
38862
  function moveDir(from, to) {
38462
38863
  try {
38463
- (0, import_node_fs62.renameSync)(from, to);
38864
+ (0, import_node_fs64.renameSync)(from, to);
38464
38865
  } catch (err2) {
38465
38866
  if (err2.code !== "EXDEV") throw err2;
38466
- (0, import_node_fs62.cpSync)(from, to, { recursive: true });
38467
- (0, import_node_fs62.rmSync)(from, { recursive: true, force: true });
38867
+ (0, import_node_fs64.cpSync)(from, to, { recursive: true });
38868
+ (0, import_node_fs64.rmSync)(from, { recursive: true, force: true });
38468
38869
  }
38469
38870
  }
38470
38871
  function moveFile(from, to) {
38471
38872
  try {
38472
- (0, import_node_fs62.renameSync)(from, to);
38873
+ (0, import_node_fs64.renameSync)(from, to);
38473
38874
  } catch (err2) {
38474
38875
  if (err2.code !== "EXDEV") throw err2;
38475
- (0, import_node_fs62.cpSync)(from, to);
38476
- (0, import_node_fs62.rmSync)(from, { force: true });
38876
+ (0, import_node_fs64.cpSync)(from, to);
38877
+ (0, import_node_fs64.rmSync)(from, { force: true });
38477
38878
  }
38478
38879
  }
38479
38880
  function carryLegacyContents(gateDir, verityDir) {
38480
38881
  let copied = 0;
38481
38882
  const walk2 = (relDir) => {
38482
- const srcDir = (0, import_node_path46.join)(gateDir, relDir);
38483
- for (const entry of (0, import_node_fs62.readdirSync)(srcDir)) {
38484
- const rel = relDir ? (0, import_node_path46.join)(relDir, entry) : entry;
38485
- const src = (0, import_node_path46.join)(gateDir, rel);
38486
- const dest = (0, import_node_path46.join)(verityDir, rel);
38487
- if ((0, import_node_fs62.statSync)(src).isDirectory()) {
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()) {
38488
38889
  walk2(rel);
38489
- } else if (!(0, import_node_fs62.existsSync)(dest)) {
38490
- (0, import_node_fs62.mkdirSync)((0, import_node_path46.dirname)(dest), { recursive: true });
38491
- (0, import_node_fs62.cpSync)(src, dest);
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);
38492
38893
  copied++;
38493
38894
  }
38494
38895
  }
@@ -38497,22 +38898,22 @@ function carryLegacyContents(gateDir, verityDir) {
38497
38898
  return copied;
38498
38899
  }
38499
38900
  async function needsMigration(root = repoRoot()) {
38500
- const gateDir = (0, import_node_path46.join)(root, ".gate");
38501
- const verityDir = (0, import_node_path46.join)(root, ".verity");
38502
- if ((0, import_node_fs62.existsSync)(gateDir) && !(0, import_node_fs62.existsSync)(verityDir)) return true;
38503
- if ((0, import_node_fs62.existsSync)(gateDir) && (0, import_node_fs62.existsSync)(verityDir)) {
38504
- if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(gateDir, "credentials")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(verityDir, "credentials"))) {
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"))) {
38505
38906
  return true;
38506
38907
  }
38507
- if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(gateDir, "memory")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(verityDir, "memory"))) {
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"))) {
38508
38909
  return true;
38509
38910
  }
38510
38911
  }
38511
- const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
38512
- if ((0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38912
+ const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38913
+ if ((0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38513
38914
  return true;
38514
38915
  }
38515
- if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(root, "GATE.md")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(root, "VERITY.md"))) {
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"))) {
38516
38917
  return true;
38517
38918
  }
38518
38919
  if (await hasLegacyHooksAt(root)) return true;
@@ -38641,7 +39042,7 @@ function runSelect(opts) {
38641
39042
  cursor: initialIdx[0] ?? 0,
38642
39043
  chosen: new Set(mode2 === "single" ? [initialIdx[0] ?? 0] : initialIdx)
38643
39044
  };
38644
- return new Promise((resolve8) => {
39045
+ return new Promise((resolve9) => {
38645
39046
  let painted = 0;
38646
39047
  let settled = false;
38647
39048
  const draw = () => {
@@ -38689,7 +39090,7 @@ function runSelect(opts) {
38689
39090
  if (settled) return;
38690
39091
  settled = true;
38691
39092
  restore();
38692
- resolve8(value);
39093
+ resolve9(value);
38693
39094
  };
38694
39095
  readline2.emitKeypressEvents(input);
38695
39096
  input.setRawMode(true);
@@ -38710,9 +39111,9 @@ async function askLine(question, io = {}) {
38710
39111
  output: io.output ?? process.stdout
38711
39112
  });
38712
39113
  try {
38713
- return await new Promise((resolve8) => {
38714
- rl.question(question).then((a) => resolve8(a.trim())).catch(() => resolve8(null));
38715
- rl.once("close", () => setImmediate(() => resolve8(null)));
39114
+ return await new Promise((resolve9) => {
39115
+ rl.question(question).then((a) => resolve9(a.trim())).catch(() => resolve9(null));
39116
+ rl.once("close", () => setImmediate(() => resolve9(null)));
38716
39117
  });
38717
39118
  } finally {
38718
39119
  rl.close();
@@ -38793,15 +39194,31 @@ async function promptMultiSelect(question, choices, fallback) {
38793
39194
  }
38794
39195
 
38795
39196
  // src/lib/prove/lean-install.ts
38796
- var import_node_fs63 = require("node:fs");
38797
- var import_node_crypto20 = require("node:crypto");
39197
+ var import_node_fs65 = require("node:fs");
39198
+ var import_node_crypto21 = require("node:crypto");
38798
39199
  var import_node_child_process18 = require("node:child_process");
38799
39200
  var import_node_os10 = require("node:os");
38800
- var import_node_path47 = require("node:path");
39201
+ var import_node_path50 = require("node:path");
38801
39202
  var import_promises18 = require("node:stream/promises");
38802
39203
  var import_node_stream = require("node:stream");
38803
39204
  var RELEASES = "https://releases.lean-lang.org/lean4";
38804
39205
  var LEAN_DOWNLOAD_SIZE = "\u2248800 MB download, 2.7 GB on disk";
39206
+ var DOWNLOAD_STALL_MS = 6e4;
39207
+ var LEAN_DISK_NEEDED_BYTES = 3.75 * 1024 ** 3;
39208
+ function freeBytes(dir) {
39209
+ let d = dir;
39210
+ for (let i2 = 0; i2 < 64; i2++) {
39211
+ try {
39212
+ const st = (0, import_node_fs65.statfsSync)(d);
39213
+ return Number(st.bavail) * Number(st.bsize);
39214
+ } catch {
39215
+ const up = (0, import_node_path50.join)(d, "..");
39216
+ if (up === d) return null;
39217
+ d = up;
39218
+ }
39219
+ }
39220
+ return null;
39221
+ }
38805
39222
  var LEAN_ASSET_SHA256 = {
38806
39223
  "v4.34.0": {
38807
39224
  "lean-4.34.0-darwin.zip": "75a2a4b8e3d35680e8f51fae5a42c79702f463dd73ee1520fb61e5a9143e336c",
@@ -38815,9 +39232,9 @@ function expectedSha256(asset, version = pinnedVersion()) {
38815
39232
  return LEAN_ASSET_SHA256[version]?.[asset] ?? null;
38816
39233
  }
38817
39234
  function sha256File(path) {
38818
- return new Promise((resolve8, reject) => {
38819
- const hash = (0, import_node_crypto20.createHash)("sha256");
38820
- (0, import_node_fs63.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve8(hash.digest("hex"))).on("error", reject);
39235
+ return new Promise((resolve9, reject) => {
39236
+ 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);
38821
39238
  });
38822
39239
  }
38823
39240
  async function verifyDownload(zip, asset, version = pinnedVersion()) {
@@ -38837,7 +39254,7 @@ function leanAssetName(version = pinnedVersion()) {
38837
39254
  return suffix ? `lean-${v}-${suffix}.zip` : null;
38838
39255
  }
38839
39256
  function pinnedVersionDir(env = process.env) {
38840
- return (0, import_node_path47.join)(verityLeanHome(env), pinnedVersion());
39257
+ return (0, import_node_path50.join)(verityLeanHome(env), pinnedVersion());
38841
39258
  }
38842
39259
  function lakeBinary() {
38843
39260
  return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
@@ -38848,29 +39265,44 @@ function unzip(zip, dest) {
38848
39265
  for (const [cmd, args2] of attempts) {
38849
39266
  try {
38850
39267
  (0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
38851
- if ((0, import_node_fs63.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
39268
+ if ((0, import_node_fs65.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
38852
39269
  errors.push(`${cmd}: produced nothing`);
38853
39270
  } catch (err2) {
38854
39271
  errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
38855
39272
  try {
38856
- for (const e of (0, import_node_fs63.readdirSync)(dest)) (0, import_node_fs63.rmSync)((0, import_node_path47.join)(dest, e), { recursive: true, force: true });
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 });
38857
39274
  } catch {
38858
39275
  }
38859
39276
  }
38860
39277
  }
38861
39278
  return { ok: false, error: errors.join("; ") };
38862
39279
  }
38863
- async function download(url, dest, onProgress) {
38864
- const res = await fetch(url, { redirect: "follow" });
38865
- if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status}`);
38866
- const total = Number(res.headers.get("content-length")) || null;
38867
- let seen = 0;
38868
- const stream = import_node_stream.Readable.fromWeb(res.body);
38869
- stream.on("data", (chunk) => {
38870
- seen += chunk.length;
38871
- onProgress(seen, total);
38872
- });
38873
- await (0, import_promises18.pipeline)(stream, (0, import_node_fs63.createWriteStream)(dest));
39280
+ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
39281
+ const ctrl = new AbortController();
39282
+ let timer;
39283
+ const arm = () => {
39284
+ clearTimeout(timer);
39285
+ timer = setTimeout(() => ctrl.abort(), stallMs);
39286
+ };
39287
+ arm();
39288
+ try {
39289
+ const res = await fetch(url, { redirect: "follow", signal: ctrl.signal });
39290
+ if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status}`);
39291
+ const total = Number(res.headers.get("content-length")) || null;
39292
+ let seen = 0;
39293
+ const stream = import_node_stream.Readable.fromWeb(res.body);
39294
+ stream.on("data", (chunk) => {
39295
+ arm();
39296
+ seen += chunk.length;
39297
+ onProgress(seen, total);
39298
+ });
39299
+ await (0, import_promises18.pipeline)(stream, (0, import_node_fs65.createWriteStream)(dest), { signal: ctrl.signal });
39300
+ } catch (err2) {
39301
+ if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
39302
+ throw err2;
39303
+ } finally {
39304
+ clearTimeout(timer);
39305
+ }
38874
39306
  }
38875
39307
  function inPlaceProgress(label2, write = (s) => process.stderr.write(s)) {
38876
39308
  let active = false;
@@ -38908,10 +39340,16 @@ async function installLean(opts = {}) {
38908
39340
  const dir = pinnedVersionDir(env);
38909
39341
  const url = `${RELEASES}/${pinnedVersion()}/${asset}`;
38910
39342
  const home = verityLeanHome(env);
38911
- const tmp = (0, import_node_path47.join)(home, ".tmp");
38912
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
38913
- (0, import_node_fs63.mkdirSync)(tmp, { recursive: true });
38914
- const zip = (0, import_node_path47.join)(tmp, asset);
39343
+ const free = freeBytes(home);
39344
+ const needed = opts.minFreeBytes ?? LEAN_DISK_NEEDED_BYTES;
39345
+ if (free !== null && free < needed) {
39346
+ const gb = (n) => (n / 1024 ** 3).toFixed(1);
39347
+ return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
39348
+ }
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);
38915
39353
  say(`downloading ${url}`);
38916
39354
  let lastPct = -1;
38917
39355
  try {
@@ -38924,40 +39362,40 @@ async function installLean(opts = {}) {
38924
39362
  }
38925
39363
  });
38926
39364
  } catch (err2) {
38927
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39365
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38928
39366
  return { ok: false, error: err2.message };
38929
39367
  }
38930
39368
  say("verifying checksum");
38931
39369
  const verified = await verifyDownload(zip, asset);
38932
39370
  if (!verified.ok) {
38933
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39371
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38934
39372
  return { ok: false, error: verified.error };
38935
39373
  }
38936
39374
  say("unpacking (this takes a minute)");
38937
- const unpack = (0, import_node_path47.join)(tmp, "unpack");
38938
- (0, import_node_fs63.mkdirSync)(unpack);
39375
+ const unpack = (0, import_node_path50.join)(tmp, "unpack");
39376
+ (0, import_node_fs65.mkdirSync)(unpack);
38939
39377
  const unpacked = unzip(zip, unpack);
38940
39378
  if (!unpacked.ok) {
38941
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39379
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38942
39380
  return { ok: false, error: `unpack failed: ${unpacked.error}` };
38943
39381
  }
38944
- const entries = (0, import_node_fs63.readdirSync)(unpack);
38945
- const top = entries.length === 1 && (0, import_node_fs63.statSync)((0, import_node_path47.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path47.join)(unpack, entries[0]) : unpack;
38946
- if (!(0, import_node_fs63.existsSync)((0, import_node_path47.join)(top, "bin", lakeBinary()))) {
38947
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
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 });
38948
39386
  return { ok: false, error: "the archive did not contain bin/lake" };
38949
39387
  }
38950
- (0, import_node_fs63.rmSync)(dir, { recursive: true, force: true });
38951
- (0, import_node_fs63.mkdirSync)(home, { recursive: true });
38952
- (0, import_node_fs63.renameSync)(top, dir);
38953
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
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 });
38954
39392
  return { ok: true, dir };
38955
39393
  }
38956
39394
 
38957
39395
  // src/lib/remote-config.ts
38958
- var import_node_fs64 = require("node:fs");
39396
+ var import_node_fs66 = require("node:fs");
38959
39397
  var import_promises19 = require("node:fs/promises");
38960
- var import_node_path48 = require("node:path");
39398
+ var import_node_path51 = require("node:path");
38961
39399
  var import_yaml5 = __toESM2(require_dist());
38962
39400
  var IGNORE_RIDER = "verityignore";
38963
39401
  async function fetchRemoteSetup(opts) {
@@ -39002,7 +39440,7 @@ async function adoptRemoteSetup(found, opts) {
39002
39440
  written.push(STANDARD_FILE);
39003
39441
  if (rider !== null) {
39004
39442
  const localIgnore = projectPath(VERITYIGNORE_FILE);
39005
- if (!(0, import_node_fs64.existsSync)(localIgnore)) {
39443
+ if (!(0, import_node_fs66.existsSync)(localIgnore)) {
39006
39444
  await writeOut(VERITYIGNORE_FILE, rider);
39007
39445
  written.push(VERITYIGNORE_FILE);
39008
39446
  } else {
@@ -39035,7 +39473,7 @@ async function adoptRemoteSetup(found, opts) {
39035
39473
  }
39036
39474
  async function writeOut(relative6, body2) {
39037
39475
  const target = projectPath(relative6);
39038
- await (0, import_promises19.mkdir)((0, import_node_path48.dirname)(target), { recursive: true });
39476
+ await (0, import_promises19.mkdir)((0, import_node_path51.dirname)(target), { recursive: true });
39039
39477
  await (0, import_promises19.writeFile)(target, body2);
39040
39478
  }
39041
39479
  function describeRemote(found) {
@@ -39152,15 +39590,15 @@ async function runOptionalAuth(resolution, opts = {}) {
39152
39590
  }
39153
39591
  function resolveDataDir2() {
39154
39592
  const candidates2 = [
39155
- (0, import_node_path49.join)(__dirname, "..", "data"),
39593
+ (0, import_node_path52.join)(__dirname, "..", "data"),
39156
39594
  // installed: node_modules/@codacy/verity-cli/data
39157
- (0, import_node_path49.join)(__dirname, "..", "..", "data"),
39595
+ (0, import_node_path52.join)(__dirname, "..", "..", "data"),
39158
39596
  // edge case: nested resolution
39159
- (0, import_node_path49.join)(process.cwd(), "cli", "data")
39597
+ (0, import_node_path52.join)(process.cwd(), "cli", "data")
39160
39598
  // local dev: running from repo root
39161
39599
  ];
39162
39600
  for (const candidate of candidates2) {
39163
- if ((0, import_node_fs65.existsSync)((0, import_node_path49.join)(candidate, "skills"))) {
39601
+ if ((0, import_node_fs67.existsSync)((0, import_node_path52.join)(candidate, "skills"))) {
39164
39602
  return candidate;
39165
39603
  }
39166
39604
  }
@@ -39176,9 +39614,9 @@ async function skillIsCurrent(src, dest) {
39176
39614
  const list2 = (dir) => {
39177
39615
  const out2 = [];
39178
39616
  const walk2 = (d, prefix) => {
39179
- for (const e of (0, import_node_fs65.readdirSync)(d, { withFileTypes: true })) {
39617
+ for (const e of (0, import_node_fs67.readdirSync)(d, { withFileTypes: true })) {
39180
39618
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
39181
- if (e.isDirectory()) walk2((0, import_node_path49.join)(d, e.name), rel);
39619
+ if (e.isDirectory()) walk2((0, import_node_path52.join)(d, e.name), rel);
39182
39620
  else if (e.isFile()) out2.push(rel);
39183
39621
  }
39184
39622
  };
@@ -39189,8 +39627,8 @@ async function skillIsCurrent(src, dest) {
39189
39627
  const shipped = list2(src);
39190
39628
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
39191
39629
  for (const rel of shipped) {
39192
- const a = await (0, import_promises20.readFile)((0, import_node_path49.join)(src, rel), "utf-8");
39193
- const b = await (0, import_promises20.readFile)((0, import_node_path49.join)(dest, rel), "utf-8");
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");
39194
39632
  if (a !== b) return false;
39195
39633
  }
39196
39634
  return true;
@@ -39216,8 +39654,10 @@ var INTENSITY_CHOICES = [
39216
39654
  { id: "thorough", label: "thorough", hint: "all tools, all rules (~15s)" }
39217
39655
  ];
39218
39656
  var FORMAL_CHOICES = [
39219
- { id: "yes", label: "yes", hint: "a Lean model of the riskiest changed function; blocks only on a REPRODUCED counterexample", recommended: true },
39220
- { id: "no", label: "no", hint: "enable later with: verity config formal push" }
39657
+ { id: "yes", label: "yes", hint: "a Lean model of the riskiest changed function; blocks only on a REPRODUCED counterexample" },
39658
+ // No is the default (review of #255): "yes" downloads ≈800 MB and unpacks
39659
+ // 2.7 GB, and a bare Enter must never do that.
39660
+ { id: "no", label: "no", hint: "enable later with: verity config formal push", recommended: true }
39221
39661
  ];
39222
39662
  var MOMENT_CHOICES = [
39223
39663
  { id: "stop", label: "On stop", hint: "after every agent turn \u2014 fast feedback while you work", recommended: true },
@@ -39391,7 +39831,7 @@ async function synthesizeLocally(opts) {
39391
39831
  async function healStaleAnalysisConfig(globals) {
39392
39832
  const configPath = projectPath(CODACY_CONFIG_FILE);
39393
39833
  const standardPath = projectPath(STANDARD_FILE);
39394
- if (!(0, import_node_fs65.existsSync)(configPath) || !(0, import_node_fs65.existsSync)(standardPath)) return;
39834
+ if (!(0, import_node_fs67.existsSync)(configPath) || !(0, import_node_fs67.existsSync)(standardPath)) return;
39395
39835
  const validation = validatePatternIds();
39396
39836
  if (validation.status !== "invalid") return;
39397
39837
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -39488,17 +39928,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
39488
39928
  async function installSkills(force, step) {
39489
39929
  step("Installing skills");
39490
39930
  const dataDir = resolveDataDir2();
39491
- const skillsSource = (0, import_node_path49.join)(dataDir, "skills");
39931
+ const skillsSource = (0, import_node_path52.join)(dataDir, "skills");
39492
39932
  const skillsDest = ".claude/skills";
39493
39933
  let skillsInstalled = 0;
39494
39934
  for (const skill of SKILLS) {
39495
- const src = (0, import_node_path49.join)(skillsSource, skill);
39496
- const dest = (0, import_node_path49.join)(skillsDest, skill);
39497
- if (!(0, import_node_fs65.existsSync)(src)) {
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)) {
39498
39938
  printWarn(` Skill data not found: ${skill}`);
39499
39939
  continue;
39500
39940
  }
39501
- if ((0, import_node_fs65.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39941
+ if ((0, import_node_fs67.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39502
39942
  skillsInstalled++;
39503
39943
  continue;
39504
39944
  }
@@ -39623,26 +40063,39 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
39623
40063
  printWarn(` Formal verification: off \u2014 ${formalRefusalMessage(cfg.formal_refused)}`);
39624
40064
  return;
39625
40065
  }
39626
- const toolchain = findToolchain();
39627
40066
  if (cfg.formal === "push") {
39628
- if (toolchain) printInfo(" Formal verification at push \u2713");
40067
+ if (findToolchain()) printInfo(" Formal verification at push \u2713");
39629
40068
  else printWarn(" Formal verification is on but Lean is missing \u2014 run: verity lean install");
39630
40069
  return;
39631
40070
  }
40071
+ if (cfg.formal === "off") {
40072
+ printInfo(" Formal verification: off (enable with: verity config formal push)");
40073
+ return;
40074
+ }
39632
40075
  if (defaultsOnly || !interactive()) {
39633
40076
  printInfo(" Formal verification (a model-based bug finder at push): off \u2014 enable with: verity config formal push");
39634
40077
  return;
39635
40078
  }
40079
+ const toolchain = findToolchain();
39636
40080
  console.log("");
39637
40081
  console.log(" Formal verification review \u2014 a model-based bug finder for your riskiest code.");
39638
40082
  console.log(" At push, Verity picks the riskiest changed function, checks a small model of");
39639
40083
  console.log(" it, and replays any counterexample on the real code (its source is sent to");
39640
40084
  console.log(" Verity for that). Only a reproduced bug can block; most pushes get no model.");
39641
- console.log(` Adds /verity-prove <worry> to check any code on demand.${toolchain ? "" : ` Needs to install Lean 4 (${LEAN_DOWNLOAD_SIZE}) on "yes".`}`);
40085
+ console.log(" Adds /verity-prove <worry> to check any code on demand, e.g.");
40086
+ console.log(` ${DIM}/verity-prove can the webhook handler charge twice on a retried event?${NC}`);
40087
+ if (!toolchain) {
40088
+ const dir = pinnedVersionDir();
40089
+ const home = (0, import_node_os11.homedir)();
40090
+ const shown = dir.startsWith(home + import_node_path52.sep) ? `~${dir.slice(home.length)}` : dir;
40091
+ console.log("");
40092
+ console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
40093
+ }
39642
40094
  console.log("");
39643
- const wants = await promptChoice("Formal verification at push?", FORMAL_CHOICES, "yes");
40095
+ const wants = await promptChoice("Formal verification at push?", FORMAL_CHOICES, "no");
39644
40096
  if (wants === "yes" && pluginMode) printInfo(" Plugin: the push check works now; /verity:verity-prove arrives with the plugin's next release.");
39645
40097
  if (wants !== "yes") {
40098
+ writeProjectConfig({ formal: "off" });
39646
40099
  printInfo(" Formal verification: off (enable later with: verity config formal push)");
39647
40100
  return;
39648
40101
  }
@@ -39693,7 +40146,7 @@ function registerInitCommand(program2) {
39693
40146
  const staleMarker = clearStalePluginMarker();
39694
40147
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
39695
40148
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
39696
- const isProject = projectMarkers.some((m) => (0, import_node_fs65.existsSync)(m));
40149
+ const isProject = projectMarkers.some((m) => (0, import_node_fs67.existsSync)(m));
39697
40150
  if (!isProject) {
39698
40151
  printError("No project detected in the current directory.");
39699
40152
  printInfo('Run "verity init" from your project root.');
@@ -39747,7 +40200,7 @@ function registerInitCommand(program2) {
39747
40200
  const claudeInstalled = await checkPrerequisites(step);
39748
40201
  console.log("");
39749
40202
  if (pluginMode) {
39750
- printInfo("Skipping skills \u2014 the Verity plugin provides them, namespaced as /verity:<name>.");
40203
+ step("Skills already installed by the plugin, namespaced as /verity:<name>");
39751
40204
  } else {
39752
40205
  await installSkills(force, step);
39753
40206
  }
@@ -39796,7 +40249,7 @@ function registerInitCommand(program2) {
39796
40249
  untrackMemory: opts.untrackMemory === true,
39797
40250
  untrackState: opts.untrackState === true
39798
40251
  });
39799
- const globalVerityDir = (0, import_node_path49.join)(process.env.HOME ?? "", ".verity");
40252
+ const globalVerityDir = (0, import_node_path52.join)(process.env.HOME ?? "", ".verity");
39800
40253
  await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
39801
40254
  console.log("");
39802
40255
  step("Wiring Claude Code hooks");
@@ -39871,7 +40324,7 @@ function registerInitCommand(program2) {
39871
40324
  }
39872
40325
  step("Your project's Standard");
39873
40326
  let haveStandard = false;
39874
- if ((0, import_node_fs65.existsSync)(projectPath(STANDARD_FILE))) {
40327
+ if ((0, import_node_fs67.existsSync)(projectPath(STANDARD_FILE))) {
39875
40328
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
39876
40329
  haveStandard = true;
39877
40330
  } else {
@@ -39901,7 +40354,7 @@ function registerInitCommand(program2) {
39901
40354
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
39902
40355
  init: {
39903
40356
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
39904
- cli_version: true ? "0.34.0-experimental.dc0010f" : "dev"
40357
+ cli_version: true ? "0.34.0-experimental.e086ee3" : "dev"
39905
40358
  }
39906
40359
  });
39907
40360
  } catch (err2) {
@@ -39951,8 +40404,8 @@ function registerInitCommand(program2) {
39951
40404
  }
39952
40405
 
39953
40406
  // src/commands/uninstall.ts
39954
- var import_node_fs66 = require("node:fs");
39955
- var import_node_path50 = require("node:path");
40407
+ var import_node_fs68 = require("node:fs");
40408
+ var import_node_path53 = require("node:path");
39956
40409
  function registerUninstallCommand(program2) {
39957
40410
  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) => {
39958
40411
  const dryRun = opts.dryRun ?? false;
@@ -39961,11 +40414,11 @@ function registerUninstallCommand(program2) {
39961
40414
  const actions = [];
39962
40415
  const skillsRoot = projectPath(".claude/skills");
39963
40416
  for (const name2 of PROJECT_SKILL_NAMES) {
39964
- const dir = (0, import_node_path50.join)(skillsRoot, name2);
39965
- if ((0, import_node_fs66.existsSync)(dir)) {
40417
+ const dir = (0, import_node_path53.join)(skillsRoot, name2);
40418
+ if ((0, import_node_fs68.existsSync)(dir)) {
39966
40419
  actions.push({
39967
40420
  label: `Remove .claude/skills/${name2}/`,
39968
- apply: () => (0, import_node_fs66.rmSync)(dir, { recursive: true, force: true })
40421
+ apply: () => (0, import_node_fs68.rmSync)(dir, { recursive: true, force: true })
39969
40422
  });
39970
40423
  }
39971
40424
  }
@@ -39979,24 +40432,24 @@ function registerUninstallCommand(program2) {
39979
40432
  });
39980
40433
  }
39981
40434
  const verityDir = projectPath(VERITY_DIR);
39982
- if ((0, import_node_fs66.existsSync)(verityDir)) {
40435
+ if ((0, import_node_fs68.existsSync)(verityDir)) {
39983
40436
  actions.push({
39984
40437
  label: `Remove ${VERITY_DIR}/`,
39985
- apply: () => (0, import_node_fs66.rmSync)(verityDir, { recursive: true, force: true })
40438
+ apply: () => (0, import_node_fs68.rmSync)(verityDir, { recursive: true, force: true })
39986
40439
  });
39987
40440
  }
39988
40441
  if (!keepVerityMd) {
39989
40442
  const verityMd = projectPath(VERITY_MD_FILE);
39990
- if ((0, import_node_fs66.existsSync)(verityMd)) {
40443
+ if ((0, import_node_fs68.existsSync)(verityMd)) {
39991
40444
  actions.push({
39992
40445
  label: `Remove ${VERITY_MD_FILE}`,
39993
- apply: () => (0, import_node_fs66.rmSync)(verityMd, { force: true })
40446
+ apply: () => (0, import_node_fs68.rmSync)(verityMd, { force: true })
39994
40447
  });
39995
40448
  }
39996
40449
  }
39997
40450
  const cleanupEmptyDir = (path) => {
39998
- if ((0, import_node_fs66.existsSync)(path) && (0, import_node_fs66.statSync)(path).isDirectory() && (0, import_node_fs66.readdirSync)(path).length === 0) {
39999
- (0, import_node_fs66.rmdirSync)(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);
40000
40453
  }
40001
40454
  };
40002
40455
  actions.push({
@@ -40007,11 +40460,11 @@ function registerUninstallCommand(program2) {
40007
40460
  }
40008
40461
  });
40009
40462
  const home = process.env.HOME ?? "";
40010
- const globalVerityDir = (0, import_node_path50.join)(home, ".verity");
40011
- if (purgeGlobal && (0, import_node_fs66.existsSync)(globalVerityDir)) {
40463
+ const globalVerityDir = (0, import_node_path53.join)(home, ".verity");
40464
+ if (purgeGlobal && (0, import_node_fs68.existsSync)(globalVerityDir)) {
40012
40465
  actions.push({
40013
40466
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
40014
- apply: () => (0, import_node_fs66.rmSync)(globalVerityDir, { recursive: true, force: true })
40467
+ apply: () => (0, import_node_fs68.rmSync)(globalVerityDir, { recursive: true, force: true })
40015
40468
  });
40016
40469
  }
40017
40470
  if (actions.length === 0) {
@@ -40205,8 +40658,8 @@ function registerTaskCommands(program2) {
40205
40658
  }
40206
40659
 
40207
40660
  // src/commands/reset.ts
40208
- var import_node_fs67 = require("node:fs");
40209
- var import_node_path51 = require("node:path");
40661
+ var import_node_fs69 = require("node:fs");
40662
+ var import_node_path54 = require("node:path");
40210
40663
  function registerResetCommand(program2) {
40211
40664
  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) => {
40212
40665
  const globals = program2.opts();
@@ -40243,11 +40696,11 @@ function registerResetCommand(program2) {
40243
40696
  }
40244
40697
  const cacheDir = projectPath(CACHE_DIR);
40245
40698
  let purged = 0;
40246
- if ((0, import_node_fs67.existsSync)(cacheDir)) {
40247
- for (const entry of (0, import_node_fs67.readdirSync)(cacheDir)) {
40699
+ if ((0, import_node_fs69.existsSync)(cacheDir)) {
40700
+ for (const entry of (0, import_node_fs69.readdirSync)(cacheDir)) {
40248
40701
  if (entry.startsWith("pending-")) {
40249
40702
  try {
40250
- (0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(cacheDir, entry));
40703
+ (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(cacheDir, entry));
40251
40704
  purged++;
40252
40705
  } catch {
40253
40706
  }
@@ -40262,19 +40715,19 @@ function registerResetCommand(program2) {
40262
40715
  projectPath(`${VERITY_DIR}/.last-analysis`)
40263
40716
  ];
40264
40717
  for (const file of filesToClear) {
40265
- if ((0, import_node_fs67.existsSync)(file)) {
40718
+ if ((0, import_node_fs69.existsSync)(file)) {
40266
40719
  try {
40267
- (0, import_node_fs67.writeFileSync)(file, "");
40720
+ (0, import_node_fs69.writeFileSync)(file, "");
40268
40721
  } catch {
40269
40722
  }
40270
40723
  }
40271
40724
  }
40272
40725
  if (opts.all) {
40273
40726
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
40274
- if ((0, import_node_fs67.existsSync)(logsDir)) {
40275
- for (const entry of (0, import_node_fs67.readdirSync)(logsDir)) {
40727
+ if ((0, import_node_fs69.existsSync)(logsDir)) {
40728
+ for (const entry of (0, import_node_fs69.readdirSync)(logsDir)) {
40276
40729
  try {
40277
- (0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(logsDir, entry));
40730
+ (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(logsDir, entry));
40278
40731
  } catch {
40279
40732
  }
40280
40733
  }
@@ -40286,7 +40739,7 @@ function registerResetCommand(program2) {
40286
40739
  }
40287
40740
 
40288
40741
  // src/commands/reflect.ts
40289
- var import_node_fs68 = require("node:fs");
40742
+ var import_node_fs70 = require("node:fs");
40290
40743
 
40291
40744
  // src/lib/reflection-globs.ts
40292
40745
  var MAX_GLOBS = 6;
@@ -40294,7 +40747,7 @@ var PATH_TOKEN = /[A-Za-z0-9_./-]*[A-Za-z0-9_-]\.[A-Za-z0-9]{1,8}(?::\d+(?::\d+)
40294
40747
  function clean(token) {
40295
40748
  return token.replace(/:\d+(?::\d+)?$/, "").replace(/^[`'"(\[]+/, "").replace(/[`'"),\].;!?]+$/, "").replace(/^\.\//, "");
40296
40749
  }
40297
- function resolve6(token, treePaths) {
40750
+ function resolve7(token, treePaths) {
40298
40751
  if (treePaths.includes(token)) return token;
40299
40752
  const suffix = token.startsWith("/") ? token : `/${token}`;
40300
40753
  const matches = treePaths.filter((p) => p.endsWith(suffix));
@@ -40307,7 +40760,7 @@ function deriveFileGlobs(text, treePaths) {
40307
40760
  for (const raw of text.match(PATH_TOKEN) ?? []) {
40308
40761
  const token = clean(raw);
40309
40762
  if (!token) continue;
40310
- const path = resolve6(token, treePaths);
40763
+ const path = resolve7(token, treePaths);
40311
40764
  if (!path || seen.has(path)) continue;
40312
40765
  seen.add(path);
40313
40766
  out2.push(path);
@@ -40324,14 +40777,19 @@ async function writeNodeToDisk(args2) {
40324
40777
  { treePaths: listTrackedFiles(), recordBaseline: false }
40325
40778
  );
40326
40779
  if (written === 0) return false;
40327
- return (0, import_node_fs68.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40780
+ return (0, import_node_fs70.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40328
40781
  } catch {
40329
40782
  return false;
40330
40783
  }
40331
40784
  }
40332
40785
  function registerReflectCommand(program2) {
40333
- program2.command("reflect").description("Capture learnings \u2014 auto-extract or record a reflection").option("--user-input <text>", "The reflection to record (the agent-drafted or user-dictated text)").option("--kind <kind>", "Node kind (decision, gotcha, pattern, security, quality, intent, domain, integration)", "gotcha").option("--task-id <id>", "Task to reflect on (defaults to current task)").option("--confirmed", "The USER authored or confirmed these exact words \u2014 records as human-authored (source: user, confidence 1.0)").option("--file-globs <glob...>", "Files this reflection is about. Without any, the paths cited in the text are used; a reflection matching no file never surfaces in a review").option("--autonomous", "(deprecated, ignored) reflections are always recorded without a confirm step").action(async (opts) => {
40786
+ program2.command("reflect").description("Capture learnings \u2014 auto-extract or record a reflection").option("--user-input <text>", "The reflection to record (the agent-drafted or user-dictated text); - reads it from stdin, so the words never pass through shell quoting").option("--kind <kind>", "Node kind (decision, gotcha, pattern, security, quality, intent, domain, integration)", "gotcha").option("--task-id <id>", "Task to reflect on (defaults to current task)").option("--confirmed", "The USER authored or confirmed these exact words \u2014 records as human-authored (source: user, confidence 1.0)").option("--file-globs <glob...>", "Files this reflection is about. Without any, the paths cited in the text are used; a reflection matching no file never surfaces in a review").option("--autonomous", "(deprecated, ignored) reflections are always recorded without a confirm step").action(async (opts) => {
40334
40787
  const globals = program2.opts();
40788
+ const input = readTextInput(opts.userInput, "--user-input");
40789
+ if (!input.ok) {
40790
+ printError(input.error);
40791
+ process.exit(1);
40792
+ }
40335
40793
  await ensureMemoryDir();
40336
40794
  const tokenResult = await resolveToken(globals.token);
40337
40795
  if (!tokenResult.ok) {
@@ -40392,7 +40850,7 @@ function registerReflectCommand(program2) {
40392
40850
  taskResolution = "none";
40393
40851
  printWarn("No active task found \u2014 saving as an unattached reflection.");
40394
40852
  }
40395
- const userInput = opts.userInput;
40853
+ const userInput = input.text;
40396
40854
  if (userInput) {
40397
40855
  const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
40398
40856
  const kind = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
@@ -40756,9 +41214,9 @@ function registerRunCommand(program2) {
40756
41214
  }
40757
41215
 
40758
41216
  // src/commands/telemetry.ts
40759
- var import_node_fs69 = require("node:fs");
41217
+ var import_node_fs71 = require("node:fs");
40760
41218
  async function recordTelemetryChoice(choice) {
40761
- if (!(0, import_node_fs69.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41219
+ if (!(0, import_node_fs71.existsSync)(projectPath(SETUP_STATE_FILE))) return;
40762
41220
  try {
40763
41221
  if ((await readSetupState())?.telemetry === choice) return;
40764
41222
  await writeSetupState({ telemetry: choice });
@@ -40835,8 +41293,8 @@ function registerTelemetryCommands(program2) {
40835
41293
  }
40836
41294
 
40837
41295
  // src/commands/prove.ts
40838
- var import_node_fs70 = require("node:fs");
40839
- var import_node_path52 = require("node:path");
41296
+ var import_node_fs72 = require("node:fs");
41297
+ var import_node_path55 = require("node:path");
40840
41298
 
40841
41299
  // src/lib/prove/hint-pool.ts
40842
41300
  var STOP2 = /* @__PURE__ */ new Set([
@@ -40963,7 +41421,13 @@ async function proveAuth(program2) {
40963
41421
  }
40964
41422
  function registerProveCommand(program2) {
40965
41423
  const prove = program2.command("prove").description("Formal verification (Lean 4) of small, risky pieces of code \u2014 on demand");
40966
- prove.command("candidates [paths...]").description("Rank code worth a formal model, from git history and risk signals").option("--since <when>", `git --since window (default: "${DEFAULT_SINCE}")`).option("--limit <n>", "Candidates to show", "10").option("--rank <ranker>", "deterministic | luna | jev (luna and jev need an API key)", "deterministic").option("--hint <text>", "What the user wants checked, in their words (biases the rank; implies --rank luna)").option("--json", "Machine-readable output").action(async (paths, opts) => {
41424
+ prove.command("candidates [paths...]").description("Rank code worth a formal model, from git history and risk signals").option("--since <when>", `git --since window (default: "${DEFAULT_SINCE}")`).option("--limit <n>", "Candidates to show", "10").option("--rank <ranker>", "deterministic | luna | jev (luna and jev need an API key)", "deterministic").option("--hint <text>", "What the user wants checked, in their words (biases the rank; implies --rank luna); - reads it from stdin, so the words never pass through shell quoting").option("--json", "Machine-readable output").action(async (paths, opts) => {
41425
+ const hint = readTextInput(opts.hint, "--hint");
41426
+ if (!hint.ok) {
41427
+ printError(hint.error);
41428
+ process.exit(2);
41429
+ }
41430
+ opts.hint = hint.text;
40967
41431
  if (opts.hint && opts.rank === "deterministic") opts.rank = "luna";
40968
41432
  const root = repoRoot();
40969
41433
  const ranker = RANKERS[opts.rank];
@@ -40972,7 +41436,7 @@ function registerProveCommand(program2) {
40972
41436
  process.exit(2);
40973
41437
  }
40974
41438
  const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
40975
- let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path52.relative)(root, (0, import_node_path52.resolve)(p)) || ".") });
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)) || ".") });
40976
41440
  if (opts.hint && paths.length === 0) {
40977
41441
  const hit = hintMatches(root, opts.hint);
40978
41442
  if (hit.files.length > 0) {
@@ -41026,7 +41490,7 @@ function registerProveCommand(program2) {
41026
41490
  });
41027
41491
  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) => {
41028
41492
  const root = repoRoot();
41029
- if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41493
+ if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41030
41494
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41031
41495
  process.exit(2);
41032
41496
  }
@@ -41050,7 +41514,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41050
41514
  const reports = [];
41051
41515
  for (const f of files) {
41052
41516
  const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
41053
- report.file = (0, import_node_path52.relative)(root, f);
41517
+ report.file = (0, import_node_path55.relative)(root, f);
41054
41518
  reports.push(report);
41055
41519
  try {
41056
41520
  writeResult(root, report);
@@ -41088,7 +41552,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41088
41552
  printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
41089
41553
  process.exit(2);
41090
41554
  }
41091
- if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41555
+ if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41092
41556
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41093
41557
  process.exit(2);
41094
41558
  }
@@ -41119,7 +41583,7 @@ ${report.error ?? ""}`);
41119
41583
  printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
41120
41584
  return;
41121
41585
  }
41122
- const modelSource = readRegularFileInRoot(root, (0, import_node_path52.relative)(root, file), 512 * 1024);
41586
+ const modelSource = readRegularFileInRoot(root, (0, import_node_path55.relative)(root, file), 512 * 1024);
41123
41587
  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`);
41124
41588
  const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
41125
41589
  const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
@@ -41139,7 +41603,7 @@ ${report.error ?? ""}`);
41139
41603
  });
41140
41604
  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) => {
41141
41605
  const root = repoRoot();
41142
- let files = paths.map((p) => (0, import_node_path52.relative)(root, (0, import_node_path52.resolve)(p)));
41606
+ let files = paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)));
41143
41607
  if (files.length === 0) {
41144
41608
  const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
41145
41609
  const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
@@ -41168,7 +41632,19 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41168
41632
  }
41169
41633
  process.exit(outcome.findings.some((f) => f.verdict === "reproduced") ? 1 : 0);
41170
41634
  });
41171
- prove.command("generate <target>").description("Have the Verity service write a Lean model of one symbol (file#symbol), lint it, and check it here \u2014 up to 3 rounds").option("--lines <a-b>", "Model a region of the file (1-based, inclusive) instead of a named symbol").option("--hint <text>", "The user's worry, in their words (may become an intent property)").option("--revise <model>", "Revise this existing model after a diverged replay (with --note)").option("--note <text>", "What the replay showed was different (with --revise)").option("--json", "Machine-readable output").action(async (targetArg, opts) => {
41635
+ prove.command("generate <target>").description("Have the Verity service write a Lean model of one symbol (file#symbol), lint it, and check it here \u2014 up to 3 rounds").option("--lines <a-b>", "Model a region of the file (1-based, inclusive) instead of a named symbol").option("--hint <text>", "The user's worry, in their words (may become an intent property); - reads it from stdin").option("--revise <model>", "Revise this existing model after a diverged replay (with --note)").option("--note <text>", "What the replay showed was different (with --revise); - reads it from stdin").option("--json", "Machine-readable output").action(async (targetArg, opts) => {
41636
+ if (opts.hint === "-" && opts.note === "-") {
41637
+ printError("Only one of --hint and --note can read stdin (-).");
41638
+ process.exit(2);
41639
+ }
41640
+ for (const flag of ["hint", "note"]) {
41641
+ const input = readTextInput(opts[flag], `--${flag}`);
41642
+ if (!input.ok) {
41643
+ printError(input.error);
41644
+ process.exit(2);
41645
+ }
41646
+ opts[flag] = input.text;
41647
+ }
41172
41648
  const root = repoRoot();
41173
41649
  const auth2 = await proveAuth(program2);
41174
41650
  if (!auth2 && !(process.env.VERITY_PROVE_DIRECT === "1" && process.env.OPENAI_API_KEY)) {
@@ -41199,9 +41675,9 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41199
41675
  let revise;
41200
41676
  if (opts.revise) {
41201
41677
  const existing = resolveModelFile(root, opts.revise);
41202
- const src = existing ? readRegularFileInRoot(root, (0, import_node_path52.relative)(root, existing), 64 * 1024) : null;
41678
+ const src = existing ? readRegularFileInRoot(root, (0, import_node_path55.relative)(root, existing), 64 * 1024) : null;
41203
41679
  if (!src || !src.ok || !opts.note) {
41204
- printError('--revise needs an existing model under Models/ and --note "<what the replay showed>"');
41680
+ printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
41205
41681
  process.exit(2);
41206
41682
  }
41207
41683
  revise = { source: src.content, note: opts.note };
@@ -41238,8 +41714,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41238
41714
  });
41239
41715
  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) => {
41240
41716
  const root = repoRoot();
41241
- const rel0 = (0, import_node_path52.relative)(root, (0, import_node_path52.isAbsolute)(file) ? file : (0, import_node_path52.join)(root, file)).replace(/\\/g, "/");
41242
- const rel = rel0.startsWith("..") || (0, import_node_path52.isAbsolute)(rel0) ? null : rel0;
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;
41243
41719
  if (!rel) {
41244
41720
  printError(`${file} is not inside this repository`);
41245
41721
  process.exit(2);
@@ -41255,8 +41731,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41255
41731
  });
41256
41732
  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) => {
41257
41733
  const root = repoRoot();
41258
- const rel = (0, import_node_path52.relative)(root, (0, import_node_path52.isAbsolute)(file) ? file : (0, import_node_path52.join)(root, file));
41259
- const digest = rel.startsWith("..") || (0, import_node_path52.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
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);
41260
41736
  if (!digest) {
41261
41737
  printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
41262
41738
  process.exit(2);
@@ -41290,10 +41766,10 @@ function refreshScaffold(root) {
41290
41766
  }
41291
41767
 
41292
41768
  // src/commands/lean.ts
41293
- var import_node_fs71 = require("node:fs");
41769
+ var import_node_fs73 = require("node:fs");
41294
41770
  var import_node_child_process20 = require("node:child_process");
41295
- var import_node_os11 = require("node:os");
41296
- var import_node_path53 = require("node:path");
41771
+ var import_node_os12 = require("node:os");
41772
+ var import_node_path56 = require("node:path");
41297
41773
  function registerLeanCommand(program2) {
41298
41774
  const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
41299
41775
  lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
@@ -41310,7 +41786,7 @@ function registerLeanCommand(program2) {
41310
41786
  const managed = pinnedVersionDir();
41311
41787
  const matches = version ? version.includes(pin) : false;
41312
41788
  if (opts.json) {
41313
- printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs71.existsSync)((0, import_node_path53.join)(managed, "bin")), asset: leanAssetName() });
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() });
41314
41790
  return;
41315
41791
  }
41316
41792
  printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
@@ -41324,11 +41800,11 @@ function registerLeanCommand(program2) {
41324
41800
  lean.command("install").description("Download and unpack the pinned Lean 4 into ~/.verity/lean/<version> (official release, \u2248800 MB, 2.7 GB on disk)").option("--yes", "Do not ask").option("--force", "Reinstall even if present").action(async (opts) => {
41325
41801
  const asset = leanAssetName();
41326
41802
  if (!asset) {
41327
- printError(`no Lean release for ${(0, import_node_os11.platform)()}/${(0, import_node_os11.arch)()}`);
41803
+ printError(`no Lean release for ${(0, import_node_os12.platform)()}/${(0, import_node_os12.arch)()}`);
41328
41804
  process.exit(2);
41329
41805
  }
41330
41806
  const dir = pinnedVersionDir();
41331
- if ((0, import_node_fs71.existsSync)((0, import_node_path53.join)(dir, "bin", "lake")) && !opts.force) {
41807
+ if ((0, import_node_fs73.existsSync)((0, import_node_path56.join)(dir, "bin", "lake")) && !opts.force) {
41332
41808
  printInfo(`already installed at ${dir}`);
41333
41809
  return;
41334
41810
  }
@@ -41364,18 +41840,18 @@ function registerLeanCommand(program2) {
41364
41840
  });
41365
41841
  lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
41366
41842
  const dir = pinnedVersionDir();
41367
- if (!(0, import_node_fs71.existsSync)(dir)) {
41843
+ if (!(0, import_node_fs73.existsSync)(dir)) {
41368
41844
  printInfo("nothing to remove");
41369
41845
  return;
41370
41846
  }
41371
- (0, import_node_fs71.rmSync)(dir, { recursive: true, force: true });
41847
+ (0, import_node_fs73.rmSync)(dir, { recursive: true, force: true });
41372
41848
  printInfo(`removed ${dir}`);
41373
41849
  });
41374
41850
  }
41375
41851
 
41376
41852
  // src/cli.ts
41377
- program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.dc0010f").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) => {
41378
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.dc0010f");
41853
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.e086ee3").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.0-experimental.e086ee3");
41379
41855
  setUserNamedServiceUrl(program.opts().serviceUrl);
41380
41856
  try {
41381
41857
  await foldLegacyLocalCredential();