@codacy/verity-cli 0.34.1 → 0.34.2

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:
@@ -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" : "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_fs62 = require("node:fs");
33867
+ var import_node_path50 = 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
  }
@@ -33864,7 +33993,7 @@ async function runAgentReview(options) {
33864
33993
  }
33865
33994
 
33866
33995
  // src/lib/prove/auto.ts
33867
- var import_node_path47 = require("node:path");
33996
+ var import_node_path49 = require("node:path");
33868
33997
  var import_node_crypto19 = require("node:crypto");
33869
33998
 
33870
33999
  // src/lib/prove/signals.ts
@@ -34906,9 +35035,9 @@ function effectSites(numbered2) {
34906
35035
  const t = r.text.trim();
34907
35036
  if (!t || t.startsWith("//") || t.startsWith("#") || t.startsWith("*")) continue;
34908
35037
  const onParam = [...params].some((p) => callsOn(t, p) || callsDirect(t, p));
34909
- const 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}`);
35038
+ const kind2 = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
35039
+ if (!kind2) continue;
35040
+ out2.push(`L${r.n} [${kind2}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
34912
35041
  if (out2.length >= MAX_EFFECT_SITES) break;
34913
35042
  }
34914
35043
  return out2;
@@ -35551,9 +35680,9 @@ async function runReplay(brief, opts) {
35551
35680
  if (opts.auth) return runReplayViaServer(brief, opts.auth, opts.timeoutMs);
35552
35681
  const env = opts.env ?? process.env;
35553
35682
  const none = { covered: 0, total: 0, ratio: 0, basis: "none" };
35554
- const 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");
35683
+ const refuse2 = (error) => ({ claimed: null, verdict: "unverified", reason: "", downgrade: error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: 0, containerId: null, error });
35684
+ if (env.VERITY_PROVE_DIRECT !== "1") return refuse2("not logged in (run `verity login`); replays run on the Verity service");
35685
+ if (!opts.apiKey) return refuse2("OPENAI_API_KEY is not set");
35557
35686
  return runReplayInContainer(brief, { apiKey: opts.apiKey, model: opts.model, timeoutMs: opts.timeoutMs, maxRounds: opts.maxRounds, fetchImpl: opts.fetchImpl });
35558
35687
  }
