@codacy/verity-cli 0.34.0-experimental.92a1040 → 0.34.0-experimental.afcb0e6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/verity.js CHANGED
@@ -10435,13 +10435,13 @@ var require_web_tree_sitter2 = __commonJS2({
10435
10435
  }
10436
10436
  readAsync = /* @__PURE__ */ __name(async (url) => {
10437
10437
  if (isFileURI(url)) {
10438
- return new Promise((resolve8, reject) => {
10438
+ return new Promise((resolve9, reject) => {
10439
10439
  var xhr = new XMLHttpRequest();
10440
10440
  xhr.open("GET", url, true);
10441
10441
  xhr.responseType = "arraybuffer";
10442
10442
  xhr.onload = () => {
10443
10443
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
10444
- resolve8(xhr.response);
10444
+ resolve9(xhr.response);
10445
10445
  return;
10446
10446
  }
10447
10447
  reject(xhr.status);
@@ -10634,9 +10634,9 @@ var require_web_tree_sitter2 = __commonJS2({
10634
10634
  __name(receiveInstantiationResult, "receiveInstantiationResult");
10635
10635
  var info2 = getWasmImports();
10636
10636
  if (Module["instantiateWasm"]) {
10637
- return new Promise((resolve8, reject) => {
10637
+ return new Promise((resolve9, reject) => {
10638
10638
  Module["instantiateWasm"](info2, (mod, inst) => {
10639
- resolve8(receiveInstance(mod, inst));
10639
+ resolve9(receiveInstance(mod, inst));
10640
10640
  });
10641
10641
  });
10642
10642
  }
@@ -11969,8 +11969,8 @@ var require_web_tree_sitter2 = __commonJS2({
11969
11969
  if (runtimeInitialized) {
11970
11970
  moduleRtn = Module;
11971
11971
  } else {
11972
- moduleRtn = new Promise((resolve8, reject) => {
11973
- readyPromiseResolve = resolve8;
11972
+ moduleRtn = new Promise((resolve9, reject) => {
11973
+ readyPromiseResolve = resolve9;
11974
11974
  readyPromiseReject = reject;
11975
11975
  });
11976
11976
  }
@@ -14447,8 +14447,87 @@ var import_node_child_process4 = require("node:child_process");
14447
14447
 
14448
14448
  // src/constants.ts
14449
14449
  var import_node_child_process = require("node:child_process");
14450
+ var import_node_fs2 = require("node:fs");
14451
+ var import_node_path2 = require("node:path");
14452
+
14453
+ // src/lib/context-identity.ts
14454
+ var import_node_crypto = require("node:crypto");
14450
14455
  var import_node_fs = require("node:fs");
14456
+ var import_node_os = require("node:os");
14451
14457
  var import_node_path = require("node:path");
14458
+ var SHARED_SENTINELS = /* @__PURE__ */ new Set([
14459
+ "",
14460
+ "-",
14461
+ "n/a",
14462
+ "na",
14463
+ "none",
14464
+ "null",
14465
+ "undefined",
14466
+ "unknown",
14467
+ "anon",
14468
+ "anonymous",
14469
+ "default",
14470
+ "_default"
14471
+ ]);
14472
+ function isSharedSentinel(value) {
14473
+ if (value == null) return true;
14474
+ return SHARED_SENTINELS.has(value.trim().toLowerCase());
14475
+ }
14476
+ var ephemeral = /* @__PURE__ */ new Map();
14477
+ function ephemeralId(slot, width) {
14478
+ let id = ephemeral.get(slot);
14479
+ if (!id) {
14480
+ id = `eph-${(0, import_node_crypto.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
14481
+ ephemeral.set(slot, id);
14482
+ }
14483
+ return id;
14484
+ }
14485
+ function contextIdentity(input) {
14486
+ const tokenUsable = !isSharedSentinel(input.token ?? null);
14487
+ const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
14488
+ const userKey = tokenUsable ? (0, import_node_crypto.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
14489
+ const sessionKey2 = sessionUsable ? (0, import_node_crypto.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
14490
+ let treeKey = "no-tree";
14491
+ const rawTree = input.treeRoot;
14492
+ if (rawTree && !isSharedSentinel(rawTree)) {
14493
+ let resolved = rawTree;
14494
+ try {
14495
+ resolved = import_node_fs.realpathSync.native(rawTree);
14496
+ } catch {
14497
+ }
14498
+ treeKey = (0, import_node_crypto.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
14499
+ }
14500
+ return {
14501
+ userKey,
14502
+ treeKey,
14503
+ sessionKey: sessionKey2,
14504
+ userKeySource: tokenUsable ? "token" : "ephemeral",
14505
+ sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
14506
+ ephemeral: !tokenUsable || !sessionUsable
14507
+ };
14508
+ }
14509
+ function verityHome() {
14510
+ const override = process.env.VERITY_HOME;
14511
+ return override && override.trim() ? (0, import_node_path.resolve)(override) : (0, import_node_path.join)((0, import_node_os.homedir)(), ".verity");
14512
+ }
14513
+ function dossierDir(identity) {
14514
+ return (0, import_node_path.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
14515
+ }
14516
+ function treeDir(identity) {
14517
+ return (0, import_node_path.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
14518
+ }
14519
+ function scopeIdentity(token, sessionId) {
14520
+ const t = (token ?? "").trim();
14521
+ const s = (sessionId ?? "").trim();
14522
+ const userKey = t.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
14523
+ const sessionKey2 = s.length > 0 ? (0, import_node_crypto.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
14524
+ return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
14525
+ }
14526
+ function sessionScopeKey(token, sessionId) {
14527
+ return scopeIdentity(token, sessionId).bucket;
14528
+ }
14529
+
14530
+ // src/constants.ts
14452
14531
  var _repoRoot = null;
14453
14532
  function repoRoot() {
14454
14533
  if (_repoRoot === null) {
@@ -14476,17 +14555,36 @@ function mainWorktreeRoot() {
14476
14555
  _mainRoot = null;
14477
14556
  return _mainRoot;
14478
14557
  }
14479
- const abs = common.startsWith("/") ? common : (0, import_node_path.join)(repoRoot(), common);
14480
- _mainRoot = (0, import_node_path.dirname)(abs);
14558
+ const abs = common.startsWith("/") ? common : (0, import_node_path2.join)(repoRoot(), common);
14559
+ _mainRoot = (0, import_node_path2.dirname)(abs);
14481
14560
  } catch {
14482
14561
  _mainRoot = null;
14483
14562
  }
14484
14563
  return _mainRoot;
14485
14564
  }
14486
14565
  function verityConfigured() {
14487
- if ((0, import_node_fs.existsSync)((0, import_node_path.join)(repoRoot(), VERITY_DIR))) return true;
14566
+ if (isProjectVerityDir((0, import_node_path2.join)(repoRoot(), VERITY_DIR))) return true;
14488
14567
  const main = mainWorktreeRoot();
14489
- return !!main && (0, import_node_fs.existsSync)((0, import_node_path.join)(main, VERITY_DIR));
14568
+ return !!main && isProjectVerityDir((0, import_node_path2.join)(main, VERITY_DIR));
14569
+ }
14570
+ function isProjectVerityDir(dir) {
14571
+ return (0, import_node_fs2.existsSync)(dir) && !isMachineStore(dir);
14572
+ }
14573
+ function isMachineStore(dir) {
14574
+ const here = canonicalPath(dir);
14575
+ const stores = [process.env.HOME ? (0, import_node_path2.join)(process.env.HOME, VERITY_DIR) : null, verityHome()];
14576
+ return stores.some((s) => s !== null && canonicalPath(s) === here);
14577
+ }
14578
+ function canonicalPath(p) {
14579
+ try {
14580
+ return import_node_fs2.realpathSync.native(p);
14581
+ } catch {
14582
+ }
14583
+ try {
14584
+ return (0, import_node_path2.join)(import_node_fs2.realpathSync.native((0, import_node_path2.dirname)(p)), (0, import_node_path2.basename)(p));
14585
+ } catch {
14586
+ return (0, import_node_path2.resolve)(p);
14587
+ }
14490
14588
  }
14491
14589
  var VERITY_DIR = ".verity";
14492
14590
  var CREDENTIALS_FILE = `${VERITY_DIR}/credentials`;
@@ -14507,7 +14605,7 @@ var MEMORY_DIR = `${VERITY_DIR}/memory`;
14507
14605
  var CODACY_CONFIG_FILE = ".codacy/codacy.config.json";
14508
14606
  var VERITYIGNORE_FILE = ".verityignore";
14509
14607
  function projectPath(relativePath) {
14510
- return (0, import_node_path.join)(repoRoot(), relativePath);
14608
+ return (0, import_node_path2.join)(repoRoot(), relativePath);
14511
14609
  }
14512
14610
  var MAX_DELTA_BYTES = 194560;
14513
14611
  var MAX_FILES = 40;
@@ -14681,7 +14779,7 @@ function printVerbose(msg, verbose) {
14681
14779
  }
14682
14780
 
14683
14781
  // src/lib/debug-log.ts
14684
- var import_node_fs2 = require("node:fs");
14782
+ var import_node_fs3 = require("node:fs");
14685
14783
  function isDebugEnabled() {
14686
14784
  const v = process.env.VERITY_DEBUG;
14687
14785
  if (v === "0" || v === "false" || v === "off") return false;
@@ -14699,24 +14797,24 @@ function writeLine(obj) {
14699
14797
  try {
14700
14798
  const dir = projectPath(DEBUG_LOG_DIR);
14701
14799
  const file = projectPath(DEBUG_LOG_FILE);
14702
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
14800
+ (0, import_node_fs3.mkdirSync)(dir, { recursive: true });
14703
14801
  rotateIfNeeded(file);
14704
- (0, import_node_fs2.appendFileSync)(file, JSON.stringify(obj) + "\n");
14802
+ (0, import_node_fs3.appendFileSync)(file, JSON.stringify(obj) + "\n");
14705
14803
  } catch {
14706
14804
  }
14707
14805
  }
14708
14806
  function rotateIfNeeded(file) {
14709
14807
  try {
14710
- const s = (0, import_node_fs2.statSync)(file);
14808
+ const s = (0, import_node_fs3.statSync)(file);
14711
14809
  if (s.size < DEBUG_LOG_MAX_BYTES) return;
14712
- (0, import_node_fs2.renameSync)(file, `${file}.1`);
14810
+ (0, import_node_fs3.renameSync)(file, `${file}.1`);
14713
14811
  } catch {
14714
14812
  }
14715
14813
  }
14716
14814
 
14717
14815
  // src/lib/credentials.ts
14718
14816
  var import_promises = require("node:fs/promises");
14719
- var import_node_path2 = require("node:path");
14817
+ var import_node_path3 = require("node:path");
14720
14818
  var import_node_child_process2 = require("node:child_process");
14721
14819
  function globalCredentialsPath() {
14722
14820
  return `${process.env.HOME}/.verity/credentials`;
@@ -14791,7 +14889,7 @@ async function readGlobalCredential(remote) {
14791
14889
  }
14792
14890
  async function upsertGlobalCredential(remote, rec) {
14793
14891
  const path = globalCredentialsPath();
14794
- await (0, import_promises.mkdir)((0, import_node_path2.dirname)(path), { recursive: true });
14892
+ await (0, import_promises.mkdir)((0, import_node_path3.dirname)(path), { recursive: true });
14795
14893
  let content = "";
14796
14894
  try {
14797
14895
  content = await (0, import_promises.readFile)(path, "utf-8");
@@ -14935,10 +15033,10 @@ async function foldLegacyLocalCredential(remoteArg) {
14935
15033
 
14936
15034
  // src/lib/git.ts
14937
15035
  var import_node_child_process3 = require("node:child_process");
14938
- var import_node_fs3 = require("node:fs");
14939
- var import_node_path3 = require("node:path");
15036
+ var import_node_fs4 = require("node:fs");
15037
+ var import_node_path4 = require("node:path");
14940
15038
  function resolveFile(relpath) {
14941
- return (0, import_node_fs3.existsSync)(relpath) ? relpath : null;
15039
+ return (0, import_node_fs4.existsSync)(relpath) ? relpath : null;
14942
15040
  }
14943
15041
  function execGit(cmd) {
14944
15042
  try {
@@ -14956,7 +15054,7 @@ function readBaselineSha() {
14956
15054
  if (sha === null) return null;
14957
15055
  if (!commitResolves(sha)) {
14958
15056
  try {
14959
- (0, import_node_fs3.unlinkSync)(BASELINE_SHA_FILE);
15057
+ (0, import_node_fs4.unlinkSync)(BASELINE_SHA_FILE);
14960
15058
  } catch {
14961
15059
  }
14962
15060
  return null;
@@ -14964,10 +15062,10 @@ function readBaselineSha() {
14964
15062
  return sha;
14965
15063
  }
14966
15064
  function readRawBaselineSha() {
14967
- if (!(0, import_node_fs3.existsSync)(BASELINE_SHA_FILE)) return null;
15065
+ if (!(0, import_node_fs4.existsSync)(BASELINE_SHA_FILE)) return null;
14968
15066
  let sha;
14969
15067
  try {
14970
- sha = (0, import_node_fs3.readFileSync)(BASELINE_SHA_FILE, "utf-8").trim();
15068
+ sha = (0, import_node_fs4.readFileSync)(BASELINE_SHA_FILE, "utf-8").trim();
14971
15069
  } catch {
14972
15070
  return null;
14973
15071
  }
@@ -14976,8 +15074,8 @@ function readRawBaselineSha() {
14976
15074
  function writeBaselineSha(sha) {
14977
15075
  if (!SHA_RE.test(sha)) return;
14978
15076
  try {
14979
- (0, import_node_fs3.mkdirSync)((0, import_node_path3.dirname)(BASELINE_SHA_FILE), { recursive: true });
14980
- (0, import_node_fs3.writeFileSync)(BASELINE_SHA_FILE, sha);
15077
+ (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(BASELINE_SHA_FILE), { recursive: true });
15078
+ (0, import_node_fs4.writeFileSync)(BASELINE_SHA_FILE, sha);
14981
15079
  } catch {
14982
15080
  }
14983
15081
  }
@@ -15065,17 +15163,17 @@ function showContentAtRef(ref, repoRelPath) {
15065
15163
  }
15066
15164
  function filterAnalyzable(files) {
15067
15165
  return files.filter((f) => {
15068
- const ext = (0, import_node_path3.extname)(f).slice(1);
15166
+ const ext = (0, import_node_path4.extname)(f).slice(1);
15069
15167
  return ANALYZABLE_EXTENSIONS.has(ext);
15070
15168
  });
15071
15169
  }
15072
15170
  function filterReviewable(files) {
15073
15171
  return files.filter((f) => {
15074
- const ext = (0, import_node_path3.extname)(f).slice(1);
15172
+ const ext = (0, import_node_path4.extname)(f).slice(1);
15075
15173
  if (ANALYZABLE_EXTENSIONS.has(ext)) return false;
15076
15174
  if (REVIEWABLE_EXTENSIONS.has(ext)) return true;
15077
- const basename8 = f.split("/").pop() ?? "";
15078
- if (REVIEWABLE_FILENAMES.has(basename8)) return true;
15175
+ const basename9 = f.split("/").pop() ?? "";
15176
+ if (REVIEWABLE_FILENAMES.has(basename9)) return true;
15079
15177
  if (REVIEWABLE_PATH_PATTERNS.some((p) => p.test(f))) return true;
15080
15178
  return false;
15081
15179
  });
@@ -15550,7 +15648,7 @@ async function maybeHealServiceUrl(resolution, verbose) {
15550
15648
 
15551
15649
  // src/lib/register.ts
15552
15650
  var readline = __toESM2(require("node:readline/promises"));
15553
- var import_node_os = require("node:os");
15651
+ var import_node_os2 = require("node:os");
15554
15652
 
15555
15653
  // src/lib/spinner.ts
15556
15654
  var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
@@ -15638,7 +15736,7 @@ function startSpinner(label2, opts = {}) {
15638
15736
  }
15639
15737
 
15640
15738
  // src/lib/provider-auth.ts
15641
- var sleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
15739
+ var sleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
15642
15740
  var form = (fields) => new URLSearchParams(fields).toString();
15643
15741
  async function githubAccountId(owner) {
15644
15742
  try {
@@ -15903,7 +16001,7 @@ function deviceLabel() {
15903
16001
  const override = process.env.VERITY_DEVICE_LABEL?.trim();
15904
16002
  if (override) return override;
15905
16003
  try {
15906
- return (0, import_node_os.hostname)() || void 0;
16004
+ return (0, import_node_os2.hostname)() || void 0;
15907
16005
  } catch {
15908
16006
  return void 0;
15909
16007
  }
@@ -16061,8 +16159,8 @@ function registerAuthCommands(program2) {
16061
16159
  }
16062
16160
 
16063
16161
  // src/lib/pending-login.ts
16064
- var import_node_fs4 = require("node:fs");
16065
- var import_node_path4 = require("node:path");
16162
+ var import_node_fs5 = require("node:fs");
16163
+ var import_node_path5 = require("node:path");
16066
16164
  function pendingLoginPath() {
16067
16165
  return `${process.env.HOME}/.verity/pending-login.json`;
16068
16166
  }
@@ -16078,26 +16176,26 @@ function savePendingLogin(dc, serviceUrl, now = Date.now()) {
16078
16176
  created_at: new Date(now).toISOString()
16079
16177
  };
16080
16178
  const path = pendingLoginPath();
16081
- (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(path), { recursive: true });
16179
+ (0, import_node_fs5.mkdirSync)((0, import_node_path5.dirname)(path), { recursive: true });
16082
16180
  clearPendingLogin();
16083
- (0, import_node_fs4.writeFileSync)(path, JSON.stringify(record, null, 2) + "\n", { mode: 384, flag: "wx" });
16181
+ (0, import_node_fs5.writeFileSync)(path, JSON.stringify(record, null, 2) + "\n", { mode: 384, flag: "wx" });
16084
16182
  try {
16085
- (0, import_node_fs4.chmodSync)(path, 384);
16183
+ (0, import_node_fs5.chmodSync)(path, 384);
16086
16184
  } catch {
16087
16185
  }
16088
16186
  return record;
16089
16187
  }
16090
16188
  function readPendingLogin(now = Date.now()) {
16091
16189
  const path = pendingLoginPath();
16092
- if (!(0, import_node_fs4.existsSync)(path)) return { status: "none" };
16190
+ if (!(0, import_node_fs5.existsSync)(path)) return { status: "none" };
16093
16191
  try {
16094
- if ((0, import_node_fs4.lstatSync)(path).isSymbolicLink()) return { status: "invalid", reason: "it is a symlink" };
16192
+ if ((0, import_node_fs5.lstatSync)(path).isSymbolicLink()) return { status: "invalid", reason: "it is a symlink" };
16095
16193
  } catch {
16096
16194
  return { status: "none" };
16097
16195
  }
16098
16196
  let parsed;
16099
16197
  try {
16100
- parsed = JSON.parse((0, import_node_fs4.readFileSync)(path, "utf-8"));
16198
+ parsed = JSON.parse((0, import_node_fs5.readFileSync)(path, "utf-8"));
16101
16199
  } catch {
16102
16200
  return { status: "invalid", reason: "it is not valid JSON" };
16103
16201
  }
@@ -16118,7 +16216,7 @@ function readPendingLogin(now = Date.now()) {
16118
16216
  }
16119
16217
  function clearPendingLogin() {
16120
16218
  try {
16121
- (0, import_node_fs4.unlinkSync)(pendingLoginPath());
16219
+ (0, import_node_fs5.unlinkSync)(pendingLoginPath());
16122
16220
  return true;
16123
16221
  } catch {
16124
16222
  return false;
@@ -16674,11 +16772,11 @@ function registerLogoutCommand(program2) {
16674
16772
 
16675
16773
  // src/lib/hooks.ts
16676
16774
  var import_promises4 = require("node:fs/promises");
16677
- var import_node_path6 = require("node:path");
16775
+ var import_node_path7 = require("node:path");
16678
16776
 
16679
16777
  // src/lib/json-file.ts
16680
16778
  var import_promises3 = require("node:fs/promises");
16681
- var import_node_path5 = require("node:path");
16779
+ var import_node_path6 = require("node:path");
16682
16780
  function jsonSemanticEqual(a, b) {
16683
16781
  if (a === b) return true;
16684
16782
  if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) {
@@ -16724,7 +16822,7 @@ async function writeJsonFilePreservingStyle(file, value) {
16724
16822
  const indent = currentRaw !== null ? detectJsonIndent(currentRaw) : 2;
16725
16823
  const next = JSON.stringify(value, null, indent) + "\n";
16726
16824
  if (next === currentRaw) return false;
16727
- await (0, import_promises3.mkdir)((0, import_node_path5.dirname)(file), { recursive: true });
16825
+ await (0, import_promises3.mkdir)((0, import_node_path6.dirname)(file), { recursive: true });
16728
16826
  await (0, import_promises3.writeFile)(file, next);
16729
16827
  return true;
16730
16828
  }
@@ -16909,13 +17007,13 @@ async function writeSettings(settings) {
16909
17007
  }
16910
17008
  async function readSettingsAt(root) {
16911
17009
  try {
16912
- return JSON.parse(await (0, import_promises4.readFile)((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
17010
+ return JSON.parse(await (0, import_promises4.readFile)((0, import_node_path7.join)(root, CLAUDE_SETTINGS_FILE), "utf-8"));
16913
17011
  } catch {
16914
17012
  return {};
16915
17013
  }
16916
17014
  }
16917
17015
  async function writeSettingsAt(root, settings) {
16918
- await writeJsonFilePreservingStyle((0, import_node_path6.join)(root, CLAUDE_SETTINGS_FILE), settings);
17016
+ await writeJsonFilePreservingStyle((0, import_node_path7.join)(root, CLAUDE_SETTINGS_FILE), settings);
16919
17017
  }
16920
17018
  async function hasLegacyHooksAt(root) {
16921
17019
  const settings = await readSettingsAt(root);
@@ -17104,12 +17202,12 @@ async function applyMomentSelection(moments) {
17104
17202
  }
17105
17203
 
17106
17204
  // src/lib/project-config.ts
17107
- var import_node_fs6 = require("node:fs");
17108
- var import_node_path8 = require("node:path");
17205
+ var import_node_fs7 = require("node:fs");
17206
+ var import_node_path9 = require("node:path");
17109
17207
 
17110
17208
  // src/lib/repo-controlled.ts
17111
- var import_node_fs5 = require("node:fs");
17112
- var import_node_path7 = require("node:path");
17209
+ var import_node_fs6 = require("node:fs");
17210
+ var import_node_path8 = require("node:path");
17113
17211
 
17114
17212
  // src/lib/hardened-git.ts
17115
17213
  var import_node_child_process5 = require("node:child_process");
@@ -17190,7 +17288,7 @@ function repoControlled(worktree, rel) {
17190
17288
  for (let i2 = 1; i2 <= parts2.length; i2++) {
17191
17289
  let st;
17192
17290
  try {
17193
- st = (0, import_node_fs5.lstatSync)((0, import_node_path7.join)(worktree, ...parts2.slice(0, i2)));
17291
+ st = (0, import_node_fs6.lstatSync)((0, import_node_path8.join)(worktree, ...parts2.slice(0, i2)));
17194
17292
  } catch (err2) {
17195
17293
  const code = err2?.code;
17196
17294
  if (code === "ENOENT" || code === "ENOTDIR") return null;
@@ -17214,8 +17312,8 @@ function parseMoments(raw) {
17214
17312
  }
17215
17313
  function readConfigFile(path) {
17216
17314
  try {
17217
- if (!(0, import_node_fs6.existsSync)(path)) return null;
17218
- const raw = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf-8"));
17315
+ if (!(0, import_node_fs7.existsSync)(path)) return null;
17316
+ const raw = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf-8"));
17219
17317
  const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
17220
17318
  const source2 = raw.git_moments_source === "user" || raw.git_moments_source === "init" ? raw.git_moments_source : void 0;
17221
17319
  return {
@@ -17232,13 +17330,13 @@ function candidates() {
17232
17330
  const out2 = [{ path: local, source: "local" }];
17233
17331
  const main = mainWorktreeRoot();
17234
17332
  if (main) {
17235
- const inherited = (0, import_node_path8.join)(main, PROJECT_CONFIG_FILE);
17333
+ const inherited = (0, import_node_path9.join)(main, PROJECT_CONFIG_FILE);
17236
17334
  if (inherited !== local) out2.push({ path: inherited, source: "main-worktree" });
17237
17335
  }
17238
17336
  return out2;
17239
17337
  }
17240
17338
  function formalRefusal(path) {
17241
- return repoControlled((0, import_node_path8.dirname)((0, import_node_path8.dirname)(path)), PROJECT_CONFIG_FILE);
17339
+ return repoControlled((0, import_node_path9.dirname)((0, import_node_path9.dirname)(path)), PROJECT_CONFIG_FILE);
17242
17340
  }
17243
17341
  function readProjectConfigRaw() {
17244
17342
  for (const { path, source: source2 } of candidates()) {
@@ -17274,8 +17372,8 @@ function writeProjectConfig(patch) {
17274
17372
  ...patch
17275
17373
  };
17276
17374
  const target = projectPath(PROJECT_CONFIG_FILE);
17277
- (0, import_node_fs6.mkdirSync)((0, import_node_path8.dirname)(target), { recursive: true });
17278
- (0, import_node_fs6.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
17375
+ (0, import_node_fs7.mkdirSync)((0, import_node_path9.dirname)(target), { recursive: true });
17376
+ (0, import_node_fs7.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
17279
17377
  return next;
17280
17378
  }
17281
17379
  function resolveGuardMoments(explicit) {
@@ -17284,11 +17382,11 @@ function resolveGuardMoments(explicit) {
17284
17382
  }
17285
17383
 
17286
17384
  // src/lib/plugin-ownership.ts
17287
- var import_node_fs9 = require("node:fs");
17385
+ var import_node_fs10 = require("node:fs");
17288
17386
 
17289
17387
  // src/lib/which.ts
17290
- var import_node_fs7 = require("node:fs");
17291
- var import_node_path9 = require("node:path");
17388
+ var import_node_fs8 = require("node:fs");
17389
+ var import_node_path10 = require("node:path");
17292
17390
  function executableExtensions(platform4, pathext) {
17293
17391
  if (platform4 !== "win32") return [""];
17294
17392
  const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
@@ -17306,14 +17404,14 @@ function whichSync(bin, opts = {}) {
17306
17404
  if (!rawPath) return null;
17307
17405
  const exts = executableExtensions(platform4, opts.pathext ?? process.env.PATHEXT);
17308
17406
  const real = opts.real ?? true;
17309
- for (const dir of rawPath.split(import_node_path9.delimiter)) {
17407
+ for (const dir of rawPath.split(import_node_path10.delimiter)) {
17310
17408
  if (!dir) continue;
17311
17409
  for (const ext of exts) {
17312
- const candidate = (0, import_node_path9.join)(dir, bin + ext);
17410
+ const candidate = (0, import_node_path10.join)(dir, bin + ext);
17313
17411
  try {
17314
- if (!(0, import_node_fs7.statSync)(candidate).isFile()) continue;
17315
- if (platform4 !== "win32") (0, import_node_fs7.accessSync)(candidate, import_node_fs7.constants.X_OK);
17316
- return real ? (0, import_node_fs7.realpathSync)(candidate) : candidate;
17412
+ if (!(0, import_node_fs8.statSync)(candidate).isFile()) continue;
17413
+ if (platform4 !== "win32") (0, import_node_fs8.accessSync)(candidate, import_node_fs8.constants.X_OK);
17414
+ return real ? (0, import_node_fs8.realpathSync)(candidate) : candidate;
17317
17415
  } catch {
17318
17416
  continue;
17319
17417
  }
@@ -17323,11 +17421,11 @@ function whichSync(bin, opts = {}) {
17323
17421
  }
17324
17422
 
17325
17423
  // src/lib/plugin-ownership.ts
17326
- var import_node_os2 = require("node:os");
17327
- var import_node_path10 = require("node:path");
17424
+ var import_node_os3 = require("node:os");
17425
+ var import_node_path11 = require("node:path");
17328
17426
 
17329
17427
  // src/lib/stderr-log.ts
17330
- var import_node_fs8 = require("node:fs");
17428
+ var import_node_fs9 = require("node:fs");
17331
17429
  var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
17332
17430
  var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
17333
17431
  function scrub(s) {
@@ -17340,9 +17438,9 @@ function append(text) {
17340
17438
  try {
17341
17439
  const dir = projectPath(DEBUG_LOG_DIR);
17342
17440
  const file = projectPath(STDERR_LOG_FILE);
17343
- (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
17441
+ (0, import_node_fs9.mkdirSync)(dir, { recursive: true });
17344
17442
  rotateIfNeeded(file);
17345
- (0, import_node_fs8.appendFileSync)(file, text);
17443
+ (0, import_node_fs9.appendFileSync)(file, text);
17346
17444
  } catch {
17347
17445
  }
17348
17446
  }
@@ -17390,8 +17488,8 @@ function markerPath() {
17390
17488
  }
17391
17489
  function readMarker() {
17392
17490
  try {
17393
- if (!(0, import_node_fs9.existsSync)(markerPath())) return null;
17394
- const raw = JSON.parse((0, import_node_fs9.readFileSync)(markerPath(), "utf-8"));
17491
+ if (!(0, import_node_fs10.existsSync)(markerPath())) return null;
17492
+ const raw = JSON.parse((0, import_node_fs10.readFileSync)(markerPath(), "utf-8"));
17395
17493
  const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
17396
17494
  if (!pluginRoot || CONTROL_CHARS2.test(pluginRoot)) return null;
17397
17495
  const version = typeof raw.version === "string" && !CONTROL_CHARS2.test(raw.version) ? raw.version : null;
@@ -17409,23 +17507,23 @@ function recordPluginOwnership(sessionId) {
17409
17507
  const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
17410
17508
  if (!pluginRoot) return;
17411
17509
  try {
17412
- (0, import_node_fs9.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
17510
+ (0, import_node_fs10.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
17413
17511
  const marker = {
17414
17512
  session_id: sessionId,
17415
17513
  plugin_root: pluginRoot,
17416
17514
  version: process.env.VERITY_PLUGIN_VERSION || null,
17417
17515
  ts: Math.floor(Date.now() / 1e3)
17418
17516
  };
17419
- (0, import_node_fs9.writeFileSync)(markerPath(), JSON.stringify(marker));
17517
+ (0, import_node_fs10.writeFileSync)(markerPath(), JSON.stringify(marker));
17420
17518
  } catch {
17421
17519
  }
17422
17520
  }
17423
17521
  function claudeConfigDir() {
17424
- return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path10.join)((0, import_node_os2.homedir)(), ".claude");
17522
+ return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".claude");
17425
17523
  }
17426
17524
  function readJsonFile(path) {
17427
17525
  try {
17428
- const parsed = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf-8"));
17526
+ const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
17429
17527
  return parsed && typeof parsed === "object" ? parsed : null;
17430
17528
  } catch {
17431
17529
  return null;
@@ -17433,9 +17531,9 @@ function readJsonFile(path) {
17433
17531
  }
17434
17532
  function enabledPluginSetting(key) {
17435
17533
  const files = [
17436
- projectPath((0, import_node_path10.join)(".claude", "settings.local.json")),
17437
- projectPath((0, import_node_path10.join)(".claude", "settings.json")),
17438
- (0, import_node_path10.join)(claudeConfigDir(), "settings.json")
17534
+ projectPath((0, import_node_path11.join)(".claude", "settings.local.json")),
17535
+ projectPath((0, import_node_path11.join)(".claude", "settings.json")),
17536
+ (0, import_node_path11.join)(claudeConfigDir(), "settings.json")
17439
17537
  ];
17440
17538
  for (const file of files) {
17441
17539
  const map = readJsonFile(file)?.enabledPlugins;
@@ -17447,11 +17545,11 @@ function enabledPluginSetting(key) {
17447
17545
  }
17448
17546
  function marketplaceLocations() {
17449
17547
  const out2 = /* @__PURE__ */ new Map();
17450
- const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17548
+ const known = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17451
17549
  if (!known) return out2;
17452
17550
  for (const [name2, entry] of Object.entries(known)) {
17453
17551
  const loc2 = entry?.installLocation;
17454
- if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path10.resolve)(loc2));
17552
+ if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path11.resolve)(loc2));
17455
17553
  }
17456
17554
  return out2;
17457
17555
  }
@@ -17465,7 +17563,7 @@ function globalVerityVersion() {
17465
17563
  const entry = verityPathEntry();
17466
17564
  if (!entry) return null;
17467
17565
  try {
17468
- const pkg = readJsonFile((0, import_node_path10.join)((0, import_node_path10.dirname)((0, import_node_fs9.realpathSync)(entry)), "..", "package.json"));
17566
+ const pkg = readJsonFile((0, import_node_path11.join)((0, import_node_path11.dirname)((0, import_node_fs10.realpathSync)(entry)), "..", "package.json"));
17469
17567
  if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
17470
17568
  return pkg.version;
17471
17569
  } catch {
@@ -17482,7 +17580,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
17482
17580
  function marketplaceConflict() {
17483
17581
  const wanted = VERITY_MARKETPLACE;
17484
17582
  for (const file of ["settings.json", "settings.local.json"]) {
17485
- const path = (0, import_node_path10.join)(claudeConfigDir(), file);
17583
+ const path = (0, import_node_path11.join)(claudeConfigDir(), file);
17486
17584
  const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
17487
17585
  const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
17488
17586
  if (entry2 && typeof entry2 === "object") {
@@ -17492,7 +17590,7 @@ function marketplaceConflict() {
17492
17590
  }
17493
17591
  }
17494
17592
  }
17495
- const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17593
+ const known = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17496
17594
  const entry = known?.[wanted];
17497
17595
  if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
17498
17596
  return { name: wanted, declaredAs: describeSource(entry.source) };
@@ -17513,7 +17611,7 @@ function describeSource(src) {
17513
17611
  return target ? `${kind} \u2192 ${target}` : kind;
17514
17612
  }
17515
17613
  function legacyMarketplaceInstall() {
17516
- const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17614
+ const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17517
17615
  if (!plugins || typeof plugins !== "object") return null;
17518
17616
  for (const key of Object.keys(plugins)) {
17519
17617
  const at = key.lastIndexOf("@");
@@ -17525,13 +17623,13 @@ function legacyMarketplaceInstall() {
17525
17623
  }
17526
17624
  function realpathOr(p) {
17527
17625
  try {
17528
- return import_node_fs9.realpathSync.native(p);
17626
+ return import_node_fs10.realpathSync.native(p);
17529
17627
  } catch {
17530
- return (0, import_node_path10.resolve)(p);
17628
+ return (0, import_node_path11.resolve)(p);
17531
17629
  }
17532
17630
  }
17533
17631
  function isWithin(want, dir) {
17534
- return want === dir || want.startsWith(dir + import_node_path10.sep);
17632
+ return want === dir || want.startsWith(dir + import_node_path11.sep);
17535
17633
  }
17536
17634
  function entryAppliesHere(entry, here) {
17537
17635
  const e = entry;
@@ -17541,9 +17639,9 @@ function entryAppliesHere(entry, here) {
17541
17639
  return forProject === here;
17542
17640
  }
17543
17641
  function registrySays(pluginRoot) {
17544
- const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17642
+ const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17545
17643
  if (!plugins || typeof plugins !== "object") return "unverified";
17546
- const want = (0, import_node_path10.resolve)(pluginRoot);
17644
+ const want = (0, import_node_path11.resolve)(pluginRoot);
17547
17645
  const here = realpathOr(repoRoot());
17548
17646
  const markets = marketplaceLocations();
17549
17647
  for (const [key, value] of Object.entries(plugins)) {
@@ -17552,15 +17650,15 @@ function registrySays(pluginRoot) {
17552
17650
  const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
17553
17651
  const claims = applicable.some((entry) => {
17554
17652
  const installPath = entry?.installPath;
17555
- return typeof installPath === "string" && (0, import_node_path10.resolve)(installPath) === want;
17653
+ return typeof installPath === "string" && (0, import_node_path11.resolve)(installPath) === want;
17556
17654
  }) || source2 !== void 0 && applicable.length > 0 && isWithin(want, source2);
17557
17655
  if (claims) {
17558
17656
  if (enabledPluginSetting(key) === false) return "gone";
17559
- return (0, import_node_fs9.existsSync)(pluginRoot) ? "live" : "gone";
17657
+ return (0, import_node_fs10.existsSync)(pluginRoot) ? "live" : "gone";
17560
17658
  }
17561
17659
  }
17562
- const managed = (0, import_node_path10.resolve)((0, import_node_path10.join)(claudeConfigDir(), "plugins", "cache"));
17563
- return want === managed || want.startsWith(managed + import_node_path10.sep) ? "gone" : "unverified";
17660
+ const managed = (0, import_node_path11.resolve)((0, import_node_path11.join)(claudeConfigDir(), "plugins", "cache"));
17661
+ return want === managed || want.startsWith(managed + import_node_path11.sep) ? "gone" : "unverified";
17564
17662
  }
17565
17663
  var _live = /* @__PURE__ */ new Map();
17566
17664
  function pluginLiveness(pluginRoot) {
@@ -17574,7 +17672,7 @@ function clearStalePluginMarker() {
17574
17672
  const marker = readMarker();
17575
17673
  if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
17576
17674
  try {
17577
- (0, import_node_fs9.rmSync)(markerPath(), { force: true });
17675
+ (0, import_node_fs10.rmSync)(markerPath(), { force: true });
17578
17676
  } catch {
17579
17677
  return null;
17580
17678
  }
@@ -17602,7 +17700,7 @@ function pluginActiveHere() {
17602
17700
  return activePluginInstall() !== null;
17603
17701
  }
17604
17702
  function registeredVerityPlugin() {
17605
- const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17703
+ const plugins = readJsonFile((0, import_node_path11.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17606
17704
  if (!plugins || typeof plugins !== "object") return null;
17607
17705
  const here = realpathOr(repoRoot());
17608
17706
  for (const [key, value] of Object.entries(plugins)) {
@@ -17612,7 +17710,7 @@ function registeredVerityPlugin() {
17612
17710
  for (const entry of Array.isArray(value) ? value : []) {
17613
17711
  const e = entry;
17614
17712
  const installPath = typeof e.installPath === "string" ? e.installPath : "";
17615
- if (!installPath || !(0, import_node_fs9.existsSync)(installPath)) continue;
17713
+ if (!installPath || !(0, import_node_fs10.existsSync)(installPath)) continue;
17616
17714
  if (!entryAppliesHere(entry, here)) continue;
17617
17715
  return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
17618
17716
  }
@@ -17664,28 +17762,28 @@ async function resolveHookWiring() {
17664
17762
  }
17665
17763
 
17666
17764
  // src/lib/cli-provenance.ts
17667
- var import_node_fs10 = require("node:fs");
17668
- var import_node_os3 = require("node:os");
17669
- var import_node_path11 = require("node:path");
17765
+ var import_node_fs11 = require("node:fs");
17766
+ var import_node_os4 = require("node:os");
17767
+ var import_node_path12 = require("node:path");
17670
17768
  var CLI_PACKAGE = "@codacy/verity-cli";
17671
- var CLI_ENTRY = (0, import_node_path11.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
17769
+ var CLI_ENTRY = (0, import_node_path12.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
17672
17770
  function readJson(path) {
17673
17771
  try {
17674
- const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
17772
+ const parsed = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
17675
17773
  return parsed && typeof parsed === "object" ? parsed : null;
17676
17774
  } catch {
17677
17775
  return null;
17678
17776
  }
17679
17777
  }
17680
17778
  function versionUnder(base) {
17681
- const entry = (0, import_node_path11.join)(base, CLI_ENTRY);
17682
- if (!(0, import_node_fs10.existsSync)(entry)) return null;
17683
- const pkg = readJson((0, import_node_path11.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
17779
+ const entry = (0, import_node_path12.join)(base, CLI_ENTRY);
17780
+ if (!(0, import_node_fs11.existsSync)(entry)) return null;
17781
+ const pkg = readJson((0, import_node_path12.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
17684
17782
  return typeof pkg?.version === "string" ? pkg.version : null;
17685
17783
  }
17686
17784
  function versionForEntry(entry) {
17687
17785
  try {
17688
- const pkg = readJson((0, import_node_path11.join)((0, import_node_path11.dirname)((0, import_node_fs10.realpathSync)(entry)), "..", "package.json"));
17786
+ const pkg = readJson((0, import_node_path12.join)((0, import_node_path12.dirname)((0, import_node_fs11.realpathSync)(entry)), "..", "package.json"));
17689
17787
  return typeof pkg?.version === "string" ? pkg.version : null;
17690
17788
  } catch {
17691
17789
  return null;
@@ -17693,16 +17791,16 @@ function versionForEntry(entry) {
17693
17791
  }
17694
17792
  function resolveHooksCli(pluginRoot) {
17695
17793
  const override = process.env.VERITY_CLI_PATH;
17696
- if (override && (0, import_node_fs10.existsSync)(override)) {
17794
+ if (override && (0, import_node_fs11.existsSync)(override)) {
17697
17795
  return { version: versionForEntry(override), rung: "override" };
17698
17796
  }
17699
17797
  const fromPlugin = versionUnder(pluginRoot);
17700
17798
  if (fromPlugin !== null) return { version: fromPlugin, rung: "plugin" };
17701
- if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
17702
- const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".verity", "plugin-cli");
17799
+ if ((0, import_node_fs11.existsSync)((0, import_node_path12.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
17800
+ const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity", "plugin-cli");
17703
17801
  const fromData = versionUnder(dataDir);
17704
17802
  if (fromData !== null) return { version: fromData, rung: "plugin-data" };
17705
- if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
17803
+ if ((0, import_node_fs11.existsSync)((0, import_node_path12.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
17706
17804
  const global = globalVerityVersion();
17707
17805
  if (global !== null) return { version: global, rung: "global" };
17708
17806
  return null;
@@ -17804,7 +17902,7 @@ function pluginCliInvocation() {
17804
17902
  return resolverCommand(root);
17805
17903
  }
17806
17904
  function resolverCommand(root) {
17807
- return `node ${JSON.stringify((0, import_node_path11.join)(root, "scripts", "verity.mjs"))}`;
17905
+ return `node ${JSON.stringify((0, import_node_path12.join)(root, "scripts", "verity.mjs"))}`;
17808
17906
  }
17809
17907
 
17810
17908
  // src/commands/hooks.ts
@@ -17940,18 +18038,18 @@ function registerHooksCommands(program2) {
17940
18038
  }
17941
18039
 
17942
18040
  // src/commands/intent.ts
17943
- var import_node_crypto9 = require("node:crypto");
18041
+ var import_node_crypto10 = require("node:crypto");
17944
18042
 
17945
18043
  // src/lib/conversation-buffer.ts
17946
18044
  var import_promises5 = require("node:fs/promises");
17947
- var import_node_fs11 = require("node:fs");
18045
+ var import_node_fs12 = require("node:fs");
17948
18046
  var import_node_child_process6 = require("node:child_process");
17949
- var import_node_crypto = require("node:crypto");
18047
+ var import_node_crypto2 = require("node:crypto");
17950
18048
  function stripImageReferences(text) {
17951
18049
  return text.replace(/\[Image #\d+\]/g, "[screenshot \u2014 not available for review]");
17952
18050
  }
17953
18051
  function bufferTmpPath() {
17954
- return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto.randomBytes)(4).toString("hex")}.tmp`;
18052
+ return `${CONVERSATION_BUFFER_FILE}.${process.pid}.${(0, import_node_crypto2.randomBytes)(4).toString("hex")}.tmp`;
17955
18053
  }
17956
18054
  async function appendToConversationBuffer(prompt, sessionId) {
17957
18055
  try {
@@ -17980,7 +18078,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
17980
18078
  }
17981
18079
  async function readAndClearConversationBuffer(currentSessionId) {
17982
18080
  try {
17983
- if ((0, import_node_fs11.existsSync)(CONVERSATION_BUFFER_FILE)) {
18081
+ if ((0, import_node_fs12.existsSync)(CONVERSATION_BUFFER_FILE)) {
17984
18082
  const entries = await readBufferEntries();
17985
18083
  let mine = entries;
17986
18084
  let others = [];
@@ -18004,7 +18102,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
18004
18102
  };
18005
18103
  }
18006
18104
  }
18007
- if ((0, import_node_fs11.existsSync)(INTENT_FILE)) {
18105
+ if ((0, import_node_fs12.existsSync)(INTENT_FILE)) {
18008
18106
  try {
18009
18107
  const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
18010
18108
  await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
@@ -18295,83 +18393,6 @@ function isCommandOnlyTurn(input) {
18295
18393
  return commands.every(isNonAuthoringCommand);
18296
18394
  }
18297
18395
 
18298
- // src/lib/context-identity.ts
18299
- var import_node_crypto2 = require("node:crypto");
18300
- var import_node_fs12 = require("node:fs");
18301
- var import_node_os4 = require("node:os");
18302
- var import_node_path12 = require("node:path");
18303
- var SHARED_SENTINELS = /* @__PURE__ */ new Set([
18304
- "",
18305
- "-",
18306
- "n/a",
18307
- "na",
18308
- "none",
18309
- "null",
18310
- "undefined",
18311
- "unknown",
18312
- "anon",
18313
- "anonymous",
18314
- "default",
18315
- "_default"
18316
- ]);
18317
- function isSharedSentinel(value) {
18318
- if (value == null) return true;
18319
- return SHARED_SENTINELS.has(value.trim().toLowerCase());
18320
- }
18321
- var ephemeral = /* @__PURE__ */ new Map();
18322
- function ephemeralId(slot, width) {
18323
- let id = ephemeral.get(slot);
18324
- if (!id) {
18325
- id = `eph-${(0, import_node_crypto2.randomBytes)(Math.ceil(width / 2)).toString("hex").slice(0, width - 4)}`;
18326
- ephemeral.set(slot, id);
18327
- }
18328
- return id;
18329
- }
18330
- function contextIdentity(input) {
18331
- const tokenUsable = !isSharedSentinel(input.token ?? null);
18332
- const sessionUsable = !isSharedSentinel(input.sessionId ?? null);
18333
- const userKey = tokenUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.token)).digest("hex").slice(0, 12) : ephemeralId("user", 12);
18334
- const sessionKey2 = sessionUsable ? (0, import_node_crypto2.createHash)("sha256").update(String(input.sessionId)).digest("hex").slice(0, 16) : ephemeralId("session", 16);
18335
- let treeKey = "no-tree";
18336
- const rawTree = input.treeRoot;
18337
- if (rawTree && !isSharedSentinel(rawTree)) {
18338
- let resolved = rawTree;
18339
- try {
18340
- resolved = import_node_fs12.realpathSync.native(rawTree);
18341
- } catch {
18342
- }
18343
- treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
18344
- }
18345
- return {
18346
- userKey,
18347
- treeKey,
18348
- sessionKey: sessionKey2,
18349
- userKeySource: tokenUsable ? "token" : "ephemeral",
18350
- sessionKeySource: sessionUsable ? "session_id" : "ephemeral",
18351
- ephemeral: !tokenUsable || !sessionUsable
18352
- };
18353
- }
18354
- function verityHome() {
18355
- const override = process.env.VERITY_HOME;
18356
- return override && override.trim() ? (0, import_node_path12.resolve)(override) : (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity");
18357
- }
18358
- function dossierDir(identity) {
18359
- return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
18360
- }
18361
- function treeDir(identity) {
18362
- return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
18363
- }
18364
- function scopeIdentity(token, sessionId) {
18365
- const t = (token ?? "").trim();
18366
- const s = (sessionId ?? "").trim();
18367
- const userKey = t.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(t).digest("hex").slice(0, 12) : "anon";
18368
- const sessionKey2 = s.length > 0 ? (0, import_node_crypto2.createHash)("sha256").update(s).digest("hex").slice(0, 16) : "_default";
18369
- return { userKey, sessionKey: sessionKey2, bucket: `${userKey}/${sessionKey2}` };
18370
- }
18371
- function sessionScopeKey(token, sessionId) {
18372
- return scopeIdentity(token, sessionId).bucket;
18373
- }
18374
-
18375
18396
  // src/lib/task-context-buffer.ts
18376
18397
  var import_promises6 = require("node:fs/promises");
18377
18398
  var import_node_fs13 = require("node:fs");
@@ -20037,6 +20058,97 @@ var LEGACY_MD_END = "<!-- gate-memory:end -->";
20037
20058
  var LEGACY_PRESERVE_START = "<!-- gate-memory:preserve -->";
20038
20059
  var LEGACY_PRESERVE_END = "<!-- /gate-memory:preserve -->";
20039
20060
  var CLAUDE_MD_PROSE = [
20061
+ "## Project Memory",
20062
+ "",
20063
+ "This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
20064
+ "non-trivial work, scan `.verity/memory/index.md` for decisions, gotchas, and patterns",
20065
+ "that may apply to the change you are about to make. Open specific node files via",
20066
+ "the Read tool when the title or scope suggests relevance.",
20067
+ "",
20068
+ "The graph is auto-maintained by Verity. Files at `.verity/memory/_archive/` are",
20069
+ "superseded \u2014 ignore them unless investigating history.",
20070
+ "",
20071
+ "Knowledge the organization's other repositories learned is mirrored outside the",
20072
+ "repo at `~/.verity/orgs/<host>/<owner>/memory/` (`verity memory org` lists it).",
20073
+ "Each claim says where it came from; one that is wrong here is demoted for",
20074
+ 'everyone with `verity memory demote <id> --reason "\u2026"`.',
20075
+ "",
20076
+ "## Quality gate: accepted risks",
20077
+ "",
20078
+ "When the Verity pre-commit/pre-push gate FAILs, fix the findings \u2014 that is the",
20079
+ 'default. Use `verity waive <pattern-id> --file <path> --reason "\u2026"` ONLY to relay',
20080
+ "a risk a human has explicitly accepted: a named code-review finding, an ADR, or",
20081
+ "the user saying so in this conversation. The --reason must cite that source.",
20082
+ "",
20083
+ "Never waive on your own judgment, to get past a block, or pre-emptively. A waive",
20084
+ "binds to the file's current bytes and voids automatically when the file changes,",
20085
+ "and every waive is recorded in the run ledger. For a pattern-level false positive",
20086
+ "use `verity feedback finding <run-id> <pattern-id> false_positive` instead.",
20087
+ "",
20088
+ "## Post-task reflection",
20089
+ "",
20090
+ `When a task is complete (you've created a PR, the user says "done" or "ship it",`,
20091
+ "or the work is clearly finished), **draft the reflection yourself** \u2014 1\u20133",
20092
+ "concrete things worth remembering (a decision, a gotcha, or a pattern), each",
20093
+ "cited with the files / PR / commands / error-signatures it came from. Skip",
20094
+ "entirely if nothing non-obvious happened \u2014 that judgement is the ONLY filter,",
20095
+ "because nothing reviews the reflection before it lands.",
20096
+ "",
20097
+ "Then record it straight away. There is no confirm step, in any environment:",
20098
+ "",
20099
+ "```bash",
20100
+ "verity reflect --user-input - --kind <kind> <<'VERITY_EOF_<random>'",
20101
+ "<your draft>",
20102
+ "VERITY_EOF_<random>",
20103
+ "```",
20104
+ "",
20105
+ 'The draft goes through the quoted heredoc, never inside `"\u2026"` on the command',
20106
+ 'line, where a `"` or `$(\u2026)` in it would run in the shell. Replace `<random>`',
20107
+ "with 8 random letters and digits that you pick for this call, the same at both",
20108
+ "ends. Text written before you picked them cannot end the heredoc early.",
20109
+ "",
20110
+ "Add `--confirmed` ONLY when the user authored or dictated the words. Without",
20111
+ "it the node is stored as `source: agent` \u2014 Verity thought this, nobody checked",
20112
+ "it. With it, `source: user` at full confidence \u2014 a person stands behind this.",
20113
+ "Never claim the second for your own draft, however good it is.",
20114
+ "",
20115
+ "**Name the files in the text.** Verity scopes the reflection to the paths it",
20116
+ "cites, and a reflection that names no file in this repo is never retrieved for",
20117
+ "a later review \u2014 it is recorded and then invisible. The command says so when it",
20118
+ "happens; `--file-globs '<path or glob>'` is the fix when the prose cannot carry",
20119
+ "the paths.",
20120
+ "",
20121
+ "Then tell the user, in one line, what you recorded and where: the command",
20122
+ "prints the node id, the path under `.verity/memory/`, and a dashboard link.",
20123
+ "They did not agree to it in advance, so say it happened \u2014 editing or deleting",
20124
+ "that file is how they correct it.",
20125
+ "",
20126
+ "> Durable, hand-curated guidance goes in the preserve region below (it survives",
20127
+ "> regeneration) or anywhere OUTSIDE these markers. Everything else between the",
20128
+ "> markers is tool-owned and overwritten on each run.",
20129
+ "",
20130
+ "## Housekeeping Turns",
20131
+ "",
20132
+ "When a turn will be pure housekeeping \u2014 pulling, installing dependencies,",
20133
+ "rebasing, a formatting sweep you are not authoring \u2014 declare it BEFORE doing it:",
20134
+ "",
20135
+ "```bash",
20136
+ 'verity ignore --turn --agent --reason "pulling latest before starting"',
20137
+ "```",
20138
+ "",
20139
+ "This skips the review for that turn, which saves the turn Verity would",
20140
+ "otherwise spend saying it had nothing to say. Use `--for 30m` instead of",
20141
+ "`--turn` when a single piece of housekeeping spans several turns.",
20142
+ "",
20143
+ "**It is a claim about the turn, not a way to silence review.** The declaration",
20144
+ "is checked against what the turn actually did: if anything is authored \u2014 by you,",
20145
+ "by a subagent, or by a shell command that can write files \u2014 it voids, the review",
20146
+ "runs anyway, and the broken declaration is reported. So declare housekeeping you",
20147
+ "are about to do, never work you have already done, and never as a way to get past",
20148
+ "a finding. Declarations are budgeted per session and every one is recorded with",
20149
+ "its reason."
20150
+ ].join("\n");
20151
+ var CLAUDE_MD_PROSE_PRE_STDIN = [
20040
20152
  "## Project Memory",
20041
20153
  "",
20042
20154
  "This project has a knowledge graph maintained at `.verity/memory/`. Before starting",
@@ -20478,6 +20590,7 @@ function stripKnownProse(interior) {
20478
20590
  const trimmed = interior.replace(/^\n+/, "");
20479
20591
  for (const prose of [
20480
20592
  CLAUDE_MD_PROSE,
20593
+ CLAUDE_MD_PROSE_PRE_STDIN,
20481
20594
  CLAUDE_MD_PROSE_PRE_ORG,
20482
20595
  CLAUDE_MD_PROSE_PRE_AUTORECORD,
20483
20596
  CLAUDE_MD_PROSE_PRE_REFLECT,
@@ -20544,7 +20657,7 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
20544
20657
 
20545
20658
  // src/lib/dossier-session.ts
20546
20659
  var import_node_fs26 = require("node:fs");
20547
- var import_node_crypto8 = require("node:crypto");
20660
+ var import_node_crypto9 = require("node:crypto");
20548
20661
  var import_node_path22 = require("node:path");
20549
20662
 
20550
20663
  // src/lib/pending-repeat.ts
@@ -20621,6 +20734,7 @@ function isRepeatOfAny(text, priorFingerprints, threshold = REPEAT_THRESHOLD) {
20621
20734
  }
20622
20735
 
20623
20736
  // src/lib/dossier/bounds.ts
20737
+ var import_node_crypto5 = require("node:crypto");
20624
20738
  var MAX_LINE_BYTES = 4096;
20625
20739
  var MAX_GOAL_CHARS = 2e3;
20626
20740
  var GOAL_KEEP = 8;
@@ -20632,10 +20746,17 @@ var NOT_MINE_CAP = 300;
20632
20746
  var STATEMENTS_OPEN_CAP = 40;
20633
20747
  var COMMANDS_CAP = 12;
20634
20748
  var DIVERGENCE_CAP = 10;
20635
- var DIVERGENCE_SEEN_CAP = 300;
20749
+ var DIVERGENCE_BULK_AT = 300;
20750
+ var DIVERGENCE_KEYS_PER_LINE = 200;
20636
20751
  function divergenceKey(path, hash) {
20637
20752
  return `${path}@${hash ?? "unknown"}`;
20638
20753
  }
20754
+ function packedDivergenceDigest(key) {
20755
+ return (0, import_node_crypto5.createHash)("sha256").update(key).digest("hex").slice(0, 12);
20756
+ }
20757
+ function packedDivergenceKey(digest) {
20758
+ return `#${digest}`;
20759
+ }
20639
20760
  var MARKS_CAP = 50;
20640
20761
  var ROTATE_BYTES = 1048576;
20641
20762
  var ROTATE_KEEP = 2;
@@ -20649,7 +20770,7 @@ function statementAnchorKey(file, patternId) {
20649
20770
  }
20650
20771
 
20651
20772
  // src/lib/dossier/log.ts
20652
- var import_node_crypto5 = require("node:crypto");
20773
+ var import_node_crypto6 = require("node:crypto");
20653
20774
  var import_node_fs22 = require("node:fs");
20654
20775
  var import_node_path20 = require("node:path");
20655
20776
  var CRC_TABLE = (() => {
@@ -20691,7 +20812,7 @@ function nextSeq() {
20691
20812
  function encodeEvent(ev) {
20692
20813
  const full = {
20693
20814
  v: 1,
20694
- id: (0, import_node_crypto5.randomBytes)(4).toString("hex"),
20815
+ id: (0, import_node_crypto6.randomBytes)(4).toString("hex"),
20695
20816
  ...ev
20696
20817
  };
20697
20818
  let body2 = JSON.stringify(full);
@@ -20762,7 +20883,7 @@ function rotateIfNeeded2(d) {
20762
20883
  }
20763
20884
 
20764
20885
  // src/lib/dossier/fold-dossier.ts
20765
- var import_node_crypto6 = require("node:crypto");
20886
+ var import_node_crypto7 = require("node:crypto");
20766
20887
  var import_node_fs23 = require("node:fs");
20767
20888
  var import_node_path21 = require("node:path");
20768
20889
  var EMPTY_CAPABILITIES = () => ({
@@ -20854,7 +20975,7 @@ function reduce(state, events, now) {
20854
20975
  state.meta.seq = Math.max(state.meta.seq, ev.seq);
20855
20976
  switch (ev.k) {
20856
20977
  case "goal": {
20857
- const hash = (0, import_node_crypto6.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
20978
+ const hash = (0, import_node_crypto7.createHash)("sha256").update(ev.text).digest("hex").slice(0, 16);
20858
20979
  const prev = state.goal[state.goal.length - 1];
20859
20980
  if (prev && prev.hash === hash) {
20860
20981
  prev.repeats = (prev.repeats ?? 0) + 1;
@@ -20982,12 +21103,13 @@ function reduce(state, events, now) {
20982
21103
  break;
20983
21104
  }
20984
21105
  case "divergence": {
20985
- state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
20986
21106
  state.divergence.events.push({ kind: ev.kind, path: ev.path, at: ev.at });
20987
- const key = divergenceKey(ev.path, ev.hash ?? null);
20988
- if (!seenDivergence.has(key)) {
21107
+ const keys = Array.isArray(ev.keys) ? ev.keys.filter((k) => typeof k === "string").map(packedDivergenceKey) : [divergenceKey(ev.path, ev.hash ?? null)];
21108
+ for (const key of keys) {
21109
+ if (seenDivergence.has(key)) continue;
20989
21110
  seenDivergence.add(key);
20990
- if (state.divergence.seen.length < DIVERGENCE_SEEN_CAP) state.divergence.seen.push(key);
21111
+ state.divergence.seen.push(key);
21112
+ state.divergence.counts[ev.kind] = (state.divergence.counts[ev.kind] ?? 0) + 1;
20991
21113
  }
20992
21114
  break;
20993
21115
  }
@@ -21294,14 +21416,14 @@ function assessContinuity(i2) {
21294
21416
  }
21295
21417
 
21296
21418
  // src/lib/dossier/reanchor.ts
21297
- var import_node_crypto7 = require("node:crypto");
21419
+ var import_node_crypto8 = require("node:crypto");
21298
21420
  var import_node_fs25 = require("node:fs");
21299
21421
  function lineSha(text) {
21300
- return (0, import_node_crypto7.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21422
+ return (0, import_node_crypto8.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21301
21423
  }
21302
21424
  function fileHash(path) {
21303
21425
  try {
21304
- return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21426
+ return (0, import_node_crypto8.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21305
21427
  } catch {
21306
21428
  return null;
21307
21429
  }
@@ -21798,7 +21920,7 @@ function recordTurn(d, t) {
21798
21920
  // Identity is the COMMAND, not its category — otherwise `npm test -- a` and
21799
21921
  // `npm test -- b` are one row and the streak counts two different commands
21800
21922
  // as a run of one.
21801
- cmd_hash: (0, import_node_crypto8.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
21923
+ cmd_hash: (0, import_node_crypto9.createHash)("sha256").update(c.head || c.class).digest("hex").slice(0, 12),
21802
21924
  head: c.head || c.class,
21803
21925
  status: toStatus(c.last_status)
21804
21926
  });
@@ -21816,10 +21938,23 @@ function recordTurn(d, t) {
21816
21938
  }
21817
21939
  }
21818
21940
  const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
21941
+ const fresh = [];
21819
21942
  for (const u of t.unobserved) {
21820
21943
  const hash = fileHash((0, import_node_path22.join)(root, u.p));
21821
- if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
21822
- appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
21944
+ const key = divergenceKey(u.p, hash);
21945
+ const digest = packedDivergenceDigest(key);
21946
+ if (seenDivergence.has(key) || seenDivergence.has(packedDivergenceKey(digest))) continue;
21947
+ fresh.push({ path: u.p, hash, digest });
21948
+ }
21949
+ if (fresh.length > DIVERGENCE_BULK_AT) {
21950
+ for (let i2 = 0; i2 < fresh.length; i2 += DIVERGENCE_KEYS_PER_LINE) {
21951
+ const slice2 = fresh.slice(i2, i2 + DIVERGENCE_KEYS_PER_LINE);
21952
+ appendEvent(d, { k: "divergence", kind: "external_mutation", path: slice2[0].path, keys: slice2.map((f) => f.digest) });
21953
+ }
21954
+ } else {
21955
+ for (const f of fresh) {
21956
+ appendEvent(d, { k: "divergence", kind: "external_mutation", path: f.path, hash: f.hash });
21957
+ }
21823
21958
  }
21824
21959
  const newCompactions = (t.compactions ?? 0) - (t.known?.compactions ?? 0);
21825
21960
  for (let i2 = 0; i2 < newCompactions; i2++) {
@@ -22084,7 +22219,7 @@ async function fireClassify(prompt, sessionId, globals) {
22084
22219
  logEvent("classify_skipped", { reason: "no_service_url", detail: urlResult.error });
22085
22220
  return;
22086
22221
  }
22087
- const promptHash = (0, import_node_crypto9.createHash)("sha256").update(prompt).digest("hex");
22222
+ const promptHash = (0, import_node_crypto10.createHash)("sha256").update(prompt).digest("hex");
22088
22223
  const result = await apiRequest({
22089
22224
  method: "POST",
22090
22225
  path: "/classify-task",
@@ -22128,7 +22263,7 @@ var import_node_path26 = require("node:path");
22128
22263
  // src/lib/baseline.ts
22129
22264
  var import_node_fs28 = require("node:fs");
22130
22265
  var import_node_path25 = require("node:path");
22131
- var import_node_crypto10 = require("node:crypto");
22266
+ var import_node_crypto11 = require("node:crypto");
22132
22267
 
22133
22268
  // src/lib/snapshot.ts
22134
22269
  var import_node_fs27 = require("node:fs");
@@ -22397,7 +22532,7 @@ var MIRROR_MAX_BYTES = 2 * 1024 * 1024;
22397
22532
  var DEFAULT_SESSION_KEY = "_default";
22398
22533
  function sessionKey(sessionId) {
22399
22534
  if (!sessionId) return DEFAULT_SESSION_KEY;
22400
- return (0, import_node_crypto10.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
22535
+ return (0, import_node_crypto11.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
22401
22536
  }
22402
22537
  function sessionDir(key) {
22403
22538
  return (0, import_node_path25.join)(projectPath(BASELINE_DIR), key);
@@ -22859,17 +22994,17 @@ async function readHookStdin() {
22859
22994
  try {
22860
22995
  if (process.stdin.isTTY) return {};
22861
22996
  const chunks = [];
22862
- const timeout = new Promise((resolve8) => setTimeout(() => resolve8({}), 500));
22863
- const read2 = new Promise((resolve8) => {
22997
+ const timeout = new Promise((resolve9) => setTimeout(() => resolve9({}), 500));
22998
+ const read2 = new Promise((resolve9) => {
22864
22999
  process.stdin.on("data", (c) => chunks.push(c));
22865
23000
  process.stdin.on("end", () => {
22866
23001
  try {
22867
- resolve8(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
23002
+ resolve9(JSON.parse(Buffer.concat(chunks).toString("utf-8").trim() || "{}"));
22868
23003
  } catch {
22869
- resolve8({});
23004
+ resolve9({});
22870
23005
  }
22871
23006
  });
22872
- process.stdin.on("error", () => resolve8({}));
23007
+ process.stdin.on("error", () => resolve9({}));
22873
23008
  process.stdin.resume();
22874
23009
  });
22875
23010
  return await Promise.race([read2, timeout]);
@@ -22965,7 +23100,7 @@ function isIgnored2(path) {
22965
23100
  }
22966
23101
  function listProjectFiles(root) {
22967
23102
  try {
22968
- const out2 = (0, import_node_child_process9.execSync)("git ls-files -z", {
23103
+ const out2 = (0, import_node_child_process9.execSync)("git ls-files -z --cached --others --exclude-standard", {
22969
23104
  cwd: root,
22970
23105
  encoding: "utf-8",
22971
23106
  maxBuffer: 32 * 1024 * 1024,
@@ -24317,10 +24452,10 @@ var import_node_fs38 = require("node:fs");
24317
24452
 
24318
24453
  // src/lib/debounce.ts
24319
24454
  var import_node_fs37 = require("node:fs");
24320
- var import_node_crypto11 = require("node:crypto");
24455
+ var import_node_crypto12 = require("node:crypto");
24321
24456
  function scopedFile(base, sessionId) {
24322
24457
  if (!sessionId) return base;
24323
- return `${base}.${(0, import_node_crypto11.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
24458
+ return `${base}.${(0, import_node_crypto12.createHash)("sha1").update(sessionId).digest("hex").slice(0, 12)}`;
24324
24459
  }
24325
24460
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
24326
24461
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
@@ -24361,7 +24496,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
24361
24496
  return "No files modified since last analysis";
24362
24497
  }
24363
24498
  function computeContentHash(files) {
24364
- const hash = (0, import_node_crypto11.createHash)("sha1");
24499
+ const hash = (0, import_node_crypto12.createHash)("sha1");
24365
24500
  const sorted = [...files].sort();
24366
24501
  for (const f of sorted) {
24367
24502
  const resolved = resolveFile(f) ?? f;
@@ -24817,20 +24952,56 @@ function registerStatusCommand(program2) {
24817
24952
  });
24818
24953
  }
24819
24954
 
24955
+ // src/lib/text-input.ts
24956
+ var import_node_fs39 = require("node:fs");
24957
+ var MAX_STDIN_BYTES = 64 * 1024;
24958
+ function readTextInput(value, flag, readStdin2 = () => (0, import_node_fs39.readFileSync)(0)) {
24959
+ if (value !== "-") return { ok: true, text: value };
24960
+ let raw;
24961
+ try {
24962
+ raw = readStdin2();
24963
+ } catch (err2) {
24964
+ return { ok: false, error: `Could not read ${flag} from stdin: ${err2.message}` };
24965
+ }
24966
+ if (raw.length > MAX_STDIN_BYTES) {
24967
+ return { ok: false, error: `${flag} from stdin is ${raw.length} bytes; the limit is ${MAX_STDIN_BYTES}.` };
24968
+ }
24969
+ const text = raw.toString("utf8").replace(/\r?\n$/, "");
24970
+ if (!text.trim()) return { ok: false, error: `${flag} from stdin is empty.` };
24971
+ return { ok: true, text };
24972
+ }
24973
+
24974
+ // src/lib/terminal-text.ts
24975
+ var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
24976
+ function terminalText(value, max = 4e3) {
24977
+ if (typeof value !== "string") return "";
24978
+ const clean2 = value.replace(CONTROL, "");
24979
+ return clean2.length > max ? `${clean2.slice(0, max - 1)}\u2026` : clean2;
24980
+ }
24981
+ function terminalUrl(value) {
24982
+ const clean2 = terminalText(value, 2e3);
24983
+ return /^https?:\/\/\S+$/.test(clean2) ? clean2 : "";
24984
+ }
24985
+
24820
24986
  // src/commands/feedback.ts
24821
24987
  function registerFeedbackCommand(program2) {
24822
24988
  const feedbackCmd = program2.command("feedback").description("Send feedback to the Verity team");
24823
- feedbackCmd.command("message <text>").description("Send general feedback").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (message, opts) => {
24824
- const globals = program2.opts();
24825
- await sendGeneralFeedback(message, opts, globals);
24989
+ feedbackCmd.command("message <text>").description("Send general feedback (- reads the message from stdin, so the words never pass through shell quoting)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (text, opts) => {
24990
+ await sendMessageArg(text, opts, program2.opts());
24826
24991
  });
24827
- feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.)").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action, note, opts) => {
24992
+ feedbackCmd.command("finding <run-id> <pattern-id> <action> [note]").description("Submit per-finding feedback (false_positive, acknowledged, useful, etc.); a note of - is read from stdin").option("--file <path>", "File path the finding applies to").option("--line <n>", "Line number", parseInt).action(async (runId, patternId, action, inlineNote, opts) => {
24828
24993
  const globals = program2.opts();
24829
24994
  const validActions = ["false_positive", "acknowledged", "will_fix_later", "wrong_severity", "useful"];
24830
24995
  if (!validActions.includes(action)) {
24831
24996
  printError(`Invalid action "${action}". Must be one of: ${validActions.join(", ")}`);
24832
24997
  process.exit(1);
24833
24998
  }
24999
+ const noteInput = readTextInput(inlineNote, "the note");
25000
+ if (!noteInput.ok) {
25001
+ printError(noteInput.error);
25002
+ process.exit(1);
25003
+ }
25004
+ const note = noteInput.text;
24834
25005
  const tokenResult = await resolveToken(globals.token);
24835
25006
  if (!tokenResult.ok) {
24836
25007
  printError(tokenResult.error);
@@ -24866,21 +25037,28 @@ function registerFeedbackCommand(program2) {
24866
25037
  });
24867
25038
  feedbackCmd.argument("[message]", "Feedback message (for backwards compat)").option("--session-id <id>", "Session identifier").option("--model <name>", "Agent model name").action(async (message, opts) => {
24868
25039
  if (!message) return;
24869
- const globals = program2.opts();
24870
- await sendGeneralFeedback(message, opts, globals);
25040
+ await sendMessageArg(message, opts, program2.opts());
24871
25041
  });
24872
25042
  }
25043
+ async function sendMessageArg(arg, opts, globals) {
25044
+ const input = readTextInput(arg, "the message");
25045
+ if (!input.ok || !input.text) {
25046
+ printError(input.ok ? "Nothing to send." : input.error);
25047
+ process.exit(1);
25048
+ }
25049
+ await sendGeneralFeedback(input.text, opts, globals);
25050
+ }
24873
25051
  async function sendGeneralFeedback(message, opts, globals) {
24874
25052
  const tokenResult = await resolveToken(globals.token);
24875
25053
  if (!tokenResult.ok) {
24876
25054
  printError(tokenResult.error);
24877
- printInfo(`Your message: ${message}`);
25055
+ printInfo(`Your message: ${terminalText(message, message.length)}`);
24878
25056
  process.exit(1);
24879
25057
  }
24880
25058
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
24881
25059
  if (!urlResult.ok) {
24882
25060
  printError(urlResult.error);
24883
- printInfo(`Your message: ${message}`);
25061
+ printInfo(`Your message: ${terminalText(message, message.length)}`);
24884
25062
  process.exit(1);
24885
25063
  }
24886
25064
  const body2 = { message };
@@ -24898,7 +25076,7 @@ async function sendGeneralFeedback(message, opts, globals) {
24898
25076
  });
24899
25077
  if (!result.ok) {
24900
25078
  printError(`Couldn't send feedback: ${result.error}`);
24901
- printInfo(`Your message: ${message}`);
25079
+ printInfo(`Your message: ${terminalText(message, message.length)}`);
24902
25080
  process.exit(1);
24903
25081
  }
24904
25082
  printInfo("Thanks, feedback sent!");
@@ -24983,7 +25161,8 @@ function createRun(opts, globals) {
24983
25161
  }
24984
25162
 
24985
25163
  // src/commands/analyze/index.ts
24986
- var import_node_fs52 = require("node:fs");
25164
+ var import_node_fs53 = require("node:fs");
25165
+ var import_node_path40 = require("node:path");
24987
25166
 
24988
25167
  // src/lib/repo-context.ts
24989
25168
  var import_node_child_process11 = require("node:child_process");
@@ -25947,7 +26126,7 @@ function installRunEvidence(run4) {
25947
26126
  }
25948
26127
 
25949
26128
  // src/lib/git-frame.ts
25950
- var import_node_fs39 = require("node:fs");
26129
+ var import_node_fs40 = require("node:fs");
25951
26130
  var import_node_os6 = require("node:os");
25952
26131
  var import_node_path30 = require("node:path");
25953
26132
  var import_node_path31 = require("node:path");
@@ -26117,14 +26296,14 @@ function gitAt(dir, args2) {
26117
26296
  }
26118
26297
  function realpathOr2(p) {
26119
26298
  try {
26120
- return import_node_fs39.realpathSync.native(p);
26299
+ return import_node_fs40.realpathSync.native(p);
26121
26300
  } catch {
26122
26301
  return (0, import_node_path30.resolve)(p);
26123
26302
  }
26124
26303
  }
26125
26304
  function resolveFrame(input) {
26126
26305
  const found = findMomentSegment(input.command, input.on);
26127
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs39.existsSync)(input.hookCwd);
26306
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs40.existsSync)(input.hookCwd);
26128
26307
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
26129
26308
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
26130
26309
  const refuse = (refusal) => ({
@@ -26147,7 +26326,7 @@ function resolveFrame(input) {
26147
26326
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
26148
26327
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
26149
26328
  if (targetDir !== baseDir) {
26150
- if (!(0, import_node_fs39.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26329
+ if (!(0, import_node_fs40.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26151
26330
  dir = targetDir;
26152
26331
  }
26153
26332
  }
@@ -26334,7 +26513,7 @@ function stagedRange(frame, command) {
26334
26513
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
26335
26514
  }
26336
26515
  const mergeHead = frame.gitDir ? (0, import_node_path31.join)(frame.gitDir, "MERGE_HEAD") : null;
26337
- if (mergeHead && (0, import_node_fs39.existsSync)(mergeHead)) {
26516
+ if (mergeHead && (0, import_node_fs40.existsSync)(mergeHead)) {
26338
26517
  const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
26339
26518
  const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
26340
26519
  const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
@@ -26468,7 +26647,7 @@ function truthy(v) {
26468
26647
  }
26469
26648
 
26470
26649
  // src/lib/transcript.ts
26471
- var import_node_fs40 = require("node:fs");
26650
+ var import_node_fs41 = require("node:fs");
26472
26651
  var MAX_READ_BYTES = 256 * 1024;
26473
26652
  var SMALL_FILE_BYTES = 64 * 1024;
26474
26653
  var MAX_FILES_LIST = 20;
@@ -26495,7 +26674,7 @@ async function extractActionSummary(transcriptPath) {
26495
26674
  function readTurnLines(transcriptPath) {
26496
26675
  let size;
26497
26676
  try {
26498
- size = (0, import_node_fs40.statSync)(transcriptPath).size;
26677
+ size = (0, import_node_fs41.statSync)(transcriptPath).size;
26499
26678
  } catch {
26500
26679
  return null;
26501
26680
  }
@@ -26503,7 +26682,7 @@ function readTurnLines(transcriptPath) {
26503
26682
  let raw;
26504
26683
  let windowed = false;
26505
26684
  if (size <= SMALL_FILE_BYTES) {
26506
- raw = (0, import_node_fs40.readFileSync)(transcriptPath, "utf-8");
26685
+ raw = (0, import_node_fs41.readFileSync)(transcriptPath, "utf-8");
26507
26686
  } else {
26508
26687
  windowed = true;
26509
26688
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -26786,28 +26965,28 @@ async function readStopHookStdin() {
26786
26965
  try {
26787
26966
  if (process.stdin.isTTY) return empty;
26788
26967
  const chunks = [];
26789
- const timeout = new Promise((resolve8) => setTimeout(() => resolve8(empty), 500));
26790
- const read2 = new Promise((resolve8) => {
26968
+ const timeout = new Promise((resolve9) => setTimeout(() => resolve9(empty), 500));
26969
+ const read2 = new Promise((resolve9) => {
26791
26970
  process.stdin.on("data", (chunk) => chunks.push(chunk));
26792
26971
  process.stdin.on("end", () => {
26793
26972
  const raw = Buffer.concat(chunks).toString("utf-8").trim();
26794
26973
  if (!raw) {
26795
- resolve8(empty);
26974
+ resolve9(empty);
26796
26975
  return;
26797
26976
  }
26798
26977
  try {
26799
26978
  const data = JSON.parse(raw);
26800
- resolve8({
26979
+ resolve9({
26801
26980
  assistantMessage: typeof data.last_assistant_message === "string" ? data.last_assistant_message : null,
26802
26981
  stopReason: typeof data.stop_reason === "string" ? data.stop_reason : null,
26803
26982
  transcriptPath: typeof data.transcript_path === "string" ? data.transcript_path : null,
26804
26983
  sessionId: typeof data.session_id === "string" ? data.session_id : null
26805
26984
  });
26806
26985
  } catch {
26807
- resolve8(empty);
26986
+ resolve9(empty);
26808
26987
  }
26809
26988
  });
26810
- process.stdin.on("error", () => resolve8(empty));
26989
+ process.stdin.on("error", () => resolve9(empty));
26811
26990
  process.stdin.resume();
26812
26991
  });
26813
26992
  return await Promise.race([read2, timeout]);
@@ -27073,7 +27252,7 @@ function channelSilence(input) {
27073
27252
  // src/lib/cli-version.ts
27074
27253
  function cliVersion() {
27075
27254
  try {
27076
- return true ? "0.34.0-experimental.92a1040" : "dev";
27255
+ return true ? "0.34.0-experimental.afcb0e6" : "dev";
27077
27256
  } catch {
27078
27257
  return "dev";
27079
27258
  }
@@ -27114,7 +27293,7 @@ async function sendSkipBeacon(ctx, reason) {
27114
27293
 
27115
27294
  // src/lib/static-analysis.ts
27116
27295
  var import_node_child_process12 = require("node:child_process");
27117
- var import_node_fs41 = require("node:fs");
27296
+ var import_node_fs42 = require("node:fs");
27118
27297
  var SEVERITY_ORDER = {
27119
27298
  Error: 0,
27120
27299
  Critical: 0,
@@ -27170,7 +27349,7 @@ function runCodacyAnalysis(files) {
27170
27349
  if (files.length === 0) return empty;
27171
27350
  const existingFiles = files.filter((f) => {
27172
27351
  try {
27173
- return (0, import_node_fs41.existsSync)(f);
27352
+ return (0, import_node_fs42.existsSync)(f);
27174
27353
  } catch {
27175
27354
  return false;
27176
27355
  }
@@ -27439,7 +27618,7 @@ async function scope(run4) {
27439
27618
  }
27440
27619
 
27441
27620
  // src/lib/specs.ts
27442
- var import_node_fs42 = require("node:fs");
27621
+ var import_node_fs43 = require("node:fs");
27443
27622
  var import_node_path32 = require("node:path");
27444
27623
  var SPEC_CANDIDATES = [
27445
27624
  "CLAUDE.md",
@@ -27481,7 +27660,7 @@ function discoverSpecs(consulted = []) {
27481
27660
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
27482
27661
  if (totalBytes >= totalCap) return false;
27483
27662
  if (seen.has(specPath)) return true;
27484
- if (!(0, import_node_fs42.existsSync)(specPath)) return true;
27663
+ if (!(0, import_node_fs43.existsSync)(specPath)) return true;
27485
27664
  seen.add(specPath);
27486
27665
  const remaining = totalCap - totalBytes;
27487
27666
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
@@ -27504,7 +27683,7 @@ function discoverSpecs(consulted = []) {
27504
27683
  if (!addSpec(candidate)) break;
27505
27684
  }
27506
27685
  for (const dir of ["spec", "docs"]) {
27507
- if (!(0, import_node_fs42.existsSync)(dir)) continue;
27686
+ if (!(0, import_node_fs43.existsSync)(dir)) continue;
27508
27687
  try {
27509
27688
  const mdFiles = findMdFiles(dir, 2).sort();
27510
27689
  for (const mdFile of mdFiles) {
@@ -27519,7 +27698,7 @@ function findMdFiles(dir, maxDepth, depth = 0) {
27519
27698
  if (depth >= maxDepth) return [];
27520
27699
  const result = [];
27521
27700
  try {
27522
- const entries = (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true });
27701
+ const entries = (0, import_node_fs43.readdirSync)(dir, { withFileTypes: true });
27523
27702
  for (const entry of entries) {
27524
27703
  const fullPath = (0, import_node_path32.join)(dir, entry.name);
27525
27704
  if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -27539,13 +27718,13 @@ function discoverPlans() {
27539
27718
  if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
27540
27719
  sources.push({ root: process.cwd(), prefix: (0, import_node_path32.join)(".claude", "plans") });
27541
27720
  }
27542
- if (home && (0, import_node_fs42.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
27721
+ if (home && (0, import_node_fs43.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
27543
27722
  const candidates2 = [];
27544
27723
  const seen = /* @__PURE__ */ new Set();
27545
27724
  for (const source2 of sources) {
27546
27725
  let names2;
27547
27726
  try {
27548
- names2 = (0, import_node_fs42.readdirSync)(source2.prefix ? (0, import_node_path32.join)(source2.root, source2.prefix) : source2.root);
27727
+ names2 = (0, import_node_fs43.readdirSync)(source2.prefix ? (0, import_node_path32.join)(source2.root, source2.prefix) : source2.root);
27549
27728
  } catch {
27550
27729
  continue;
27551
27730
  }
@@ -27572,7 +27751,7 @@ function isRealDirectoryChain(root, parts2) {
27572
27751
  for (const part of parts2) {
27573
27752
  current = (0, import_node_path32.join)(current, part);
27574
27753
  try {
27575
- if (!(0, import_node_fs42.lstatSync)(current).isDirectory()) return false;
27754
+ if (!(0, import_node_fs43.lstatSync)(current).isDirectory()) return false;
27576
27755
  } catch {
27577
27756
  return false;
27578
27757
  }
@@ -27587,7 +27766,7 @@ function discoverGuardDocs(rangeFiles2) {
27587
27766
  if (result.length >= MAX_SPEC_FILES) break;
27588
27767
  if (!GUARD_DOC_EXT.test(path)) continue;
27589
27768
  if (path.startsWith("/") || path.includes("..")) continue;
27590
- if (!(0, import_node_fs42.existsSync)(path)) continue;
27769
+ if (!(0, import_node_fs43.existsSync)(path)) continue;
27591
27770
  const opened = openRegularInRoot(process.cwd(), path);
27592
27771
  if (!opened.ok) continue;
27593
27772
  if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
@@ -27773,7 +27952,7 @@ async function mode(run4) {
27773
27952
  }
27774
27953
 
27775
27954
  // src/lib/fold.ts
27776
- var import_node_fs43 = require("node:fs");
27955
+ var import_node_fs44 = require("node:fs");
27777
27956
  var import_node_path33 = require("node:path");
27778
27957
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
27779
27958
  "user",
@@ -27911,7 +28090,7 @@ function candidateRoots(repoRoot2) {
27911
28090
  const norm2 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
27912
28091
  const out2 = [norm2];
27913
28092
  try {
27914
- const real = import_node_fs43.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
28093
+ const real = import_node_fs44.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
27915
28094
  if (real !== norm2) out2.push(real);
27916
28095
  } catch {
27917
28096
  }
@@ -27999,8 +28178,8 @@ function fold(transcriptPath, opts = {}) {
27999
28178
  }
28000
28179
  };
28001
28180
  try {
28002
- if (!(0, import_node_fs43.existsSync)(transcriptPath)) return result;
28003
- ingest((0, import_node_fs43.readFileSync)(transcriptPath, "utf8"), "agent");
28181
+ if (!(0, import_node_fs44.existsSync)(transcriptPath)) return result;
28182
+ ingest((0, import_node_fs44.readFileSync)(transcriptPath, "utf8"), "agent");
28004
28183
  result.coverage.complete = true;
28005
28184
  } catch {
28006
28185
  return result;
@@ -28011,19 +28190,19 @@ function fold(transcriptPath, opts = {}) {
28011
28190
  (0, import_node_path33.basename)(transcriptPath).replace(/\.jsonl$/, ""),
28012
28191
  "subagents"
28013
28192
  );
28014
- if ((0, import_node_fs43.existsSync)(sidecarDir)) {
28193
+ if ((0, import_node_fs44.existsSync)(sidecarDir)) {
28015
28194
  const maxFiles = opts.maxSidecars ?? 200;
28016
28195
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
28017
28196
  const found = [];
28018
28197
  const walk2 = (d, depth) => {
28019
28198
  if (depth > 4) return;
28020
- for (const e of (0, import_node_fs43.readdirSync)(d, { withFileTypes: true })) {
28199
+ for (const e of (0, import_node_fs44.readdirSync)(d, { withFileTypes: true })) {
28021
28200
  const p = (0, import_node_path33.join)(d, e.name);
28022
28201
  if (e.isDirectory()) {
28023
28202
  walk2(p, depth + 1);
28024
28203
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
28025
28204
  try {
28026
- const st = (0, import_node_fs43.statSync)(p);
28205
+ const st = (0, import_node_fs44.statSync)(p);
28027
28206
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
28028
28207
  } catch {
28029
28208
  result.coverage.malformed++;
@@ -28040,7 +28219,7 @@ function fold(transcriptPath, opts = {}) {
28040
28219
  continue;
28041
28220
  }
28042
28221
  try {
28043
- ingest((0, import_node_fs43.readFileSync)(f.path, "utf8"), "subagent");
28222
+ ingest((0, import_node_fs44.readFileSync)(f.path, "utf8"), "subagent");
28044
28223
  bytes += f.size;
28045
28224
  result.coverage.subagentFiles++;
28046
28225
  } catch {
@@ -28075,7 +28254,7 @@ function fold(transcriptPath, opts = {}) {
28075
28254
  }
28076
28255
  function classifyUnobserved(path) {
28077
28256
  try {
28078
- const st = (0, import_node_fs43.statSync)(path);
28257
+ const st = (0, import_node_fs44.statSync)(path);
28079
28258
  if (!st.isFile()) return "unreadable";
28080
28259
  } catch {
28081
28260
  return "unreadable";
@@ -28390,20 +28569,20 @@ async function evidence(run4) {
28390
28569
  }
28391
28570
 
28392
28571
  // src/lib/cache-cleanup.ts
28393
- var import_node_fs44 = require("node:fs");
28572
+ var import_node_fs45 = require("node:fs");
28394
28573
  var import_node_path34 = require("node:path");
28395
28574
  var CACHE_TTL_DAYS = 7;
28396
28575
  function pruneStaleCache() {
28397
28576
  try {
28398
28577
  const dir = projectPath(CACHE_DIR);
28399
28578
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
28400
- for (const entry of (0, import_node_fs44.readdirSync)(dir)) {
28579
+ for (const entry of (0, import_node_fs45.readdirSync)(dir)) {
28401
28580
  if (!entry.startsWith("pending-")) continue;
28402
28581
  const path = (0, import_node_path34.join)(dir, entry);
28403
28582
  try {
28404
- const stat3 = (0, import_node_fs44.statSync)(path);
28583
+ const stat3 = (0, import_node_fs45.statSync)(path);
28405
28584
  if (stat3.mtimeMs < cutoff) {
28406
- (0, import_node_fs44.unlinkSync)(path);
28585
+ (0, import_node_fs45.unlinkSync)(path);
28407
28586
  logEvent("cache_entry_pruned", {
28408
28587
  path: entry,
28409
28588
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -28417,7 +28596,7 @@ function pruneStaleCache() {
28417
28596
  }
28418
28597
 
28419
28598
  // src/lib/context-files.ts
28420
- var import_node_fs45 = require("node:fs");
28599
+ var import_node_fs46 = require("node:fs");
28421
28600
  var import_node_os7 = require("node:os");
28422
28601
  var MAX_CONTEXT_FILES = 10;
28423
28602
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -28475,7 +28654,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
28475
28654
  continue;
28476
28655
  }
28477
28656
  try {
28478
- const content = (0, import_node_fs45.readFileSync)(safePath, "utf8");
28657
+ const content = (0, import_node_fs46.readFileSync)(safePath, "utf8");
28479
28658
  const bytes = Buffer.byteLength(content);
28480
28659
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
28481
28660
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -28541,7 +28720,7 @@ async function contextFiles(run4) {
28541
28720
  }
28542
28721
 
28543
28722
  // src/lib/code/index.ts
28544
- var import_node_crypto12 = require("node:crypto");
28723
+ var import_node_crypto13 = require("node:crypto");
28545
28724
 
28546
28725
  // src/lib/code/languages.ts
28547
28726
  var JS_LIKE = {
@@ -28633,7 +28812,7 @@ function languageOf2(path) {
28633
28812
  }
28634
28813
 
28635
28814
  // src/lib/code/runtime.ts
28636
- var import_node_fs46 = require("node:fs");
28815
+ var import_node_fs47 = require("node:fs");
28637
28816
  var import_node_path35 = require("node:path");
28638
28817
  var import_web_tree_sitter2 = __toESM2(require_web_tree_sitter2());
28639
28818
 
@@ -28705,7 +28884,7 @@ function grammarCandidates(file, pkg, env = process.env) {
28705
28884
  }
28706
28885
  function locateGrammar(id, env = process.env) {
28707
28886
  const g = grammars_default[id];
28708
- return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs46.existsSync)(p)) ?? null;
28887
+ return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs47.existsSync)(p)) ?? null;
28709
28888
  }
28710
28889
  var loading = null;
28711
28890
  function loadRuntime(env = process.env) {
@@ -30319,7 +30498,7 @@ function byPath(fns, name2) {
30319
30498
  function makeCodeMap(rt) {
30320
30499
  const cache = /* @__PURE__ */ new Map();
30321
30500
  const outline = (path, content, deadlineAt = Date.now() + DEFAULT_PARSE_MS) => {
30322
- const key = `${path}\0${(0, import_node_crypto12.createHash)("sha1").update(content).digest("hex")}`;
30501
+ const key = `${path}\0${(0, import_node_crypto13.createHash)("sha1").update(content).digest("hex")}`;
30323
30502
  const hit = cache.get(key);
30324
30503
  if (hit) return { source: "tree-sitter", value: hit, elapsedMs: 0 };
30325
30504
  let r;
@@ -31034,7 +31213,7 @@ async function repoContext(run4) {
31034
31213
 
31035
31214
  // src/lib/seed-runner.ts
31036
31215
  var import_promises15 = require("node:fs/promises");
31037
- var import_node_fs47 = require("node:fs");
31216
+ var import_node_fs48 = require("node:fs");
31038
31217
  var import_node_path36 = require("node:path");
31039
31218
  var import_yaml4 = __toESM2(require_dist());
31040
31219
 
@@ -31259,7 +31438,7 @@ async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
31259
31438
  const titles = /* @__PURE__ */ new Set();
31260
31439
  for (const dir of NODE_DIRS) {
31261
31440
  const full = (0, import_node_path36.join)(memoryDir3, dir);
31262
- if (!(0, import_node_fs47.existsSync)(full)) continue;
31441
+ if (!(0, import_node_fs48.existsSync)(full)) continue;
31263
31442
  let files;
31264
31443
  try {
31265
31444
  files = await (0, import_promises15.readdir)(full);
@@ -31341,7 +31520,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
31341
31520
  return fm;
31342
31521
  }
31343
31522
  async function runSeed(opts) {
31344
- if (!(0, import_node_fs47.existsSync)(STANDARD_FILE)) {
31523
+ if (!(0, import_node_fs48.existsSync)(STANDARD_FILE)) {
31345
31524
  return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
31346
31525
  }
31347
31526
  let standardDoc;
@@ -31353,7 +31532,7 @@ async function runSeed(opts) {
31353
31532
  }
31354
31533
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
31355
31534
  let readmeContent;
31356
- if ((0, import_node_fs47.existsSync)("README.md")) {
31535
+ if ((0, import_node_fs48.existsSync)("README.md")) {
31357
31536
  try {
31358
31537
  readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
31359
31538
  } catch {
@@ -31361,7 +31540,7 @@ async function runSeed(opts) {
31361
31540
  }
31362
31541
  let claudeMdContent;
31363
31542
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
31364
- if ((0, import_node_fs47.existsSync)(p)) {
31543
+ if ((0, import_node_fs48.existsSync)(p)) {
31365
31544
  try {
31366
31545
  claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
31367
31546
  break;
@@ -31441,7 +31620,7 @@ async function runSeed(opts) {
31441
31620
  continue;
31442
31621
  }
31443
31622
  const deduplicated = res.data.deduplicated === true;
31444
- if (deduplicated && (0, import_node_fs47.existsSync)(targetPath)) {
31623
+ if (deduplicated && (0, import_node_fs48.existsSync)(targetPath)) {
31445
31624
  existing++;
31446
31625
  continue;
31447
31626
  }
@@ -31463,7 +31642,7 @@ async function runSeed(opts) {
31463
31642
  }
31464
31643
 
31465
31644
  // src/commands/analyze/phases/08-memory-manifest.ts
31466
- var import_node_fs48 = require("node:fs");
31645
+ var import_node_fs49 = require("node:fs");
31467
31646
  var import_node_path37 = require("node:path");
31468
31647
  async function memoryManifest(run4) {
31469
31648
  const { globals } = run4;
@@ -31475,8 +31654,8 @@ async function memoryManifest(run4) {
31475
31654
  try {
31476
31655
  await ensureMemoryDir();
31477
31656
  const seedMarker = (0, import_node_path37.join)(VERITY_DIR, ".seeded");
31478
- const hasStandard = (0, import_node_fs48.existsSync)(STANDARD_FILE);
31479
- const alreadyTried = (0, import_node_fs48.existsSync)(seedMarker);
31657
+ const hasStandard = (0, import_node_fs49.existsSync)(STANDARD_FILE);
31658
+ const alreadyTried = (0, import_node_fs49.existsSync)(seedMarker);
31480
31659
  if (hasStandard && !alreadyTried) {
31481
31660
  const preManifest = await buildManifest();
31482
31661
  if (preManifest.nodes.length === 0) {
@@ -31489,7 +31668,7 @@ async function memoryManifest(run4) {
31489
31668
  dryRun: false
31490
31669
  });
31491
31670
  if (seedResult.created > 0 || seedResult.existing > 0) {
31492
- (0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
31671
+ (0, import_node_fs49.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
31493
31672
  `);
31494
31673
  if (seedResult.created > 0) {
31495
31674
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
@@ -31500,7 +31679,7 @@ async function memoryManifest(run4) {
31500
31679
  failed: seedResult.failed
31501
31680
  });
31502
31681
  } else if (seedResult.skipped === "already_seeded") {
31503
- (0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
31682
+ (0, import_node_fs49.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
31504
31683
  `);
31505
31684
  } else {
31506
31685
  logEvent("auto_seed_noop", {
@@ -31688,8 +31867,24 @@ async function workingMemory(run4) {
31688
31867
  Object.assign(run4, { incrementReport, memory: memory2, memorySession, reachability });
31689
31868
  }
31690
31869
 
31870
+ // src/lib/payload-bounds.ts
31871
+ var MAX_WIRE_PATHS = 500;
31872
+ function boundPaths(paths, first, max = MAX_WIRE_PATHS) {
31873
+ if (paths.length <= max) return [...paths];
31874
+ const present = new Set(paths);
31875
+ const kept = /* @__PURE__ */ new Set();
31876
+ const out2 = [];
31877
+ for (const p of [...first, ...paths]) {
31878
+ if (out2.length >= max) break;
31879
+ if (!present.has(p) || kept.has(p)) continue;
31880
+ kept.add(p);
31881
+ out2.push(p);
31882
+ }
31883
+ return out2;
31884
+ }
31885
+
31691
31886
  // src/lib/note-budget.ts
31692
- var import_node_fs49 = require("node:fs");
31887
+ var import_node_fs50 = require("node:fs");
31693
31888
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
31694
31889
  var EPISODE_STALE_SECONDS = 30 * 60;
31695
31890
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -31711,9 +31906,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
31711
31906
  }
31712
31907
  function readAdvisoryEpisode(sessionId) {
31713
31908
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
31714
- if (!(0, import_node_fs49.existsSync)(file)) return null;
31909
+ if (!(0, import_node_fs50.existsSync)(file)) return null;
31715
31910
  try {
31716
- const o = JSON.parse((0, import_node_fs49.readFileSync)(file, "utf-8")) ?? {};
31911
+ const o = JSON.parse((0, import_node_fs50.readFileSync)(file, "utf-8")) ?? {};
31717
31912
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
31718
31913
  if (isNaN(delivered)) return null;
31719
31914
  return {
@@ -31727,8 +31922,8 @@ function readAdvisoryEpisode(sessionId) {
31727
31922
  }
31728
31923
  function writeAdvisoryEpisode(episode, sessionId) {
31729
31924
  try {
31730
- (0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
31731
- (0, import_node_fs49.writeFileSync)(
31925
+ (0, import_node_fs50.mkdirSync)(VERITY_DIR, { recursive: true });
31926
+ (0, import_node_fs50.writeFileSync)(
31732
31927
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
31733
31928
  JSON.stringify({ v: 1, ...episode })
31734
31929
  );
@@ -31802,6 +31997,7 @@ async function buildRequest(run4) {
31802
31997
  (conversation?.prompts?.length ?? 0) > 0
31803
31998
  );
31804
31999
  const noteConfirmation = peekNoteOutcome();
32000
+ const unobserved = foldResult?.unobserved ?? [];
31805
32001
  const excludedByReason = {};
31806
32002
  for (const e of codeDelta.excluded ?? []) {
31807
32003
  excludedByReason[e.reason] = (excludedByReason[e.reason] ?? 0) + 1;
@@ -31846,7 +32042,9 @@ async function buildRequest(run4) {
31846
32042
  coverage_telemetry: coverageTelemetry,
31847
32043
  static_results: staticResults,
31848
32044
  code_delta: codeDelta,
31849
- changed_files: allForReview,
32045
+ // Bounded, reviewed paths first — the server applies the same bound. The
32046
+ // full count is `coverage_telemetry.for_review`. VRT-242.
32047
+ changed_files: boundPaths(allForReview, codeDelta.files.map((f) => f.path)),
31850
32048
  standard_version: "latest",
31851
32049
  analysis_mode: analysisMode,
31852
32050
  plan_only: analysisMode === "plan",
@@ -31897,7 +32095,9 @@ async function buildRequest(run4) {
31897
32095
  // `hash_at_last_verdict` is frozen at each verdict and `hash_now` tracks
31898
32096
  // disk, so their inequality IS "changed since we last spoke".
31899
32097
  authored_since_verdict: memorySession ? foldDossier(memorySession.d).authored_all.filter((a) => a.hash_now !== a.hash_at_last_verdict).map((a) => a.path) : [],
31900
- unobserved: foldResult?.unobserved ?? [],
32098
+ // The server reads only how many; a bulk change sent every path. VRT-242.
32099
+ unobserved: unobserved.slice(0, MAX_WIRE_PATHS),
32100
+ ...unobserved.length > MAX_WIRE_PATHS && { unobserved_total: unobserved.length },
31901
32101
  commands: foldResult?.commands ?? [],
31902
32102
  tools: foldResult?.tools ?? [],
31903
32103
  tasks: foldResult?.tasks ?? [],
@@ -32060,14 +32260,14 @@ async function buildRequest(run4) {
32060
32260
  }
32061
32261
 
32062
32262
  // src/lib/offline.ts
32063
- var import_node_fs50 = require("node:fs");
32064
- var import_node_crypto13 = require("node:crypto");
32263
+ var import_node_fs51 = require("node:fs");
32264
+ var import_node_crypto14 = require("node:crypto");
32065
32265
  function cacheRequest(body2) {
32066
32266
  try {
32067
- (0, import_node_fs50.mkdirSync)(CACHE_DIR, { recursive: true });
32068
- const suffix = (0, import_node_crypto13.randomBytes)(4).toString("hex");
32267
+ (0, import_node_fs51.mkdirSync)(CACHE_DIR, { recursive: true });
32268
+ const suffix = (0, import_node_crypto14.randomBytes)(4).toString("hex");
32069
32269
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
32070
- (0, import_node_fs50.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
32270
+ (0, import_node_fs51.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
32071
32271
  } catch {
32072
32272
  }
32073
32273
  }
@@ -32108,8 +32308,10 @@ function buildOfflineFallback(reason, staticResults) {
32108
32308
  }
32109
32309
 
32110
32310
  // src/lib/retry.ts
32311
+ var WORKER_RESOURCE_LIMIT = 546;
32111
32312
  function shouldWarmRetryAnalyze(result) {
32112
32313
  if (result.ok) return false;
32314
+ if (result.http_status === WORKER_RESOURCE_LIMIT) return false;
32113
32315
  if (result.category === "network" || result.category === "timeout") return true;
32114
32316
  if (result.category === "http_5xx") return true;
32115
32317
  if (result.category === "invalid_json" && (result.http_status ?? 0) >= 500) return true;
@@ -32119,7 +32321,7 @@ function shouldWarmRetryAnalyze(result) {
32119
32321
  // src/commands/analyze/phases/12-transmit.ts
32120
32322
  async function transmit(run4) {
32121
32323
  const { globals } = run4;
32122
- const { codeDelta, requestBody, serviceUrl, staticResults, token } = run4;
32324
+ const { requestBody, serviceUrl, staticResults, token } = run4;
32123
32325
  const ANALYZE_TIMEOUT_MS = 1e5;
32124
32326
  let result = await analyzeRequest({
32125
32327
  serviceUrl,
@@ -32156,11 +32358,12 @@ async function transmit(run4) {
32156
32358
  }
32157
32359
  if (!result.ok) {
32158
32360
  cacheRequest(requestBody);
32361
+ const sentKb = () => Math.round(Buffer.byteLength(JSON.stringify(requestBody)) / 1024);
32159
32362
  let message;
32160
32363
  if (result.http_status === 413) {
32161
- const totalBytes = codeDelta.files.reduce((sum, f) => sum + f.content.length, 0);
32162
- const kb = Math.round(totalBytes / 1024);
32163
- message = `Verity: request rejected \u2014 payload too large (${kb}KB over the 190KB cap). Commit or stash pre-existing changes, or run with --mode skip if you didn't intend to submit code this turn.`;
32364
+ message = `Verity: request rejected \u2014 payload too large (${sentKb()} KB sent: ${result.error}). Commit or stash pre-existing changes, or run with --mode skip if you didn't intend to submit code this turn.`;
32365
+ } else if (result.http_status === WORKER_RESOURCE_LIMIT) {
32366
+ message = `Verity: the service ran out of CPU or memory on this request (HTTP 546, ${sentKb()} KB sent). This is not a cold start: the same change fails the same way, so it was not retried. Commit or stash unrelated changes to shrink the request (local analysis this run).`;
32164
32367
  } else if (result.category === "network" || result.category === "timeout") {
32165
32368
  message = `Verity offline \u2014 ${result.error}`;
32166
32369
  } else if (result.error.startsWith("STALE_VERIFICATION")) {
@@ -32186,7 +32389,7 @@ async function transmit(run4) {
32186
32389
  }
32187
32390
 
32188
32391
  // src/commands/analyze/phases/13-reconcile.ts
32189
- var import_node_fs51 = require("node:fs");
32392
+ var import_node_fs52 = require("node:fs");
32190
32393
  var import_node_path39 = require("node:path");
32191
32394
  async function reconcile(run4) {
32192
32395
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory: memory2, memorySession, response, reviewable, securityFiles, turnId } = run4;
@@ -32216,7 +32419,7 @@ async function reconcile(run4) {
32216
32419
  const st = foldDossier(memorySession.d);
32217
32420
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line2) => {
32218
32421
  try {
32219
- const src = (0, import_node_fs51.readFileSync)((0, import_node_path39.join)(repoRoot(), file), "utf8").split("\n");
32422
+ const src = (0, import_node_fs52.readFileSync)((0, import_node_path39.join)(repoRoot(), file), "utf8").split("\n");
32220
32423
  const at = src[line2 - 1];
32221
32424
  return at === void 0 ? null : lineSha(at);
32222
32425
  } catch {
@@ -33038,7 +33241,7 @@ function registerAnalyzeCommand(program2) {
33038
33241
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
33039
33242
  async function runAnalyze(opts, globals) {
33040
33243
  if (!verityConfigured()) {
33041
- (0, import_node_fs52.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
33244
+ (0, import_node_fs53.writeSync)(2, isMachineStore((0, import_node_path40.join)(repoRoot(), VERITY_DIR)) ? "[verity] nothing to review in your home directory \u2014 run Verity inside a project.\n" : '[verity] not set up in this project \u2014 run "verity init" first.\n');
33042
33245
  process.exit(0);
33043
33246
  }
33044
33247
  const run4 = createRun(opts, globals);
@@ -33059,11 +33262,12 @@ async function runAnalyze(opts, globals) {
33059
33262
  }
33060
33263
 
33061
33264
  // src/commands/baseline.ts
33062
- var import_node_fs54 = require("node:fs");
33265
+ var import_node_fs55 = require("node:fs");
33266
+ var import_node_path42 = require("node:path");
33063
33267
 
33064
33268
  // src/lib/project-skills.ts
33065
- var import_node_fs53 = require("node:fs");
33066
- var import_node_path40 = require("node:path");
33269
+ var import_node_fs54 = require("node:fs");
33270
+ var import_node_path41 = require("node:path");
33067
33271
  var PROJECT_SKILL_NAMES = [
33068
33272
  "verity-setup",
33069
33273
  "verity-analyze",
@@ -33089,14 +33293,14 @@ var LEGACY_SKILL_NAMES = [
33089
33293
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
33090
33294
  function staleProjectSkills() {
33091
33295
  const root = projectPath(".claude/skills");
33092
- if (!(0, import_node_fs53.existsSync)(root)) return [];
33093
- return ALL.filter((name2) => (0, import_node_fs53.existsSync)((0, import_node_path40.join)(root, name2)));
33296
+ if (!(0, import_node_fs54.existsSync)(root)) return [];
33297
+ return ALL.filter((name2) => (0, import_node_fs54.existsSync)((0, import_node_path41.join)(root, name2)));
33094
33298
  }
33095
33299
  function removeProjectSkills() {
33096
33300
  const root = projectPath(".claude/skills");
33097
33301
  const removed = [];
33098
33302
  for (const name2 of staleProjectSkills()) {
33099
- (0, import_node_fs53.rmSync)((0, import_node_path40.join)(root, name2), { recursive: true, force: true });
33303
+ (0, import_node_fs54.rmSync)((0, import_node_path41.join)(root, name2), { recursive: true, force: true });
33100
33304
  removed.push(name2);
33101
33305
  }
33102
33306
  return removed;
@@ -33129,6 +33333,7 @@ function registerBaselineCommands(program2) {
33129
33333
  const skewMsg = skew ? `Verity: your global \`verity\` CLI is ${skew.global} but the hooks run ${skew.hooks}. Fix it before using \`verity\` in a terminal: ${skew.remedy}` : null;
33130
33334
  const skewNote = skew ? `Before anything else, including /verity:init's questions, tell the user their global \`verity\` is ${skew.global}, the hooks run ${skew.hooks}, and \`${skew.remedy}\` fixes it. Until they have, do not send them to run \`verity login\` in a terminal: that runs the global one, which can sign this machine in to a different server.` : null;
33131
33335
  if (!verityConfigured()) {
33336
+ if (isMachineStore((0, import_node_path42.join)(repoRoot(), VERITY_DIR))) process.exit(0);
33132
33337
  const how = isPluginInvocation() ? "Tell the user to run /verity:init \u2014 they type it; you cannot invoke it." : "Tell the user to run `verity init` in their terminal.";
33133
33338
  const lines = [
33134
33339
  `Verity is installed but this project is not set up yet, so the quality gate will not review anything here. ${how}`
@@ -33161,13 +33366,13 @@ function registerBaselineCommands(program2) {
33161
33366
  let memoryMsg = null;
33162
33367
  let memoryAgentLine = null;
33163
33368
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
33164
- if (realStart && !(0, import_node_fs54.existsSync)(memoryNotice)) {
33369
+ if (realStart && !(0, import_node_fs55.existsSync)(memoryNotice)) {
33165
33370
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
33166
33371
  if (trackedGraph > 0) {
33167
33372
  memoryMsg = `Verity: this project commits its knowledge base (${trackedGraph} files under .verity/memory/), so Verity's generated notes show up in every diff and pull request. Run \`verity memory untrack\` to keep them on disk but out of git, or \`verity memory track\` to keep committing them on purpose.`;
33168
33373
  memoryAgentLine = `This project has ${trackedGraph} knowledge-graph files tracked in git under .verity/memory/. As of Verity 0.32.6 the graph is machine-local by default \u2014 it is rebuilt from the service, and committing it puts generated notes in every pull request. If the user wants that stopped, run \`verity memory untrack\` for them: it keeps every file on disk and stages their removal from the index, so they only need to commit \u2014 and their teammates' working copies will vanish on the next pull and re-sync from the service, which is expected. If they would rather keep committing it, \`verity memory track\` records that and nothing will offer again.`;
33169
33374
  try {
33170
- (0, import_node_fs54.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33375
+ (0, import_node_fs55.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33171
33376
  } catch {
33172
33377
  }
33173
33378
  }
@@ -33268,10 +33473,16 @@ function hookSource(value) {
33268
33473
  }
33269
33474
 
33270
33475
  // src/commands/review.ts
33271
- var import_node_fs55 = require("node:fs");
33476
+ var import_node_fs56 = require("node:fs");
33272
33477
  function registerReviewCommand(program2) {
33273
- program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars)").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
33478
+ program2.command("review").description("Run on-demand Verity analysis (advisory, never blocks)").requiredOption("--files <paths>", "Comma-separated file list").option("--changed <paths>", "Subset of --files that were modified").option("--intent <text>", "User intent description (max 2000 chars); - reads it from stdin, so the words never pass through shell quoting").option("--specs <paths>", "Comma-separated spec file paths").option("--json", "Output raw JSON response").action(async (opts) => {
33274
33479
  const globals = program2.opts();
33480
+ const intent = readTextInput(opts.intent, "--intent");
33481
+ if (!intent.ok) {
33482
+ printError(intent.error);
33483
+ process.exit(0);
33484
+ }
33485
+ opts.intent = intent.text;
33275
33486
  try {
33276
33487
  await runReview(opts, globals);
33277
33488
  } catch (err2) {
@@ -33285,7 +33496,7 @@ async function runReview(opts, globals) {
33285
33496
  const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
33286
33497
  const analyzable = filterAnalyzable(allFiles);
33287
33498
  const securityFiles = filterSecurity(allFiles);
33288
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs55.existsSync)(f) || resolveFile(f) !== null);
33499
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs56.existsSync)(f) || resolveFile(f) !== null);
33289
33500
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
33290
33501
  const codeDelta = collectCodeDelta(allFiles);
33291
33502
  const tokenResult = await resolveToken(globals.token);
@@ -33351,19 +33562,40 @@ async function runReview(opts, globals) {
33351
33562
  }
33352
33563
 
33353
33564
  // src/commands/guard.ts
33354
- var import_node_fs59 = require("node:fs");
33355
- var import_node_path45 = require("node:path");
33565
+ var import_node_fs61 = require("node:fs");
33566
+ var import_node_path48 = require("node:path");
33356
33567
 
33357
- // src/lib/terminal-text.ts
33358
- var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
33359
- function terminalText(value, max = 4e3) {
33360
- if (typeof value !== "string") return "";
33361
- const clean2 = value.replace(CONTROL, "");
33362
- return clean2.length > max ? `${clean2.slice(0, max - 1)}\u2026` : clean2;
33568
+ // src/lib/vendored.ts
33569
+ var import_node_fs57 = require("node:fs");
33570
+ var import_node_path43 = require("node:path");
33571
+ var INSTALLED_SKILL = /^\.claude\/skills\/(verity-[a-z0-9-]+)\/(.+)$/;
33572
+ function dataDirOrNull() {
33573
+ try {
33574
+ return resolveDataDir();
33575
+ } catch {
33576
+ return null;
33577
+ }
33363
33578
  }
33364
- function terminalUrl(value) {
33365
- const clean2 = terminalText(value, 2e3);
33366
- return /^https?:\/\/\S+$/.test(clean2) ? clean2 : "";
33579
+ function shippedSkillFile(path, dataDir = dataDirOrNull()) {
33580
+ const m = path.replace(/\\/g, "/").match(INSTALLED_SKILL);
33581
+ if (!m || !dataDir) return null;
33582
+ const [, skill, rel] = m;
33583
+ if (rel.split("/").some((seg) => seg === ".." || seg === ".")) return null;
33584
+ try {
33585
+ return (0, import_node_fs57.readFileSync)((0, import_node_path43.join)(dataDir, "skills", skill, rel), "utf8");
33586
+ } catch {
33587
+ return null;
33588
+ }
33589
+ }
33590
+ function partitionVendored(files, read2, dataDir = dataDirOrNull()) {
33591
+ const review = [];
33592
+ const vendored = [];
33593
+ for (const f of files) {
33594
+ const shipped = shippedSkillFile(f, dataDir);
33595
+ if (shipped !== null && read2(f) === shipped) vendored.push(f);
33596
+ else review.push(f);
33597
+ }
33598
+ return { review, vendored };
33367
33599
  }
33368
33600
 
33369
33601
  // src/lib/agent-driver.ts
@@ -33445,7 +33677,7 @@ async function runAgentReview(options) {
33445
33677
  }
33446
33678
  if (!settled) {
33447
33679
  const wait = Math.max(0, remaining() - FINISH_TIMEOUT_MS);
33448
- await Promise.race([oneShotDone, new Promise((resolve8) => setTimeout(resolve8, wait))]);
33680
+ await Promise.race([oneShotDone, new Promise((resolve9) => setTimeout(resolve9, wait))]);
33449
33681
  }
33450
33682
  const finished = await options.http.post(
33451
33683
  "/agent-review/finish",
@@ -33460,8 +33692,8 @@ async function runAgentReview(options) {
33460
33692
  }
33461
33693
 
33462
33694
  // src/lib/prove/auto.ts
33463
- var import_node_path44 = require("node:path");
33464
- var import_node_crypto18 = require("node:crypto");
33695
+ var import_node_path47 = require("node:path");
33696
+ var import_node_crypto19 = require("node:crypto");
33465
33697
 
33466
33698
  // src/lib/prove/signals.ts
33467
33699
  var DEFAULT_SINCE = "180 days ago";
@@ -35187,18 +35419,18 @@ function renderReplay(model, property, r) {
35187
35419
  // src/lib/prove/runner.ts
35188
35420
  var import_node_child_process15 = require("node:child_process");
35189
35421
  var import_node_os8 = require("node:os");
35190
- var import_node_fs58 = require("node:fs");
35422
+ var import_node_fs60 = require("node:fs");
35191
35423
  var import_node_os9 = require("node:os");
35192
- var import_node_path43 = require("node:path");
35424
+ var import_node_path46 = require("node:path");
35193
35425
 
35194
35426
  // src/lib/prove/scaffold.ts
35195
- var import_node_fs57 = require("node:fs");
35196
- var import_node_path42 = require("node:path");
35427
+ var import_node_fs59 = require("node:fs");
35428
+ var import_node_path45 = require("node:path");
35197
35429
 
35198
35430
  // src/lib/prove/safe-write.ts
35199
- var import_node_fs56 = require("node:fs");
35200
- var import_node_crypto14 = require("node:crypto");
35201
- var import_node_path41 = require("node:path");
35431
+ var import_node_fs58 = require("node:fs");
35432
+ var import_node_crypto15 = require("node:crypto");
35433
+ var import_node_path44 = require("node:path");
35202
35434
  var SafeWriteError = class extends Error {
35203
35435
  constructor(reason, path) {
35204
35436
  super(`refusing to write ${path}: ${reason}`);
@@ -35207,10 +35439,10 @@ var SafeWriteError = class extends Error {
35207
35439
  this.name = "SafeWriteError";
35208
35440
  }
35209
35441
  };
35210
- var FLAGS3 = import_node_fs56.constants;
35442
+ var FLAGS3 = import_node_fs58.constants;
35211
35443
  var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
35212
35444
  function assertPlainRelative(rel) {
35213
- if (!rel || (0, import_node_path41.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35445
+ if (!rel || (0, import_node_path44.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35214
35446
  for (const part of rel.split(/[\\/]/)) {
35215
35447
  if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
35216
35448
  }
@@ -35219,34 +35451,34 @@ function ensureDirsNoFollow(root, rel) {
35219
35451
  const parts2 = rel.split(/[\\/]/);
35220
35452
  let cur = root;
35221
35453
  for (const part of parts2.slice(0, -1)) {
35222
- cur = (0, import_node_path41.join)(cur, part);
35454
+ cur = (0, import_node_path44.join)(cur, part);
35223
35455
  let st;
35224
35456
  try {
35225
- st = (0, import_node_fs56.lstatSync)(cur);
35457
+ st = (0, import_node_fs58.lstatSync)(cur);
35226
35458
  } catch {
35227
- (0, import_node_fs56.mkdirSync)(cur);
35459
+ (0, import_node_fs58.mkdirSync)(cur);
35228
35460
  continue;
35229
35461
  }
35230
35462
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
35231
35463
  if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
35232
35464
  }
35233
- return (0, import_node_path41.join)(root, rel);
35465
+ return (0, import_node_path44.join)(root, rel);
35234
35466
  }
35235
35467
  function insideRoot(realRoot, realPath) {
35236
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path41.sep) ? realRoot : realRoot + import_node_path41.sep);
35468
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path44.sep) ? realRoot : realRoot + import_node_path44.sep);
35237
35469
  }
35238
35470
  function removeQuietly(path) {
35239
35471
  try {
35240
- (0, import_node_fs56.unlinkSync)(path);
35472
+ (0, import_node_fs58.unlinkSync)(path);
35241
35473
  } catch {
35242
35474
  }
35243
35475
  }
35244
35476
  function writeFileInRootNoFollow(root, rel, content) {
35245
35477
  assertPlainRelative(rel);
35246
35478
  const dest = ensureDirsNoFollow(root, rel);
35247
- const dir = (0, import_node_path41.dirname)(dest);
35479
+ const dir = (0, import_node_path44.dirname)(dest);
35248
35480
  try {
35249
- const st = (0, import_node_fs56.lstatSync)(dest);
35481
+ const st = (0, import_node_fs58.lstatSync)(dest);
35250
35482
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
35251
35483
  if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
35252
35484
  } catch (err2) {
@@ -35254,41 +35486,41 @@ function writeFileInRootNoFollow(root, rel, content) {
35254
35486
  }
35255
35487
  let realRoot;
35256
35488
  try {
35257
- realRoot = (0, import_node_fs56.realpathSync)(root);
35489
+ realRoot = (0, import_node_fs58.realpathSync)(root);
35258
35490
  } catch {
35259
35491
  throw new SafeWriteError("unwritable", root);
35260
35492
  }
35261
- const tmp = (0, import_node_path41.join)(dir, `.${(0, import_node_path41.basename)(dest)}.${(0, import_node_crypto14.randomBytes)(6).toString("hex")}.tmp`);
35493
+ const tmp = (0, import_node_path44.join)(dir, `.${(0, import_node_path44.basename)(dest)}.${(0, import_node_crypto15.randomBytes)(6).toString("hex")}.tmp`);
35262
35494
  let fd;
35263
35495
  try {
35264
- fd = (0, import_node_fs56.openSync)(tmp, import_node_fs56.constants.O_WRONLY | import_node_fs56.constants.O_CREAT | import_node_fs56.constants.O_EXCL | NOFOLLOW2, 420);
35496
+ fd = (0, import_node_fs58.openSync)(tmp, import_node_fs58.constants.O_WRONLY | import_node_fs58.constants.O_CREAT | import_node_fs58.constants.O_EXCL | NOFOLLOW2, 420);
35265
35497
  } catch {
35266
35498
  throw new SafeWriteError("unwritable", tmp);
35267
35499
  }
35268
35500
  try {
35269
- const opened = (0, import_node_fs56.fstatSync)(fd, { bigint: true });
35501
+ const opened = (0, import_node_fs58.fstatSync)(fd, { bigint: true });
35270
35502
  let realTmp;
35271
35503
  try {
35272
- realTmp = (0, import_node_fs56.realpathSync)(tmp);
35504
+ realTmp = (0, import_node_fs58.realpathSync)(tmp);
35273
35505
  } catch {
35274
35506
  throw new SafeWriteError("escaped", tmp);
35275
35507
  }
35276
- const there = (0, import_node_fs56.lstatSync)(realTmp, { bigint: true });
35508
+ const there = (0, import_node_fs58.lstatSync)(realTmp, { bigint: true });
35277
35509
  if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
35278
35510
  throw new SafeWriteError("escaped", tmp);
35279
35511
  }
35280
35512
  const buf = Buffer.from(content, "utf-8");
35281
35513
  let off = 0;
35282
- while (off < buf.length) off += (0, import_node_fs56.writeSync)(fd, buf, off, buf.length - off);
35514
+ while (off < buf.length) off += (0, import_node_fs58.writeSync)(fd, buf, off, buf.length - off);
35283
35515
  } catch (err2) {
35284
- (0, import_node_fs56.closeSync)(fd);
35516
+ (0, import_node_fs58.closeSync)(fd);
35285
35517
  removeQuietly(tmp);
35286
35518
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
35287
35519
  }
35288
- (0, import_node_fs56.closeSync)(fd);
35520
+ (0, import_node_fs58.closeSync)(fd);
35289
35521
  try {
35290
- if (!insideRoot(realRoot, (0, import_node_fs56.realpathSync)(dir)) || (0, import_node_fs56.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35291
- (0, import_node_fs56.renameSync)(tmp, dest);
35522
+ if (!insideRoot(realRoot, (0, import_node_fs58.realpathSync)(dir)) || (0, import_node_fs58.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35523
+ (0, import_node_fs58.renameSync)(tmp, dest);
35292
35524
  } catch (err2) {
35293
35525
  removeQuietly(tmp);
35294
35526
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
@@ -35302,9 +35534,9 @@ function pathHasNoLink(root, rel) {
35302
35534
  }
35303
35535
  let cur = root;
35304
35536
  for (const part of rel.split(/[\\/]/)) {
35305
- cur = cur + import_node_path41.sep + part;
35537
+ cur = cur + import_node_path44.sep + part;
35306
35538
  try {
35307
- if ((0, import_node_fs56.lstatSync)(cur).isSymbolicLink()) return false;
35539
+ if ((0, import_node_fs58.lstatSync)(cur).isSymbolicLink()) return false;
35308
35540
  } catch {
35309
35541
  return true;
35310
35542
  }
@@ -35614,20 +35846,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
35614
35846
  never committed; what reaches the team is the bug report and the fix.
35615
35847
  `;
35616
35848
  function scaffoldProofs(root) {
35617
- const proofsDir = (0, import_node_path42.join)(root, PROOFS_DIR);
35849
+ const proofsDir = (0, import_node_path45.join)(root, PROOFS_DIR);
35618
35850
  const written = [];
35619
35851
  const kept = [];
35620
35852
  for (const stray of ["lakefile.lean"]) {
35621
35853
  const rel = `${PROOFS_DIR}/${stray}`;
35622
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
35854
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
35623
35855
  try {
35624
- (0, import_node_fs57.rmSync)((0, import_node_path42.join)(root, rel), { force: true });
35856
+ (0, import_node_fs59.rmSync)((0, import_node_path45.join)(root, rel), { force: true });
35625
35857
  } catch {
35626
35858
  }
35627
35859
  }
35628
35860
  for (const f of PROOFS_TEMPLATE_FILES) {
35629
35861
  const rel = `${PROOFS_DIR}/${f.path}`;
35630
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
35862
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
35631
35863
  const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
35632
35864
  if (current.ok && current.content === f.content) {
35633
35865
  kept.push(rel);
@@ -35640,8 +35872,8 @@ function scaffoldProofs(root) {
35640
35872
  [`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
35641
35873
  [`${MODELS_DIR}/README.md`, MODELS_README]
35642
35874
  ]) {
35643
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
35644
- if (existsNoFollow((0, import_node_path42.join)(root, rel))) {
35875
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path45.join)(root, rel));
35876
+ if (existsNoFollow((0, import_node_path45.join)(root, rel))) {
35645
35877
  kept.push(rel);
35646
35878
  continue;
35647
35879
  }
@@ -35652,7 +35884,7 @@ function scaffoldProofs(root) {
35652
35884
  }
35653
35885
  function existsNoFollow(abs) {
35654
35886
  try {
35655
- (0, import_node_fs57.lstatSync)(abs);
35887
+ (0, import_node_fs59.lstatSync)(abs);
35656
35888
  return true;
35657
35889
  } catch {
35658
35890
  return false;
@@ -35660,7 +35892,7 @@ function existsNoFollow(abs) {
35660
35892
  }
35661
35893
 
35662
35894
  // src/lib/prove/report.ts
35663
- var import_node_crypto15 = require("node:crypto");
35895
+ var import_node_crypto16 = require("node:crypto");
35664
35896
  var IDENT2 = /^[A-Za-z0-9_][A-Za-z0-9_.-]{0,63}$/;
35665
35897
  var SHA256 = /^(sha256:)?[0-9a-f]{64}$/;
35666
35898
  var KINDS2 = /* @__PURE__ */ new Set(["structural", "intent"]);
@@ -35808,7 +36040,7 @@ function sha256InRoot(root, file) {
35808
36040
  const opened = openRegularInRoot(root, file);
35809
36041
  if (!opened.ok) return null;
35810
36042
  try {
35811
- return (0, import_node_crypto15.createHash)("sha256").update(readOpened(opened.fd, opened.size)).digest("hex");
36043
+ return (0, import_node_crypto16.createHash)("sha256").update(readOpened(opened.fd, opened.size)).digest("hex");
35812
36044
  } catch {
35813
36045
  return null;
35814
36046
  }
@@ -35910,17 +36142,17 @@ function renderReport(r) {
35910
36142
 
35911
36143
  // src/lib/prove/runner.ts
35912
36144
  function verityLeanHome(env = process.env) {
35913
- return env.VERITY_LEAN_HOME ?? (0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
36145
+ return env.VERITY_LEAN_HOME ?? (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
35914
36146
  }
35915
36147
  function findToolchain(env = process.env) {
35916
- const managedBin = (0, import_node_path43.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
35917
- const elanBin = (0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
35918
- const elanHas = (0, import_node_fs58.existsSync)((0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
35919
- const userPath = (env.PATH ?? "").split(import_node_path43.delimiter).filter((d) => d && (elanHas || (0, import_node_path43.resolve)(d) !== (0, import_node_path43.resolve)(elanBin)));
35920
- const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path43.delimiter);
36148
+ const managedBin = (0, import_node_path46.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
36149
+ const elanBin = (0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
36150
+ const elanHas = (0, import_node_fs60.existsSync)((0, import_node_path46.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
36151
+ const userPath = (env.PATH ?? "").split(import_node_path46.delimiter).filter((d) => d && (elanHas || (0, import_node_path46.resolve)(d) !== (0, import_node_path46.resolve)(elanBin)));
36152
+ const path = [managedBin, ...elanHas ? [elanBin] : [], ...userPath].join(import_node_path46.delimiter);
35921
36153
  const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
35922
36154
  const exe = process.platform === "win32" ? "lake.exe" : "lake";
35923
- const candidates2 = [(0, import_node_path43.join)(managedBin, exe), ...elanHas ? [(0, import_node_path43.join)(elanBin, exe)] : [], exe];
36155
+ const candidates2 = [(0, import_node_path46.join)(managedBin, exe), ...elanHas ? [(0, import_node_path46.join)(elanBin, exe)] : [], exe];
35924
36156
  for (const candidate of candidates2) {
35925
36157
  try {
35926
36158
  (0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
@@ -35958,7 +36190,7 @@ function run2(tc, cwd, args2, timeoutMs) {
35958
36190
  function runAsync(tc, cwd, args2, timeoutMs) {
35959
36191
  const started = Date.now();
35960
36192
  const MAX = 16 * 1024 * 1024;
35961
- return new Promise((resolve8) => {
36193
+ return new Promise((resolve9) => {
35962
36194
  const posix = (0, import_node_os8.platform)() !== "win32";
35963
36195
  const child = (0, import_node_child_process15.spawn)(tc.lake, args2, { cwd, env: tc.env, stdio: ["ignore", "pipe", "pipe"], detached: posix });
35964
36196
  let stdout = "";
@@ -35986,8 +36218,8 @@ function runAsync(tc, cwd, args2, timeoutMs) {
35986
36218
  if (settled) return;
35987
36219
  settled = true;
35988
36220
  clearTimeout(timer);
35989
- if (ok) resolve8({ ok: true, stdout, stderr: "", durationMs: Date.now() - started, timedOut: false });
35990
- else resolve8({ ok: false, stdout, stderr: stderr || message || "", durationMs: Date.now() - started, timedOut });
36221
+ if (ok) resolve9({ ok: true, stdout, stderr: "", durationMs: Date.now() - started, timedOut: false });
36222
+ else resolve9({ ok: false, stdout, stderr: stderr || message || "", durationMs: Date.now() - started, timedOut });
35991
36223
  };
35992
36224
  child.on("error", (err2) => finish(false, err2.message));
35993
36225
  child.on("close", (code) => finish(code === 0 && !timedOut));
@@ -35999,7 +36231,7 @@ function proofsWorkspaceProblem(root) {
35999
36231
  for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
36000
36232
  let st;
36001
36233
  try {
36002
- st = (0, import_node_fs58.lstatSync)((0, import_node_path43.join)(root, rel));
36234
+ st = (0, import_node_fs60.lstatSync)((0, import_node_path46.join)(root, rel));
36003
36235
  } catch {
36004
36236
  break;
36005
36237
  }
@@ -36019,44 +36251,44 @@ function refused(problem) {
36019
36251
  function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36020
36252
  const problem = proofsWorkspaceProblem(root);
36021
36253
  if (problem) return refused(problem);
36022
- return run2(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36254
+ return run2(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36023
36255
  }
36024
36256
  async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36025
36257
  const problem = proofsWorkspaceProblem(root);
36026
36258
  if (problem) return refused(problem);
36027
- return runAsync(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36259
+ return runAsync(tc, (0, import_node_path46.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36028
36260
  }
36029
36261
  function isModelInRoot(modelsAbs, rel) {
36030
- if (!rel.endsWith(".lean") || (0, import_node_path43.isAbsolute)(rel) || rel.startsWith("..")) return false;
36262
+ if (!rel.endsWith(".lean") || (0, import_node_path46.isAbsolute)(rel) || rel.startsWith("..")) return false;
36031
36263
  return statRegularInRoot(modelsAbs, rel).ok;
36032
36264
  }
36033
36265
  function resolveModelFile(root, arg) {
36034
- const modelsAbs = (0, import_node_path43.join)(root, MODELS_DIR);
36035
- const asPath = (0, import_node_path43.relative)(modelsAbs, (0, import_node_path43.isAbsolute)(arg) ? arg : (0, import_node_path43.resolve)(root, arg));
36266
+ const modelsAbs = (0, import_node_path46.join)(root, MODELS_DIR);
36267
+ const asPath = (0, import_node_path46.relative)(modelsAbs, (0, import_node_path46.isAbsolute)(arg) ? arg : (0, import_node_path46.resolve)(root, arg));
36036
36268
  const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
36037
36269
  for (const rel of candidates2) {
36038
- if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path43.join)(modelsAbs, rel);
36270
+ if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path46.join)(modelsAbs, rel);
36039
36271
  }
36040
36272
  return null;
36041
36273
  }
36042
36274
  function listModelFiles(root) {
36043
- const modelsAbs = (0, import_node_path43.join)(root, MODELS_DIR);
36044
- if (!(0, import_node_fs58.existsSync)(modelsAbs)) return [];
36045
- return (0, import_node_fs58.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path43.join)(modelsAbs, f));
36275
+ const modelsAbs = (0, import_node_path46.join)(root, MODELS_DIR);
36276
+ if (!(0, import_node_fs60.existsSync)(modelsAbs)) return [];
36277
+ return (0, import_node_fs60.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path46.join)(modelsAbs, f));
36046
36278
  }
36047
36279
  function trimDiagnostics(text) {
36048
36280
  return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36049
36281
  }
36050
36282
  function checkModel(tc, root, modelFile, opts = {}) {
36051
- const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
36052
- const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
36283
+ const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36284
+ const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36053
36285
  const problem = proofsWorkspaceProblem(root);
36054
36286
  const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36055
36287
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36056
36288
  }
36057
36289
  async function checkModelAsync(tc, root, modelFile, opts = {}) {
36058
- const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
36059
- const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
36290
+ const proofsAbs = (0, import_node_path46.join)(root, PROOFS_DIR);
36291
+ const rel = (0, import_node_path46.relative)(proofsAbs, modelFile);
36060
36292
  const problem = proofsWorkspaceProblem(root);
36061
36293
  const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36062
36294
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
@@ -36065,10 +36297,10 @@ function toReport(res, root, modelFile, timeoutMs) {
36065
36297
  const parsed = parseVerityLines(res.stdout);
36066
36298
  const combined = `${res.stdout}
36067
36299
  ${res.stderr}`;
36068
- const name2 = parsed.header?.model ?? (0, import_node_path43.basename)(modelFile, ".lean");
36300
+ const name2 = parsed.header?.model ?? (0, import_node_path46.basename)(modelFile, ".lean");
36069
36301
  const report = {
36070
36302
  model: name2,
36071
- file: (0, import_node_path43.relative)(root, modelFile),
36303
+ file: (0, import_node_path46.relative)(root, modelFile),
36072
36304
  ok: res.ok,
36073
36305
  header: parsed.header,
36074
36306
  properties: parsed.properties,
@@ -36143,7 +36375,7 @@ function mergeFormalFindings(response, outcome, pushedFiles) {
36143
36375
  }
36144
36376
 
36145
36377
  // src/lib/prove/scalpel.ts
36146
- var import_node_crypto16 = require("node:crypto");
36378
+ var import_node_crypto17 = require("node:crypto");
36147
36379
  var ARITHMETIC = /Math\.(?:round|floor|ceil|trunc)\(|\bround\(|\bdivmod\(|[\w)\]]\s*(?:\*|\/(?!\/)|%)\s*[\w(]/;
36148
36380
  function functionHazard(numbered2) {
36149
36381
  const sites = effectSites(numbered2);
@@ -36173,7 +36405,7 @@ function semanticFingerprint(numbered2) {
36173
36405
  if (LOG_LINE.test(t)) continue;
36174
36406
  kept.push(t.replace(/\s+/g, " "));
36175
36407
  }
36176
- return (0, import_node_crypto16.createHash)("sha256").update(kept.join("\n")).digest("hex");
36408
+ return (0, import_node_crypto17.createHash)("sha256").update(kept.join("\n")).digest("hex");
36177
36409
  }
36178
36410
  function readVerified(root, now = Date.now()) {
36179
36411
  const read2 = readRegularFileInRoot(root, VERIFIED_FILE, 256 * 1024);
@@ -36196,9 +36428,9 @@ function recordVerified(root, rec, now = Date.now()) {
36196
36428
  }
36197
36429
 
36198
36430
  // src/lib/prove/context.ts
36199
- var import_node_crypto17 = require("node:crypto");
36431
+ var import_node_crypto18 = require("node:crypto");
36200
36432
  var CONTEXT_BUDGET_MS = 2e3;
36201
- var sha256 = (s) => (0, import_node_crypto17.createHash)("sha256").update(s).digest("hex");
36433
+ var sha256 = (s) => (0, import_node_crypto18.createHash)("sha256").update(s).digest("hex");
36202
36434
  var TEST_PATH4 = /(^|\/)(tests?|__tests__|spec)\/|\.(test|spec)\.[a-z]+$/;
36203
36435
  function slice(content, f, maxLines) {
36204
36436
  const all = content.split("\n");
@@ -36387,7 +36619,7 @@ function workingTreeReader(root) {
36387
36619
  };
36388
36620
  }
36389
36621
  function sha256Of(content) {
36390
- return (0, import_node_crypto18.createHash)("sha256").update(content).digest("hex");
36622
+ return (0, import_node_crypto19.createHash)("sha256").update(content).digest("hex");
36391
36623
  }
36392
36624
  function defaultDeps(opts) {
36393
36625
  const env = opts.env ?? process.env;
@@ -36638,7 +36870,7 @@ async function runFormalPhase(input) {
36638
36870
  modelName = gen.name;
36639
36871
  const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
36640
36872
  writeFileInRootNoFollow(root, rel, gen.source);
36641
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
36873
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
36642
36874
  progress.model = { name: gen.name, file: rel, rounds: round };
36643
36875
  progress.step = "check";
36644
36876
  report = await deps.check(root, abs);
@@ -36699,11 +36931,11 @@ async function runFormalPhase(input) {
36699
36931
  const budget = Math.max(2e4, timeLeft() - 5e3);
36700
36932
  const byId = /* @__PURE__ */ new Map();
36701
36933
  let stoppedEarly = false;
36702
- await new Promise((resolve8) => {
36934
+ await new Promise((resolve9) => {
36703
36935
  let left = toReplay.length;
36704
- if (left === 0) return resolve8();
36936
+ if (left === 0) return resolve9();
36705
36937
  const settle = () => {
36706
- if (--left === 0) resolve8();
36938
+ if (--left === 0) resolve9();
36707
36939
  };
36708
36940
  for (const p of toReplay) {
36709
36941
  void (async () => {
@@ -36716,7 +36948,7 @@ async function runFormalPhase(input) {
36716
36948
  if (!stoppedEarly) byId.set(p.id, r);
36717
36949
  if (r.verdict === "reproduced" && !stoppedEarly && !isCrash(p)) {
36718
36950
  stoppedEarly = true;
36719
- resolve8();
36951
+ resolve9();
36720
36952
  }
36721
36953
  })().catch(() => {
36722
36954
  byId.set(p.id, null);
@@ -36760,7 +36992,7 @@ async function runFormalPhase(input) {
36760
36992
  return done({
36761
36993
  status: "checked",
36762
36994
  target,
36763
- model: { name: modelName, file: (0, import_node_path44.relative)(root, (0, import_node_path44.join)(root, modelFile)), rounds },
36995
+ model: { name: modelName, file: (0, import_node_path47.relative)(root, (0, import_node_path47.join)(root, modelFile)), rounds },
36764
36996
  properties: report.properties,
36765
36997
  findings
36766
36998
  });
@@ -36823,7 +37055,7 @@ async function generateAndCheck(root, req, opts) {
36823
37055
  }
36824
37056
  const rel = `${dir}/${gen.name}.lean`;
36825
37057
  writeFileInRootNoFollow(root, rel, gen.source);
36826
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
37058
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path47.join)(root, rel);
36827
37059
  const report = await opts.deps.check(root, abs);
36828
37060
  const abstracts = report.header?.abstracts ?? [];
36829
37061
  const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
@@ -36911,10 +37143,10 @@ function runFormalPhaseWithin(input) {
36911
37143
  if (left <= 0) return Promise.resolve(skippedOutcome("deadline", "no time left"));
36912
37144
  const progress = input.progress ?? {};
36913
37145
  let timer = null;
36914
- const cutoff = new Promise((resolve8) => {
37146
+ const cutoff = new Promise((resolve9) => {
36915
37147
  timer = setTimeout(() => {
36916
37148
  progress.cancelled = true;
36917
- resolve8(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
37149
+ resolve9(cutOffOutcome(progress, `hard stop after ${Math.round(left / 1e3)} s during ${progress.step ?? "setup"}`, left));
36918
37150
  }, left);
36919
37151
  });
36920
37152
  return Promise.race([runFormalPhase({ ...input, progress }), cutoff]).finally(() => {
@@ -36951,13 +37183,14 @@ function describeFormalOutcome(o) {
36951
37183
  var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
36952
37184
  var WRITERS_BUDGET_MS = 1500;
36953
37185
  var EXCERPT_MAX_LINES2 = 30;
37186
+ var VENDORED_READ_MAX_BYTES = 256 * 1024;
36954
37187
  var GUARD_BLOCK_CAP = 2;
36955
- var GUARD_ITER_FILE = (0, import_node_path45.join)(VERITY_DIR, ".guard-iteration");
37188
+ var GUARD_ITER_FILE = (0, import_node_path48.join)(VERITY_DIR, ".guard-iteration");
36956
37189
  function readPreToolUseStdin() {
36957
37190
  const empty = { command: "", cwd: null, sessionId: null };
36958
- return new Promise((resolve8) => {
37191
+ return new Promise((resolve9) => {
36959
37192
  try {
36960
- if (process.stdin.isTTY) return resolve8(empty);
37193
+ if (process.stdin.isTTY) return resolve9(empty);
36961
37194
  const chunks = [];
36962
37195
  let timer;
36963
37196
  let settled = false;
@@ -36970,7 +37203,7 @@ function readPreToolUseStdin() {
36970
37203
  process.stdin.removeListener("end", onEnd);
36971
37204
  process.stdin.removeListener("error", onError);
36972
37205
  process.stdin.pause();
36973
- resolve8(value);
37206
+ resolve9(value);
36974
37207
  };
36975
37208
  const onEnd = () => {
36976
37209
  try {
@@ -36991,13 +37224,13 @@ function readPreToolUseStdin() {
36991
37224
  process.stdin.on("error", onError);
36992
37225
  process.stdin.resume();
36993
37226
  } catch {
36994
- resolve8(empty);
37227
+ resolve9(empty);
36995
37228
  }
36996
37229
  });
36997
37230
  }
36998
37231
  function readIterMap() {
36999
37232
  try {
37000
- const raw = JSON.parse((0, import_node_fs59.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37233
+ const raw = JSON.parse((0, import_node_fs61.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37001
37234
  if (raw && typeof raw === "object") {
37002
37235
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
37003
37236
  return { [raw.moment]: raw.count };
@@ -37017,10 +37250,10 @@ function readIter(moment) {
37017
37250
  }
37018
37251
  function writeIter(moment, count) {
37019
37252
  try {
37020
- (0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
37253
+ (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37021
37254
  const map = readIterMap();
37022
37255
  map[moment] = count;
37023
- (0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37256
+ (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37024
37257
  } catch {
37025
37258
  }
37026
37259
  }
@@ -37030,10 +37263,10 @@ function resetIter(moment) {
37030
37263
  if (!(moment in map)) return;
37031
37264
  delete map[moment];
37032
37265
  if (Object.keys(map).length === 0) {
37033
- if ((0, import_node_fs59.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs59.unlinkSync)(GUARD_ITER_FILE);
37266
+ if ((0, import_node_fs61.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs61.unlinkSync)(GUARD_ITER_FILE);
37034
37267
  } else {
37035
- (0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
37036
- (0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37268
+ (0, import_node_fs61.mkdirSync)(VERITY_DIR, { recursive: true });
37269
+ (0, import_node_fs61.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37037
37270
  }
37038
37271
  } catch {
37039
37272
  }
@@ -37103,7 +37336,7 @@ function hasBlockingFinding(response, sentFiles) {
37103
37336
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
37104
37337
  const analyzable = filterAnalyzable(files);
37105
37338
  const securityFiles = filterSecurity(files);
37106
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs59.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
37339
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs61.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
37107
37340
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
37108
37341
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
37109
37342
  const requestBody = {
@@ -37340,7 +37573,15 @@ async function runGuard(opts, globals) {
37340
37573
  `Verity ${moment}: this command stages files as it runs and the resulting set could not be resolved (${range.refusal}); the ${verb} was allowed WITHOUT a Verity review. Stage first (\`git add \u2026\`) and re-run the ${verb} to have it reviewed.`
37341
37574
  );
37342
37575
  }
37343
- const files = rangeFiles(frame, range);
37576
+ const committed = revisionSource(
37577
+ frame.worktreeRoot ?? process.cwd(),
37578
+ range.kind === "push" && range.head !== "INDEX" ? range.head : null
37579
+ );
37580
+ const { review: files, vendored } = partitionVendored(rangeFiles(frame, range), (p) => {
37581
+ const read2 = committed.read(p, VENDORED_READ_MAX_BYTES);
37582
+ return read2.ok ? read2.content : null;
37583
+ });
37584
+ if (vendored.length > 0) logEvent("guard_vendored", { moment, n: vendored.length, paths: vendored.slice(0, 20) });
37344
37585
  if (files.length === 0) process.exit(0);
37345
37586
  const tokenResult = await resolveToken(globals.token);
37346
37587
  const urlResult = await resolveServiceUrl(globals.serviceUrl);
@@ -37720,8 +37961,8 @@ function registerIgnoreCommand(program2) {
37720
37961
  }
37721
37962
 
37722
37963
  // src/commands/waive.ts
37723
- var import_node_crypto19 = require("node:crypto");
37724
- var import_node_fs60 = require("node:fs");
37964
+ var import_node_crypto20 = require("node:crypto");
37965
+ var import_node_fs62 = require("node:fs");
37725
37966
  function registerWaiveCommand(program2) {
37726
37967
  program2.command("waive <pattern-id>").description("Record an accepted-risk disposition for an open finding (voids when the file changes)").option("--file <path>", "File the finding is anchored to, REPO-RELATIVE (recommended \u2014 narrows the waive)").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action(async (patternId, opts) => {
37727
37968
  const globals = program2.opts();
@@ -37750,7 +37991,7 @@ function registerWaiveCommand(program2) {
37750
37991
  if (opts.file) {
37751
37992
  body2.file = opts.file;
37752
37993
  try {
37753
- body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0, import_node_fs60.readFileSync)(opts.file)).digest("hex");
37994
+ body2.file_sha256 = (0, import_node_crypto20.createHash)("sha256").update((0, import_node_fs62.readFileSync)(opts.file)).digest("hex");
37754
37995
  } catch {
37755
37996
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
37756
37997
  process.exit(1);
@@ -37775,10 +38016,10 @@ function registerWaiveCommand(program2) {
37775
38016
  }
37776
38017
 
37777
38018
  // src/commands/init.ts
37778
- var import_node_fs65 = require("node:fs");
38019
+ var import_node_fs67 = require("node:fs");
37779
38020
  var import_promises20 = require("node:fs/promises");
37780
38021
  var import_yaml6 = __toESM2(require_dist());
37781
- var import_node_path49 = require("node:path");
38022
+ var import_node_path52 = require("node:path");
37782
38023
  var import_node_child_process19 = require("node:child_process");
37783
38024
 
37784
38025
  // src/lib/banner.ts
@@ -37857,7 +38098,7 @@ function printPhase(n, of, title, subtitle) {
37857
38098
  }
37858
38099
 
37859
38100
  // src/commands/doctor.ts
37860
- var import_node_fs61 = require("node:fs");
38101
+ var import_node_fs63 = require("node:fs");
37861
38102
 
37862
38103
  // src/lib/prereqs.ts
37863
38104
  var import_node_child_process16 = require("node:child_process");
@@ -37918,13 +38159,13 @@ function checkAnalysisCli() {
37918
38159
  }
37919
38160
  var INSTALL_TIMEOUT_MS = 12e4;
37920
38161
  function run3(command, args2, opts = {}) {
37921
- return new Promise((resolve8) => {
38162
+ return new Promise((resolve9) => {
37922
38163
  const child = (0, import_node_child_process16.spawn)(command, args2, {
37923
38164
  stdio: opts.inherit ? "inherit" : "pipe",
37924
38165
  timeout: INSTALL_TIMEOUT_MS
37925
38166
  });
37926
- child.on("error", () => resolve8(false));
37927
- child.on("close", (code) => resolve8(code === 0));
38167
+ child.on("error", () => resolve9(false));
38168
+ child.on("close", (code) => resolve9(code === 0));
37928
38169
  });
37929
38170
  }
37930
38171
  async function installAnalysisCli() {
@@ -38065,11 +38306,11 @@ async function buildReport() {
38065
38306
  const hooks = wiring.status;
38066
38307
  const provenance = cliProvenance();
38067
38308
  const telemetry = await checkTelemetry();
38068
- const hasConfig = (0, import_node_fs61.existsSync)(projectPath(CODACY_CONFIG_FILE));
38309
+ const hasConfig = (0, import_node_fs63.existsSync)(projectPath(CODACY_CONFIG_FILE));
38069
38310
  const artifacts = {
38070
- standard: (0, import_node_fs61.existsSync)(projectPath(STANDARD_FILE)),
38311
+ standard: (0, import_node_fs63.existsSync)(projectPath(STANDARD_FILE)),
38071
38312
  analysisConfig: hasConfig,
38072
- verityMd: (0, import_node_fs61.existsSync)(projectPath(VERITY_MD_FILE)),
38313
+ verityMd: (0, import_node_fs63.existsSync)(projectPath(VERITY_MD_FILE)),
38073
38314
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
38074
38315
  };
38075
38316
  const next = [];
@@ -38228,8 +38469,8 @@ function registerDoctorCommand(program2) {
38228
38469
  }
38229
38470
 
38230
38471
  // src/commands/migrate.ts
38231
- var import_node_fs62 = require("node:fs");
38232
- var import_node_path46 = require("node:path");
38472
+ var import_node_fs64 = require("node:fs");
38473
+ var import_node_path49 = require("node:path");
38233
38474
  var import_node_child_process17 = require("node:child_process");
38234
38475
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
38235
38476
  function defaultNpmRemover(pkg) {
@@ -38266,12 +38507,12 @@ async function runMigration(opts = {}) {
38266
38507
  return { actions, migrated: actions.length > 0 };
38267
38508
  }
38268
38509
  function migrateProjectDir(root, actions) {
38269
- const gateDir = (0, import_node_path46.join)(root, ".gate");
38270
- const verityDir = (0, import_node_path46.join)(root, ".verity");
38271
- if ((0, import_node_fs62.existsSync)(gateDir) && !(0, import_node_fs62.existsSync)(verityDir)) {
38510
+ const gateDir = (0, import_node_path49.join)(root, ".gate");
38511
+ const verityDir = (0, import_node_path49.join)(root, ".verity");
38512
+ if ((0, import_node_fs64.existsSync)(gateDir) && !(0, import_node_fs64.existsSync)(verityDir)) {
38272
38513
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
38273
38514
  }
38274
- if ((0, import_node_fs62.existsSync)(gateDir) && (0, import_node_fs62.existsSync)(verityDir)) {
38515
+ if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
38275
38516
  return migrateProjectDirCarry(gateDir, verityDir, actions);
38276
38517
  }
38277
38518
  return false;
@@ -38292,13 +38533,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
38292
38533
  }
38293
38534
  }
38294
38535
  if (moved) {
38295
- if ((0, import_node_fs62.existsSync)(gateDir)) {
38536
+ if ((0, import_node_fs64.existsSync)(gateDir)) {
38296
38537
  const carried = carryLegacyContents(gateDir, verityDir);
38297
38538
  if (carried > 0) {
38298
38539
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
38299
38540
  }
38300
38541
  try {
38301
- (0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
38542
+ (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
38302
38543
  } catch {
38303
38544
  }
38304
38545
  }
@@ -38314,18 +38555,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
38314
38555
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
38315
38556
  }
38316
38557
  try {
38317
- (0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
38558
+ (0, import_node_fs64.rmSync)(gateDir, { recursive: true, force: true });
38318
38559
  } catch {
38319
38560
  }
38320
38561
  return carried > 0;
38321
38562
  }
38322
38563
  function migrateGlobalCredentials(home, actions) {
38323
38564
  if (!home) return;
38324
- const gateCreds = (0, import_node_path46.join)(home, ".gate", "credentials");
38325
- const verityCreds = (0, import_node_path46.join)(home, ".verity", "credentials");
38326
- if (!(0, import_node_fs62.existsSync)(gateCreds)) return;
38327
- if (!(0, import_node_fs62.existsSync)(verityCreds)) {
38328
- (0, import_node_fs62.mkdirSync)((0, import_node_path46.join)(home, ".verity"), { recursive: true });
38565
+ const gateCreds = (0, import_node_path49.join)(home, ".gate", "credentials");
38566
+ const verityCreds = (0, import_node_path49.join)(home, ".verity", "credentials");
38567
+ if (!(0, import_node_fs64.existsSync)(gateCreds)) return;
38568
+ if (!(0, import_node_fs64.existsSync)(verityCreds)) {
38569
+ (0, import_node_fs64.mkdirSync)((0, import_node_path49.join)(home, ".verity"), { recursive: true });
38329
38570
  moveFile(gateCreds, verityCreds);
38330
38571
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
38331
38572
  return;
@@ -38347,8 +38588,8 @@ async function migrateLegacyHooks(root, actions) {
38347
38588
  }
38348
38589
  }
38349
38590
  async function migrateClaudeMd(root, actions) {
38350
- const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
38351
- const hadLegacyBlock = (0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38591
+ const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38592
+ const hadLegacyBlock = (0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38352
38593
  if (!hadLegacyBlock) return;
38353
38594
  try {
38354
38595
  await ensureClaudeMdPointer(root);
@@ -38358,9 +38599,9 @@ async function migrateClaudeMd(root, actions) {
38358
38599
  }
38359
38600
  }
38360
38601
  function migrateStandardFile(root, actions) {
38361
- const gateMd = (0, import_node_path46.join)(root, "GATE.md");
38362
- const verityMd = (0, import_node_path46.join)(root, "VERITY.md");
38363
- if (!(0, import_node_fs62.existsSync)(gateMd) || (0, import_node_fs62.existsSync)(verityMd)) return;
38602
+ const gateMd = (0, import_node_path49.join)(root, "GATE.md");
38603
+ const verityMd = (0, import_node_path49.join)(root, "VERITY.md");
38604
+ if (!(0, import_node_fs64.existsSync)(gateMd) || (0, import_node_fs64.existsSync)(verityMd)) return;
38364
38605
  let moved = false;
38365
38606
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
38366
38607
  try {
@@ -38372,12 +38613,12 @@ function migrateStandardFile(root, actions) {
38372
38613
  if (!moved) moveFile(gateMd, verityMd);
38373
38614
  const content = readFileSyncSafe(verityMd);
38374
38615
  const refreshed = content.split("GATE.md").join("VERITY.md");
38375
- if (refreshed !== content) (0, import_node_fs62.writeFileSync)(verityMd, refreshed);
38616
+ if (refreshed !== content) (0, import_node_fs64.writeFileSync)(verityMd, refreshed);
38376
38617
  actions.push("Renamed GATE.md \u2192 VERITY.md");
38377
38618
  }
38378
38619
  async function migrateTelemetryHeaders(root, actions) {
38379
- const file = (0, import_node_path46.join)(root, ".claude", "settings.local.json");
38380
- if (!(0, import_node_fs62.existsSync)(file)) return;
38620
+ const file = (0, import_node_path49.join)(root, ".claude", "settings.local.json");
38621
+ if (!(0, import_node_fs64.existsSync)(file)) return;
38381
38622
  let settings;
38382
38623
  try {
38383
38624
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -38425,14 +38666,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
38425
38666
  }
38426
38667
  if (toAppend.length > 0) {
38427
38668
  const sep5 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
38428
- (0, import_node_fs62.writeFileSync)(verityCreds, verityContent + sep5 + toAppend.join("\n") + "\n");
38669
+ (0, import_node_fs64.writeFileSync)(verityCreds, verityContent + sep5 + toAppend.join("\n") + "\n");
38429
38670
  }
38430
- (0, import_node_fs62.rmSync)(gateCreds, { force: true });
38671
+ (0, import_node_fs64.rmSync)(gateCreds, { force: true });
38431
38672
  return toAppend.length;
38432
38673
  }
38433
38674
  function readFileSyncSafe(path) {
38434
38675
  try {
38435
- return (0, import_node_fs62.readFileSync)(path, "utf-8");
38676
+ return (0, import_node_fs64.readFileSync)(path, "utf-8");
38436
38677
  } catch {
38437
38678
  return "";
38438
38679
  }
@@ -38447,35 +38688,35 @@ function hasStagedChanges(root) {
38447
38688
  }
38448
38689
  function moveDir(from, to) {
38449
38690
  try {
38450
- (0, import_node_fs62.renameSync)(from, to);
38691
+ (0, import_node_fs64.renameSync)(from, to);
38451
38692
  } catch (err2) {
38452
38693
  if (err2.code !== "EXDEV") throw err2;
38453
- (0, import_node_fs62.cpSync)(from, to, { recursive: true });
38454
- (0, import_node_fs62.rmSync)(from, { recursive: true, force: true });
38694
+ (0, import_node_fs64.cpSync)(from, to, { recursive: true });
38695
+ (0, import_node_fs64.rmSync)(from, { recursive: true, force: true });
38455
38696
  }
38456
38697
  }
38457
38698
  function moveFile(from, to) {
38458
38699
  try {
38459
- (0, import_node_fs62.renameSync)(from, to);
38700
+ (0, import_node_fs64.renameSync)(from, to);
38460
38701
  } catch (err2) {
38461
38702
  if (err2.code !== "EXDEV") throw err2;
38462
- (0, import_node_fs62.cpSync)(from, to);
38463
- (0, import_node_fs62.rmSync)(from, { force: true });
38703
+ (0, import_node_fs64.cpSync)(from, to);
38704
+ (0, import_node_fs64.rmSync)(from, { force: true });
38464
38705
  }
38465
38706
  }
38466
38707
  function carryLegacyContents(gateDir, verityDir) {
38467
38708
  let copied = 0;
38468
38709
  const walk2 = (relDir) => {
38469
- const srcDir = (0, import_node_path46.join)(gateDir, relDir);
38470
- for (const entry of (0, import_node_fs62.readdirSync)(srcDir)) {
38471
- const rel = relDir ? (0, import_node_path46.join)(relDir, entry) : entry;
38472
- const src = (0, import_node_path46.join)(gateDir, rel);
38473
- const dest = (0, import_node_path46.join)(verityDir, rel);
38474
- if ((0, import_node_fs62.statSync)(src).isDirectory()) {
38710
+ const srcDir = (0, import_node_path49.join)(gateDir, relDir);
38711
+ for (const entry of (0, import_node_fs64.readdirSync)(srcDir)) {
38712
+ const rel = relDir ? (0, import_node_path49.join)(relDir, entry) : entry;
38713
+ const src = (0, import_node_path49.join)(gateDir, rel);
38714
+ const dest = (0, import_node_path49.join)(verityDir, rel);
38715
+ if ((0, import_node_fs64.statSync)(src).isDirectory()) {
38475
38716
  walk2(rel);
38476
- } else if (!(0, import_node_fs62.existsSync)(dest)) {
38477
- (0, import_node_fs62.mkdirSync)((0, import_node_path46.dirname)(dest), { recursive: true });
38478
- (0, import_node_fs62.cpSync)(src, dest);
38717
+ } else if (!(0, import_node_fs64.existsSync)(dest)) {
38718
+ (0, import_node_fs64.mkdirSync)((0, import_node_path49.dirname)(dest), { recursive: true });
38719
+ (0, import_node_fs64.cpSync)(src, dest);
38479
38720
  copied++;
38480
38721
  }
38481
38722
  }
@@ -38484,22 +38725,22 @@ function carryLegacyContents(gateDir, verityDir) {
38484
38725
  return copied;
38485
38726
  }
38486
38727
  async function needsMigration(root = repoRoot()) {
38487
- const gateDir = (0, import_node_path46.join)(root, ".gate");
38488
- const verityDir = (0, import_node_path46.join)(root, ".verity");
38489
- if ((0, import_node_fs62.existsSync)(gateDir) && !(0, import_node_fs62.existsSync)(verityDir)) return true;
38490
- if ((0, import_node_fs62.existsSync)(gateDir) && (0, import_node_fs62.existsSync)(verityDir)) {
38491
- if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(gateDir, "credentials")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(verityDir, "credentials"))) {
38728
+ const gateDir = (0, import_node_path49.join)(root, ".gate");
38729
+ const verityDir = (0, import_node_path49.join)(root, ".verity");
38730
+ if ((0, import_node_fs64.existsSync)(gateDir) && !(0, import_node_fs64.existsSync)(verityDir)) return true;
38731
+ if ((0, import_node_fs64.existsSync)(gateDir) && (0, import_node_fs64.existsSync)(verityDir)) {
38732
+ if ((0, import_node_fs64.existsSync)((0, import_node_path49.join)(gateDir, "credentials")) && !(0, import_node_fs64.existsSync)((0, import_node_path49.join)(verityDir, "credentials"))) {
38492
38733
  return true;
38493
38734
  }
38494
- if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(gateDir, "memory")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(verityDir, "memory"))) {
38735
+ if ((0, import_node_fs64.existsSync)((0, import_node_path49.join)(gateDir, "memory")) && !(0, import_node_fs64.existsSync)((0, import_node_path49.join)(verityDir, "memory"))) {
38495
38736
  return true;
38496
38737
  }
38497
38738
  }
38498
- const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
38499
- if ((0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38739
+ const claudeMd = (0, import_node_path49.join)(root, "CLAUDE.md");
38740
+ if ((0, import_node_fs64.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38500
38741
  return true;
38501
38742
  }
38502
- if ((0, import_node_fs62.existsSync)((0, import_node_path46.join)(root, "GATE.md")) && !(0, import_node_fs62.existsSync)((0, import_node_path46.join)(root, "VERITY.md"))) {
38743
+ if ((0, import_node_fs64.existsSync)((0, import_node_path49.join)(root, "GATE.md")) && !(0, import_node_fs64.existsSync)((0, import_node_path49.join)(root, "VERITY.md"))) {
38503
38744
  return true;
38504
38745
  }
38505
38746
  if (await hasLegacyHooksAt(root)) return true;
@@ -38628,7 +38869,7 @@ function runSelect(opts) {
38628
38869
  cursor: initialIdx[0] ?? 0,
38629
38870
  chosen: new Set(mode2 === "single" ? [initialIdx[0] ?? 0] : initialIdx)
38630
38871
  };
38631
- return new Promise((resolve8) => {
38872
+ return new Promise((resolve9) => {
38632
38873
  let painted = 0;
38633
38874
  let settled = false;
38634
38875
  const draw = () => {
@@ -38676,7 +38917,7 @@ function runSelect(opts) {
38676
38917
  if (settled) return;
38677
38918
  settled = true;
38678
38919
  restore();
38679
- resolve8(value);
38920
+ resolve9(value);
38680
38921
  };
38681
38922
  readline2.emitKeypressEvents(input);
38682
38923
  input.setRawMode(true);
@@ -38697,9 +38938,9 @@ async function askLine(question, io = {}) {
38697
38938
  output: io.output ?? process.stdout
38698
38939
  });
38699
38940
  try {
38700
- return await new Promise((resolve8) => {
38701
- rl.question(question).then((a) => resolve8(a.trim())).catch(() => resolve8(null));
38702
- rl.once("close", () => setImmediate(() => resolve8(null)));
38941
+ return await new Promise((resolve9) => {
38942
+ rl.question(question).then((a) => resolve9(a.trim())).catch(() => resolve9(null));
38943
+ rl.once("close", () => setImmediate(() => resolve9(null)));
38703
38944
  });
38704
38945
  } finally {
38705
38946
  rl.close();
@@ -38780,11 +39021,11 @@ async function promptMultiSelect(question, choices, fallback) {
38780
39021
  }
38781
39022
 
38782
39023
  // src/lib/prove/lean-install.ts
38783
- var import_node_fs63 = require("node:fs");
38784
- var import_node_crypto20 = require("node:crypto");
39024
+ var import_node_fs65 = require("node:fs");
39025
+ var import_node_crypto21 = require("node:crypto");
38785
39026
  var import_node_child_process18 = require("node:child_process");
38786
39027
  var import_node_os10 = require("node:os");
38787
- var import_node_path47 = require("node:path");
39028
+ var import_node_path50 = require("node:path");
38788
39029
  var import_promises18 = require("node:stream/promises");
38789
39030
  var import_node_stream = require("node:stream");
38790
39031
  var RELEASES = "https://releases.lean-lang.org/lean4";
@@ -38795,10 +39036,10 @@ function freeBytes(dir) {
38795
39036
  let d = dir;
38796
39037
  for (let i2 = 0; i2 < 64; i2++) {
38797
39038
  try {
38798
- const st = (0, import_node_fs63.statfsSync)(d);
39039
+ const st = (0, import_node_fs65.statfsSync)(d);
38799
39040
  return Number(st.bavail) * Number(st.bsize);
38800
39041
  } catch {
38801
- const up = (0, import_node_path47.join)(d, "..");
39042
+ const up = (0, import_node_path50.join)(d, "..");
38802
39043
  if (up === d) return null;
38803
39044
  d = up;
38804
39045
  }
@@ -38818,9 +39059,9 @@ function expectedSha256(asset, version = pinnedVersion()) {
38818
39059
  return LEAN_ASSET_SHA256[version]?.[asset] ?? null;
38819
39060
  }
38820
39061
  function sha256File(path) {
38821
- return new Promise((resolve8, reject) => {
38822
- const hash = (0, import_node_crypto20.createHash)("sha256");
38823
- (0, import_node_fs63.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve8(hash.digest("hex"))).on("error", reject);
39062
+ return new Promise((resolve9, reject) => {
39063
+ const hash = (0, import_node_crypto21.createHash)("sha256");
39064
+ (0, import_node_fs65.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve9(hash.digest("hex"))).on("error", reject);
38824
39065
  });
38825
39066
  }
38826
39067
  async function verifyDownload(zip, asset, version = pinnedVersion()) {
@@ -38840,7 +39081,7 @@ function leanAssetName(version = pinnedVersion()) {
38840
39081
  return suffix ? `lean-${v}-${suffix}.zip` : null;
38841
39082
  }
38842
39083
  function pinnedVersionDir(env = process.env) {
38843
- return (0, import_node_path47.join)(verityLeanHome(env), pinnedVersion());
39084
+ return (0, import_node_path50.join)(verityLeanHome(env), pinnedVersion());
38844
39085
  }
38845
39086
  function lakeBinary() {
38846
39087
  return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
@@ -38851,12 +39092,12 @@ function unzip(zip, dest) {
38851
39092
  for (const [cmd, args2] of attempts) {
38852
39093
  try {
38853
39094
  (0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
38854
- if ((0, import_node_fs63.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
39095
+ if ((0, import_node_fs65.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
38855
39096
  errors.push(`${cmd}: produced nothing`);
38856
39097
  } catch (err2) {
38857
39098
  errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
38858
39099
  try {
38859
- for (const e of (0, import_node_fs63.readdirSync)(dest)) (0, import_node_fs63.rmSync)((0, import_node_path47.join)(dest, e), { recursive: true, force: true });
39100
+ for (const e of (0, import_node_fs65.readdirSync)(dest)) (0, import_node_fs65.rmSync)((0, import_node_path50.join)(dest, e), { recursive: true, force: true });
38860
39101
  } catch {
38861
39102
  }
38862
39103
  }
@@ -38882,7 +39123,7 @@ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
38882
39123
  seen += chunk.length;
38883
39124
  onProgress(seen, total);
38884
39125
  });
38885
- await (0, import_promises18.pipeline)(stream, (0, import_node_fs63.createWriteStream)(dest), { signal: ctrl.signal });
39126
+ await (0, import_promises18.pipeline)(stream, (0, import_node_fs65.createWriteStream)(dest), { signal: ctrl.signal });
38886
39127
  } catch (err2) {
38887
39128
  if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
38888
39129
  throw err2;
@@ -38932,10 +39173,10 @@ async function installLean(opts = {}) {
38932
39173
  const gb = (n) => (n / 1024 ** 3).toFixed(1);
38933
39174
  return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
38934
39175
  }
38935
- const tmp = (0, import_node_path47.join)(home, ".tmp");
38936
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
38937
- (0, import_node_fs63.mkdirSync)(tmp, { recursive: true });
38938
- const zip = (0, import_node_path47.join)(tmp, asset);
39176
+ const tmp = (0, import_node_path50.join)(home, ".tmp");
39177
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
39178
+ (0, import_node_fs65.mkdirSync)(tmp, { recursive: true });
39179
+ const zip = (0, import_node_path50.join)(tmp, asset);
38939
39180
  say(`downloading ${url}`);
38940
39181
  let lastPct = -1;
38941
39182
  try {
@@ -38948,40 +39189,40 @@ async function installLean(opts = {}) {
38948
39189
  }
38949
39190
  });
38950
39191
  } catch (err2) {
38951
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39192
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38952
39193
  return { ok: false, error: err2.message };
38953
39194
  }
38954
39195
  say("verifying checksum");
38955
39196
  const verified = await verifyDownload(zip, asset);
38956
39197
  if (!verified.ok) {
38957
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39198
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38958
39199
  return { ok: false, error: verified.error };
38959
39200
  }
38960
39201
  say("unpacking (this takes a minute)");
38961
- const unpack = (0, import_node_path47.join)(tmp, "unpack");
38962
- (0, import_node_fs63.mkdirSync)(unpack);
39202
+ const unpack = (0, import_node_path50.join)(tmp, "unpack");
39203
+ (0, import_node_fs65.mkdirSync)(unpack);
38963
39204
  const unpacked = unzip(zip, unpack);
38964
39205
  if (!unpacked.ok) {
38965
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39206
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38966
39207
  return { ok: false, error: `unpack failed: ${unpacked.error}` };
38967
39208
  }
38968
- const entries = (0, import_node_fs63.readdirSync)(unpack);
38969
- const top = entries.length === 1 && (0, import_node_fs63.statSync)((0, import_node_path47.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path47.join)(unpack, entries[0]) : unpack;
38970
- if (!(0, import_node_fs63.existsSync)((0, import_node_path47.join)(top, "bin", lakeBinary()))) {
38971
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39209
+ const entries = (0, import_node_fs65.readdirSync)(unpack);
39210
+ const top = entries.length === 1 && (0, import_node_fs65.statSync)((0, import_node_path50.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path50.join)(unpack, entries[0]) : unpack;
39211
+ if (!(0, import_node_fs65.existsSync)((0, import_node_path50.join)(top, "bin", lakeBinary()))) {
39212
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38972
39213
  return { ok: false, error: "the archive did not contain bin/lake" };
38973
39214
  }
38974
- (0, import_node_fs63.rmSync)(dir, { recursive: true, force: true });
38975
- (0, import_node_fs63.mkdirSync)(home, { recursive: true });
38976
- (0, import_node_fs63.renameSync)(top, dir);
38977
- (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
39215
+ (0, import_node_fs65.rmSync)(dir, { recursive: true, force: true });
39216
+ (0, import_node_fs65.mkdirSync)(home, { recursive: true });
39217
+ (0, import_node_fs65.renameSync)(top, dir);
39218
+ (0, import_node_fs65.rmSync)(tmp, { recursive: true, force: true });
38978
39219
  return { ok: true, dir };
38979
39220
  }
38980
39221
 
38981
39222
  // src/lib/remote-config.ts
38982
- var import_node_fs64 = require("node:fs");
39223
+ var import_node_fs66 = require("node:fs");
38983
39224
  var import_promises19 = require("node:fs/promises");
38984
- var import_node_path48 = require("node:path");
39225
+ var import_node_path51 = require("node:path");
38985
39226
  var import_yaml5 = __toESM2(require_dist());
38986
39227
  var IGNORE_RIDER = "verityignore";
38987
39228
  async function fetchRemoteSetup(opts) {
@@ -39026,7 +39267,7 @@ async function adoptRemoteSetup(found, opts) {
39026
39267
  written.push(STANDARD_FILE);
39027
39268
  if (rider !== null) {
39028
39269
  const localIgnore = projectPath(VERITYIGNORE_FILE);
39029
- if (!(0, import_node_fs64.existsSync)(localIgnore)) {
39270
+ if (!(0, import_node_fs66.existsSync)(localIgnore)) {
39030
39271
  await writeOut(VERITYIGNORE_FILE, rider);
39031
39272
  written.push(VERITYIGNORE_FILE);
39032
39273
  } else {
@@ -39059,7 +39300,7 @@ async function adoptRemoteSetup(found, opts) {
39059
39300
  }
39060
39301
  async function writeOut(relative6, body2) {
39061
39302
  const target = projectPath(relative6);
39062
- await (0, import_promises19.mkdir)((0, import_node_path48.dirname)(target), { recursive: true });
39303
+ await (0, import_promises19.mkdir)((0, import_node_path51.dirname)(target), { recursive: true });
39063
39304
  await (0, import_promises19.writeFile)(target, body2);
39064
39305
  }
39065
39306
  function describeRemote(found) {
@@ -39176,15 +39417,15 @@ async function runOptionalAuth(resolution, opts = {}) {
39176
39417
  }
39177
39418
  function resolveDataDir2() {
39178
39419
  const candidates2 = [
39179
- (0, import_node_path49.join)(__dirname, "..", "data"),
39420
+ (0, import_node_path52.join)(__dirname, "..", "data"),
39180
39421
  // installed: node_modules/@codacy/verity-cli/data
39181
- (0, import_node_path49.join)(__dirname, "..", "..", "data"),
39422
+ (0, import_node_path52.join)(__dirname, "..", "..", "data"),
39182
39423
  // edge case: nested resolution
39183
- (0, import_node_path49.join)(process.cwd(), "cli", "data")
39424
+ (0, import_node_path52.join)(process.cwd(), "cli", "data")
39184
39425
  // local dev: running from repo root
39185
39426
  ];
39186
39427
  for (const candidate of candidates2) {
39187
- if ((0, import_node_fs65.existsSync)((0, import_node_path49.join)(candidate, "skills"))) {
39428
+ if ((0, import_node_fs67.existsSync)((0, import_node_path52.join)(candidate, "skills"))) {
39188
39429
  return candidate;
39189
39430
  }
39190
39431
  }
@@ -39200,9 +39441,9 @@ async function skillIsCurrent(src, dest) {
39200
39441
  const list2 = (dir) => {
39201
39442
  const out2 = [];
39202
39443
  const walk2 = (d, prefix) => {
39203
- for (const e of (0, import_node_fs65.readdirSync)(d, { withFileTypes: true })) {
39444
+ for (const e of (0, import_node_fs67.readdirSync)(d, { withFileTypes: true })) {
39204
39445
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
39205
- if (e.isDirectory()) walk2((0, import_node_path49.join)(d, e.name), rel);
39446
+ if (e.isDirectory()) walk2((0, import_node_path52.join)(d, e.name), rel);
39206
39447
  else if (e.isFile()) out2.push(rel);
39207
39448
  }
39208
39449
  };
@@ -39213,8 +39454,8 @@ async function skillIsCurrent(src, dest) {
39213
39454
  const shipped = list2(src);
39214
39455
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
39215
39456
  for (const rel of shipped) {
39216
- const a = await (0, import_promises20.readFile)((0, import_node_path49.join)(src, rel), "utf-8");
39217
- const b = await (0, import_promises20.readFile)((0, import_node_path49.join)(dest, rel), "utf-8");
39457
+ const a = await (0, import_promises20.readFile)((0, import_node_path52.join)(src, rel), "utf-8");
39458
+ const b = await (0, import_promises20.readFile)((0, import_node_path52.join)(dest, rel), "utf-8");
39218
39459
  if (a !== b) return false;
39219
39460
  }
39220
39461
  return true;
@@ -39417,7 +39658,7 @@ async function synthesizeLocally(opts) {
39417
39658
  async function healStaleAnalysisConfig(globals) {
39418
39659
  const configPath = projectPath(CODACY_CONFIG_FILE);
39419
39660
  const standardPath = projectPath(STANDARD_FILE);
39420
- if (!(0, import_node_fs65.existsSync)(configPath) || !(0, import_node_fs65.existsSync)(standardPath)) return;
39661
+ if (!(0, import_node_fs67.existsSync)(configPath) || !(0, import_node_fs67.existsSync)(standardPath)) return;
39421
39662
  const validation = validatePatternIds();
39422
39663
  if (validation.status !== "invalid") return;
39423
39664
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -39514,17 +39755,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
39514
39755
  async function installSkills(force, step) {
39515
39756
  step("Installing skills");
39516
39757
  const dataDir = resolveDataDir2();
39517
- const skillsSource = (0, import_node_path49.join)(dataDir, "skills");
39758
+ const skillsSource = (0, import_node_path52.join)(dataDir, "skills");
39518
39759
  const skillsDest = ".claude/skills";
39519
39760
  let skillsInstalled = 0;
39520
39761
  for (const skill of SKILLS) {
39521
- const src = (0, import_node_path49.join)(skillsSource, skill);
39522
- const dest = (0, import_node_path49.join)(skillsDest, skill);
39523
- if (!(0, import_node_fs65.existsSync)(src)) {
39762
+ const src = (0, import_node_path52.join)(skillsSource, skill);
39763
+ const dest = (0, import_node_path52.join)(skillsDest, skill);
39764
+ if (!(0, import_node_fs67.existsSync)(src)) {
39524
39765
  printWarn(` Skill data not found: ${skill}`);
39525
39766
  continue;
39526
39767
  }
39527
- if ((0, import_node_fs65.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39768
+ if ((0, import_node_fs67.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39528
39769
  skillsInstalled++;
39529
39770
  continue;
39530
39771
  }
@@ -39724,7 +39965,7 @@ function registerInitCommand(program2) {
39724
39965
  const staleMarker = clearStalePluginMarker();
39725
39966
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
39726
39967
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
39727
- const isProject = projectMarkers.some((m) => (0, import_node_fs65.existsSync)(m));
39968
+ const isProject = projectMarkers.some((m) => (0, import_node_fs67.existsSync)(m));
39728
39969
  if (!isProject) {
39729
39970
  printError("No project detected in the current directory.");
39730
39971
  printInfo('Run "verity init" from your project root.');
@@ -39827,7 +40068,7 @@ function registerInitCommand(program2) {
39827
40068
  untrackMemory: opts.untrackMemory === true,
39828
40069
  untrackState: opts.untrackState === true
39829
40070
  });
39830
- const globalVerityDir = (0, import_node_path49.join)(process.env.HOME ?? "", ".verity");
40071
+ const globalVerityDir = (0, import_node_path52.join)(process.env.HOME ?? "", ".verity");
39831
40072
  await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
39832
40073
  console.log("");
39833
40074
  step("Wiring Claude Code hooks");
@@ -39902,7 +40143,7 @@ function registerInitCommand(program2) {
39902
40143
  }
39903
40144
  step("Your project's Standard");
39904
40145
  let haveStandard = false;
39905
- if ((0, import_node_fs65.existsSync)(projectPath(STANDARD_FILE))) {
40146
+ if ((0, import_node_fs67.existsSync)(projectPath(STANDARD_FILE))) {
39906
40147
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
39907
40148
  haveStandard = true;
39908
40149
  } else {
@@ -39932,7 +40173,7 @@ function registerInitCommand(program2) {
39932
40173
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
39933
40174
  init: {
39934
40175
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
39935
- cli_version: true ? "0.34.0-experimental.92a1040" : "dev"
40176
+ cli_version: true ? "0.34.0-experimental.afcb0e6" : "dev"
39936
40177
  }
39937
40178
  });
39938
40179
  } catch (err2) {
@@ -39982,8 +40223,8 @@ function registerInitCommand(program2) {
39982
40223
  }
39983
40224
 
39984
40225
  // src/commands/uninstall.ts
39985
- var import_node_fs66 = require("node:fs");
39986
- var import_node_path50 = require("node:path");
40226
+ var import_node_fs68 = require("node:fs");
40227
+ var import_node_path53 = require("node:path");
39987
40228
  function registerUninstallCommand(program2) {
39988
40229
  program2.command("uninstall").description("Remove Verity from this project (skills, hooks, .verity/, VERITY.md)").option("--dry-run", "Show what would be removed without doing it").option("--purge-global", "Also remove ~/.verity/ (deletes saved tokens \u2014 reconnect requires re-registration)").option("--keep-verity-md", "Keep the project root VERITY.md file").action(async (opts) => {
39989
40230
  const dryRun = opts.dryRun ?? false;
@@ -39992,11 +40233,11 @@ function registerUninstallCommand(program2) {
39992
40233
  const actions = [];
39993
40234
  const skillsRoot = projectPath(".claude/skills");
39994
40235
  for (const name2 of PROJECT_SKILL_NAMES) {
39995
- const dir = (0, import_node_path50.join)(skillsRoot, name2);
39996
- if ((0, import_node_fs66.existsSync)(dir)) {
40236
+ const dir = (0, import_node_path53.join)(skillsRoot, name2);
40237
+ if ((0, import_node_fs68.existsSync)(dir)) {
39997
40238
  actions.push({
39998
40239
  label: `Remove .claude/skills/${name2}/`,
39999
- apply: () => (0, import_node_fs66.rmSync)(dir, { recursive: true, force: true })
40240
+ apply: () => (0, import_node_fs68.rmSync)(dir, { recursive: true, force: true })
40000
40241
  });
40001
40242
  }
40002
40243
  }
@@ -40010,24 +40251,24 @@ function registerUninstallCommand(program2) {
40010
40251
  });
40011
40252
  }
40012
40253
  const verityDir = projectPath(VERITY_DIR);
40013
- if ((0, import_node_fs66.existsSync)(verityDir)) {
40254
+ if ((0, import_node_fs68.existsSync)(verityDir)) {
40014
40255
  actions.push({
40015
40256
  label: `Remove ${VERITY_DIR}/`,
40016
- apply: () => (0, import_node_fs66.rmSync)(verityDir, { recursive: true, force: true })
40257
+ apply: () => (0, import_node_fs68.rmSync)(verityDir, { recursive: true, force: true })
40017
40258
  });
40018
40259
  }
40019
40260
  if (!keepVerityMd) {
40020
40261
  const verityMd = projectPath(VERITY_MD_FILE);
40021
- if ((0, import_node_fs66.existsSync)(verityMd)) {
40262
+ if ((0, import_node_fs68.existsSync)(verityMd)) {
40022
40263
  actions.push({
40023
40264
  label: `Remove ${VERITY_MD_FILE}`,
40024
- apply: () => (0, import_node_fs66.rmSync)(verityMd, { force: true })
40265
+ apply: () => (0, import_node_fs68.rmSync)(verityMd, { force: true })
40025
40266
  });
40026
40267
  }
40027
40268
  }
40028
40269
  const cleanupEmptyDir = (path) => {
40029
- if ((0, import_node_fs66.existsSync)(path) && (0, import_node_fs66.statSync)(path).isDirectory() && (0, import_node_fs66.readdirSync)(path).length === 0) {
40030
- (0, import_node_fs66.rmdirSync)(path);
40270
+ if ((0, import_node_fs68.existsSync)(path) && (0, import_node_fs68.statSync)(path).isDirectory() && (0, import_node_fs68.readdirSync)(path).length === 0) {
40271
+ (0, import_node_fs68.rmdirSync)(path);
40031
40272
  }
40032
40273
  };
40033
40274
  actions.push({
@@ -40038,11 +40279,11 @@ function registerUninstallCommand(program2) {
40038
40279
  }
40039
40280
  });
40040
40281
  const home = process.env.HOME ?? "";
40041
- const globalVerityDir = (0, import_node_path50.join)(home, ".verity");
40042
- if (purgeGlobal && (0, import_node_fs66.existsSync)(globalVerityDir)) {
40282
+ const globalVerityDir = (0, import_node_path53.join)(home, ".verity");
40283
+ if (purgeGlobal && (0, import_node_fs68.existsSync)(globalVerityDir)) {
40043
40284
  actions.push({
40044
40285
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
40045
- apply: () => (0, import_node_fs66.rmSync)(globalVerityDir, { recursive: true, force: true })
40286
+ apply: () => (0, import_node_fs68.rmSync)(globalVerityDir, { recursive: true, force: true })
40046
40287
  });
40047
40288
  }
40048
40289
  if (actions.length === 0) {
@@ -40236,8 +40477,8 @@ function registerTaskCommands(program2) {
40236
40477
  }
40237
40478
 
40238
40479
  // src/commands/reset.ts
40239
- var import_node_fs67 = require("node:fs");
40240
- var import_node_path51 = require("node:path");
40480
+ var import_node_fs69 = require("node:fs");
40481
+ var import_node_path54 = require("node:path");
40241
40482
  function registerResetCommand(program2) {
40242
40483
  program2.command("reset").description("Close the current task and clear transient state").option("--keep-task", "Only purge caches; leave the current task open").option("--all", "Also purge diagnostic logs (.verity/.logs/)").action(async (opts) => {
40243
40484
  const globals = program2.opts();
@@ -40274,11 +40515,11 @@ function registerResetCommand(program2) {
40274
40515
  }
40275
40516
  const cacheDir = projectPath(CACHE_DIR);
40276
40517
  let purged = 0;
40277
- if ((0, import_node_fs67.existsSync)(cacheDir)) {
40278
- for (const entry of (0, import_node_fs67.readdirSync)(cacheDir)) {
40518
+ if ((0, import_node_fs69.existsSync)(cacheDir)) {
40519
+ for (const entry of (0, import_node_fs69.readdirSync)(cacheDir)) {
40279
40520
  if (entry.startsWith("pending-")) {
40280
40521
  try {
40281
- (0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(cacheDir, entry));
40522
+ (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(cacheDir, entry));
40282
40523
  purged++;
40283
40524
  } catch {
40284
40525
  }
@@ -40293,19 +40534,19 @@ function registerResetCommand(program2) {
40293
40534
  projectPath(`${VERITY_DIR}/.last-analysis`)
40294
40535
  ];
40295
40536
  for (const file of filesToClear) {
40296
- if ((0, import_node_fs67.existsSync)(file)) {
40537
+ if ((0, import_node_fs69.existsSync)(file)) {
40297
40538
  try {
40298
- (0, import_node_fs67.writeFileSync)(file, "");
40539
+ (0, import_node_fs69.writeFileSync)(file, "");
40299
40540
  } catch {
40300
40541
  }
40301
40542
  }
40302
40543
  }
40303
40544
  if (opts.all) {
40304
40545
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
40305
- if ((0, import_node_fs67.existsSync)(logsDir)) {
40306
- for (const entry of (0, import_node_fs67.readdirSync)(logsDir)) {
40546
+ if ((0, import_node_fs69.existsSync)(logsDir)) {
40547
+ for (const entry of (0, import_node_fs69.readdirSync)(logsDir)) {
40307
40548
  try {
40308
- (0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(logsDir, entry));
40549
+ (0, import_node_fs69.unlinkSync)((0, import_node_path54.join)(logsDir, entry));
40309
40550
  } catch {
40310
40551
  }
40311
40552
  }
@@ -40317,7 +40558,7 @@ function registerResetCommand(program2) {
40317
40558
  }
40318
40559
 
40319
40560
  // src/commands/reflect.ts
40320
- var import_node_fs68 = require("node:fs");
40561
+ var import_node_fs70 = require("node:fs");
40321
40562
 
40322
40563
  // src/lib/reflection-globs.ts
40323
40564
  var MAX_GLOBS = 6;
@@ -40325,7 +40566,7 @@ var PATH_TOKEN = /[A-Za-z0-9_./-]*[A-Za-z0-9_-]\.[A-Za-z0-9]{1,8}(?::\d+(?::\d+)
40325
40566
  function clean(token) {
40326
40567
  return token.replace(/:\d+(?::\d+)?$/, "").replace(/^[`'"(\[]+/, "").replace(/[`'"),\].;!?]+$/, "").replace(/^\.\//, "");
40327
40568
  }
40328
- function resolve6(token, treePaths) {
40569
+ function resolve7(token, treePaths) {
40329
40570
  if (treePaths.includes(token)) return token;
40330
40571
  const suffix = token.startsWith("/") ? token : `/${token}`;
40331
40572
  const matches = treePaths.filter((p) => p.endsWith(suffix));
@@ -40338,7 +40579,7 @@ function deriveFileGlobs(text, treePaths) {
40338
40579
  for (const raw of text.match(PATH_TOKEN) ?? []) {
40339
40580
  const token = clean(raw);
40340
40581
  if (!token) continue;
40341
- const path = resolve6(token, treePaths);
40582
+ const path = resolve7(token, treePaths);
40342
40583
  if (!path || seen.has(path)) continue;
40343
40584
  seen.add(path);
40344
40585
  out2.push(path);
@@ -40355,14 +40596,19 @@ async function writeNodeToDisk(args2) {
40355
40596
  { treePaths: listTrackedFiles(), recordBaseline: false }
40356
40597
  );
40357
40598
  if (written === 0) return false;
40358
- return (0, import_node_fs68.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40599
+ return (0, import_node_fs70.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40359
40600
  } catch {
40360
40601
  return false;
40361
40602
  }
40362
40603
  }
40363
40604
  function registerReflectCommand(program2) {
40364
- program2.command("reflect").description("Capture learnings \u2014 auto-extract or record a reflection").option("--user-input <text>", "The reflection to record (the agent-drafted or user-dictated text)").option("--kind <kind>", "Node kind (decision, gotcha, pattern, security, quality, intent, domain, integration)", "gotcha").option("--task-id <id>", "Task to reflect on (defaults to current task)").option("--confirmed", "The USER authored or confirmed these exact words \u2014 records as human-authored (source: user, confidence 1.0)").option("--file-globs <glob...>", "Files this reflection is about. Without any, the paths cited in the text are used; a reflection matching no file never surfaces in a review").option("--autonomous", "(deprecated, ignored) reflections are always recorded without a confirm step").action(async (opts) => {
40605
+ program2.command("reflect").description("Capture learnings \u2014 auto-extract or record a reflection").option("--user-input <text>", "The reflection to record (the agent-drafted or user-dictated text); - reads it from stdin, so the words never pass through shell quoting").option("--kind <kind>", "Node kind (decision, gotcha, pattern, security, quality, intent, domain, integration)", "gotcha").option("--task-id <id>", "Task to reflect on (defaults to current task)").option("--confirmed", "The USER authored or confirmed these exact words \u2014 records as human-authored (source: user, confidence 1.0)").option("--file-globs <glob...>", "Files this reflection is about. Without any, the paths cited in the text are used; a reflection matching no file never surfaces in a review").option("--autonomous", "(deprecated, ignored) reflections are always recorded without a confirm step").action(async (opts) => {
40365
40606
  const globals = program2.opts();
40607
+ const input = readTextInput(opts.userInput, "--user-input");
40608
+ if (!input.ok) {
40609
+ printError(input.error);
40610
+ process.exit(1);
40611
+ }
40366
40612
  await ensureMemoryDir();
40367
40613
  const tokenResult = await resolveToken(globals.token);
40368
40614
  if (!tokenResult.ok) {
@@ -40423,7 +40669,7 @@ function registerReflectCommand(program2) {
40423
40669
  taskResolution = "none";
40424
40670
  printWarn("No active task found \u2014 saving as an unattached reflection.");
40425
40671
  }
40426
- const userInput = opts.userInput;
40672
+ const userInput = input.text;
40427
40673
  if (userInput) {
40428
40674
  const validKinds = ["decision", "gotcha", "pattern", "security", "quality", "intent", "domain", "integration"];
40429
40675
  const kind = validKinds.includes(opts.kind) ? opts.kind : "gotcha";
@@ -40787,9 +41033,9 @@ function registerRunCommand(program2) {
40787
41033
  }
40788
41034
 
40789
41035
  // src/commands/telemetry.ts
40790
- var import_node_fs69 = require("node:fs");
41036
+ var import_node_fs71 = require("node:fs");
40791
41037
  async function recordTelemetryChoice(choice) {
40792
- if (!(0, import_node_fs69.existsSync)(projectPath(SETUP_STATE_FILE))) return;
41038
+ if (!(0, import_node_fs71.existsSync)(projectPath(SETUP_STATE_FILE))) return;
40793
41039
  try {
40794
41040
  if ((await readSetupState())?.telemetry === choice) return;
40795
41041
  await writeSetupState({ telemetry: choice });
@@ -40866,8 +41112,8 @@ function registerTelemetryCommands(program2) {
40866
41112
  }
40867
41113
 
40868
41114
  // src/commands/prove.ts
40869
- var import_node_fs70 = require("node:fs");
40870
- var import_node_path52 = require("node:path");
41115
+ var import_node_fs72 = require("node:fs");
41116
+ var import_node_path55 = require("node:path");
40871
41117
 
40872
41118
  // src/lib/prove/hint-pool.ts
40873
41119
  var STOP2 = /* @__PURE__ */ new Set([
@@ -40994,7 +41240,13 @@ async function proveAuth(program2) {
40994
41240
  }
40995
41241
  function registerProveCommand(program2) {
40996
41242
  const prove = program2.command("prove").description("Formal verification (Lean 4) of small, risky pieces of code \u2014 on demand");
40997
- prove.command("candidates [paths...]").description("Rank code worth a formal model, from git history and risk signals").option("--since <when>", `git --since window (default: "${DEFAULT_SINCE}")`).option("--limit <n>", "Candidates to show", "10").option("--rank <ranker>", "deterministic | luna | jev (luna and jev need an API key)", "deterministic").option("--hint <text>", "What the user wants checked, in their words (biases the rank; implies --rank luna)").option("--json", "Machine-readable output").action(async (paths, opts) => {
41243
+ prove.command("candidates [paths...]").description("Rank code worth a formal model, from git history and risk signals").option("--since <when>", `git --since window (default: "${DEFAULT_SINCE}")`).option("--limit <n>", "Candidates to show", "10").option("--rank <ranker>", "deterministic | luna | jev (luna and jev need an API key)", "deterministic").option("--hint <text>", "What the user wants checked, in their words (biases the rank; implies --rank luna); - reads it from stdin, so the words never pass through shell quoting").option("--json", "Machine-readable output").action(async (paths, opts) => {
41244
+ const hint = readTextInput(opts.hint, "--hint");
41245
+ if (!hint.ok) {
41246
+ printError(hint.error);
41247
+ process.exit(2);
41248
+ }
41249
+ opts.hint = hint.text;
40998
41250
  if (opts.hint && opts.rank === "deterministic") opts.rank = "luna";
40999
41251
  const root = repoRoot();
41000
41252
  const ranker = RANKERS[opts.rank];
@@ -41003,7 +41255,7 @@ function registerProveCommand(program2) {
41003
41255
  process.exit(2);
41004
41256
  }
41005
41257
  const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
41006
- let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path52.relative)(root, (0, import_node_path52.resolve)(p)) || ".") });
41258
+ let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)) || ".") });
41007
41259
  if (opts.hint && paths.length === 0) {
41008
41260
  const hit = hintMatches(root, opts.hint);
41009
41261
  if (hit.files.length > 0) {
@@ -41057,7 +41309,7 @@ function registerProveCommand(program2) {
41057
41309
  });
41058
41310
  prove.command("check [model]").description("Elaborate a model (or every model) with the local Lean toolchain and report each property").option("--timeout <ms>", "Per-model timeout in ms", "120000").option("--json", "Machine-readable output").action((model, opts) => {
41059
41311
  const root = repoRoot();
41060
- if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41312
+ if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41061
41313
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41062
41314
  process.exit(2);
41063
41315
  }
@@ -41081,7 +41333,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41081
41333
  const reports = [];
41082
41334
  for (const f of files) {
41083
41335
  const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
41084
- report.file = (0, import_node_path52.relative)(root, f);
41336
+ report.file = (0, import_node_path55.relative)(root, f);
41085
41337
  reports.push(report);
41086
41338
  try {
41087
41339
  writeResult(root, report);
@@ -41119,7 +41371,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41119
41371
  printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
41120
41372
  process.exit(2);
41121
41373
  }
41122
- if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41374
+ if (!(0, import_node_fs72.existsSync)((0, import_node_path55.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41123
41375
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41124
41376
  process.exit(2);
41125
41377
  }
@@ -41150,7 +41402,7 @@ ${report.error ?? ""}`);
41150
41402
  printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
41151
41403
  return;
41152
41404
  }
41153
- const modelSource = readRegularFileInRoot(root, (0, import_node_path52.relative)(root, file), 512 * 1024);
41405
+ const modelSource = readRegularFileInRoot(root, (0, import_node_path55.relative)(root, file), 512 * 1024);
41154
41406
  if (!opts.json) printInfo(`replaying ${targets.length} counterexample(s) of ${model} in network-less containers (${Math.min(targets.length, REPLAY_CONCURRENCY)} at a time)\u2026`);
41155
41407
  const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
41156
41408
  const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
@@ -41170,7 +41422,7 @@ ${report.error ?? ""}`);
41170
41422
  });
41171
41423
  prove.command("auto [files...]").description("The formal phase the pre-push guard runs: select one risky symbol among changed files, generate a model, check it, replay counterexamples (default files: the commits ahead of upstream)").option("--deadline <ms>", "Budget for the whole phase", "170000").option("--json", "Machine-readable output").action(async (paths, opts) => {
41172
41424
  const root = repoRoot();
41173
- let files = paths.map((p) => (0, import_node_path52.relative)(root, (0, import_node_path52.resolve)(p)));
41425
+ let files = paths.map((p) => (0, import_node_path55.relative)(root, (0, import_node_path55.resolve)(p)));
41174
41426
  if (files.length === 0) {
41175
41427
  const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
41176
41428
  const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
@@ -41199,7 +41451,19 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41199
41451
  }
41200
41452
  process.exit(outcome.findings.some((f) => f.verdict === "reproduced") ? 1 : 0);
41201
41453
  });
41202
- prove.command("generate <target>").description("Have the Verity service write a Lean model of one symbol (file#symbol), lint it, and check it here \u2014 up to 3 rounds").option("--lines <a-b>", "Model a region of the file (1-based, inclusive) instead of a named symbol").option("--hint <text>", "The user's worry, in their words (may become an intent property)").option("--revise <model>", "Revise this existing model after a diverged replay (with --note)").option("--note <text>", "What the replay showed was different (with --revise)").option("--json", "Machine-readable output").action(async (targetArg, opts) => {
41454
+ prove.command("generate <target>").description("Have the Verity service write a Lean model of one symbol (file#symbol), lint it, and check it here \u2014 up to 3 rounds").option("--lines <a-b>", "Model a region of the file (1-based, inclusive) instead of a named symbol").option("--hint <text>", "The user's worry, in their words (may become an intent property); - reads it from stdin").option("--revise <model>", "Revise this existing model after a diverged replay (with --note)").option("--note <text>", "What the replay showed was different (with --revise); - reads it from stdin").option("--json", "Machine-readable output").action(async (targetArg, opts) => {
41455
+ if (opts.hint === "-" && opts.note === "-") {
41456
+ printError("Only one of --hint and --note can read stdin (-).");
41457
+ process.exit(2);
41458
+ }
41459
+ for (const flag of ["hint", "note"]) {
41460
+ const input = readTextInput(opts[flag], `--${flag}`);
41461
+ if (!input.ok) {
41462
+ printError(input.error);
41463
+ process.exit(2);
41464
+ }
41465
+ opts[flag] = input.text;
41466
+ }
41203
41467
  const root = repoRoot();
41204
41468
  const auth2 = await proveAuth(program2);
41205
41469
  if (!auth2 && !(process.env.VERITY_PROVE_DIRECT === "1" && process.env.OPENAI_API_KEY)) {
@@ -41230,9 +41494,9 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41230
41494
  let revise;
41231
41495
  if (opts.revise) {
41232
41496
  const existing = resolveModelFile(root, opts.revise);
41233
- const src = existing ? readRegularFileInRoot(root, (0, import_node_path52.relative)(root, existing), 64 * 1024) : null;
41497
+ const src = existing ? readRegularFileInRoot(root, (0, import_node_path55.relative)(root, existing), 64 * 1024) : null;
41234
41498
  if (!src || !src.ok || !opts.note) {
41235
- printError('--revise needs an existing model under Models/ and --note "<what the replay showed>"');
41499
+ printError("--revise needs an existing model under Models/ and --note - with what the replay showed on stdin");
41236
41500
  process.exit(2);
41237
41501
  }
41238
41502
  revise = { source: src.content, note: opts.note };
@@ -41269,8 +41533,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41269
41533
  });
41270
41534
  prove.command("waive <file>").description("Dismiss the remembered formal finding(s) on a file for its current bytes \u2014 the accepted-risk path for a formal block").requiredOption("--reason <text>", "The human disposition this records (reviewer finding, ADR, \u2026)").action((file, opts) => {
41271
41535
  const root = repoRoot();
41272
- const rel0 = (0, import_node_path52.relative)(root, (0, import_node_path52.isAbsolute)(file) ? file : (0, import_node_path52.join)(root, file)).replace(/\\/g, "/");
41273
- const rel = rel0.startsWith("..") || (0, import_node_path52.isAbsolute)(rel0) ? null : rel0;
41536
+ const rel0 = (0, import_node_path55.relative)(root, (0, import_node_path55.isAbsolute)(file) ? file : (0, import_node_path55.join)(root, file)).replace(/\\/g, "/");
41537
+ const rel = rel0.startsWith("..") || (0, import_node_path55.isAbsolute)(rel0) ? null : rel0;
41274
41538
  if (!rel) {
41275
41539
  printError(`${file} is not inside this repository`);
41276
41540
  process.exit(2);
@@ -41286,8 +41550,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41286
41550
  });
41287
41551
  prove.command("hash <file>").description("Print the sha256 of a file, for a model header (Verity.model \u2026 sha256). Path is REPO-relative, as in the header").action((file) => {
41288
41552
  const root = repoRoot();
41289
- const rel = (0, import_node_path52.relative)(root, (0, import_node_path52.isAbsolute)(file) ? file : (0, import_node_path52.join)(root, file));
41290
- const digest = rel.startsWith("..") || (0, import_node_path52.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
41553
+ const rel = (0, import_node_path55.relative)(root, (0, import_node_path55.isAbsolute)(file) ? file : (0, import_node_path55.join)(root, file));
41554
+ const digest = rel.startsWith("..") || (0, import_node_path55.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
41291
41555
  if (!digest) {
41292
41556
  printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
41293
41557
  process.exit(2);
@@ -41321,10 +41585,10 @@ function refreshScaffold(root) {
41321
41585
  }
41322
41586
 
41323
41587
  // src/commands/lean.ts
41324
- var import_node_fs71 = require("node:fs");
41588
+ var import_node_fs73 = require("node:fs");
41325
41589
  var import_node_child_process20 = require("node:child_process");
41326
41590
  var import_node_os11 = require("node:os");
41327
- var import_node_path53 = require("node:path");
41591
+ var import_node_path56 = require("node:path");
41328
41592
  function registerLeanCommand(program2) {
41329
41593
  const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
41330
41594
  lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
@@ -41341,7 +41605,7 @@ function registerLeanCommand(program2) {
41341
41605
  const managed = pinnedVersionDir();
41342
41606
  const matches = version ? version.includes(pin) : false;
41343
41607
  if (opts.json) {
41344
- printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs71.existsSync)((0, import_node_path53.join)(managed, "bin")), asset: leanAssetName() });
41608
+ printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs73.existsSync)((0, import_node_path56.join)(managed, "bin")), asset: leanAssetName() });
41345
41609
  return;
41346
41610
  }
41347
41611
  printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
@@ -41359,7 +41623,7 @@ function registerLeanCommand(program2) {
41359
41623
  process.exit(2);
41360
41624
  }
41361
41625
  const dir = pinnedVersionDir();
41362
- if ((0, import_node_fs71.existsSync)((0, import_node_path53.join)(dir, "bin", "lake")) && !opts.force) {
41626
+ if ((0, import_node_fs73.existsSync)((0, import_node_path56.join)(dir, "bin", "lake")) && !opts.force) {
41363
41627
  printInfo(`already installed at ${dir}`);
41364
41628
  return;
41365
41629
  }
@@ -41395,18 +41659,18 @@ function registerLeanCommand(program2) {
41395
41659
  });
41396
41660
  lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
41397
41661
  const dir = pinnedVersionDir();
41398
- if (!(0, import_node_fs71.existsSync)(dir)) {
41662
+ if (!(0, import_node_fs73.existsSync)(dir)) {
41399
41663
  printInfo("nothing to remove");
41400
41664
  return;
41401
41665
  }
41402
- (0, import_node_fs71.rmSync)(dir, { recursive: true, force: true });
41666
+ (0, import_node_fs73.rmSync)(dir, { recursive: true, force: true });
41403
41667
  printInfo(`removed ${dir}`);
41404
41668
  });
41405
41669
  }
41406
41670
 
41407
41671
  // src/cli.ts
41408
- program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.92a1040").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) => {
41409
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.92a1040");
41672
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.afcb0e6").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) => {
41673
+ installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.afcb0e6");
41410
41674
  setUserNamedServiceUrl(program.opts().serviceUrl);
41411
41675
  try {
41412
41676
  await foldLegacyLocalCredential();