@codacy/verity-cli 0.35.1-experimental.19ce23f → 0.35.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.
Files changed (3) hide show
  1. package/CHANGELOG.md +29 -3
  2. package/bin/verity.js +792 -571
  3. package/package.json +1 -1
package/bin/verity.js CHANGED
@@ -2928,7 +2928,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2928
2928
  * @param {(string | Function)} text - string to add, or a function returning a string
2929
2929
  * @return {Command} `this` command for chaining
2930
2930
  */
2931
- addHelpText(position, text2) {
2931
+ addHelpText(position, text3) {
2932
2932
  const allowedValues = ["beforeAll", "before", "after", "afterAll"];
2933
2933
  if (!allowedValues.includes(position)) {
2934
2934
  throw new Error(`Unexpected value for position to addHelpText.
@@ -2937,10 +2937,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
2937
2937
  const helpEvent = `${position}Help`;
2938
2938
  this.on(helpEvent, (context) => {
2939
2939
  let helpStr;
2940
- if (typeof text2 === "function") {
2941
- helpStr = text2({ error: context.error, command: context.command });
2940
+ if (typeof text3 === "function") {
2941
+ helpStr = text3({ error: context.error, command: context.command });
2942
2942
  } else {
2943
- helpStr = text2;
2943
+ helpStr = text3;
2944
2944
  }
2945
2945
  if (helpStr) {
2946
2946
  context.write(`${helpStr}
@@ -3750,13 +3750,13 @@ var require_createNode = __commonJS2({
3750
3750
  var defaultTagPrefix = "tag:yaml.org,2002:";
3751
3751
  function findTagObject(value, tagName, tags) {
3752
3752
  if (tagName) {
3753
- const match = tags.filter((t) => t.tag === tagName);
3754
- const tagObj = match.find((t) => !t.format) ?? match[0];
3753
+ const match = tags.filter((t2) => t2.tag === tagName);
3754
+ const tagObj = match.find((t2) => !t2.format) ?? match[0];
3755
3755
  if (!tagObj)
3756
3756
  throw new Error(`Tag ${tagName} not found`);
3757
3757
  return tagObj;
3758
3758
  }
3759
- return tags.find((t) => t.identify?.(value) && !t.format);
3759
+ return tags.find((t2) => t2.identify?.(value) && !t2.format);
3760
3760
  }
3761
3761
  function createNode(value, tagName, ctx) {
3762
3762
  if (identity.isDocument(value))
@@ -3982,14 +3982,14 @@ var require_foldFlowLines = __commonJS2({
3982
3982
  var FOLD_FLOW = "flow";
3983
3983
  var FOLD_BLOCK = "block";
3984
3984
  var FOLD_QUOTED = "quoted";
3985
- function foldFlowLines(text2, indent, mode2 = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
3985
+ function foldFlowLines(text3, indent, mode2 = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
3986
3986
  if (!lineWidth || lineWidth < 0)
3987
- return text2;
3987
+ return text3;
3988
3988
  if (lineWidth < minContentWidth)
3989
3989
  minContentWidth = 0;
3990
3990
  const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
3991
- if (text2.length <= endStep)
3992
- return text2;
3991
+ if (text3.length <= endStep)
3992
+ return text3;
3993
3993
  const folds = [];
3994
3994
  const escapedFolds = {};
3995
3995
  let end = lineWidth - indent.length;
@@ -4006,14 +4006,14 @@ var require_foldFlowLines = __commonJS2({
4006
4006
  let escStart = -1;
4007
4007
  let escEnd = -1;
4008
4008
  if (mode2 === FOLD_BLOCK) {
4009
- i2 = consumeMoreIndentedLines(text2, i2, indent.length);
4009
+ i2 = consumeMoreIndentedLines(text3, i2, indent.length);
4010
4010
  if (i2 !== -1)
4011
4011
  end = i2 + endStep;
4012
4012
  }
4013
- for (let ch; ch = text2[i2 += 1]; ) {
4013
+ for (let ch; ch = text3[i2 += 1]; ) {
4014
4014
  if (mode2 === FOLD_QUOTED && ch === "\\") {
4015
4015
  escStart = i2;
4016
- switch (text2[i2 + 1]) {
4016
+ switch (text3[i2 + 1]) {
4017
4017
  case "x":
4018
4018
  i2 += 3;
4019
4019
  break;
@@ -4030,12 +4030,12 @@ var require_foldFlowLines = __commonJS2({
4030
4030
  }
4031
4031
  if (ch === "\n") {
4032
4032
  if (mode2 === FOLD_BLOCK)
4033
- i2 = consumeMoreIndentedLines(text2, i2, indent.length);
4033
+ i2 = consumeMoreIndentedLines(text3, i2, indent.length);
4034
4034
  end = i2 + indent.length + endStep;
4035
4035
  split = void 0;
4036
4036
  } else {
4037
4037
  if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") {
4038
- const next = text2[i2 + 1];
4038
+ const next = text3[i2 + 1];
4039
4039
  if (next && next !== " " && next !== "\n" && next !== " ")
4040
4040
  split = i2;
4041
4041
  }
@@ -4047,12 +4047,12 @@ var require_foldFlowLines = __commonJS2({
4047
4047
  } else if (mode2 === FOLD_QUOTED) {
4048
4048
  while (prev === " " || prev === " ") {
4049
4049
  prev = ch;
4050
- ch = text2[i2 += 1];
4050
+ ch = text3[i2 += 1];
4051
4051
  overflow = true;
4052
4052
  }
4053
4053
  const j = i2 > escEnd + 1 ? i2 - 2 : escStart - 1;
4054
4054
  if (escapedFolds[j])
4055
- return text2;
4055
+ return text3;
4056
4056
  folds.push(j);
4057
4057
  escapedFolds[j] = true;
4058
4058
  end = j + endStep;
@@ -4067,39 +4067,39 @@ var require_foldFlowLines = __commonJS2({
4067
4067
  if (overflow && onOverflow)
4068
4068
  onOverflow();
4069
4069
  if (folds.length === 0)
4070
- return text2;
4070
+ return text3;
4071
4071
  if (onFold)
4072
4072
  onFold();
4073
- let res = text2.slice(0, folds[0]);
4073
+ let res = text3.slice(0, folds[0]);
4074
4074
  for (let i3 = 0; i3 < folds.length; ++i3) {
4075
4075
  const fold2 = folds[i3];
4076
- const end2 = folds[i3 + 1] || text2.length;
4076
+ const end2 = folds[i3 + 1] || text3.length;
4077
4077
  if (fold2 === 0)
4078
4078
  res = `
4079
- ${indent}${text2.slice(0, end2)}`;
4079
+ ${indent}${text3.slice(0, end2)}`;
4080
4080
  else {
4081
4081
  if (mode2 === FOLD_QUOTED && escapedFolds[fold2])
4082
- res += `${text2[fold2]}\\`;
4082
+ res += `${text3[fold2]}\\`;
4083
4083
  res += `
4084
- ${indent}${text2.slice(fold2 + 1, end2)}`;
4084
+ ${indent}${text3.slice(fold2 + 1, end2)}`;
4085
4085
  }
4086
4086
  }
4087
4087
  return res;
4088
4088
  }
4089
- function consumeMoreIndentedLines(text2, i2, indent) {
4089
+ function consumeMoreIndentedLines(text3, i2, indent) {
4090
4090
  let end = i2;
4091
4091
  let start2 = i2 + 1;
4092
- let ch = text2[start2];
4092
+ let ch = text3[start2];
4093
4093
  while (ch === " " || ch === " ") {
4094
4094
  if (i2 < start2 + indent) {
4095
- ch = text2[++i2];
4095
+ ch = text3[++i2];
4096
4096
  } else {
4097
4097
  do {
4098
- ch = text2[++i2];
4098
+ ch = text3[++i2];
4099
4099
  } while (ch && ch !== "\n");
4100
4100
  end = i2;
4101
4101
  start2 = i2 + 1;
4102
- ch = text2[start2];
4102
+ ch = text3[start2];
4103
4103
  }
4104
4104
  }
4105
4105
  return end;
@@ -4383,10 +4383,10 @@ ${indent}`);
4383
4383
  let res = _stringify(type);
4384
4384
  if (res === null) {
4385
4385
  const { defaultKeyType, defaultStringType } = ctx.options;
4386
- const t = implicitKey && defaultKeyType || defaultStringType;
4387
- res = _stringify(t);
4386
+ const t2 = implicitKey && defaultKeyType || defaultStringType;
4387
+ res = _stringify(t2);
4388
4388
  if (res === null)
4389
- throw new Error(`Unsupported default string type ${t}`);
4389
+ throw new Error(`Unsupported default string type ${t2}`);
4390
4390
  }
4391
4391
  return res;
4392
4392
  }
@@ -4446,24 +4446,24 @@ var require_stringify = __commonJS2({
4446
4446
  }
4447
4447
  function getTagObject(tags, item) {
4448
4448
  if (item.tag) {
4449
- const match = tags.filter((t) => t.tag === item.tag);
4449
+ const match = tags.filter((t2) => t2.tag === item.tag);
4450
4450
  if (match.length > 0)
4451
- return match.find((t) => t.format === item.format) ?? match[0];
4451
+ return match.find((t2) => t2.format === item.format) ?? match[0];
4452
4452
  }
4453
4453
  let tagObj = void 0;
4454
4454
  let obj;
4455
4455
  if (identity.isScalar(item)) {
4456
4456
  obj = item.value;
4457
- let match = tags.filter((t) => t.identify?.(obj));
4457
+ let match = tags.filter((t2) => t2.identify?.(obj));
4458
4458
  if (match.length > 1) {
4459
- const testMatch = match.filter((t) => t.test);
4459
+ const testMatch = match.filter((t2) => t2.test);
4460
4460
  if (testMatch.length > 0)
4461
4461
  match = testMatch;
4462
4462
  }
4463
- tagObj = match.find((t) => t.format === item.format) ?? match.find((t) => !t.format);
4463
+ tagObj = match.find((t2) => t2.format === item.format) ?? match.find((t2) => !t2.format);
4464
4464
  } else {
4465
4465
  obj = item;
4466
- tagObj = tags.find((t) => t.nodeClass && obj instanceof t.nodeClass);
4466
+ tagObj = tags.find((t2) => t2.nodeClass && obj instanceof t2.nodeClass);
4467
4467
  }
4468
4468
  if (!tagObj) {
4469
4469
  const name2 = obj?.constructor?.name ?? (obj === null ? "null" : typeof obj);
@@ -7389,7 +7389,7 @@ var require_compose_collection = __commonJS2({
7389
7389
  if (!tagToken || !tagName || tagName === "!" || tagName === YAMLMap.YAMLMap.tagName && expType === "map" || tagName === YAMLSeq.YAMLSeq.tagName && expType === "seq") {
7390
7390
  return resolveCollection(CN, ctx, token, onError, tagName);
7391
7391
  }
7392
- let tag = ctx.schema.tags.find((t) => t.tag === tagName && t.collection === expType);
7392
+ let tag = ctx.schema.tags.find((t2) => t2.tag === tagName && t2.collection === expType);
7393
7393
  if (!tag) {
7394
7394
  const kt = ctx.schema.knownTags[tagName];
7395
7395
  if (kt?.collection === expType) {
@@ -13882,11 +13882,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13882
13882
  for (const c of captures) {
13883
13883
  if (c.name === captureName) nodes.push(c.node.text);
13884
13884
  }
13885
- const test = /* @__PURE__ */ __name((text2, positive) => {
13886
- return positive ? regex.test(text2) : !regex.test(text2);
13885
+ const test = /* @__PURE__ */ __name((text3, positive) => {
13886
+ return positive ? regex.test(text3) : !regex.test(text3);
13887
13887
  }, "test");
13888
13888
  if (nodes.length === 0) return !isPositive;
13889
- return matchAll2 ? nodes.every((text2) => test(text2, isPositive)) : nodes.some((text2) => test(text2, isPositive));
13889
+ return matchAll2 ? nodes.every((text3) => test(text3, isPositive)) : nodes.some((text3) => test(text3, isPositive));
13890
13890
  });
13891
13891
  }
13892
13892
  __name(parseMatchPredicate, "parseMatchPredicate");
@@ -13916,7 +13916,7 @@ ${JSON.stringify(symbolNames, null, 2)}`);
13916
13916
  if (c.name === captureName) nodes.push(c.node.text);
13917
13917
  }
13918
13918
  if (nodes.length === 0) return !isPositive;
13919
- return nodes.every((text2) => values.includes(text2)) === isPositive;
13919
+ return nodes.every((text3) => values.includes(text3)) === isPositive;
13920
13920
  });
13921
13921
  }
13922
13922
  __name(parseAnyOfPredicate, "parseAnyOfPredicate");
@@ -14517,9 +14517,9 @@ function treeDir(identity) {
14517
14517
  return (0, import_node_path.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
14518
14518
  }
14519
14519
  function scopeIdentity(token, sessionId) {
14520
- const t = (token ?? "").trim();
14520
+ const t2 = (token ?? "").trim();
14521
14521
  const s = (sessionId ?? "").trim();
14522
- const userKey = t.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
14522
+ const userKey = t2.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(t2).digest("hex").slice(0, 12) : "anon";
14523
14523
  const sessionKey2 = s.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
14524
14524
  return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
14525
14525
  }
@@ -14733,7 +14733,7 @@ var SECURITY_PATTERNS = [
14733
14733
  /(^|\/)gradle\.lockfile$/
14734
14734
  ];
14735
14735
  var PROD_SERVICE_URL = "https://ofcamwrjwrkazqvdchko.supabase.co/functions/v1";
14736
- var DEFAULT_SERVICE_URL = "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1".length > 0 ? "https://wukeddyzpijoegyajtnc.supabase.co/functions/v1" : PROD_SERVICE_URL;
14736
+ var DEFAULT_SERVICE_URL = "".length > 0 ? "" : PROD_SERVICE_URL;
14737
14737
  var GITHUB_CLIENT_ID = "Iv23li88HxAi3ZrbYzWh";
14738
14738
  var GITHUB_DEVICE_CODE_URL = "https://github.com/login/device/code";
14739
14739
  var GITHUB_ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token";
@@ -15325,7 +15325,7 @@ function pinRefusalMessage(verdict, targetUrl) {
15325
15325
  // src/lib/cli-version.ts
15326
15326
  function cliVersion() {
15327
15327
  try {
15328
- return true ? "0.35.1-experimental.19ce23f" : "dev";
15328
+ return true ? "0.35.2" : "dev";
15329
15329
  } catch {
15330
15330
  return "dev";
15331
15331
  }
@@ -15758,14 +15758,14 @@ function clipboards(platform4, env) {
15758
15758
  if (env.DISPLAY) out2.push(["xclip", ["-selection", "clipboard"]], ["xsel", ["--clipboard", "--input"]]);
15759
15759
  return out2;
15760
15760
  }
15761
- function copyToClipboard(text2, opts = {}) {
15761
+ function copyToClipboard(text3, opts = {}) {
15762
15762
  const env = opts.env ?? process.env;
15763
15763
  const platform4 = opts.platform ?? process.platform;
15764
- if (!/^[A-Za-z0-9-]{1,32}$/.test(text2)) return false;
15764
+ if (!/^[A-Za-z0-9-]{1,32}$/.test(text3)) return false;
15765
15765
  if (env.SSH_CONNECTION || env.SSH_TTY || env.CI) return false;
15766
15766
  for (const [cmd, args2] of clipboards(platform4, env)) {
15767
15767
  try {
15768
- const r = (opts.run ?? import_node_child_process4.spawnSync)(cmd, args2, { input: text2, stdio: ["pipe", "ignore", "ignore"], timeout: 2e3 });
15768
+ const r = (opts.run ?? import_node_child_process4.spawnSync)(cmd, args2, { input: text3, stdio: ["pipe", "ignore", "ignore"], timeout: 2e3 });
15769
15769
  if (!r.error && r.status === 0) return true;
15770
15770
  } catch {
15771
15771
  }
@@ -15835,11 +15835,11 @@ function startSpinner(label2, opts = {}) {
15835
15835
  },
15836
15836
  succeed(message) {
15837
15837
  finish(() => {
15838
- const text2 = message ?? current;
15838
+ const text3 = message ?? current;
15839
15839
  const clock2 = showElapsed ? ` (${secondsSince(start2)})` : "";
15840
15840
  stream.write(
15841
- color ? ` ${GREEN2}\u2713${RESET} ${text2}${DIM2}${clock2}${RESET}
15842
- ` : ` \u2713 ${text2}${clock2}
15841
+ color ? ` ${GREEN2}\u2713${RESET} ${text3}${DIM2}${clock2}${RESET}
15842
+ ` : ` \u2713 ${text3}${clock2}
15843
15843
  `
15844
15844
  );
15845
15845
  });
@@ -16365,11 +16365,11 @@ function clearPendingLogin() {
16365
16365
  // src/lib/login-report.ts
16366
16366
  async function describeLoginOutcome(out2, opts = {}) {
16367
16367
  const lines = [];
16368
- const info2 = (text2) => {
16369
- lines.push({ level: "info", text: text2 });
16368
+ const info2 = (text3) => {
16369
+ lines.push({ level: "info", text: text3 });
16370
16370
  };
16371
- const warn = (text2) => {
16372
- lines.push({ level: "warn", text: text2 });
16371
+ const warn = (text3) => {
16372
+ lines.push({ level: "warn", text: text3 });
16373
16373
  };
16374
16374
  const identity = out2.email ?? (out2.userId != null ? `user #${out2.userId}` : "your account");
16375
16375
  info2(`Logged in as ${identity}. \u2713`);
@@ -16683,12 +16683,14 @@ function removeIfOurs(fd, path) {
16683
16683
  } catch {
16684
16684
  }
16685
16685
  }
16686
- function openTarget(path, append2) {
16686
+ function openTarget(path, append2, createOnly = false) {
16687
16687
  const base = import_node_fs7.constants.O_WRONLY | (append2 ? import_node_fs7.constants.O_APPEND : 0) | O_NOFOLLOW;
16688
- try {
16689
- return { fd: (0, import_node_fs7.openSync)(path, base), created: false };
16690
- } catch (e) {
16691
- if (e.code !== "ENOENT") return null;
16688
+ if (!createOnly) {
16689
+ try {
16690
+ return { fd: (0, import_node_fs7.openSync)(path, base), created: false };
16691
+ } catch (e) {
16692
+ if (e.code !== "ENOENT") return null;
16693
+ }
16692
16694
  }
16693
16695
  try {
16694
16696
  return { fd: (0, import_node_fs7.openSync)(path, base | import_node_fs7.constants.O_CREAT | import_node_fs7.constants.O_EXCL, 384), created: true };
@@ -16696,13 +16698,13 @@ function openTarget(path, append2) {
16696
16698
  return null;
16697
16699
  }
16698
16700
  }
16699
- function writeVerified(root, name2, hooks, append2, write) {
16701
+ function writeVerified(root, name2, hooks, append2, write, createOnly = false) {
16700
16702
  const r = validateRoot(root);
16701
16703
  if (!r || !bareName(name2)) return false;
16702
16704
  const path = (0, import_node_path7.join)(r.real, name2);
16703
16705
  if (!absentOrRegular(path)) return false;
16704
16706
  if (!runHook(hooks)) return false;
16705
- const opened = openTarget(path, append2);
16707
+ const opened = openTarget(path, append2, createOnly);
16706
16708
  if (!opened) return false;
16707
16709
  try {
16708
16710
  if (!verifyOpened(opened.fd, path, r)) {
@@ -16728,17 +16730,22 @@ function runHook(hooks) {
16728
16730
  return false;
16729
16731
  }
16730
16732
  }
16731
- function appendInRoot(root, name2, text2, hooks = {}) {
16733
+ function appendInRoot(root, name2, text3, hooks = {}) {
16732
16734
  return writeVerified(root, name2, hooks, true, (fd) => {
16733
- (0, import_node_fs7.writeSync)(fd, text2);
16735
+ (0, import_node_fs7.writeSync)(fd, text3);
16734
16736
  });
16735
16737
  }
16736
- function replaceInRoot(root, name2, text2, hooks = {}) {
16738
+ function replaceInRoot(root, name2, text3, hooks = {}) {
16737
16739
  return writeVerified(root, name2, hooks, false, (fd) => {
16738
16740
  (0, import_node_fs7.ftruncateSync)(fd, 0);
16739
- (0, import_node_fs7.writeSync)(fd, text2, 0);
16741
+ (0, import_node_fs7.writeSync)(fd, text3, 0);
16740
16742
  });
16741
16743
  }
16744
+ function createInRoot(root, name2, text3, hooks = {}) {
16745
+ return writeVerified(root, name2, hooks, false, (fd) => {
16746
+ (0, import_node_fs7.writeSync)(fd, text3, 0);
16747
+ }, true);
16748
+ }
16742
16749
 
16743
16750
  // src/lib/repo-file.ts
16744
16751
  var DEFAULT_MAX_BYTES = 512 * 1024;
@@ -16748,6 +16755,16 @@ function writeRepoFile(relative9, body2) {
16748
16755
  throw new Error(`refused to write ${relative9}: it, or its folder, is a link or not a regular file`);
16749
16756
  }
16750
16757
  }
16758
+ var COPY_NAMES = 10;
16759
+ function keepStandardCopy(body2, now = /* @__PURE__ */ new Date()) {
16760
+ const stamp2 = now.toISOString().replace(/[:.]/g, "-");
16761
+ for (let n2 = 0; n2 < COPY_NAMES; n2++) {
16762
+ const relative9 = `${VERITY_DIR}/standard.${stamp2}${n2 === 0 ? "" : `-${n2}`}.yaml`;
16763
+ const path = projectPath(relative9);
16764
+ if (createInRoot((0, import_node_path8.dirname)(path), (0, import_node_path8.basename)(path), body2)) return relative9;
16765
+ }
16766
+ throw new Error(`refused to create ${VERITY_DIR}/standard.${stamp2}.yaml: ${VERITY_DIR} is a link or not a folder, or ${COPY_NAMES} copies with that time exist`);
16767
+ }
16751
16768
  function readRepoFile(relative9, maxBytes = DEFAULT_MAX_BYTES) {
16752
16769
  const root = repoRoot();
16753
16770
  if (throughLinkedFolder(root, relative9)) return null;
@@ -17321,9 +17338,9 @@ function declaredDependencies(root, files) {
17321
17338
  for (const path of pythonManifests) {
17322
17339
  if (!(0, import_node_fs10.existsSync)(path)) continue;
17323
17340
  try {
17324
- const text2 = (0, import_node_fs10.readFileSync)(path, "utf-8");
17325
- for (const m of text2.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
17326
- for (const line2 of text2.split("\n")) {
17341
+ const text3 = (0, import_node_fs10.readFileSync)(path, "utf-8");
17342
+ for (const m of text3.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
17343
+ for (const line2 of text3.split("\n")) {
17327
17344
  if (!/dependencies\s*=/.test(line2)) continue;
17328
17345
  for (const m of line2.matchAll(/["']([A-Za-z][A-Za-z0-9._-]+)/g)) names2.push(m[1]);
17329
17346
  }
@@ -17337,8 +17354,8 @@ function declaredDependencies(root, files) {
17337
17354
  for (const path of goMods) {
17338
17355
  if (!(0, import_node_fs10.existsSync)(path)) continue;
17339
17356
  try {
17340
- const text2 = (0, import_node_fs10.readFileSync)(path, "utf-8");
17341
- for (const m of text2.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
17357
+ const text3 = (0, import_node_fs10.readFileSync)(path, "utf-8");
17358
+ for (const m of text3.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
17342
17359
  names2.push(m[1].replace(/^github\.com\//, ""));
17343
17360
  }
17344
17361
  } catch {
@@ -17348,9 +17365,9 @@ function declaredDependencies(root, files) {
17348
17365
  const path = (0, import_node_path10.join)(root, file);
17349
17366
  if (!(0, import_node_fs10.existsSync)(path)) continue;
17350
17367
  try {
17351
- const text2 = (0, import_node_fs10.readFileSync)(path, "utf-8");
17352
- for (const m of text2.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
17353
- if (file === "Cargo.toml") names2.push(...cargoDependencyKeys(text2));
17368
+ const text3 = (0, import_node_fs10.readFileSync)(path, "utf-8");
17369
+ for (const m of text3.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
17370
+ if (file === "Cargo.toml") names2.push(...cargoDependencyKeys(text3));
17354
17371
  } catch {
17355
17372
  }
17356
17373
  }
@@ -17365,8 +17382,8 @@ function declaredDependencies(root, files) {
17365
17382
  for (const rel of composerFiles) {
17366
17383
  let composer = null;
17367
17384
  try {
17368
- const text2 = manifest(rel);
17369
- composer = text2 === null ? null : JSON.parse(text2);
17385
+ const text3 = manifest(rel);
17386
+ composer = text3 === null ? null : JSON.parse(text3);
17370
17387
  } catch {
17371
17388
  }
17372
17389
  if (!composer || typeof composer !== "object") continue;
@@ -17376,20 +17393,20 @@ function declaredDependencies(root, files) {
17376
17393
  }
17377
17394
  }
17378
17395
  for (const rel of files.filter((f) => /\.(cs|fs)proj$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT)) {
17379
- const text2 = manifest(rel);
17380
- if (text2 === null) continue;
17381
- for (const m of text2.matchAll(/<PackageReference\b[^>]*?\bInclude="([A-Za-z][A-Za-z0-9._-]+)"/g)) names2.push(m[1]);
17396
+ const text3 = manifest(rel);
17397
+ if (text3 === null) continue;
17398
+ for (const m of text3.matchAll(/<PackageReference\b[^>]*?\bInclude="([A-Za-z][A-Za-z0-9._-]+)"/g)) names2.push(m[1]);
17382
17399
  }
17383
17400
  for (const rel of files.filter((f) => f.includes("/") && (0, import_node_path10.basename)(f) === "Cargo.toml").slice(0, NESTED_MANIFEST_LIMIT)) {
17384
- const text2 = manifest(rel);
17385
- if (text2 !== null) names2.push(...cargoDependencyKeys(text2));
17401
+ const text3 = manifest(rel);
17402
+ if (text3 !== null) names2.push(...cargoDependencyKeys(text3));
17386
17403
  }
17387
17404
  return names2;
17388
17405
  }
17389
- function cargoDependencyKeys(text2) {
17406
+ function cargoDependencyKeys(text3) {
17390
17407
  const names2 = [];
17391
17408
  let inDeps = false;
17392
- for (const raw of text2.split("\n")) {
17409
+ for (const raw of text3.split("\n")) {
17393
17410
  const line2 = raw.trim();
17394
17411
  const header = /^\[([^\]]+)\]$/.exec(line2);
17395
17412
  if (header) {
@@ -17651,30 +17668,30 @@ function shipsCli(root, files) {
17651
17668
  };
17652
17669
  const candidates2 = files.filter((f) => Object.hasOwn(CLI_DECLARATION, (0, import_node_path11.basename)(f))).sort((a, b) => a.split("/").length - b.split("/").length || a.localeCompare(b));
17653
17670
  for (const rel of candidates2) {
17654
- const text2 = read2(rel);
17655
- if (text2 !== null && CLI_DECLARATION[(0, import_node_path11.basename)(rel)](text2)) return true;
17671
+ const text3 = read2(rel);
17672
+ if (text3 !== null && CLI_DECLARATION[(0, import_node_path11.basename)(rel)](text3)) return true;
17656
17673
  }
17657
17674
  return false;
17658
17675
  }
17659
17676
  var CLI_DECLARATION = {
17660
- "package.json": (text2) => {
17677
+ "package.json": (text3) => {
17661
17678
  try {
17662
- const bin = JSON.parse(text2).bin;
17679
+ const bin = JSON.parse(text3).bin;
17663
17680
  return typeof bin === "string" && bin.length > 0 || isRecord(bin) && Object.keys(bin).length > 0;
17664
17681
  } catch {
17665
17682
  return false;
17666
17683
  }
17667
17684
  },
17668
- "pyproject.toml": (text2) => /^\s*\[(project\.scripts|tool\.poetry\.scripts)\]\s*$/m.test(text2),
17669
- "setup.py": (text2) => /console_scripts/.test(text2),
17670
- "setup.cfg": (text2) => /console_scripts/.test(text2),
17671
- "Cargo.toml": (text2) => /^\s*\[\[bin\]\]\s*$/m.test(text2)
17685
+ "pyproject.toml": (text3) => /^\s*\[(project\.scripts|tool\.poetry\.scripts)\]\s*$/m.test(text3),
17686
+ "setup.py": (text3) => /console_scripts/.test(text3),
17687
+ "setup.cfg": (text3) => /console_scripts/.test(text3),
17688
+ "Cargo.toml": (text3) => /^\s*\[\[bin\]\]\s*$/m.test(text3)
17672
17689
  };
17673
17690
 
17674
17691
  // src/lib/verity-md.ts
17675
17692
  var UNPRINTABLE = /[\u0000-\u001f\u007f-\u009f\u2028\u2029\u202a-\u202e\u2066-\u2069]+/g;
17676
- function markdownPlain(text2, max = 200) {
17677
- const oneLine2 = text2.replace(UNPRINTABLE, " ").replace(/\s+/g, " ").trim();
17693
+ function markdownPlain(text3, max = 200) {
17694
+ const oneLine2 = text3.replace(UNPRINTABLE, " ").replace(/\s+/g, " ").trim();
17678
17695
  const bounded = oneLine2.length > max ? `${oneLine2.slice(0, max - 1)}\u2026` : oneLine2;
17679
17696
  return bounded.replace(/[\\`*_{}[\]()<>#+!|~]/g, (c) => `\\${c}`);
17680
17697
  }
@@ -17715,7 +17732,7 @@ function describeOrigin(origin) {
17715
17732
  if (origin.kind === "adopted") {
17716
17733
  return `adopted from the service${origin.createdBy ? `, created by ${markdownPlain(origin.createdBy, 120)}` : ""}`;
17717
17734
  }
17718
- return `derived from this codebase${origin.tools.length > 0 ? ` \xB7 ${origin.tools.map((t) => markdownPlain(t, 60)).join(", ")}` : ""}`;
17735
+ return `derived from this codebase${origin.tools.length > 0 ? ` \xB7 ${origin.tools.map((t2) => markdownPlain(t2, 60)).join(", ")}` : ""}`;
17719
17736
  }
17720
17737
  function closingNote(origin) {
17721
17738
  if (origin.kind === "adopted") {
@@ -17748,7 +17765,7 @@ ${list2(dimensions, DEFAULT_DIMENSIONS)}
17748
17765
  ${packs.length > 0 ? `## Review Packs
17749
17766
  ${list2(packs, [])}
17750
17767
 
17751
- The Verity service expands each pack into its patterns. To list them: \`verity standard get --resolved\`
17768
+ The Verity service expands each pack into its patterns. What each pack holds: \`verity standard catalogue <pack>\`, or https://verity.md/review-packs. What this project's review reads: \`verity standard get --resolved\`
17752
17769
  ` : `## Security Patterns
17753
17770
  ${list2(patterns, DEFAULT_SECURITY)}
17754
17771
  `}${custom.length > 0 ? `
@@ -18400,11 +18417,11 @@ function registerTokenCommand(program2) {
18400
18417
  printInfo("No tokens found for this repository.");
18401
18418
  return;
18402
18419
  }
18403
- for (const t of tokens) {
18404
- const type = t.token_type ?? "user";
18405
- const expires = t.expires_at ? `expires ${t.expires_at.slice(0, 10)}` : "no expiry";
18406
- const lastUsed = t.last_used_at ? `last used ${t.last_used_at.slice(0, 10)}` : "never used";
18407
- printInfo(`${t.id} [${type}] ${t.agent_name ?? "unnamed"} (${expires}, ${lastUsed})`);
18420
+ for (const t2 of tokens) {
18421
+ const type = t2.token_type ?? "user";
18422
+ const expires = t2.expires_at ? `expires ${t2.expires_at.slice(0, 10)}` : "no expiry";
18423
+ const lastUsed = t2.last_used_at ? `last used ${t2.last_used_at.slice(0, 10)}` : "never used";
18424
+ printInfo(`${t2.id} [${type}] ${t2.agent_name ?? "unnamed"} (${expires}, ${lastUsed})`);
18408
18425
  }
18409
18426
  });
18410
18427
  token.command("revoke <id>").description("Revoke a token by id (service tokens: any current writer may revoke)").action(async (id) => {
@@ -19340,13 +19357,13 @@ function scrub(s) {
19340
19357
  var installed = false;
19341
19358
  var wroteBanner = false;
19342
19359
  var banner = "";
19343
- function append(text2) {
19360
+ function append(text3) {
19344
19361
  try {
19345
19362
  const dir = projectPath(DEBUG_LOG_DIR);
19346
19363
  const file = projectPath(STDERR_LOG_FILE);
19347
19364
  (0, import_node_fs16.mkdirSync)(dir, { recursive: true });
19348
19365
  rotateIfNeeded(file);
19349
- (0, import_node_fs16.appendFileSync)(file, text2);
19366
+ (0, import_node_fs16.appendFileSync)(file, text3);
19350
19367
  } catch {
19351
19368
  }
19352
19369
  }
@@ -19368,19 +19385,19 @@ function installStderrLog(cmd, argv, version) {
19368
19385
  const result = original(...args2);
19369
19386
  try {
19370
19387
  const chunk = args2[0];
19371
- const text2 = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
19388
+ const text3 = typeof chunk === "string" ? chunk : Buffer.isBuffer(chunk) ? chunk.toString("utf-8") : String(chunk);
19372
19389
  ensureBanner();
19373
- append(scrub(text2));
19390
+ append(scrub(text3));
19374
19391
  } catch {
19375
19392
  }
19376
19393
  return result;
19377
19394
  };
19378
19395
  process.stderr.write = tee;
19379
19396
  }
19380
- function logToFileOnly(text2) {
19397
+ function logToFileOnly(text3) {
19381
19398
  if (!installed) return;
19382
19399
  ensureBanner();
19383
- append(text2.endsWith("\n") ? text2 : `${text2}
19400
+ append(text3.endsWith("\n") ? text3 : `${text3}
19384
19401
  `);
19385
19402
  }
19386
19403
 
@@ -19954,8 +19971,8 @@ var import_promises5 = require("node:fs/promises");
19954
19971
  var import_node_fs19 = require("node:fs");
19955
19972
  var import_node_child_process8 = require("node:child_process");
19956
19973
  var import_node_crypto2 = require("node:crypto");
19957
- function stripImageReferences(text2) {
19958
- return text2.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
19974
+ function stripImageReferences(text3) {
19975
+ return text3.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
19959
19976
  }
19960
19977
  function bufferTmpPath() {
19961
19978
  return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto2.randomBytes)(4).toString("hex")}.tmp`;
@@ -20192,7 +20209,7 @@ function isNonAuthoringCommand(cmd) {
20192
20209
  function hasNonEditAuthorship(actionSummary, sessionAuthoredCode) {
20193
20210
  if (!actionSummary) return sessionAuthoredCode;
20194
20211
  if ((actionSummary.subagents ?? 0) > 0) return true;
20195
- if (Object.keys(actionSummary.tool_counts ?? {}).some((t) => t.startsWith("mcp__"))) return true;
20212
+ if (Object.keys(actionSummary.tool_counts ?? {}).some((t2) => t2.startsWith("mcp__"))) return true;
20196
20213
  const commands = actionSummary.commands ?? [];
20197
20214
  if (commands.some((c) => FILE_MUTATE_RE.test(c))) return true;
20198
20215
  if (sessionAuthoredCode) {
@@ -20221,7 +20238,7 @@ function narrowToAgentAuthored(files, actionSummary) {
20221
20238
  if (touched.length === 0) return files;
20222
20239
  return files.filter((f) => {
20223
20240
  const suffix = "/" + f;
20224
- return touched.some((t) => t === f || t.endsWith(suffix));
20241
+ return touched.some((t2) => t2 === f || t2.endsWith(suffix));
20225
20242
  });
20226
20243
  }
20227
20244
 
@@ -20731,9 +20748,9 @@ var STOPWORDS = /* @__PURE__ */ new Set([
20731
20748
  "within",
20732
20749
  "without"
20733
20750
  ]);
20734
- function tokenize(text2) {
20751
+ function tokenize(text3) {
20735
20752
  return new Set(
20736
- text2.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOPWORDS.has(w))
20753
+ text3.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOPWORDS.has(w))
20737
20754
  );
20738
20755
  }
20739
20756
  function jaccardKeywords(a, b) {
@@ -20750,9 +20767,9 @@ function relevance(node, ctx) {
20750
20767
  if (nodeTags.length > 0 && ctx.changeTags && ctx.changeTags.length > 0) {
20751
20768
  const change = new Set(ctx.changeTags);
20752
20769
  let hit = 0;
20753
- for (const t of nodeTags) {
20754
- if (!change.has(t)) continue;
20755
- hit += t.startsWith("pkg:") || t.startsWith("tbl:") ? 1 : t.startsWith("sym:") ? 0.8 : t.startsWith("dir:") ? 0.4 : 0.15;
20770
+ for (const t2 of nodeTags) {
20771
+ if (!change.has(t2)) continue;
20772
+ hit += t2.startsWith("pkg:") || t2.startsWith("tbl:") ? 1 : t2.startsWith("sym:") ? 0.8 : t2.startsWith("dir:") ? 0.4 : 0.15;
20756
20773
  }
20757
20774
  tagScore = Math.min(1, hit / TAG_SATURATION);
20758
20775
  }
@@ -20810,9 +20827,9 @@ var MAX_BUDGET_TOKENS = 4e3;
20810
20827
  var MAX_NODE_FILE_BYTES = 64 * 1024;
20811
20828
  var MIN_SCORE = RELEVANCE_FLOOR * 0.5;
20812
20829
  var ORG_MIN_SHARED_TERMS = 2;
20813
- function orgTerms(text2) {
20830
+ function orgTerms(text3) {
20814
20831
  return new Set(
20815
- text2.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
20832
+ text3.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length > 2)
20816
20833
  );
20817
20834
  }
20818
20835
  function sharedTerms(a, b) {
@@ -21171,12 +21188,12 @@ function ensureVerityGitignore() {
21171
21188
  if (hasSupersededMemory && !memoryIsCommitted) {
21172
21189
  next = fenceMemoryLines(next);
21173
21190
  }
21174
- let text2 = next.join("\n");
21191
+ let text3 = next.join("\n");
21175
21192
  if (!hasMarker) {
21176
- const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
21177
- text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
21193
+ const sep7 = text3 === "" ? "" : text3.endsWith("\n") ? "\n" : "\n\n";
21194
+ text3 = text3 + sep7 + VERITY_GITIGNORE_BLOCK;
21178
21195
  }
21179
- if (text2 !== content) (0, import_node_fs24.writeFileSync)(".gitignore", text2);
21196
+ if (text3 !== content) (0, import_node_fs24.writeFileSync)(".gitignore", text3);
21180
21197
  return verified(
21181
21198
  memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
21182
21199
  );
@@ -21202,13 +21219,13 @@ function writeFencedBlock() {
21202
21219
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
21203
21220
  let lines = content.split("\n").map((l) => BREAKING_ENTRIES.has(l.trim()) ? ".verity/*" : l);
21204
21221
  lines = fenceMemoryLines(lines);
21205
- let text2 = lines.join("\n");
21222
+ let text3 = lines.join("\n");
21206
21223
  if (!hasMarker) {
21207
- const sep7 = text2 === "" ? "" : text2.endsWith("\n") ? "\n" : "\n\n";
21208
- text2 = text2 + sep7 + VERITY_GITIGNORE_BLOCK;
21224
+ const sep7 = text3 === "" ? "" : text3.endsWith("\n") ? "\n" : "\n\n";
21225
+ text3 = text3 + sep7 + VERITY_GITIGNORE_BLOCK;
21209
21226
  }
21210
21227
  try {
21211
- (0, import_node_fs24.writeFileSync)(".gitignore", text2);
21228
+ (0, import_node_fs24.writeFileSync)(".gitignore", text3);
21212
21229
  return true;
21213
21230
  } catch {
21214
21231
  return false;
@@ -22234,26 +22251,26 @@ var CLAUDE_MD_PROSE_LEGACY = [
22234
22251
  "superseded \u2014 ignore them unless investigating history."
22235
22252
  ].join("\n");
22236
22253
  var PRESERVE_PLACEHOLDER = "<!-- Add binding, hand-curated guidance here; it survives Verity regeneration. -->";
22237
- function* scanLines(text2) {
22254
+ function* scanLines(text3) {
22238
22255
  let offset = 0;
22239
22256
  let inFence = false;
22240
- for (const line2 of text2.split("\n")) {
22257
+ for (const line2 of text3.split("\n")) {
22241
22258
  const isFence = /^(`{3,}|~{3,})/.test(line2.trim());
22242
22259
  if (isFence) inFence = !inFence;
22243
22260
  yield { line: line2, start: offset, inFence: inFence || isFence };
22244
22261
  offset += line2.length + 1;
22245
22262
  }
22246
22263
  }
22247
- function findMarker(text2, marker, from = 0) {
22248
- for (const { line: line2, start: start2, inFence } of scanLines(text2)) {
22264
+ function findMarker(text3, marker, from = 0) {
22265
+ for (const { line: line2, start: start2, inFence } of scanLines(text3)) {
22249
22266
  if (!inFence && start2 >= from && line2.startsWith(marker)) {
22250
22267
  return start2;
22251
22268
  }
22252
22269
  }
22253
22270
  return -1;
22254
22271
  }
22255
- function hasLegacyMemoryBlock(text2) {
22256
- return findMarker(text2, LEGACY_MD_START) !== -1;
22272
+ function hasLegacyMemoryBlock(text3) {
22273
+ return findMarker(text3, LEGACY_MD_START) !== -1;
22257
22274
  }
22258
22275
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
22259
22276
  const claudeMdPath = (0, import_node_path23.join)(cwd, "CLAUDE.md");
@@ -22454,10 +22471,10 @@ var STOP = /* @__PURE__ */ new Set([
22454
22471
  "verify",
22455
22472
  "check"
22456
22473
  ]);
22457
- function pendingTokens(text2) {
22458
- if (!text2 || typeof text2 !== "string") return [];
22474
+ function pendingTokens(text3) {
22475
+ if (!text3 || typeof text3 !== "string") return [];
22459
22476
  const out2 = /* @__PURE__ */ new Set();
22460
- for (const raw of text2.toLowerCase().split(/[^a-z0-9]+/)) {
22477
+ for (const raw of text3.toLowerCase().split(/[^a-z0-9]+/)) {
22461
22478
  if (raw.length <= 3) continue;
22462
22479
  if (STOP.has(raw)) continue;
22463
22480
  out2.add(raw);
@@ -22469,11 +22486,11 @@ function overlapCoefficient(a, b) {
22469
22486
  if (a.length === 0 || b.length === 0) return 0;
22470
22487
  const setB = new Set(b);
22471
22488
  let shared = 0;
22472
- for (const t of a) if (setB.has(t)) shared++;
22489
+ for (const t2 of a) if (setB.has(t2)) shared++;
22473
22490
  return shared / Math.min(a.length, b.length);
22474
22491
  }
22475
- function isRepeatOfAny(text2, priorFingerprints, threshold = REPEAT_THRESHOLD) {
22476
- const tokens = pendingTokens(text2);
22492
+ function isRepeatOfAny(text3, priorFingerprints, threshold = REPEAT_THRESHOLD) {
22493
+ const tokens = pendingTokens(text3);
22477
22494
  if (tokens.length === 0) return false;
22478
22495
  return priorFingerprints.some((prior) => overlapCoefficient(tokens, prior) >= threshold);
22479
22496
  }
@@ -22519,13 +22536,13 @@ var import_node_crypto6 = require("node:crypto");
22519
22536
  var import_node_fs27 = require("node:fs");
22520
22537
  var import_node_path24 = require("node:path");
22521
22538
  var CRC_TABLE = (() => {
22522
- const t = new Int32Array(256);
22539
+ const t2 = new Int32Array(256);
22523
22540
  for (let i2 = 0; i2 < 256; i2++) {
22524
22541
  let c = i2;
22525
22542
  for (let k = 0; k < 8; k++) c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
22526
- t[i2] = c;
22543
+ t2[i2] = c;
22527
22544
  }
22528
- return t;
22545
+ return t2;
22529
22546
  })();
22530
22547
  function crc32(s) {
22531
22548
  let c = -1;
@@ -22550,8 +22567,8 @@ function openDossier(identity) {
22550
22567
  }
22551
22568
  var lastSeq = 0;
22552
22569
  function nextSeq() {
22553
- const t = Date.now() * 1e3;
22554
- lastSeq = t > lastSeq ? t : lastSeq + 1;
22570
+ const t2 = Date.now() * 1e3;
22571
+ lastSeq = t2 > lastSeq ? t2 : lastSeq + 1;
22555
22572
  return lastSeq;
22556
22573
  }
22557
22574
  function encodeEvent(ev) {
@@ -22996,7 +23013,7 @@ function expandState(raw) {
22996
23013
  const g = raw.g;
22997
23014
  const a = raw.a;
22998
23015
  const n2 = raw.n;
22999
- const t = raw.t;
23016
+ const t2 = raw.t;
23000
23017
  const c = raw.c;
23001
23018
  const dv = raw.d;
23002
23019
  const m = raw.m;
@@ -23047,7 +23064,7 @@ function expandState(raw) {
23047
23064
  at: iso(x[2]),
23048
23065
  head_sha: x[3]
23049
23066
  })) ?? null,
23050
- statements: t.map((x) => ({
23067
+ statements: t2.map((x) => ({
23051
23068
  anchor_key: x[0],
23052
23069
  file: x[1],
23053
23070
  line: x[2],
@@ -23163,8 +23180,8 @@ function assessContinuity(i2) {
23163
23180
  // src/lib/dossier/reanchor.ts
23164
23181
  var import_node_crypto8 = require("node:crypto");
23165
23182
  var import_node_fs30 = require("node:fs");
23166
- function lineSha(text2) {
23167
- return (0, import_node_crypto8.createHash)("sha256").update(text2.trim()).digest("hex").slice(0, HASH_WIDTH);
23183
+ function lineSha(text3) {
23184
+ return (0, import_node_crypto8.createHash)("sha256").update(text3.trim()).digest("hex").slice(0, HASH_WIDTH);
23168
23185
  }
23169
23186
  function fileHash(path) {
23170
23187
  try {
@@ -23637,20 +23654,20 @@ function recordGoal(d, prompt, source2 = "prompt") {
23637
23654
  appendEvent(d, { k: "goal_continue", text: prompt.slice(0, 64) });
23638
23655
  return;
23639
23656
  }
23640
- const text2 = prompt.slice(0, MAX_GOAL_CHARS);
23657
+ const text3 = prompt.slice(0, MAX_GOAL_CHARS);
23641
23658
  appendEvent(d, {
23642
23659
  k: "goal",
23643
- text: text2,
23660
+ text: text3,
23644
23661
  text_len: prompt.length,
23645
23662
  source: source2,
23646
23663
  ...prompt.length > MAX_GOAL_CHARS && { truncated: true }
23647
23664
  });
23648
23665
  }
23649
- function recordTurn(d, t) {
23666
+ function recordTurn(d, t2) {
23650
23667
  const root = repoRoot();
23651
- for (const a of t.authored) {
23668
+ for (const a of t2.authored) {
23652
23669
  const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
23653
- const prior = t.known?.authored?.get(a.p);
23670
+ const prior = t2.known?.authored?.get(a.p);
23654
23671
  const hash = fileHash((0, import_node_path26.join)(root, a.p));
23655
23672
  const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
23656
23673
  const adds = Math.max(0, a.a - (prior?.adds ?? 0));
@@ -23658,7 +23675,7 @@ function recordTurn(d, t) {
23658
23675
  if (prior && hunks === 0 && adds === 0 && dels === 0 && prior.hash_now === hash) continue;
23659
23676
  appendEvent(d, { k: "authored", path: a.p, origin, adds, dels, hunks, hash_now: hash });
23660
23677
  }
23661
- for (const c of t.commands) {
23678
+ for (const c of t2.commands) {
23662
23679
  appendEvent(d, {
23663
23680
  k: "command",
23664
23681
  cls: normaliseClass(c.class),
@@ -23671,20 +23688,20 @@ function recordTurn(d, t) {
23671
23688
  });
23672
23689
  }
23673
23690
  const head = getCurrentCommit();
23674
- for (const p of t.dirtyAtStart ?? []) {
23691
+ for (const p of t2.dirtyAtStart ?? []) {
23675
23692
  appendEvent(d, { k: "not_mine", path: p, reason: "dirty_at_start", head_sha: head });
23676
23693
  }
23677
- for (const p of t.foreign ?? []) {
23694
+ for (const p of t2.foreign ?? []) {
23678
23695
  appendEvent(d, { k: "not_mine", path: p, reason: "other_session", head_sha: head });
23679
23696
  }
23680
- for (const u of t.unobserved) {
23697
+ for (const u of t2.unobserved) {
23681
23698
  if (isGeneratedPath(u.p)) {
23682
23699
  appendEvent(d, { k: "not_mine", path: u.p, reason: "generated", head_sha: head });
23683
23700
  }
23684
23701
  }
23685
- const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
23702
+ const seenDivergence = t2.known?.divergence ?? /* @__PURE__ */ new Set();
23686
23703
  const fresh = [];
23687
- for (const u of t.unobserved) {
23704
+ for (const u of t2.unobserved) {
23688
23705
  const hash = fileHash((0, import_node_path26.join)(root, u.p));
23689
23706
  const key = divergenceKey(u.p, hash);
23690
23707
  const digest = packedDivergenceDigest(key);
@@ -23701,13 +23718,13 @@ function recordTurn(d, t) {
23701
23718
  appendEvent(d, { k: "divergence", kind: "external_mutation", path: f.path, hash: f.hash });
23702
23719
  }
23703
23720
  }
23704
- const newCompactions = (t.compactions ?? 0) - (t.known?.compactions ?? 0);
23721
+ const newCompactions = (t2.compactions ?? 0) - (t2.known?.compactions ?? 0);
23705
23722
  for (let i2 = 0; i2 < newCompactions; i2++) {
23706
23723
  appendEvent(d, { k: "mark", kind: "compaction", from: null, to: null });
23707
23724
  }
23708
- const known = t.known?.branch ?? null;
23709
- if (known && t.branch && known !== t.branch) {
23710
- appendEvent(d, { k: "mark", kind: "branch_switch", from: known, to: t.branch });
23725
+ const known = t2.known?.branch ?? null;
23726
+ if (known && t2.branch && known !== t2.branch) {
23727
+ appendEvent(d, { k: "mark", kind: "branch_switch", from: known, to: t2.branch });
23711
23728
  }
23712
23729
  }
23713
23730
  function normaliseClass(cls) {
@@ -23772,7 +23789,7 @@ function recordVerdict(d, v) {
23772
23789
  // actually spoke — a silenced turn delivered nothing, so nothing was "said
23773
23790
  // before" and labelling the next turn's items as repeats would be a lie.
23774
23791
  ...v.emitted === true && v.pendingTexts && v.pendingTexts.length > 0 && {
23775
- pending_sigs: v.pendingTexts.slice(0, 8).map((t) => pendingTokens(t).slice(0, 16))
23792
+ pending_sigs: v.pendingTexts.slice(0, 8).map((t2) => pendingTokens(t2).slice(0, 16))
23776
23793
  },
23777
23794
  emitted: v.emitted === true,
23778
23795
  idle: v.idle !== false,
@@ -24580,8 +24597,8 @@ function buildCompactionContext(session) {
24580
24597
  `${r.projection.fold.refused} earlier finding(s) were dropped because the code they pointed at no longer matches. They are resolved; do not revisit them.`
24581
24598
  );
24582
24599
  }
24583
- const text2 = lines.join("\n");
24584
- if (text2.length <= MAX_CHARS) return text2;
24600
+ const text3 = lines.join("\n");
24601
+ if (text3.length <= MAX_CHARS) return text3;
24585
24602
  const trimmed = [...lines.slice(0, 5), ...lines.slice(5, 5 + 2)].join("\n");
24586
24603
  return trimmed.length <= MAX_CHARS ? trimmed : null;
24587
24604
  }
@@ -24647,7 +24664,7 @@ async function readHookStdin() {
24647
24664
  // src/commands/standard.ts
24648
24665
  var import_node_fs38 = require("node:fs");
24649
24666
  var import_node_path31 = require("node:path");
24650
- var import_yaml7 = __toESM2(require_dist());
24667
+ var import_yaml8 = __toESM2(require_dist());
24651
24668
 
24652
24669
  // src/lib/synthesize.ts
24653
24670
  var import_node_fs36 = require("node:fs");
@@ -24858,14 +24875,14 @@ function trackedSourceFiles(root, opts = {}) {
24858
24875
  return files.slice(0, opts.maxFiles ?? 5e3);
24859
24876
  }
24860
24877
  var EFFECT_LINE = /\bawait\b|\basync\s+with\b|\.then\(|\bsetTimeout\(|\bsetInterval\(|\bwith\s+\w[\w.]*\.(?:lock|acquire)\b|\bLock\(\)/;
24861
- function countEffects(text2) {
24878
+ function countEffects(text3) {
24862
24879
  let n2 = 0;
24863
- for (const line2 of text2.split("\n")) if (EFFECT_LINE.test(line2)) n2++;
24880
+ for (const line2 of text3.split("\n")) if (EFFECT_LINE.test(line2)) n2++;
24864
24881
  return n2;
24865
24882
  }
24866
- function scanRisk(text2) {
24883
+ function scanRisk(text3) {
24867
24884
  const counts = Object.fromEntries(RISK_PATTERNS.map(([c]) => [c, 0]));
24868
- for (const line2 of text2.split("\n")) {
24885
+ for (const line2 of text3.split("\n")) {
24869
24886
  for (const [category, re] of RISK_PATTERNS) {
24870
24887
  if (re.test(line2)) counts[category]++;
24871
24888
  }
@@ -24961,14 +24978,14 @@ var SECRET_PATTERNS = [
24961
24978
  var EMAIL = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g;
24962
24979
  var URL_CREDENTIALS = /\b([a-z][a-z0-9+.-]*:\/\/)[^\s/:@]+:[^\s/@]+@/gi;
24963
24980
  var CONTROL3 = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f\u2028-\u202e\u2066-\u2069]/g;
24964
- function redact(text2) {
24965
- let out2 = text2.replace(CONTROL3, "");
24981
+ function redact(text3) {
24982
+ let out2 = text3.replace(CONTROL3, "");
24966
24983
  for (const re of SECRET_PATTERNS) out2 = out2.replace(re, "[redacted]");
24967
24984
  out2 = out2.replace(URL_CREDENTIALS, "$1[redacted]@");
24968
24985
  return out2.replace(EMAIL, "[email]");
24969
24986
  }
24970
- function oneLine(text2, max) {
24971
- return redact(text2.replace(/[\r\n\t]+/g, " ")).trim().slice(0, max);
24987
+ function oneLine(text3, max) {
24988
+ return redact(text3.replace(/[\r\n\t]+/g, " ")).trim().slice(0, max);
24972
24989
  }
24973
24990
  function safePath(p) {
24974
24991
  if (!p || p.length > PATH_MAX || p.startsWith("/") || p.includes("\\")) return null;
@@ -25010,11 +25027,11 @@ function indentWidth(line2) {
25010
25027
  }
25011
25028
  return w;
25012
25029
  }
25013
- function stripCode(text2) {
25030
+ function stripCode(text3) {
25014
25031
  const out2 = [];
25015
25032
  let fence = null;
25016
25033
  let underItem = false;
25017
- for (const line2 of text2.split("\n")) {
25034
+ for (const line2 of text3.split("\n")) {
25018
25035
  const body2 = line2.replace(QUOTE, "");
25019
25036
  if (fence) {
25020
25037
  const close = FENCE_CLOSE.exec(body2);
@@ -25042,27 +25059,27 @@ function stripCode(text2) {
25042
25059
  return out2.join("\n");
25043
25060
  }
25044
25061
  function docText(raw) {
25045
- let text2 = raw;
25046
- const start2 = text2.indexOf(MANAGED_START);
25047
- const end = start2 >= 0 ? text2.indexOf(MANAGED_END, start2) : -1;
25062
+ let text3 = raw;
25063
+ const start2 = text3.indexOf(MANAGED_START);
25064
+ const end = start2 >= 0 ? text3.indexOf(MANAGED_END, start2) : -1;
25048
25065
  if (start2 >= 0 && end > start2) {
25049
- const block = text2.slice(start2, end);
25066
+ const block = text3.slice(start2, end);
25050
25067
  const ps = block.indexOf(PRESERVE_START2);
25051
25068
  const pe = ps >= 0 ? block.indexOf(PRESERVE_END2, ps) : -1;
25052
25069
  const kept = ps >= 0 && pe > ps ? block.slice(ps + PRESERVE_START2.length, pe) : "";
25053
- text2 = text2.slice(0, start2) + kept + text2.slice(end + MANAGED_END.length);
25070
+ text3 = text3.slice(0, start2) + kept + text3.slice(end + MANAGED_END.length);
25054
25071
  }
25055
- text2 = stripCode(text2.replace(/<!--[\s\S]*?-->/g, "").replace(/<!--[\s\S]*$/, "")).replace(/\n{3,}/g, "\n\n");
25056
- return redact(text2).trim();
25072
+ text3 = stripCode(text3.replace(/<!--[\s\S]*?-->/g, "").replace(/<!--[\s\S]*$/, "")).replace(/\n{3,}/g, "\n\n");
25073
+ return redact(text3).trim();
25057
25074
  }
25058
25075
  var RULE_TITLE = /convention|pattern|rule|gotcha|footgun|pitfall|best practice|guideline|principle|standard|style|architecture|design|security|database|migration|schema|\bapi\b|error|state|naming|structure|i18n|internationali[sz]|translation|important|critical|warning|do not|don't|never|must|avoid/i;
25059
25076
  var SETUP_TITLE = /setup|set up|install|getting started|quick ?start|command|script|\bci\b|release|deploy|reference|link|troubleshoot|licen[cs]e|faq|contact|support|changelog|prerequisite|environment|on the web|cloud|skill|documentation/i;
25060
25077
  var NORMATIVE = /\b(must|never|always|do not|don't|should|shouldn't|avoid|prefer|required|only|instead of|make sure|ensure)\b/i;
25061
- function docSections(text2) {
25078
+ function docSections(text3) {
25062
25079
  const out2 = [];
25063
25080
  const open = [];
25064
25081
  let current = { order: 0, heading: null, path: "", parents: [], lines: [] };
25065
- for (const line2 of text2.split("\n")) {
25082
+ for (const line2 of text3.split("\n")) {
25066
25083
  const m = /^(#{1,6})\s+(.*)$/.exec(line2);
25067
25084
  if (!m) {
25068
25085
  current.lines.push(line2);
@@ -25084,9 +25101,9 @@ function sectionRank(s) {
25084
25101
  const title = rule && !setup ? 2 : setup && !rule ? 0 : 1;
25085
25102
  return title * 1e3 + Math.min(999, s.lines.filter((l) => NORMATIVE.test(l)).length);
25086
25103
  }
25087
- function fitDoc(text2, budget) {
25088
- if (utf8(text2) <= budget) return text2;
25089
- const all = docSections(text2);
25104
+ function fitDoc(text3, budget) {
25105
+ if (utf8(text3) <= budget) return text3;
25106
+ const all = docSections(text3);
25090
25107
  const lineBytes = (line2) => utf8(line2) + 1;
25091
25108
  const GAP = lineBytes("\u2026");
25092
25109
  const chosen = /* @__PURE__ */ new Map();
@@ -25127,14 +25144,14 @@ function fitDoc(text2, budget) {
25127
25144
  }
25128
25145
  return cutToBytes(out2.join("\n").replace(/\n{3,}/g, "\n\n").trim(), budget);
25129
25146
  }
25130
- function utf8(text2) {
25131
- return Buffer.byteLength(text2, "utf8");
25147
+ function utf8(text3) {
25148
+ return Buffer.byteLength(text3, "utf8");
25132
25149
  }
25133
- function cutToBytes(text2, max) {
25134
- if (utf8(text2) <= max) return text2;
25150
+ function cutToBytes(text3, max) {
25151
+ if (utf8(text3) <= max) return text3;
25135
25152
  let out2 = "";
25136
25153
  let n2 = 0;
25137
- for (const ch of text2) {
25154
+ for (const ch of text3) {
25138
25155
  const b = utf8(ch);
25139
25156
  if (n2 + b > max) break;
25140
25157
  out2 += ch;
@@ -25161,11 +25178,11 @@ function readDocs(root, files) {
25161
25178
  const read2 = readRegularFileInRoot(root, name2, 256 * 1024);
25162
25179
  if (!read2.ok) continue;
25163
25180
  const fresh = docText(read2.content).split("\n").filter((l) => /^#{1,6}\s/.test(l) || normal(l).length < 25 || !sent.has(normal(l))).join("\n");
25164
- const text2 = fitDoc(fresh, room);
25165
- if (!text2) continue;
25166
- for (const l of text2.split("\n")) if (normal(l).length >= 25) sent.add(normal(l));
25167
- total += utf8(text2);
25168
- out2.push({ name: name2, text: text2 });
25181
+ const text3 = fitDoc(fresh, room);
25182
+ if (!text3) continue;
25183
+ for (const l of text3.split("\n")) if (normal(l).length >= 25) sent.add(normal(l));
25184
+ total += utf8(text3);
25185
+ out2.push({ name: name2, text: text3 });
25169
25186
  }
25170
25187
  return out2;
25171
25188
  }
@@ -25633,8 +25650,8 @@ async function writeSetupState(patch) {
25633
25650
  } catch {
25634
25651
  }
25635
25652
  }
25636
- const text2 = JSON.stringify(next, null, raw !== null ? detectJsonIndent(raw) : 2) + "\n";
25637
- if (!replaceInRoot(projectPath(VERITY_DIR), "setup.json", text2)) {
25653
+ const text3 = JSON.stringify(next, null, raw !== null ? detectJsonIndent(raw) : 2) + "\n";
25654
+ if (!replaceInRoot(projectPath(VERITY_DIR), "setup.json", text3)) {
25638
25655
  throw new Error(`Could not write ${SETUP_STATE_FILE}: it is a link, or ${VERITY_DIR} is not a folder of this repository`);
25639
25656
  }
25640
25657
  return next;
@@ -25786,9 +25803,8 @@ async function pullStandard(globals, opts = {}) {
25786
25803
  if (local && typeof local === "object" && !Array.isArray(local) && sameStandard(local, remote.standard.content)) {
25787
25804
  return { status: "same", version };
25788
25805
  }
25789
- backup = `.verity/standard.${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.yaml`;
25790
25806
  try {
25791
- writeRepoFile(backup, raw);
25807
+ backup = keepStandardCopy(raw);
25792
25808
  } catch (err2) {
25793
25809
  return { status: "failed", message: `Could not keep a copy of ${STANDARD_FILE} (${terminalText(err2 instanceof Error ? err2.message : String(err2), 200)}), so it was not replaced. Nothing changed.` };
25794
25810
  }
@@ -25823,6 +25839,174 @@ async function runPull(globals) {
25823
25839
  for (const note of r.notes) printWarn(terminalText(note, 300));
25824
25840
  }
25825
25841
 
25842
+ // src/commands/standard-catalogue.ts
25843
+ var import_yaml7 = __toESM2(require_dist());
25844
+ var PAGE = "verity.md/review-packs";
25845
+ var t = (v, max = 300) => terminalText(typeof v === "string" ? v : String(v ?? ""), max);
25846
+ function extendedPacks(yamlText) {
25847
+ if (!yamlText) return /* @__PURE__ */ new Set();
25848
+ try {
25849
+ const doc = (0, import_yaml7.parse)(yamlText);
25850
+ if (!Array.isArray(doc?.extends)) return /* @__PURE__ */ new Set();
25851
+ return new Set(doc.extends.filter((e) => typeof e === "string").map((e) => e.replace(/^verity\//, "").replace(/@.*$/, "")));
25852
+ } catch {
25853
+ return /* @__PURE__ */ new Set();
25854
+ }
25855
+ }
25856
+ function whenText(pack) {
25857
+ if (pack.always) return "always on";
25858
+ const items = pack.when?.any ?? pack.when?.all;
25859
+ if (!items || items.length === 0) return "add it by hand";
25860
+ const list2 = (label2, v) => `${label2} ${v.slice(0, 4).join(", ")}${v.length > 4 ? `, +${v.length - 4} more` : ""}`;
25861
+ const parts2 = items.map((s) => {
25862
+ if (s.bin) return "the repository ships a CLI";
25863
+ if (s.language) return list2("languages", s.language);
25864
+ if (s.framework) return list2("frameworks", s.framework);
25865
+ if (s.dep) return list2("dependencies", s.dep);
25866
+ if (s.path) return list2("paths", s.path);
25867
+ return "another signal";
25868
+ });
25869
+ return `when ${parts2.join(pack.when?.all ? " and " : " or ")}`;
25870
+ }
25871
+ function renderPackList(c, extended) {
25872
+ const width = Math.max(...c.packs.map((p) => p.ref.length));
25873
+ const lines = [`Review packs (catalogue ${t(c.catalogue_version, 40)}). The full catalogue: ${PAGE}`];
25874
+ for (const p of c.packs) {
25875
+ const mark = extended.has(p.id) ? "\u2713" : " ";
25876
+ const n2 = `${p.rules.length} rule${p.rules.length === 1 ? "" : "s"}`;
25877
+ lines.push(` ${mark} ${t(p.ref, 60).padEnd(width)} ${n2.padStart(8)} ${t(whenText(p), 200)}`);
25878
+ }
25879
+ if (extended.size > 0) lines.push(`\u2713 = in "extends" in ${STANDARD_FILE}`);
25880
+ lines.push("The rules of one pack: verity standard catalogue <pack>");
25881
+ return lines;
25882
+ }
25883
+ function renderPack(p, extended) {
25884
+ const head = `${t(p.ref, 60)}: ${t(p.title, 60)} (${p.rules.length} rule${p.rules.length === 1 ? "" : "s"}, ${t(whenText(p), 200)})${extended.has(p.id) ? ". This project extends it." : ""}`;
25885
+ const lines = [head, ` ${t(p.summary, 400)}`];
25886
+ for (const r of p.rules) {
25887
+ const refs = [...r.maps_to.cwe ?? [], ...r.maps_to.owasp ?? [], ...r.maps_to.owasp_api ?? [], ...r.maps_to.owasp_llm ?? []];
25888
+ lines.push("");
25889
+ lines.push(` ${t(r.id, 80)} ${t(r.severity, 10)} ${t(r.category, 20)} ${t(r.title, 120)}${refs.length ? ` [${t(refs.slice(0, 4).join(", "), 120)}]` : ""}`);
25890
+ lines.push(` ${t(r.rule, 600)}`);
25891
+ if (!r.reviewed_in_diff) lines.push(" Not given to the diff reviewer yet: it is seen in commands or the session, not in the code change.");
25892
+ if (r.also_in.length) lines.push(` Also in: ${t(r.also_in.join(", "), 200)}`);
25893
+ }
25894
+ lines.push("");
25895
+ lines.push(`Turn one rule off in ${STANDARD_FILE}: overrides: { <rule-id>: off }, then verity standard push. Examples: ${PAGE}#${t(p.id, 40)}`);
25896
+ return lines;
25897
+ }
25898
+ var LIMITS2 = { packs: 32, rules: 200, list: 200, id: 120, text: 8e3, item: 200 };
25899
+ var text = (v, max = LIMITS2.text) => typeof v === "string" && v.length <= max;
25900
+ var strings = (v) => Array.isArray(v) && v.length <= LIMITS2.list && v.every((x) => text(x, LIMITS2.item));
25901
+ var optionalStrings = (v) => v === void 0 || strings(v);
25902
+ var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
25903
+ function isSignal(v) {
25904
+ if (!isObject(v)) return false;
25905
+ const keys = Object.keys(v);
25906
+ if (keys.length !== 1) return false;
25907
+ const [k] = keys;
25908
+ if (k === "bin") return v.bin === true;
25909
+ return ["language", "framework", "dep", "path"].includes(k) && strings(v[k]);
25910
+ }
25911
+ function isWhen(v) {
25912
+ if (v === null) return true;
25913
+ if (!isObject(v)) return false;
25914
+ const keys = Object.keys(v);
25915
+ if (keys.length !== 1 || keys[0] !== "any" && keys[0] !== "all") return false;
25916
+ const items = v[keys[0]];
25917
+ return Array.isArray(items) && items.length <= LIMITS2.list && items.every(isSignal);
25918
+ }
25919
+ function isRule(v) {
25920
+ if (!isObject(v)) return false;
25921
+ const m = v.maps_to;
25922
+ return text(v.id, LIMITS2.id) && text(v.severity, LIMITS2.id) && text(v.category, LIMITS2.id) && text(v.title, LIMITS2.item) && text(v.rule) && text(v.evidence_required) && typeof v.reviewed_in_diff === "boolean" && strings(v.also_in) && isObject(m) && ["cwe", "owasp", "owasp_api", "owasp_llm"].every((k) => optionalStrings(m[k]));
25923
+ }
25924
+ function isPack(v) {
25925
+ if (!isObject(v)) return false;
25926
+ return text(v.id, LIMITS2.id) && text(v.ref, LIMITS2.id) && text(v.title, LIMITS2.item) && text(v.summary) && typeof v.always === "boolean" && isWhen(v.when) && Array.isArray(v.rules) && v.rules.length <= LIMITS2.rules && v.rules.every(isRule);
25927
+ }
25928
+ var copyStrings = (v) => [...v];
25929
+ function copyRule(v) {
25930
+ const m = v.maps_to;
25931
+ const maps = {};
25932
+ for (const k of ["cwe", "owasp", "owasp_api", "owasp_llm"]) if (m[k] !== void 0) maps[k] = copyStrings(m[k]);
25933
+ return {
25934
+ id: v.id,
25935
+ title: v.title,
25936
+ rule: v.rule,
25937
+ evidence_required: v.evidence_required,
25938
+ category: v.category,
25939
+ severity: v.severity,
25940
+ reviewed_in_diff: v.reviewed_in_diff,
25941
+ maps_to: maps,
25942
+ also_in: copyStrings(v.also_in)
25943
+ };
25944
+ }
25945
+ function copyWhen(v) {
25946
+ if (v === null) return null;
25947
+ const w = v;
25948
+ const key = "any" in w ? "any" : "all";
25949
+ const signals = w[key].map((s) => {
25950
+ const [k, val] = Object.entries(s)[0];
25951
+ return k === "bin" ? { bin: true } : { [k]: copyStrings(val) };
25952
+ });
25953
+ return key === "any" ? { any: signals } : { all: signals };
25954
+ }
25955
+ function asCatalogue(v) {
25956
+ if (!isObject(v) || !text(v.catalogue_version, LIMITS2.id) || !Array.isArray(v.packs) || v.packs.length > LIMITS2.packs || !v.packs.every(isPack)) return null;
25957
+ return {
25958
+ catalogue_version: v.catalogue_version,
25959
+ packs: v.packs.map((p) => ({
25960
+ id: p.id,
25961
+ ref: p.ref,
25962
+ title: p.title,
25963
+ summary: p.summary,
25964
+ always: p.always,
25965
+ when: copyWhen(p.when),
25966
+ rules: p.rules.map(copyRule)
25967
+ }))
25968
+ };
25969
+ }
25970
+ async function runCatalogue(globals, pack, opts) {
25971
+ const url = await resolveServiceUrl(globals.serviceUrl);
25972
+ if (!url.ok) {
25973
+ printError(t(url.error));
25974
+ process.exit(1);
25975
+ }
25976
+ const res = await apiRequest({
25977
+ method: "GET",
25978
+ path: "/standards/catalogue/packs",
25979
+ serviceUrl: url.data,
25980
+ verbose: globals.verbose,
25981
+ cmd: "standard catalogue",
25982
+ withoutRemote: true,
25983
+ timeout: 15e3
25984
+ });
25985
+ if (!res.ok) {
25986
+ printError(`Could not read the review-pack catalogue from the Verity service: ${t(res.error)}. See ${PAGE}`);
25987
+ process.exit(1);
25988
+ }
25989
+ const catalogue = asCatalogue(res.data);
25990
+ if (!catalogue) {
25991
+ printError(`The Verity service answered with something that is not a review-pack catalogue. See ${PAGE}`);
25992
+ process.exit(1);
25993
+ }
25994
+ const extended = extendedPacks(readRepoFile(STANDARD_FILE));
25995
+ if (pack === void 0) {
25996
+ if (opts.json) printJson(catalogue);
25997
+ else for (const line2 of renderPackList(catalogue, extended)) printInfo(line2);
25998
+ return;
25999
+ }
26000
+ const id = pack.replace(/^verity\//, "").replace(/@.*$/, "");
26001
+ const found = catalogue.packs.find((p) => p.id === id);
26002
+ if (!found) {
26003
+ printError(`No review pack named "${t(pack, 60)}". The packs: ${t(catalogue.packs.map((p) => p.id).join(", "), 300)}.`);
26004
+ process.exit(1);
26005
+ }
26006
+ if (opts.json) printJson(found);
26007
+ else for (const line2 of renderPack(found, extended)) printInfo(line2);
26008
+ }
26009
+
25826
26010
  // src/commands/standard.ts
25827
26011
  function registerStandardCommands(program2) {
25828
26012
  const standard = program2.command("standard").description("Manage the project Standard");
@@ -25860,6 +26044,7 @@ function registerStandardCommands(program2) {
25860
26044
  });
25861
26045
  standard.command("generate").description("Have Verity write project-specific rules from a profile of this repository (asks before sending it)").option("--yes", `Send the profile without asking (you have read ${PROFILE_FILE})`).option("--status", "Print whether the service writes project rules for this project: on, off, unsupported or unknown. Sends nothing.").action((opts) => runGenerate(program2.opts(), opts));
25862
26046
  standard.command("pull").description("Write the team's Standard on the service into .verity/standard.yaml (keeps a copy of yours)").action(() => runPull(program2.opts()));
26047
+ standard.command("catalogue [pack]").description("What each review pack holds: every pack, or the rules of one (core, api, data, \u2026)").option("--json", "Print the catalogue as JSON").action((pack, opts) => runCatalogue(program2.opts(), pack, opts));
25863
26048
  standard.command("push").description("Upload the project Standard to the service").option("--file <path>", "Path to standard YAML file", STANDARD_FILE).option("--created-by <name>", "Who created this version", "claude-code").action(async (opts) => {
25864
26049
  const globals = program2.opts();
25865
26050
  const tokenResult = await resolveToken(globals.token);
@@ -25997,7 +26182,7 @@ function standardUploadBody(yamlText, file, ignoreRaw, createdBy) {
25997
26182
  if (!author.ok) return { ok: false, error: `--created-by: ${author.error}. Nothing was sent.` };
25998
26183
  let parsed;
25999
26184
  try {
26000
- parsed = (0, import_yaml7.parse)(yamlText);
26185
+ parsed = (0, import_yaml8.parse)(yamlText);
26001
26186
  } catch (err2) {
26002
26187
  return { ok: false, error: `Invalid YAML in ${shown}: ${terminalText(err2.message, 300)}` };
26003
26188
  }
@@ -27087,15 +27272,15 @@ function renderSeatUsage(d, now = /* @__PURE__ */ new Date()) {
27087
27272
  lines.push(` ${pad("Turn reviews", 24)}session ${pad(used(me.session.turn, ml?.turn.session), 12)}week ${pad(used(w.turn, memberWeek("turn")), 14)}busiest session ${n(w.peak_session.turn)}`);
27088
27273
  lines.push(` This week: ${n(w.blocked)} blocked, ${n(w.warned)} warned \xB7 review time p50 ${secs(w.latency_ms.p50)}, p90 ${secs(w.latency_ms.p90)}`);
27089
27274
  }
27090
- const t = d.totals.weeks[0];
27275
+ const t2 = d.totals.weeks[0];
27091
27276
  lines.push("");
27092
27277
  lines.push(`Team \xB7 ${n(d.totals.active_members)} active this week`);
27093
- const poolUsed = pool?.used ?? (pool ? { commit: t.commit, turn: t.turn } : null);
27278
+ const poolUsed = pool?.used ?? (pool ? { commit: t2.commit, turn: t2.turn } : null);
27094
27279
  if (pool && poolUsed && d.plan) {
27095
27280
  lines.push(
27096
27281
  ` Week pool: ${n(poolUsed.commit)} / ${n(pool.commit)} commit & push, ${n(poolUsed.turn)} / ${n(pool.turn)} turn (${poolText(d.plan, pool.members)}; the session limit is each member's)`
27097
27282
  );
27098
- if (pool.used) lines.push(` Everyone in ${d.organization.name} this week, members or not: ${n(t.commit)} commit & push, ${n(t.turn)} turn.`);
27283
+ if (pool.used) lines.push(` Everyone in ${d.organization.name} this week, members or not: ${n(t2.commit)} commit & push, ${n(t2.turn)} turn.`);
27099
27284
  }
27100
27285
  if (d.viewer !== "member" && d.members.length > 0) {
27101
27286
  const rows = d.members.map((m) => [
@@ -27113,19 +27298,19 @@ function renderSeatUsage(d, now = /* @__PURE__ */ new Date()) {
27113
27298
  const total = [
27114
27299
  "Team total",
27115
27300
  n(d.totals.session.commit),
27116
- used(t.commit, totalLimit("commit")),
27117
- n(t.peak_session.commit),
27301
+ used(t2.commit, totalLimit("commit")),
27302
+ n(t2.peak_session.commit),
27118
27303
  n(d.totals.session.turn),
27119
- used(t.turn, totalLimit("turn")),
27120
- n(t.blocked),
27121
- `${secs(t.latency_ms.p50)} / ${secs(t.latency_ms.p90)}`
27304
+ used(t2.turn, totalLimit("turn")),
27305
+ n(t2.blocked),
27306
+ `${secs(t2.latency_ms.p50)} / ${secs(t2.latency_ms.p90)}`
27122
27307
  ];
27123
27308
  const widths = head.map((h, i2) => Math.max(h.length, ...rows.map((r) => r[i2].length), total[i2].length) + 2);
27124
27309
  lines.push(" " + head.map((h, i2) => pad(h, widths[i2])).join("").trimEnd());
27125
27310
  for (const r of rows) lines.push(" " + r.map((c, i2) => pad(c, widths[i2])).join("").trimEnd());
27126
27311
  lines.push(" " + total.map((c, i2) => pad(c, widths[i2])).join("").trimEnd());
27127
27312
  } else {
27128
- lines.push(` This week: ${n(t.commit)} commit & push reviews, ${n(t.turn)} turn reviews, ${n(t.blocked)} blocked.`);
27313
+ lines.push(` This week: ${n(t2.commit)} commit & push reviews, ${n(t2.turn)} turn reviews, ${n(t2.blocked)} blocked.`);
27129
27314
  if (d.viewer === "member") lines.push(` Only the admins of ${d.organization.name} see every member.`);
27130
27315
  }
27131
27316
  if (d.truncated) lines.push(" (Partial: the org has more reviews than one report reads.)");
@@ -27250,16 +27435,16 @@ function readTextInput(value, flag, readStdin2 = () => (0, import_node_fs42.read
27250
27435
  if (raw.length > MAX_STDIN_BYTES) {
27251
27436
  return { ok: false, error: `${flag} from stdin is ${raw.length} bytes; the limit is ${MAX_STDIN_BYTES}.` };
27252
27437
  }
27253
- const text2 = raw.toString("utf8").replace(/\r?\n$/, "");
27254
- if (!text2.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
27255
- return { ok: true, text: text2 };
27438
+ const text3 = raw.toString("utf8").replace(/\r?\n$/, "");
27439
+ if (!text3.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
27440
+ return { ok: true, text: text3 };
27256
27441
  }
27257
27442
 
27258
27443
  // src/commands/feedback.ts
27259
27444
  function registerFeedbackCommand(program2) {
27260
27445
  const feedbackCmd = program2.command("feedback").description("Send feedback to the Verity team");
27261
- feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text2, opts) => {
27262
- await sendMessageArg(text2, opts, program2.opts());
27446
+ feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text3, opts) => {
27447
+ await sendMessageArg(text3, opts, program2.opts());
27263
27448
  });
27264
27449
  feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.); a note of - is read from stdin").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action, inlineNote, opts) => {
27265
27450
  const globals = program2.opts();
@@ -27865,28 +28050,28 @@ function parseRgLine(line2) {
27865
28050
  return { file: line2.slice(0, first), line: n2, text: line2.slice(second + 1) };
27866
28051
  }
27867
28052
  var isWordChar = (c) => c !== void 0 && /[A-Za-z0-9_]/.test(c);
27868
- function wordHit(text2, symbol) {
28053
+ function wordHit(text3, symbol) {
27869
28054
  let from = 0;
27870
28055
  for (; ; ) {
27871
- const at = text2.indexOf(symbol, from);
28056
+ const at = text3.indexOf(symbol, from);
27872
28057
  if (at < 0) return false;
27873
- const before = at === 0 ? void 0 : text2[at - 1];
27874
- const after = text2[at + symbol.length];
28058
+ const before = at === 0 ? void 0 : text3[at - 1];
28059
+ const after = text3[at + symbol.length];
27875
28060
  if (!isWordChar(before) && !isWordChar(after)) return true;
27876
28061
  from = at + 1;
27877
28062
  }
27878
28063
  }
27879
- function isContractLine(text2, symbol) {
28064
+ function isContractLine(text3, symbol) {
27880
28065
  for (const kw of ["implements", "extends"]) {
27881
28066
  let from = 0;
27882
28067
  for (; ; ) {
27883
- const at = text2.indexOf(kw, from);
28068
+ const at = text3.indexOf(kw, from);
27884
28069
  if (at < 0) break;
27885
28070
  from = at + 1;
27886
- const before = at === 0 ? void 0 : text2[at - 1];
27887
- const after = text2[at + kw.length];
28071
+ const before = at === 0 ? void 0 : text3[at - 1];
28072
+ const after = text3[at + kw.length];
27888
28073
  if (isWordChar(before) || isWordChar(after)) continue;
27889
- let clause = text2.slice(at + kw.length);
28074
+ let clause = text3.slice(at + kw.length);
27890
28075
  const stop2 = Math.min(
27891
28076
  ...[clause.indexOf(";"), clause.indexOf("{")].filter((i2) => i2 >= 0)
27892
28077
  );
@@ -27918,20 +28103,20 @@ function partitionSites(rgLines, symbols, opts) {
27918
28103
  if (opts.sentPaths.has(h.file)) continue;
27919
28104
  if (opts.isExcluded(h.file)) continue;
27920
28105
  if (!isCodeSiteFile(h.file)) continue;
27921
- const text2 = h.text.trim();
27922
- if (text2.length === 0 || IMPORT_LINE.test(h.text)) continue;
27923
- if (COMMENT_LINE.test(text2)) continue;
27924
- if (BARE_MEMBER_LINE.test(text2) || GO_IMPORT_PATH_LINE.test(text2)) continue;
28106
+ const text3 = h.text.trim();
28107
+ if (text3.length === 0 || IMPORT_LINE.test(h.text)) continue;
28108
+ if (COMMENT_LINE.test(text3)) continue;
28109
+ if (BARE_MEMBER_LINE.test(text3) || GO_IMPORT_PATH_LINE.test(text3)) continue;
27925
28110
  const n2 = perFile.get(h.file) ?? 0;
27926
28111
  if (n2 >= MAX_SITES_PER_FILE) continue;
27927
28112
  const site = {
27928
28113
  file: h.file,
27929
28114
  line: h.line,
27930
- text: text2.slice(0, SITE_TEXT_MAX),
28115
+ text: text3.slice(0, SITE_TEXT_MAX),
27931
28116
  symbol: h.symbol,
27932
28117
  // R2 falls out of R1 for free: a word search for `Sym` already matches
27933
28118
  // `implements Sym` / `extends Sym` lines — classification is all R2 is.
27934
- ...isContractLine(text2, h.symbol) ? { kind: "contract" } : {}
28119
+ ...isContractLine(text3, h.symbol) ? { kind: "contract" } : {}
27935
28120
  };
27936
28121
  if (isTestPath(h.file)) {
27937
28122
  if (tests.length < MAX_TEST_SLOTS) {
@@ -27951,8 +28136,8 @@ var MAX_IMPORTERS_PER_FILE = 2;
27951
28136
  function moduleKey(path) {
27952
28137
  return path.replace(/\.(ts|tsx|js|jsx|mjs|cjs|mts|cts)$/i, "").replace(/\/index$/, "");
27953
28138
  }
27954
- function importSpecifier(text2) {
27955
- const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text2);
28139
+ function importSpecifier(text3) {
28140
+ const m = /(?:\bfrom|\brequire\s*\(|\bimport\s*\(|^\s*import)\s*['"]([^'"\n]+)['"]/.exec(text3);
27956
28141
  return m?.[1] ?? null;
27957
28142
  }
27958
28143
  function resolveSpecifier(fromFile, spec) {
@@ -28222,8 +28407,8 @@ function extractEnclosingExcerpt(content, siteLine, path) {
28222
28407
  start2 = Math.max(1, siteLine - (EXCERPT_MAX_LINES - 6));
28223
28408
  }
28224
28409
  const end = Math.min(lines.length, start2 + EXCERPT_MAX_LINES - 1);
28225
- const text2 = lines.slice(start2 - 1, end).join("\n").slice(0, EXCERPT_MAX_CHARS);
28226
- return { start_line: start2, text: text2 };
28410
+ const text3 = lines.slice(start2 - 1, end).join("\n").slice(0, EXCERPT_MAX_CHARS);
28411
+ return { start_line: start2, text: text3 };
28227
28412
  }
28228
28413
  function upgradeToExcerpts(rc, opts) {
28229
28414
  if (rc.state !== "ok") return;
@@ -28357,10 +28542,10 @@ function formatRunEvidence(run4, startedAt) {
28357
28542
  }
28358
28543
  }
28359
28544
  if (run4.foldResult?.tools?.length) {
28360
- const shown = run4.foldResult.tools.slice(0, 6).map((t) => {
28361
- const outcome = t.failed > 0 ? `${t.failed} failed` : t.last_status === 0 ? "ok" : "?";
28362
- const where2 = t.targets.length > 0 ? ` \u2192 ${t.targets.slice(0, 2).join(", ")}` : "";
28363
- return `${t.runs}\xD7 ${t.name} (${outcome})${where2}`;
28545
+ const shown = run4.foldResult.tools.slice(0, 6).map((t2) => {
28546
+ const outcome = t2.failed > 0 ? `${t2.failed} failed` : t2.last_status === 0 ? "ok" : "?";
28547
+ const where2 = t2.targets.length > 0 ? ` \u2192 ${t2.targets.slice(0, 2).join(", ")}` : "";
28548
+ return `${t2.runs}\xD7 ${t2.name} (${outcome})${where2}`;
28364
28549
  });
28365
28550
  const more = run4.foldResult.tools.length > 6 ? ` \u2026 +${run4.foldResult.tools.length - 6} more` : "";
28366
28551
  out2 += row("tools", shown.join(" \xB7 ") + more);
@@ -28369,9 +28554,9 @@ function formatRunEvidence(run4, startedAt) {
28369
28554
  }
28370
28555
  }
28371
28556
  if (run4.foldResult?.tasks?.length) {
28372
- const t = run4.foldResult.tasks;
28373
- const done2 = t.filter((x) => x.status === "completed").length;
28374
- out2 += row("tasks", `${t.length} \xB7 ${done2} completed \xB7 ` + list(t.slice(0, 4).map((x) => `#${x.id} ${x.name} [${x.status}]`), 4));
28557
+ const t2 = run4.foldResult.tasks;
28558
+ const done2 = t2.filter((x) => x.status === "completed").length;
28559
+ out2 += row("tasks", `${t2.length} \xB7 ${done2} completed \xB7 ` + list(t2.slice(0, 4).map((x) => `#${x.id} ${x.name} [${x.status}]`), 4));
28375
28560
  }
28376
28561
  if (run4.specs?.length) {
28377
28562
  const readThisSession = new Set(run4.actionSummary?.files_read ?? []);
@@ -28525,31 +28710,31 @@ function parsePushTarget(segment) {
28525
28710
  let refspec = null;
28526
28711
  let isDelete = false;
28527
28712
  for (let i2 = 0; i2 < tokens.length; i2++) {
28528
- const t = tokens[i2];
28529
- if (t === "-d" || t === "--delete") {
28713
+ const t2 = tokens[i2];
28714
+ if (t2 === "-d" || t2 === "--delete") {
28530
28715
  isDelete = true;
28531
28716
  continue;
28532
28717
  }
28533
- if (t.startsWith("--repo=")) {
28534
- remote = t.slice("--repo=".length);
28718
+ if (t2.startsWith("--repo=")) {
28719
+ remote = t2.slice("--repo=".length);
28535
28720
  continue;
28536
28721
  }
28537
- if (t === "--repo") {
28722
+ if (t2 === "--repo") {
28538
28723
  remote = tokens[++i2] ?? null;
28539
28724
  continue;
28540
28725
  }
28541
- if (PUSH_VALUE_FLAGS.has(t)) {
28726
+ if (PUSH_VALUE_FLAGS.has(t2)) {
28542
28727
  i2++;
28543
28728
  continue;
28544
28729
  }
28545
- if (t.startsWith("-")) continue;
28546
- if (SHELL_DYNAMIC.test(t)) return none;
28730
+ if (t2.startsWith("-")) continue;
28731
+ if (SHELL_DYNAMIC.test(t2)) return none;
28547
28732
  if (remote === null) {
28548
- remote = t;
28733
+ remote = t2;
28549
28734
  continue;
28550
28735
  }
28551
28736
  if (refspec === null) {
28552
- refspec = t;
28737
+ refspec = t2;
28553
28738
  continue;
28554
28739
  }
28555
28740
  break;
@@ -28875,21 +29060,21 @@ function rangeMessages(frame, range) {
28875
29060
  return frameGit(frame, ["show", "-s", "--format=%B%x00", ...commits]).split("\0").map((s) => s.trim()).filter(Boolean).join("\n\n");
28876
29061
  }
28877
29062
  function frameTelemetry(frame, range, divergence) {
28878
- const t = {
29063
+ const t2 = {
28879
29064
  anchor: frame.anchor,
28880
29065
  linked_worktree: frame.isLinkedWorktree,
28881
29066
  range_via: range?.via ?? null,
28882
29067
  refusal: frame.refusal
28883
29068
  };
28884
29069
  if (divergence) {
28885
- t.root_differs = !!frame.worktreeRoot && !!divergence.actualRoot && realpathOr2(frame.worktreeRoot) !== realpathOr2(divergence.actualRoot);
29070
+ t2.root_differs = !!frame.worktreeRoot && !!divergence.actualRoot && realpathOr2(frame.worktreeRoot) !== realpathOr2(divergence.actualRoot);
28886
29071
  const a = [...divergence.actualFiles].sort().join("\n");
28887
29072
  const b = [...divergence.frameFiles].sort().join("\n");
28888
- t.files_differ = a !== b;
28889
- t.frame_file_count = divergence.frameFiles.length;
28890
- t.actual_file_count = divergence.actualFiles.length;
29073
+ t2.files_differ = a !== b;
29074
+ t2.frame_file_count = divergence.frameFiles.length;
29075
+ t2.actual_file_count = divergence.actualFiles.length;
28891
29076
  }
28892
- return t;
29077
+ return t2;
28893
29078
  }
28894
29079
 
28895
29080
  // src/lib/transcript-path.ts
@@ -29388,12 +29573,12 @@ function parseKnowledgeNote(raw) {
29388
29573
  if (!raw || typeof raw !== "object") return null;
29389
29574
  const o = raw;
29390
29575
  const node_id = typeof o.node_id === "string" ? o.node_id.trim() : "";
29391
- const text2 = typeof o.text === "string" ? o.text.trim() : "";
29392
- if (!node_id || !text2) return null;
29393
- if (text2.length > 1e3) return null;
29576
+ const text3 = typeof o.text === "string" ? o.text.trim() : "";
29577
+ if (!node_id || !text3) return null;
29578
+ if (text3.length > 1e3) return null;
29394
29579
  return {
29395
29580
  node_id,
29396
- text: text2,
29581
+ text: text3,
29397
29582
  file: typeof o.file === "string" && o.file ? o.file : null,
29398
29583
  line: typeof o.line === "number" && Number.isFinite(o.line) && o.line > 0 ? Math.floor(o.line) : null
29399
29584
  };
@@ -29441,10 +29626,10 @@ function judgedSeverity(f) {
29441
29626
  var MAX_AGENT_CONTEXT_CHARS = 1500;
29442
29627
  var MAX_AGENT_ITEMS = 5;
29443
29628
  var REPORT_PREFIX = "Verity review (a report on the code just written \u2014 relay what matters to the user; it is not an instruction to you):";
29444
- function renderItem(label2, text2, patternId, file, line2) {
29629
+ function renderItem(label2, text3, patternId, file, line2) {
29445
29630
  const where2 = file ? ` (${file}${line2 !== void 0 && line2 !== "" ? `:${line2}` : ""})` : "";
29446
29631
  const id = patternId ? ` [${patternId}]` : "";
29447
- return `- ${label2}${text2}${where2}${id}`;
29632
+ return `- ${label2}${text3}${where2}${id}`;
29448
29633
  }
29449
29634
  function channelInputFrom(response, intentRepeat = 0, priorPendingFingerprints = []) {
29450
29635
  const metadata2 = response.metadata ?? {};
@@ -29535,24 +29720,24 @@ function composeAgentContext(input) {
29535
29720
  for (const p of input.pendingItems ?? []) {
29536
29721
  if (lines.length >= MAX_AGENT_ITEMS) break;
29537
29722
  if (p.pattern_id === "intent-misalignment") continue;
29538
- const text3 = p.description ?? p.title ?? p.reason;
29539
- if (!text3) continue;
29540
- const seenBefore = isRepeatOfAny(text3, input.priorPendingFingerprints ?? []);
29723
+ const text4 = p.description ?? p.title ?? p.reason;
29724
+ if (!text4) continue;
29725
+ const seenBefore = isRepeatOfAny(text4, input.priorPendingFingerprints ?? []);
29541
29726
  lines.push(
29542
- renderItem("", text3, p.pattern_id, p.file, p.line) + (seenBefore ? "\n (raised earlier this session and still open \u2014 do not re-explain it; act on it or carry on)" : "")
29727
+ renderItem("", text4, p.pattern_id, p.file, p.line) + (seenBefore ? "\n (raised earlier this session and still open \u2014 do not re-explain it; act on it or carry on)" : "")
29543
29728
  );
29544
29729
  }
29545
29730
  if (lines.length === 0) return { text: null, shown: [] };
29546
29731
  const body2 = `${REPORT_PREFIX}
29547
29732
  ${lines.slice(0, MAX_AGENT_ITEMS).join("\n")}`;
29548
- const text2 = truncateToCap(body2);
29549
- return { text: text2, shown: shown.filter((s) => text2.split("\n").includes(s.line)).map((s) => s.finding) };
29733
+ const text3 = truncateToCap(body2);
29734
+ return { text: text3, shown: shown.filter((s) => text3.split("\n").includes(s.line)).map((s) => s.finding) };
29550
29735
  }
29551
- function truncateToCap(text2) {
29552
- if (text2.length <= MAX_AGENT_CONTEXT_CHARS) return text2;
29736
+ function truncateToCap(text3) {
29737
+ if (text3.length <= MAX_AGENT_CONTEXT_CHARS) return text3;
29553
29738
  const marker = "\n- (truncated)";
29554
29739
  const budget = MAX_AGENT_CONTEXT_CHARS - marker.length;
29555
- const lines = text2.slice(0, budget).split("\n");
29740
+ const lines = text3.slice(0, budget).split("\n");
29556
29741
  lines.pop();
29557
29742
  return `${lines.join("\n")}${marker}`;
29558
29743
  }
@@ -30728,9 +30913,9 @@ function fold(transcriptPath, opts = {}) {
30728
30913
  runs: s.runs,
30729
30914
  failed: s.failed,
30730
30915
  last_status: s.last_status,
30731
- targets: [...s.targets].map((t) => toRepoRelative(t, opts.repoRoot)).sort()
30916
+ targets: [...s.targets].map((t2) => toRepoRelative(t2, opts.repoRoot)).sort()
30732
30917
  })).sort((a, b) => b.runs - a.runs || a.name.localeCompare(b.name));
30733
- result.tasks = [...taskById.entries()].map(([id, t]) => ({ id, name: t.name, status: t.status })).sort((a, b) => (Number(a.id) || 0) - (Number(b.id) || 0));
30918
+ result.tasks = [...taskById.entries()].map(([id, t2]) => ({ id, name: t2.name, status: t2.status })).sort((a, b) => (Number(a.id) || 0) - (Number(b.id) || 0));
30734
30919
  const authoredPaths = new Set(result.authored.map((a) => a.p));
30735
30920
  for (const raw of opts.changedFiles ?? []) {
30736
30921
  const p = toRepoRelative(raw, opts.repoRoot);
@@ -31416,8 +31601,8 @@ var cap = (s, n2) => {
31416
31601
  function qualifierOf(node, spec) {
31417
31602
  if (spec.id === "go" && node.type === "method_declaration") {
31418
31603
  const receiver = node.childForFieldName("receiver");
31419
- const t = receiver?.descendantsOfType("type_identifier")[0];
31420
- return t ? t.text : null;
31604
+ const t2 = receiver?.descendantsOfType("type_identifier")[0];
31605
+ return t2 ? t2.text : null;
31421
31606
  }
31422
31607
  for (let p = node.parent; p; p = p.parent) {
31423
31608
  if (spec.classes.has(p.type)) return p.childForFieldName("name")?.text ?? null;
@@ -31572,10 +31757,10 @@ function factsOf(def, spec, defs, path) {
31572
31757
  const walk2 = (n2, ctx) => {
31573
31758
  const anonymousMember = n2.parent?.type === "class_body" && n2.parent.parent?.type === "object_creation_expression";
31574
31759
  if (n2.id !== def.fn.id && !anonymousMember && (defs.has(n2.id) || spec.classes.has(n2.type) || spec.definitions[n2.type])) return;
31575
- const t = n2.type;
31760
+ const t2 = n2.type;
31576
31761
  bind(n2);
31577
31762
  const down = (c, next = ctx) => walk2(c, next);
31578
- if (spec.calls.has(t)) {
31763
+ if (spec.calls.has(t2)) {
31579
31764
  const { receiver, name: name2, args: args2 } = callParts(n2, spec);
31580
31765
  if (name2) {
31581
31766
  calls.push({
@@ -31596,29 +31781,29 @@ function factsOf(def, spec, defs, path) {
31596
31781
  return;
31597
31782
  }
31598
31783
  }
31599
- if (spec.awaits.has(t)) awaits.push(line(n2));
31600
- if (t === "defer_statement") {
31784
+ if (spec.awaits.has(t2)) awaits.push(line(n2));
31785
+ if (t2 === "defer_statement") {
31601
31786
  for (const c of n2.namedChildren) down(c, { ...ctx, within: [...ctx.within, "defer"] });
31602
31787
  return;
31603
31788
  }
31604
- if (spec.lockNodes.has(t)) {
31789
+ if (spec.lockNodes.has(t2)) {
31605
31790
  locks.push(line(n2));
31606
31791
  for (const c of n2.namedChildren) down(c, { ...ctx, within: [...ctx.within, "synchronized"] });
31607
31792
  return;
31608
31793
  }
31609
- if (t === "with_statement") {
31794
+ if (t2 === "with_statement") {
31610
31795
  const item = n2.namedChildren[0];
31611
31796
  if (PY_LOCK_ITEM.test(item?.text ?? "")) locks.push(line(n2));
31612
31797
  const label2 = withLabel(item);
31613
31798
  for (const c of n2.namedChildren) down(c, c.type === "block" && label2 ? { ...ctx, within: [...ctx.within, label2] } : ctx);
31614
31799
  return;
31615
31800
  }
31616
- if (spec.loops.has(t)) {
31801
+ if (spec.loops.has(t2)) {
31617
31802
  loops.push(line(n2));
31618
31803
  for (const c of n2.namedChildren) down(c, { ...ctx, inLoop: true });
31619
31804
  return;
31620
31805
  }
31621
- if (spec.tries.has(t)) {
31806
+ if (spec.tries.has(t2)) {
31622
31807
  const handlers = n2.namedChildren.filter((c) => spec.handlers.has(c.type));
31623
31808
  tries.push({ line: line(n2), end: n2.endPosition.row + 1, catches: handlers.length > 0, rethrows: handlers.some(throwsIn) });
31624
31809
  const body2 = n2.childForFieldName("body");
@@ -31737,9 +31922,9 @@ function literalName(literal) {
31737
31922
  return prefix.length >= 2 ? { name: prefix, confidence: "prefix" } : null;
31738
31923
  }
31739
31924
  var SIMPLE_EXPRESSION = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*(?:\(\))?$/;
31740
- var STABLE_EXPRESSION = (t) => {
31741
- if (t.endsWith("()")) return true;
31742
- const root = t.split(".")[0];
31925
+ var STABLE_EXPRESSION = (t2) => {
31926
+ if (t2.endsWith("()")) return true;
31927
+ const root = t2.split(".")[0];
31743
31928
  return root === "this" || root === "self" || /^[A-Z]/.test(root);
31744
31929
  };
31745
31930
  function argResource(kind2, arg) {
@@ -31752,13 +31937,13 @@ function argResource(kind2, arg) {
31752
31937
  const keyed = keyedCall(arg.text);
31753
31938
  return keyed ? { kind: kind2, name: keyed, confidence: "expression" } : { kind: kind2, name: null, confidence: "unknown" };
31754
31939
  }
31755
- function keyedCall(text2) {
31756
- const t = text2.trim();
31757
- const open = t.indexOf("(");
31758
- if (open <= 0 || !t.endsWith(")")) return null;
31759
- const callee = t.slice(0, open);
31940
+ function keyedCall(text3) {
31941
+ const t2 = text3.trim();
31942
+ const open = t2.indexOf("(");
31943
+ if (open <= 0 || !t2.endsWith(")")) return null;
31944
+ const callee = t2.slice(0, open);
31760
31945
  if (!/^[A-Za-z_$][\w$.]*$/.test(callee)) return null;
31761
- const constant = /\b[A-Z][A-Z0-9_]{2,}\b/.exec(t.slice(open + 1, -1));
31946
+ const constant = /\b[A-Z][A-Z0-9_]{2,}\b/.exec(t2.slice(open + 1, -1));
31762
31947
  return constant ? `${callee}(${constant[0]})` : null;
31763
31948
  }
31764
31949
  function snake(s) {
@@ -31787,16 +31972,16 @@ var SQL_TABLE = [
31787
31972
  [/\bfrom\s+[`"[]?([\w.]+)/i, "read"]
31788
31973
  ];
31789
31974
  function sqlLiteral(c) {
31790
- const text2 = c.args.find((a) => a.literal !== null && SQL.test(a.literal))?.literal;
31791
- if (!text2) return null;
31975
+ const text3 = c.args.find((a) => a.literal !== null && SQL.test(a.literal))?.literal;
31976
+ if (!text3) return null;
31792
31977
  for (const [re, op] of SQL_TABLE) {
31793
- const m = re.exec(text2);
31978
+ const m = re.exec(text3);
31794
31979
  if (m) {
31795
31980
  const name2 = m[1].split(".").pop();
31796
- return { op, resource: table(name2), rule: "sql.literal", lock: op === "read" && /\bfor\s+(?:no\s+key\s+)?update\b/i.test(text2) };
31981
+ return { op, resource: table(name2), rule: "sql.literal", lock: op === "read" && /\bfor\s+(?:no\s+key\s+)?update\b/i.test(text3) };
31797
31982
  }
31798
31983
  }
31799
- return { op: /^\s*select\b/i.test(text2) ? "read" : "write", resource: { kind: "table", name: null, confidence: "unknown" }, rule: "sql.literal" };
31984
+ return { op: /^\s*select\b/i.test(text3) ? "read" : "write", resource: { kind: "table", name: null, confidence: "unknown" }, rule: "sql.literal" };
31800
31985
  }
31801
31986
  var SB_WRITE = /* @__PURE__ */ new Set(["insert", "update", "upsert", "delete"]);
31802
31987
  var SB_FROM = /\bfrom\(\s*(['"`])([\w.-]+)\1\s*\)\s*$/;
@@ -31973,7 +32158,7 @@ function heldAt(fn, line2) {
31973
32158
  }
31974
32159
  function contextOf(c, fn) {
31975
32160
  const recvRoot = (c.receiver ?? "").split(".")[0];
31976
- const tryBlock = c.tryAt === null ? null : fn.tries.find((t) => t.line === c.tryAt) ?? null;
32161
+ const tryBlock = c.tryAt === null ? null : fn.tries.find((t2) => t2.line === c.tryAt) ?? null;
31977
32162
  return {
31978
32163
  txn: c.within.some((w) => TXN.has(w)) || recvRoot === "tx" || recvRoot === "trx",
31979
32164
  // A lock this call runs inside, or a statement lock taken earlier and still held.
@@ -32192,42 +32377,42 @@ var ALIAS_OF = "alias-of:";
32192
32377
  var FIELD_OF = "field-of:";
32193
32378
  var IDENT_CHAR = /[\w$]/;
32194
32379
  var isIdent = (s) => /^[A-Za-z_$][\w$]*$/.test(s);
32195
- function wordAt(text2, word) {
32380
+ function wordAt(text3, word) {
32196
32381
  const out2 = [];
32197
- for (let i2 = text2.indexOf(word); i2 >= 0; i2 = text2.indexOf(word, i2 + 1)) {
32198
- if (IDENT_CHAR.test(text2[i2 - 1] ?? "") || IDENT_CHAR.test(text2[i2 + word.length] ?? "")) continue;
32382
+ for (let i2 = text3.indexOf(word); i2 >= 0; i2 = text3.indexOf(word, i2 + 1)) {
32383
+ if (IDENT_CHAR.test(text3[i2 - 1] ?? "") || IDENT_CHAR.test(text3[i2 + word.length] ?? "")) continue;
32199
32384
  out2.push(i2);
32200
32385
  }
32201
32386
  return out2;
32202
32387
  }
32203
32388
  var GO_NOT_TYPES = /* @__PURE__ */ new Set(["int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64", "complex64", "complex128", "string", "bool", "byte", "rune", "error", "any", "func", "chan", "map", "struct", "interface", "range", "make", "new", "nil", "true", "false"]);
32204
- function typeAt(text2, i2, lang) {
32389
+ function typeAt(text3, i2, lang) {
32205
32390
  let j = i2;
32206
32391
  const skip = () => {
32207
- while (j < text2.length && /[\s?*&]/.test(text2[j])) j++;
32392
+ while (j < text3.length && /[\s?*&]/.test(text3[j])) j++;
32208
32393
  };
32209
32394
  skip();
32210
- for (const kw of ["new ", "readonly ", "await "]) if (text2.startsWith(kw, j)) {
32395
+ for (const kw of ["new ", "readonly ", "await "]) if (text3.startsWith(kw, j)) {
32211
32396
  j += kw.length;
32212
32397
  skip();
32213
32398
  }
32214
32399
  let k = j;
32215
- while (k < text2.length && /[\w$.]/.test(text2[k])) k++;
32216
- const name2 = text2.slice(j, k).split(".").pop() ?? "";
32400
+ while (k < text3.length && /[\w$.]/.test(text3[k])) k++;
32401
+ const name2 = text3.slice(j, k).split(".").pop() ?? "";
32217
32402
  if (lang === "go") return /^[A-Za-z_]\w*$/.test(name2) && !GO_NOT_TYPES.has(name2) ? name2 : null;
32218
32403
  return /^[A-Z][\w$]*$/.test(name2) ? name2 : null;
32219
32404
  }
32220
32405
  function declaredType(scope2, v, lang) {
32221
32406
  for (const i2 of wordAt(scope2, v)) {
32222
32407
  const after = scope2.slice(i2 + v.length);
32223
- const t = after.trimStart();
32224
- if (lang !== "go" && lang !== "java" && t.startsWith(":") && !t.startsWith("::")) {
32408
+ const t2 = after.trimStart();
32409
+ if (lang !== "go" && lang !== "java" && t2.startsWith(":") && !t2.startsWith("::")) {
32225
32410
  const ty = typeAt(after, after.indexOf(":") + 1, lang);
32226
32411
  if (ty) return ty;
32227
32412
  }
32228
- const eq = t.startsWith(":=") ? 2 : t.startsWith("=") && !t.startsWith("==") ? 1 : 0;
32413
+ const eq = t2.startsWith(":=") ? 2 : t2.startsWith("=") && !t2.startsWith("==") ? 1 : 0;
32229
32414
  if (eq) {
32230
- const rhs = t.slice(eq).trimStart();
32415
+ const rhs = t2.slice(eq).trimStart();
32231
32416
  if (lang === "go" && rhs.startsWith("new(")) {
32232
32417
  const ty2 = typeAt(rhs, 4, lang);
32233
32418
  if (ty2) return ty2;
@@ -32338,8 +32523,8 @@ function receiverType(content, lang, caller, receiver, callLine) {
32338
32523
  if (lang === "go" && caller && caller.params.includes(receiver)) {
32339
32524
  const body2 = lines.slice(caller.start.line, callLine).join("\n");
32340
32525
  if (rebindsInGo(body2, receiver)) {
32341
- const t = declaredType(body2, receiver, lang);
32342
- return t && !t.includes(":") ? t : null;
32526
+ const t2 = declaredType(body2, receiver, lang);
32527
+ return t2 && !t2.includes(":") ? t2 : null;
32343
32528
  }
32344
32529
  }
32345
32530
  const goReceiver = lang === "go" && caller && caller.params[0] === receiver && caller.qualified.includes(".");
@@ -32363,10 +32548,10 @@ function boundInGo(fnText, name2) {
32363
32548
  const brace = fnText.indexOf("{");
32364
32549
  return wordAt(brace < 0 ? fnText : fnText.slice(0, brace), name2).length > 0;
32365
32550
  }
32366
- function rebindsInGo(text2, name2) {
32367
- for (const i2 of wordAt(text2, name2)) {
32368
- const lineEnd = text2.indexOf("\n", i2);
32369
- const rest = text2.slice(i2 + name2.length, lineEnd < 0 ? void 0 : lineEnd);
32551
+ function rebindsInGo(text3, name2) {
32552
+ for (const i2 of wordAt(text3, name2)) {
32553
+ const lineEnd = text3.indexOf("\n", i2);
32554
+ const rest = text3.slice(i2 + name2.length, lineEnd < 0 ? void 0 : lineEnd);
32370
32555
  const decl = rest.indexOf(":=");
32371
32556
  if (decl >= 0 && /^[\s\w,]*$/.test(rest.slice(0, decl))) return true;
32372
32557
  }
@@ -32391,15 +32576,15 @@ function localType(content, lang, caller, name2, lines, classes, depth) {
32391
32576
  const fnText = caller ? lines.slice(caller.start.line - 1, caller.end.line).join("\n") : "";
32392
32577
  const local = caller ? declaredType(fnText, name2, lang) : null;
32393
32578
  if (!local && caller && lang === "go" && boundInGo(fnText, name2)) return null;
32394
- const t = local ?? declaredType(lang === "go" ? goPackageVars(content) : content, name2, lang);
32395
- if (!t) return null;
32396
- if (t.startsWith(RESULT_OF)) {
32397
- const [fn, idx] = t.slice(RESULT_OF.length).split("#");
32579
+ const t2 = local ?? declaredType(lang === "go" ? goPackageVars(content) : content, name2, lang);
32580
+ if (!t2) return null;
32581
+ if (t2.startsWith(RESULT_OF)) {
32582
+ const [fn, idx] = t2.slice(RESULT_OF.length).split("#");
32398
32583
  return resultTypeOf(content, fn, lang, Number(idx ?? 0)) ?? `${RESULT_OF}${fn}#${idx ?? 0}`;
32399
32584
  }
32400
- if (t.startsWith(ALIAS_OF)) return localType(content, lang, caller, t.slice(ALIAS_OF.length), lines, classes, depth + 1);
32401
- if (t.startsWith(FIELD_OF)) {
32402
- const [base, field] = t.slice(FIELD_OF.length).split(".");
32585
+ if (t2.startsWith(ALIAS_OF)) return localType(content, lang, caller, t2.slice(ALIAS_OF.length), lines, classes, depth + 1);
32586
+ if (t2.startsWith(FIELD_OF)) {
32587
+ const [base, field] = t2.slice(FIELD_OF.length).split(".");
32403
32588
  const baseType = localType(content, lang, caller, base, lines, classes, depth + 1);
32404
32589
  const cls = baseType ? classes.find((c) => c.name === baseType) : null;
32405
32590
  if (!cls) return null;
@@ -32407,7 +32592,7 @@ function localType(content, lang, caller, name2, lines, classes, depth) {
32407
32592
  const self2 = lang === "python" ? "self" : "this";
32408
32593
  return declaredType(body2, field, lang) ?? declaredType(body2, `${self2}.${field}`, lang);
32409
32594
  }
32410
- return t;
32595
+ return t2;
32411
32596
  }
32412
32597
  function classFiles(type, fromPath, content, lang, source2, resolveImport, importOf2) {
32413
32598
  if (classesIn(content, lang).some((c) => c.name === type)) return [fromPath];
@@ -32592,15 +32777,15 @@ function importOf(content, lang, name2, receiver) {
32592
32777
  return null;
32593
32778
  }
32594
32779
  var TS_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
32595
- function parseJsonc(text2) {
32780
+ function parseJsonc(text3) {
32596
32781
  let out2 = "";
32597
32782
  let inString = false;
32598
- for (let i2 = 0; i2 < text2.length; i2++) {
32599
- const c = text2[i2];
32783
+ for (let i2 = 0; i2 < text3.length; i2++) {
32784
+ const c = text3[i2];
32600
32785
  if (inString) {
32601
32786
  out2 += c;
32602
32787
  if (c === "\\") {
32603
- out2 += text2[++i2] ?? "";
32788
+ out2 += text3[++i2] ?? "";
32604
32789
  continue;
32605
32790
  }
32606
32791
  if (c === '"') inString = false;
@@ -32611,14 +32796,14 @@ function parseJsonc(text2) {
32611
32796
  out2 += c;
32612
32797
  continue;
32613
32798
  }
32614
- if (c === "/" && text2[i2 + 1] === "/") {
32615
- while (i2 < text2.length && text2[i2] !== "\n") i2++;
32799
+ if (c === "/" && text3[i2 + 1] === "/") {
32800
+ while (i2 < text3.length && text3[i2] !== "\n") i2++;
32616
32801
  out2 += "\n";
32617
32802
  continue;
32618
32803
  }
32619
- if (c === "/" && text2[i2 + 1] === "*") {
32804
+ if (c === "/" && text3[i2 + 1] === "*") {
32620
32805
  i2 += 2;
32621
- while (i2 < text2.length && !(text2[i2] === "*" && text2[i2 + 1] === "/")) i2++;
32806
+ while (i2 < text3.length && !(text3[i2] === "*" && text3[i2 + 1] === "/")) i2++;
32622
32807
  i2++;
32623
32808
  continue;
32624
32809
  }
@@ -32659,8 +32844,8 @@ function tsCandidates(spec, fromPath, cfg) {
32659
32844
  const star = pattern.indexOf("*");
32660
32845
  const matched = star < 0 ? spec === pattern ? "" : null : spec.startsWith(pattern.slice(0, star)) && spec.endsWith(pattern.slice(star + 1)) ? spec.slice(star, spec.length - (pattern.length - star - 1)) : null;
32661
32846
  if (matched === null) continue;
32662
- for (const t of targets) {
32663
- const b = joinPath(root ?? "", t.replace("*", matched));
32847
+ for (const t2 of targets) {
32848
+ const b = joinPath(root ?? "", t2.replace("*", matched));
32664
32849
  if (b !== null) bases.push(b);
32665
32850
  }
32666
32851
  }
@@ -32827,36 +33012,36 @@ function definitionOf(input) {
32827
33012
  }
32828
33013
  var MAX_CALLER_SCAN_FILES = 60;
32829
33014
  var isWordChar2 = (c) => c !== void 0 && /[\w$]/.test(c);
32830
- function callStarts(text2, name2) {
33015
+ function callStarts(text3, name2) {
32831
33016
  const out2 = [];
32832
- for (let i2 = text2.indexOf(name2); i2 >= 0; i2 = text2.indexOf(name2, i2 + 1)) {
33017
+ for (let i2 = text3.indexOf(name2); i2 >= 0; i2 = text3.indexOf(name2, i2 + 1)) {
32833
33018
  let j = i2 + name2.length;
32834
- if (text2[j] === "<") {
33019
+ if (text3[j] === "<") {
32835
33020
  let depth = 0;
32836
- for (; j < text2.length; j++) {
32837
- if (text2[j] === "<") depth++;
32838
- else if (text2[j] === ">" && --depth === 0) break;
33021
+ for (; j < text3.length; j++) {
33022
+ if (text3[j] === "<") depth++;
33023
+ else if (text3[j] === ">" && --depth === 0) break;
32839
33024
  }
32840
33025
  j++;
32841
33026
  }
32842
- if (text2[j] === "(") out2.push({ index: i2, open: j });
33027
+ if (text3[j] === "(") out2.push({ index: i2, open: j });
32843
33028
  }
32844
33029
  return out2;
32845
33030
  }
32846
- function callsName(text2, name2) {
32847
- const t = text2.trim();
32848
- if (t.startsWith("//") || t.startsWith("*") || t.startsWith("/*") || t.startsWith("#")) return false;
32849
- for (const at of callStarts(text2, name2)) {
33031
+ function callsName(text3, name2) {
33032
+ const t2 = text3.trim();
33033
+ if (t2.startsWith("//") || t2.startsWith("*") || t2.startsWith("/*") || t2.startsWith("#")) return false;
33034
+ for (const at of callStarts(text3, name2)) {
32850
33035
  const i2 = at.index;
32851
- const spread = text2.slice(Math.max(0, i2 - 3), i2) === "...";
32852
- if (isWordChar2(text2[i2 - 1]) || text2[i2 - 1] === "." && !spread) continue;
33036
+ const spread = text3.slice(Math.max(0, i2 - 3), i2) === "...";
33037
+ if (isWordChar2(text3[i2 - 1]) || text3[i2 - 1] === "." && !spread) continue;
32853
33038
  let depth = 0;
32854
33039
  let j = at.open;
32855
- for (; j < text2.length; j++) {
32856
- if (text2[j] === "(") depth++;
32857
- else if (text2[j] === ")" && --depth === 0) break;
33040
+ for (; j < text3.length; j++) {
33041
+ if (text3[j] === "(") depth++;
33042
+ else if (text3[j] === ")" && --depth === 0) break;
32858
33043
  }
32859
- const after = text2.slice(j + 1).trimStart();
33044
+ const after = text3.slice(j + 1).trimStart();
32860
33045
  if (after.startsWith(":") || after.startsWith("{")) continue;
32861
33046
  return true;
32862
33047
  }
@@ -32946,11 +33131,11 @@ function callersOf(input) {
32946
33131
  if (seen.has(line2) || declared.has(line2)) continue;
32947
33132
  const inside2 = r.value.some((f) => f.start.line <= line2 && line2 <= f.end.line && f.calls.some((c) => c.line === line2 && c.name === name2));
32948
33133
  if (inside2) continue;
32949
- const text2 = lines[line2 - 1] ?? "";
32950
- if (!callsName(text2, name2) || /^\s*(?:export\s+)?(?:async\s+)?(?:function|def|func)\b/.test(text2)) continue;
33134
+ const text3 = lines[line2 - 1] ?? "";
33135
+ if (!callsName(text3, name2) || /^\s*(?:export\s+)?(?:async\s+)?(?:function|def|func)\b/.test(text3)) continue;
32951
33136
  const enclosing = r.value.filter((f) => f.start.line <= line2 && line2 <= f.end.line).sort((a, b) => a.end.line - a.start.line - (b.end.line - b.start.line))[0];
32952
33137
  seen.add(line2);
32953
- callers.push({ path: p, caller: enclosing ? enclosing.qualified : null, line: line2, text: text2.trim().slice(0, 200), provenance: fileTie });
33138
+ callers.push({ path: p, caller: enclosing ? enclosing.qualified : null, line: line2, text: text3.trim().slice(0, 200), provenance: fileTie });
32954
33139
  }
32955
33140
  }
32956
33141
  }
@@ -33257,24 +33442,24 @@ ${m.accessors.map((x) => ` ${x.fn.path}:${x.fn.start.line} ${x.fn.qualified} \u
33257
33442
  return { ok: true, value: lines.join("\n") };
33258
33443
  };
33259
33444
  var KINDS = ["table", "cache", "file", "http", "queue", "service", "memory"];
33260
- function parseResource(text2) {
33261
- const colon = text2.indexOf(":");
33262
- const kind2 = colon > 0 ? text2.slice(0, colon) : "";
33263
- if (KINDS.includes(kind2)) return { kinds: [kind2], name: text2.slice(colon + 1) };
33264
- return { kinds: KINDS, name: text2 };
33445
+ function parseResource(text3) {
33446
+ const colon = text3.indexOf(":");
33447
+ const kind2 = colon > 0 ? text3.slice(0, colon) : "";
33448
+ if (KINDS.includes(kind2)) return { kinds: [kind2], name: text3.slice(colon + 1) };
33449
+ return { kinds: KINDS, name: text3 };
33265
33450
  }
33266
33451
  var writersOfTool = async (ctx, args2) => {
33267
- const text2 = str2(args2.resource, 300, "resource");
33268
- if (!text2.ok) return text2;
33269
- const { kinds, name: name2 } = parseResource(text2.value);
33452
+ const text3 = str2(args2.resource, 300, "resource");
33453
+ if (!text3.ok) return text3;
33454
+ const { kinds, name: name2 } = parseResource(text3.value);
33270
33455
  if (name2.length < 2) return { ok: false, error: "resource name too short to search for" };
33271
33456
  const deadline = Date.now() + TOOL_MS;
33272
33457
  const src = source(ctx);
33273
33458
  const terms = [.../* @__PURE__ */ new Set([name2, ...searchTerms({ kind: "table", name: name2, confidence: "inferred" })])];
33274
33459
  const files = /* @__PURE__ */ new Set();
33275
33460
  let truncated = false;
33276
- for (const t of terms) {
33277
- const found = src.search(t, { maxHits: 300, timeoutMs: Math.max(100, deadline - Date.now()) });
33461
+ for (const t2 of terms) {
33462
+ const found = src.search(t2, { maxHits: 300, timeoutMs: Math.max(100, deadline - Date.now()) });
33278
33463
  if (!found.ok) {
33279
33464
  truncated = true;
33280
33465
  continue;
@@ -33305,7 +33490,7 @@ var writersOfTool = async (ctx, args2) => {
33305
33490
  if (files.size > 25) truncated = true;
33306
33491
  const list2 = (xs) => xs.length ? xs.slice(0, MAX_LIST).map((x) => ` ${x}`).join("\n") + (xs.length > MAX_LIST ? `
33307
33492
  \u2026 ${xs.length - MAX_LIST} more` : "") : " none found";
33308
- return { ok: true, value: `${text2.value} (${where(ctx)}), heuristic${truncated ? ", search cut short" : ""}
33493
+ return { ok: true, value: `${text3.value} (${where(ctx)}), heuristic${truncated ? ", search cut short" : ""}
33309
33494
  writers:
33310
33495
  ${list2(writers)}
33311
33496
  readers:
@@ -33363,9 +33548,9 @@ function validateRepoPath(value, { allowRoot = false } = {}) {
33363
33548
  function lineNumber(value, fallback) {
33364
33549
  return typeof value === "number" && Number.isInteger(value) && value >= 1 ? value : fallback;
33365
33550
  }
33366
- function capOutput(text2) {
33367
- return text2.length > TOOL_LIMITS.outputChars ? `${text2.slice(0, TOOL_LIMITS.outputChars)}
33368
- [truncated at ${TOOL_LIMITS.outputChars} characters]` : text2;
33551
+ function capOutput(text3) {
33552
+ return text3.length > TOOL_LIMITS.outputChars ? `${text3.slice(0, TOOL_LIMITS.outputChars)}
33553
+ [truncated at ${TOOL_LIMITS.outputChars} characters]` : text3;
33369
33554
  }
33370
33555
  function git(ctx, args2, opts = {}) {
33371
33556
  return runGit(ctx.root, args2, { timeoutMs: opts.timeoutMs ?? TOOL_LIMITS.gitTimeoutMs, maxBuffer: opts.maxBuffer ?? TOOL_LIMITS.fileBytes });
@@ -33499,8 +33684,8 @@ var listFilesTool = async (ctx, args2) => {
33499
33684
  \u2026 ${more} more` : ""}` : "no matching files" };
33500
33685
  };
33501
33686
  var searchTool = async (ctx, args2) => {
33502
- const text2 = args2.text;
33503
- if (typeof text2 !== "string" || text2.length === 0 || text2.length > TOOL_LIMITS.textChars || /[\n\r]/.test(text2)) {
33687
+ const text3 = args2.text;
33688
+ if (typeof text3 !== "string" || text3.length === 0 || text3.length > TOOL_LIMITS.textChars || /[\n\r]/.test(text3)) {
33504
33689
  return { ok: false, error: `text must be 1-${TOOL_LIMITS.textChars} characters on one line` };
33505
33690
  }
33506
33691
  const glob = typeof args2.path_glob === "string" && args2.path_glob.length > 0 ? args2.path_glob : null;
@@ -33509,7 +33694,7 @@ var searchTool = async (ctx, args2) => {
33509
33694
  }
33510
33695
  const pathspec = glob ? [`:(glob)${glob}`] : [];
33511
33696
  const revision = ctx.range.kind === "push" ? [ctx.range.head] : ["--cached"];
33512
- const res = await git(ctx, ["grep", "-n", "-I", "-F", "--no-color", ...revision.filter((r) => r === "--cached"), "-e", text2, ...revision.filter((r) => r !== "--cached"), "--", ...pathspec]);
33697
+ const res = await git(ctx, ["grep", "-n", "-I", "-F", "--no-color", ...revision.filter((r) => r === "--cached"), "-e", text3, ...revision.filter((r) => r !== "--cached"), "--", ...pathspec]);
33513
33698
  if (!res.ok) {
33514
33699
  if (res.error === "failed" && res.stderr.trim() === "") return { ok: true, value: "no matches" };
33515
33700
  return { ok: false, error: gitFailure(res, "search") };
@@ -33643,10 +33828,10 @@ function writerExcerpts(codeMap, writers, read2, maxLines, maxChars, budget) {
33643
33828
  if (content === null) continue;
33644
33829
  const win = functionWindow(codeMap, w.file, content, w.line, maxLines);
33645
33830
  if (!win) continue;
33646
- const text2 = content.split("\n").slice(win.start_line - 1, win.end_line).join("\n").slice(0, maxChars);
33647
- if (used2 + text2.length > budget) break;
33648
- used2 += text2.length;
33649
- out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text: text2 });
33831
+ const text3 = content.split("\n").slice(win.start_line - 1, win.end_line).join("\n").slice(0, maxChars);
33832
+ if (used2 + text3.length > budget) break;
33833
+ used2 += text3.length;
33834
+ out2.push({ file: w.file, start_line: win.start_line, symbol: `${w.symbol} (writes ${w.resource}, like ${w.changed})`, kind: "writer", text: text3 });
33650
33835
  }
33651
33836
  return out2;
33652
33837
  }
@@ -33706,7 +33891,7 @@ async function repoContext(run4) {
33706
33891
  var import_promises11 = require("node:fs/promises");
33707
33892
  var import_node_fs53 = require("node:fs");
33708
33893
  var import_node_path42 = require("node:path");
33709
- var import_yaml8 = __toESM2(require_dist());
33894
+ var import_yaml9 = __toESM2(require_dist());
33710
33895
 
33711
33896
  // src/lib/seed.ts
33712
33897
  function extractReadmeIntro(content) {
@@ -34017,7 +34202,7 @@ async function runSeed(opts) {
34017
34202
  let standardDoc;
34018
34203
  try {
34019
34204
  const raw = await (0, import_promises11.readFile)(STANDARD_FILE, "utf-8");
34020
- standardDoc = (0, import_yaml8.parse)(raw);
34205
+ standardDoc = (0, import_yaml9.parse)(raw);
34021
34206
  } catch {
34022
34207
  return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
34023
34208
  }
@@ -35093,7 +35278,7 @@ async function reconcile(run4) {
35093
35278
  const episodeSignals = {
35094
35279
  humanSpoke: (conversation?.prompts?.length ?? 0) > 0,
35095
35280
  rawFail: decision === "FAIL",
35096
- tasksCompleted: (foldResult?.tasks ?? []).filter((t) => t.status === "completed").length,
35281
+ tasksCompleted: (foldResult?.tasks ?? []).filter((t2) => t2.status === "completed").length,
35097
35282
  now: Math.floor(Date.now() / 1e3)
35098
35283
  };
35099
35284
  let episode = resolveEpisode(readAdvisoryEpisode(baselineSessionId), episodeSignals);
@@ -36317,7 +36502,7 @@ var IDENT2 = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$/;
36317
36502
  var SHA256 = /^(sha256:)?[0-9a-f]{64}$/;
36318
36503
  var KINDS2 = /* @__PURE__ */ new Set(["structural", "intent"]);
36319
36504
  var RESULTS = /* @__PURE__ */ new Set(["holds", "counterexample", "exhausted", "proved"]);
36320
- var LIMITS2 = {
36505
+ var LIMITS3 = {
36321
36506
  text: 1e3,
36322
36507
  // desc, source
36323
36508
  state: 4e3,
@@ -36348,22 +36533,22 @@ function strArr(v, maxItems, maxItem) {
36348
36533
  return out2;
36349
36534
  }
36350
36535
  function nat(v) {
36351
- return typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= LIMITS2.int ? v : null;
36536
+ return typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= LIMITS3.int ? v : null;
36352
36537
  }
36353
36538
  function repoPath2(v) {
36354
- const s = str3(v, LIMITS2.path);
36539
+ const s = str3(v, LIMITS3.path);
36355
36540
  if (!s || s.startsWith("/") || /^[A-Za-z]:[\\/]/.test(s)) return null;
36356
36541
  if (s.split(/[\\/]/).some((p) => p === ".." || p === "")) return null;
36357
36542
  return s;
36358
36543
  }
36359
36544
  function parseHeader(obj) {
36360
36545
  const model = ident(obj.model);
36361
- if (!model || !Array.isArray(obj.abstracts) || obj.abstracts.length > LIMITS2.abstracts) return null;
36546
+ if (!model || !Array.isArray(obj.abstracts) || obj.abstracts.length > LIMITS3.abstracts) return null;
36362
36547
  const abstracts = [];
36363
36548
  for (const a of obj.abstracts) {
36364
36549
  if (!isPlainObject2(a)) return null;
36365
36550
  const file = repoPath2(a.file);
36366
- const symbol = str3(a.symbol, LIMITS2.symbol);
36551
+ const symbol = str3(a.symbol, LIMITS3.symbol);
36367
36552
  const sha = a.sha256 === void 0 ? "" : str3(a.sha256, 80);
36368
36553
  if (!file || !symbol || sha === null) return null;
36369
36554
  if (sha !== "" && sha !== "TBD" && !SHA256.test(sha)) return null;
@@ -36385,8 +36570,8 @@ function parseProperty(obj) {
36385
36570
  const id = ident(obj.id);
36386
36571
  const kind2 = typeof obj.kind === "string" && KINDS2.has(obj.kind) ? obj.kind : null;
36387
36572
  const result = typeof obj.result === "string" && RESULTS.has(obj.result) ? obj.result : null;
36388
- const source2 = obj.source === void 0 ? "" : str3(obj.source, LIMITS2.text);
36389
- const desc = obj.desc === void 0 ? "" : str3(obj.desc, LIMITS2.text);
36573
+ const source2 = obj.source === void 0 ? "" : str3(obj.source, LIMITS3.text);
36574
+ const desc = obj.desc === void 0 ? "" : str3(obj.desc, LIMITS3.text);
36390
36575
  if (!model || !id || !kind2 || !result || source2 === null || desc === null) return null;
36391
36576
  const p = { model, id, kind: kind2, source: source2, desc, result };
36392
36577
  if (obj.bound !== void 0) {
@@ -36400,24 +36585,24 @@ function parseProperty(obj) {
36400
36585
  p.states = n2;
36401
36586
  }
36402
36587
  if (obj.trace !== void 0) {
36403
- const t = strArr(obj.trace, LIMITS2.traceItems, LIMITS2.traceItem);
36404
- if (!t) return null;
36405
- p.trace = t;
36588
+ const t2 = strArr(obj.trace, LIMITS3.traceItems, LIMITS3.traceItem);
36589
+ if (!t2) return null;
36590
+ p.trace = t2;
36406
36591
  }
36407
36592
  if (obj.states_along !== void 0) {
36408
- const s = strArr(obj.states_along, LIMITS2.traceItems, LIMITS2.state);
36593
+ const s = strArr(obj.states_along, LIMITS3.traceItems, LIMITS3.state);
36409
36594
  if (!s) return null;
36410
36595
  p.states_along = s;
36411
36596
  }
36412
36597
  if (obj.final !== void 0) {
36413
- const f = str3(obj.final, LIMITS2.state);
36598
+ const f = str3(obj.final, LIMITS3.state);
36414
36599
  if (f === null) return null;
36415
36600
  p.final = f;
36416
36601
  }
36417
36602
  if (obj.theorem !== void 0) {
36418
- const t = str3(obj.theorem, LIMITS2.symbol);
36419
- if (t === null) return null;
36420
- p.theorem = t;
36603
+ const t2 = str3(obj.theorem, LIMITS3.symbol);
36604
+ if (t2 === null) return null;
36605
+ p.theorem = t2;
36421
36606
  }
36422
36607
  return p;
36423
36608
  }
@@ -36696,8 +36881,8 @@ function listModelFiles(root) {
36696
36881
  if (!(0, import_node_fs61.existsSync)(modelsAbs)) return [];
36697
36882
  return (0, import_node_fs61.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path49.join)(modelsAbs, f));
36698
36883
  }
36699
- function trimDiagnostics(text2) {
36700
- return text2.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36884
+ function trimDiagnostics(text3) {
36885
+ return text3.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36701
36886
  }
36702
36887
  function checkModel(tc, root, modelFile, opts = {}) {
36703
36888
  const proofsAbs = (0, import_node_path49.join)(root, PROOFS_DIR);
@@ -37709,9 +37894,9 @@ var HAS_FAILURE = /fail|error|throw|time[sd]?[\s_-]*out|reject|exception|unavail
37709
37894
  var HAS_CRASH = /crash|die|kill|abort|restart/i;
37710
37895
  function missingTrigger(desc, trace) {
37711
37896
  const d = desc.toLowerCase();
37712
- const t = trace.join(" ");
37713
- if (NEEDS_CRASH.test(d) && !HAS_CRASH.test(t)) return "a crash";
37714
- if (NEEDS_FAILURE.test(d) && !HAS_FAILURE.test(t)) return "a failure";
37897
+ const t2 = trace.join(" ");
37898
+ if (NEEDS_CRASH.test(d) && !HAS_CRASH.test(t2)) return "a crash";
37899
+ if (NEEDS_FAILURE.test(d) && !HAS_FAILURE.test(t2)) return "a failure";
37715
37900
  return null;
37716
37901
  }
37717
37902
  function ungroundedMessage(list2) {
@@ -37911,13 +38096,13 @@ var lunaRanker = {
37911
38096
  signal: controller.signal
37912
38097
  });
37913
38098
  if (!res.ok) {
37914
- const text3 = await res.text().catch(() => "");
37915
- return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${text3.slice(0, 200)}`, ranked: fallback };
38099
+ const text4 = await res.text().catch(() => "");
38100
+ return { ok: false, ranker: "luna", error: `OpenAI ${res.status}: ${text4.slice(0, 200)}`, ranked: fallback };
37916
38101
  }
37917
38102
  const data = await res.json();
37918
- const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
37919
- if (!text2) return { ok: false, ranker: "luna", error: "no output_text in response", ranked: fallback };
37920
- const parsed = JSON.parse(text2);
38103
+ const text3 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
38104
+ if (!text3) return { ok: false, ranker: "luna", error: "no output_text in response", ranked: fallback };
38105
+ const parsed = JSON.parse(text3);
37921
38106
  const items = parsed.items.map((i2) => {
37922
38107
  const legacy = i2.critical === void 0 && i2.hazard === void 0 && i2.error_prone === void 0;
37923
38108
  const criteria = legacy ? { critical: Number(i2.score) || 0, hazard: Number(i2.score) || 0, error_prone: Number(i2.score) || 0 } : { critical: Number(i2.critical) || 0, hazard: Number(i2.hazard) || 0, error_prone: Number(i2.error_prone) || 0 };
@@ -38235,42 +38420,42 @@ function lintModelSource(source2) {
38235
38420
  let sawCheck = false;
38236
38421
  for (const raw of code.split("\n")) {
38237
38422
  const line2 = raw.trimEnd();
38238
- const t = line2.trim();
38239
- if (t === "") continue;
38240
- if (/^import\b/.test(t)) {
38241
- if (t !== "import Verity") reasons.push(`only \`import Verity\` is allowed (got \`${t.slice(0, 40)}\`)`);
38423
+ const t2 = line2.trim();
38424
+ if (t2 === "") continue;
38425
+ if (/^import\b/.test(t2)) {
38426
+ if (t2 !== "import Verity") reasons.push(`only \`import Verity\` is allowed (got \`${t2.slice(0, 40)}\`)`);
38242
38427
  sawImport = true;
38243
38428
  continue;
38244
38429
  }
38245
- if (/^open\b/.test(t)) {
38246
- if (t !== "open Verity") reasons.push(`only \`open Verity\` is allowed (got \`${t.slice(0, 40)}\`)`);
38430
+ if (/^open\b/.test(t2)) {
38431
+ if (t2 !== "open Verity") reasons.push(`only \`open Verity\` is allowed (got \`${t2.slice(0, 40)}\`)`);
38247
38432
  continue;
38248
38433
  }
38249
- if (/^namespace\b/.test(t)) {
38250
- if (!/^namespace Models\.[A-Za-z][A-Za-z0-9_]*$/.test(t)) reasons.push(`namespace must be \`Models.<Name>\` (got \`${t.slice(0, 40)}\`)`);
38434
+ if (/^namespace\b/.test(t2)) {
38435
+ if (!/^namespace Models\.[A-Za-z][A-Za-z0-9_]*$/.test(t2)) reasons.push(`namespace must be \`Models.<Name>\` (got \`${t2.slice(0, 40)}\`)`);
38251
38436
  continue;
38252
38437
  }
38253
- if (/^end\b/.test(t)) {
38254
- if (!/^end( Models\.[A-Za-z][A-Za-z0-9_]*)?$/.test(t)) reasons.push(`unexpected \`${t.slice(0, 40)}\``);
38438
+ if (/^end\b/.test(t2)) {
38439
+ if (!/^end( Models\.[A-Za-z][A-Za-z0-9_]*)?$/.test(t2)) reasons.push(`unexpected \`${t2.slice(0, 40)}\``);
38255
38440
  continue;
38256
38441
  }
38257
- if (/^section\b|^mutual\b/.test(t)) {
38258
- reasons.push(`\`${t.split(/\s/)[0]}\` is not allowed in a model`);
38442
+ if (/^section\b|^mutual\b/.test(t2)) {
38443
+ reasons.push(`\`${t2.split(/\s/)[0]}\` is not allowed in a model`);
38259
38444
  continue;
38260
38445
  }
38261
- const hashes = [...t.matchAll(/#/g)];
38446
+ const hashes = [...t2.matchAll(/#/g)];
38262
38447
  for (const h of hashes) {
38263
38448
  const at = h.index ?? 0;
38264
- if (t[at + 1] === "[") continue;
38265
- if (at === 0 && /^#eval\s+Verity\.(model|check|checkData|proved)\b/.test(t)) {
38266
- if (EFFECT_OPERATORS.test(t.slice(5))) reasons.push(`effect operator on an #eval line: \`${t.slice(0, 60)}\``);
38267
- if (/#eval\s+Verity\.model\b/.test(t)) sawModelHeader = true;
38449
+ if (t2[at + 1] === "[") continue;
38450
+ if (at === 0 && /^#eval\s+Verity\.(model|check|checkData|proved)\b/.test(t2)) {
38451
+ if (EFFECT_OPERATORS.test(t2.slice(5))) reasons.push(`effect operator on an #eval line: \`${t2.slice(0, 60)}\``);
38452
+ if (/#eval\s+Verity\.model\b/.test(t2)) sawModelHeader = true;
38268
38453
  else sawCheck = true;
38269
38454
  continue;
38270
38455
  }
38271
- reasons.push(`command not allowed: \`${t.slice(Math.max(0, at - 5), at + 40)}\` (only \`#eval Verity.model|check|checkData|proved\` at line start)`);
38456
+ reasons.push(`command not allowed: \`${t2.slice(Math.max(0, at - 5), at + 40)}\` (only \`#eval Verity.model|check|checkData|proved\` at line start)`);
38272
38457
  }
38273
- if (/^\s/.test(raw) && EFFECT_OPERATORS.test(t) && /\bVerity\./.test(t)) reasons.push(`effect operator near a Verity call: \`${t.slice(0, 60)}\``);
38458
+ if (/^\s/.test(raw) && EFFECT_OPERATORS.test(t2) && /\bVerity\./.test(t2)) reasons.push(`effect operator near a Verity call: \`${t2.slice(0, 60)}\``);
38274
38459
  }
38275
38460
  if (!sawImport) reasons.push("missing `import Verity`");
38276
38461
  if (!sawModelHeader) reasons.push("no `#eval Verity.model` header");
@@ -38288,11 +38473,11 @@ function joinBrokenLiterals(source2) {
38288
38473
  let i2 = 0;
38289
38474
  while (i2 < raw.length) {
38290
38475
  let r = raw[i2];
38291
- let t = tok[i2];
38476
+ let t2 = tok[i2];
38292
38477
  i2++;
38293
38478
  for (; ; ) {
38294
- const d = depth + braceDelta(t);
38295
- const end = t.trimEnd();
38479
+ const d = depth + braceDelta(t2);
38480
+ const end = t2.trimEnd();
38296
38481
  if (!(d > 0 && end.endsWith(",") && i2 < raw.length)) break;
38297
38482
  while (i2 < raw.length && tok[i2].trim() === "") i2++;
38298
38483
  if (i2 >= raw.length) break;
@@ -38301,10 +38486,10 @@ function joinBrokenLiterals(source2) {
38301
38486
  const nextTok = tok[i2];
38302
38487
  const lead = nextTok.length - nextTok.trimStart().length;
38303
38488
  r = r.slice(0, cut) + " " + nextRaw.slice(lead);
38304
- t = t.slice(0, cut) + " " + nextTok.slice(lead);
38489
+ t2 = t2.slice(0, cut) + " " + nextTok.slice(lead);
38305
38490
  i2++;
38306
38491
  }
38307
- depth = Math.max(0, depth + braceDelta(t));
38492
+ depth = Math.max(0, depth + braceDelta(t2));
38308
38493
  outRaw.push(r);
38309
38494
  }
38310
38495
  return outRaw.join("\n");
@@ -38576,19 +38761,19 @@ var PURE_METHODS2 = /* @__PURE__ */ new Set([
38576
38761
  "test",
38577
38762
  "match"
38578
38763
  ]);
38579
- function callsOn(text2, name2) {
38764
+ function callsOn(text3, name2) {
38580
38765
  const needle = `${name2}.`;
38581
- for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
38582
- if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
38583
- const call = CALL_AFTER_DOT.exec(text2.slice(i2 + needle.length));
38766
+ for (let i2 = text3.indexOf(needle); i2 >= 0; i2 = text3.indexOf(needle, i2 + 1)) {
38767
+ if (i2 > 0 && IDENT_CHAR2.test(text3[i2 - 1])) continue;
38768
+ const call = CALL_AFTER_DOT.exec(text3.slice(i2 + needle.length));
38584
38769
  if (call && !PURE_METHODS2.has(call[1])) return true;
38585
38770
  }
38586
38771
  return false;
38587
38772
  }
38588
- function callsDirect(text2, name2) {
38773
+ function callsDirect(text3, name2) {
38589
38774
  const needle = `${name2}(`;
38590
- for (let i2 = text2.indexOf(needle); i2 >= 0; i2 = text2.indexOf(needle, i2 + 1)) {
38591
- if (i2 > 0 && IDENT_CHAR2.test(text2[i2 - 1])) continue;
38775
+ for (let i2 = text3.indexOf(needle); i2 >= 0; i2 = text3.indexOf(needle, i2 + 1)) {
38776
+ if (i2 > 0 && IDENT_CHAR2.test(text3[i2 - 1])) continue;
38592
38777
  return true;
38593
38778
  }
38594
38779
  return false;
@@ -38610,12 +38795,12 @@ function effectSites(numbered2) {
38610
38795
  const out2 = [];
38611
38796
  for (const [i2, r] of rows.entries()) {
38612
38797
  if (i2 === 0) continue;
38613
- const t = r.text.trim();
38614
- if (!t || t.startsWith("//") || t.startsWith("#") || t.startsWith("*")) continue;
38615
- const onParam = [...params].some((p) => callsOn(t, p) || callsDirect(t, p));
38616
- const kind2 = EFFECT_LINE2.test(t) || onParam ? "effect" : CONTROL_LINE.test(t) ? "control" : null;
38798
+ const t2 = r.text.trim();
38799
+ if (!t2 || t2.startsWith("//") || t2.startsWith("#") || t2.startsWith("*")) continue;
38800
+ const onParam = [...params].some((p) => callsOn(t2, p) || callsDirect(t2, p));
38801
+ const kind2 = EFFECT_LINE2.test(t2) || onParam ? "effect" : CONTROL_LINE.test(t2) ? "control" : null;
38617
38802
  if (!kind2) continue;
38618
- out2.push(`L${r.n} [${kind2}] ${t.length > 160 ? t.slice(0, 157) + "\u2026" : t}`);
38803
+ out2.push(`L${r.n} [${kind2}] ${t2.length > 160 ? t2.slice(0, 157) + "\u2026" : t2}`);
38619
38804
  if (out2.length >= MAX_EFFECT_SITES) break;
38620
38805
  }
38621
38806
  return out2;
@@ -38624,7 +38809,7 @@ function starChanged(numbered2, changed) {
38624
38809
  const isChanged = (n2) => !!changed?.some((r) => n2 >= r.from && n2 <= r.to);
38625
38810
  const starred = [];
38626
38811
  let total = 0;
38627
- const text2 = numbered2.split("\n").map((raw) => {
38812
+ const text3 = numbered2.split("\n").map((raw) => {
38628
38813
  const m = NUMBERED_LINE.exec(raw);
38629
38814
  if (!m) return raw;
38630
38815
  total++;
@@ -38640,43 +38825,43 @@ function starChanged(numbered2, changed) {
38640
38825
  runs.push(i2 === j ? `${starred[i2]}` : `${starred[i2]}\u2013${starred[j]}`);
38641
38826
  i2 = j;
38642
38827
  }
38643
- return { text: text2, ranges: runs.join(", "), count: starred.length, total };
38828
+ return { text: text3, ranges: runs.join(", "), count: starred.length, total };
38644
38829
  }
38645
- function renderGenerateInput(t, previous) {
38830
+ function renderGenerateInput(t2, previous) {
38646
38831
  const parts2 = [];
38647
- parts2.push(`# Target: ${t.file} \u2014 \`${t.symbol}\`${t.lines ? ` (lines ${t.lines.from}\u2013${t.lines.to})` : ""}`);
38648
- parts2.push(`Header values: file := "${t.file}", symbol := "${t.symbol}", sha256 := "${t.sha256}", lines := "${t.lines ? `${t.lines.from}-${t.lines.to}` : ""}"`);
38649
- if (t.reasons.length) parts2.push(`Why it was selected: ${t.reasons.join(" \xB7 ")}`);
38650
- if (t.properties.length) parts2.push(`Suggested properties: ${t.properties.join(", ")}`);
38651
- if (t.lens === "security") parts2.push("SECURITY: an attacker outside the trust boundary can drive this code. Follow AN ATTACKER.");
38652
- if (t.hypotheses?.length) parts2.push(`Hypotheses from the selector (questions to try, not verdicts):
38653
- ${t.hypotheses.slice(0, MAX_HYPOTHESES2).map((h) => ` - ${h}`).join("\n")}`);
38654
- const numbered2 = t.numbered.slice(0, MAX_NUMBERED_BYTES);
38832
+ parts2.push(`# Target: ${t2.file} \u2014 \`${t2.symbol}\`${t2.lines ? ` (lines ${t2.lines.from}\u2013${t2.lines.to})` : ""}`);
38833
+ parts2.push(`Header values: file := "${t2.file}", symbol := "${t2.symbol}", sha256 := "${t2.sha256}", lines := "${t2.lines ? `${t2.lines.from}-${t2.lines.to}` : ""}"`);
38834
+ if (t2.reasons.length) parts2.push(`Why it was selected: ${t2.reasons.join(" \xB7 ")}`);
38835
+ if (t2.properties.length) parts2.push(`Suggested properties: ${t2.properties.join(", ")}`);
38836
+ if (t2.lens === "security") parts2.push("SECURITY: an attacker outside the trust boundary can drive this code. Follow AN ATTACKER.");
38837
+ if (t2.hypotheses?.length) parts2.push(`Hypotheses from the selector (questions to try, not verdicts):
38838
+ ${t2.hypotheses.slice(0, MAX_HYPOTHESES2).map((h) => ` - ${h}`).join("\n")}`);
38839
+ const numbered2 = t2.numbered.slice(0, MAX_NUMBERED_BYTES);
38655
38840
  const sites = effectSites(numbered2);
38656
- const push = starChanged(numbered2, t.changed);
38841
+ const push = starChanged(numbered2, t2.changed);
38657
38842
  if (push.count > 0) parts2.push(`A push: it changed ${push.count} of these ${push.total} lines (${push.ranges}), marked \`*|\` below. Look first for a bug the change introduced.`);
38658
38843
  parts2.push("", sites.length ? `Effect sites (STEP 1 \u2014 where the real world can interleave, fail or crash):
38659
38844
  ${sites.map((s) => ` ${s}`).join("\n")}` : "Effect sites: none \u2014 a pure computation (STEP 3: Verity.checkData on concrete inputs).");
38660
38845
  parts2.push("", "```", push.count > 0 ? push.text : numbered2, "```");
38661
- if (t.effects?.length) {
38846
+ if (t2.effects?.length) {
38662
38847
  parts2.push("", `State this function touches (from the parser; "via" names the helper that does it):
38663
- ${t.effects.slice(0, MAX_CONTEXT_EFFECTS).map((e) => ` ${e}`).join("\n")}`);
38848
+ ${t2.effects.slice(0, MAX_CONTEXT_EFFECTS).map((e) => ` ${e}`).join("\n")}`);
38664
38849
  }
38665
- if (t.coAccessors?.length) {
38850
+ if (t2.coAccessors?.length) {
38666
38851
  parts2.push("", "# Other functions that touch the same state (STEP 2 \u2014 the second actor)");
38667
- for (const c of t.coAccessors.slice(0, MAX_CO_ACCESSORS)) {
38852
+ for (const c of t2.coAccessors.slice(0, MAX_CO_ACCESSORS)) {
38668
38853
  parts2.push("", `## ${c.file} \u2014 \`${c.symbol}\` (lines ${c.lines.from}\u2013${c.lines.to})`, `Header values: file := "${c.file}", symbol := "${c.symbol}", sha256 := "${c.sha256}", lines := "${c.lines.from}-${c.lines.to}"`);
38669
38854
  if (c.touches.length) parts2.push(`It touches: ${c.touches.slice(0, MAX_CONTEXT_EFFECTS).join(" \xB7 ")}`);
38670
38855
  parts2.push("```", c.numbered, "```");
38671
38856
  }
38672
38857
  }
38673
- if (t.helpers?.length) {
38858
+ if (t2.helpers?.length) {
38674
38859
  parts2.push("", "# Helpers it calls (their effects happen at the line that calls them)");
38675
- for (const h of t.helpers.slice(0, MAX_HELPERS2)) parts2.push("", `## ${h.file} \u2014 \`${h.symbol}\` (lines ${h.lines.from}\u2013${h.lines.to})`, "```", h.numbered, "```");
38860
+ for (const h of t2.helpers.slice(0, MAX_HELPERS2)) parts2.push("", `## ${h.file} \u2014 \`${h.symbol}\` (lines ${h.lines.from}\u2013${h.lines.to})`, "```", h.numbered, "```");
38676
38861
  }
38677
- if (t.callers?.length) {
38862
+ if (t2.callers?.length) {
38678
38863
  parts2.push("", "# Where it is called (a caller's guard bounds the inputs it can get)");
38679
- for (const c of t.callers.slice(0, MAX_CALLERS2)) parts2.push("", `## ${c.file}:${c.line}${c.caller ? ` \u2014 in \`${c.caller}\`` : ""}`, "```", c.numbered, "```");
38864
+ for (const c of t2.callers.slice(0, MAX_CALLERS2)) parts2.push("", `## ${c.file}:${c.line}${c.caller ? ` \u2014 in \`${c.caller}\`` : ""}`, "```", c.numbered, "```");
38680
38865
  }
38681
38866
  if (previous) {
38682
38867
  parts2.push("", "# Your previous attempt was not accepted \u2014 the diagnostics say why. Fix it (same model, same properties):", "```lean", previous.source.slice(0, 32 * 1024), "```", "Diagnostics:", "```", previous.error.slice(0, 4e3), "```");
@@ -38771,11 +38956,11 @@ async function generateModel(target, opts) {
38771
38956
  return { ok: false, error: name2 === "TimeoutError" || name2 === "AbortError" ? "timed out" : err2.message };
38772
38957
  }
38773
38958
  const usage = data.usage ? { inputTokens: Number(data.usage.input_tokens ?? 0), outputTokens: Number(data.usage.output_tokens ?? 0) } : null;
38774
- const text2 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
38775
- if (!text2) return { ok: false, error: "no output_text in response", usage };
38959
+ const text3 = (data.output ?? []).flatMap((o) => o.content ?? []).find((c) => c.type === "output_text")?.text;
38960
+ if (!text3) return { ok: false, error: "no output_text in response", usage };
38776
38961
  let parsed;
38777
38962
  try {
38778
- parsed = JSON.parse(text2);
38963
+ parsed = JSON.parse(text3);
38779
38964
  } catch {
38780
38965
  return { ok: false, error: "answer was not JSON", usage };
38781
38966
  }
@@ -38785,8 +38970,8 @@ async function generateModel(target, opts) {
38785
38970
  // src/lib/prove/replay.ts
38786
38971
  var MAX_SOURCE_BYTES = 96 * 1024;
38787
38972
  var MAX_MODEL_BYTES = 32 * 1024;
38788
- function numberLines(text2, from = 1) {
38789
- return text2.split("\n").map((l, i2) => `${String(i2 + from).padStart(5)}| ${l}`).join("\n");
38973
+ function numberLines(text3, from = 1) {
38974
+ return text3.split("\n").map((l, i2) => `${String(i2 + from).padStart(5)}| ${l}`).join("\n");
38790
38975
  }
38791
38976
  var PY_DECL = /^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(/;
38792
38977
  var TS_DECLS = [
@@ -38803,8 +38988,8 @@ function copiedLines(brief) {
38803
38988
  const out2 = /* @__PURE__ */ new Set();
38804
38989
  for (const src of brief.sources) {
38805
38990
  for (const l of (src.content ?? "").split("\n")) {
38806
- const t = l.trim();
38807
- if (t) out2.add(t);
38991
+ const t2 = l.trim();
38992
+ if (t2) out2.add(t2);
38808
38993
  }
38809
38994
  }
38810
38995
  return out2;
@@ -38812,8 +38997,8 @@ function copiedLines(brief) {
38812
38997
  function harnessInvokes(texts, symbol, py, copied = /* @__PURE__ */ new Set()) {
38813
38998
  if (!/^[A-Za-z_$][\w$]*$/.test(symbol)) return null;
38814
38999
  let declared = false;
38815
- for (const t of texts) {
38816
- for (const line2 of t.split("\n")) {
39000
+ for (const t2 of texts) {
39001
+ for (const line2 of t2.split("\n")) {
38817
39002
  if (declaresSymbol(line2, symbol, py)) {
38818
39003
  declared = true;
38819
39004
  continue;
@@ -38860,9 +39045,9 @@ function extractSymbolBody(source2, symbol, file, range) {
38860
39045
  }
38861
39046
  return null;
38862
39047
  }
38863
- function significantLines(text2) {
39048
+ function significantLines(text3) {
38864
39049
  const out2 = [];
38865
- for (const raw of text2.split("\n")) {
39050
+ for (const raw of text3.split("\n")) {
38866
39051
  const l = raw.trim();
38867
39052
  if (l.length < 12) continue;
38868
39053
  if (/^(\/\/|\/\*|\*|#)/.test(l)) continue;
@@ -38875,7 +39060,7 @@ function verbatimCoverage(symbolBody, texts) {
38875
39060
  const wanted = significantLines(symbolBody);
38876
39061
  if (wanted.length === 0) return { covered: 0, total: 0, ratio: 0 };
38877
39062
  const have = /* @__PURE__ */ new Set();
38878
- for (const t of texts) for (const l of t.split("\n")) have.add(l.trim());
39063
+ for (const t2 of texts) for (const l of t2.split("\n")) have.add(l.trim());
38879
39064
  const covered = wanted.filter((l) => have.has(l)).length;
38880
39065
  return { covered, total: wanted.length, ratio: covered / wanted.length };
38881
39066
  }
@@ -38887,14 +39072,14 @@ function isTrackedInRoot(root, file) {
38887
39072
  function buildReplayBrief(root, report, property, modelSource, readSource) {
38888
39073
  const sources = (report.header?.abstracts ?? []).map((a) => {
38889
39074
  const read2 = readSource ? readSource(a.file, MAX_SOURCE_BYTES) : isTrackedInRoot(root, a.file) ? readRegularFileInRoot(root, a.file, MAX_SOURCE_BYTES) : { ok: false, reason: "not tracked by git \u2014 models may only abstract tracked source" };
38890
- const text2 = read2.ok ? read2.content : "";
39075
+ const text3 = read2.ok ? read2.content : "";
38891
39076
  return {
38892
39077
  file: a.file,
38893
39078
  symbol: a.symbol,
38894
- numbered: text2 ? numberLines(text2) : `(could not read ${a.file}: ${read2.ok ? "" : read2.reason})`,
38895
- symbolBody: text2 ? extractSymbolBody(text2, a.symbol, a.file, a.lines) : null,
39079
+ numbered: text3 ? numberLines(text3) : `(could not read ${a.file}: ${read2.ok ? "" : read2.reason})`,
39080
+ symbolBody: text3 ? extractSymbolBody(text3, a.symbol, a.file, a.lines) : null,
38896
39081
  lines: a.lines,
38897
- content: text2
39082
+ content: text3
38898
39083
  };
38899
39084
  });
38900
39085
  return { model: report.model, property, modelSource: modelSource.slice(0, MAX_MODEL_BYTES), sources };
@@ -38976,7 +39161,7 @@ function parseReplayOutput(output) {
38976
39161
  let executedCalls = 0;
38977
39162
  const shellTexts = [];
38978
39163
  const outputTexts = [];
38979
- let text2 = null;
39164
+ let text3 = null;
38980
39165
  for (const item of output) {
38981
39166
  if (item.type === "shell_call") {
38982
39167
  shellCalls++;
@@ -38991,14 +39176,14 @@ function parseReplayOutput(output) {
38991
39176
  if (typeof o.stderr === "string" && o.stderr) outputTexts.push(o.stderr);
38992
39177
  }
38993
39178
  } else if (item.type === "message" && Array.isArray(item.content)) {
38994
- const t = item.content.find((c) => c.type === "output_text")?.text;
38995
- if (typeof t === "string") text2 = t;
39179
+ const t2 = item.content.find((c) => c.type === "output_text")?.text;
39180
+ if (typeof t2 === "string") text3 = t2;
38996
39181
  }
38997
39182
  }
38998
39183
  let claim = null;
38999
- if (text2) {
39184
+ if (text3) {
39000
39185
  try {
39001
- const o = JSON.parse(text2);
39186
+ const o = JSON.parse(text3);
39002
39187
  const verdict = o.verdict;
39003
39188
  if (verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable") {
39004
39189
  claim = {
@@ -39016,7 +39201,7 @@ function parseReplayOutput(output) {
39016
39201
  var RESULT_LINE = /REPLAY_RESULT=(reproduced|diverged)\b/g;
39017
39202
  function printedResult(outputTexts) {
39018
39203
  let last = null;
39019
- for (const t of outputTexts) for (const m of t.matchAll(RESULT_LINE)) last = m[1];
39204
+ for (const t2 of outputTexts) for (const m of t2.matchAll(RESULT_LINE)) last = m[1];
39020
39205
  return last;
39021
39206
  }
39022
39207
  var RESULT_MISSING = "the harness never printed REPLAY_RESULT=reproduced on its own stdout \u2014 the verdict was the model's word, not the run's";
@@ -39057,7 +39242,7 @@ function judgeReplay(brief, parsed) {
39057
39242
  return { claimed, verdict: "unverified", reason: parsed.claim.reason, downgrade: RESULT_MISSING, verbatim };
39058
39243
  }
39059
39244
  const copied = copiedLines(brief);
39060
- if (claimed === "reproduced" && !texts.some((t) => t.split("\n").some((l) => !copied.has(l.trim()) && l.includes("diverged")))) {
39245
+ if (claimed === "reproduced" && !texts.some((t2) => t2.split("\n").some((l) => !copied.has(l.trim()) && l.includes("diverged")))) {
39061
39246
  return { claimed, verdict: "unverified", reason: parsed.claim.reason, downgrade: FIXED_VERDICT, verbatim };
39062
39247
  }
39063
39248
  if (claimed === "reproduced" && primary && harnessInvokes(texts, primary.symbol, /\.py$/.test(primary.file), copied) === false) {
@@ -39418,10 +39603,10 @@ function semanticFingerprint(numbered2) {
39418
39603
  const kept = [];
39419
39604
  for (const raw of numbered2.split("\n")) {
39420
39605
  const line2 = raw.replace(/^\s*\d+\| ?/, "");
39421
- const t = line2.trim();
39422
- if (!t || t.startsWith("//") || t.startsWith("#") || t.startsWith("*") || t.startsWith("/*")) continue;
39423
- if (LOG_LINE.test(t)) continue;
39424
- kept.push(t.replace(/\s+/g, " "));
39606
+ const t2 = line2.trim();
39607
+ if (!t2 || t2.startsWith("//") || t2.startsWith("#") || t2.startsWith("*") || t2.startsWith("/*")) continue;
39608
+ if (LOG_LINE.test(t2)) continue;
39609
+ kept.push(t2.replace(/\s+/g, " "));
39425
39610
  }
39426
39611
  return (0, import_node_crypto19.createHash)("sha256").update(kept.join("\n")).digest("hex");
39427
39612
  }
@@ -40311,7 +40496,7 @@ var MAX_TURNS2 = 14;
40311
40496
  var VERDICTS = ["REAL", "REAL-LOW", "PREVENTED", "ARTIFACT", "UNSURE"];
40312
40497
  var verdictOf = (v) => typeof v === "string" && VERDICTS.includes(v) ? v : null;
40313
40498
  var introducedOf = (v) => v === "yes" || v === "no" ? v : "unknown";
40314
- var text = (v, n2) => typeof v === "string" ? v.slice(0, n2) : "";
40499
+ var text2 = (v, n2) => typeof v === "string" ? v.slice(0, n2) : "";
40315
40500
  function verifyPost(auth3) {
40316
40501
  return async (body2, timeoutMs) => {
40317
40502
  const res = await apiRequest({
@@ -40367,8 +40552,8 @@ async function verifyFinding(input, opts) {
40367
40552
  const res = await opts.post({ ...body2, remaining_ms: remaining() }, Math.max(1, remaining()));
40368
40553
  if (!res.ok) return end("failed", { error: res.error.slice(0, 200) });
40369
40554
  const d = res.data;
40370
- if (d.enabled === false) return end("disabled", { error: text(d.reason, 60) });
40371
- if (d.error && typeof d.error === "object") return end("failed", { error: text(d.error.code, 60) || "SERVICE_ERROR" });
40555
+ if (d.enabled === false) return end("disabled", { error: text2(d.reason, 60) });
40556
+ if (d.error && typeof d.error === "object") return end("failed", { error: text2(d.error.code, 60) || "SERVICE_ERROR" });
40372
40557
  rounds = typeof d.round === "number" && Number.isInteger(d.round) && d.round >= 0 ? d.round : rounds + 1;
40373
40558
  if (typeof d.cost_usd === "number") {
40374
40559
  if (!Number.isFinite(d.cost_usd) || d.cost_usd < 0) return end("failed", { error: "invalid cost" });
@@ -40376,17 +40561,17 @@ async function verifyFinding(input, opts) {
40376
40561
  } else unpriced++;
40377
40562
  if (d.done) {
40378
40563
  const a = d.answer;
40379
- if (!a) return end("failed", { error: text(d.error, 60) || "no verdict" });
40564
+ if (!a) return end("failed", { error: text2(d.error, 60) || "no verdict" });
40380
40565
  const verdict = verdictOf(a.verdict);
40381
40566
  if (!verdict) return end("failed", { error: "unknown verdict" });
40382
40567
  return end("answered", {
40383
40568
  verdict,
40384
40569
  claimed: verdictOf(a.claimed),
40385
40570
  introduced: introducedOf(a.introduced),
40386
- trigger: text(a.trigger, 400),
40571
+ trigger: text2(a.trigger, 400),
40387
40572
  preventedBy: typeof a.prevented_by === "string" ? a.prevented_by.slice(0, 600) : null,
40388
- effect: text(a.effect, 600),
40389
- reason: text(a.reason, 2e3),
40573
+ effect: text2(a.effect, 600),
40574
+ reason: text2(a.reason, 2e3),
40390
40575
  quotes: (Array.isArray(a.quotes) ? a.quotes : []).slice(0, 12).flatMap((q) => {
40391
40576
  const o = q ?? {};
40392
40577
  return typeof o.path === "string" && typeof o.text === "string" ? [{ path: o.path.slice(0, 400), text: o.text.slice(0, 600), witnessed: o.witnessed === true }] : [];
@@ -40668,17 +40853,17 @@ function parsePrIntent(command) {
40668
40853
  }
40669
40854
  var TRIVIAL_INTENT = /^(wip|tmp|temp|test|fix|chore|amend|\.+|fixup!.*|squash!.*|merge\b.*)$/i;
40670
40855
  var SHELL_PLUMBING = /\$\(|`|<<-?\s*['"]?[A-Za-z_]/;
40671
- function isSubstantiveIntent(text2) {
40672
- if (!text2) return false;
40673
- const t = text2.trim();
40674
- if (t.length < 12) return false;
40675
- if (TRIVIAL_INTENT.test(t)) return false;
40676
- if (SHELL_PLUMBING.test(t)) return false;
40856
+ function isSubstantiveIntent(text3) {
40857
+ if (!text3) return false;
40858
+ const t2 = text3.trim();
40859
+ if (t2.length < 12) return false;
40860
+ if (TRIVIAL_INTENT.test(t2)) return false;
40861
+ if (SHELL_PLUMBING.test(t2)) return false;
40677
40862
  return true;
40678
40863
  }
40679
40864
  function extractStatedIntent(moment, command, pushedMessages = null) {
40680
- const text2 = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
40681
- return isSubstantiveIntent(text2) ? text2 : null;
40865
+ const text3 = moment === "pre-commit" ? parseCommitMessage(command) : parsePrIntent(command) ?? pushedMessages;
40866
+ return isSubstantiveIntent(text3) ? text3 : null;
40682
40867
  }
40683
40868
  function hasBlockingFinding(response, sentFiles) {
40684
40869
  return ofThisChange(response, sentFiles).some((f) => SERIOUS.has(String(f.severity ?? "").toLowerCase()));
@@ -41101,7 +41286,7 @@ async function runGuard(opts, globals) {
41101
41286
  properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
41102
41287
  findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
41103
41288
  // Review effort "max" models more than one function: each one, and why the search stopped early.
41104
- targets: (formalOutcome.targets ?? []).map((t) => `${t.file}#${t.symbol}:${t.status}${t.skip ? `(${t.skip})` : ""}`),
41289
+ targets: (formalOutcome.targets ?? []).map((t2) => `${t2.file}#${t2.symbol}:${t2.status}${t2.skip ? `(${t2.skip})` : ""}`),
41105
41290
  stopped_at: formalOutcome.stoppedAt?.skip ?? null,
41106
41291
  // Decision 81: what each property rests on (a rule, or "line"), what was
41107
41292
  // sent back or dropped as ungrounded, and which counterexamples lack their
@@ -41604,10 +41789,10 @@ var utcDay2 = (d) => d.toISOString().slice(0, 10);
41604
41789
  var DAY_MS2 = 864e5;
41605
41790
  function plausibleDay(day, now) {
41606
41791
  if (!DAY.test(day)) return false;
41607
- const t = Date.parse(`${day}T00:00:00Z`);
41608
- if (Number.isNaN(t) || new Date(t).toISOString().slice(0, 10) !== day) return false;
41792
+ const t2 = Date.parse(`${day}T00:00:00Z`);
41793
+ if (Number.isNaN(t2) || new Date(t2).toISOString().slice(0, 10) !== day) return false;
41609
41794
  const today2 = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
41610
- return t >= today2 - MAX_RUN_AGE_DAYS * DAY_MS2 && t <= today2 + DAY_MS2;
41795
+ return t2 >= today2 - MAX_RUN_AGE_DAYS * DAY_MS2 && t2 <= today2 + DAY_MS2;
41611
41796
  }
41612
41797
  function readPending(now) {
41613
41798
  try {
@@ -41761,21 +41946,21 @@ var PALETTE = {
41761
41946
  glow: [220, 255, 240],
41762
41947
  text: [235, 238, 240]
41763
41948
  };
41764
- function styles(t) {
41765
- const fg = (c, basic) => !t.color ? "" : t.truecolor ? `\x1B[38;2;${c.join(";")}m` : basic;
41949
+ function styles(t2) {
41950
+ const fg = (c, basic) => !t2.color ? "" : t2.truecolor ? `\x1B[38;2;${c.join(";")}m` : basic;
41766
41951
  return {
41767
- reset: t.color ? "\x1B[0m" : "",
41768
- bold: t.color ? "\x1B[1m" : "",
41952
+ reset: t2.color ? "\x1B[0m" : "",
41953
+ bold: t2.color ? "\x1B[1m" : "",
41769
41954
  green: fg(PALETTE.green, "\x1B[32m"),
41770
41955
  teal: fg(PALETTE.teal, "\x1B[36m"),
41771
41956
  gray: fg(PALETTE.gray, "\x1B[90m"),
41772
41957
  faint: fg(PALETTE.faint, "\x1B[90m"),
41773
- yellow: t.color ? "\x1B[33m" : "",
41774
- rgb: (c) => t.truecolor ? `\x1B[38;2;${c.join(";")}m` : ""
41958
+ yellow: t2.color ? "\x1B[33m" : "",
41959
+ rgb: (c) => t2.truecolor ? `\x1B[38;2;${c.join(";")}m` : ""
41775
41960
  };
41776
41961
  }
41777
- var mix = (a, b, t) => [0, 1, 2].map((i2) => Math.round(a[i2] + (b[i2] - a[i2]) * t));
41778
- var ease = (t) => 1 - Math.pow(1 - t, 3);
41962
+ var mix = (a, b, t2) => [0, 1, 2].map((i2) => Math.round(a[i2] + (b[i2] - a[i2]) * t2));
41963
+ var ease = (t2) => 1 - Math.pow(1 - t2, 3);
41779
41964
  var ANSI = /\x1b\[[0-9;?]*[A-Za-z]/g;
41780
41965
  function visibleWidth(s) {
41781
41966
  return [...s.replace(ANSI, "")].length;
@@ -41796,8 +41981,8 @@ function fitLine(s, width) {
41796
41981
  }
41797
41982
  return out2 + "\u2026" + (s.includes("\x1B[") ? "\x1B[0m" : "");
41798
41983
  }
41799
- function wrapText(text2, width, hang = "") {
41800
- const words = text2.split(/\s+/).filter(Boolean);
41984
+ function wrapText(text3, width, hang = "") {
41985
+ const words = text3.split(/\s+/).filter(Boolean);
41801
41986
  if (words.length === 0) return [""];
41802
41987
  const indent = visibleWidth(hang) < width - 1 ? hang : "";
41803
41988
  const lines = [];
@@ -41854,12 +42039,12 @@ var Screen = class {
41854
42039
  this.term = term;
41855
42040
  this.s = styles(term);
41856
42041
  }
41857
- write(text2) {
41858
- this.term.out.write(text2);
42042
+ write(text3) {
42043
+ this.term.out.write(text3);
41859
42044
  }
41860
42045
  /** One frame: one write, inside a synchronized update when motion is on. */
41861
- frame(text2) {
41862
- this.write(this.term.motion ? SYNC_ON + text2 + SYNC_OFF : text2);
42046
+ frame(text3) {
42047
+ this.write(this.term.motion ? SYNC_ON + text3 + SYNC_OFF : text3);
41863
42048
  }
41864
42049
  hideCursor() {
41865
42050
  if (!this.term.screen || this.hidden) return;
@@ -41976,8 +42161,8 @@ var Screen = class {
41976
42161
  this.hideCursor();
41977
42162
  const start2 = Date.now();
41978
42163
  const draw = () => {
41979
- const t = (Math.sin((Date.now() - start2) / 1400 * Math.PI * 2 - Math.PI / 2) + 1) / 2;
41980
- const dot = this.term.truecolor ? `${this.s.rgb(mix(PALETTE.faint, PALETTE.green, t))}\u25CF${this.s.reset}` : `${t > 0.5 ? this.s.green : this.s.faint}\u25CF${this.s.reset}`;
42164
+ const t2 = (Math.sin((Date.now() - start2) / 1400 * Math.PI * 2 - Math.PI / 2) + 1) / 2;
42165
+ const dot = this.term.truecolor ? `${this.s.rgb(mix(PALETTE.faint, PALETTE.green, t2))}\u25CF${this.s.reset}` : `${t2 > 0.5 ? this.s.green : this.s.faint}\u25CF${this.s.reset}`;
41981
42166
  const line2 = `${prefix}${dot} ${label2()} ${this.s.gray}${clock(start2)}${this.s.reset}`;
41982
42167
  this.frame(CLEAR_LINE + fitLine(line2, this.term.columns() - 1));
41983
42168
  };
@@ -42001,9 +42186,9 @@ var Screen = class {
42001
42186
  this.hideCursor();
42002
42187
  const start2 = Date.now();
42003
42188
  for (; ; ) {
42004
- const t = Math.min(1, (Date.now() - start2) / ms);
42005
- this.frame(CLEAR_LINE + fitLine(prefix + render2(targets.map((n2) => Math.round(n2 * ease(t)))), width));
42006
- if (t >= 1) break;
42189
+ const t2 = Math.min(1, (Date.now() - start2) / ms);
42190
+ this.frame(CLEAR_LINE + fitLine(prefix + render2(targets.map((n2) => Math.round(n2 * ease(t2)))), width));
42191
+ if (t2 >= 1) break;
42007
42192
  await sleep2(30);
42008
42193
  }
42009
42194
  this.write("\n");
@@ -42014,17 +42199,17 @@ var sleep2 = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
42014
42199
 
42015
42200
  // src/lib/ui/rail-motion.ts
42016
42201
  async function drawLanguages(rail, input) {
42017
- const t = rail.screen.term;
42202
+ const t2 = rail.screen.term;
42018
42203
  const s = rail.screen.s;
42019
42204
  const langs = input.map((l) => ({ name: terminalText(l.name, 40), pct: l.pct }));
42020
- if (!t.screen || langs.length === 0) {
42205
+ if (!t2.screen || langs.length === 0) {
42021
42206
  if (langs.length) rail.line(langs.map((l) => `${l.name} ${l.pct}%`).join(", "));
42022
42207
  return;
42023
42208
  }
42024
- const width = Math.max(10, Math.min(44, t.columns() - 8));
42209
+ const width = Math.max(10, Math.min(44, t2.columns() - 8));
42025
42210
  const tones = [s.green, s.teal, s.gray];
42026
42211
  const bar = (shown) => {
42027
- const track = t.color ? `${s.faint}\u2501` : "\u2500";
42212
+ const track = t2.color ? `${s.faint}\u2501` : "\u2500";
42028
42213
  let out2 = "";
42029
42214
  let cell = 0;
42030
42215
  langs.forEach((l, i2) => {
@@ -42035,7 +42220,7 @@ async function drawLanguages(rail, input) {
42035
42220
  return out2 + s.reset;
42036
42221
  };
42037
42222
  const prefix = `${s.gray}\u2502${s.reset} `;
42038
- if (t.motion) {
42223
+ if (t2.motion) {
42039
42224
  rail.screen.hideCursor();
42040
42225
  const start2 = Date.now();
42041
42226
  for (; ; ) {
@@ -42053,7 +42238,7 @@ async function drawLanguages(rail, input) {
42053
42238
  rail.emitLine(prefix + langs.map((l, i2) => `${tones[Math.min(i2, 2)]}\u25CF${s.reset} ${l.name} ${s.gray}${l.pct}%${s.reset}`).join(" "));
42054
42239
  }
42055
42240
  async function drawRules(rail, input) {
42056
- const t = rail.screen.term;
42241
+ const t2 = rail.screen.term;
42057
42242
  const s = rail.screen.s;
42058
42243
  const w = rail.lineWidth();
42059
42244
  const rules = input.map((r) => ({
@@ -42063,7 +42248,7 @@ async function drawRules(rail, input) {
42063
42248
  basis: terminalText(r.basis, 300)
42064
42249
  }));
42065
42250
  for (const r of rules) {
42066
- if (!t.screen) {
42251
+ if (!t2.screen) {
42067
42252
  rail.emitLine(` - ${r.id}: ${r.description}`);
42068
42253
  rail.emitLine(` Applies: ${r.scope} \xB7 ${r.basis}`);
42069
42254
  continue;
@@ -42075,7 +42260,7 @@ async function drawRules(rail, input) {
42075
42260
  ...desc.map((d) => `${edge} ${c2}${d}${s.reset}`),
42076
42261
  `${edge} ${c3}${r.scope} \xB7 from ${r.basis}${s.reset}`
42077
42262
  ];
42078
- if (!t.motion || !t.truecolor) {
42263
+ if (!t2.motion || !t2.truecolor) {
42079
42264
  for (const l of lines(s.green, "", s.gray)) rail.emitLine(l);
42080
42265
  continue;
42081
42266
  }
@@ -42123,16 +42308,16 @@ function lightRow(screen, row2, r, center) {
42123
42308
  return out2 + screen.s.reset;
42124
42309
  }
42125
42310
  async function wordmark(screen, opts) {
42126
- const t = screen.term;
42127
- if (!t.screen) return;
42311
+ const t2 = screen.term;
42312
+ if (!t2.screen) return;
42128
42313
  screen.write("\n");
42129
- if (t.columns() < 50) {
42314
+ if (t2.columns() < 50) {
42130
42315
  screen.write(` ${screen.s.green}Verity${screen.s.reset}
42131
42316
 
42132
42317
  `);
42133
42318
  return;
42134
42319
  }
42135
- if (!opts.reveal || !t.motion || !t.truecolor) {
42320
+ if (!opts.reveal || !t2.motion || !t2.truecolor) {
42136
42321
  for (const row2 of WORDMARK) screen.write(` ${screen.s.green}${row2}${screen.s.reset}
42137
42322
  `);
42138
42323
  } else {
@@ -42150,7 +42335,7 @@ async function wordmark(screen, opts) {
42150
42335
  }
42151
42336
  screen.showCursor();
42152
42337
  }
42153
- if (TAGLINE.length + 2 <= t.columns()) screen.write(` ${screen.s.gray}${TAGLINE}${screen.s.reset}
42338
+ if (TAGLINE.length + 2 <= t2.columns()) screen.write(` ${screen.s.gray}${TAGLINE}${screen.s.reset}
42154
42339
  `);
42155
42340
  screen.write("\n");
42156
42341
  }
@@ -42230,23 +42415,23 @@ var Rail = class {
42230
42415
  * yellow: something the reader must act on.
42231
42416
  */
42232
42417
  line(raw, tone = "muted") {
42233
- const text2 = terminalText(raw, Number.MAX_SAFE_INTEGER);
42418
+ const text3 = terminalText(raw, Number.MAX_SAFE_INTEGER);
42234
42419
  if (!this.t.screen) {
42235
- this.emit(` ${text2}`);
42420
+ this.emit(` ${text3}`);
42236
42421
  return;
42237
42422
  }
42238
42423
  const color = tone === "muted" ? this.s.gray : tone === "warn" ? this.s.yellow : "";
42239
42424
  const reset = tone === "plain" ? "" : this.s.reset;
42240
- for (const l of wrapText(text2, this.width() - 3)) this.emit(`${this.s.gray}\u2502${this.s.reset} ${color}${l}${reset}`);
42425
+ for (const l of wrapText(text3, this.width() - 3)) this.emit(`${this.s.gray}\u2502${this.s.reset} ${color}${l}${reset}`);
42241
42426
  }
42242
42427
  /**
42243
42428
  * A line that belongs to the NEXT step, said before it starts (where a token
42244
42429
  * is about to go). On a screen it sits on the rail; in a log it stands alone,
42245
42430
  * so it does not read as a detail of the step above.
42246
42431
  */
42247
- note(text2) {
42248
- if (this.t.screen) this.line(text2);
42249
- else this.emit(terminalText(text2, Number.MAX_SAFE_INTEGER));
42432
+ note(text3) {
42433
+ if (this.t.screen) this.line(text3);
42434
+ else this.emit(terminalText(text3, Number.MAX_SAFE_INTEGER));
42250
42435
  }
42251
42436
  /** Key hints: Enter send v view the profile n skip (a screen only). */
42252
42437
  keys(pairs) {
@@ -42293,8 +42478,8 @@ var Rail = class {
42293
42478
  this.block++;
42294
42479
  }
42295
42480
  /** A finished sub-result under the active step (a screen only). */
42296
- ticked(text2) {
42297
- if (this.t.screen) this.emit(`${this.s.gray}\u2502${this.s.reset} ${this.s.green}\u2713${this.s.reset} ${text2}`);
42481
+ ticked(text3) {
42482
+ if (this.t.screen) this.emit(`${this.s.gray}\u2502${this.s.reset} ${this.s.green}\u2713${this.s.reset} ${text3}`);
42298
42483
  }
42299
42484
  /** The end of the rail, and the one next step. */
42300
42485
  end(title, next) {
@@ -42999,7 +43184,7 @@ function classifyCodacyConfig(root = repoRoot()) {
42999
43184
  return "foreign";
43000
43185
  }
43001
43186
  const tools = typeof parsed === "object" && parsed !== null ? parsed.tools : void 0;
43002
- const pointsAtVerity2 = Array.isArray(tools) && tools.some((t) => typeof t === "object" && t !== null && t.localConfigurationFile === VERITY_ESLINT_LOCAL_PATH);
43187
+ const pointsAtVerity2 = Array.isArray(tools) && tools.some((t2) => typeof t2 === "object" && t2 !== null && t2.localConfigurationFile === VERITY_ESLINT_LOCAL_PATH);
43003
43188
  if (!pointsAtVerity2) return "foreign";
43004
43189
  const eslint = readRegularFileInRoot(root, VERITY_ESLINT_CONFIG_FILE, MAX_BYTES);
43005
43190
  return eslint.ok && eslint.content.startsWith(VERITY_ESLINT_FIRST_LINE) ? "verity" : "foreign";
@@ -43272,7 +43457,7 @@ async function hooksStep(ui, ctx) {
43272
43457
  // src/commands/init/standard.ts
43273
43458
  var import_node_fs77 = require("node:fs");
43274
43459
  var import_node_path66 = require("node:path");
43275
- var import_yaml9 = __toESM2(require_dist());
43460
+ var import_yaml10 = __toESM2(require_dist());
43276
43461
 
43277
43462
  // src/lib/catalogue-client.ts
43278
43463
  async function fetchCatalogue(opts) {
@@ -43310,7 +43495,7 @@ async function choosePacks(globals) {
43310
43495
  }
43311
43496
  }
43312
43497
  function sayPacks(ui, plan) {
43313
- ui.rail.line(terminalText(`Review packs: ${describePacks(plan.packs)}`, 400));
43498
+ ui.rail.line(terminalText(`Review packs: ${describePacks(plan.packs)}. What each holds: verity standard catalogue`, 400));
43314
43499
  }
43315
43500
 
43316
43501
  // src/commands/init/team-standard.ts
@@ -43369,11 +43554,21 @@ function sayAdopted(ui, team) {
43369
43554
  }
43370
43555
 
43371
43556
  // src/commands/init/standard.ts
43557
+ function usesReviewPacks() {
43558
+ const raw = readRepoFile(STANDARD_FILE);
43559
+ if (raw === null) return true;
43560
+ try {
43561
+ const content = (0, import_yaml10.parse)(raw);
43562
+ return Array.isArray(content?.extends);
43563
+ } catch {
43564
+ return true;
43565
+ }
43566
+ }
43372
43567
  function hasProjectRules() {
43373
43568
  const raw = readRepoFile(STANDARD_FILE);
43374
43569
  if (raw === null) return true;
43375
43570
  try {
43376
- const content = (0, import_yaml9.parse)(raw);
43571
+ const content = (0, import_yaml10.parse)(raw);
43377
43572
  const rules = content?.custom_patterns;
43378
43573
  if (rules === void 0 || rules === null) return false;
43379
43574
  return !Array.isArray(rules) || rules.length > 0;
@@ -43424,7 +43619,7 @@ function localStandardProblem() {
43424
43619
  if (raw === null) return `${STANDARD_FILE} is a link, not a regular file, or larger than 512 KB.`;
43425
43620
  let parsed;
43426
43621
  try {
43427
- parsed = (0, import_yaml9.parse)(raw);
43622
+ parsed = (0, import_yaml10.parse)(raw);
43428
43623
  } catch (err2) {
43429
43624
  return `${STANDARD_FILE} is not valid YAML: ${terminalText(err2 instanceof Error ? err2.message : String(err2), 200)}`;
43430
43625
  }
@@ -43433,7 +43628,7 @@ function localStandardProblem() {
43433
43628
  if (!valid.ok) return `${STANDARD_FILE} is not a Standard the service accepts: ${terminalText(valid.error, 200)}`;
43434
43629
  return null;
43435
43630
  }
43436
- function removeDerivedStandard() {
43631
+ function removeLocalStandard() {
43437
43632
  const path = projectPath(STANDARD_FILE);
43438
43633
  try {
43439
43634
  const folder = (0, import_node_fs77.lstatSync)((0, import_node_path66.dirname)(path));
@@ -43442,6 +43637,19 @@ function removeDerivedStandard() {
43442
43637
  } catch {
43443
43638
  }
43444
43639
  }
43640
+ function setLocalStandardAside(now = /* @__PURE__ */ new Date(), remove = removeLocalStandard) {
43641
+ const raw = readRepoFile(STANDARD_FILE);
43642
+ if (raw === null) return { ok: false, message: `${STANDARD_FILE} is a link, not a regular file, or larger than 512 KB, so it was not set aside.` };
43643
+ let path;
43644
+ try {
43645
+ path = keepStandardCopy(raw, now);
43646
+ } catch (err2) {
43647
+ return { ok: false, message: `Could not keep a copy of ${STANDARD_FILE} (${terminalText(err2 instanceof Error ? err2.message : String(err2), 200)}), so it was not set aside.` };
43648
+ }
43649
+ remove();
43650
+ if ((0, import_node_fs77.existsSync)(projectPath(STANDARD_FILE))) return { ok: false, message: `Could not remove ${STANDARD_FILE} after copying it to ${path}.` };
43651
+ return { ok: true, path };
43652
+ }
43445
43653
  async function standardStep(ui, ctx) {
43446
43654
  const { rail } = ui;
43447
43655
  const s = ui.screen.s;
@@ -43470,7 +43678,7 @@ async function standardStep(ui, ctx) {
43470
43678
  sayAdopted(ui, again);
43471
43679
  return end({ source: "adopted", version: again.version, profile: profile2 });
43472
43680
  }
43473
- removeDerivedStandard();
43681
+ removeLocalStandard();
43474
43682
  if (again.status === "write-failed" || again.status === "unavailable") rail.line(terminalText(again.reason, 300));
43475
43683
  return { ...leaveTeamStandard(again.status === "write-failed" ? "write-failed" : "unavailable", null), profile: profile2 };
43476
43684
  };
@@ -43501,12 +43709,25 @@ async function standardStep(ui, ctx) {
43501
43709
  rail.line(team2.status === "none" ? `There is no Standard on the service either, so reviews have no rules. Fix ${STANDARD_FILE}, or delete it, then run verity init again.` : team2.status === "unavailable" ? `The Verity service did not answer (${terminalText(team2.reason, 200)}), so no Standard is confirmed. Fix ${STANDARD_FILE}, then run verity init again.` : `No Standard on the service was looked up. Fix ${STANDARD_FILE}, or sign in, then run verity init again.`);
43502
43710
  return end({ source: "none", version: null, profile: notAsked });
43503
43711
  };
43712
+ if (ctx.standard === "new" && (0, import_node_fs77.lstatSync)(projectPath(STANDARD_FILE), { throwIfNoEntry: false })) {
43713
+ const aside = setLocalStandardAside();
43714
+ if (!aside.ok) {
43715
+ rail.warn("Could not set your Standard aside for a new one");
43716
+ rail.line(terminalText(aside.message, 300));
43717
+ rail.line("Your Standard is as it was. Fix the cause, or move the file yourself, then run verity init --standard new again.");
43718
+ return end({ source: "none", version: null, profile: notAsked });
43719
+ }
43720
+ rail.done(`Set your Standard aside ${s.gray}\xB7 a copy is in ${aside.path}${s.reset}`);
43721
+ }
43504
43722
  if ((0, import_node_fs77.existsSync)(projectPath(STANDARD_FILE))) {
43505
43723
  const problem = localStandardProblem();
43506
43724
  if (problem !== null) return unusableHere(problem);
43507
43725
  const sync = await pushLocalStandardIfMissing(ctx.globals);
43508
43726
  rail.done("Kept your Standard");
43509
43727
  rail.line(`${STANDARD_FILE} is already here, so this run leaves it as it is. Edit it there, then share the change: verity standard push`);
43728
+ if (!usesReviewPacks()) {
43729
+ rail.line("It does not use review packs. To move it to packs and keep your rules: verity standard push. To build a new one: verity init --standard new", "muted");
43730
+ }
43510
43731
  if (sync.status === "pushed") {
43511
43732
  rail.line(sync.version !== null ? `It was only on this machine. It is shared now as v${sync.version}.` : "It is only on this machine:", sync.version !== null ? "muted" : "warn");
43512
43733
  for (const line2 of sync.lines) if (!line2.startsWith("Standard pushed")) rail.line(terminalText(line2, 600), "warn");
@@ -44191,7 +44412,7 @@ async function recordAnswers(ui, momentIds, telemetry, completed) {
44191
44412
  moments: momentIds,
44192
44413
  ...telemetry ? { telemetry } : {},
44193
44414
  // A failed run also clears an earlier stamp: "done" describes this checkout now.
44194
- init: completed ? { completed_at: (/* @__PURE__ */ new Date()).toISOString(), cli_version: true ? "0.35.1-experimental.19ce23f" : "dev" } : void 0
44415
+ init: completed ? { completed_at: (/* @__PURE__ */ new Date()).toISOString(), cli_version: true ? "0.35.2" : "dev" } : void 0
44195
44416
  });
44196
44417
  } catch (err2) {
44197
44418
  ui.rail.line(`Could not record the setup answers: ${terminalText(err2.message, 200)}`, "warn");
@@ -44656,13 +44877,13 @@ function registerTaskCommands(program2) {
44656
44877
  return;
44657
44878
  }
44658
44879
  printInfo("Tasks:");
44659
- for (const t of tasks) {
44660
- const status = t.status ?? "active";
44880
+ for (const t2 of tasks) {
44881
+ const status = t2.status ?? "active";
44661
44882
  const statusTag = status !== "active" ? ` [${status}]` : "";
44662
- const runs = t.run_count;
44663
- const ago = t.last_run_at ? timeAgo2(t.last_run_at) : "";
44883
+ const runs = t2.run_count;
44884
+ const ago = t2.last_run_at ? timeAgo2(t2.last_run_at) : "";
44664
44885
  const detail2 = runs != null ? `${runs} run${runs === 1 ? "" : "s"}${ago ? ", " + ago : ""}` : "";
44665
- printInfo(` ${t.label}${statusTag}${detail2 ? " (" + detail2 + ")" : ""}`);
44886
+ printInfo(` ${t2.label}${statusTag}${detail2 ? " (" + detail2 + ")" : ""}`);
44666
44887
  }
44667
44888
  });
44668
44889
  task.command("close").description("Close the current task (next run starts a new task)").option("--id <taskId>", "Close a specific task by ID").action(async (opts) => {
@@ -44893,11 +45114,11 @@ function resolve8(token, treePaths) {
44893
45114
  const matches = treePaths.filter((p) => p.endsWith(suffix));
44894
45115
  return matches.length === 1 ? matches[0] : null;
44895
45116
  }
44896
- function deriveFileGlobs(text2, treePaths) {
44897
- if (!text2 || treePaths.length === 0) return [];
45117
+ function deriveFileGlobs(text3, treePaths) {
45118
+ if (!text3 || treePaths.length === 0) return [];
44898
45119
  const out2 = [];
44899
45120
  const seen = /* @__PURE__ */ new Set();
44900
- for (const raw of text2.match(PATH_TOKEN) ?? []) {
45121
+ for (const raw of text3.match(PATH_TOKEN) ?? []) {
44901
45122
  const token = clean(raw);
44902
45123
  if (!token) continue;
44903
45124
  const path = resolve8(token, treePaths);
@@ -44967,15 +45188,15 @@ function registerReflectCommand(program2) {
44967
45188
  }
44968
45189
  if (!taskId) {
44969
45190
  const recent = mem.data.recent_tasks ?? [];
44970
- for (const t of recent) {
44971
- const label2 = t.label;
45191
+ for (const t2 of recent) {
45192
+ const label2 = t2.label;
44972
45193
  if (isMetaTaskLabel(label2)) continue;
44973
- const lastRunAt = t.last_run_at;
45194
+ const lastRunAt = t2.last_run_at;
44974
45195
  if (lastRunAt) {
44975
45196
  const age = Date.now() - new Date(lastRunAt).getTime();
44976
45197
  if (Number.isFinite(age) && age > STALE_TASK_MS) continue;
44977
45198
  }
44978
- taskId = t.id;
45199
+ taskId = t2.id;
44979
45200
  taskResolution = "recent";
44980
45201
  break;
44981
45202
  }
@@ -46114,10 +46335,10 @@ function registerLeanCommand(program2) {
46114
46335
  }
46115
46336
 
46116
46337
  // src/cli.ts
46117
- program.name("verity").description("CLI for Verity quality gate service").version("0.35.1-experimental.19ce23f").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) => {
46338
+ program.name("verity").description("CLI for Verity quality gate service").version("0.35.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) => {
46118
46339
  const isTelemetryHelper = actionCommand.name() === "headers" && actionCommand.parent?.name() === "telemetry";
46119
46340
  if (!isTelemetryHelper) {
46120
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.35.1-experimental.19ce23f");
46341
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.35.2");
46121
46342
  }
46122
46343
  setUserNamedServiceUrl(program.opts().serviceUrl);
46123
46344
  try {