35559
35688
  function renderReplay(model, property, r) {
@@ -35591,18 +35720,18 @@ function renderReplay(model, property, r) {
35591
35720
  // src/lib/prove/runner.ts
35592
35721
  var import_node_child_process15 = require("node:child_process");
35593
35722
  var import_node_os8 = require("node:os");
35594
- var import_node_fs60 = require("node:fs");
35723
+ var import_node_fs61 = require("node:fs");
35595
35724
  var import_node_os9 = require("node:os");
35596
- var import_node_path46 = require("node:path");
35725
+ var import_node_path48 = require("node:path");
35597
35726
 
35598
35727
  // src/lib/prove/scaffold.ts
35599
- var import_node_fs59 = require("node:fs");
35600
- var import_node_path45 = require("node:path");
35728
+ var import_node_fs60 = require("node:fs");
35729
+ var import_node_path47 = require("node:path");
35601
35730
 
35602
35731
  // src/lib/prove/safe-write.ts
35603
- var import_node_fs58 = require("node:fs");
35732
+ var import_node_fs59 = require("node:fs");
35604
35733
  var import_node_crypto15 = require("node:crypto");
35605
- var import_node_path44 = require("node:path");
35734
+ var import_node_path46 = require("node:path");
35606
35735
  var SafeWriteError = class extends Error {
35607
35736
  constructor(reason, path) {
35608
35737
  super(`refusing to write ${path}: ${reason}`);
@@ -35611,10 +35740,10 @@ var SafeWriteError = class extends Error {
35611
35740
  this.name = "SafeWriteError";
35612
35741
  }
35613
35742
  };
35614
- var FLAGS3 = import_node_fs58.constants;
35743
+ var FLAGS3 = import_node_fs59.constants;
35615
35744
  var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
35616
35745
  function assertPlainRelative(rel) {
35617
- if (!rel || (0, import_node_path44.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35746
+ if (!rel || (0, import_node_path46.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35618
35747
  for (const part of rel.split(/[\\/]/)) {
35619
35748
  if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
35620
35749
  }
@@ -35623,34 +35752,34 @@ function ensureDirsNoFollow(root, rel) {
35623
35752
  const parts2 = rel.split(/[\\/]/);
35624
35753
  let cur = root;
35625
35754
  for (const part of parts2.slice(0, -1)) {
35626
- cur = (0, import_node_path44.join)(cur, part);
35755
+ cur = (0, import_node_path46.join)(cur, part);
35627
35756
  let st;
35628
35757
  try {
35629
- st = (0, import_node_fs58.lstatSync)(cur);
35758
+ st = (0, import_node_fs59.lstatSync)(cur);
35630
35759
  } catch {
35631
- (0, import_node_fs58.mkdirSync)(cur);
35760
+ (0, import_node_fs59.mkdirSync)(cur);
35632
35761
  continue;
35633
35762
  }
35634
35763
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
35635
35764
  if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
35636
35765
  }
35637
- return (0, import_node_path44.join)(root, rel);
35766
+ return (0, import_node_path46.join)(root, rel);
35638
35767
  }
35639
35768
  function insideRoot(realRoot, realPath) {
35640
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path44.sep) ? realRoot : realRoot + import_node_path44.sep);
35769
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path46.sep) ? realRoot : realRoot + import_node_path46.sep);
35641
35770
  }
35642
35771
  function removeQuietly(path) {
35643
35772
  try {
35644
- (0, import_node_fs58.unlinkSync)(path);
35773
+ (0, import_node_fs59.unlinkSync)(path);
35645
35774
  } catch {
35646
35775
  }
35647
35776
  }
35648
35777
  function writeFileInRootNoFollow(root, rel, content) {
35649
35778
  assertPlainRelative(rel);
35650
35779
  const dest = ensureDirsNoFollow(root, rel);
35651
- const dir = (0, import_node_path44.dirname)(dest);
35780
+ const dir = (0, import_node_path46.dirname)(dest);
35652
35781
  try {
35653
- const st = (0, import_node_fs58.lstatSync)(dest);
35782
+ const st = (0, import_node_fs59.lstatSync)(dest);
35654
35783
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
35655
35784
  if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
35656
35785
  } catch (err2) {
@@ -35658,41 +35787,41 @@ function writeFileInRootNoFollow(root, rel, content) {
35658
35787
  }
35659
35788
  let realRoot;
35660
35789
  try {
35661
- realRoot = (0, import_node_fs58.realpathSync)(root);
35790
+ realRoot = (0, import_node_fs59.realpathSync)(root);
35662
35791
  } catch {
35663
35792
  throw new SafeWriteError("unwritable", root);
35664
35793
  }
35665
- const tmp = (0, import_node_path44.join)(dir, `.${(0, import_node_path44.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35794
+ const tmp = (0, import_node_path46.join)(dir, `.${(0, import_node_path46.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35666
35795
  let fd;
35667
35796
  try {
35668
- fd = (0, 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);
35797
+ fd = (0, import_node_fs59.openSync)(tmp, import_node_fs59.constants.O_WRONLY | import_node_fs59.constants.O_CREAT | import_node_fs59.constants.O_EXCL | NOFOLLOW2, 420);
35669
35798
  } catch {
35670
35799
  throw new SafeWriteError("unwritable", tmp);
35671
35800
  }
35672
35801
  try {
35673
- const opened = (0, import_node_fs58.fstatSync)(fd, { bigint: true });
35802
+ const opened = (0, import_node_fs59.fstatSync)(fd, { bigint: true });
35674
35803
  let realTmp;
35675
35804
  try {
35676
- realTmp = (0, import_node_fs58.realpathSync)(tmp);
35805
+ realTmp = (0, import_node_fs59.realpathSync)(tmp);
35677
35806
  } catch {
35678
35807
  throw new SafeWriteError("escaped", tmp);
35679
35808
  }
35680
- const there = (0, import_node_fs58.lstatSync)(realTmp, { bigint: true });
35809
+ const there = (0, import_node_fs59.lstatSync)(realTmp, { bigint: true });
35681
35810
  if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
35682
35811
  throw new SafeWriteError("escaped", tmp);
35683
35812
  }
35684
35813
  const buf = Buffer.from(content, "utf-8");
35685
35814
  let off = 0;
35686
- while (off < buf.length) off += (0, import_node_fs58.writeSync)(fd, buf, off, buf.length - off);
35815
+ while (off < buf.length) off += (0, import_node_fs59.writeSync)(fd, buf, off, buf.length - off);
35687
35816
  } catch (err2) {
35688
- (0, import_node_fs58.closeSync)(fd);
35817
+ (0, import_node_fs59.closeSync)(fd);
35689
35818
  removeQuietly(tmp);
35690
35819
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
35691
35820
  }
35692
- (0, import_node_fs58.closeSync)(fd);
35821
+ (0, import_node_fs59.closeSync)(fd);
35693
35822
  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);
35823
+ if (!insideRoot(realRoot, (0, import_node_fs59.realpathSync)(dir)) || (0, import_node_fs59.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35824
+ (0, import_node_fs59.renameSync)(tmp, dest);
35696
35825
  } catch (err2) {
35697
35826
  removeQuietly(tmp);
35698
35827
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
@@ -35706,9 +35835,9 @@ function pathHasNoLink(root, rel) {
35706
35835
  }
35707
35836
  let cur = root;
35708
35837
  for (const part of rel.split(/[\\/]/)) {
35709
- cur = cur + import_node_path44.sep + part;
35838
+ cur = cur + import_node_path46.sep + part;
35710
35839
  try {
35711
- if ((0, import_node_fs58.lstatSync)(cur).isSymbolicLink()) return false;
35840
+ if ((0, import_node_fs59.lstatSync)(cur).isSymbolicLink()) return false;
35712
35841
  } catch {
35713
35842
  return true;
35714
35843
  }
@@ -36018,20 +36147,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
36018
36147
  never committed; what reaches the team is the bug report and the fix.
36019
36148
  `;
36020
36149
  function scaffoldProofs(root) {
36021
- const proofsDir = (0, import_node_path45.join)(root, PROOFS_DIR);
36150
+ const proofsDir = (0, import_node_path47.join)(root, PROOFS_DIR);
36022
36151
  const written = [];
36023
36152
  const kept = [];
36024
36153
  for (const stray of ["lakefile.lean"]) {
36025
36154
  const rel = `${PROOFS_DIR}/${stray}`;
36026
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36155
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path47.join)(root, rel));
36027
36156
  try {
36028
- (0, import_node_fs59.rmSync)((0, import_node_path45.join)(root, rel), { force: true });
36157
+ (0, import_node_fs60.rmSync)((0, import_node_path47.join)(root, rel), { force: true });
36029
36158
  } catch {
36030
36159
  }
36031
36160
  }
36032
36161
  for (const f of PROOFS_TEMPLATE_FILES) {
36033
36162
  const rel = `${PROOFS_DIR}/${f.path}`;
36034
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36163
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path47.join)(root, rel));
36035
36164
  const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
36036
36165
  if (current.ok && current.content === f.content) {
36037
36166
  kept.push(rel);
@@ -36044,8 +36173,8 @@ function scaffoldProofs(root) {
36044
36173
  [`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
36045
36174
  [`${MODELS_DIR}/README.md`, MODELS_README]
36046
36175
  ]) {
36047
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
36048
- if (existsNoFollow((0, import_node_path45.join)(root, rel))) {
36176
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path47.join)(root, rel));
36177
+ if (existsNoFollow((0, import_node_path47.join)(root, rel))) {
36049
36178
  kept.push(rel);
36050
36179
  continue;
36051
36180
  }
@@ -36056,7 +36185,7 @@ function scaffoldProofs(root) {
36056
36185
  }
36057
36186
  function existsNoFollow(abs) {
36058
36187
  try {
36059
- (0, import_node_fs59.lstatSync)(abs);
36188
+ (0, import_node_fs60.lstatSync)(abs);
36060
36189
  return true;
36061
36190
  } catch {
36062
36191
  return false;
@@ -36135,12 +36264,12 @@ function parseHeader(obj) {
36135
36264
  function parseProperty(obj) {
36136
36265
  const model = ident(obj.model);
36137
36266
  const id = ident(obj.id);
36138
- const kind = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
36267
+ const kind2 = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
36139
36268
  const result = typeof obj.result === "string" && RESULTS.has(obj.result) ? obj.result : null;
36140
36269
  const source2 = obj.source === void 0 ? "" : str2(obj.source, LIMITS.text);
36141
36270
  const desc = obj.desc === void 0 ? "" : str2(obj.desc, LIMITS.text);
36142
- if (!model || !id || !kind || !result || source2 === null || desc === null) return null;
36143
- const p = { model, id, kind, source: source2, desc, result };
36271
+ if (!model || !id || !kind2 || !result || source2 === null || desc === null) return null;
36272
+ const p = { model, id, kind: kind2, source: source2, desc, result };
36144
36273
  if (obj.bound !== void 0) {
36145
36274
  const n = nat(obj.bound);
36146
36275
  if (n === null) return null;
@@ -36314,17 +36443,17 @@ function renderReport(r) {
36314
36443
 
36315
36444
  // src/lib/prove/runner.ts
36316
36445
  function verityLeanHome(env = process.env) {
36317
- return env.VERITY_LEAN_HOME ?? (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36446
+ return env.VERITY_LEAN_HOME ?? (0, import_node_path48.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36318
36447
  }
36319
36448
  function findToolchain(env = process.env) {
36320
- const managedBin = (0, 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);
36449
+ const managedBin = (0, import_node_path48.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
36450
+ const elanBin = (0, import_node_path48.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
36451
+ const elanHas = (0, import_node_fs61.existsSync)((0, import_node_path48.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
36452
+ const userPath = (env.PATH ?? "").split(import_node_path48.delimiter).filter((d) => d && (elanHas || (0, import_node_path48.resolve)(d) !== (0, import_node_path48.resolve)(elanBin)));
36453
+ const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path48.delimiter);
36325
36454
  const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
36326
36455
  const exe = process.platform === "win32" ? "lake.exe" : "lake";
36327
- const candidates2 = [(0, import_node_path46.join)(managedBin, exe), ...elanHas ? [(0, import_node_path46.join)(elanBin, exe)] : [], exe];
36456
+ const candidates2 = [(0, import_node_path48.join)(managedBin, exe), ...elanHas ? [(0, import_node_path48.join)(elanBin, exe)] : [], exe];
36328
36457
  for (const candidate of candidates2) {
36329
36458
  try {
36330
36459
  (0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
@@ -36403,7 +36532,7 @@ function proofsWorkspaceProblem(root) {
36403
36532
  for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
36404
36533
  let st;
36405
36534
  try {
36406
- st = (0, import_node_fs60.lstatSync)((0, import_node_path46.join)(root, rel));
36535
+ st = (0, import_node_fs61.lstatSync)((0, import_node_path48.join)(root, rel));
36407
36536
  } catch {
36408
36537
  break;
36409
36538
  }
@@ -36423,44 +36552,44 @@ function refused(problem) {
36423
36552
  function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36424
36553
  const problem = proofsWorkspaceProblem(root);
36425
36554
  if (problem) return refused(problem);
36426
- return run2(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36555
+ return run2(tc, (0, import_node_path48.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36427
36556
  }
36428
36557
  async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36429
36558
  const problem = proofsWorkspaceProblem(root);
36430
36559
  if (problem) return refused(problem);
36431
- return runAsync(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36560
+ return runAsync(tc, (0, import_node_path48.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36432
36561
  }
36433
36562
  function isModelInRoot(modelsAbs, rel) {
36434
- if (!rel.endsWith(".lean") || (0, import_node_path46.isAbsolute)(rel) || rel.startsWith("..")) return false;
36563
+ if (!rel.endsWith(".lean") || (0, import_node_path48.isAbsolute)(rel) || rel.startsWith("..")) return false;
36435
36564
  return statRegularInRoot(modelsAbs, rel).ok;
36436
36565
  }
36437
36566
  function resolveModelFile(root, arg) {
36438
- const modelsAbs = (0, 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));
36567
+ const modelsAbs = (0, import_node_path48.join)(root, MODELS_DIR);
36568
+ const asPath = (0, import_node_path48.relative)(modelsAbs, (0, import_node_path48.isAbsolute)(arg) ? arg : (0, import_node_path48.resolve)(root, arg));
36440
36569
  const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
36441
36570
  for (const rel of candidates2) {
36442
- if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path46.join)(modelsAbs, rel);
36571
+ if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path48.join)(modelsAbs, rel);
36443
36572
  }
36444
36573
  return null;
36445
36574
  }
36446
36575
  function listModelFiles(root) {
36447
- const modelsAbs = (0, 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));
36576
+ const modelsAbs = (0, import_node_path48.join)(root, MODELS_DIR);
36577
+ if (!(0, import_node_fs61.existsSync)(modelsAbs)) return [];
36578
+ return (0, import_node_fs61.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path48.join)(modelsAbs, f));
36450
36579
  }
36451
36580
  function trimDiagnostics(text) {
36452
36581
  return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36453
36582
  }
36454
36583
  function checkModel(tc, root, modelFile, opts = {}) {
36455
- const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36456
- const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36584
+ const proofsAbs = (0, import_node_path48.join)(root, PROOFS_DIR);
36585
+ const rel = (0, import_node_path48.relative)(proofsAbs, modelFile);
36457
36586
  const problem = proofsWorkspaceProblem(root);
36458
36587
  const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36459
36588
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36460
36589
  }
36461
36590
  async function checkModelAsync(tc, root, modelFile, opts = {}) {
36462
- const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36463
- const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36591
+ const proofsAbs = (0, import_node_path48.join)(root, PROOFS_DIR);
36592
+ const rel = (0, import_node_path48.relative)(proofsAbs, modelFile);
36464
36593
  const problem = proofsWorkspaceProblem(root);
36465
36594
  const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36466
36595
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
@@ -36469,10 +36598,10 @@ function toReport(res, root, modelFile, timeoutMs) {
36469
36598
  const parsed = parseVerityLines(res.stdout);
36470
36599
  const combined = `${res.stdout}
36471
36600
  ${res.stderr}`;
36472
- const name2 = parsed.header?.model ?? (0, import_node_path46.basename)(modelFile, ".lean");
36601
+ const name2 = parsed.header?.model ?? (0, import_node_path48.basename)(modelFile, ".lean");
36473
36602
  const report = {
36474
36603
  model: name2,
36475
- file: (0, import_node_path46.relative)(root, modelFile),
36604
+ file: (0, import_node_path48.relative)(root, modelFile),
36476
36605
  ok: res.ok,
36477
36606
  header: parsed.header,
36478
36607
  properties: parsed.properties,
@@ -36519,9 +36648,9 @@ function isCrashTrace(trace) {
36519
36648
  }
36520
36649
  function mergeFormalFindings(response, outcome, pushedFiles) {
36521
36650
  if (!outcome) return { blocking: 0 };
36522
- const 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)));
36651
+ const norm3 = (p) => p.replace(/\\/g, "/");
36652
+ const pushed = new Set(pushedFiles.map(norm3));
36653
+ const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm3(f.file)));
36525
36654
  if (blocking.length === 0) return { blocking: 0 };
36526
36655
  const existing = Array.isArray(response.findings) ? response.findings : [];
36527
36656
  response.findings = [
@@ -36717,15 +36846,15 @@ function nonNegative(v) {
36717
36846
  return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
36718
36847
  }
36719
36848
  function readLedger(root) {
36720
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
36721
- const empty = { day: today, models: 0, costUsd: 0 };
36849
+ const today2 = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
36850
+ const empty = { day: today2, models: 0, costUsd: 0 };
36722
36851
  if (!isLocalState(root, AUTO_LEDGER)) return empty;
36723
36852
  const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
36724
36853
  if (!read2.ok) return empty;
36725
36854
  try {
36726
36855
  const o = JSON.parse(read2.content);
36727
- if (o.day !== today || typeof o.models !== "number") return empty;
36728
- return { day: today, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
36856
+ if (o.day !== today2 || typeof o.models !== "number") return empty;
36857
+ return { day: today2, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
36729
36858
  } catch {
36730
36859
  return empty;
36731
36860
  }
@@ -36903,7 +37032,7 @@ async function runFormalPhase(input) {
36903
37032
  const ranked = await deps.rank(eligible, root, input.changedLines);
36904
37033
  if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
36905
37034
  if (ranked.ok) spend(ranked);
36906
- candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
37035
+ candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)), commits: c.commits, fixCommits: c.fixCommits, risk: c.risk }));
36907
37036
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
36908
37037
  const minScore = input.minScore ?? DEFAULT_MIN_SCORE;
36909
37038
  let qualified = ranked.ranked.filter((c) => c.ai && c.ai.score >= minScore);
@@ -37012,7 +37141,7 @@ async function runFormalPhase(input) {
37012
37141
  const sha2562 = sha256Of(chosen.content);
37013
37142
  const chosenContent = chosen.content;
37014
37143
  const { lines, numbered: numbered2 } = chosen;
37015
- const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {} };
37144
+ const target = { file: top.file, symbol: top.ai.symbol, lines, score: top.ai.score, reasons: [...top.reasons, ...top.ai.reasons], extent: chosen.extent, ...chosen.context ? { context: chosen.context.stats } : {}, ...floor ? { floor: true } : {}, signals: { commits: top.commits, fixCommits: top.fixCommits, risk: top.risk } };
37016
37145
  progress.target = target;
37017
37146
  if (!REPLAYABLE.test(top.file)) return done({ status: "skipped", skip: "replay-unsupported", detail: `${top.file}: replay supports TS/JS and Python`, target });
37018
37147
  if (timeLeft() < GENERATE_RESERVE_MS) return done({ status: "skipped", skip: "not-enough-time", detail: `${Math.round(timeLeft() / 1e3)} s left before generation`, target });
@@ -37042,7 +37171,7 @@ async function runFormalPhase(input) {
37042
37171
  modelName = gen.name;
37043
37172
  const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
37044
37173
  writeFileInRootNoFollow(root, rel, gen.source);
37045
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
37174
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path49.join)(root, rel);
37046
37175
  progress.model = { name: gen.name, file: rel, rounds: round };
37047
37176
  progress.step = "check";
37048
37177
  report = await deps.check(root, abs);
@@ -37164,7 +37293,7 @@ async function runFormalPhase(input) {
37164
37293
  return done({
37165
37294
  status: "checked",
37166
37295
  target,
37167
- model: { name: modelName, file: (0, import_node_path47.relative)(root, (0, import_node_path47.join)(root, modelFile)), rounds },
37296
+ model: { name: modelName, file: (0, import_node_path49.relative)(root, (0, import_node_path49.join)(root, modelFile)), rounds },
37168
37297
  properties: report.properties,
37169
37298
  findings
37170
37299
  });
@@ -37197,7 +37326,19 @@ async function generateAndCheck(root, req, opts) {
37197
37326
  const read2 = readSrc(req.file, 96 * 1024);
37198
37327
  if (!read2.ok) return { ok: false, error: `${req.file}: ${read2.reason}`, rounds: 0, costUsd: 0 };
37199
37328
  const sha2562 = sha256Of(read2.content);
37200
- const { lines, numbered: numbered2 } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
37329
+ const { lines, numbered: numbered2, extent } = describeTarget(read2.content, req.symbol, req.file, req.lines, { codeMap: opts.deps.codeMap });
37330
+ let warning;
37331
+ if (!lines) {
37332
+ const outline = extent === "fallback:not-found" ? opts.deps.codeMap?.outline(req.file, read2.content) : void 0;
37333
+ if (outline?.source === "tree-sitter") {
37334
+ const names2 = [...new Set(outline.value.filter((f) => f.name && f.kind !== "lambda").map((f) => f.qualified))];
37335
+ const last = (req.symbol.split(/[.#:]/).pop() ?? req.symbol).toLowerCase();
37336
+ const close = names2.filter((n) => n.toLowerCase().includes(last));
37337
+ const shown = (close.length > 0 ? close : names2).slice(0, 12);
37338
+ return { ok: false, error: `no function \`${req.symbol}\` in ${req.file}${shown.length ? ` (it has: ${shown.join(", ")})` : ""}. Name one as ${req.file}#<name>, or pass --lines a-b`, rounds: 0, costUsd: 0 };
37339
+ }
37340
+ 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.`;
37341
+ }
37201
37342
  const target = {
37202
37343
  file: req.file,
37203
37344
  symbol: req.symbol,
@@ -37205,7 +37346,9 @@ async function generateAndCheck(root, req, opts) {
37205
37346
  sha256: sha2562,
37206
37347
  numbered: numbered2,
37207
37348
  reasons: req.hint ? [`the user's worry, in their words: ${req.hint.slice(0, 280)}`] : [],
37208
- properties: []
37349
+ properties: [],
37350
+ // The run row records which extractor answered, as at push.
37351
+ extentSource: extent
37209
37352
  };
37210
37353
  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
37354
  Object.assign(target, context?.fields ?? {});
@@ -37227,7 +37370,7 @@ async function generateAndCheck(root, req, opts) {
37227
37370
  }
37228
37371
  const rel = `${dir}/${gen.name}.lean`;
37229
37372
  writeFileInRootNoFollow(root, rel, gen.source);
37230
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
37373
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path49.join)(root, rel);
37231
37374
  const report = await opts.deps.check(root, abs);
37232
37375
  const abstracts = report.header?.abstracts ?? [];
37233
37376
  const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
@@ -37241,14 +37384,14 @@ async function generateAndCheck(root, req, opts) {
37241
37384
  const g = basisOf(p.source, files);
37242
37385
  return g.ok ? [] : [`${p.id}: ${g.why}`];
37243
37386
  });
37244
- if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd };
37387
+ if (bad.length === 0) return { ok: true, name: gen.name, file: rel, report, rounds: round, costUsd, ...warning ? { warning } : {} };
37245
37388
  lastError = ungroundedMessage(bad.join("; "));
37246
37389
  if (round < maxRounds) {
37247
37390
  previous = { source: gen.source, error: lastError };
37248
37391
  continue;
37249
37392
  }
37250
37393
  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 };
37394
+ if (grounded.length > 0) return { ok: true, name: gen.name, file: rel, report: { ...report, properties: grounded }, rounds: round, costUsd, ...warning ? { warning } : {} };
37252
37395
  break;
37253
37396
  }
37254
37397
  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");
@@ -37274,9 +37417,16 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
37274
37417
  }
37275
37418
  const build = await buildLibraryAsync(toolchain, root, 9e4);
37276
37419
  if (!build.ok) return { ok: false, skip: "library-build-failed", detail: build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).join(" ").slice(0, 200) };
37420
+ const code = await loadCodeContext(root, env, codeSource);
37421
+ return { ok: true, deps: { ...defaultDeps({ auth: auth2, apiKey, env, toolchain, readSource, ...code }), codeSource: code.codeSource } };
37422
+ }
37423
+ async function loadCodeContext(root, env = process.env, codeSource) {
37277
37424
  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 } };
37425
+ return { codeMap: loaded.ok ? loaded.map : null, codeSource: codeSource ?? withoutPaths(worktreeSource(root), isDeniedPath) };
37426
+ }
37427
+ async function onDemandDeps(root, opts) {
37428
+ const code = await loadCodeContext(root, opts.env);
37429
+ return { ...defaultDeps({ ...opts, tier: "deep", ...code }), codeSource: code.codeSource };
37280
37430
  }
37281
37431
  function changedFunction(codeMap, file, content, changed) {
37282
37432
  const outline = codeMap.outline(file, content);
@@ -37351,13 +37501,138 @@ function describeFormalOutcome(o) {
37351
37501
  return `formal: ${o.model?.name ?? "?"} on ${o.target?.file ?? "?"}#${o.target?.symbol ?? "?"} (${o.model?.rounds ?? 1} round${o.model?.rounds === 1 ? "" : "s"}) \xB7 ${parts2.join(" \xB7 ")} \xB7 ${Math.round(o.durationMs / 1e3)} s${cost}${cut}`;
37352
37502
  }
37353
37503
 
37504
+ // src/lib/prove/record.ts
37505
+ var RECORD_TIMEOUT_MS = 8e3;
37506
+ var HOOK_EXIT_MARGIN_MS = 5e3;
37507
+ var MIN_RECORD_POST_MS = 1e3;
37508
+ function guardRecordDeadline(hookStartedAt) {
37509
+ return hookStartedAt + GUARD_TIMEOUT_MS - HOOK_EXIT_MARGIN_MS;
37510
+ }
37511
+ function recordPostTimeout(now, deadlineAt, timeoutMs = RECORD_TIMEOUT_MS) {
37512
+ if (deadlineAt === void 0) return timeoutMs;
37513
+ const left = deadlineAt - now;
37514
+ return left < MIN_RECORD_POST_MS ? null : Math.min(timeoutMs, left);
37515
+ }
37516
+ var norm2 = (p) => p.replace(/\\/g, "/");
37517
+ var SAFE_SEGMENT = /^[A-Za-z0-9._@+~$()[\]-]{1,255}$/;
37518
+ function safeRepoPath(p) {
37519
+ const n = norm2(p);
37520
+ if (!n || n.length > 512 || n.startsWith("/") || /^[A-Za-z]:\//.test(n)) return null;
37521
+ return n.split("/").every((s) => s !== "." && s !== ".." && SAFE_SEGMENT.test(s)) ? n : null;
37522
+ }
37523
+ var SYMBOL = /^[A-Za-z_$][\w$]*(?:[.#:][A-Za-z_$][\w$]*)*$/;
37524
+ var IDENT3 = /^[A-Za-z][\w]*$/;
37525
+ var TRACE_STEP = /^[A-Za-z_]\w{0,63}$/;
37526
+ var ELIDED_STEP = "\u2026";
37527
+ function recordBasis(source2) {
37528
+ if (typeof source2 !== "string") return "";
37529
+ if (/^rule:[a-z-]+$/.test(source2)) return source2;
37530
+ const m = /^(?:([^:\s]+):)?L(\d+)(?::|$)/.exec(source2);
37531
+ return m ? m[1] ? `${norm2(m[1])}:L${m[2]}` : `L${m[2]}` : "";
37532
+ }
37533
+ function recordTrace(trace) {
37534
+ return trace.slice(0, 16).map((s) => {
37535
+ const name2 = (s.trim().split(/[\s(]/, 1)[0] ?? "").split(".").pop() ?? "";
37536
+ return TRACE_STEP.test(name2) ? name2 : ELIDED_STEP;
37537
+ });
37538
+ }
37539
+ var ident2 = (s, re, max) => typeof s === "string" && s.length <= max && re.test(s) ? s : null;
37540
+ var kind = (k) => k === "intent" ? "intent" : "structural";
37541
+ var signalsOf = (c) => c && typeof c.commits === "number" && typeof c.fixCommits === "number" ? { commits: c.commits, fix_commits: c.fixCommits, risk: Object.fromEntries(Object.entries(c.risk ?? {}).filter(([, n]) => typeof n === "number" && n > 0).slice(0, 16)) } : null;
37542
+ function buildPhaseRecord(outcome, ctx) {
37543
+ const pushed = new Set(ctx.pushedFiles.map(norm2));
37544
+ const blocks = (f) => ctx.moment === "push" && f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file));
37545
+ const symbol = (s) => ident2(s, SYMBOL, 200);
37546
+ return {
37547
+ moment: ctx.moment,
37548
+ status: outcome.status,
37549
+ skip: outcome.skip ?? null,
37550
+ parent_run_id: ctx.parentRunId,
37551
+ target: outcome.target && symbol(outcome.target.symbol) && safeRepoPath(outcome.target.file) ? {
37552
+ file: safeRepoPath(outcome.target.file),
37553
+ symbol: symbol(outcome.target.symbol),
37554
+ lines: outcome.target.lines ?? null,
37555
+ score: Math.max(0, Math.min(1, outcome.target.score)),
37556
+ extent: ident2(outcome.target.extent, /^[a-z-]+(?::[a-z-]+)?$/, 60),
37557
+ signals: signalsOf(outcome.target.signals)
37558
+ } : null,
37559
+ candidates: (outcome.candidates ?? []).filter((c) => safeRepoPath(c.file)).slice(0, 12).map((c) => ({
37560
+ file: safeRepoPath(c.file),
37561
+ symbol: c.symbol === null ? null : symbol(c.symbol),
37562
+ score: c.score === null ? null : Math.max(0, Math.min(1, c.score)),
37563
+ criteria: c.criteria,
37564
+ reasked: c.reasked,
37565
+ signals: signalsOf(c)
37566
+ })),
37567
+ model: outcome.model && ident2(outcome.model.name, /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)*$/, 120) ? { name: outcome.model.name, rounds: Math.max(0, Math.min(20, outcome.model.rounds)) } : null,
37568
+ properties: (outcome.properties ?? []).filter((p) => ident2(p.id, IDENT3, 120)).slice(0, 16).map((p) => ({
37569
+ id: p.id,
37570
+ kind: kind(p.kind),
37571
+ basis: recordBasis(p.source),
37572
+ result: p.result,
37573
+ bound: p.bound ?? null,
37574
+ states: p.states ?? null
37575
+ })),
37576
+ findings: outcome.findings.filter((f) => ident2(f.property, IDENT3, 120) && symbol(f.symbol) && safeRepoPath(f.file)).slice(0, 8).map((f) => ({
37577
+ property: f.property,
37578
+ kind: kind(f.kind),
37579
+ trace: recordTrace(f.trace),
37580
+ file: safeRepoPath(f.file),
37581
+ symbol: f.symbol,
37582
+ verdict: f.verdict,
37583
+ waived: f.waived === true,
37584
+ blocked: blocks(f)
37585
+ })),
37586
+ grounding: outcome.grounding ? {
37587
+ sent_back: outcome.grounding.sentBack,
37588
+ dropped: outcome.grounding.dropped.filter((id) => ident2(id, IDENT3, 120)).slice(0, 16),
37589
+ trigger_missing: (outcome.grounding.triggerMissing ?? []).filter((id) => ident2(id, IDENT3, 120)).slice(0, 16)
37590
+ } : null,
37591
+ usage: {
37592
+ input_tokens: outcome.usage.inputTokens,
37593
+ output_tokens: outcome.usage.outputTokens,
37594
+ cost_usd: outcome.usage.costUsd,
37595
+ unpriced: outcome.usage.unpriced
37596
+ },
37597
+ duration_ms: Math.round(outcome.durationMs)
37598
+ };
37599
+ }
37600
+ async function postPhaseRecord(outcome, ctx, post) {
37601
+ try {
37602
+ const timeout = recordPostTimeout((post.now ?? Date.now)(), post.deadlineAt, post.timeoutMs ?? RECORD_TIMEOUT_MS);
37603
+ if (timeout === null) {
37604
+ logEvent("formal_record_skipped", { moment: ctx.moment, reason: "hook-deadline" });
37605
+ return null;
37606
+ }
37607
+ const res = await apiRequest({
37608
+ method: "POST",
37609
+ path: "/prove/record",
37610
+ serviceUrl: post.serviceUrl,
37611
+ token: post.token,
37612
+ body: buildPhaseRecord(outcome, ctx),
37613
+ timeout,
37614
+ cmd: "prove-record"
37615
+ });
37616
+ if (!res.ok) {
37617
+ logEvent("formal_record_failed", { moment: ctx.moment, category: res.category ?? "unknown", http_status: res.http_status ?? null });
37618
+ return null;
37619
+ }
37620
+ const runId = typeof res.data?.run_id === "string" ? res.data.run_id : null;
37621
+ logEvent("formal_record", { moment: ctx.moment, run_id: runId });
37622
+ return runId;
37623
+ } catch (err2) {
37624
+ logEvent("formal_record_failed", { moment: ctx.moment, category: "exception", name: err2?.constructor?.name ?? "Error" });
37625
+ return null;
37626
+ }
37627
+ }
37628
+
37354
37629
  // src/commands/guard.ts
37355
37630
  var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
37356
37631
  var WRITERS_BUDGET_MS = 1500;
37357
37632
  var EXCERPT_MAX_LINES2 = 30;
37358
37633
  var VENDORED_READ_MAX_BYTES = 256 * 1024;
37359
37634
  var GUARD_BLOCK_CAP = 2;
37360
- var GUARD_ITER_FILE = (0, import_node_path48.join)(VERITY_DIR, ".guard-iteration");
37635
+ var GUARD_ITER_FILE = (0, import_node_path50.join)(VERITY_DIR, ".guard-iteration");
37361
37636
  function readPreToolUseStdin() {
37362
37637
  const empty = { command: "", cwd: null, sessionId: null };
37363
37638
  return new Promise((resolve9) => {
@@ -37402,7 +37677,7 @@ function readPreToolUseStdin() {
37402
37677
  }
37403
37678
  function readIterMap() {
37404
37679
  try {
37405
- const raw = JSON.parse((0, import_node_fs61.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37680
+ const raw = JSON.parse((0, import_node_fs62.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37406
37681
  if (raw && typeof raw === "object") {
37407
37682
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
37408
37683
  return { [raw.moment]: raw.count };
@@ -37422,10 +37697,10 @@ function readIter(moment) {
37422
37697
  }
37423
37698
  function writeIter(moment, count) {
37424
37699
  try {
37425
- (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37700
+ (0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
37426
37701
  const map = readIterMap();
37427
37702
  map[moment] = count;
37428
- (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37703
+ (0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37429
37704
  } catch {
37430
37705
  }
37431
37706
  }
@@ -37435,10 +37710,10 @@ function resetIter(moment) {
37435
37710
  if (!(moment in map)) return;
37436
37711
  delete map[moment];
37437
37712
  if (Object.keys(map).length === 0) {
37438
- if ((0, import_node_fs61.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs61.unlinkSync)(GUARD_ITER_FILE);
37713
+ if ((0, import_node_fs62.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs62.unlinkSync)(GUARD_ITER_FILE);
37439
37714
  } else {
37440
- (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37441
- (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37715
+ (0, import_node_fs62.mkdirSync)(VERITY_DIR, { recursive: true });
37716
+ (0, import_node_fs62.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37442
37717
  }
37443
37718
  } catch {
37444
37719
  }
@@ -37508,7 +37783,7 @@ function hasBlockingFinding(response, sentFiles) {
37508
37783
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
37509
37784
  const analyzable = filterAnalyzable(files);
37510
37785
  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);
37786
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs62.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
37512
37787
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
37513
37788
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
37514
37789
  const requestBody = {
@@ -37521,7 +37796,7 @@ function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedInte
37521
37796
  agent_harness: "claude-code",
37522
37797
  // Prefer the session id Claude Code passes on the hook payload; fall back
37523
37798
  // to the env var, then 'unknown'.
37524
- session_id: sessionId ?? process.env.CLAUDE_SESSION_ID ?? "unknown",
37799
+ session_id: sessionId ?? envSessionId() ?? "unknown",
37525
37800
  trigger,
37526
37801
  iteration: iter + 1
37527
37802
  }
@@ -37925,6 +38200,13 @@ async function runGuard(opts, globals) {
37925
38200
  const witnessed = [...codeDelta.files.map((f) => f.path), ...agentVerdict?.witnessed_files ?? []];
37926
38201
  mergeFormalFindings(response, formalOutcome, files);
37927
38202
  decision = response.gate_decision ?? "(unrecognised)";
38203
+ if (formalOutcome) {
38204
+ await postPhaseRecord(formalOutcome, {
38205
+ moment: "push",
38206
+ parentRunId: typeof response.run_id === "string" ? response.run_id : null,
38207
+ pushedFiles: files
38208
+ }, { serviceUrl: urlResult.data, token: tokenResult.data.token, deadlineAt: guardRecordDeadline(hookStartedAt) });
38209
+ }
37928
38210
  if (!result.ok) {
37929
38211
  const authRemedy = result.error.startsWith("STALE_VERIFICATION") ? " Your GitHub verification expired \u2014 run `verity login` to re-verify." : result.error.startsWith("FORBIDDEN") ? " No access grant for this repository \u2014 run `verity login` to refresh your grants." : result.error.startsWith("INVALID_TOKEN") ? " Your Verity login expired or was revoked \u2014 run `verity login` to sign in again." : "";
37930
38212
  if (oneShotLostOutcome({ agentGate: decision, agentBlocking: hasBlockingFinding(response, witnessed) }) === "block") {
@@ -38042,7 +38324,7 @@ function writeBlockMessage(moment, response, covDetail) {
38042
38324
 
38043
38325
  // src/commands/ignore.ts
38044
38326
  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) => {
38327
+ const ignore = program2.command("ignore").description("Declare the next turn (or a short window) as housekeeping \u2014 no review needed").option("--turn", "Cover the next turn only (the default)").option("--for <duration>", "Cover a window: 30m, 45s, 1h (max 60m)").option("--reason <reason>", "Why this window needs no review \u2014 required, and recorded").option("--agent", "Mark the declaration as agent-invoked (a ledger label, not a permission)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").option("--json", "Output raw JSON").action(async (opts) => {
38046
38328
  const globals = program2.opts();
38047
38329
  const now = Math.floor(Date.now() / 1e3);
38048
38330
  const reason = opts.reason?.trim();
@@ -38069,7 +38351,7 @@ function registerIgnoreCommand(program2) {
38069
38351
  }
38070
38352
  const tokenResult = await resolveToken(globals.token);
38071
38353
  const token = tokenResult.ok ? tokenResult.data.token : void 0;
38072
- const sessionId = opts.sessionId || process.env.CLAUDE_SESSION_ID || void 0;
38354
+ const sessionId = opts.sessionId || envSessionId();
38073
38355
  const keys = ignoreStateKeys(token, sessionId);
38074
38356
  const existing = resolveIgnoreState(keys);
38075
38357
  const spent = existing?.state.spent ?? 0;
@@ -38115,11 +38397,11 @@ function registerIgnoreCommand(program2) {
38115
38397
  printInfo(`Verity will skip ${window2} \u2014 "${reason}" (${spent + 1}/${IGNORE_BUDGET} this session).`);
38116
38398
  printInfo("It covers turns that author nothing. If anything is written, the declaration voids and the review runs.");
38117
38399
  });
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) => {
38400
+ ignore.command("clear").description("Cancel the active declaration (the spent budget is not refunded)").option("--session-id <id>", "Session id (defaults to $CLAUDE_SESSION_ID, then $CLAUDE_CODE_SESSION_ID)").action(async (opts) => {
38119
38401
  const globals = program2.opts();
38120
38402
  const tokenResult = await resolveToken(globals.token);
38121
38403
  const token = tokenResult.ok ? tokenResult.data.token : void 0;
38122
- const sessionId = opts.sessionId || process.env.CLAUDE_SESSION_ID || void 0;
38404
+ const sessionId = opts.sessionId || envSessionId();
38123
38405
  const found = resolveIgnoreState(ignoreStateKeys(token, sessionId));
38124
38406
  const active = resolveActive(found?.state ?? null, Math.floor(Date.now() / 1e3));
38125
38407
  if (!found || !active) {
@@ -38134,7 +38416,7 @@ function registerIgnoreCommand(program2) {
38134
38416
 
38135
38417
  // src/commands/waive.ts
38136
38418
  var import_node_crypto20 = require("node:crypto");
38137
- var import_node_fs62 = require("node:fs");
38419
+ var import_node_fs63 = require("node:fs");
38138
38420
  function registerWaiveCommand(program2) {
38139
38421
  program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
38140
38422
  const globals = program2.opts();
@@ -38163,7 +38445,7 @@ function registerWaiveCommand(program2) {
38163
38445
  if (opts.file) {
38164
38446
  body2.file = opts.file;
38165
38447
  try {
38166
- body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs62.readFileSync)(opts.file)).digest("hex");
38448
+ body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs63.readFileSync)(opts.file)).digest("hex");
38167
38449
  } catch {
38168
38450
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
38169
38451
  process.exit(1);
@@ -38188,10 +38470,10 @@ function registerWaiveCommand(program2) {
38188
38470
  }
38189
38471
 
38190
38472
  // src/commands/init.ts
38191
- var import_node_fs67 = require("node:fs");
38473
+ var import_node_fs68 = require("node:fs");
38192
38474
  var import_promises20 = require("node:fs/promises");
38193
38475
  var import_yaml6 = __toESM2(require_dist());
38194
- var import_node_path52 = require("node:path");
38476
+ var import_node_path54 = require("node:path");
38195
38477
  var import_node_os11 = require("node:os");
38196
38478
  var import_node_child_process19 = require("node:child_process");
38197
38479
 
@@ -38271,7 +38553,7 @@ function printPhase(n, of, title, subtitle) {
38271
38553
  }
38272
38554
 
38273
38555
  // src/commands/doctor.ts
38274
- var import_node_fs63 = require("node:fs");
38556
+ var import_node_fs64 = require("node:fs");
38275
38557
 
38276
38558
  // src/lib/prereqs.ts
38277
38559
  var import_node_child_process16 = require("node:child_process");
@@ -38479,11 +38761,11 @@ async function buildReport() {
38479
38761
  const hooks = wiring.status;
38480
38762
  const provenance = cliProvenance();
38481
38763
  const telemetry = await checkTelemetry();
38482
- const hasConfig = (0, import_node_fs63.existsSync)(projectPath(CODACY_CONFIG_FILE));
38764
+ const hasConfig = (0, import_node_fs64.existsSync)(projectPath(CODACY_CONFIG_FILE));
38483
38765
  const artifacts = {
38484
- standard: (0, import_node_fs63.existsSync)(projectPath(STANDARD_FILE)),
38766
+ standard: (0, import_node_fs64.existsSync)(projectPath(STANDARD_FILE)),
38485
38767
  analysisConfig: hasConfig,
38486
- verityMd: (0, import_node_fs63.existsSync)(projectPath(VERITY_MD_FILE)),
38768
+ verityMd: (0, import_node_fs64.existsSync)(projectPath(VERITY_MD_FILE)),
38487
38769
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
38488
38770
  };
38489
38771
  const next = [];
@@ -38642,8 +38924,8 @@ function registerDoctorCommand(program2) {
38642
38924
  }
38643
38925
 
38644
38926
  // src/commands/migrate.ts
38645
- var import_node_fs64 = require("node:fs");
38646
- var import_node_path49 = require("node:path");
38927
+ var import_node_fs65 = require("node:fs");
38928
+ var import_node_path51 = require("node:path");
38647
38929
  var import_node_child_process17 = require("node:child_process");
38648
38930
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
38649
38931
  function defaultNpmRemover(pkg) {
@@ -38680,12 +38962,12 @@ async function runMigration(opts = {}) {
38680
38962
  return { actions, migrated: actions.length > 0 };
38681
38963
  }
38682
38964
  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)) {
38965
+ const gateDir = (0, import_node_path51.join)(root, ".gate");
38966
+ const verityDir = (0, import_node_path51.join)(root, ".verity");
38967
+ if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) {
38686
38968
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
38687
38969
  }
38688
- if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
38970
+ if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
38689
38971
  return migrateProjectDirCarry(gateDir, verityDir, actions);
38690
38972
  }
38691
38973
  return false;
@@ -38706,13 +38988,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
38706
38988
  }
38707
38989
  }
38708
38990
  if (moved) {
38709
- if ((0, import_node_fs64.existsSync)(gateDir)) {
38991
+ if ((0, import_node_fs65.existsSync)(gateDir)) {
38710
38992
  const carried = carryLegacyContents(gateDir, verityDir);
38711
38993
  if (carried > 0) {
38712
38994
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
38713
38995
  }
38714
38996
  try {
38715
- (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
38997
+ (0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
38716
38998
  } catch {
38717
38999
  }
38718
39000
  }
@@ -38728,18 +39010,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
38728
39010
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
38729
39011
  }
38730
39012
  try {
38731
- (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
39013
+ (0, import_node_fs65.rmSync)(gateDir, { recursive: true, force: true });
38732
39014
  } catch {
38733
39015
  }
38734
39016
  return carried > 0;
38735
39017
  }
38736
39018
  function migrateGlobalCredentials(home, actions) {
38737
39019
  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 });
39020
+ const gateCreds = (0, import_node_path51.join)(home, ".gate", "credentials");
39021
+ const verityCreds = (0, import_node_path51.join)(home, ".verity", "credentials");
39022
+ if (!(0, import_node_fs65.existsSync)(gateCreds)) return;
39023
+ if (!(0, import_node_fs65.existsSync)(verityCreds)) {
39024
+ (0, import_node_fs65.mkdirSync)((0, import_node_path51.join)(home, ".verity"), { recursive: true });
38743
39025
  moveFile(gateCreds, verityCreds);
38744
39026
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
38745
39027
  return;
@@ -38761,8 +39043,8 @@ async function migrateLegacyHooks(root, actions) {
38761
39043
  }
38762
39044
  }
38763
39045
  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));
39046
+ const claudeMd = (0, import_node_path51.join)(root, "CLAUDE.md");
39047
+ const hadLegacyBlock = (0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38766
39048
  if (!hadLegacyBlock) return;
38767
39049
  try {
38768
39050
  await ensureClaudeMdPointer(root);
@@ -38772,9 +39054,9 @@ async function migrateClaudeMd(root, actions) {
38772
39054
  }
38773
39055
  }
38774
39056
  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;
39057
+ const gateMd = (0, import_node_path51.join)(root, "GATE.md");
39058
+ const verityMd = (0, import_node_path51.join)(root, "VERITY.md");
39059
+ if (!(0, import_node_fs65.existsSync)(gateMd) || (0, import_node_fs65.existsSync)(verityMd)) return;
38778
39060
  let moved = false;
38779
39061
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
38780
39062
  try {
@@ -38786,12 +39068,12 @@ function migrateStandardFile(root, actions) {
38786
39068
  if (!moved) moveFile(gateMd, verityMd);
38787
39069
  const content = readFileSyncSafe(verityMd);
38788
39070
  const refreshed = content.split("GATE.md").join("VERITY.md");
38789
- if (refreshed !== content) (0, import_node_fs64.writeFileSync)(verityMd, refreshed);
39071
+ if (refreshed !== content) (0, import_node_fs65.writeFileSync)(verityMd, refreshed);
38790
39072
  actions.push("Renamed GATE.md \u2192 VERITY.md");
38791
39073
  }
38792
39074
  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;
39075
+ const file = (0, import_node_path51.join)(root, ".claude", "settings.local.json");
39076
+ if (!(0, import_node_fs65.existsSync)(file)) return;
38795
39077
  let settings;
38796
39078
  try {
38797
39079
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -38838,15 +39120,15 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
38838
39120
  toAppend.push(line2.replace(/\r$/, ""));
38839
39121
  }
38840
39122
  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");
39123
+ const sep7 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
39124
+ (0, import_node_fs65.writeFileSync)(verityCreds, verityContent + sep7 + toAppend.join("\n") + "\n");
38843
39125
  }
38844
- (0, import_node_fs64.rmSync)(gateCreds, { force: true });
39126
+ (0, import_node_fs65.rmSync)(gateCreds, { force: true });
38845
39127
  return toAppend.length;
38846
39128
  }
38847
39129
  function readFileSyncSafe(path) {
38848
39130
  try {
38849
- return (0, import_node_fs64.readFileSync)(path, "utf-8");
39131
+ return (0, import_node_fs65.readFileSync)(path, "utf-8");
38850
39132
  } catch {
38851
39133
  return "";
38852
39134
  }
@@ -38861,35 +39143,35 @@ function hasStagedChanges(root) {
38861
39143
  }
38862
39144
  function moveDir(from, to) {
38863
39145
  try {
38864
- (0, import_node_fs64.renameSync)(from, to);
39146
+ (0, import_node_fs65.renameSync)(from, to);
38865
39147
  } catch (err2) {
38866
39148
  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 });
39149
+ (0, import_node_fs65.cpSync)(from, to, { recursive: true });
39150
+ (0, import_node_fs65.rmSync)(from, { recursive: true, force: true });
38869
39151
  }
38870
39152
  }
38871
39153
  function moveFile(from, to) {
38872
39154
  try {
38873
- (0, import_node_fs64.renameSync)(from, to);
39155
+ (0, import_node_fs65.renameSync)(from, to);
38874
39156
  } catch (err2) {
38875
39157
  if (err2.code !== "EXDEV") throw err2;
38876
- (0, import_node_fs64.cpSync)(from, to);
38877
- (0, import_node_fs64.rmSync)(from, { force: true });
39158
+ (0, import_node_fs65.cpSync)(from, to);
39159
+ (0, import_node_fs65.rmSync)(from, { force: true });
38878
39160
  }
38879
39161
  }
38880
39162
  function carryLegacyContents(gateDir, verityDir) {
38881
39163
  let copied = 0;
38882
39164
  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()) {
39165
+ const srcDir = (0, import_node_path51.join)(gateDir, relDir);
39166
+ for (const entry of (0, import_node_fs65.readdirSync)(srcDir)) {
39167
+ const rel = relDir ? (0, import_node_path51.join)(relDir, entry) : entry;
39168
+ const src = (0, import_node_path51.join)(gateDir, rel);
39169
+ const dest = (0, import_node_path51.join)(verityDir, rel);
39170
+ if ((0, import_node_fs65.statSync)(src).isDirectory()) {
38889
39171
  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);
39172
+ } else if (!(0, import_node_fs65.existsSync)(dest)) {
39173
+ (0, import_node_fs65.mkdirSync)((0, import_node_path51.dirname)(dest), { recursive: true });
39174
+ (0, import_node_fs65.cpSync)(src, dest);
38893
39175
  copied++;
38894
39176
  }
38895
39177
  }
@@ -38898,22 +39180,22 @@ function carryLegacyContents(gateDir, verityDir) {
38898
39180
  return copied;
38899
39181
  }
38900
39182
  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"))) {
39183
+ const gateDir = (0, import_node_path51.join)(root, ".gate");
39184
+ const verityDir = (0, import_node_path51.join)(root, ".verity");
39185
+ if ((0, import_node_fs65.existsSync)(gateDir) && !(0, import_node_fs65.existsSync)(verityDir)) return true;
39186
+ if ((0, import_node_fs65.existsSync)(gateDir) && (0, import_node_fs65.existsSync)(verityDir)) {
39187
+ if ((0, import_node_fs65.existsSync)((0, import_node_path51.join)(gateDir, "credentials")) && !(0, import_node_fs65.existsSync)((0, import_node_path51.join)(verityDir, "credentials"))) {
38906
39188
  return true;
38907
39189
  }
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"))) {
39190
+ if ((0, import_node_fs65.existsSync)((0, import_node_path51.join)(gateDir, "memory")) && !(0, import_node_fs65.existsSync)((0, import_node_path51.join)(verityDir, "memory"))) {
38909
39191
  return true;
38910
39192
  }
38911
39193
  }
38912
- const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38913
- if ((0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
39194
+ const claudeMd = (0, import_node_path51.join)(root, "CLAUDE.md");
39195
+ if ((0, import_node_fs65.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38914
39196
  return true;
38915
39197
  }
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"))) {
39198
+ if ((0, import_node_fs65.existsSync)((0, import_node_path51.join)(root, "GATE.md")) && !(0, import_node_fs65.existsSync)((0, import_node_path51.join)(root, "VERITY.md"))) {
38917
39199
  return true;
38918
39200
  }
38919
39201
  if (await hasLegacyHooksAt(root)) return true;
@@ -39194,11 +39476,11 @@ async function promptMultiSelect(question, choices, fallback) {
39194
39476
  }
39195
39477
 
39196
39478
  // src/lib/prove/lean-install.ts
39197
- var import_node_fs65 = require("node:fs");
39479
+ var import_node_fs66 = require("node:fs");
39198
39480
  var import_node_crypto21 = require("node:crypto");
39199
39481
  var import_node_child_process18 = require("node:child_process");
39200
39482
  var import_node_os10 = require("node:os");
39201
- var import_node_path50 = require("node:path");
39483
+ var import_node_path52 = require("node:path");
39202
39484
  var import_promises18 = require("node:stream/promises");
39203
39485
  var import_node_stream = require("node:stream");
39204
39486
  var RELEASES = "https://releases.lean-lang.org/lean4";
@@ -39209,10 +39491,10 @@ function freeBytes(dir) {
39209
39491
  let d = dir;
39210
39492
  for (let i2 = 0; i2 < 64; i2++) {
39211
39493
  try {
39212
- const st = (0, import_node_fs65.statfsSync)(d);
39494
+ const st = (0, import_node_fs66.statfsSync)(d);
39213
39495
  return Number(st.bavail) * Number(st.bsize);
39214
39496
  } catch {
39215
- const up = (0, import_node_path50.join)(d, "..");
39497
+ const up = (0, import_node_path52.join)(d, "..");
39216
39498
  if (up === d) return null;
39217
39499
  d = up;
39218
39500
  }
@@ -39234,7 +39516,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
39234
39516
  function sha256File(path) {
39235
39517
  return new Promise((resolve9, reject) => {
39236
39518
  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);
39519
+ (0, import_node_fs66.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
39238
39520
  });
39239
39521
  }
39240
39522
  async function verifyDownload(zip, asset, version = pinnedVersion()) {
@@ -39254,7 +39536,7 @@ function leanAssetName(version = pinnedVersion()) {
39254
39536
  return suffix ? `lean-${v}-${suffix}.zip` : null;
39255
39537
  }
39256
39538
  function pinnedVersionDir(env = process.env) {
39257
- return (0, import_node_path50.join)(verityLeanHome(env), pinnedVersion());
39539
+ return (0, import_node_path52.join)(verityLeanHome(env), pinnedVersion());
39258
39540
  }
39259
39541
  function lakeBinary() {
39260
39542
  return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
@@ -39265,12 +39547,12 @@ function unzip(zip, dest) {
39265
39547
  for (const [cmd, args2] of attempts) {
39266
39548
  try {
39267
39549
  (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 };
39550
+ if ((0, import_node_fs66.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
39269
39551
  errors.push(`${cmd}: produced nothing`);
39270
39552
  } catch (err2) {
39271
39553
  errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
39272
39554
  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 });
39555
+ for (const e of (0, import_node_fs66.readdirSync)(dest)) (0, import_node_fs66.rmSync)((0, import_node_path52.join)(dest, e), { recursive: true, force: true });
39274
39556
  } catch {
39275
39557
  }
39276
39558
  }
@@ -39296,7 +39578,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
39296
39578
  seen += chunk.length;
39297
39579
  onProgress(seen, total);
39298
39580
  });
39299
- await (0, import_promises18.pipeline)(stream, (0, import_node_fs65.createWriteStream)(dest), { signal: ctrl.signal });
39581
+ await (0, import_promises18.pipeline)(stream, (0, import_node_fs66.createWriteStream)(dest), { signal: ctrl.signal });
39300
39582
  } catch (err2) {
39301
39583
  if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
39302
39584
  throw err2;
@@ -39346,10 +39628,10 @@ async function installLean(opts = {}) {
39346
39628
  const gb = (n) => (n / 1024 ** 3).toFixed(1);
39347
39629
  return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
39348
39630
  }
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);
39631
+ const tmp = (0, import_node_path52.join)(home, ".tmp");
39632
+ (0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
39633
+ (0, import_node_fs66.mkdirSync)(tmp, { recursive: true });
39634
+ const zip = (0, import_node_path52.join)(tmp, asset);
39353
39635
  say(`downloading ${url}`);
39354
39636
  let lastPct = -1;
39355
39637
  try {
@@ -39362,40 +39644,40 @@ async function installLean(opts = {}) {
39362
39644
  }
39363
39645
  });
39364
39646
  } catch (err2) {
39365
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39647
+ (0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
39366
39648
  return { ok: false, error: err2.message };
39367
39649
  }
39368
39650
  say("verifying checksum");
39369
39651
  const verified = await verifyDownload(zip, asset);
39370
39652
  if (!verified.ok) {
39371
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39653
+ (0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
39372
39654
  return { ok: false, error: verified.error };
39373
39655
  }
39374
39656
  say("unpacking (this takes a minute)");
39375
- const unpack = (0, import_node_path50.join)(tmp, "unpack");
39376
- (0, import_node_fs65.mkdirSync)(unpack);
39657
+ const unpack = (0, import_node_path52.join)(tmp, "unpack");
39658
+ (0, import_node_fs66.mkdirSync)(unpack);
39377
39659
  const unpacked = unzip(zip, unpack);
39378
39660
  if (!unpacked.ok) {
39379
- (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39661
+ (0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
39380
39662
  return { ok: false, error: `unpack failed: ${unpacked.error}` };
39381
39663
  }
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 });
39664
+ const entries = (0, import_node_fs66.readdirSync)(unpack);
39665
+ const top = entries.length === 1 && (0, import_node_fs66.statSync)((0, import_node_path52.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path52.join)(unpack, entries[0]) : unpack;
39666
+ if (!(0, import_node_fs66.existsSync)((0, import_node_path52.join)(top, "bin", lakeBinary()))) {
39667
+ (0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
39386
39668
  return { ok: false, error: "the archive did not contain bin/lake" };
39387
39669
  }
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 });
39670
+ (0, import_node_fs66.rmSync)(dir, { recursive: true, force: true });
39671
+ (0, import_node_fs66.mkdirSync)(home, { recursive: true });
39672
+ (0, import_node_fs66.renameSync)(top, dir);
39673
+ (0, import_node_fs66.rmSync)(tmp, { recursive: true, force: true });
39392
39674
  return { ok: true, dir };
39393
39675
  }
39394
39676
 
39395
39677
  // src/lib/remote-config.ts
39396
- var import_node_fs66 = require("node:fs");
39678
+ var import_node_fs67 = require("node:fs");
39397
39679
  var import_promises19 = require("node:fs/promises");
39398
- var import_node_path51 = require("node:path");
39680
+ var import_node_path53 = require("node:path");
39399
39681
  var import_yaml5 = __toESM2(require_dist());
39400
39682
  var IGNORE_RIDER = "verityignore";
39401
39683
  async function fetchRemoteSetup(opts) {
@@ -39440,7 +39722,7 @@ async function adoptRemoteSetup(found, opts) {
39440
39722
  written.push(STANDARD_FILE);
39441
39723
  if (rider !== null) {
39442
39724
  const localIgnore = projectPath(VERITYIGNORE_FILE);
39443
- if (!(0, import_node_fs66.existsSync)(localIgnore)) {
39725
+ if (!(0, import_node_fs67.existsSync)(localIgnore)) {
39444
39726
  await writeOut(VERITYIGNORE_FILE, rider);
39445
39727
  written.push(VERITYIGNORE_FILE);
39446
39728
  } else {
@@ -39471,9 +39753,9 @@ async function adoptRemoteSetup(found, opts) {
39471
39753
  written.push(VERITY_MD_FILE);
39472
39754
  return { written, notes };
39473
39755
  }
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 });
39756
+ async function writeOut(relative7, body2) {
39757
+ const target = projectPath(relative7);
39758
+ await (0, import_promises19.mkdir)((0, import_node_path53.dirname)(target), { recursive: true });
39477
39759
  await (0, import_promises19.writeFile)(target, body2);
39478
39760
  }
39479
39761
  function describeRemote(found) {
@@ -39590,15 +39872,15 @@ async function runOptionalAuth(resolution, opts = {}) {
39590
39872
  }
39591
39873
  function resolveDataDir2() {
39592
39874
  const candidates2 = [
39593
- (0, import_node_path52.join)(__dirname, "..", "data"),
39875
+ (0, import_node_path54.join)(__dirname, "..", "data"),
39594
39876
  // installed: node_modules/@codacy/verity-cli/data
39595
- (0, import_node_path52.join)(__dirname, "..", "..", "data"),
39877
+ (0, import_node_path54.join)(__dirname, "..", "..", "data"),
39596
39878
  // edge case: nested resolution
39597
- (0, import_node_path52.join)(process.cwd(), "cli", "data")
39879
+ (0, import_node_path54.join)(process.cwd(), "cli", "data")
39598
39880
  // local dev: running from repo root
39599
39881
  ];
39600
39882
  for (const candidate of candidates2) {
39601
- if ((0, import_node_fs67.existsSync)((0, import_node_path52.join)(candidate, "skills"))) {
39883
+ if ((0, import_node_fs68.existsSync)((0, import_node_path54.join)(candidate, "skills"))) {
39602
39884
  return candidate;
39603
39885
  }
39604
39886
  }
@@ -39614,9 +39896,9 @@ async function skillIsCurrent(src, dest) {
39614
39896
  const list2 = (dir) => {
39615
39897
  const out2 = [];
39616
39898
  const walk2 = (d, prefix) => {
39617
- for (const e of (0, import_node_fs67.readdirSync)(d, { withFileTypes: true })) {
39899
+ for (const e of (0, import_node_fs68.readdirSync)(d, { withFileTypes: true })) {
39618
39900
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
39619
- if (e.isDirectory()) walk2((0, import_node_path52.join)(d, e.name), rel);
39901
+ if (e.isDirectory()) walk2((0, import_node_path54.join)(d, e.name), rel);
39620
39902
  else if (e.isFile()) out2.push(rel);
39621
39903
  }
39622
39904
  };
@@ -39627,8 +39909,8 @@ async function skillIsCurrent(src, dest) {
39627
39909
  const shipped = list2(src);
39628
39910
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
39629
39911
  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");
39912
+ const a = await (0, import_promises20.readFile)((0, import_node_path54.join)(src, rel), "utf-8");
39913
+ const b = await (0, import_promises20.readFile)((0, import_node_path54.join)(dest, rel), "utf-8");
39632
39914
  if (a !== b) return false;
39633
39915
  }
39634
39916
  return true;
@@ -39724,7 +40006,7 @@ function parseTelemetryAnswer(raw) {
39724
40006
  return null;
39725
40007
  }
39726
40008
  function insideClaudeCode() {
39727
- return !!process.env.CLAUDECODE || !!process.env.CLAUDE_SESSION_ID;
40009
+ return !!process.env.CLAUDECODE || !!envSessionId();
39728
40010
  }
39729
40011
  function resumeDeferredPending(previous) {
39730
40012
  return previous?.telemetry === "deferred";
@@ -39831,7 +40113,7 @@ async function synthesizeLocally(opts) {
39831
40113
  async function healStaleAnalysisConfig(globals) {
39832
40114
  const configPath = projectPath(CODACY_CONFIG_FILE);
39833
40115
  const standardPath = projectPath(STANDARD_FILE);
39834
- if (!(0, import_node_fs67.existsSync)(configPath) || !(0, import_node_fs67.existsSync)(standardPath)) return;
40116
+ if (!(0, import_node_fs68.existsSync)(configPath) || !(0, import_node_fs68.existsSync)(standardPath)) return;
39835
40117
  const validation = validatePatternIds();
39836
40118
  if (validation.status !== "invalid") return;
39837
40119
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -39928,17 +40210,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
39928
40210
  async function installSkills(force, step) {
39929
40211
  step("Installing skills");
39930
40212
  const dataDir = resolveDataDir2();
39931
- const skillsSource = (0, import_node_path52.join)(dataDir, "skills");
40213
+ const skillsSource = (0, import_node_path54.join)(dataDir, "skills");
39932
40214
  const skillsDest = ".claude/skills";
39933
40215
  let skillsInstalled = 0;
39934
40216
  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)) {
40217
+ const src = (0, import_node_path54.join)(skillsSource, skill);
40218
+ const dest = (0, import_node_path54.join)(skillsDest, skill);
40219
+ if (!(0, import_node_fs68.existsSync)(src)) {
39938
40220
  printWarn(` Skill data not found: ${skill}`);
39939
40221
  continue;
39940
40222
  }
39941
- if ((0, import_node_fs67.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
40223
+ if ((0, import_node_fs68.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39942
40224
  skillsInstalled++;
39943
40225
  continue;
39944
40226
  }
@@ -40087,7 +40369,7 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
40087
40369
  if (!toolchain) {
40088
40370
  const dir = pinnedVersionDir();
40089
40371
  const home = (0, import_node_os11.homedir)();
40090
- const shown = dir.startsWith(home + import_node_path52.sep) ? `~${dir.slice(home.length)}` : dir;
40372
+ const shown = dir.startsWith(home + import_node_path54.sep) ? `~${dir.slice(home.length)}` : dir;
40091
40373
  console.log("");
40092
40374
  console.log(` "yes" installs Lean 4 (${LEAN_DOWNLOAD_SIZE}) into ${shown}`);
40093
40375
  }
@@ -40146,7 +40428,7 @@ function registerInitCommand(program2) {
40146
40428
  const staleMarker = clearStalePluginMarker();
40147
40429
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
40148
40430
  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));
40431
+ const isProject = projectMarkers.some((m) => (0, import_node_fs68.existsSync)(m));
40150
40432
  if (!isProject) {
40151
40433
  printError("No project detected in the current directory.");
40152
40434
  printInfo('Run "verity init" from your project root.');
@@ -40249,7 +40531,7 @@ function registerInitCommand(program2) {
40249
40531
  untrackMemory: opts.untrackMemory === true,
40250
40532
  untrackState: opts.untrackState === true
40251
40533
  });
40252
- const globalVerityDir = (0, import_node_path52.join)(process.env.HOME ?? "", ".verity");
40534
+ const globalVerityDir = (0, import_node_path54.join)(process.env.HOME ?? "", ".verity");
40253
40535
  await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
40254
40536
  console.log("");
40255
40537
  step("Wiring Claude Code hooks");
@@ -40324,7 +40606,7 @@ function registerInitCommand(program2) {
40324
40606
  }
40325
40607
  step("Your project's Standard");
40326
40608
  let haveStandard = false;
40327
- if ((0, import_node_fs67.existsSync)(projectPath(STANDARD_FILE))) {
40609
+ if ((0, import_node_fs68.existsSync)(projectPath(STANDARD_FILE))) {
40328
40610
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
40329
40611
  haveStandard = true;
40330
40612
  } else {
@@ -40354,7 +40636,7 @@ function registerInitCommand(program2) {
40354
40636
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
40355
40637
  init: {
40356
40638
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
40357
- cli_version: true ? "0.34.1" : "dev"
40639
+ cli_version: true ? "0.34.2" : "dev"
40358
40640
  }
40359
40641
  });
40360
40642
  } catch (err2) {
@@ -40404,8 +40686,8 @@ function registerInitCommand(program2) {
40404
40686
  }
40405
40687
 
40406
40688
  // src/commands/uninstall.ts
40407
- var import_node_fs68 = require("node:fs");
40408
- var import_node_path53 = require("node:path");
40689
+ var import_node_fs69 = require("node:fs");
40690
+ var import_node_path55 = require("node:path");
40409
40691
  function registerUninstallCommand(program2) {
40410
40692
  program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
40411
40693
  const dryRun = opts.dryRun ?? false;
@@ -40414,11 +40696,11 @@ function registerUninstallCommand(program2) {
40414
40696
  const actions = [];
40415
40697
  const skillsRoot = projectPath(".claude/skills");
40416
40698
  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)) {
40699
+ const dir = (0, import_node_path55.join)(skillsRoot, name2);
40700
+ if ((0, import_node_fs69.existsSync)(dir)) {
40419
40701
  actions.push({
40420
40702
  label: `Remove .claude/skills/${name2}/`,
40421
- apply: () => (0, import_node_fs68.rmSync)(dir, { recursive: true, force: true })
40703
+ apply: () => (0, import_node_fs69.rmSync)(dir, { recursive: true, force: true })
40422
40704
  });
40423
40705
  }
40424
40706
  }
@@ -40432,24 +40714,24 @@ function registerUninstallCommand(program2) {
40432
40714
  });
40433
40715
  }
40434
40716
  const verityDir = projectPath(VERITY_DIR);
40435
- if ((0, import_node_fs68.existsSync)(verityDir)) {
40717
+ if ((0, import_node_fs69.existsSync)(verityDir)) {
40436
40718
  actions.push({
40437
40719
  label: `Remove ${VERITY_DIR}/`,
40438
- apply: () => (0, import_node_fs68.rmSync)(verityDir, { recursive: true, force: true })
40720
+ apply: () => (0, import_node_fs69.rmSync)(verityDir, { recursive: true, force: true })
40439
40721
  });
40440
40722
  }
40441
40723
  if (!keepVerityMd) {
40442
40724
  const verityMd = projectPath(VERITY_MD_FILE);
40443
- if ((0, import_node_fs68.existsSync)(verityMd)) {
40725
+ if ((0, import_node_fs69.existsSync)(verityMd)) {
40444
40726
  actions.push({
40445
40727
  label: `Remove ${VERITY_MD_FILE}`,
40446
- apply: () => (0, import_node_fs68.rmSync)(verityMd, { force: true })
40728
+ apply: () => (0, import_node_fs69.rmSync)(verityMd, { force: true })
40447
40729
  });
40448
40730
  }
40449
40731
  }
40450
40732
  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);
40733
+ if ((0, import_node_fs69.existsSync)(path) && (0, import_node_fs69.statSync)(path).isDirectory() && (0, import_node_fs69.readdirSync)(path).length === 0) {
40734
+ (0, import_node_fs69.rmdirSync)(path);
40453
40735
  }
40454
40736
  };
40455
40737
  actions.push({
@@ -40460,11 +40742,11 @@ function registerUninstallCommand(program2) {
40460
40742
  }
40461
40743
  });
40462
40744
  const home = process.env.HOME ?? "";
40463
- const globalVerityDir = (0, import_node_path53.join)(home, ".verity");
40464
- if (purgeGlobal && (0, import_node_fs68.existsSync)(globalVerityDir)) {
40745
+ const globalVerityDir = (0, import_node_path55.join)(home, ".verity");
40746
+ if (purgeGlobal && (0, import_node_fs69.existsSync)(globalVerityDir)) {
40465
40747
  actions.push({
40466
40748
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
40467
- apply: () => (0, import_node_fs68.rmSync)(globalVerityDir, { recursive: true, force: true })
40749
+ apply: () => (0, import_node_fs69.rmSync)(globalVerityDir, { recursive: true, force: true })
40468
40750
  });
40469
40751
  }
40470
40752
  if (actions.length === 0) {
@@ -40491,9 +40773,26 @@ function registerUninstallCommand(program2) {
40491
40773
 
40492
40774
  // src/commands/task.ts
40493
40775
  function memoryPath() {
40494
- const sid = process.env.CLAUDE_SESSION_ID;
40776
+ const sid = envSessionId();
40495
40777
  return sid ? `/memory?session_id=${encodeURIComponent(sid)}` : "/memory";
40496
40778
  }
40779
+ var TASK_STATUSES = ["active", "closed", "merged"];
40780
+ var TASK_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
40781
+ function isTaskId(value) {
40782
+ return typeof value === "string" && TASK_ID.test(value);
40783
+ }
40784
+ function taskListPath(status) {
40785
+ if (status === void 0) return "/tasks";
40786
+ if (!TASK_STATUSES.includes(status)) return null;
40787
+ return `/tasks?status=${encodeURIComponent(status)}`;
40788
+ }
40789
+ function taskActionPath(taskId, action) {
40790
+ return isTaskId(taskId) ? `/tasks/${encodeURIComponent(taskId)}/${action}` : null;
40791
+ }
40792
+ function refuse(message) {
40793
+ printError(message);
40794
+ process.exit(1);
40795
+ }
40497
40796
  function timeAgo2(isoDate) {
40498
40797
  const ms = Date.now() - new Date(isoDate).getTime();
40499
40798
  const mins = Math.floor(ms / 6e4);
@@ -40521,10 +40820,11 @@ function registerTaskCommands(program2) {
40521
40820
  task.command("list").description("List tasks").option("--status <status>", "Filter by status (active, closed, merged)").action(async (opts) => {
40522
40821
  const globals = program2.opts();
40523
40822
  const { token, serviceUrl } = await getAuth(globals);
40524
- const statusParam = opts.status ? `?status=${opts.status}` : "";
40823
+ const listPath = taskListPath(opts.status);
40824
+ if (!listPath) refuse(`Unknown status ${JSON.stringify(String(opts.status).slice(0, 40))} \u2014 use one of: ${TASK_STATUSES.join(", ")}`);
40525
40825
  const result = await apiRequest({
40526
40826
  method: "GET",
40527
- path: `/tasks${statusParam}`,
40827
+ path: listPath,
40528
40828
  serviceUrl,
40529
40829
  token,
40530
40830
  verbose: globals.verbose,
@@ -40573,9 +40873,11 @@ function registerTaskCommands(program2) {
40573
40873
  }
40574
40874
  taskId = ct.id;
40575
40875
  }
40876
+ const closePath = taskActionPath(taskId, "close");
40877
+ if (!closePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
40576
40878
  const result = await apiRequest({
40577
40879
  method: "POST",
40578
- path: `/tasks/${taskId}/close`,
40880
+ path: closePath,
40579
40881
  serviceUrl,
40580
40882
  token,
40581
40883
  verbose: globals.verbose,
@@ -40622,9 +40924,11 @@ function registerTaskCommands(program2) {
40622
40924
  }
40623
40925
  taskId = ct.id;
40624
40926
  }
40927
+ const renamePath = taskActionPath(taskId, "rename");
40928
+ if (!renamePath) refuse(`Not a task id (expected a UUID): ${JSON.stringify(String(taskId).slice(0, 80))}`);
40625
40929
  const result = await apiRequest({
40626
40930
  method: "POST",
40627
- path: `/tasks/${taskId}/rename`,
40931
+ path: renamePath,
40628
40932
  serviceUrl,
40629
40933
  token,
40630
40934
  body: { label: label2.slice(0, 120) },
@@ -40639,6 +40943,9 @@ function registerTaskCommands(program2) {
40639
40943
  });
40640
40944
  task.command("merge <source> <target>").description("Merge source task into target task").action(async (source2, target) => {
40641
40945
  const globals = program2.opts();
40946
+ if (!isTaskId(source2) || !isTaskId(target)) {
40947
+ refuse("task merge takes two task ids (UUIDs): `verity task merge <source> <target>`");
40948
+ }
40642
40949
  const { token, serviceUrl } = await getAuth(globals);
40643
40950
  const result = await apiRequest({
40644
40951
  method: "POST",
@@ -40658,8 +40965,8 @@ function registerTaskCommands(program2) {
40658
40965
  }
40659
40966
 
40660
40967
  // src/commands/reset.ts
40661
- var import_node_fs69 = require("node:fs");
40662
- var import_node_path54 = require("node:path");
40968
+ var import_node_fs70 = require("node:fs");
40969
+ var import_node_path56 = require("node:path");
40663
40970
  function registerResetCommand(program2) {
40664
40971
  program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
40665
40972
  const globals = program2.opts();
@@ -40668,78 +40975,95 @@ function registerResetCommand(program2) {
40668
40975
  const tokenResult = await resolveToken(globals.token);
40669
40976
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
40670
40977
  if (tokenResult.ok && urlResult.ok) {
40978
+ const sessionId = envSessionId();
40671
40979
  const mem = await apiRequest({
40672
40980
  method: "GET",
40673
- path: process.env.CLAUDE_SESSION_ID ? `/memory?session_id=${encodeURIComponent(process.env.CLAUDE_SESSION_ID)}` : "/memory",
40981
+ path: sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory",
40674
40982
  serviceUrl: urlResult.data,
40675
40983
  token: tokenResult.data.token,
40676
40984
  timeout: 1e4,
40677
40985
  cmd: "reset_lookup"
40678
40986
  });
40679
40987
  const ct = mem.ok ? mem.data.current_task : null;
40680
- if (ct?.id) {
40988
+ const closePath = ct?.id ? taskActionPath(ct.id, "close") : null;
40989
+ if (ct?.id && !closePath) {
40990
+ printError("The current task in the service response has a malformed id \u2014 not closing it.");
40991
+ }
40992
+ if (closePath) {
40681
40993
  const closeResult = await apiRequest({
40682
40994
  method: "POST",
40683
- path: `/tasks/${ct.id}/close`,
40995
+ path: closePath,
40684
40996
  serviceUrl: urlResult.data,
40685
40997
  token: tokenResult.data.token,
40686
40998
  timeout: 1e4,
40687
40999
  cmd: "reset_close"
40688
41000
  });
40689
41001
  if (closeResult.ok) {
40690
- printInfo(`Closed task: "${ct.label}"`);
41002
+ printInfo(`Closed task: "${terminalText(ct?.label, 200) || "(unnamed)"}"`);
40691
41003
  }
40692
41004
  }
40693
41005
  }
40694
41006
  } catch {
40695
41007
  }
40696
41008
  }
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
- }
41009
+ const purged = purgeVerityDir((0, import_node_path56.basename)(CACHE_DIR), (name2) => name2.startsWith("pending-"));
41010
+ if (purged === null) printError(`Did not purge ${CACHE_DIR}: it is not a directory inside ${VERITY_DIR}.`);
41011
+ const stateDir2 = projectPath(VERITY_DIR);
40710
41012
  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`)
41013
+ (0, import_node_path56.basename)(INTENT_FILE),
41014
+ (0, import_node_path56.basename)(HASH_FILE),
41015
+ (0, import_node_path56.basename)(BASELINE_SHA_FILE),
41016
+ ".iteration-count",
41017
+ ".last-analysis"
40716
41018
  ];
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
- }
41019
+ for (const name2 of filesToClear) {
41020
+ if (lstatOrNull((0, import_node_path56.join)(stateDir2, name2)) && !replaceInRoot(stateDir2, name2, "")) {
41021
+ printError(`Did not clear ${VERITY_DIR}/${name2}: it is not a regular file inside ${VERITY_DIR}.`);
40723
41022
  }
40724
41023
  }
40725
41024
  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.");
41025
+ const logs = purgeVerityDir(".logs", () => true);
41026
+ if (logs === null) printError(`Did not clear ${VERITY_DIR}/.logs: it is not a directory inside ${VERITY_DIR}.`);
41027
+ else printInfo("Cleared diagnostic logs.");
40736
41028
  }
40737
- printInfo(`Reset complete. Purged ${purged} cached request${purged !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
41029
+ const count = purged ?? 0;
41030
+ printInfo(`Reset complete. Purged ${count} cached request${count !== 1 ? "s" : ""}.${opts.keepTask ? "" : " Next run starts a new task."}`);
40738
41031
  });
40739
41032
  }
41033
+ function lstatOrNull(path) {
41034
+ try {
41035
+ return (0, import_node_fs70.lstatSync)(path);
41036
+ } catch {
41037
+ return null;
41038
+ }
41039
+ }
41040
+ function purgeVerityDir(child, select) {
41041
+ const verityDir = projectPath(VERITY_DIR);
41042
+ const dir = (0, import_node_path56.join)(verityDir, child);
41043
+ const parent = lstatOrNull(verityDir);
41044
+ const st = lstatOrNull(dir);
41045
+ if (!st) return 0;
41046
+ if (!parent || parent.isSymbolicLink() || !parent.isDirectory()) return null;
41047
+ if (st.isSymbolicLink() || !st.isDirectory()) return null;
41048
+ try {
41049
+ if ((0, import_node_fs70.realpathSync)(dir) !== (0, import_node_path56.join)((0, import_node_fs70.realpathSync)(verityDir), child)) return null;
41050
+ } catch {
41051
+ return null;
41052
+ }
41053
+ let removed = 0;
41054
+ for (const entry of (0, import_node_fs70.readdirSync)(dir, { withFileTypes: true })) {
41055
+ if (entry.isDirectory() || !select(entry.name)) continue;
41056
+ try {
41057
+ (0, import_node_fs70.unlinkSync)((0, import_node_path56.join)(dir, entry.name));
41058
+ removed++;
41059
+ } catch {
41060
+ }
41061
+ }
41062
+ return removed;
41063
+ }
40740
41064
 
40741
41065
  // src/commands/reflect.ts
40742
- var import_node_fs70 = require("node:fs");
41066
+ var import_node_fs71 = require("node:fs");
40743
41067
 
40744
41068
  // src/lib/reflection-globs.ts
40745
41069
  var MAX_GLOBS = 6;
@@ -40777,7 +41101,7 @@ async function writeNodeToDisk(args2) {
40777
41101
  { treePaths: listTrackedFiles(), recordBaseline: false }
40778
41102
  );
40779
41103
  if (written === 0) return false;
40780
- return (0, import_node_fs70.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
41104
+ return (0, import_node_fs71.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40781
41105
  } catch {
40782
41106
  return false;
40783
41107
  }
@@ -40808,7 +41132,7 @@ function registerReflectCommand(program2) {
40808
41132
  let taskResolution = "flag";
40809
41133
  let inheritedGlobs = [];
40810
41134
  if (!taskId) {
40811
- const sessionId = process.env.CLAUDE_SESSION_ID ?? "";
41135
+ const sessionId = envSessionId() ?? "";
40812
41136
  const memPath = sessionId ? `/memory?session_id=${encodeURIComponent(sessionId)}` : "/memory";
40813
41137
  const mem = await apiRequest({
40814
41138
  method: "GET",
@@ -40853,7 +41177,7 @@ function registerReflectCommand(program2) {
40853
41177
  const userInput = input.text;
40854
41178
  if (userInput) {
40855
41179
  const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
40856
- const kind = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
41180
+ const kind2 = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
40857
41181
  const confirmed = opts.confirmed === true;
40858
41182
  const source2 = confirmed ? "user" : "agent";
40859
41183
  const explicitGlobs = Array.isArray(opts.fileGlobs) ? opts.fileGlobs.map((g) => g.trim()).filter(Boolean) : [];
@@ -40865,7 +41189,7 @@ function registerReflectCommand(program2) {
40865
41189
  serviceUrl,
40866
41190
  token,
40867
41191
  body: {
40868
- kind,
41192
+ kind: kind2,
40869
41193
  title: userInput.slice(0, 200),
40870
41194
  body: userInput,
40871
41195
  domains: [],
@@ -41214,9 +41538,9 @@ function registerRunCommand(program2) {
41214
41538
  }
41215
41539
 
41216
41540
  // src/commands/telemetry.ts
41217
- var import_node_fs71 = require("node:fs");
41541
+ var import_node_fs72 = require("node:fs");
41218
41542
  async function recordTelemetryChoice(choice) {
41219
- if (!(0, import_node_fs71.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41543
+ if (!(0, import_node_fs72.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41220
41544
  try {
41221
41545
  if ((await readSetupState())?.telemetry === choice) return;
41222
41546
  await writeSetupState({ telemetry: choice });
@@ -41293,8 +41617,8 @@ function registerTelemetryCommands(program2) {
41293
41617
  }
41294
41618
 
41295
41619
  // src/commands/prove.ts
41296
- var import_node_fs72 = require("node:fs");
41297
- var import_node_path55 = require("node:path");
41620
+ var import_node_fs73 = require("node:fs");
41621
+ var import_node_path57 = require("node:path");
41298
41622
 
41299
41623
  // src/lib/prove/hint-pool.ts
41300
41624
  var STOP2 = /* @__PURE__ */ new Set([
@@ -41436,7 +41760,7 @@ function registerProveCommand(program2) {
41436
41760
  process.exit(2);
41437
41761
  }
41438
41762
  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)) || ".") });
41763
+ let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path57.relative)(root, (0, import_node_path57.resolve)(p)) || ".") });
41440
41764
  if (opts.hint && paths.length === 0) {
41441
41765
  const hit = hintMatches(root, opts.hint);
41442
41766
  if (hit.files.length > 0) {
@@ -41490,7 +41814,7 @@ function registerProveCommand(program2) {
41490
41814
  });
41491
41815
  prove.command("check [model]").description("Elaborate a model (or every model) with the local Lean toolchain and report each property").option("--timeout <ms>", "Per-model timeout in ms", "120000").option("--json", "Machine-readable output").action((model, opts) => {
41492
41816
  const root = repoRoot();
41493
- if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41817
+ if (!(0, import_node_fs73.existsSync)((0, import_node_path57.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41494
41818
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41495
41819
  process.exit(2);
41496
41820
  }
@@ -41514,7 +41838,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41514
41838
  const reports = [];
41515
41839
  for (const f of files) {
41516
41840
  const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
41517
- report.file = (0, import_node_path55.relative)(root, f);
41841
+ report.file = (0, import_node_path57.relative)(root, f);
41518
41842
  reports.push(report);
41519
41843
  try {
41520
41844
  writeResult(root, report);
@@ -41552,7 +41876,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41552
41876
  printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
41553
41877
  process.exit(2);
41554
41878
  }
41555
- if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41879
+ if (!(0, import_node_fs73.existsSync)((0, import_node_path57.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41556
41880
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41557
41881
  process.exit(2);
41558
41882
  }
@@ -41583,7 +41907,7 @@ ${report.error ?? ""}`);
41583
41907
  printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
41584
41908
  return;
41585
41909
  }
41586
- const modelSource = readRegularFileInRoot(root, (0, import_node_path55.relative)(root, file), 512 * 1024);
41910
+ const modelSource = readRegularFileInRoot(root, (0, import_node_path57.relative)(root, file), 512 * 1024);
41587
41911
  if (!opts.json) printInfo(`replaying ${targets.length} counterexample(s) of ${model} in network-less containers (${Math.min(targets.length, REPLAY_CONCURRENCY)} at a time)\u2026`);
41588
41912
  const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
41589
41913
  const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
@@ -41603,7 +41927,7 @@ ${report.error ?? ""}`);
41603
41927
  });
41604
41928
  prove.command("auto [files...]").description("The formal phase the pre-push guard runs: select one risky symbol among changed files, generate a model, check it, replay counterexamples (default files: the commits ahead of upstream)").option("--deadline <ms>", "Budget for the whole phase", "170000").option("--json", "Machine-readable output").action(async (paths, opts) => {
41605
41929
  const root = repoRoot();
41606
- let files = paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)));
41930
+ let files = paths.map((p) => (0, import_node_path57.relative)(root, (0, import_node_path57.resolve)(p)));
41607
41931
  if (files.length === 0) {
41608
41932
  const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
41609
41933
  const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
@@ -41613,8 +41937,10 @@ ${report.error ?? ""}`);
41613
41937
  printInfo("No changed files to consider (nothing ahead of upstream). Pass paths explicitly.");
41614
41938
  return;
41615
41939
  }
41616
- const prep = await prepareFormalPhase(root, process.env, await proveAuth(program2) ?? void 0);
41940
+ const auth2 = await proveAuth(program2);
41941
+ const prep = await prepareFormalPhase(root, process.env, auth2 ?? void 0);
41617
41942
  const outcome = prep.ok ? await runFormalPhaseWithin({ root, files, deadlineAt: Date.now() + Math.max(3e4, Number(opts.deadline) || 17e4), deps: prep.deps }).catch((err2) => skippedOutcome("error", String(err2?.message ?? err2).slice(0, 200))) : skippedOutcome(prep.skip, prep.detail);
41943
+ if (auth2) await postPhaseRecord(outcome, { moment: "on-demand", parentRunId: null, pushedFiles: [] }, auth2);
41618
41944
  if (opts.json) {
41619
41945
  printJson(outcome);
41620
41946
  } else {
@@ -41675,7 +42001,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41675
42001
  let revise;
41676
42002
  if (opts.revise) {
41677
42003
  const existing = resolveModelFile(root, opts.revise);
41678
- const src = existing ? readRegularFileInRoot(root, (0, import_node_path55.relative)(root, existing), 64 * 1024) : null;
42004
+ const src = existing ? readRegularFileInRoot(root, (0, import_node_path57.relative)(root, existing), 64 * 1024) : null;
41679
42005
  if (!src || !src.ok || !opts.note) {
41680
42006
  printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
41681
42007
  process.exit(2);
@@ -41688,21 +42014,22 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41688
42014
  printError("Verity library did not build");
41689
42015
  process.exit(2);
41690
42016
  }
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" });
42017
+ const deps = await onDemandDeps(root, { auth: auth2 ?? void 0, apiKey: process.env.VERITY_PROVE_DIRECT === "1" ? process.env.OPENAI_API_KEY : void 0, toolchain: tc });
41692
42018
  if (!opts.json) printInfo(`asking the Verity service for a model of ${symbol || `${file}:${opts.lines}`} \u2026`);
41693
42019
  const out2 = await generateAndCheck(root, { file, symbol: symbol || `${file}:${opts.lines}`, lines, hint: opts.hint, revise }, { deps, maxRounds: 3 });
41694
42020
  if (!out2.ok) {
41695
42021
  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`);
42022
+ 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
42023
  process.exit(2);
41698
42024
  }
42025
+ if (out2.warning && !opts.json) printWarn(out2.warning);
41699
42026
  try {
41700
42027
  writeResult(root, out2.report);
41701
42028
  } catch (err2) {
41702
42029
  if (!(err2 instanceof SafeWriteError)) throw err2;
41703
42030
  }
41704
42031
  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) } });
42032
+ 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
42033
  return;
41707
42034
  }
41708
42035
  printInfo(`wrote ${out2.file} (${out2.rounds} round(s)${out2.costUsd ? `, $${out2.costUsd.toFixed(2)}` : ""})`);
@@ -41714,8 +42041,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41714
42041
  });
41715
42042
  prove.command("waive <file>").description("Dismiss the remembered formal finding(s) on a file for its current bytes \u2014 the accepted-risk path for a formal block").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action((file, opts) => {
41716
42043
  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;
42044
+ const rel0 = (0, import_node_path57.relative)(root, (0, import_node_path57.isAbsolute)(file) ? file : (0, import_node_path57.join)(root, file)).replace(/\\/g, "/");
42045
+ const rel = rel0.startsWith("..") || (0, import_node_path57.isAbsolute)(rel0) ? null : rel0;
41719
42046
  if (!rel) {
41720
42047
  printError(`${file} is not inside this repository`);
41721
42048
  process.exit(2);
@@ -41731,8 +42058,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41731
42058
  });
41732
42059
  prove.command("hash <file>").description("Print the sha256 of a file, for a model header (Verity.model \u2026 sha256). Path is REPO-relative, as in the header").action((file) => {
41733
42060
  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);
42061
+ const rel = (0, import_node_path57.relative)(root, (0, import_node_path57.isAbsolute)(file) ? file : (0, import_node_path57.join)(root, file));
42062
+ const digest = rel.startsWith("..") || (0, import_node_path57.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
41736
42063
  if (!digest) {
41737
42064
  printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
41738
42065
  process.exit(2);
@@ -41766,10 +42093,10 @@ function refreshScaffold(root) {
41766
42093
  }
41767
42094
 
41768
42095
  // src/commands/lean.ts
41769
- var import_node_fs73 = require("node:fs");
42096
+ var import_node_fs74 = require("node:fs");
41770
42097
  var import_node_child_process20 = require("node:child_process");
41771
42098
  var import_node_os12 = require("node:os");
41772
- var import_node_path56 = require("node:path");
42099
+ var import_node_path58 = require("node:path");
41773
42100
  function registerLeanCommand(program2) {
41774
42101
  const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
41775
42102
  lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
@@ -41786,7 +42113,7 @@ function registerLeanCommand(program2) {
41786
42113
  const managed = pinnedVersionDir();
41787
42114
  const matches = version ? version.includes(pin) : false;
41788
42115
  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() });
42116
+ printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs74.existsSync)((0, import_node_path58.join)(managed, "bin")), asset: leanAssetName() });
41790
42117
  return;
41791
42118
  }
41792
42119
  printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
@@ -41804,7 +42131,7 @@ function registerLeanCommand(program2) {
41804
42131
  process.exit(2);
41805
42132
  }
41806
42133
  const dir = pinnedVersionDir();
41807
- if ((0, import_node_fs73.existsSync)((0, import_node_path56.join)(dir, "bin", "lake")) && !opts.force) {
42134
+ if ((0, import_node_fs74.existsSync)((0, import_node_path58.join)(dir, "bin", "lake")) && !opts.force) {
41808
42135
  printInfo(`already installed at ${dir}`);
41809
42136
  return;
41810
42137
  }
@@ -41840,18 +42167,18 @@ function registerLeanCommand(program2) {
41840
42167
  });
41841
42168
  lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
41842
42169
  const dir = pinnedVersionDir();
41843
- if (!(0, import_node_fs73.existsSync)(dir)) {
42170
+ if (!(0, import_node_fs74.existsSync)(dir)) {
41844
42171
  printInfo("nothing to remove");
41845
42172
  return;
41846
42173
  }
41847
- (0, import_node_fs73.rmSync)(dir, { recursive: true, force: true });
42174
+ (0, import_node_fs74.rmSync)(dir, { recursive: true, force: true });
41848
42175
  printInfo(`removed ${dir}`);
41849
42176
  });
41850
42177
  }
41851
42178
 
41852
42179
  // 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");
42180
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.2").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr").hook("preAction", async (_thisCommand, actionCommand) => {
42181
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.2");
41855
42182
  setUserNamedServiceUrl(program.opts().serviceUrl);
41856
42183
  try {
41857
42184
  await foldLegacyLocalCredential();