@codacy/verity-cli 0.34.1 → 0.34.2-experimental.312358d

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: sep6, value } = collItem;
6978
+ const { start: start2, key, sep: sep7, value } = collItem;
6979
6979
  const keyProps = resolveProps.resolveProps(start2, {
6980
6980
  indicator: "explicit-key-ind",
6981
- next: key ?? sep6?.[0],
6981
+ next: key ?? sep7?.[0],
6982
6982
  offset,
6983
6983
  onError,
6984
6984
  parentIndent: bm.indent,
@@ -6992,7 +6992,7 @@ var require_resolve_block_map = __commonJS2({
6992
6992
  else if ("indent" in key && key.indent !== bm.indent)
6993
6993
  onError(offset, "BAD_INDENT", startColMsg);
6994
6994
  }
6995
- if (!keyProps.anchor && !keyProps.tag && !sep6) {
6995
+ if (!keyProps.anchor && !keyProps.tag && !sep7) {
6996
6996
  commentEnd = keyProps.end;
6997
6997
  if (keyProps.comment) {
6998
6998
  if (map.comment)
@@ -7016,7 +7016,7 @@ var require_resolve_block_map = __commonJS2({
7016
7016
  ctx.atKey = false;
7017
7017
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
7018
7018
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
7019
- const valueProps = resolveProps.resolveProps(sep6 ?? [], {
7019
+ const valueProps = resolveProps.resolveProps(sep7 ?? [], {
7020
7020
  indicator: "map-value-ind",
7021
7021
  next: value,
7022
7022
  offset: keyNode.range[2],
@@ -7032,7 +7032,7 @@ var require_resolve_block_map = __commonJS2({
7032
7032
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
7033
7033
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
7034
7034
  }
7035
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep6, null, valueProps, onError);
7035
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep7, null, valueProps, onError);
7036
7036
  if (ctx.schema.compat)
7037
7037
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
7038
7038
  offset = valueNode.range[2];
@@ -7123,7 +7123,7 @@ var require_resolve_end = __commonJS2({
7123
7123
  let comment = "";
7124
7124
  if (end) {
7125
7125
  let hasSpace = false;
7126
- let sep6 = "";
7126
+ let sep7 = "";
7127
7127
  for (const token of end) {
7128
7128
  const { source: source2, type } = token;
7129
7129
  switch (type) {
@@ -7137,13 +7137,13 @@ var require_resolve_end = __commonJS2({
7137
7137
  if (!comment)
7138
7138
  comment = cb;
7139
7139
  else
7140
- comment += sep6 + cb;
7141
- sep6 = "";
7140
+ comment += sep7 + cb;
7141
+ sep7 = "";
7142
7142
  break;
7143
7143
  }
7144
7144
  case "newline":
7145
7145
  if (comment)
7146
- sep6 += source2;
7146
+ sep7 += source2;
7147
7147
  hasSpace = true;
7148
7148
  break;
7149
7149
  default:
@@ -7186,18 +7186,18 @@ var require_resolve_flow_collection = __commonJS2({
7186
7186
  let offset = fc.offset + fc.start.source.length;
7187
7187
  for (let i2 = 0; i2 < fc.items.length; ++i2) {
7188
7188
  const collItem = fc.items[i2];
7189
- const { start: start2, key, sep: sep6, value } = collItem;
7189
+ const { start: start2, key, sep: sep7, value } = collItem;
7190
7190
  const props = resolveProps.resolveProps(start2, {
7191
7191
  flow: fcName,
7192
7192
  indicator: "explicit-key-ind",
7193
- next: key ?? sep6?.[0],
7193
+ next: key ?? sep7?.[0],
7194
7194
  offset,
7195
7195
  onError,
7196
7196
  parentIndent: fc.indent,
7197
7197
  startOnNewline: false
7198
7198
  });
7199
7199
  if (!props.found) {
7200
- if (!props.anchor && !props.tag && !sep6 && !value) {
7200
+ if (!props.anchor && !props.tag && !sep7 && !value) {
7201
7201
  if (i2 === 0 && props.comma)
7202
7202
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
7203
7203
  else if (i2 < fc.items.length - 1)
@@ -7251,8 +7251,8 @@ var require_resolve_flow_collection = __commonJS2({
7251
7251
  }
7252
7252
  }
7253
7253
  }
7254
- if (!isMap && !sep6 && !props.found) {
7255
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep6, null, props, onError);
7254
+ if (!isMap && !sep7 && !props.found) {
7255
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep7, null, props, onError);
7256
7256
  coll.items.push(valueNode);
7257
7257
  offset = valueNode.range[2];
7258
7258
  if (isBlock(value))
@@ -7264,7 +7264,7 @@ var require_resolve_flow_collection = __commonJS2({
7264
7264
  if (isBlock(key))
7265
7265
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
7266
7266
  ctx.atKey = false;
7267
- const valueProps = resolveProps.resolveProps(sep6 ?? [], {
7267
+ const valueProps = resolveProps.resolveProps(sep7 ?? [], {
7268
7268
  flow: fcName,
7269
7269
  indicator: "map-value-ind",
7270
7270
  next: value,
@@ -7275,8 +7275,8 @@ var require_resolve_flow_collection = __commonJS2({
7275
7275
  });
7276
7276
  if (valueProps.found) {
7277
7277
  if (!isMap && !props.found && ctx.options.strict) {
7278
- if (sep6)
7279
- for (const st of sep6) {
7278
+ if (sep7)
7279
+ for (const st of sep7) {
7280
7280
  if (st === valueProps.found)
7281
7281
  break;
7282
7282
  if (st.type === "newline") {
@@ -7293,7 +7293,7 @@ var require_resolve_flow_collection = __commonJS2({
7293
7293
  else
7294
7294
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
7295
7295
  }
7296
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep6, null, valueProps, onError) : null;
7296
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep7, null, valueProps, onError) : null;
7297
7297
  if (valueNode) {
7298
7298
  if (isBlock(value))
7299
7299
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -7473,7 +7473,7 @@ var require_resolve_block_scalar = __commonJS2({
7473
7473
  chompStart = i2 + 1;
7474
7474
  }
7475
7475
  let value = "";
7476
- let sep6 = "";
7476
+ let sep7 = "";
7477
7477
  let prevMoreIndented = false;
7478
7478
  for (let i2 = 0; i2 < contentStart; ++i2)
7479
7479
  value += lines[i2][0].slice(trimIndent) + "\n";
@@ -7490,24 +7490,24 @@ var require_resolve_block_scalar = __commonJS2({
7490
7490
  indent = "";
7491
7491
  }
7492
7492
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
7493
- value += sep6 + indent.slice(trimIndent) + content;
7494
- sep6 = "\n";
7493
+ value += sep7 + indent.slice(trimIndent) + content;
7494
+ sep7 = "\n";
7495
7495
  } else if (indent.length > trimIndent || content[0] === " ") {
7496
- if (sep6 === " ")
7497
- sep6 = "\n";
7498
- else if (!prevMoreIndented && sep6 === "\n")
7499
- sep6 = "\n\n";
7500
- value += sep6 + indent.slice(trimIndent) + content;
7501
- sep6 = "\n";
7496
+ if (sep7 === " ")
7497
+ sep7 = "\n";
7498
+ else if (!prevMoreIndented && sep7 === "\n")
7499
+ sep7 = "\n\n";
7500
+ value += sep7 + indent.slice(trimIndent) + content;
7501
+ sep7 = "\n";
7502
7502
  prevMoreIndented = true;
7503
7503
  } else if (content === "") {
7504
- if (sep6 === "\n")
7504
+ if (sep7 === "\n")
7505
7505
  value += "\n";
7506
7506
  else
7507
- sep6 = "\n";
7507
+ sep7 = "\n";
7508
7508
  } else {
7509
- value += sep6 + content;
7510
- sep6 = " ";
7509
+ value += sep7 + content;
7510
+ sep7 = " ";
7511
7511
  prevMoreIndented = false;
7512
7512
  }
7513
7513
  }
@@ -7689,25 +7689,25 @@ var require_resolve_flow_scalar = __commonJS2({
7689
7689
  if (!match)
7690
7690
  return source2;
7691
7691
  let res = match[1];
7692
- let sep6 = " ";
7692
+ let sep7 = " ";
7693
7693
  let pos = first.lastIndex;
7694
7694
  line2.lastIndex = pos;
7695
7695
  while (match = line2.exec(source2)) {
7696
7696
  if (match[1] === "") {
7697
- if (sep6 === "\n")
7698
- res += sep6;
7697
+ if (sep7 === "\n")
7698
+ res += sep7;
7699
7699
  else
7700
- sep6 = "\n";
7700
+ sep7 = "\n";
7701
7701
  } else {
7702
- res += sep6 + match[1];
7703
- sep6 = " ";
7702
+ res += sep7 + match[1];
7703
+ sep7 = " ";
7704
7704
  }
7705
7705
  pos = line2.lastIndex;
7706
7706
  }
7707
7707
  const last = /[ \t]*(.*)/sy;
7708
7708
  last.lastIndex = pos;
7709
7709
  match = last.exec(source2);
7710
- return res + sep6 + (match?.[1] ?? "");
7710
+ return res + sep7 + (match?.[1] ?? "");
7711
7711
  }
7712
7712
  function doubleQuotedValue(source2, onError) {
7713
7713
  let res = "";
@@ -8514,14 +8514,14 @@ var require_cst_stringify = __commonJS2({
8514
8514
  }
8515
8515
  }
8516
8516
  }
8517
- function stringifyItem({ start: start2, key, sep: sep6, value }) {
8517
+ function stringifyItem({ start: start2, key, sep: sep7, value }) {
8518
8518
  let res = "";
8519
8519
  for (const st of start2)
8520
8520
  res += st.source;
8521
8521
  if (key)
8522
8522
  res += stringifyToken(key);
8523
- if (sep6)
8524
- for (const st of sep6)
8523
+ if (sep7)
8524
+ for (const st of sep7)
8525
8525
  res += st.source;
8526
8526
  if (value)
8527
8527
  res += stringifyToken(value);
@@ -9671,18 +9671,18 @@ var require_parser = __commonJS2({
9671
9671
  if (this.type === "map-value-ind") {
9672
9672
  const prev = getPrevProps(this.peek(2));
9673
9673
  const start2 = getFirstKeyStartProps(prev);
9674
- let sep6;
9674
+ let sep7;
9675
9675
  if (scalar.end) {
9676
- sep6 = scalar.end;
9677
- sep6.push(this.sourceToken);
9676
+ sep7 = scalar.end;
9677
+ sep7.push(this.sourceToken);
9678
9678
  delete scalar.end;
9679
9679
  } else
9680
- sep6 = [this.sourceToken];
9680
+ sep7 = [this.sourceToken];
9681
9681
  const map = {
9682
9682
  type: "block-map",
9683
9683
  offset: scalar.offset,
9684
9684
  indent: scalar.indent,
9685
- items: [{ start: start2, key: scalar, sep: sep6 }]
9685
+ items: [{ start: start2, key: scalar, sep: sep7 }]
9686
9686
  };
9687
9687
  this.onKeyLine = true;
9688
9688
  this.stack[this.stack.length - 1] = map;
@@ -9835,15 +9835,15 @@ var require_parser = __commonJS2({
9835
9835
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
9836
9836
  const start3 = getFirstKeyStartProps(it.start);
9837
9837
  const key = it.key;
9838
- const sep6 = it.sep;
9839
- sep6.push(this.sourceToken);
9838
+ const sep7 = it.sep;
9839
+ sep7.push(this.sourceToken);
9840
9840
  delete it.key;
9841
9841
  delete it.sep;
9842
9842
  this.stack.push({
9843
9843
  type: "block-map",
9844
9844
  offset: this.offset,
9845
9845
  indent: this.indent,
9846
- items: [{ start: start3, key, sep: sep6 }]
9846
+ items: [{ start: start3, key, sep: sep7 }]
9847
9847
  });
9848
9848
  } else if (start2.length > 0) {
9849
9849
  it.sep = it.sep.concat(start2, this.sourceToken);
@@ -10037,13 +10037,13 @@ var require_parser = __commonJS2({
10037
10037
  const prev = getPrevProps(parent);
10038
10038
  const start2 = getFirstKeyStartProps(prev);
10039
10039
  fixFlowSeqItems(fc);
10040
- const sep6 = fc.end.splice(1, fc.end.length);
10041
- sep6.push(this.sourceToken);
10040
+ const sep7 = fc.end.splice(1, fc.end.length);
10041
+ sep7.push(this.sourceToken);
10042
10042
  const map = {
10043
10043
  type: "block-map",
10044
10044
  offset: fc.offset,
10045
10045
  indent: fc.indent,
10046
- items: [{ start: start2, key: fc, sep: sep6 }]
10046
+ items: [{ start: start2, key: fc, sep: sep7 }]
10047
10047
  };
10048
10048
  this.onKeyLine = true;
10049
10049
  this.stack[this.stack.length - 1] = map;
@@ -13782,9 +13782,9 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13782
13782
  PatternStructure: 5
13783
13783
  };
13784
13784
  var QueryError = class _QueryError extends Error {
13785
- constructor(kind, info2, index, length) {
13786
- super(_QueryError.formatMessage(kind, info2));
13787
- this.kind = kind;
13785
+ constructor(kind2, info2, index, length) {
13786
+ super(_QueryError.formatMessage(kind2, info2));
13787
+ this.kind = kind2;
13788
13788
  this.info = info2;
13789
13789
  this.index = index;
13790
13790
  this.length = length;
@@ -13798,8 +13798,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13798
13798
  __name(this, "QueryError");
13799
13799
  }
13800
13800
  /** Formats an error message based on the error kind and info */
13801
- static formatMessage(kind, info2) {
13802
- switch (kind) {
13801
+ static formatMessage(kind2, info2) {
13802
+ switch (kind2) {
13803
13803
  case QueryErrorKind.NodeName:
13804
13804
  return `Bad node name '${info2.word}'`;
13805
13805
  case QueryErrorKind.FieldName:
@@ -14726,7 +14726,7 @@ var SECURITY_PATTERNS = [
14726
14726
  /Dockerfile/
14727
14727
  ];
14728
14728
  var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
14729
- var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
14729
+ var DEFAULT_SERVICE_URL = "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1".length > 0 ? "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1" : PROD_SERVICE_URL;
14730
14730
  var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
14731
14731
  var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
14732
14732
  var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
@@ -15172,8 +15172,8 @@ function filterReviewable(files) {
15172
15172
  const ext = (0, import_node_path4.extname)(f).slice(1);
15173
15173
  if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
15174
15174
  if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
15175
- const basename9 = f.split("/").pop() ?? "";
15176
- if (REVIEWABLE_FILENAMES.has(basename9)) return true;
15175
+ const basename11 = f.split("/").pop() ?? "";
15176
+ if (REVIEWABLE_FILENAMES.has(basename11)) return true;
15177
15177
  if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
15178
15178
  return false;
15179
15179
  });
@@ -16278,8 +16278,8 @@ async function reportLoginOutcome(out2, opts = {}) {
16278
16278
  printWarn(" repository will report that account. Remove its line from ~/.verity/credentials");
16279
16279
  printWarn(" only if you want this repository on the login you just completed.");
16280
16280
  } else {
16281
- const kind = rec.userId != null ? "superseded per-repository" : "anonymous project-specific";
16282
- printWarn(` Note: this repository has a ${kind} credential that takes`);
16281
+ const kind2 = rec.userId != null ? "superseded per-repository" : "anonymous project-specific";
16282
+ printWarn(` Note: this repository has a ${kind2} credential that takes`);
16283
16283
  printWarn(" precedence here. Remove its line from ~/.verity/credentials to use your login.");
16284
16284
  printWarn(' Until then, "verity login" in this repository re-runs the full GitHub flow');
16285
16285
  printWarn(" every time.");
@@ -16287,6 +16287,15 @@ async function reportLoginOutcome(out2, opts = {}) {
16287
16287
  }
16288
16288
  }
16289
16289
 
16290
+ // src/lib/session-env.ts
16291
+ function envSessionId(env = process.env) {
16292
+ for (const name2 of ["CLAUDE_SESSION_ID", "CLAUDE_CODE_SESSION_ID"]) {
16293
+ const value = env[name2];
16294
+ if (value) return value;
16295
+ }
16296
+ return void 0;
16297
+ }
16298
+
16290
16299
  // src/commands/login.ts
16291
16300
  function registerLoginCommand(program2) {
16292
16301
  program2.command("login").description("Log in to Verity (one GitHub login grants access to all your repositories)").option("--force", "Re-authenticate even if already logged in").option("--start", "Show the GitHub code and return at once (finish with --finish); prints JSON").option("--finish", "Wait for approval of the code --start showed, then log in; prints JSON").option("--wait <seconds>", "With --finish: how long to wait for approval before returning", "100").option("--cancel", "Discard a code --start showed that will not be approved").action(async (opts) => {
@@ -16303,7 +16312,7 @@ function registerLoginCommand(program2) {
16303
16312
  return;
16304
16313
  }
16305
16314
  const split = !!(opts.start || opts.finish);
16306
- if (!split && !process.stdin.isTTY && (process.env.CLAUDECODE || process.env.CLAUDE_SESSION_ID)) {
16315
+ if (!split && !process.stdin.isTTY && (process.env.CLAUDECODE || envSessionId())) {
16307
16316
  printWarn("Inside a Claude Code session the code below may not be visible until this command ends.");
16308
16317
  printWarn(' Use "verity login --start", then "verity login --finish" once it is approved.');
16309
16318
  }
@@ -16851,6 +16860,7 @@ var VERITY_SESSION_END_HOOK = {
16851
16860
  command: "verity session end"
16852
16861
  };
16853
16862
  var GUARD_TIMEOUT = 300;
16863
+ var GUARD_TIMEOUT_MS = GUARD_TIMEOUT * 1e3;
16854
16864
  function buildGuardHook(on) {
16855
16865
  return {
16856
16866
  type: "command",
@@ -17606,9 +17616,9 @@ function pointsAtVerity(src) {
17606
17616
  }
17607
17617
  function describeSource(src) {
17608
17618
  if (!src || typeof src !== "object") return "an unrecognised source";
17609
- const kind = typeof src.source === "string" ? src.source : "unknown";
17619
+ const kind2 = typeof src.source === "string" ? src.source : "unknown";
17610
17620
  const target = typeof src.repo === "string" && src.repo || typeof src.url === "string" && src.url || typeof src.path === "string" && src.path || "";
17611
- return target ? `${kind} \u2192 ${target}` : kind;
17621
+ return target ? `${kind2} \u2192 ${target}` : kind2;
17612
17622
  }
17613
17623
  function legacyMarketplaceInstall() {
17614
17624
  const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
@@ -18532,8 +18542,8 @@ function slugify(s) {
18532
18542
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
18533
18543
  }
18534
18544
  function orgNodePath(node) {
18535
- const kind = ORG_KINDS.includes(node.kind) ? node.kind : "domain";
18536
- return `${kind}/${slugify(node.title) || "claim"}-${node.tag_id.replace(/-/g, "").slice(0, 8)}.md`;
18545
+ const kind2 = ORG_KINDS.includes(node.kind) ? node.kind : "domain";
18546
+ return `${kind2}/${slugify(node.title) || "claim"}-${node.tag_id.replace(/-/g, "").slice(0, 8)}.md`;
18537
18547
  }
18538
18548
  function renderOrgNode(node, orgName) {
18539
18549
  const fm = [
@@ -18622,10 +18632,10 @@ function renderIndex(orgName, nodes) {
18622
18632
  ];
18623
18633
  const byKind = /* @__PURE__ */ new Map();
18624
18634
  for (const n of nodes) byKind.set(n.kind, [...byKind.get(n.kind) ?? [], n]);
18625
- for (const kind of ORG_KINDS) {
18626
- const list2 = byKind.get(kind);
18635
+ for (const kind2 of ORG_KINDS) {
18636
+ const list2 = byKind.get(kind2);
18627
18637
  if (!list2?.length) continue;
18628
- lines.push(`## ${kind}/ (${list2.length})`);
18638
+ lines.push(`## ${kind2}/ (${list2.length})`);
18629
18639
  for (const n of list2) lines.push(`- [[${orgNodePath(n).split("/")[1].replace(/\.md$/, "")}]] \u2014 ${n.title} \xB7 ${n.origin}`);
18630
18640
  lines.push("");
18631
18641
  }
@@ -18684,8 +18694,8 @@ async function readOrgMirror(remote = requestRemote()) {
18684
18694
  const dir = orgMirrorDir(remote);
18685
18695
  if (!dir || !(0, import_node_fs14.existsSync)(dir)) return [];
18686
18696
  const out2 = [];
18687
- for (const kind of ORG_KINDS) {
18688
- const kindDir = (0, import_node_path14.join)(dir, kind);
18697
+ for (const kind2 of ORG_KINDS) {
18698
+ const kindDir = (0, import_node_path14.join)(dir, kind2);
18689
18699
  if (!(0, import_node_fs14.existsSync)(kindDir)) continue;
18690
18700
  let files;
18691
18701
  try {
@@ -18953,16 +18963,16 @@ function relevance(node, ctx) {
18953
18963
  return { score, via: { glob: globHit, tag: tagScore, text: textScore } };
18954
18964
  }
18955
18965
  var KIND_POOL_STRENGTH = 20;
18956
- function priorFor(kind, pooled) {
18957
- const base = KIND_PRIOR_MEAN[kind] ?? DEFAULT_PRIOR_MEAN;
18966
+ function priorFor(kind2, pooled) {
18967
+ const base = KIND_PRIOR_MEAN[kind2] ?? DEFAULT_PRIOR_MEAN;
18958
18968
  const a = pooled ? Math.max(0, pooled.alpha) : 0;
18959
18969
  const b = pooled ? Math.max(0, pooled.beta) : 0;
18960
- const mean = pooled && kind !== "integration" ? (KIND_POOL_STRENGTH * base + a) / (KIND_POOL_STRENGTH + a + b) : base;
18970
+ const mean = pooled && kind2 !== "integration" ? (KIND_POOL_STRENGTH * base + a) / (KIND_POOL_STRENGTH + a + b) : base;
18961
18971
  return { alpha: mean * PRIOR_STRENGTH, beta: (1 - mean) * PRIOR_STRENGTH };
18962
18972
  }
18963
- function posteriorFor(kind, own, pooled) {
18964
- const p = priorFor(kind, pooled);
18965
- if (!own || kind === "integration") return p;
18973
+ function posteriorFor(kind2, own, pooled) {
18974
+ const p = priorFor(kind2, pooled);
18975
+ if (!own || kind2 === "integration") return p;
18966
18976
  return { alpha: p.alpha + Math.max(0, own.alpha), beta: p.beta + Math.max(0, own.beta) };
18967
18977
  }
18968
18978
  function posteriorMean(p) {
@@ -19476,8 +19486,8 @@ function ensureVerityGitignore() {
19476
19486
  }
19477
19487
  let text = next.join("\n");
19478
19488
  if (!hasMarker) {
19479
- const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19480
- text = text + sep6 + VERITY_GITIGNORE_BLOCK;
19489
+ const sep7 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19490
+ text = text + sep7 + VERITY_GITIGNORE_BLOCK;
19481
19491
  }
19482
19492
  if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
19483
19493
  return verified(
@@ -19507,8 +19517,8 @@ function writeFencedBlock() {
19507
19517
  lines = fenceMemoryLines(lines);
19508
19518
  let text = lines.join("\n");
19509
19519
  if (!hasMarker) {
19510
- const sep6 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19511
- text = text + sep6 + VERITY_GITIGNORE_BLOCK;
19520
+ const sep7 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19521
+ text = text + sep7 + VERITY_GITIGNORE_BLOCK;
19512
19522
  }
19513
19523
  try {
19514
19524
  (0, import_node_fs19.writeFileSync)(".gitignore", text);
@@ -19558,8 +19568,8 @@ function keepMemoryTracked() {
19558
19568
  }
19559
19569
  if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
19560
19570
  try {
19561
- const sep6 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
19562
- (0, import_node_fs19.writeFileSync)(".gitignore", content + sep6 + MEMORY_OPT_OUT_STANZA);
19571
+ const sep7 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
19572
+ (0, import_node_fs19.writeFileSync)(".gitignore", content + sep7 + MEMORY_OPT_OUT_STANZA);
19563
19573
  } catch {
19564
19574
  return "failed";
19565
19575
  }
@@ -20002,7 +20012,7 @@ async function regenerateIndex() {
20002
20012
  try {
20003
20013
  const content = await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8");
20004
20014
  const title = pickFrontmatter(content, "title") ?? slug;
20005
- const kind = pickFrontmatter(content, "kind") ?? "-";
20015
+ const kind2 = pickFrontmatter(content, "kind") ?? "-";
20006
20016
  const confidence = pickFrontmatter(content, "confidence");
20007
20017
  const globs = pickFrontmatterArray(content, "file_globs");
20008
20018
  const status = pickFrontmatter(content, "status") ?? "active";
@@ -20010,7 +20020,7 @@ async function regenerateIndex() {
20010
20020
  const globPart = globs.length > 0 ? ` \xB7 scope: \`${globs.slice(0, 3).join("`, `")}\`` : "";
20011
20021
  const statusPart = status !== "active" ? ` \xB7 *${status}*` : "";
20012
20022
  lines.push(`- [[${slug}]] \u2014 **${title}**`);
20013
- lines.push(` *${kind}*${confPart}${globPart}${statusPart}`);
20023
+ lines.push(` *${kind2}*${confPart}${globPart}${statusPart}`);
20014
20024
  } catch {
20015
20025
  lines.push(`- [[${slug}]]`);
20016
20026
  }
@@ -22053,8 +22063,8 @@ function toRegister(severity) {
22053
22063
  return "NOTE";
22054
22064
  }
22055
22065
  }
22056
- function recordMark(d, kind, from, to) {
22057
- appendEvent(d, { k: "mark", kind, from: from ?? null, to: to ?? null });
22066
+ function recordMark(d, kind2, from, to) {
22067
+ appendEvent(d, { k: "mark", kind: kind2, from: from ?? null, to: to ?? null });
22058
22068
  }
22059
22069
  function recordCapabilities(d, c, known) {
22060
22070
  const put = (field, value, tier) => {
@@ -22149,13 +22159,13 @@ function registerIntentCommands(program2) {
22149
22159
  if (!prompt) {
22150
22160
  process.exit(0);
22151
22161
  }
22152
- if (deferredToPlugin("intent capture", event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null)) {
22162
+ if (deferredToPlugin("intent capture", event.session_id ?? envSessionId() ?? null)) {
22153
22163
  process.exit(0);
22154
22164
  }
22155
22165
  const isPrimitive = isSlashCommand(prompt);
22156
22166
  const authForScope = await resolveToken(program2.opts().token);
22157
22167
  const scopeToken = authForScope.ok ? authForScope.data.token : void 0;
22158
- const scopeSession = event.session_id || process.env.CLAUDE_SESSION_ID || "";
22168
+ const scopeSession = event.session_id || envSessionId() || "";
22159
22169
  if (!isPrimitive) await appendToConversationBuffer(prompt, sessionScopeKey(scopeToken, scopeSession));
22160
22170
  if (!isPrimitive) {
22161
22171
  try {
@@ -22875,7 +22885,12 @@ function registerLifecycleCommands(program2) {
22875
22885
  }
22876
22886
  if (!verityConfigured()) process.exit(0);
22877
22887
  const event = await readHookStdin();
22878
- const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
22888
+ const resolved = resolveHookSession(opts.sessionId, event, envSessionId());
22889
+ if (!resolved.ok) {
22890
+ logEvent("lifecycle_session_flag_refused", { command: "compact" });
22891
+ process.exit(0);
22892
+ }
22893
+ const sessionId = resolved.sessionId;
22879
22894
  if (deferredToPlugin("compact", sessionId)) process.exit(0);
22880
22895
  const globals = program2.opts();
22881
22896
  const tok = await resolveToken(globals.token);
@@ -22904,9 +22919,14 @@ function registerLifecycleCommands(program2) {
22904
22919
  }
22905
22920
  if (!verityConfigured()) process.exit(0);
22906
22921
  const event = await readHookStdin();
22907
- const sessionId = opts.sessionId ?? event.session_id ?? process.env.CLAUDE_SESSION_ID ?? null;
22922
+ const resolved = resolveHookSession(opts.sessionId, event, envSessionId());
22923
+ if (!resolved.ok) {
22924
+ logEvent("lifecycle_session_flag_refused", { command: "session end" });
22925
+ process.exit(0);
22926
+ }
22927
+ const sessionId = resolved.sessionId;
22908
22928
  if (deferredToPlugin("session end", sessionId)) process.exit(0);
22909
- const reason = opts.reason ?? event.session_end_reason ?? event.reason ?? "other";
22929
+ const reason = hookWord(opts.reason) ?? event.session_end_reason ?? event.reason ?? "other";
22910
22930
  if (reason === "clear") {
22911
22931
  writeCarry(sessionId ?? void 0, getCurrentCommit());
22912
22932
  }
@@ -22990,20 +23010,56 @@ function buildCompactionContext(session) {
22990
23010
  const trimmed = [...lines.slice(0, 5), ...lines.slice(5, 5 + 2)].join("\n");
22991
23011
  return trimmed.length <= MAX_CHARS ? trimmed : null;
22992
23012
  }
23013
+ var MAX_HOOK_EVENT_BYTES = 64 * 1024;
23014
+ var SESSION_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
23015
+ var HOOK_WORD = /^[a-z][a-z_]{0,63}$/;
23016
+ function isHookSessionId(value) {
23017
+ return typeof value === "string" && SESSION_ID.test(value);
23018
+ }
23019
+ function hookWord(value) {
23020
+ return typeof value === "string" && HOOK_WORD.test(value) ? value : void 0;
23021
+ }
23022
+ function resolveHookSession(flag, event, env) {
23023
+ if (flag !== void 0) return isHookSessionId(flag) ? { ok: true, sessionId: flag } : { ok: false };
23024
+ if (event.session_id) return { ok: true, sessionId: event.session_id };
23025
+ return { ok: true, sessionId: isHookSessionId(env) ? env : null };
23026
+ }
23027
+ function parseHookEvent(raw) {
23028
+ let data;
23029
+ try {
23030
+ data = JSON.parse(raw.trim() || "{}");
23031
+ } catch {
23032
+ return {};
23033
+ }
23034
+ if (!data || typeof data !== "object" || Array.isArray(data)) return {};
23035
+ const o = data;
23036
+ const event = {};
23037
+ if (isHookSessionId(o.session_id)) event.session_id = o.session_id;
23038
+ const compaction = hookWord(o.compaction_type);
23039
+ if (compaction) event.compaction_type = compaction;
23040
+ const endReason = hookWord(o.session_end_reason);
23041
+ if (endReason) event.session_end_reason = endReason;
23042
+ const reason = hookWord(o.reason);
23043
+ if (reason) event.reason = reason;
23044
+ return event;
23045
+ }
22993
23046
  async function readHookStdin() {
22994
23047
  try {
22995
23048
  if (process.stdin.isTTY) return {};
22996
23049
  const chunks = [];
23050
+ let size = 0;
22997
23051
  const timeout = new Promise((resolve9) => setTimeout(() => resolve9({}), 500));
22998
23052
  const read2 = new Promise((resolve9) => {
22999
- process.stdin.on("data", (c) => chunks.push(c));
23000
- process.stdin.on("end", () => {
23001
- try {
23002
- resolve9(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
23003
- } catch {
23053
+ process.stdin.on("data", (c) => {
23054
+ size += c.length;
23055
+ if (size > MAX_HOOK_EVENT_BYTES) {
23056
+ process.stdin.destroy();
23004
23057
  resolve9({});
23058
+ return;
23005
23059
  }
23060
+ chunks.push(c);
23006
23061
  });
23062
+ process.stdin.on("end", () => resolve9(parseHookEvent(Buffer.concat(chunks).toString("utf-8"))));
23007
23063
  process.stdin.on("error", () => resolve9({}));
23008
23064
  process.stdin.resume();
23009
23065
  });
@@ -23827,8 +23883,8 @@ async function correctVerityMdVersion(opts) {
23827
23883
  origin: { kind: "synthesized", tools: opts.tools }
23828
23884
  }));
23829
23885
  }
23830
- async function writeFileTo(relative6, body2) {
23831
- const target = projectPath(relative6);
23886
+ async function writeFileTo(relative7, body2) {
23887
+ const target = projectPath(relative7);
23832
23888
  await (0, import_promises10.mkdir)((0, import_node_path29.dirname)(target), { recursive: true });
23833
23889
  await (0, import_promises10.writeFile)(target, body2);
23834
23890
  }
@@ -24907,7 +24963,7 @@ function registerStatusCommand(program2) {
24907
24963
  {
24908
24964
  const tokenForScope = tokenResult.data.token;
24909
24965
  const found = resolveIgnoreState(
24910
- ignoreStateKeys(tokenForScope, process.env.CLAUDE_SESSION_ID || void 0)
24966
+ ignoreStateKeys(tokenForScope, envSessionId())
24911
24967
  );
24912
24968
  const now = Math.floor(Date.now() / 1e3);
24913
24969
  const active = resolveActive(found?.state ?? null, now);
@@ -25100,7 +25156,7 @@ async function sendGeneralFeedback(message, opts, globals) {
25100
25156
  process.exit(1);
25101
25157
  }
25102
25158
  const body2 = { message };
25103
- const sessionId = opts.sessionId ?? process.env.CLAUDE_SESSION_ID;
25159
+ const sessionId = opts.sessionId ?? envSessionId();
25104
25160
  const model = opts.model ?? process.env.CLAUDE_MODEL ?? "unknown";
25105
25161
  if (sessionId) body2.session_id = sessionId;
25106
25162
  if (model) body2.agent_model = model;
@@ -26344,7 +26400,7 @@ function resolveFrame(input) {
26344
26400
  const hookDirUsable = !!input.hookCwd && (0, import_node_fs40.existsSync)(input.hookCwd);
26345
26401
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
26346
26402
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
26347
- const refuse = (refusal) => ({
26403
+ const refuse2 = (refusal) => ({
26348
26404
  moment: found?.moment ?? null,
26349
26405
  frame: { worktreeRoot: null, gitDir: null, commonDir: null, isLinkedWorktree: false, branch: null, anchor, refusal }
26350
26406
  });
@@ -26358,19 +26414,19 @@ function resolveFrame(input) {
26358
26414
  if (!kindRes.some((re) => re.test(segments[i2]))) continue;
26359
26415
  const target = extractCommandTarget(input.command, i2, baseDir);
26360
26416
  if (target.named) anchor = "command-target";
26361
- if (target.unresolvable) return refuse(`target:${target.unresolvable}`);
26417
+ if (target.unresolvable) return refuse2(`target:${target.unresolvable}`);
26362
26418
  dirs.add(target.dir ?? baseDir);
26363
26419
  }
26364
- if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
26420
+ if (dirs.size > 1) return refuse2(`target:multiple ${found.moment} targets in one command`);
26365
26421
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
26366
26422
  if (targetDir !== baseDir) {
26367
- if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26423
+ if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse2(`target:directory does not exist: ${targetDir}`);
26368
26424
  dir = targetDir;
26369
26425
  }
26370
26426
  }
26371
26427
  const toplevel = gitAt(dir, ["rev-parse", "--show-toplevel"]);
26372
26428
  if (!toplevel) {
26373
- return refuse(anchor === "command-target" ? `target:not a git repository: ${dir}` : `anchor:not a git repository: ${dir}`);
26429
+ return refuse2(anchor === "command-target" ? `target:not a git repository: ${dir}` : `anchor:not a git repository: ${dir}`);
26374
26430
  }
26375
26431
  const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
26376
26432
  const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
@@ -26966,7 +27022,7 @@ function sanitizeCommandWithLoss(rawCmd) {
26966
27022
  const lost = lines.slice(1).some((l) => l.trim().length > 0);
26967
27023
  const first = lines[0];
26968
27024
  const cmd = sanitizeCommand(first);
26969
- const hadSeparator = SEPARATORS.some((sep6) => first.indexOf(sep6) > 0);
27025
+ const hadSeparator = SEPARATORS.some((sep7) => first.indexOf(sep7) > 0);
26970
27026
  return { cmd, lost: lost || !hadSeparator && first.length > MAX_COMMAND_CHARS };
26971
27027
  }
26972
27028
  var SEPARATORS = [" | ", " > ", " >> ", " 2>", " && ", " ; "];
@@ -26975,11 +27031,11 @@ function sanitizeCommand(rawCmd) {
26975
27031
  let cmd = rawCmd.split("\n")[0];
26976
27032
  let cut = -1;
26977
27033
  let marker = "";
26978
- for (const sep6 of SEPARATORS) {
26979
- const idx = cmd.indexOf(sep6);
27034
+ for (const sep7 of SEPARATORS) {
27035
+ const idx = cmd.indexOf(sep7);
26980
27036
  if (idx > 0 && (cut === -1 || idx < cut)) {
26981
27037
  cut = idx;
26982
- marker = sep6.trim();
27038
+ marker = sep7.trim();
26983
27039
  }
26984
27040
  }
26985
27041
  if (cut > -1) cmd = cmd.slice(0, cut);
@@ -27046,13 +27102,13 @@ async function bootstrap(run4) {
27046
27102
  isTTY: process.stdout.isTTY === true
27047
27103
  });
27048
27104
  const { assistantMessage: assistantResponse, stopReason, transcriptPath, sessionId } = await readStopHookStdin();
27049
- if (deferredToPlugin("analyze", sessionId ?? process.env.CLAUDE_SESSION_ID ?? null)) {
27105
+ if (deferredToPlugin("analyze", sessionId ?? envSessionId() ?? null)) {
27050
27106
  process.exit(0);
27051
27107
  }
27052
27108
  const actionSummary = transcriptPath ? await extractActionSummary(transcriptPath) : null;
27053
27109
  const tokenResult = await resolveToken(globals.token);
27054
27110
  const scopeToken = tokenResult.ok ? tokenResult.data.token : void 0;
27055
- const rawSessionId = sessionId || process.env.CLAUDE_SESSION_ID || void 0;
27111
+ const rawSessionId = sessionId || envSessionId();
27056
27112
  const baselineSessionId = sessionScopeKey(scopeToken, rawSessionId);
27057
27113
  if (tokenResult.ok) {
27058
27114
  run4.beacon = {
@@ -27257,7 +27313,7 @@ function channelSilence(input) {
27257
27313
  // src/lib/cli-version.ts
27258
27314
  function cliVersion() {
27259
27315
  try {
27260
- return true ? "0.34.1" : "dev";
27316
+ return true ? "0.34.2-experimental.312358d" : "dev";
27261
27317
  } catch {
27262
27318
  return "dev";
27263
27319
  }
@@ -27497,10 +27553,10 @@ var EMPTY_RESULT = {
27497
27553
  findings: [],
27498
27554
  summary: { total_findings: 0, by_severity: {}, tools_run: [] }
27499
27555
  };
27500
- function withFailure(kind, detail) {
27556
+ function withFailure(kind2, detail) {
27501
27557
  return {
27502
27558
  ...EMPTY_RESULT,
27503
- summary: { ...EMPTY_RESULT.summary, failure: { kind, detail: detail.slice(0, 300) } }
27559
+ summary: { ...EMPTY_RESULT.summary, failure: { kind: kind2, detail: detail.slice(0, 300) } }
27504
27560
  };
27505
27561
  }
27506
27562
  function runCodacyAnalysisIfAvailable(files) {
@@ -28058,7 +28114,7 @@ async function connect(run4) {
28058
28114
  async function mode(run4) {
28059
28115
  const { opts, globals } = run4;
28060
28116
  const { actionSummary, allForReview, assistantResponse, baseline, conversation, memory: memory2, noFilesChanged, serviceUrl, sessionId, token, turnAuthoredCode } = run4;
28061
- const sessionIdForMemory = sessionId || process.env.CLAUDE_SESSION_ID || "";
28117
+ const sessionIdForMemory = sessionId || envSessionId() || "";
28062
28118
  let predictedMode;
28063
28119
  try {
28064
28120
  const memoryPath2 = sessionIdForMemory ? `/memory?session_id=${encodeURIComponent(sessionIdForMemory)}` : "/memory";
@@ -28259,11 +28315,11 @@ var rootCandidateCache = /* @__PURE__ */ new Map();
28259
28315
  function candidateRoots(repoRoot2) {
28260
28316
  const cached2 = rootCandidateCache.get(repoRoot2);
28261
28317
  if (cached2) return cached2;
28262
- const norm2 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
28263
- const out2 = [norm2];
28318
+ const norm3 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
28319
+ const out2 = [norm3];
28264
28320
  try {
28265
- const real = import_node_fs44.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
28266
- if (real !== norm2) out2.push(real);
28321
+ const real = import_node_fs44.realpathSync.native(norm3).replace(/\\/g, "/").replace(/\/+$/, "");
28322
+ if (real !== norm3) out2.push(real);
28267
28323
  } catch {
28268
28324
  }
28269
28325
  for (const r of [...out2]) {
@@ -29114,39 +29170,39 @@ function extentOf(node) {
29114
29170
  }
29115
29171
  function definitionsIn(root, spec) {
29116
29172
  const out2 = [];
29117
- const add = (name2, kind, extent, fn, owner, last = extent) => {
29173
+ const add = (name2, kind2, extent, fn, owner, last = extent) => {
29118
29174
  const q = qualifierOf(owner, spec);
29119
- out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind, extent, last, fn });
29175
+ out2.push({ name: name2, qualified: q ? `${q}.${name2}` : name2, kind: kind2, extent, last, fn });
29120
29176
  };
29121
29177
  const visit = (n) => {
29122
- const kind = spec.definitions[n.type];
29123
- if (kind && n.childForFieldName("body")) {
29178
+ const kind2 = spec.definitions[n.type];
29179
+ if (kind2 && n.childForFieldName("body")) {
29124
29180
  const nameNode = n.childForFieldName("name");
29125
29181
  if (nameNode && nameNode.type !== "computed_property_name") {
29126
29182
  const inClass = qualifierOf(n, spec) !== null;
29127
- const k = spec.id === "python" ? inClass ? "method" : "function" : kind;
29183
+ const k = spec.id === "python" ? inClass ? "method" : "function" : kind2;
29128
29184
  add(nameNode.text, k, extentOf(n), n, n, n.parent?.type === "decorated_definition" ? n.parent : n);
29129
29185
  }
29130
29186
  } else if (spec.functionValues.has(n.type) && n.parent) {
29131
29187
  const p = n.parent;
29132
- const kind2 = n.type === "arrow_function" ? "arrow" : n.type === "lambda" || n.type === "lambda_expression" ? "lambda" : "function";
29188
+ const kind3 = n.type === "arrow_function" ? "arrow" : n.type === "lambda" || n.type === "lambda_expression" ? "lambda" : "function";
29133
29189
  const bound = p.childForFieldName("value")?.id === n.id;
29134
29190
  if (bound && p.type === "variable_declarator" && p.childForFieldName("name")?.type === "identifier") {
29135
29191
  const decl = p.parent && p.parent.namedChildren.filter((c) => c.type === "variable_declarator").length === 1 ? p.parent : p;
29136
- add(p.childForFieldName("name").text, kind2, decl, n, p);
29192
+ add(p.childForFieldName("name").text, kind3, decl, n, p);
29137
29193
  } else if (bound && (p.type === "public_field_definition" || p.type === "field_definition")) {
29138
29194
  const nameNode = p.childForFieldName("name") ?? p.childForFieldName("property");
29139
- if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind2, extentOf(p), n, p, p);
29195
+ if (nameNode && nameNode.type !== "computed_property_name") add(nameNode.text, kind3, extentOf(p), n, p, p);
29140
29196
  } else if (bound && p.type === "pair") {
29141
29197
  const key = p.childForFieldName("key");
29142
- if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind2, p, n, p);
29198
+ if (key && (key.type === "property_identifier" || key.type === "identifier")) add(key.text, kind3, p, n, p);
29143
29199
  } else if (p.type === "arguments" && moduleCall(p.parent)) {
29144
29200
  const call = p.parent;
29145
29201
  const route = p.namedChildren[0];
29146
29202
  const quoted = route && route.id !== n.id && route.type === "string" ? unquote2(route.text) : null;
29147
29203
  const path = quoted && /^[\w/:.{}*-]{1,60}$/.test(quoted) ? quoted : null;
29148
29204
  const callee = call.childForFieldName("function").text;
29149
- add(path ? `${callee} ${path}` : callee, kind2, call.parent, n, call);
29205
+ add(path ? `${callee} ${path}` : callee, kind3, call.parent, n, call);
29150
29206
  }
29151
29207
  }
29152
29208
  for (const c of n.namedChildren) visit(c);
@@ -29423,15 +29479,15 @@ var STABLE_EXPRESSION = (t) => {
29423
29479
  const root = t.split(".")[0];
29424
29480
  return root === "this" || root === "self" || /^[A-Z]/.test(root);
29425
29481
  };
29426
- function argResource(kind, arg) {
29427
- if (!arg) return { kind, name: null, confidence: "unknown" };
29482
+ function argResource(kind2, arg) {
29483
+ if (!arg) return { kind: kind2, name: null, confidence: "unknown" };
29428
29484
  if (arg.literal !== null) {
29429
29485
  const n = literalName(arg.literal);
29430
- return n ? { kind, name: n.name, confidence: n.confidence } : { kind, name: null, confidence: "unknown" };
29486
+ return n ? { kind: kind2, name: n.name, confidence: n.confidence } : { kind: kind2, name: null, confidence: "unknown" };
29431
29487
  }
29432
- if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind, name: arg.text, confidence: "expression" };
29488
+ if (SIMPLE_EXPRESSION.test(arg.text) && STABLE_EXPRESSION(arg.text)) return { kind: kind2, name: arg.text, confidence: "expression" };
29433
29489
  const keyed = keyedCall(arg.text);
29434
- return keyed ? { kind, name: keyed, confidence: "expression" } : { kind, name: null, confidence: "unknown" };
29490
+ return keyed ? { kind: kind2, name: keyed, confidence: "expression" } : { kind: kind2, name: null, confidence: "unknown" };
29435
29491
  }
29436
29492
  function keyedCall(text) {
29437
29493
  const t = text.trim();
@@ -30940,8 +30996,8 @@ ${m.accessors.map((x) => ` ${x.fn.path}:${x.fn.start.line} ${x.fn.qualified} \u
30940
30996
  var KINDS = ["table", "cache", "file", "http", "queue", "service", "memory"];
30941
30997
  function parseResource(text) {
30942
30998
  const colon = text.indexOf(":");
30943
- const kind = colon > 0 ? text.slice(0, colon) : "";
30944
- if (KINDS.includes(kind)) return { kinds: [kind], name: text.slice(colon + 1) };
30999
+ const kind2 = colon > 0 ? text.slice(0, colon) : "";
31000
+ if (KINDS.includes(kind2)) return { kinds: [kind2], name: text.slice(colon + 1) };
30945
31001
  return { kinds: KINDS, name: text };
30946
31002
  }
30947
31003
  var writersOfTool = async (ctx, args2) => {
@@ -31951,7 +32007,7 @@ async function workingMemory(run4) {
31951
32007
  const { opts } = run4;
31952
32008
  const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run4;
31953
32009
  let { reachability } = run4;
31954
- const memorySession = sessionDossier(token, sessionId ?? process.env.CLAUDE_SESSION_ID ?? null);
32010
+ const memorySession = sessionDossier(token, sessionId ?? envSessionId() ?? null);
31955
32011
  let memory2 = null;
31956
32012
  let incrementReport = null;
31957
32013
  if (memorySession) {
@@ -32224,7 +32280,7 @@ async function buildRequest(run4) {
32224
32280
  context: {
32225
32281
  agent_model: process.env.CLAUDE_MODEL ?? "unknown",
32226
32282
  agent_harness: "claude-code",
32227
- session_id: sessionId || process.env.CLAUDE_SESSION_ID || "unknown",
32283
+ session_id: sessionId || envSessionId() || "unknown",
32228
32284
  iteration,
32229
32285
  // Makes fleet composition falsifiable — without it, no adoption-gated
32230
32286
  // rollout decision can be checked against anything.
@@ -33434,12 +33490,41 @@ async function runAnalyze(opts, globals) {
33434
33490
  }
33435
33491
 
33436
33492
  // src/commands/baseline.ts
33437
- var import_node_fs55 = require("node:fs");
33438
- var import_node_path42 = require("node:path");
33493
+ var import_node_fs56 = require("node:fs");
33494
+ var import_node_path43 = require("node:path");
33439
33495
 
33440
- // src/lib/project-skills.ts
33496
+ // src/lib/skew-notice.ts
33441
33497
  var import_node_fs54 = require("node:fs");
33442
33498
  var import_node_path41 = require("node:path");
33499
+ var MARKER = ".skew-notice.json";
33500
+ function markerPath2() {
33501
+ return (0, import_node_path41.join)(verityHome(), MARKER);
33502
+ }
33503
+ function today(now) {
33504
+ const y = now.getFullYear();
33505
+ const m = String(now.getMonth() + 1).padStart(2, "0");
33506
+ const d = String(now.getDate()).padStart(2, "0");
33507
+ return `${y}-${m}-${d}`;
33508
+ }
33509
+ function skewNoticeDue(skew, now = /* @__PURE__ */ new Date()) {
33510
+ try {
33511
+ const seen = JSON.parse((0, import_node_fs54.readFileSync)(markerPath2(), "utf-8"));
33512
+ return !(seen.global === skew.global && seen.hooks === skew.hooks && seen.day === today(now));
33513
+ } catch {
33514
+ return true;
33515
+ }
33516
+ }
33517
+ function recordSkewNotice(skew, now = /* @__PURE__ */ new Date()) {
33518
+ try {
33519
+ (0, import_node_fs54.mkdirSync)(verityHome(), { recursive: true, mode: 448 });
33520
+ (0, import_node_fs54.writeFileSync)(markerPath2(), JSON.stringify({ global: skew.global, hooks: skew.hooks, day: today(now) }) + "\n");
33521
+ } catch {
33522
+ }
33523
+ }
33524
+
33525
+ // src/lib/project-skills.ts
33526
+ var import_node_fs55 = require("node:fs");
33527
+ var import_node_path42 = require("node:path");
33443
33528
  var PROJECT_SKILL_NAMES = [
33444
33529
  "verity-setup",
33445
33530
  "verity-analyze",
@@ -33465,14 +33550,14 @@ var LEGACY_SKILL_NAMES = [
33465
33550
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
33466
33551
  function staleProjectSkills() {
33467
33552
  const root = projectPath(".claude/skills");
33468
- if (!(0, import_node_fs54.existsSync)(root)) return [];
33469
- return ALL.filter((name2) => (0, import_node_fs54.existsSync)((0, import_node_path41.join)(root, name2)));
33553
+ if (!(0, import_node_fs55.existsSync)(root)) return [];
33554
+ return ALL.filter((name2) => (0, import_node_fs55.existsSync)((0, import_node_path42.join)(root, name2)));
33470
33555
  }
33471
33556
  function removeProjectSkills() {
33472
33557
  const root = projectPath(".claude/skills");
33473
33558
  const removed = [];
33474
33559
  for (const name2 of staleProjectSkills()) {
33475
- (0, import_node_fs54.rmSync)((0, import_node_path41.join)(root, name2), { recursive: true, force: true });
33560
+ (0, import_node_fs55.rmSync)((0, import_node_path42.join)(root, name2), { recursive: true, force: true });
33476
33561
  removed.push(name2);
33477
33562
  }
33478
33563
  return removed;
@@ -33492,20 +33577,22 @@ function registerBaselineCommands(program2) {
33492
33577
  if (!process.stdin.isTTY) {
33493
33578
  const input = (await readStdin()).trim();
33494
33579
  if (input) {
33495
- const event = parseHookEvent(input);
33580
+ const event = parseHookEvent2(input);
33496
33581
  if (opts.sessionId === void 0) sessionId = event.sessionId;
33497
33582
  if (opts.source === void 0) source2 = event.source;
33498
33583
  }
33499
33584
  }
33500
- const session = sessionId ?? validSessionId(process.env.CLAUDE_SESSION_ID);
33585
+ const session = sessionId ?? validSessionId(envSessionId());
33501
33586
  const cli = pluginCliInvocation();
33502
33587
  const skew = cliVersionSkew();
33503
33588
  const why = skew ? `the \`verity\` on PATH is ${skew.global} but the hooks run ${skew.hooks}, so it is not the CLI they use` : verityOnPath() ? "the `verity` on PATH is a separate install whose version could not be read" : "this machine has no `verity` on PATH \u2014 the plugin carries its own copy";
33504
33589
  const cliLine = cli ? `Verity CLI: ${why}. When a Verity skill tells you to run \`verity <args>\`, run \`${cli} <args>\` instead. Everything else about the command is identical.` : null;
33505
- const skewMsg = skew ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
33506
- const skewNote = skew ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. Until they have, do not send them to run \`verity login\` in a terminal: that runs the global one, which can sign this machine in to a different server.` : null;
33590
+ const skewLoud = !!skew && skewNoticeDue(skew);
33591
+ const skewMsg = skew && skewLoud ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
33592
+ const loginWarning = "Until they have, do not send them to run `verity login` in a terminal: that runs the global one, which can sign this machine in to a different server.";
33593
+ const skewNote = !skew ? null : skewLoud ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. ${loginWarning}` : `The user's global \`verity\` is ${skew.global} and the hooks run ${skew.hooks}; \`${skew.remedy}\` fixes it. They were already told today, so do not repeat it unprompted \u2014 mention it only where it matters, such as before suggesting a \`verity\` command for their terminal. ${loginWarning}`;
33507
33594
  if (!verityConfigured()) {
33508
- if (isMachineStore((0, import_node_path42.join)(repoRoot(), VERITY_DIR))) process.exit(0);
33595
+ if (isMachineStore((0, import_node_path43.join)(repoRoot(), VERITY_DIR))) process.exit(0);
33509
33596
  const how = isPluginInvocation() ? "Tell the user to run /verity:init \u2014 they type it; you cannot invoke it." : "Tell the user to run `verity init` in their terminal.";
33510
33597
  const lines = [
33511
33598
  `Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
@@ -33532,19 +33619,20 @@ function registerBaselineCommands(program2) {
33532
33619
  }
33533
33620
  }) + "\n"
33534
33621
  );
33622
+ if (skew && skewMsg) recordSkewNotice(skew);
33535
33623
  process.exit(0);
33536
33624
  }
33537
33625
  const realStart = source2 === void 0 || source2 === "startup" || source2 === "clear";
33538
33626
  let memoryMsg = null;
33539
33627
  let memoryAgentLine = null;
33540
33628
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
33541
- if (realStart && !(0, import_node_fs55.existsSync)(memoryNotice)) {
33629
+ if (realStart && !(0, import_node_fs56.existsSync)(memoryNotice)) {
33542
33630
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
33543
33631
  if (trackedGraph > 0) {
33544
33632
  memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
33545
33633
  memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
33546
33634
  try {
33547
- (0, import_node_fs55.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33635
+ (0, import_node_fs56.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33548
33636
  } catch {
33549
33637
  }
33550
33638
  }
@@ -33572,7 +33660,7 @@ function registerBaselineCommands(program2) {
33572
33660
  }
33573
33661
  }
33574
33662
  if (memoryAgentLine) notices.push(memoryAgentLine);
33575
- if (notices.length > 0) {
33663
+ if (notices.length > 0 || skewMsg) {
33576
33664
  process.stdout.write(
33577
33665
  JSON.stringify({
33578
33666
  ...userMsg || skewMsg || memoryMsg ? { systemMessage: [skewMsg, userMsg, memoryMsg].filter(Boolean).join("\n") } : {},
@@ -33582,6 +33670,7 @@ function registerBaselineCommands(program2) {
33582
33670
  }
33583
33671
  }) + "\n"
33584
33672
  );
33673
+ if (skew && skewMsg) recordSkewNotice(skew);
33585
33674
  }
33586
33675
  } else if (memoryMsg) {
33587
33676
  process.stdout.write(
@@ -33613,7 +33702,7 @@ function registerBaselineCommands(program2) {
33613
33702
  process.exit(0);
33614
33703
  });
33615
33704
  }
33616
- var MAX_HOOK_EVENT_BYTES = 64 * 1024;
33705
+ var MAX_HOOK_EVENT_BYTES2 = 64 * 1024;
33617
33706
  var HOOK_SOURCES = /* @__PURE__ */ new Set(["startup", "resume", "clear", "compact"]);
33618
33707
  var SESSION_ID_RE2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
33619
33708
  async function readStdin() {
@@ -33621,11 +33710,11 @@ async function readStdin() {
33621
33710
  let size = 0;
33622
33711
  for await (const chunk of process.stdin) {
33623
33712
  size += chunk.length;
33624
- if (size <= MAX_HOOK_EVENT_BYTES) chunks.push(chunk);
33713
+ if (size <= MAX_HOOK_EVENT_BYTES2) chunks.push(chunk);
33625
33714
  }
33626
- return size > MAX_HOOK_EVENT_BYTES ? "" : Buffer.concat(chunks).toString("utf-8");
33715
+ return size > MAX_HOOK_EVENT_BYTES2 ? "" : Buffer.concat(chunks).toString("utf-8");
33627
33716
  }
33628
- function parseHookEvent(input) {
33717
+ function parseHookEvent2(input) {
33629
33718
  let event;
33630
33719
  try {
33631
33720
  event = JSON.parse(input);
@@ -33645,7 +33734,35 @@ function hookSource(value) {
33645
33734
  }
33646
33735
 
33647
33736
  // src/commands/review.ts
33648
- var import_node_fs56 = require("node:fs");
33737
+ var import_node_fs57 = require("node:fs");
33738
+ var import_node_path44 = require("node:path");
33739
+ function containReviewPaths(paths, base) {
33740
+ const kept = [];
33741
+ const refused2 = [];
33742
+ for (const raw of paths) {
33743
+ const candidate = (0, import_node_path44.isAbsolute)(raw) ? relativeForm(base, raw) : raw;
33744
+ if (candidate === "" || resolveInside(base, candidate) === null) refused2.push(raw);
33745
+ else kept.push(candidate);
33746
+ }
33747
+ return { kept, refused: refused2 };
33748
+ }
33749
+ function relativeForm(base, abs) {
33750
+ const lexical = (0, import_node_path44.relative)(base, abs);
33751
+ if (!(lexical === ".." || lexical.startsWith(`..${import_node_path44.sep}`) || (0, import_node_path44.isAbsolute)(lexical))) return lexical;
33752
+ try {
33753
+ let dir = (0, import_node_path44.dirname)(abs);
33754
+ let rest = (0, import_node_path44.basename)(abs);
33755
+ while (!(0, import_node_fs57.existsSync)(dir)) {
33756
+ const up = (0, import_node_path44.dirname)(dir);
33757
+ if (up === dir) return lexical;
33758
+ rest = (0, import_node_path44.join)((0, import_node_path44.basename)(dir), rest);
33759
+ dir = up;
33760
+ }
33761
+ return (0, import_node_path44.relative)((0, import_node_fs57.realpathSync)(base), (0, import_node_path44.join)((0, import_node_fs57.realpathSync)(dir), rest));
33762
+ } catch {
33763
+ return lexical;
33764
+ }
33765
+ }
33649
33766
  function registerReviewCommand(program2) {
33650
33767
  program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars); - reads it from stdin, so the words never pass through shell quoting").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
33651
33768
  const globals = program2.opts();
@@ -33664,11 +33781,23 @@ function registerReviewCommand(program2) {
33664
33781
  });
33665
33782
  }
33666
33783
  async function runReview(opts, globals) {
33667
- const allFiles = opts.files.split(",").map((f) => f.trim()).filter(Boolean);
33668
- const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
33784
+ const base = process.cwd();
33785
+ const files = containReviewPaths(opts.files.split(",").map((f) => f.trim()).filter(Boolean), base);
33786
+ const changed = opts.changed ? containReviewPaths(opts.changed.split(",").map((f) => f.trim()).filter(Boolean), base) : files;
33787
+ const refused2 = Array.from(/* @__PURE__ */ new Set([...files.refused, ...changed.refused]));
33788
+ if (refused2.length > 0) {
33789
+ printJsonCompact({
33790
+ gate_decision: "WARN",
33791
+ systemMessage: `Verity: refused ${refused2.length} path(s) outside this repository \u2014 nothing was reviewed. Pass paths inside the repository you run \`verity review\` from.`,
33792
+ refused_paths: refused2
33793
+ });
33794
+ process.exit(0);
33795
+ }
33796
+ const allFiles = files.kept;
33797
+ const changedFiles = changed.kept;
33669
33798
  const analyzable = filterAnalyzable(allFiles);
33670
33799
  const securityFiles = filterSecurity(allFiles);
33671
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs56.existsSync)(f) || resolveFile(f) !== null);
33800
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs57.existsSync)(f) || resolveFile(f) !== null);
33672
33801
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
33673
33802
  const codeDelta = collectCodeDelta(allFiles);
33674
33803
  const tokenResult = await resolveToken(globals.token);
@@ -33693,7 +33822,7 @@ async function runReview(opts, globals) {
33693
33822
  context: {
33694
33823
  agent_model: process.env.CLAUDE_MODEL ?? "unknown",
33695
33824
  agent_harness: "claude-code",
33696
- session_id: process.env.CLAUDE_SESSION_ID ?? "unknown",
33825
+ session_id: envSessionId() ?? "unknown",
33697
33826
  trigger: "review",
33698
33827
  iteration: 1
33699
33828
  }
@@ -33734,12 +33863,12 @@ async function runReview(opts, globals) {
33734
33863
  }
33735
33864
 
33736
33865
  // src/commands/guard.ts
33737
- var import_node_fs61 = require("node:fs");
33738
- var import_node_path48 = require("node:path");
33866
+ var import_node_fs63 = require("node:fs");
33867
+ var import_node_path51 = require("node:path");
33739
33868
 
33740
33869
  // src/lib/vendored.ts
33741
- var import_node_fs57 = require("node:fs");
33742
- var import_node_path43 = require("node:path");
33870
+ var import_node_fs58 = require("node:fs");
33871
+ var import_node_path45 = require("node:path");
33743
33872
  var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
33744
33873
  function dataDirOrNull() {
33745
33874
  try {
@@ -33754,7 +33883,7 @@ function shippedSkillFile(path, dataDir = dataDirOrNull()) {
33754
33883
  const [, skill, rel] = m;
33755
33884
  if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
33756
33885
  try {
33757
- return (0, import_node_fs57.readFileSync)((0, import_node_path43.join)(dataDir, "skills", skill, rel), "utf8");
33886
+ return (0, import_node_fs58.readFileSync)((0, import_node_path45.join)(dataDir, "skills", skill, rel), "utf8");
33758
33887
  } catch {
33759
33888
  return null;
33760
33889
  }
@@ -33863,8 +33992,33 @@ async function runAgentReview(options) {
33863
33992
  return { kind: "finished", response: finished.data };
33864
33993
  }
33865
33994
 
33995
+ // src/lib/effort.ts
33996
+ var import_node_fs59 = require("node:fs");
33997
+ var import_node_path46 = require("node:path");
33998
+ var import_yaml5 = __toESM2(require_dist());
33999
+ var EFFORT_PROFILES = {
34000
+ default: { pushDeadlineMs: 18e4, formal: { tier: "fast", maxRounds: 2, minScore: 0.7, costCapUsd: 1, maxTargets: 1, relaxedGates: false, dailyModels: 5, dailyCostUsd: 5 } },
34001
+ high: { pushDeadlineMs: 22e4, formal: { tier: "deep", maxRounds: 2, minScore: 0.6, costCapUsd: 2, maxTargets: 2, relaxedGates: false, dailyModels: 15, dailyCostUsd: 15 } },
34002
+ max: { pushDeadlineMs: 27e4, formal: { tier: "deep", maxRounds: 3, minScore: 0.5, costCapUsd: 4, maxTargets: 3, relaxedGates: true, dailyModels: 30, dailyCostUsd: 30 } }
34003
+ };
34004
+ function asEffort(value) {
34005
+ return value === "high" || value === "max" ? value : "default";
34006
+ }
34007
+ function resolveEffort(root, env = process.env) {
34008
+ if (env.VERITY_EFFORT) return asEffort(env.VERITY_EFFORT);
34009
+ try {
34010
+ const standard = (0, import_yaml5.parse)((0, import_node_fs59.readFileSync)((0, import_node_path46.join)(root, STANDARD_FILE), "utf8"));
34011
+ return asEffort(standard?.process_constraints?.git_moment_effort);
34012
+ } catch {
34013
+ return "default";
34014
+ }
34015
+ }
34016
+ function effortProfile(root, env = process.env) {
34017
+ return EFFORT_PROFILES[resolveEffort(root, env)];
34018
+ }
34019
+
33866
34020
  // src/lib/prove/auto.ts
33867
- var import_node_path47 = require("node:path");
34021
+ var import_node_path50 = require("node:path");
33868
34022
  var import_node_crypto19 = require("node:crypto");
33869
34023
 
33870
34024
  // src/lib/prove/signals.ts
@@ -34906,9 +35060,9 @@ function effectSites(numbered2) {
34906
35060
  const t = r.text.trim();
34907
35061
  if (!t || t.startsWith("//") || t.startsWith("#") || t.startsWith("*")) continue;
34908
35062
  const onParam = [...params].some((p) => callsOn(t, p) || callsDirect(t, p));
34909
- const kind = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
34910
- if (!kind) continue;
34911
- out2.push(`L${r.n} [${kind}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
35063
+ const kind2 = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
35064
+ if (!kind2) continue;
35065
+ out2.push(`L${r.n} [${kind2}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
34912
35066
  if (out2.length >= MAX_EFFECT_SITES) break;
34913
35067
  }
34914
35068
  return out2;
@@ -35551,9 +35705,9 @@ async function runReplay(brief, opts) {
35551
35705
  if (opts.auth) return runReplayViaServer(brief, opts.auth, opts.timeoutMs);
35552
35706
  const env = opts.env ?? process.env;
35553
35707
  const none = { covered: 0, total: 0, ratio: 0, basis: "none" };
35554
- const refuse = (error) => ({ claimed: null, verdict: "unverified", reason: "", downgrade: error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: 0, containerId: null, error });
35555
- if (env.VERITY_PROVE_DIRECT !== "1") return refuse("not logged in (run `verity login`); replays run on the Verity service");
35556
- if (!opts.apiKey) return refuse("OPENAI_API_KEY is not set");
35708
+ const refuse2 = (error) => ({ claimed: null, verdict: "unverified", reason: "", downgrade: error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: 0, containerId: null, error });
35709
+ if (env.VERITY_PROVE_DIRECT !== "1") return refuse2("not logged in (run `verity login`); replays run on the Verity service");
35710
+ if (!opts.apiKey) return refuse2("OPENAI_API_KEY is not set");
35557
35711
  return runReplayInContainer(brief, { apiKey: opts.apiKey, model: opts.model, timeoutMs: opts.timeoutMs, maxRounds: opts.maxRounds, fetchImpl: opts.fetchImpl });
35558
35712
  }
35559
35713
  function renderReplay(model, property, r) {
@@ -35591,18 +35745,18 @@ function renderReplay(model, property, r) {
35591
35745
  // src/lib/prove/runner.ts
35592
35746
  var import_node_child_process15 = require("node:child_process");
35593
35747
  var import_node_os8 = require("node:os");
35594
- var import_node_fs60 = require("node:fs");
35748
+ var import_node_fs62 = require("node:fs");
35595
35749
  var import_node_os9 = require("node:os");
35596
- var import_node_path46 = require("node:path");
35750
+ var import_node_path49 = require("node:path");
35597
35751
 
35598
35752
  // src/lib/prove/scaffold.ts
35599
- var import_node_fs59 = require("node:fs");
35600
- var import_node_path45 = require("node:path");
35753
+ var import_node_fs61 = require("node:fs");
35754
+ var import_node_path48 = require("node:path");
35601
35755
 
35602
35756
  // src/lib/prove/safe-write.ts
35603
- var import_node_fs58 = require("node:fs");
35757
+ var import_node_fs60 = require("node:fs");
35604
35758
  var import_node_crypto15 = require("node:crypto");
35605
- var import_node_path44 = require("node:path");
35759
+ var import_node_path47 = require("node:path");
35606
35760
  var SafeWriteError = class extends Error {
35607
35761
  constructor(reason, path) {
35608
35762
  super(`refusing to write ${path}: ${reason}`);
@@ -35611,10 +35765,10 @@ var SafeWriteError = class extends Error {
35611
35765
  this.name = "SafeWriteError";
35612
35766
  }
35613
35767
  };
35614
- var FLAGS3 = import_node_fs58.constants;
35768
+ var FLAGS3 = import_node_fs60.constants;
35615
35769
  var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
35616
35770
  function assertPlainRelative(rel) {
35617
- if (!rel || (0, import_node_path44.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35771
+ if (!rel || (0, import_node_path47.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35618
35772
  for (const part of rel.split(/[\\/]/)) {
35619
35773
  if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
35620
35774
  }
@@ -35623,34 +35777,34 @@ function ensureDirsNoFollow(root, rel) {
35623
35777
  const parts2 = rel.split(/[\\/]/);
35624
35778
  let cur = root;
35625
35779
  for (const part of parts2.slice(0, -1)) {
35626
- cur = (0, import_node_path44.join)(cur, part);
35780
+ cur = (0, import_node_path47.join)(cur, part);
35627
35781
  let st;
35628
35782
  try {
35629
- st = (0, import_node_fs58.lstatSync)(cur);
35783
+ st = (0, import_node_fs60.lstatSync)(cur);
35630
35784
  } catch {
35631
- (0, import_node_fs58.mkdirSync)(cur);
35785
+ (0, import_node_fs60.mkdirSync)(cur);
35632
35786
  continue;
35633
35787
  }
35634
35788
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
35635
35789
  if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
35636
35790
  }
35637
- return (0, import_node_path44.join)(root, rel);
35791
+ return (0, import_node_path47.join)(root, rel);
35638
35792
  }
35639
35793
  function insideRoot(realRoot, realPath) {
35640
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path44.sep) ? realRoot : realRoot + import_node_path44.sep);
35794
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path47.sep) ? realRoot : realRoot + import_node_path47.sep);
35641
35795
  }
35642
35796
  function removeQuietly(path) {
35643
35797
  try {
35644
- (0, import_node_fs58.unlinkSync)(path);
35798
+ (0, import_node_fs60.unlinkSync)(path);
35645
35799
  } catch {
35646
35800
  }
35647
35801
  }
35648
35802
  function writeFileInRootNoFollow(root, rel, content) {
35649
35803
  assertPlainRelative(rel);
35650
35804
  const dest = ensureDirsNoFollow(root, rel);
35651
- const dir = (0, import_node_path44.dirname)(dest);
35805
+ const dir = (0, import_node_path47.dirname)(dest);
35652
35806
  try {
35653
- const st = (0, import_node_fs58.lstatSync)(dest);
35807
+ const st = (0, import_node_fs60.lstatSync)(dest);
35654
35808
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
35655
35809
  if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
35656
35810
  } catch (err2) {
@@ -35658,41 +35812,41 @@ function writeFileInRootNoFollow(root, rel, content) {
35658
35812
  }
35659
35813
  let realRoot;
35660
35814
  try {
35661
- realRoot = (0, import_node_fs58.realpathSync)(root);
35815
+ realRoot = (0, import_node_fs60.realpathSync)(root);
35662
35816
  } catch {
35663
35817
  throw new SafeWriteError("unwritable", root);
35664
35818
  }
35665
- const tmp = (0, import_node_path44.join)(dir, `.${(0, import_node_path44.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35819
+ const tmp = (0, import_node_path47.join)(dir, `.${(0, import_node_path47.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35666
35820
  let fd;
35667
35821
  try {
35668
- fd = (0, import_node_fs58.openSync)(tmp, import_node_fs58.constants.O_WRONLY | import_node_fs58.constants.O_CREAT | import_node_fs58.constants.O_EXCL | NOFOLLOW2, 420);
35822
+ fd = (0, import_node_fs60.openSync)(tmp, import_node_fs60.constants.O_WRONLY | import_node_fs60.constants.O_CREAT | import_node_fs60.constants.O_EXCL | NOFOLLOW2, 420);
35669
35823
  } catch {
35670
35824
  throw new SafeWriteError("unwritable", tmp);
35671
35825
  }
35672
35826
  try {
35673
- const opened = (0, import_node_fs58.fstatSync)(fd, { bigint: true });
35827
+ const opened = (0, import_node_fs60.fstatSync)(fd, { bigint: true });
35674
35828
  let realTmp;
35675
35829
  try {
35676
- realTmp = (0, import_node_fs58.realpathSync)(tmp);
35830
+ realTmp = (0, import_node_fs60.realpathSync)(tmp);
35677
35831
  } catch {
35678
35832
  throw new SafeWriteError("escaped", tmp);
35679
35833
  }
35680
- const there = (0, import_node_fs58.lstatSync)(realTmp, { bigint: true });
35834
+ const there = (0, import_node_fs60.lstatSync)(realTmp, { bigint: true });
35681
35835
  if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
35682
35836
  throw new SafeWriteError("escaped", tmp);
35683
35837
  }
35684
35838
  const buf = Buffer.from(content, "utf-8");
35685
35839
  let off = 0;
35686
- while (off < buf.length) off += (0, import_node_fs58.writeSync)(fd, buf, off, buf.length - off);
35840
+ while (off < buf.length) off += (0, import_node_fs60.writeSync)(fd, buf, off, buf.length - off);
35687
35841
  } catch (err2) {
35688
- (0, import_node_fs58.closeSync)(fd);
35842
+ (0, import_node_fs60.closeSync)(fd);
35689
35843
  removeQuietly(tmp);
35690
35844
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
35691
35845
  }
35692
- (0, import_node_fs58.closeSync)(fd);
35846
+ (0, import_node_fs60.closeSync)(fd);
35693
35847
  try {
35694
- if (!insideRoot(realRoot, (0, import_node_fs58.realpathSync)(dir)) || (0, import_node_fs58.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35695
- (0, import_node_fs58.renameSync)(tmp, dest);
35848
+ if (!insideRoot(realRoot, (0, import_node_fs60.realpathSync)(dir)) || (0, import_node_fs60.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35849
+ (0, import_node_fs60.renameSync)(tmp, dest);
35696
35850
  } catch (err2) {
35697
35851
  removeQuietly(tmp);
35698
35852
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
@@ -35706,9 +35860,9 @@ function pathHasNoLink(root, rel) {
35706
35860
  }
35707
35861
  let cur = root;
35708
35862
  for (const part of rel.split(/[\\/]/)) {
35709
- cur = cur + import_node_path44.sep + part;
35863
+ cur = cur + import_node_path47.sep + part;
35710
35864
  try {
35711
- if ((0, import_node_fs58.lstatSync)(cur).isSymbolicLink()) return false;
35865
+ if ((0, import_node_fs60.lstatSync)(cur).isSymbolicLink()) return false;
35712
35866
  } catch {
35713
35867
  return true;
35714
35868
  }
@@ -36018,20 +36172,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
36018
36172
  never committed; what reaches the team is the bug report and the fix.
36019
36173
  `;
36020
36174
  function scaffoldProofs(root) {
36021
- const proofsDir = (0, import_node_path45.join)(root, PROOFS_DIR);
36175
+ const proofsDir = (0, import_node_path48.join)(root, PROOFS_DIR);
36022
36176
  const written = [];
36023
36177
  const kept = [];
36024
36178
  for (const stray of ["lakefile.lean"]) {
36025
36179
  const rel = `${PROOFS_DIR}/${stray}`;
36026
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36180
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
36027
36181
  try {
36028
- (0, import_node_fs59.rmSync)((0, import_node_path45.join)(root, rel), { force: true });
36182
+ (0, import_node_fs61.rmSync)((0, import_node_path48.join)(root, rel), { force: true });
36029
36183
  } catch {
36030
36184
  }
36031
36185
  }
36032
36186
  for (const f of PROOFS_TEMPLATE_FILES) {
36033
36187
  const rel = `${PROOFS_DIR}/${f.path}`;
36034
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36188
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
36035
36189
  const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
36036
36190
  if (current.ok && current.content === f.content) {
36037
36191
  kept.push(rel);
@@ -36044,8 +36198,8 @@ function scaffoldProofs(root) {
36044
36198
  [`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
36045
36199
  [`${MODELS_DIR}/README.md`, MODELS_README]
36046
36200
  ]) {
36047
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36048
- if (existsNoFollow((0, import_node_path45.join)(root, rel))) {
36201
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path48.join)(root, rel));
36202
+ if (existsNoFollow((0, import_node_path48.join)(root, rel))) {
36049
36203
  kept.push(rel);
36050
36204
  continue;
36051
36205
  }
@@ -36056,7 +36210,7 @@ function scaffoldProofs(root) {
36056
36210
  }
36057
36211
  function existsNoFollow(abs) {
36058
36212
  try {
36059
- (0, import_node_fs59.lstatSync)(abs);
36213
+ (0, import_node_fs61.lstatSync)(abs);
36060
36214
  return true;
36061
36215
  } catch {
36062
36216
  return false;
@@ -36135,12 +36289,12 @@ function parseHeader(obj) {
36135
36289
  function parseProperty(obj) {
36136
36290
  const model = ident(obj.model);
36137
36291
  const id = ident(obj.id);
36138
- const kind = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
36292
+ const kind2 = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
36139
36293
  const result = typeof obj.result === "string" && RESULTS.has(obj.result) ? obj.result : null;
36140
36294
  const source2 = obj.source === void 0 ? "" : str2(obj.source, LIMITS.text);
36141
36295
  const desc = obj.desc === void 0 ? "" : str2(obj.desc, LIMITS.text);
36142
- if (!model || !id || !kind || !result || source2 === null || desc === null) return null;
36143
- const p = { model, id, kind, source: source2, desc, result };
36296
+ if (!model || !id || !kind2 || !result || source2 === null || desc === null) return null;
36297
+ const p = { model, id, kind: kind2, source: source2, desc, result };
36144
36298
  if (obj.bound !== void 0) {
36145
36299
  const n = nat(obj.bound);
36146
36300
  if (n === null) return null;
@@ -36314,17 +36468,17 @@ function renderReport(r) {
36314
36468
 
36315
36469
  // src/lib/prove/runner.ts
36316
36470
  function verityLeanHome(env = process.env) {
36317
- return env.VERITY_LEAN_HOME ?? (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36471
+ return env.VERITY_LEAN_HOME ?? (0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36318
36472
  }
36319
36473
  function findToolchain(env = process.env) {
36320
- const managedBin = (0, import_node_path46.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
36321
- const elanBin = (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
36322
- const elanHas = (0, import_node_fs60.existsSync)((0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
36323
- const userPath = (env.PATH ?? "").split(import_node_path46.delimiter).filter((d) => d && (elanHas || (0, import_node_path46.resolve)(d) !== (0, import_node_path46.resolve)(elanBin)));
36324
- const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path46.delimiter);
36474
+ const managedBin = (0, import_node_path49.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
36475
+ const elanBin = (0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
36476
+ const elanHas = (0, import_node_fs62.existsSync)((0, import_node_path49.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
36477
+ const userPath = (env.PATH ?? "").split(import_node_path49.delimiter).filter((d) => d && (elanHas || (0, import_node_path49.resolve)(d) !== (0, import_node_path49.resolve)(elanBin)));
36478
+ const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path49.delimiter);
36325
36479
  const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
36326
36480
  const exe = process.platform === "win32" ? "lake.exe" : "lake";
36327
- const candidates2 = [(0, import_node_path46.join)(managedBin, exe), ...elanHas ? [(0, import_node_path46.join)(elanBin, exe)] : [], exe];
36481
+ const candidates2 = [(0, import_node_path49.join)(managedBin, exe), ...elanHas ? [(0, import_node_path49.join)(elanBin, exe)] : [], exe];
36328
36482
  for (const candidate of candidates2) {
36329
36483
  try {
36330
36484
  (0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
@@ -36403,7 +36557,7 @@ function proofsWorkspaceProblem(root) {
36403
36557
  for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
36404
36558
  let st;
36405
36559
  try {
36406
- st = (0, import_node_fs60.lstatSync)((0, import_node_path46.join)(root, rel));
36560
+ st = (0, import_node_fs62.lstatSync)((0, import_node_path49.join)(root, rel));
36407
36561
  } catch {
36408
36562
  break;
36409
36563
  }
@@ -36423,44 +36577,44 @@ function refused(problem) {
36423
36577
  function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36424
36578
  const problem = proofsWorkspaceProblem(root);
36425
36579
  if (problem) return refused(problem);
36426
- return run2(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36580
+ return run2(tc, (0, import_node_path49.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36427
36581
  }
36428
36582
  async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36429
36583
  const problem = proofsWorkspaceProblem(root);
36430
36584
  if (problem) return refused(problem);
36431
- return runAsync(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36585
+ return runAsync(tc, (0, import_node_path49.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36432
36586
  }
36433
36587
  function isModelInRoot(modelsAbs, rel) {
36434
- if (!rel.endsWith(".lean") || (0, import_node_path46.isAbsolute)(rel) || rel.startsWith("..")) return false;
36588
+ if (!rel.endsWith(".lean") || (0, import_node_path49.isAbsolute)(rel) || rel.startsWith("..")) return false;
36435
36589
  return statRegularInRoot(modelsAbs, rel).ok;
36436
36590
  }
36437
36591
  function resolveModelFile(root, arg) {
36438
- const modelsAbs = (0, import_node_path46.join)(root, MODELS_DIR);
36439
- const asPath = (0, import_node_path46.relative)(modelsAbs, (0, import_node_path46.isAbsolute)(arg) ? arg : (0, import_node_path46.resolve)(root, arg));
36592
+ const modelsAbs = (0, import_node_path49.join)(root, MODELS_DIR);
36593
+ const asPath = (0, import_node_path49.relative)(modelsAbs, (0, import_node_path49.isAbsolute)(arg) ? arg : (0, import_node_path49.resolve)(root, arg));
36440
36594
  const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
36441
36595
  for (const rel of candidates2) {
36442
- if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path46.join)(modelsAbs, rel);
36596
+ if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path49.join)(modelsAbs, rel);
36443
36597
  }
36444
36598
  return null;
36445
36599
  }
36446
36600
  function listModelFiles(root) {
36447
- const modelsAbs = (0, import_node_path46.join)(root, MODELS_DIR);
36448
- if (!(0, import_node_fs60.existsSync)(modelsAbs)) return [];
36449
- return (0, import_node_fs60.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path46.join)(modelsAbs, f));
36601
+ const modelsAbs = (0, import_node_path49.join)(root, MODELS_DIR);
36602
+ if (!(0, import_node_fs62.existsSync)(modelsAbs)) return [];
36603
+ return (0, import_node_fs62.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path49.join)(modelsAbs, f));
36450
36604
  }
36451
36605
  function trimDiagnostics(text) {
36452
36606
  return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36453
36607
  }
36454
36608
  function checkModel(tc, root, modelFile, opts = {}) {
36455
- const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36456
- const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36609
+ const proofsAbs = (0, import_node_path49.join)(root, PROOFS_DIR);
36610
+ const rel = (0, import_node_path49.relative)(proofsAbs, modelFile);
36457
36611
  const problem = proofsWorkspaceProblem(root);
36458
36612
  const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36459
36613
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36460
36614
  }
36461
36615
  async function checkModelAsync(tc, root, modelFile, opts = {}) {
36462
- const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36463
- const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36616
+ const proofsAbs = (0, import_node_path49.join)(root, PROOFS_DIR);
36617
+ const rel = (0, import_node_path49.relative)(proofsAbs, modelFile);
36464
36618
  const problem = proofsWorkspaceProblem(root);
36465
36619
  const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36466
36620
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
@@ -36469,10 +36623,10 @@ function toReport(res, root, modelFile, timeoutMs) {
36469
36623
  const parsed = parseVerityLines(res.stdout);
36470
36624
  const combined = `${res.stdout}
36471
36625
  ${res.stderr}`;
36472
- const name2 = parsed.header?.model ?? (0, import_node_path46.basename)(modelFile, ".lean");
36626
+ const name2 = parsed.header?.model ?? (0, import_node_path49.basename)(modelFile, ".lean");
36473
36627
  const report = {
36474
36628
  model: name2,
36475
- file: (0, import_node_path46.relative)(root, modelFile),
36629
+ file: (0, import_node_path49.relative)(root, modelFile),
36476
36630
  ok: res.ok,
36477
36631
  header: parsed.header,
36478
36632
  properties: parsed.properties,
@@ -36519,9 +36673,9 @@ function isCrashTrace(trace) {
36519
36673
  }
36520
36674
  function mergeFormalFindings(response, outcome, pushedFiles) {
36521
36675
  if (!outcome) return { blocking: 0 };
36522
- const norm2 = (p) => p.replace(/\\/g, "/");
36523
- const pushed = new Set(pushedFiles.map(norm2));
36524
- const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
36676
+ const norm3 = (p) => p.replace(/\\/g, "/");
36677
+ const pushed = new Set(pushedFiles.map(norm3));
36678
+ const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm3(f.file)));
36525
36679
  if (blocking.length === 0) return { blocking: 0 };
36526
36680
  const existing = Array.isArray(response.findings) ? response.findings : [];
36527
36681
  response.findings = [
@@ -36717,15 +36871,15 @@ function nonNegative(v) {
36717
36871
  return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
36718
36872
  }
36719
36873
  function readLedger(root) {
36720
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
36721
- const empty = { day: today, models: 0, costUsd: 0 };
36874
+ const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
36875
+ const empty = { day: today2, models: 0, costUsd: 0 };
36722
36876
  if (!isLocalState(root, AUTO_LEDGER)) return empty;
36723
36877
  const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
36724
36878
  if (!read2.ok) return empty;
36725
36879
  try {
36726
36880
  const o = JSON.parse(read2.content);
36727
- if (o.day !== today || typeof o.models !== "number") return empty;
36728
- return { day: today, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
36881
+ if (o.day !== today2 || typeof o.models !== "number") return empty;
36882
+ return { day: today2, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
36729
36883
  } catch {
36730
36884
  return empty;
36731
36885
  }
@@ -36867,7 +37021,7 @@ async function runFormalPhase(input) {
36867
37021
  }
36868
37022
  }
36869
37023
  if (kept.length !== persisted.length) writePersistedFindings(root, kept);
36870
- if (standing.length > 0) {
37024
+ if (standing.length > 0 && !input.skipStanding) {
36871
37025
  const first = kept.find((f) => f.file === standing[0].file);
36872
37026
  return done({
36873
37027
  status: "checked",
@@ -36895,7 +37049,7 @@ async function runFormalPhase(input) {
36895
37049
  return a.source === "tree-sitter" && a.value.effects.length >= 2;
36896
37050
  })());
36897
37051
  };
36898
- const eligible = signals.filter((s) => isEligible(s, largePush).ok || mapEligible(s.file)).slice(0, 5);
37052
+ const eligible = signals.filter((s) => input.relaxedGates || isEligible(s, largePush).ok || mapEligible(s.file)).slice(0, 5);
36899
37053
  if (eligible.length === 0) {
36900
37054
  const best = signals[0];
36901
37055
  return done({ status: "skipped", skip: "not-eligible", detail: `${best.file}: ${isEligible(best, largePush).why}` });
@@ -36903,7 +37057,7 @@ async function runFormalPhase(input) {
36903
37057
  const ranked = await deps.rank(eligible, root, input.changedLines);
36904
37058
  if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
36905
37059
  if (ranked.ok) spend(ranked);
36906
- candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
37060
+ candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)), commits: c.commits, fixCommits: c.fixCommits, risk: c.risk }));
36907
37061
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
36908
37062
  const minScore = input.minScore ?? DEFAULT_MIN_SCORE;
36909
37063
  let qualified = ranked.ranked.filter((c) => c.ai && c.ai.score >= minScore);
@@ -36949,6 +37103,10 @@ async function runFormalPhase(input) {
36949
37103
  }
36950
37104
  }
36951
37105
  if (d.resolved && d.resolved !== c.ai.symbol) c.ai.symbol = d.resolved;
37106
+ if (input.exclude?.has(`${c.file}#${c.ai.symbol}`)) {
37107
+ note("verified", `${c.ai.symbol}: modelled earlier in this push`);
37108
+ continue;
37109
+ }
36952
37110
  if (input.changedLines) {
36953
37111
  const changed = input.changedLines.get(c.file) ?? [];
36954
37112
  if (changed.length === 0) {
@@ -36990,7 +37148,7 @@ async function runFormalPhase(input) {
36990
37148
  const hazard = hasHazard(functionHazard(d.numbered));
36991
37149
  const shared = contextHazard(context);
36992
37150
  const judged = (c.ai.criteria?.hazard ?? 0) >= 0.8;
36993
- if (!hazard.ok && !shared?.ok && !judged) {
37151
+ if (!input.relaxedGates && !hazard.ok && !shared?.ok && !judged) {
36994
37152
  note("no-hazard", `${c.ai.symbol}: ${hazard.why}`);
36995
37153
  continue;
36996
37154
  }
@@ -37012,7 +37170,7 @@ async function runFormalPhase(input) {
37012
37170
  const sha2562 = sha256Of(chosen.content);
37013
37171
  const chosenContent = chosen.content;
37014
37172
  const { lines, numbered: numbered2 } = chosen;
37015
- const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {} };
37173
+ const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {}, signals: { commits: top.commits, fixCommits: top.fixCommits, risk: top.risk } };
37016
37174
  progress.target = target;
37017
37175
  if (!REPLAYABLE.test(top.file)) return done({ status: "skipped", skip: "replay-unsupported", detail: `${top.file}: replay supports TS/JS and Python`, target });
37018
37176
  if (timeLeft() < GENERATE_RESERVE_MS) return done({ status: "skipped", skip: "not-enough-time", detail: `${Math.round(timeLeft() / 1e3)} s left before generation`, target });
@@ -37023,7 +37181,7 @@ async function runFormalPhase(input) {
37023
37181
  let report = null;
37024
37182
  let modelName = "";
37025
37183
  let rounds = 0;
37026
- for (let round = 1; round <= 2; round++) {
37184
+ for (let round = 1; round <= (input.maxRounds ?? 2); round++) {
37027
37185
  if (round > 1 && overCap()) return done({ status: "skipped", skip: "cost-cap", detail: `$${usage.costUsd.toFixed(2)} spent, cap $${costCap.toFixed(2)}; no retry`, target, model: { name: modelName, file: `${AUTO_MODELS_DIR}/${modelName}.lean`, rounds } });
37028
37186
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off before generation", target });
37029
37187
  rounds = round;
@@ -37042,7 +37200,7 @@ async function runFormalPhase(input) {
37042
37200
  modelName = gen.name;
37043
37201
  const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
37044
37202
  writeFileInRootNoFollow(root, rel, gen.source);
37045
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
37203
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path50.join)(root, rel);
37046
37204
  progress.model = { name: gen.name, file: rel, rounds: round };
37047
37205
  progress.step = "check";
37048
37206
  report = await deps.check(root, abs);
@@ -37164,7 +37322,7 @@ async function runFormalPhase(input) {
37164
37322
  return done({
37165
37323
  status: "checked",
37166
37324
  target,
37167
- model: { name: modelName, file: (0, import_node_path47.relative)(root, (0, import_node_path47.join)(root, modelFile)), rounds },
37325
+ model: { name: modelName, file: (0, import_node_path50.relative)(root, (0, import_node_path50.join)(root, modelFile)), rounds },
37168
37326
  properties: report.properties,
37169
37327
  findings
37170
37328
  });
@@ -37197,7 +37355,19 @@ async function generateAndCheck(root, req, opts) {
37197
37355
  const read2 = readSrc(req.file, 96 * 1024);
37198
37356
  if (!read2.ok) return { ok: false, error: `${req.file}: ${read2.reason}`, rounds: 0, costUsd: 0 };
37199
37357
  const sha2562 = sha256Of(read2.content);
37200
- const { lines, numbered: numbered2 } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
37358
+ const { lines, numbered: numbered2, extent } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
37359
+ let warning;
37360
+ if (!lines) {
37361
+ const outline = extent === "fallback:not-found" ? opts.deps.codeMap?.outline(req.file, read2.content) : void 0;
37362
+ if (outline?.source === "tree-sitter") {
37363
+ const names2 = [...new Set(outline.value.filter((f) => f.name && f.kind !== "lambda").map((f) => f.qualified))];
37364
+ const last = (req.symbol.split(/[.#:]/).pop() ?? req.symbol).toLowerCase();
37365
+ const close = names2.filter((n) => n.toLowerCase().includes(last));
37366
+ const shown = (close.length > 0 ? close : names2).slice(0, 12);
37367
+ return { ok: false, error: `no function \`${req.symbol}\` in ${req.file}${shown.length ? ` (it has: ${shown.join(", ")})` : ""}. Name one as ${req.file}#<name>, or pass --lines a-b`, rounds: 0, costUsd: 0 };
37368
+ }
37369
+ warning = `could not find the lines of \`${req.symbol}\` in ${req.file} (${extent}): the model is written from the start of the file, and a replay must copy half of the whole file. Pass --lines a-b to name the code.`;
37370
+ }
37201
37371
  const target = {
37202
37372
  file: req.file,
37203
37373
  symbol: req.symbol,
@@ -37205,7 +37375,9 @@ async function generateAndCheck(root, req, opts) {
37205
37375
  sha256: sha2562,
37206
37376
  numbered: numbered2,
37207
37377
  reasons: req.hint ? [`the user's worry, in their words: ${req.hint.slice(0, 280)}`] : [],
37208
- properties: []
37378
+ properties: [],
37379
+ // The run row records which extractor answered, as at push.
37380
+ extentSource: extent
37209
37381
  };
37210
37382
  const context = opts.deps.codeMap && !req.lines ? targetContext({ codeMap: opts.deps.codeMap, codeSource: opts.deps.codeSource, readSource: readSrc, file: req.file, content: read2.content, symbol: req.symbol }) : null;
37211
37383
  Object.assign(target, context?.fields ?? {});
@@ -37227,7 +37399,7 @@ async function generateAndCheck(root, req, opts) {
37227
37399
  }
37228
37400
  const rel = `${dir}/${gen.name}.lean`;
37229
37401
  writeFileInRootNoFollow(root, rel, gen.source);
37230
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
37402
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path50.join)(root, rel);
37231
37403
  const report = await opts.deps.check(root, abs);
37232
37404
  const abstracts = report.header?.abstracts ?? [];
37233
37405
  const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
@@ -37241,14 +37413,14 @@ async function generateAndCheck(root, req, opts) {
37241
37413
  const g = basisOf(p.source, files);
37242
37414
  return g.ok ? [] : [`${p.id}: ${g.why}`];
37243
37415
  });
37244
- if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd };
37416
+ if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd, ...warning ? { warning } : {} };
37245
37417
  lastError = ungroundedMessage(bad.join("; "));
37246
37418
  if (round < maxRounds) {
37247
37419
  previous = { source: gen.source, error: lastError };
37248
37420
  continue;
37249
37421
  }
37250
37422
  const grounded = report.properties.filter((p) => basisOf(p.source, files).ok);
37251
- if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd };
37423
+ if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd, ...warning ? { warning } : {} };
37252
37424
  break;
37253
37425
  }
37254
37426
  lastError = stray ? `the model abstracts ${stray.file}, not ${req.file}` : report.error ?? (report.malformed ? "the model printed malformed VERITY lines" : "the model reported no property");
@@ -37259,7 +37431,7 @@ async function generateAndCheck(root, req, opts) {
37259
37431
  function skippedOutcome(skip, detail) {
37260
37432
  return { status: "skipped", skip, ...detail ? { detail } : {}, findings: [], usage: { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 }, durationMs: 0 };
37261
37433
  }
37262
- async function prepareFormalPhase(root, env = process.env, auth2, readSource, codeSource) {
37434
+ async function prepareFormalPhase(root, env = process.env, auth2, readSource, codeSource, opts = {}) {
37263
37435
  const direct = env.VERITY_PROVE_DIRECT === "1" && !!env.OPENAI_API_KEY;
37264
37436
  if (!auth2 && !direct) return { ok: false, skip: "not-logged-in" };
37265
37437
  const apiKey = direct ? env.OPENAI_API_KEY : void 0;
@@ -37274,9 +37446,16 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
37274
37446
  }
37275
37447
  const build = await buildLibraryAsync(toolchain, root, 9e4);
37276
37448
  if (!build.ok) return { ok: false, skip: "library-build-failed", detail: build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).join(" ").slice(0, 200) };
37449
+ const code = await loadCodeContext(root, env, codeSource);
37450
+ return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...opts.tier ? { tier: opts.tier } : {}, ...code }), codeSource: code.codeSource } };
37451
+ }
37452
+ async function loadCodeContext(root, env = process.env, codeSource) {
37277
37453
  const loaded = await loadCodeMap(env);
37278
- const source2 = codeSource ?? withoutPaths(worktreeSource(root), isDeniedPath);
37279
- return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, codeMap: loaded.ok ? loaded.map : null, codeSource: source2 }), codeSource: source2 } };
37454
+ return { codeMap: loaded.ok ? loaded.map : null, codeSource: codeSource ?? withoutPaths(worktreeSource(root), isDeniedPath) };
37455
+ }
37456
+ async function onDemandDeps(root, opts) {
37457
+ const code = await loadCodeContext(root, opts.env);
37458
+ return { ...defaultDeps({ ...opts, tier: "deep", ...code }), codeSource: code.codeSource };
37280
37459
  }
37281
37460
  function changedFunction(codeMap, file, content, changed) {
37282
37461
  const outline = codeMap.outline(file, content);
@@ -37321,10 +37500,52 @@ function runFormalPhaseWithin(input) {
37321
37500
  resolve9(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
37322
37501
  }, left);
37323
37502
  });
37324
- return Promise.race([runFormalPhase({ ...input, progress }), cutoff]).finally(() => {
37503
+ return Promise.race([runFormalPhaseTargets({ ...input, progress }), cutoff]).finally(() => {
37325
37504
  if (timer) clearTimeout(timer);
37326
37505
  });
37327
37506
  }
37507
+ var NOTHING_ELSE_QUALIFIES = /* @__PURE__ */ new Set(["no-source-files", "not-eligible", "no-candidate", "no-symbol", "symbol-not-in-push", "verified", "no-hazard", "too-large"]);
37508
+ async function runFormalPhaseTargets(input) {
37509
+ const first = await runFormalPhase(input);
37510
+ const max = Math.max(1, Math.floor(input.maxTargets ?? 1));
37511
+ if (max === 1 || first.status !== "checked" || !first.target) return first;
37512
+ const outcomes = [first];
37513
+ const exclude = /* @__PURE__ */ new Set([`${first.target.file}#${first.target.symbol}`]);
37514
+ const cap2 = input.costCapUsd ?? PUSH_COST_CAP_USD;
37515
+ let stoppedAt;
37516
+ while (outcomes.length < max) {
37517
+ if (input.progress?.cancelled) {
37518
+ stoppedAt = { skip: "deadline", detail: "cut off between targets" };
37519
+ break;
37520
+ }
37521
+ const left = input.deadlineAt - input.deps.now();
37522
+ if (left < GENERATE_RESERVE_MS + REPLAY_RESERVE_MS) {
37523
+ stoppedAt = { skip: "not-enough-time", detail: `${Math.round(left / 1e3)} s left before target ${outcomes.length + 1}` };
37524
+ break;
37525
+ }
37526
+ const spent = outcomes.reduce((sum, o) => sum + o.usage.costUsd, 0);
37527
+ if (spent >= cap2) {
37528
+ stoppedAt = { skip: "cost-cap", detail: `$${spent.toFixed(2)} spent, cap $${cap2.toFixed(2)}` };
37529
+ break;
37530
+ }
37531
+ const next = await runFormalPhase({ ...input, exclude, skipStanding: true, costCapUsd: cap2 - spent, progress: {} });
37532
+ if (next.status !== "checked" && next.skip && !NOTHING_ELSE_QUALIFIES.has(next.skip)) stoppedAt = { skip: next.skip, ...next.detail ? { detail: next.detail } : {} };
37533
+ if (!next.target || next.status !== "checked" && exclude.has(`${next.target.file}#${next.target.symbol}`)) break;
37534
+ exclude.add(`${next.target.file}#${next.target.symbol}`);
37535
+ outcomes.push(next);
37536
+ if (next.status !== "checked") break;
37537
+ }
37538
+ if (outcomes.length === 1) return stoppedAt ? { ...first, stoppedAt } : first;
37539
+ return {
37540
+ ...first,
37541
+ ...stoppedAt ? { stoppedAt } : {},
37542
+ findings: outcomes.flatMap((o) => o.findings),
37543
+ properties: outcomes.flatMap((o) => o.properties ?? []),
37544
+ targets: outcomes.flatMap((o) => o.target ? [{ file: o.target.file, symbol: o.target.symbol, status: o.status, ...o.skip ? { skip: o.skip } : {}, findings: o.findings.length }] : []),
37545
+ usage: outcomes.reduce((u, o) => ({ inputTokens: u.inputTokens + o.usage.inputTokens, outputTokens: u.outputTokens + o.usage.outputTokens, costUsd: Math.round((u.costUsd + o.usage.costUsd) * 1e6) / 1e6, unpriced: u.unpriced + o.usage.unpriced }), { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 }),
37546
+ durationMs: outcomes.reduce((sum, o) => sum + o.durationMs, 0)
37547
+ };
37548
+ }
37328
37549
  function cutOffOutcome(p, detail, elapsedMs) {
37329
37550
  const usage = p.usage ?? { inputTokens: 0, outputTokens: 0, costUsd: 0, unpriced: 0 };
37330
37551
  if (!p.report || !p.target || !p.model) {
@@ -37351,13 +37572,138 @@ function describeFormalOutcome(o) {
37351
37572
  return `formal: ${o.model?.name ?? "?"} on ${o.target?.file ?? "?"}#${o.target?.symbol ?? "?"} (${o.model?.rounds ?? 1} round${o.model?.rounds === 1 ? "" : "s"}) \xB7 ${parts2.join(" \xB7 ")} \xB7 ${Math.round(o.durationMs / 1e3)} s${cost}${cut}`;
37352
37573
  }
37353
37574
 
37575
+ // src/lib/prove/record.ts
37576
+ var RECORD_TIMEOUT_MS = 8e3;
37577
+ var HOOK_EXIT_MARGIN_MS = 5e3;
37578
+ var MIN_RECORD_POST_MS = 1e3;
37579
+ function guardRecordDeadline(hookStartedAt) {
37580
+ return hookStartedAt + GUARD_TIMEOUT_MS - HOOK_EXIT_MARGIN_MS;
37581
+ }
37582
+ function recordPostTimeout(now, deadlineAt, timeoutMs = RECORD_TIMEOUT_MS) {
37583
+ if (deadlineAt === void 0) return timeoutMs;
37584
+ const left = deadlineAt - now;
37585
+ return left < MIN_RECORD_POST_MS ? null : Math.min(timeoutMs, left);
37586
+ }
37587
+ var norm2 = (p) => p.replace(/\\/g, "/");
37588
+ var SAFE_SEGMENT = /^[A-Za-z0-9._@+~$()[\]-]{1,255}$/;
37589
+ function safeRepoPath(p) {
37590
+ const n = norm2(p);
37591
+ if (!n || n.length > 512 || n.startsWith("/") || /^[A-Za-z]:\//.test(n)) return null;
37592
+ return n.split("/").every((s) => s !== "." && s !== ".." && SAFE_SEGMENT.test(s)) ? n : null;
37593
+ }
37594
+ var SYMBOL = /^[A-Za-z_$][\w$]*(?:[.#:][A-Za-z_$][\w$]*)*$/;
37595
+ var IDENT3 = /^[A-Za-z][\w]*$/;
37596
+ var TRACE_STEP = /^[A-Za-z_]\w{0,63}$/;
37597
+ var ELIDED_STEP = "\u2026";
37598
+ function recordBasis(source2) {
37599
+ if (typeof source2 !== "string") return "";
37600
+ if (/^rule:[a-z-]+$/.test(source2)) return source2;
37601
+ const m = /^(?:([^:\s]+):)?L(\d+)(?::|$)/.exec(source2);
37602
+ return m ? m[1] ? `${norm2(m[1])}:L${m[2]}` : `L${m[2]}` : "";
37603
+ }
37604
+ function recordTrace(trace) {
37605
+ return trace.slice(0, 16).map((s) => {
37606
+ const name2 = (s.trim().split(/[\s(]/, 1)[0] ?? "").split(".").pop() ?? "";
37607
+ return TRACE_STEP.test(name2) ? name2 : ELIDED_STEP;
37608
+ });
37609
+ }
37610
+ var ident2 = (s, re, max) => typeof s === "string" && s.length <= max && re.test(s) ? s : null;
37611
+ var kind = (k) => k === "intent" ? "intent" : "structural";
37612
+ var signalsOf = (c) => c && typeof c.commits === "number" && typeof c.fixCommits === "number" ? { commits: c.commits, fix_commits: c.fixCommits, risk: Object.fromEntries(Object.entries(c.risk ?? {}).filter(([, n]) => typeof n === "number" && n > 0).slice(0, 16)) } : null;
37613
+ function buildPhaseRecord(outcome, ctx) {
37614
+ const pushed = new Set(ctx.pushedFiles.map(norm2));
37615
+ const blocks = (f) => ctx.moment === "push" && f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file));
37616
+ const symbol = (s) => ident2(s, SYMBOL, 200);
37617
+ return {
37618
+ moment: ctx.moment,
37619
+ status: outcome.status,
37620
+ skip: outcome.skip ?? null,
37621
+ parent_run_id: ctx.parentRunId,
37622
+ target: outcome.target && symbol(outcome.target.symbol) && safeRepoPath(outcome.target.file) ? {
37623
+ file: safeRepoPath(outcome.target.file),
37624
+ symbol: symbol(outcome.target.symbol),
37625
+ lines: outcome.target.lines ?? null,
37626
+ score: Math.max(0, Math.min(1, outcome.target.score)),
37627
+ extent: ident2(outcome.target.extent, /^[a-z-]+(?::[a-z-]+)?$/, 60),
37628
+ signals: signalsOf(outcome.target.signals)
37629
+ } : null,
37630
+ candidates: (outcome.candidates ?? []).filter((c) => safeRepoPath(c.file)).slice(0, 12).map((c) => ({
37631
+ file: safeRepoPath(c.file),
37632
+ symbol: c.symbol === null ? null : symbol(c.symbol),
37633
+ score: c.score === null ? null : Math.max(0, Math.min(1, c.score)),
37634
+ criteria: c.criteria,
37635
+ reasked: c.reasked,
37636
+ signals: signalsOf(c)
37637
+ })),
37638
+ model: outcome.model && ident2(outcome.model.name, /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)*$/, 120) ? { name: outcome.model.name, rounds: Math.max(0, Math.min(20, outcome.model.rounds)) } : null,
37639
+ properties: (outcome.properties ?? []).filter((p) => ident2(p.id, IDENT3, 120)).slice(0, 16).map((p) => ({
37640
+ id: p.id,
37641
+ kind: kind(p.kind),
37642
+ basis: recordBasis(p.source),
37643
+ result: p.result,
37644
+ bound: p.bound ?? null,
37645
+ states: p.states ?? null
37646
+ })),
37647
+ findings: outcome.findings.filter((f) => ident2(f.property, IDENT3, 120) && symbol(f.symbol) && safeRepoPath(f.file)).slice(0, 8).map((f) => ({
37648
+ property: f.property,
37649
+ kind: kind(f.kind),
37650
+ trace: recordTrace(f.trace),
37651
+ file: safeRepoPath(f.file),
37652
+ symbol: f.symbol,
37653
+ verdict: f.verdict,
37654
+ waived: f.waived === true,
37655
+ blocked: blocks(f)
37656
+ })),
37657
+ grounding: outcome.grounding ? {
37658
+ sent_back: outcome.grounding.sentBack,
37659
+ dropped: outcome.grounding.dropped.filter((id) => ident2(id, IDENT3, 120)).slice(0, 16),
37660
+ trigger_missing: (outcome.grounding.triggerMissing ?? []).filter((id) => ident2(id, IDENT3, 120)).slice(0, 16)
37661
+ } : null,
37662
+ usage: {
37663
+ input_tokens: outcome.usage.inputTokens,
37664
+ output_tokens: outcome.usage.outputTokens,
37665
+ cost_usd: outcome.usage.costUsd,
37666
+ unpriced: outcome.usage.unpriced
37667
+ },
37668
+ duration_ms: Math.round(outcome.durationMs)
37669
+ };
37670
+ }
37671
+ async function postPhaseRecord(outcome, ctx, post) {
37672
+ try {
37673
+ const timeout = recordPostTimeout((post.now ?? Date.now)(), post.deadlineAt, post.timeoutMs ?? RECORD_TIMEOUT_MS);
37674
+ if (timeout === null) {
37675
+ logEvent("formal_record_skipped", { moment: ctx.moment, reason: "hook-deadline" });
37676
+ return null;
37677
+ }
37678
+ const res = await apiRequest({
37679
+ method: "POST",
37680
+ path: "/prove/record",
37681
+ serviceUrl: post.serviceUrl,
37682
+ token: post.token,
37683
+ body: buildPhaseRecord(outcome, ctx),
37684
+ timeout,
37685
+ cmd: "prove-record"
37686
+ });
37687
+ if (!res.ok) {
37688
+ logEvent("formal_record_failed", { moment: ctx.moment, category: res.category ?? "unknown", http_status: res.http_status ?? null });
37689
+ return null;
37690
+ }
37691
+ const runId = typeof res.data?.run_id === "string" ? res.data.run_id : null;
37692
+ logEvent("formal_record", { moment: ctx.moment, run_id: runId });
37693
+ return runId;
37694
+ } catch (err2) {
37695
+ logEvent("formal_record_failed", { moment: ctx.moment, category: "exception", name: err2?.constructor?.name ?? "Error" });
37696
+ return null;
37697
+ }
37698
+ }
37699
+
37354
37700
  // src/commands/guard.ts
37355
37701
  var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
37356
37702
  var WRITERS_BUDGET_MS = 1500;
37357
37703
  var EXCERPT_MAX_LINES2 = 30;
37358
37704
  var VENDORED_READ_MAX_BYTES = 256 * 1024;
37359
37705
  var GUARD_BLOCK_CAP = 2;
37360
- var GUARD_ITER_FILE = (0, import_node_path48.join)(VERITY_DIR, ".guard-iteration");
37706
+ var GUARD_ITER_FILE = (0, import_node_path51.join)(VERITY_DIR, ".guard-iteration");
37361
37707
  function readPreToolUseStdin() {
37362
37708
  const empty = { command: "", cwd: null, sessionId: null };
37363
37709
  return new Promise((resolve9) => {
@@ -37402,7 +37748,7 @@ function readPreToolUseStdin() {
37402
37748
  }
37403
37749
  function readIterMap() {
37404
37750
  try {
37405
- const raw = JSON.parse((0, import_node_fs61.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37751
+ const raw = JSON.parse((0, import_node_fs63.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37406
37752
  if (raw && typeof raw === "object") {
37407
37753
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
37408
37754
  return { [raw.moment]: raw.count };
@@ -37422,10 +37768,10 @@ function readIter(moment) {
37422
37768
  }
37423
37769
  function writeIter(moment, count) {
37424
37770
  try {
37425
- (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37771
+ (0, import_node_fs63.mkdirSync)(VERITY_DIR, { recursive: true });
37426
37772
  const map = readIterMap();
37427
37773
  map[moment] = count;
37428
- (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37774
+ (0, import_node_fs63.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37429
37775
  } catch {
37430
37776
  }
37431
37777
  }
@@ -37435,10 +37781,10 @@ function resetIter(moment) {
37435
37781
  if (!(moment in map)) return;
37436
37782
  delete map[moment];
37437
37783
  if (Object.keys(map).length === 0) {
37438
- if ((0, import_node_fs61.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs61.unlinkSync)(GUARD_ITER_FILE);
37784
+ if ((0, import_node_fs63.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs63.unlinkSync)(GUARD_ITER_FILE);
37439
37785
  } else {
37440
- (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37441
- (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37786
+ (0, import_node_fs63.mkdirSync)(VERITY_DIR, { recursive: true });
37787
+ (0, import_node_fs63.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37442
37788
  }
37443
37789
  } catch {
37444
37790
  }
@@ -37508,7 +37854,7 @@ function hasBlockingFinding(response, sentFiles) {
37508
37854
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
37509
37855
  const analyzable = filterAnalyzable(files);
37510
37856
  const securityFiles = filterSecurity(files);
37511
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs61.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
37857
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs63.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
37512
37858
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
37513
37859
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
37514
37860
  const requestBody = {
@@ -37521,7 +37867,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
37521
37867
  agent_harness: "claude-code",
37522
37868
  // Prefer the session id Claude Code passes on the hook payload; fall back
37523
37869
  // to the env var, then 'unknown'.
37524
- session_id: sessionId ?? process.env.CLAUDE_SESSION_ID ?? "unknown",
37870
+ session_id: sessionId ?? envSessionId() ?? "unknown",
37525
37871
  trigger,
37526
37872
  iteration: iter + 1
37527
37873
  }
@@ -37652,7 +37998,8 @@ function startAgentReview(input) {
37652
37998
  http: http2,
37653
37999
  executeTools: makeToolExecutor(ctx),
37654
38000
  startedAt: input.hookStartedAt,
37655
- deadlineMs: AGENT_DEADLINE_MS[input.moment],
38001
+ // The push's deadline follows the review effort (lib/effort.ts); the commit's never does.
38002
+ deadlineMs: input.moment === "pre-push" ? effortProfile(input.root).pushDeadlineMs : AGENT_DEADLINE_MS[input.moment],
37656
38003
  start: {
37657
38004
  moment: input.moment,
37658
38005
  iteration: input.iteration,
@@ -37677,7 +38024,8 @@ function startFormalPhase(input) {
37677
38024
  const env = process.env.VERITY_GIT_MOMENT_FORMAL;
37678
38025
  if (env === "off") return null;
37679
38026
  if (env !== "push" && readProjectConfig().formal !== "push") return null;
37680
- const deadlineAt = input.hookStartedAt + AGENT_DEADLINE_MS["pre-push"] - 1e4;
38027
+ const profile = effortProfile(input.root);
38028
+ const deadlineAt = input.hookStartedAt + profile.pushDeadlineMs - 1e4;
37681
38029
  const ig = loadVerityIgnore();
37682
38030
  const files = input.files.filter((f) => !isVerityOwnedPath(f) && !isIgnored3(ig, f));
37683
38031
  let changedLines = /* @__PURE__ */ new Map();
@@ -37699,9 +38047,9 @@ function startFormalPhase(input) {
37699
38047
  return { ok: true, content };
37700
38048
  } : void 0;
37701
38049
  const run4 = async () => {
37702
- const prep = await prepareFormalPhase(input.root, process.env, input.auth, readSource, withoutPaths(tip ? revisionSource(input.root, tip) : worktreeSource(input.root), isDeniedPath));
38050
+ const prep = await prepareFormalPhase(input.root, process.env, input.auth, readSource, withoutPaths(tip ? revisionSource(input.root, tip) : worktreeSource(input.root), isDeniedPath), { tier: profile.formal.tier });
37703
38051
  if (!prep.ok) return skippedOutcome(prep.skip, prep.detail);
37704
- return runFormalPhaseWithin({ root: input.root, files, changedLines, deadlineAt, deps: prep.deps });
38052
+ return runFormalPhaseWithin({ root: input.root, files, changedLines, deadlineAt, deps: prep.deps, minScore: profile.formal.minScore, maxRounds: profile.formal.maxRounds, costCapUsd: profile.formal.costCapUsd, maxTargets: profile.formal.maxTargets, relaxedGates: profile.formal.relaxedGates, dailyCap: profile.formal.dailyModels, dailyCostCapUsd: profile.formal.dailyCostUsd });
37705
38053
  };
37706
38054
  return run4().catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200)));
37707
38055
  }
@@ -37893,6 +38241,9 @@ async function runGuard(opts, globals) {
37893
38241
  rounds: formalOutcome.model?.rounds ?? null,
37894
38242
  properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
37895
38243
  findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
38244
+ // Review effort "max" models more than one function: each one, and why the search stopped early.
38245
+ targets: (formalOutcome.targets ?? []).map((t) => `${t.file}#${t.symbol}:${t.status}${t.skip ? `(${t.skip})` : ""}`),
38246
+ stopped_at: formalOutcome.stoppedAt?.skip ?? null,
37896
38247
  // Decision 81: what each property rests on (a rule, or "line"), what was
37897
38248
  // sent back or dropped as ungrounded, and which counterexamples lack their
37898
38249
  // property's trigger (shadow). Ids and rule names only, never code.
@@ -37925,6 +38276,13 @@ async function runGuard(opts, globals) {
37925
38276
  const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
37926
38277
  mergeFormalFindings(response, formalOutcome, files);
37927
38278
  decision = response.gate_decision ?? "(unrecognised)";
38279
+ if (formalOutcome) {
38280
+ await postPhaseRecord(formalOutcome, {
38281
+ moment: "push",
38282
+ parentRunId: typeof response.run_id === "string" ? response.run_id : null,
38283
+ pushedFiles: files
38284
+ }, { serviceUrl: urlResult.data, token: tokenResult.data.token, deadlineAt: guardRecordDeadline(hookStartedAt) });
38285
+ }
37928
38286
  if (!result.ok) {
37929
38287
  const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
37930
38288
  if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
@@ -38042,7 +38400,7 @@ function writeBlockMessage(moment, response, covDetail) {
38042
38400
 
38043
38401
  // src/commands/ignore.ts
38044
38402
  function registerIgnoreCommand(program2) {
38045
- const ignore = program2.command("ignore").description("Declare the next turn (or a short window) as housekeeping \u2014 no review needed").option("--turn", "Cover the next turn only (the default)").option("--for <duration>", "Cover a window: 30m, 45s, 1h (max 60m)").option("--reason <reason>", "Why this window needs no review \u2014 required, and recorded").option("--agent", "Mark the declaration as agent-invoked (a ledger label, not a permission)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID)").option("--json", "Output raw JSON").action(async (opts) => {
38403
+ const ignore = program2.command("ignore").description("Declare the next turn (or a short window) as housekeeping \u2014 no review needed").option("--turn", "Cover the next turn only (the default)").option("--for <duration>", "Cover a window: 30m, 45s, 1h (max 60m)").option("--reason <reason>", "Why this window needs no review \u2014 required, and recorded").option("--agent", "Mark the declaration as agent-invoked (a ledger label, not a permission)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").option("--json", "Output raw JSON").action(async (opts) => {
38046
38404
  const globals = program2.opts();
38047
38405
  const now = Math.floor(Date.now() / 1e3);
38048
38406
  const reason = opts.reason?.trim();
@@ -38069,7 +38427,7 @@ function registerIgnoreCommand(program2) {
38069
38427
  }
38070
38428
  const tokenResult = await resolveToken(globals.token);
38071
38429
  const token = tokenResult.ok ? tokenResult.data.token : void 0;
38072
- const sessionId = opts.sessionId || process.env.CLAUDE_SESSION_ID || void 0;
38430
+ const sessionId = opts.sessionId || envSessionId();
38073
38431
  const keys = ignoreStateKeys(token, sessionId);
38074
38432
  const existing = resolveIgnoreState(keys);
38075
38433
  const spent = existing?.state.spent ?? 0;
@@ -38115,11 +38473,11 @@ function registerIgnoreCommand(program2) {
38115
38473
  printInfo(`Verity will skip ${window2} \u2014 "${reason}" (${spent + 1}/${IGNORE_BUDGET} this session).`);
38116
38474
  printInfo("It covers turns that author nothing. If anything is written, the declaration voids and the review runs.");
38117
38475
  });
38118
- ignore.command("clear").description("Cancel the active declaration (the spent budget is not refunded)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID)").action(async (opts) => {
38476
+ ignore.command("clear").description("Cancel the active declaration (the spent budget is not refunded)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").action(async (opts) => {
38119
38477
  const globals = program2.opts();
38120
38478
  const tokenResult = await resolveToken(globals.token);
38121
38479
  const token = tokenResult.ok ? tokenResult.data.token : void 0;
38122
- const sessionId = opts.sessionId || process.env.CLAUDE_SESSION_ID || void 0;
38480
+ const sessionId = opts.sessionId || envSessionId();
38123
38481
  const found = resolveIgnoreState(ignoreStateKeys(token, sessionId));
38124
38482
  const active = resolveActive(found?.state ?? null, Math.floor(Date.now() / 1e3));
38125
38483
  if (!found || !active) {
@@ -38134,7 +38492,7 @@ function registerIgnoreCommand(program2) {
38134
38492
 
38135
38493
  // src/commands/waive.ts
38136
38494
  var import_node_crypto20 = require("node:crypto");
38137
- var import_node_fs62 = require("node:fs");
38495
+ var import_node_fs64 = require("node:fs");
38138
38496
  function registerWaiveCommand(program2) {
38139
38497
  program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
38140
38498
  const globals = program2.opts();
@@ -38163,7 +38521,7 @@ function registerWaiveCommand(program2) {
38163
38521
  if (opts.file) {
38164
38522
  body2.file = opts.file;
38165
38523
  try {
38166
- body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs62.readFileSync)(opts.file)).digest("hex");
38524
+ body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs64.readFileSync)(opts.file)).digest("hex");
38167
38525
  } catch {
38168
38526
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
38169
38527
  process.exit(1);
@@ -38188,10 +38546,10 @@ function registerWaiveCommand(program2) {
38188
38546
  }
38189
38547
 
38190
38548
  // src/commands/init.ts
38191
- var import_node_fs67 = require("node:fs");
38549
+ var import_node_fs69 = require("node:fs");
38192
38550
  var import_promises20 = require("node:fs/promises");
38193
- var import_yaml6 = __toESM2(require_dist());
38194
- var import_node_path52 = require("node:path");
38551
+ var import_yaml7 = __toESM2(require_dist());
38552
+ var import_node_path55 = require("node:path");
38195
38553
  var import_node_os11 = require("node:os");
38196
38554
  var import_node_child_process19 = require("node:child_process");
38197
38555
 
@@ -38271,7 +38629,7 @@ function printPhase(n, of, title, subtitle) {
38271
38629
  }
38272
38630
 
38273
38631
  // src/commands/doctor.ts
38274
- var import_node_fs63 = require("node:fs");
38632
+ var import_node_fs65 = require("node:fs");
38275
38633
 
38276
38634
  // src/lib/prereqs.ts
38277
38635
  var import_node_child_process16 = require("node:child_process");
@@ -38479,11 +38837,11 @@ async function buildReport() {
38479
38837
  const hooks = wiring.status;
38480
38838
  const provenance = cliProvenance();
38481
38839
  const telemetry = await checkTelemetry();
38482
- const hasConfig = (0, import_node_fs63.existsSync)(projectPath(CODACY_CONFIG_FILE));
38840
+ const hasConfig = (0, import_node_fs65.existsSync)(projectPath(CODACY_CONFIG_FILE));
38483
38841
  const artifacts = {
38484
- standard: (0, import_node_fs63.existsSync)(projectPath(STANDARD_FILE)),
38842
+ standard: (0, import_node_fs65.existsSync)(projectPath(STANDARD_FILE)),
38485
38843
  analysisConfig: hasConfig,
38486
- verityMd: (0, import_node_fs63.existsSync)(projectPath(VERITY_MD_FILE)),
38844
+ verityMd: (0, import_node_fs65.existsSync)(projectPath(VERITY_MD_FILE)),
38487
38845
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
38488
38846
  };
38489
38847
  const next = [];
@@ -38642,8 +39000,8 @@ function registerDoctorCommand(program2) {
38642
39000
  }
38643
39001
 
38644
39002
  // src/commands/migrate.ts
38645
- var import_node_fs64 = require("node:fs");
38646
- var import_node_path49 = require("node:path");
39003
+ var import_node_fs66 = require("node:fs");
39004
+ var import_node_path52 = require("node:path");
38647
39005
  var import_node_child_process17 = require("node:child_process");
38648
39006
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
38649
39007
  function defaultNpmRemover(pkg) {
@@ -38680,12 +39038,12 @@ async function runMigration(opts = {}) {
38680
39038
  return { actions, migrated: actions.length > 0 };
38681
39039
  }
38682
39040
  function migrateProjectDir(root, actions) {
38683
- const gateDir = (0, import_node_path49.join)(root, ".gate");
38684
- const verityDir = (0, import_node_path49.join)(root, ".verity");
38685
- if ((0, import_node_fs64.existsSync)(gateDir) && !(0, import_node_fs64.existsSync)(verityDir)) {
39041
+ const gateDir = (0, import_node_path52.join)(root, ".gate");
39042
+ const verityDir = (0, import_node_path52.join)(root, ".verity");
39043
+ if ((0, import_node_fs66.existsSync)(gateDir) && !(0, import_node_fs66.existsSync)(verityDir)) {
38686
39044
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
38687
39045
  }
38688
- if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
39046
+ if ((0, import_node_fs66.existsSync)(gateDir) && (0, import_node_fs66.existsSync)(verityDir)) {
38689
39047
  return migrateProjectDirCarry(gateDir, verityDir, actions);
38690
39048
  }
38691
39049
  return false;
@@ -38706,13 +39064,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
38706
39064
  }
38707
39065
  }
38708
39066
  if (moved) {
38709
- if ((0, import_node_fs64.existsSync)(gateDir)) {
39067
+ if ((0, import_node_fs66.existsSync)(gateDir)) {
38710
39068
  const carried = carryLegacyContents(gateDir, verityDir);
38711
39069
  if (carried > 0) {
38712
39070
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
38713
39071
  }
38714
39072
  try {
38715
- (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
39073
+ (0, import_node_fs66.rmSync)(gateDir, { recursive: true, force: true });
38716
39074
  } catch {
38717
39075
  }
38718
39076
  }
@@ -38728,18 +39086,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
38728
39086
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
38729
39087
  }
38730
39088
  try {
38731
- (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
39089
+ (0, import_node_fs66.rmSync)(gateDir, { recursive: true, force: true });
38732
39090
  } catch {
38733
39091
  }
38734
39092
  return carried > 0;
38735
39093
  }
38736
39094
  function migrateGlobalCredentials(home, actions) {
38737
39095
  if (!home) return;
38738
- const gateCreds = (0, import_node_path49.join)(home, ".gate", "credentials");
38739
- const verityCreds = (0, import_node_path49.join)(home, ".verity", "credentials");
38740
- if (!(0, import_node_fs64.existsSync)(gateCreds)) return;
38741
- if (!(0, import_node_fs64.existsSync)(verityCreds)) {
38742
- (0, import_node_fs64.mkdirSync)((0, import_node_path49.join)(home, ".verity"), { recursive: true });
39096
+ const gateCreds = (0, import_node_path52.join)(home, ".gate", "credentials");
39097
+ const verityCreds = (0, import_node_path52.join)(home, ".verity", "credentials");
39098
+ if (!(0, import_node_fs66.existsSync)(gateCreds)) return;
39099
+ if (!(0, import_node_fs66.existsSync)(verityCreds)) {
39100
+ (0, import_node_fs66.mkdirSync)((0, import_node_path52.join)(home, ".verity"), { recursive: true });
38743
39101
  moveFile(gateCreds, verityCreds);
38744
39102
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
38745
39103
  return;
@@ -38761,8 +39119,8 @@ async function migrateLegacyHooks(root, actions) {
38761
39119
  }
38762
39120
  }
38763
39121
  async function migrateClaudeMd(root, actions) {
38764
- const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38765
- const hadLegacyBlock = (0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
39122
+ const claudeMd = (0, import_node_path52.join)(root, "CLAUDE.md");
39123
+ const hadLegacyBlock = (0, import_node_fs66.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38766
39124
  if (!hadLegacyBlock) return;
38767
39125
  try {
38768
39126
  await ensureClaudeMdPointer(root);
@@ -38772,9 +39130,9 @@ async function migrateClaudeMd(root, actions) {
38772
39130
  }
38773
39131
  }
38774
39132
  function migrateStandardFile(root, actions) {
38775
- const gateMd = (0, import_node_path49.join)(root, "GATE.md");
38776
- const verityMd = (0, import_node_path49.join)(root, "VERITY.md");
38777
- if (!(0, import_node_fs64.existsSync)(gateMd) || (0, import_node_fs64.existsSync)(verityMd)) return;
39133
+ const gateMd = (0, import_node_path52.join)(root, "GATE.md");
39134
+ const verityMd = (0, import_node_path52.join)(root, "VERITY.md");
39135
+ if (!(0, import_node_fs66.existsSync)(gateMd) || (0, import_node_fs66.existsSync)(verityMd)) return;
38778
39136
  let moved = false;
38779
39137
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
38780
39138
  try {
@@ -38786,12 +39144,12 @@ function migrateStandardFile(root, actions) {
38786
39144
  if (!moved) moveFile(gateMd, verityMd);
38787
39145
  const content = readFileSyncSafe(verityMd);
38788
39146
  const refreshed = content.split("GATE.md").join("VERITY.md");
38789
- if (refreshed !== content) (0, import_node_fs64.writeFileSync)(verityMd, refreshed);
39147
+ if (refreshed !== content) (0, import_node_fs66.writeFileSync)(verityMd, refreshed);
38790
39148
  actions.push("Renamed GATE.md \u2192 VERITY.md");
38791
39149
  }
38792
39150
  async function migrateTelemetryHeaders(root, actions) {
38793
- const file = (0, import_node_path49.join)(root, ".claude", "settings.local.json");
38794
- if (!(0, import_node_fs64.existsSync)(file)) return;
39151
+ const file = (0, import_node_path52.join)(root, ".claude", "settings.local.json");
39152
+ if (!(0, import_node_fs66.existsSync)(file)) return;
38795
39153
  let settings;
38796
39154
  try {
38797
39155
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -38838,15 +39196,15 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
38838
39196
  toAppend.push(line2.replace(/\r$/, ""));
38839
39197
  }
38840
39198
  if (toAppend.length > 0) {
38841
- const sep6 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
38842
- (0, import_node_fs64.writeFileSync)(verityCreds, verityContent + sep6 + toAppend.join("\n") + "\n");
39199
+ const sep7 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
39200
+ (0, import_node_fs66.writeFileSync)(verityCreds, verityContent + sep7 + toAppend.join("\n") + "\n");
38843
39201
  }
38844
- (0, import_node_fs64.rmSync)(gateCreds, { force: true });
39202
+ (0, import_node_fs66.rmSync)(gateCreds, { force: true });
38845
39203
  return toAppend.length;
38846
39204
  }
38847
39205
  function readFileSyncSafe(path) {
38848
39206
  try {
38849
- return (0, import_node_fs64.readFileSync)(path, "utf-8");
39207
+ return (0, import_node_fs66.readFileSync)(path, "utf-8");
38850
39208
  } catch {
38851
39209
  return "";
38852
39210
  }
@@ -38861,35 +39219,35 @@ function hasStagedChanges(root) {
38861
39219
  }
38862
39220
  function moveDir(from, to) {
38863
39221
  try {
38864
- (0, import_node_fs64.renameSync)(from, to);
39222
+ (0, import_node_fs66.renameSync)(from, to);
38865
39223
  } catch (err2) {
38866
39224
  if (err2.code !== "EXDEV") throw err2;
38867
- (0, import_node_fs64.cpSync)(from, to, { recursive: true });
38868
- (0, import_node_fs64.rmSync)(from, { recursive: true, force: true });
39225
+ (0, import_node_fs66.cpSync)(from, to, { recursive: true });
39226
+ (0, import_node_fs66.rmSync)(from, { recursive: true, force: true });
38869
39227
  }
38870
39228
  }
38871
39229
  function moveFile(from, to) {
38872
39230
  try {
38873
- (0, import_node_fs64.renameSync)(from, to);
39231
+ (0, import_node_fs66.renameSync)(from, to);
38874
39232
  } catch (err2) {
38875
39233
  if (err2.code !== "EXDEV") throw err2;
38876
- (0, import_node_fs64.cpSync)(from, to);
38877
- (0, import_node_fs64.rmSync)(from, { force: true });
39234
+ (0, import_node_fs66.cpSync)(from, to);
39235
+ (0, import_node_fs66.rmSync)(from, { force: true });
38878
39236
  }
38879
39237
  }
38880
39238
  function carryLegacyContents(gateDir, verityDir) {
38881
39239
  let copied = 0;
38882
39240
  const walk2 = (relDir) => {
38883
- const srcDir = (0, import_node_path49.join)(gateDir, relDir);
38884
- for (const entry of (0, import_node_fs64.readdirSync)(srcDir)) {
38885
- const rel = relDir ? (0, import_node_path49.join)(relDir, entry) : entry;
38886
- const src = (0, import_node_path49.join)(gateDir, rel);
38887
- const dest = (0, import_node_path49.join)(verityDir, rel);
38888
- if ((0, import_node_fs64.statSync)(src).isDirectory()) {
39241
+ const srcDir = (0, import_node_path52.join)(gateDir, relDir);
39242
+ for (const entry of (0, import_node_fs66.readdirSync)(srcDir)) {
39243
+ const rel = relDir ? (0, import_node_path52.join)(relDir, entry) : entry;
39244
+ const src = (0, import_node_path52.join)(gateDir, rel);
39245
+ const dest = (0, import_node_path52.join)(verityDir, rel);
39246
+ if ((0, import_node_fs66.statSync)(src).isDirectory()) {
38889
39247
  walk2(rel);
38890
- } else if (!(0, import_node_fs64.existsSync)(dest)) {
38891
- (0, import_node_fs64.mkdirSync)((0, import_node_path49.dirname)(dest), { recursive: true });
38892
- (0, import_node_fs64.cpSync)(src, dest);
39248
+ } else if (!(0, import_node_fs66.existsSync)(dest)) {
39249
+ (0, import_node_fs66.mkdirSync)((0, import_node_path52.dirname)(dest), { recursive: true });
39250
+ (0, import_node_fs66.cpSync)(src, dest);
38893
39251
  copied++;
38894
39252
  }
38895
39253
  }
@@ -38898,22 +39256,22 @@ function carryLegacyContents(gateDir, verityDir) {
38898
39256
  return copied;
38899
39257
  }
38900
39258
  async function needsMigration(root = repoRoot()) {
38901
- const gateDir = (0, import_node_path49.join)(root, ".gate");
38902
- const verityDir = (0, import_node_path49.join)(root, ".verity");
38903
- if ((0, import_node_fs64.existsSync)(gateDir) && !(0, import_node_fs64.existsSync)(verityDir)) return true;
38904
- if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
38905
- if ((0, import_node_fs64.existsSync)((0, import_node_path49.join)(gateDir, "credentials")) && !(0, import_node_fs64.existsSync)((0, import_node_path49.join)(verityDir, "credentials"))) {
39259
+ const gateDir = (0, import_node_path52.join)(root, ".gate");
39260
+ const verityDir = (0, import_node_path52.join)(root, ".verity");
39261
+ if ((0, import_node_fs66.existsSync)(gateDir) && !(0, import_node_fs66.existsSync)(verityDir)) return true;
39262
+ if ((0, import_node_fs66.existsSync)(gateDir) && (0, import_node_fs66.existsSync)(verityDir)) {
39263
+ if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(gateDir, "credentials")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(verityDir, "credentials"))) {
38906
39264
  return true;
38907
39265
  }
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"))) {
39266
+ if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(gateDir, "memory")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(verityDir, "memory"))) {
38909
39267
  return true;
38910
39268
  }
38911
39269
  }
38912
- const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38913
- if ((0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
39270
+ const claudeMd = (0, import_node_path52.join)(root, "CLAUDE.md");
39271
+ if ((0, import_node_fs66.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38914
39272
  return true;
38915
39273
  }
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"))) {
39274
+ if ((0, import_node_fs66.existsSync)((0, import_node_path52.join)(root, "GATE.md")) && !(0, import_node_fs66.existsSync)((0, import_node_path52.join)(root, "VERITY.md"))) {
38917
39275
  return true;
38918
39276
  }
38919
39277
  if (await hasLegacyHooksAt(root)) return true;
@@ -39194,11 +39552,11 @@ async function promptMultiSelect(question, choices, fallback) {
39194
39552
  }
39195
39553
 
39196
39554
  // src/lib/prove/lean-install.ts
39197
- var import_node_fs65 = require("node:fs");
39555
+ var import_node_fs67 = require("node:fs");
39198
39556
  var import_node_crypto21 = require("node:crypto");
39199
39557
  var import_node_child_process18 = require("node:child_process");
39200
39558
  var import_node_os10 = require("node:os");
39201
- var import_node_path50 = require("node:path");
39559
+ var import_node_path53 = require("node:path");
39202
39560
  var import_promises18 = require("node:stream/promises");
39203
39561
  var import_node_stream = require("node:stream");
39204
39562
  var RELEASES = "https://releases.lean-lang.org/lean4";
@@ -39209,10 +39567,10 @@ function freeBytes(dir) {
39209
39567
  let d = dir;
39210
39568
  for (let i2 = 0; i2 < 64; i2++) {
39211
39569
  try {
39212
- const st = (0, import_node_fs65.statfsSync)(d);
39570
+ const st = (0, import_node_fs67.statfsSync)(d);
39213
39571
  return Number(st.bavail) * Number(st.bsize);
39214
39572
  } catch {
39215
- const up = (0, import_node_path50.join)(d, "..");
39573
+ const up = (0, import_node_path53.join)(d, "..");
39216
39574
  if (up === d) return null;
39217
39575
  d = up;
39218
39576
  }
@@ -39234,7 +39592,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
39234
39592
  function sha256File(path) {
39235
39593
  return new Promise((resolve9, reject) => {
39236
39594
  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);
39595
+ (0, import_node_fs67.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
39238
39596
  });
39239
39597
  }
39240
39598
  async function verifyDownload(zip, asset, version = pinnedVersion()) {
@@ -39254,7 +39612,7 @@ function leanAssetName(version = pinnedVersion()) {
39254
39612
  return suffix ? `lean-${v}-${suffix}.zip` : null;
39255
39613
  }
39256
39614
  function pinnedVersionDir(env = process.env) {
39257
- return (0, import_node_path50.join)(verityLeanHome(env), pinnedVersion());
39615
+ return (0, import_node_path53.join)(verityLeanHome(env), pinnedVersion());
39258
39616
  }
39259
39617
  function lakeBinary() {
39260
39618
  return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
@@ -39265,12 +39623,12 @@ function unzip(zip, dest) {
39265
39623
  for (const [cmd, args2] of attempts) {
39266
39624
  try {
39267
39625
  (0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
39268
- if ((0, import_node_fs65.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
39626
+ if ((0, import_node_fs67.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
39269
39627
  errors.push(`${cmd}: produced nothing`);
39270
39628
  } catch (err2) {
39271
39629
  errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
39272
39630
  try {
39273
- for (const e of (0, import_node_fs65.readdirSync)(dest)) (0, import_node_fs65.rmSync)((0, import_node_path50.join)(dest, e), { recursive: true, force: true });
39631
+ for (const e of (0, import_node_fs67.readdirSync)(dest)) (0, import_node_fs67.rmSync)((0, import_node_path53.join)(dest, e), { recursive: true, force: true });
39274
39632
  } catch {
39275
39633
  }
39276
39634
  }
@@ -39296,7 +39654,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
39296
39654
  seen += chunk.length;
39297
39655
  onProgress(seen, total);
39298
39656
  });
39299
- await (0, import_promises18.pipeline)(stream, (0, import_node_fs65.createWriteStream)(dest), { signal: ctrl.signal });
39657
+ await (0, import_promises18.pipeline)(stream, (0, import_node_fs67.createWriteStream)(dest), { signal: ctrl.signal });
39300
39658
  } catch (err2) {
39301
39659
  if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
39302
39660
  throw err2;
@@ -39346,10 +39704,10 @@ async function installLean(opts = {}) {
39346
39704
  const gb = (n) => (n / 1024 ** 3).toFixed(1);
39347
39705
  return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
39348
39706
  }
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);
39707
+ const tmp = (0, import_node_path53.join)(home, ".tmp");
39708
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39709
+ (0, import_node_fs67.mkdirSync)(tmp, { recursive: true });
39710
+ const zip = (0, import_node_path53.join)(tmp, asset);
39353
39711
  say(`downloading ${url}`);
39354
39712
  let lastPct = -1;
39355
39713
  try {
@@ -39362,41 +39720,41 @@ async function installLean(opts = {}) {
39362
39720
  }
39363
39721
  });
39364
39722
  } catch (err2) {
39365
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39723
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39366
39724
  return { ok: false, error: err2.message };
39367
39725
  }
39368
39726
  say("verifying checksum");
39369
39727
  const verified = await verifyDownload(zip, asset);
39370
39728
  if (!verified.ok) {
39371
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39729
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39372
39730
  return { ok: false, error: verified.error };
39373
39731
  }
39374
39732
  say("unpacking (this takes a minute)");
39375
- const unpack = (0, import_node_path50.join)(tmp, "unpack");
39376
- (0, import_node_fs65.mkdirSync)(unpack);
39733
+ const unpack = (0, import_node_path53.join)(tmp, "unpack");
39734
+ (0, import_node_fs67.mkdirSync)(unpack);
39377
39735
  const unpacked = unzip(zip, unpack);
39378
39736
  if (!unpacked.ok) {
39379
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39737
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39380
39738
  return { ok: false, error: `unpack failed: ${unpacked.error}` };
39381
39739
  }
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 });
39740
+ const entries = (0, import_node_fs67.readdirSync)(unpack);
39741
+ const top = entries.length === 1 && (0, import_node_fs67.statSync)((0, import_node_path53.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path53.join)(unpack, entries[0]) : unpack;
39742
+ if (!(0, import_node_fs67.existsSync)((0, import_node_path53.join)(top, "bin", lakeBinary()))) {
39743
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39386
39744
  return { ok: false, error: "the archive did not contain bin/lake" };
39387
39745
  }
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 });
39746
+ (0, import_node_fs67.rmSync)(dir, { recursive: true, force: true });
39747
+ (0, import_node_fs67.mkdirSync)(home, { recursive: true });
39748
+ (0, import_node_fs67.renameSync)(top, dir);
39749
+ (0, import_node_fs67.rmSync)(tmp, { recursive: true, force: true });
39392
39750
  return { ok: true, dir };
39393
39751
  }
39394
39752
 
39395
39753
  // src/lib/remote-config.ts
39396
- var import_node_fs66 = require("node:fs");
39754
+ var import_node_fs68 = require("node:fs");
39397
39755
  var import_promises19 = require("node:fs/promises");
39398
- var import_node_path51 = require("node:path");
39399
- var import_yaml5 = __toESM2(require_dist());
39756
+ var import_node_path54 = require("node:path");
39757
+ var import_yaml6 = __toESM2(require_dist());
39400
39758
  var IGNORE_RIDER = "verityignore";
39401
39759
  async function fetchRemoteSetup(opts) {
39402
39760
  const standard = await apiRequest({
@@ -39436,11 +39794,11 @@ async function adoptRemoteSetup(found, opts) {
39436
39794
  const content = { ...found.standard.content };
39437
39795
  const rider = typeof content[IGNORE_RIDER] === "string" ? content[IGNORE_RIDER] : null;
39438
39796
  delete content[IGNORE_RIDER];
39439
- await writeOut(STANDARD_FILE, (0, import_yaml5.stringify)(content));
39797
+ await writeOut(STANDARD_FILE, (0, import_yaml6.stringify)(content));
39440
39798
  written.push(STANDARD_FILE);
39441
39799
  if (rider !== null) {
39442
39800
  const localIgnore = projectPath(VERITYIGNORE_FILE);
39443
- if (!(0, import_node_fs66.existsSync)(localIgnore)) {
39801
+ if (!(0, import_node_fs68.existsSync)(localIgnore)) {
39444
39802
  await writeOut(VERITYIGNORE_FILE, rider);
39445
39803
  written.push(VERITYIGNORE_FILE);
39446
39804
  } else {
@@ -39471,9 +39829,9 @@ async function adoptRemoteSetup(found, opts) {
39471
39829
  written.push(VERITY_MD_FILE);
39472
39830
  return { written, notes };
39473
39831
  }
39474
- async function writeOut(relative6, body2) {
39475
- const target = projectPath(relative6);
39476
- await (0, import_promises19.mkdir)((0, import_node_path51.dirname)(target), { recursive: true });
39832
+ async function writeOut(relative7, body2) {
39833
+ const target = projectPath(relative7);
39834
+ await (0, import_promises19.mkdir)((0, import_node_path54.dirname)(target), { recursive: true });
39477
39835
  await (0, import_promises19.writeFile)(target, body2);
39478
39836
  }
39479
39837
  function describeRemote(found) {
@@ -39590,15 +39948,15 @@ async function runOptionalAuth(resolution, opts = {}) {
39590
39948
  }
39591
39949
  function resolveDataDir2() {
39592
39950
  const candidates2 = [
39593
- (0, import_node_path52.join)(__dirname, "..", "data"),
39951
+ (0, import_node_path55.join)(__dirname, "..", "data"),
39594
39952
  // installed: node_modules/@codacy/verity-cli/data
39595
- (0, import_node_path52.join)(__dirname, "..", "..", "data"),
39953
+ (0, import_node_path55.join)(__dirname, "..", "..", "data"),
39596
39954
  // edge case: nested resolution
39597
- (0, import_node_path52.join)(process.cwd(), "cli", "data")
39955
+ (0, import_node_path55.join)(process.cwd(), "cli", "data")
39598
39956
  // local dev: running from repo root
39599
39957
  ];
39600
39958
  for (const candidate of candidates2) {
39601
- if ((0, import_node_fs67.existsSync)((0, import_node_path52.join)(candidate, "skills"))) {
39959
+ if ((0, import_node_fs69.existsSync)((0, import_node_path55.join)(candidate, "skills"))) {
39602
39960
  return candidate;
39603
39961
  }
39604
39962
  }
@@ -39614,9 +39972,9 @@ async function skillIsCurrent(src, dest) {
39614
39972
  const list2 = (dir) => {
39615
39973
  const out2 = [];
39616
39974
  const walk2 = (d, prefix) => {
39617
- for (const e of (0, import_node_fs67.readdirSync)(d, { withFileTypes: true })) {
39975
+ for (const e of (0, import_node_fs69.readdirSync)(d, { withFileTypes: true })) {
39618
39976
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
39619
- if (e.isDirectory()) walk2((0, import_node_path52.join)(d, e.name), rel);
39977
+ if (e.isDirectory()) walk2((0, import_node_path55.join)(d, e.name), rel);
39620
39978
  else if (e.isFile()) out2.push(rel);
39621
39979
  }
39622
39980
  };
@@ -39627,8 +39985,8 @@ async function skillIsCurrent(src, dest) {
39627
39985
  const shipped = list2(src);
39628
39986
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
39629
39987
  for (const rel of shipped) {
39630
- const a = await (0, import_promises20.readFile)((0, import_node_path52.join)(src, rel), "utf-8");
39631
- const b = await (0, import_promises20.readFile)((0, import_node_path52.join)(dest, rel), "utf-8");
39988
+ const a = await (0, import_promises20.readFile)((0, import_node_path55.join)(src, rel), "utf-8");
39989
+ const b = await (0, import_promises20.readFile)((0, import_node_path55.join)(dest, rel), "utf-8");
39632
39990
  if (a !== b) return false;
39633
39991
  }
39634
39992
  return true;
@@ -39724,7 +40082,7 @@ function parseTelemetryAnswer(raw) {
39724
40082
  return null;
39725
40083
  }
39726
40084
  function insideClaudeCode() {
39727
- return !!process.env.CLAUDECODE || !!process.env.CLAUDE_SESSION_ID;
40085
+ return !!process.env.CLAUDECODE || !!envSessionId();
39728
40086
  }
39729
40087
  function resumeDeferredPending(previous) {
39730
40088
  return previous?.telemetry === "deferred";
@@ -39831,13 +40189,13 @@ async function synthesizeLocally(opts) {
39831
40189
  async function healStaleAnalysisConfig(globals) {
39832
40190
  const configPath = projectPath(CODACY_CONFIG_FILE);
39833
40191
  const standardPath = projectPath(STANDARD_FILE);
39834
- if (!(0, import_node_fs67.existsSync)(configPath) || !(0, import_node_fs67.existsSync)(standardPath)) return;
40192
+ if (!(0, import_node_fs69.existsSync)(configPath) || !(0, import_node_fs69.existsSync)(standardPath)) return;
39835
40193
  const validation = validatePatternIds();
39836
40194
  if (validation.status !== "invalid") return;
39837
40195
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
39838
40196
  printWarn(" running silently with nothing enabled. Re-deriving it from your Standard\u2026");
39839
40197
  try {
39840
- const content = (0, import_yaml6.parse)(await (0, import_promises20.readFile)(standardPath, "utf-8"));
40198
+ const content = (0, import_yaml7.parse)(await (0, import_promises20.readFile)(standardPath, "utf-8"));
39841
40199
  const derived = await deriveConfigForStandard(content);
39842
40200
  for (const path of derived.written) printInfo(` ${path} \u2713 (re-derived)`);
39843
40201
  for (const note of derived.notes) printWarn(` ${note}`);
@@ -39928,17 +40286,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
39928
40286
  async function installSkills(force, step) {
39929
40287
  step("Installing skills");
39930
40288
  const dataDir = resolveDataDir2();
39931
- const skillsSource = (0, import_node_path52.join)(dataDir, "skills");
40289
+ const skillsSource = (0, import_node_path55.join)(dataDir, "skills");
39932
40290
  const skillsDest = ".claude/skills";
39933
40291
  let skillsInstalled = 0;
39934
40292
  for (const skill of SKILLS) {
39935
- const src = (0, import_node_path52.join)(skillsSource, skill);
39936
- const dest = (0, import_node_path52.join)(skillsDest, skill);
39937
- if (!(0, import_node_fs67.existsSync)(src)) {
40293
+ const src = (0, import_node_path55.join)(skillsSource, skill);
40294
+ const dest = (0, import_node_path55.join)(skillsDest, skill);
40295
+ if (!(0, import_node_fs69.existsSync)(src)) {
39938
40296
  printWarn(` Skill data not found: ${skill}`);
39939
40297
  continue;
39940
40298
  }
39941
- if ((0, import_node_fs67.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
40299
+ if ((0, import_node_fs69.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39942
40300
  skillsInstalled++;
39943
40301
  continue;
39944
40302
  }
@@ -40087,7 +40445,7 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
40087
40445
  if (!toolchain) {
40088
40446
  const dir = pinnedVersionDir();
40089
40447
  const home = (0, import_node_os11.homedir)();
40090
- const shown = dir.startsWith(home + import_node_path52.sep) ? `~${dir.slice(home.length)}` : dir;
40448
+ const shown = dir.startsWith(home + import_node_path55.sep) ? `~${dir.slice(home.length)}` : dir;
40091
40449
  console.log("");
40092
40450
  console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
40093
40451
  }
@@ -40146,7 +40504,7 @@ function registerInitCommand(program2) {
40146
40504
  const staleMarker = clearStalePluginMarker();
40147
40505
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
40148
40506
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
40149
- const isProject = projectMarkers.some((m) => (0, import_node_fs67.existsSync)(m));
40507
+ const isProject = projectMarkers.some((m) => (0, import_node_fs69.existsSync)(m));
40150
40508
  if (!isProject) {
40151
40509
  printError("No project detected in the current directory.");
40152
40510
  printInfo('Run "verity init" from your project root.');
@@ -40249,7 +40607,7 @@ function registerInitCommand(program2) {
40249
40607
  untrackMemory: opts.untrackMemory === true,
40250
40608
  untrackState: opts.untrackState === true
40251
40609
  });
40252
- const globalVerityDir = (0, import_node_path52.join)(process.env.HOME ?? "", ".verity");
40610
+ const globalVerityDir = (0, import_node_path55.join)(process.env.HOME ?? "", ".verity");
40253
40611
  await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
40254
40612
  console.log("");
40255
40613
  step("Wiring Claude Code hooks");
@@ -40324,7 +40682,7 @@ function registerInitCommand(program2) {
40324
40682
  }
40325
40683
  step("Your project's Standard");
40326
40684
  let haveStandard = false;
40327
- if ((0, import_node_fs67.existsSync)(projectPath(STANDARD_FILE))) {
40685
+ if ((0, import_node_fs69.existsSync)(projectPath(STANDARD_FILE))) {
40328
40686
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
40329
40687
  haveStandard = true;
40330
40688
  } else {
@@ -40354,7 +40712,7 @@ function registerInitCommand(program2) {
40354
40712
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
40355
40713
  init: {
40356
40714
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
40357
- cli_version: true ? "0.34.1" : "dev"
40715
+ cli_version: true ? "0.34.2-experimental.312358d" : "dev"
40358
40716
  }
40359
40717
  });
40360
40718
  } catch (err2) {
@@ -40404,8 +40762,8 @@ function registerInitCommand(program2) {
40404
40762
  }
40405
40763
 
40406
40764
  // src/commands/uninstall.ts
40407
- var import_node_fs68 = require("node:fs");
40408
- var import_node_path53 = require("node:path");
40765
+ var import_node_fs70 = require("node:fs");
40766
+ var import_node_path56 = require("node:path");
40409
40767
  function registerUninstallCommand(program2) {
40410
40768
  program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
40411
40769
  const dryRun = opts.dryRun ?? false;
@@ -40414,11 +40772,11 @@ function registerUninstallCommand(program2) {
40414
40772
  const actions = [];
40415
40773
  const skillsRoot = projectPath(".claude/skills");
40416
40774
  for (const name2 of PROJECT_SKILL_NAMES) {
40417
- const dir = (0, import_node_path53.join)(skillsRoot, name2);
40418
- if ((0, import_node_fs68.existsSync)(dir)) {
40775
+ const dir = (0, import_node_path56.join)(skillsRoot, name2);
40776
+ if ((0, import_node_fs70.existsSync)(dir)) {
40419
40777
  actions.push({
40420
40778
  label: `Remove .claude/skills/${name2}/`,
40421
- apply: () => (0, import_node_fs68.rmSync)(dir, { recursive: true, force: true })
40779
+ apply: () => (0, import_node_fs70.rmSync)(dir, { recursive: true, force: true })
40422
40780
  });
40423
40781
  }
40424
40782
  }
@@ -40432,24 +40790,24 @@ function registerUninstallCommand(program2) {
40432
40790
  });
40433
40791
  }
40434
40792
  const verityDir = projectPath(VERITY_DIR);
40435
- if ((0, import_node_fs68.existsSync)(verityDir)) {
40793
+ if ((0, import_node_fs70.existsSync)(verityDir)) {
40436
40794
  actions.push({
40437
40795
  label: `Remove ${VERITY_DIR}/`,
40438
- apply: () => (0, import_node_fs68.rmSync)(verityDir, { recursive: true, force: true })
40796
+ apply: () => (0, import_node_fs70.rmSync)(verityDir, { recursive: true, force: true })
40439
40797
  });
40440
40798
  }
40441
40799
  if (!keepVerityMd) {
40442
40800
  const verityMd = projectPath(VERITY_MD_FILE);
40443
- if ((0, import_node_fs68.existsSync)(verityMd)) {
40801
+ if ((0, import_node_fs70.existsSync)(verityMd)) {
40444
40802
  actions.push({
40445
40803
  label: `Remove ${VERITY_MD_FILE}`,
40446
- apply: () => (0, import_node_fs68.rmSync)(verityMd, { force: true })
40804
+ apply: () => (0, import_node_fs70.rmSync)(verityMd, { force: true })
40447
40805
  });
40448
40806
  }
40449
40807
  }
40450
40808
  const cleanupEmptyDir = (path) => {
40451
- if ((0, import_node_fs68.existsSync)(path) && (0, import_node_fs68.statSync)(path).isDirectory() && (0, import_node_fs68.readdirSync)(path).length === 0) {
40452
- (0, import_node_fs68.rmdirSync)(path);
40809
+ if ((0, import_node_fs70.existsSync)(path) && (0, import_node_fs70.statSync)(path).isDirectory() && (0, import_node_fs70.readdirSync)(path).length === 0) {
40810
+ (0, import_node_fs70.rmdirSync)(path);
40453
40811
  }
40454
40812
  };
40455
40813
  actions.push({
@@ -40460,11 +40818,11 @@ function registerUninstallCommand(program2) {
40460
40818
  }
40461
40819
  });
40462
40820
  const home = process.env.HOME ?? "";
40463
- const globalVerityDir = (0, import_node_path53.join)(home, ".verity");
40464
- if (purgeGlobal && (0, import_node_fs68.existsSync)(globalVerityDir)) {
40821
+ const globalVerityDir = (0, import_node_path56.join)(home, ".verity");
40822
+ if (purgeGlobal && (0, import_node_fs70.existsSync)(globalVerityDir)) {
40465
40823
  actions.push({
40466
40824
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
40467
- apply: () => (0, import_node_fs68.rmSync)(globalVerityDir, { recursive: true, force: true })
40825
+ apply: () => (0, import_node_fs70.rmSync)(globalVerityDir, { recursive: true, force: true })
40468
40826
  });
40469
40827
  }
40470
40828
  if (actions.length === 0) {
@@ -40491,9 +40849,26 @@ function registerUninstallCommand(program2) {
40491
40849
 
40492
40850
  // src/commands/task.ts
40493
40851
  function memoryPath() {
40494
- const sid = process.env.CLAUDE_SESSION_ID;
40852
+ const sid = envSessionId();
40495
40853
  return sid ? `/memory?session_id=${encodeURIComponent(sid)}` : "/memory";
40496
40854
  }
40855
+ var TASK_STATUSES = ["active", "closed", "merged"];
40856
+ var TASK_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
40857
+ function isTaskId(value) {
40858
+ return typeof value === "string" && TASK_ID.test(value);
40859
+ }
40860
+ function taskListPath(status) {
40861
+ if (status === void 0) return "/tasks";
40862
+ if (!TASK_STATUSES.includes(status)) return null;
40863
+ return `/tasks?status=${encodeURIComponent(status)}`;
40864
+ }
40865
+ function taskActionPath(taskId, action) {
40866
+ return isTaskId(taskId) ? `/tasks/${encodeURIComponent(taskId)}/${action}` : null;
40867
+ }
40868
+ function refuse(message) {
40869
+ printError(message);
40870
+ process.exit(1);
40871
+ }
40497
40872
  function timeAgo2(isoDate) {
40498
40873
  const ms = Date.now() - new Date(isoDate).getTime();
40499
40874
  const mins = Math.floor(ms / 6e4);
@@ -40521,10 +40896,11 @@ function registerTaskCommands(program2) {
40521
40896
  task.command("list").description("List tasks").option("--status <status>", "Filter by status (active, closed, merged)").action(async (opts) => {
40522
40897
  const globals = program2.opts();
40523
40898
  const { token, serviceUrl } = await getAuth(globals);
40524
- const statusParam = opts.status ? `?status=${opts.status}` : "";
40899
+ const listPath = taskListPath(opts.status);
40900
+ if (!listPath) refuse(`Unknown status ${JSON.stringify(String(opts.status).slice(0, 40))} \u2014 use one of: ${TASK_STATUSES.join(", ")}`);
40525
40901
  const result = await apiRequest({
40526
40902
  method: "GET",
40527
- path: `/tasks${statusParam}`,
40903
+ path: listPath,
40528
40904
  serviceUrl,
40529
40905
  token,
40530
40906
  verbose: globals.verbose,
@@ -40573,9 +40949,11 @@ function registerTaskCommands(program2) {
40573
40949
  }
40574
40950
  taskId = ct.id;
40575
40951
  }
40952
+ const closePath = taskActionPath(taskId, "close");
40953
+ if (!closePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
40576
40954
  const result = await apiRequest({
40577
40955
  method: "POST",
40578
- path: `/tasks/${taskId}/close`,
40956
+ path: closePath,
40579
40957
  serviceUrl,
40580
40958
  token,
40581
40959
  verbose: globals.verbose,
@@ -40622,9 +41000,11 @@ function registerTaskCommands(program2) {
40622
41000
  }
40623
41001
  taskId = ct.id;
40624
41002
  }
41003
+ const renamePath = taskActionPath(taskId, "rename");
41004
+ if (!renamePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
40625
41005
  const result = await apiRequest({
40626
41006
  method: "POST",
40627
- path: `/tasks/${taskId}/rename`,
41007
+ path: renamePath,
40628
41008
  serviceUrl,
40629
41009
  token,
40630
41010
  body: { label: label2.slice(0, 120) },
@@ -40639,6 +41019,9 @@ function registerTaskCommands(program2) {
40639
41019
  });
40640
41020
  task.command("merge <source> <target>").description("Merge source task into target task").action(async (source2, target) => {
40641
41021
  const globals = program2.opts();
41022
+ if (!isTaskId(source2) || !isTaskId(target)) {
41023
+ refuse("task merge takes two task ids (UUIDs): `verity task merge <source> <target>`");
41024
+ }
40642
41025
  const { token, serviceUrl } = await getAuth(globals);
40643
41026
  const result = await apiRequest({
40644
41027
  method: "POST",
@@ -40658,8 +41041,8 @@ function registerTaskCommands(program2) {
40658
41041
  }
40659
41042
 
40660
41043
  // src/commands/reset.ts
40661
- var import_node_fs69 = require("node:fs");
40662
- var import_node_path54 = require("node:path");
41044
+ var import_node_fs71 = require("node:fs");
41045
+ var import_node_path57 = require("node:path");
40663
41046
  function registerResetCommand(program2) {
40664
41047
  program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
40665
41048
  const globals = program2.opts();
@@ -40668,78 +41051,95 @@ function registerResetCommand(program2) {
40668
41051
  const tokenResult = await resolveToken(globals.token);
40669
41052
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
40670
41053
  if (tokenResult.ok && urlResult.ok) {
41054
+ const sessionId = envSessionId();
40671
41055
  const mem = await apiRequest({
40672
41056
  method: "GET",
40673
- path: process.env.CLAUDE_SESSION_ID ? `/memory?session_id=${encodeURIComponent(process.env.CLAUDE_SESSION_ID)}` : "/memory",
41057
+ path: sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory",
40674
41058
  serviceUrl: urlResult.data,
40675
41059
  token: tokenResult.data.token,
40676
41060
  timeout: 1e4,
40677
41061
  cmd: "reset_lookup"
40678
41062
  });
40679
41063
  const ct = mem.ok ? mem.data.current_task : null;
40680
- if (ct?.id) {
41064
+ const closePath = ct?.id ? taskActionPath(ct.id, "close") : null;
41065
+ if (ct?.id && !closePath) {
41066
+ printError("The current task in the service response has a malformed id \u2014 not closing it.");
41067
+ }
41068
+ if (closePath) {
40681
41069
  const closeResult = await apiRequest({
40682
41070
  method: "POST",
40683
- path: `/tasks/${ct.id}/close`,
41071
+ path: closePath,
40684
41072
  serviceUrl: urlResult.data,
40685
41073
  token: tokenResult.data.token,
40686
41074
  timeout: 1e4,
40687
41075
  cmd: "reset_close"
40688
41076
  });
40689
41077
  if (closeResult.ok) {
40690
- printInfo(`Closed task: "${ct.label}"`);
41078
+ printInfo(`Closed task: "${terminalText(ct?.label, 200) || "(unnamed)"}"`);
40691
41079
  }
40692
41080
  }
40693
41081
  }
40694
41082
  } catch {
40695
41083
  }
40696
41084
  }
40697
- const cacheDir = projectPath(CACHE_DIR);
40698
- let purged = 0;
40699
- if ((0, import_node_fs69.existsSync)(cacheDir)) {
40700
- for (const entry of (0, import_node_fs69.readdirSync)(cacheDir)) {
40701
- if (entry.startsWith("pending-")) {
40702
- try {
40703
- (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(cacheDir, entry));
40704
- purged++;
40705
- } catch {
40706
- }
40707
- }
40708
- }
40709
- }
41085
+ const purged = purgeVerityDir((0, import_node_path57.basename)(CACHE_DIR), (name2) => name2.startsWith("pending-"));
41086
+ if (purged === null) printError(`Did not purge ${CACHE_DIR}: it is not a directory inside ${VERITY_DIR}.`);
41087
+ const stateDir2 = projectPath(VERITY_DIR);
40710
41088
  const filesToClear = [
40711
- projectPath(INTENT_FILE),
40712
- projectPath(HASH_FILE),
40713
- projectPath(BASELINE_SHA_FILE),
40714
- projectPath(`${VERITY_DIR}/.iteration-count`),
40715
- projectPath(`${VERITY_DIR}/.last-analysis`)
41089
+ (0, import_node_path57.basename)(INTENT_FILE),
41090
+ (0, import_node_path57.basename)(HASH_FILE),
41091
+ (0, import_node_path57.basename)(BASELINE_SHA_FILE),
41092
+ ".iteration-count",
41093
+ ".last-analysis"
40716
41094
  ];
40717
- for (const file of filesToClear) {
40718
- if ((0, import_node_fs69.existsSync)(file)) {
40719
- try {
40720
- (0, import_node_fs69.writeFileSync)(file, "");
40721
- } catch {
40722
- }
41095
+ for (const name2 of filesToClear) {
41096
+ if (lstatOrNull((0, import_node_path57.join)(stateDir2, name2)) && !replaceInRoot(stateDir2, name2, "")) {
41097
+ printError(`Did not clear ${VERITY_DIR}/${name2}: it is not a regular file inside ${VERITY_DIR}.`);
40723
41098
  }
40724
41099
  }
40725
41100
  if (opts.all) {
40726
- const logsDir = projectPath(`${VERITY_DIR}/.logs`);
40727
- if ((0, import_node_fs69.existsSync)(logsDir)) {
40728
- for (const entry of (0, import_node_fs69.readdirSync)(logsDir)) {
40729
- try {
40730
- (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(logsDir, entry));
40731
- } catch {
40732
- }
40733
- }
40734
- }
40735
- printInfo("Cleared diagnostic logs.");
41101
+ const logs = purgeVerityDir(".logs", () => true);
41102
+ if (logs === null) printError(`Did not clear ${VERITY_DIR}/.logs: it is not a directory inside ${VERITY_DIR}.`);
41103
+ else printInfo("Cleared diagnostic logs.");
40736
41104
  }
40737
- printInfo(`Reset complete. Purged ${purged} cached request${purged !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
41105
+ const count = purged ?? 0;
41106
+ printInfo(`Reset complete. Purged ${count} cached request${count !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
40738
41107
  });
40739
41108
  }
41109
+ function lstatOrNull(path) {
41110
+ try {
41111
+ return (0, import_node_fs71.lstatSync)(path);
41112
+ } catch {
41113
+ return null;
41114
+ }
41115
+ }
41116
+ function purgeVerityDir(child, select) {
41117
+ const verityDir = projectPath(VERITY_DIR);
41118
+ const dir = (0, import_node_path57.join)(verityDir, child);
41119
+ const parent = lstatOrNull(verityDir);
41120
+ const st = lstatOrNull(dir);
41121
+ if (!st) return 0;
41122
+ if (!parent || parent.isSymbolicLink() || !parent.isDirectory()) return null;
41123
+ if (st.isSymbolicLink() || !st.isDirectory()) return null;
41124
+ try {
41125
+ if ((0, import_node_fs71.realpathSync)(dir) !== (0, import_node_path57.join)((0, import_node_fs71.realpathSync)(verityDir), child)) return null;
41126
+ } catch {
41127
+ return null;
41128
+ }
41129
+ let removed = 0;
41130
+ for (const entry of (0, import_node_fs71.readdirSync)(dir, { withFileTypes: true })) {
41131
+ if (entry.isDirectory() || !select(entry.name)) continue;
41132
+ try {
41133
+ (0, import_node_fs71.unlinkSync)((0, import_node_path57.join)(dir, entry.name));
41134
+ removed++;
41135
+ } catch {
41136
+ }
41137
+ }
41138
+ return removed;
41139
+ }
40740
41140
 
40741
41141
  // src/commands/reflect.ts
40742
- var import_node_fs70 = require("node:fs");
41142
+ var import_node_fs72 = require("node:fs");
40743
41143
 
40744
41144
  // src/lib/reflection-globs.ts
40745
41145
  var MAX_GLOBS = 6;
@@ -40777,7 +41177,7 @@ async function writeNodeToDisk(args2) {
40777
41177
  { treePaths: listTrackedFiles(), recordBaseline: false }
40778
41178
  );
40779
41179
  if (written === 0) return false;
40780
- return (0, import_node_fs70.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
41180
+ return (0, import_node_fs72.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40781
41181
  } catch {
40782
41182
  return false;
40783
41183
  }
@@ -40808,7 +41208,7 @@ function registerReflectCommand(program2) {
40808
41208
  let taskResolution = "flag";
40809
41209
  let inheritedGlobs = [];
40810
41210
  if (!taskId) {
40811
- const sessionId = process.env.CLAUDE_SESSION_ID ?? "";
41211
+ const sessionId = envSessionId() ?? "";
40812
41212
  const memPath = sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory";
40813
41213
  const mem = await apiRequest({
40814
41214
  method: "GET",
@@ -40853,7 +41253,7 @@ function registerReflectCommand(program2) {
40853
41253
  const userInput = input.text;
40854
41254
  if (userInput) {
40855
41255
  const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
40856
- const kind = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
41256
+ const kind2 = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
40857
41257
  const confirmed = opts.confirmed === true;
40858
41258
  const source2 = confirmed ? "user" : "agent";
40859
41259
  const explicitGlobs = Array.isArray(opts.fileGlobs) ? opts.fileGlobs.map((g) => g.trim()).filter(Boolean) : [];
@@ -40865,7 +41265,7 @@ function registerReflectCommand(program2) {
40865
41265
  serviceUrl,
40866
41266
  token,
40867
41267
  body: {
40868
- kind,
41268
+ kind: kind2,
40869
41269
  title: userInput.slice(0, 200),
40870
41270
  body: userInput,
40871
41271
  domains: [],
@@ -41214,9 +41614,9 @@ function registerRunCommand(program2) {
41214
41614
  }
41215
41615
 
41216
41616
  // src/commands/telemetry.ts
41217
- var import_node_fs71 = require("node:fs");
41617
+ var import_node_fs73 = require("node:fs");
41218
41618
  async function recordTelemetryChoice(choice) {
41219
- if (!(0, import_node_fs71.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41619
+ if (!(0, import_node_fs73.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41220
41620
  try {
41221
41621
  if ((await readSetupState())?.telemetry === choice) return;
41222
41622
  await writeSetupState({ telemetry: choice });
@@ -41293,8 +41693,8 @@ function registerTelemetryCommands(program2) {
41293
41693
  }
41294
41694
 
41295
41695
  // src/commands/prove.ts
41296
- var import_node_fs72 = require("node:fs");
41297
- var import_node_path55 = require("node:path");
41696
+ var import_node_fs74 = require("node:fs");
41697
+ var import_node_path58 = require("node:path");
41298
41698
 
41299
41699
  // src/lib/prove/hint-pool.ts
41300
41700
  var STOP2 = /* @__PURE__ */ new Set([
@@ -41436,7 +41836,7 @@ function registerProveCommand(program2) {
41436
41836
  process.exit(2);
41437
41837
  }
41438
41838
  const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
41439
- let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)) || ".") });
41839
+ let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path58.relative)(root, (0, import_node_path58.resolve)(p)) || ".") });
41440
41840
  if (opts.hint && paths.length === 0) {
41441
41841
  const hit = hintMatches(root, opts.hint);
41442
41842
  if (hit.files.length > 0) {
@@ -41490,7 +41890,7 @@ function registerProveCommand(program2) {
41490
41890
  });
41491
41891
  prove.command("check [model]").description("Elaborate a model (or every model) with the local Lean toolchain and report each property").option("--timeout <ms>", "Per-model timeout in ms", "120000").option("--json", "Machine-readable output").action((model, opts) => {
41492
41892
  const root = repoRoot();
41493
- if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41893
+ if (!(0, import_node_fs74.existsSync)((0, import_node_path58.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41494
41894
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41495
41895
  process.exit(2);
41496
41896
  }
@@ -41514,7 +41914,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41514
41914
  const reports = [];
41515
41915
  for (const f of files) {
41516
41916
  const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
41517
- report.file = (0, import_node_path55.relative)(root, f);
41917
+ report.file = (0, import_node_path58.relative)(root, f);
41518
41918
  reports.push(report);
41519
41919
  try {
41520
41920
  writeResult(root, report);
@@ -41552,7 +41952,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41552
41952
  printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
41553
41953
  process.exit(2);
41554
41954
  }
41555
- if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41955
+ if (!(0, import_node_fs74.existsSync)((0, import_node_path58.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41556
41956
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41557
41957
  process.exit(2);
41558
41958
  }
@@ -41583,7 +41983,7 @@ ${report.error ?? ""}`);
41583
41983
  printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
41584
41984
  return;
41585
41985
  }
41586
- const modelSource = readRegularFileInRoot(root, (0, import_node_path55.relative)(root, file), 512 * 1024);
41986
+ const modelSource = readRegularFileInRoot(root, (0, import_node_path58.relative)(root, file), 512 * 1024);
41587
41987
  if (!opts.json) printInfo(`replaying ${targets.length} counterexample(s) of ${model} in network-less containers (${Math.min(targets.length, REPLAY_CONCURRENCY)} at a time)\u2026`);
41588
41988
  const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
41589
41989
  const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
@@ -41603,7 +42003,7 @@ ${report.error ?? ""}`);
41603
42003
  });
41604
42004
  prove.command("auto [files...]").description("The formal phase the pre-push guard runs: select one risky symbol among changed files, generate a model, check it, replay counterexamples (default files: the commits ahead of upstream)").option("--deadline <ms>", "Budget for the whole phase", "170000").option("--json", "Machine-readable output").action(async (paths, opts) => {
41605
42005
  const root = repoRoot();
41606
- let files = paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)));
42006
+ let files = paths.map((p) => (0, import_node_path58.relative)(root, (0, import_node_path58.resolve)(p)));
41607
42007
  if (files.length === 0) {
41608
42008
  const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
41609
42009
  const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
@@ -41613,8 +42013,10 @@ ${report.error ?? ""}`);
41613
42013
  printInfo("No changed files to consider (nothing ahead of upstream). Pass paths explicitly.");
41614
42014
  return;
41615
42015
  }
41616
- const prep = await prepareFormalPhase(root, process.env, await proveAuth(program2) ?? void 0);
42016
+ const auth2 = await proveAuth(program2);
42017
+ const prep = await prepareFormalPhase(root, process.env, auth2 ?? void 0);
41617
42018
  const outcome = prep.ok ? await runFormalPhaseWithin({ root, files, deadlineAt: Date.now() + Math.max(3e4, Number(opts.deadline) || 17e4), deps: prep.deps }).catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200))) : skippedOutcome(prep.skip, prep.detail);
42019
+ if (auth2) await postPhaseRecord(outcome, { moment: "on-demand", parentRunId: null, pushedFiles: [] }, auth2);
41618
42020
  if (opts.json) {
41619
42021
  printJson(outcome);
41620
42022
  } else {
@@ -41675,7 +42077,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41675
42077
  let revise;
41676
42078
  if (opts.revise) {
41677
42079
  const existing = resolveModelFile(root, opts.revise);
41678
- const src = existing ? readRegularFileInRoot(root, (0, import_node_path55.relative)(root, existing), 64 * 1024) : null;
42080
+ const src = existing ? readRegularFileInRoot(root, (0, import_node_path58.relative)(root, existing), 64 * 1024) : null;
41679
42081
  if (!src || !src.ok || !opts.note) {
41680
42082
  printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
41681
42083
  process.exit(2);
@@ -41688,21 +42090,22 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41688
42090
  printError("Verity library did not build");
41689
42091
  process.exit(2);
41690
42092
  }
41691
- const deps = defaultDeps({ auth: auth2 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc, tier: "deep" });
42093
+ const deps = await onDemandDeps(root, { auth: auth2 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc });
41692
42094
  if (!opts.json) printInfo(`asking the Verity service for a model of ${symbol || `${file}:${opts.lines}`} \u2026`);
41693
42095
  const out2 = await generateAndCheck(root, { file, symbol: symbol || `${file}:${opts.lines}`, lines, hint: opts.hint, revise }, { deps, maxRounds: 3 });
41694
42096
  if (!out2.ok) {
41695
42097
  if (opts.json) printJson(out2);
41696
- else printError(`${out2.error} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""}) \u2014 write the model by hand (Models/README.md) or narrow the target`);
42098
+ else printError(out2.rounds === 0 ? out2.error : `${out2.error} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""}) \u2014 write the model by hand (Models/README.md) or narrow the target`);
41697
42099
  process.exit(2);
41698
42100
  }
42101
+ if (out2.warning && !opts.json) printWarn(out2.warning);
41699
42102
  try {
41700
42103
  writeResult(root, out2.report);
41701
42104
  } catch (err2) {
41702
42105
  if (!(err2 instanceof SafeWriteError)) throw err2;
41703
42106
  }
41704
42107
  if (opts.json) {
41705
- printJson({ name: out2.name, file: out2.file, rounds: out2.rounds, cost_usd: out2.costUsd, report: { ...out2.report, passes: reportPasses(out2.report), summary: summarize(out2.report) } });
42108
+ printJson({ name: out2.name, file: out2.file, rounds: out2.rounds, cost_usd: out2.costUsd, ...out2.warning ? { warning: out2.warning } : {}, report: { ...out2.report, passes: reportPasses(out2.report), summary: summarize(out2.report) } });
41706
42109
  return;
41707
42110
  }
41708
42111
  printInfo(`wrote ${out2.file} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""})`);
@@ -41714,8 +42117,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41714
42117
  });
41715
42118
  prove.command("waive <file>").description("Dismiss the remembered formal finding(s) on a file for its current bytes \u2014 the accepted-risk path for a formal block").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action((file, opts) => {
41716
42119
  const root = repoRoot();
41717
- const rel0 = (0, import_node_path55.relative)(root, (0, import_node_path55.isAbsolute)(file) ? file : (0, import_node_path55.join)(root, file)).replace(/\\/g, "/");
41718
- const rel = rel0.startsWith("..") || (0, import_node_path55.isAbsolute)(rel0) ? null : rel0;
42120
+ const rel0 = (0, import_node_path58.relative)(root, (0, import_node_path58.isAbsolute)(file) ? file : (0, import_node_path58.join)(root, file)).replace(/\\/g, "/");
42121
+ const rel = rel0.startsWith("..") || (0, import_node_path58.isAbsolute)(rel0) ? null : rel0;
41719
42122
  if (!rel) {
41720
42123
  printError(`${file} is not inside this repository`);
41721
42124
  process.exit(2);
@@ -41731,8 +42134,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41731
42134
  });
41732
42135
  prove.command("hash <file>").description("Print the sha256 of a file, for a model header (Verity.model \u2026 sha256). Path is REPO-relative, as in the header").action((file) => {
41733
42136
  const root = repoRoot();
41734
- const rel = (0, import_node_path55.relative)(root, (0, import_node_path55.isAbsolute)(file) ? file : (0, import_node_path55.join)(root, file));
41735
- const digest = rel.startsWith("..") || (0, import_node_path55.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
42137
+ const rel = (0, import_node_path58.relative)(root, (0, import_node_path58.isAbsolute)(file) ? file : (0, import_node_path58.join)(root, file));
42138
+ const digest = rel.startsWith("..") || (0, import_node_path58.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
41736
42139
  if (!digest) {
41737
42140
  printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
41738
42141
  process.exit(2);
@@ -41766,10 +42169,10 @@ function refreshScaffold(root) {
41766
42169
  }
41767
42170
 
41768
42171
  // src/commands/lean.ts
41769
- var import_node_fs73 = require("node:fs");
42172
+ var import_node_fs75 = require("node:fs");
41770
42173
  var import_node_child_process20 = require("node:child_process");
41771
42174
  var import_node_os12 = require("node:os");
41772
- var import_node_path56 = require("node:path");
42175
+ var import_node_path59 = require("node:path");
41773
42176
  function registerLeanCommand(program2) {
41774
42177
  const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
41775
42178
  lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
@@ -41786,7 +42189,7 @@ function registerLeanCommand(program2) {
41786
42189
  const managed = pinnedVersionDir();
41787
42190
  const matches = version ? version.includes(pin) : false;
41788
42191
  if (opts.json) {
41789
- printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs73.existsSync)((0, import_node_path56.join)(managed, "bin")), asset: leanAssetName() });
42192
+ printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs75.existsSync)((0, import_node_path59.join)(managed, "bin")), asset: leanAssetName() });
41790
42193
  return;
41791
42194
  }
41792
42195
  printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
@@ -41804,7 +42207,7 @@ function registerLeanCommand(program2) {
41804
42207
  process.exit(2);
41805
42208
  }
41806
42209
  const dir = pinnedVersionDir();
41807
- if ((0, import_node_fs73.existsSync)((0, import_node_path56.join)(dir, "bin", "lake")) && !opts.force) {
42210
+ if ((0, import_node_fs75.existsSync)((0, import_node_path59.join)(dir, "bin", "lake")) && !opts.force) {
41808
42211
  printInfo(`already installed at ${dir}`);
41809
42212
  return;
41810
42213
  }
@@ -41840,18 +42243,18 @@ function registerLeanCommand(program2) {
41840
42243
  });
41841
42244
  lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
41842
42245
  const dir = pinnedVersionDir();
41843
- if (!(0, import_node_fs73.existsSync)(dir)) {
42246
+ if (!(0, import_node_fs75.existsSync)(dir)) {
41844
42247
  printInfo("nothing to remove");
41845
42248
  return;
41846
42249
  }
41847
- (0, import_node_fs73.rmSync)(dir, { recursive: true, force: true });
42250
+ (0, import_node_fs75.rmSync)(dir, { recursive: true, force: true });
41848
42251
  printInfo(`removed ${dir}`);
41849
42252
  });
41850
42253
  }
41851
42254
 
41852
42255
  // src/cli.ts
41853
- program.name("verity").description("CLI for Verity quality gate service").version("0.34.1").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
41854
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.1");
42256
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.2-experimental.312358d").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) => {
42257
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.2-experimental.312358d");
41855
42258
  setUserNamedServiceUrl(program.opts().serviceUrl);
41856
42259
  try {
41857
42260
  await foldLegacyLocalCredential();