@codacy/verity-cli 0.34.0-experimental.b9e8508 → 0.34.0-experimental.cc5f6ec

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/bin/verity.js +894 -809
  3. package/package.json +1 -1
package/bin/verity.js CHANGED
@@ -17104,6 +17104,10 @@ async function applyMomentSelection(moments) {
17104
17104
  }
17105
17105
 
17106
17106
  // src/lib/project-config.ts
17107
+ var import_node_fs6 = require("node:fs");
17108
+ var import_node_path8 = require("node:path");
17109
+
17110
+ // src/lib/repo-controlled.ts
17107
17111
  var import_node_fs5 = require("node:fs");
17108
17112
  var import_node_path7 = require("node:path");
17109
17113
 
@@ -17180,6 +17184,26 @@ function runGit(cwd, args2, opts = {}) {
17180
17184
  });
17181
17185
  }
17182
17186
 
17187
+ // src/lib/repo-controlled.ts
17188
+ function repoControlled(worktree, rel) {
17189
+ const parts2 = rel.split("/").filter(Boolean);
17190
+ for (let i2 = 1; i2 <= parts2.length; i2++) {
17191
+ let st;
17192
+ try {
17193
+ st = (0, import_node_fs5.lstatSync)((0, import_node_path7.join)(worktree, ...parts2.slice(0, i2)));
17194
+ } catch (err2) {
17195
+ const code = err2?.code;
17196
+ if (code === "ENOENT" || code === "ENOTDIR") return null;
17197
+ return "unverified";
17198
+ }
17199
+ if (st.isSymbolicLink()) return "symlink";
17200
+ if (i2 === parts2.length && !st.isFile()) return "symlink";
17201
+ }
17202
+ const r = runGitSync(worktree, ["ls-files", "-z", "--", rel], { timeoutMs: 5e3 });
17203
+ if (!r.ok) return "unverified";
17204
+ return r.stdout.length > 0 ? "tracked" : null;
17205
+ }
17206
+
17183
17207
  // src/lib/project-config.ts
17184
17208
  var DEFAULTS = { git_moments: [] };
17185
17209
  function isMoment(value) {
@@ -17190,14 +17214,14 @@ function parseMoments(raw) {
17190
17214
  }
17191
17215
  function readConfigFile(path) {
17192
17216
  try {
17193
- if (!(0, import_node_fs5.existsSync)(path)) return null;
17194
- const raw = JSON.parse((0, import_node_fs5.readFileSync)(path, "utf-8"));
17217
+ if (!(0, import_node_fs6.existsSync)(path)) return null;
17218
+ const raw = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf-8"));
17195
17219
  const moments = Array.isArray(raw.git_moments) ? raw.git_moments.filter(isMoment) : [];
17196
17220
  const source2 = raw.git_moments_source === "user" || raw.git_moments_source === "init" ? raw.git_moments_source : void 0;
17197
17221
  return {
17198
17222
  git_moments: [...new Set(moments)],
17199
17223
  ...source2 ? { git_moments_source: source2 } : {},
17200
- ...raw.formal === "push" ? { formal: "push" } : {}
17224
+ ...raw.formal === "push" || raw.formal === "off" ? { formal: raw.formal } : {}
17201
17225
  };
17202
17226
  } catch {
17203
17227
  return DEFAULTS;
@@ -17208,22 +17232,13 @@ function candidates() {
17208
17232
  const out2 = [{ path: local, source: "local" }];
17209
17233
  const main = mainWorktreeRoot();
17210
17234
  if (main) {
17211
- const inherited = (0, import_node_path7.join)(main, PROJECT_CONFIG_FILE);
17235
+ const inherited = (0, import_node_path8.join)(main, PROJECT_CONFIG_FILE);
17212
17236
  if (inherited !== local) out2.push({ path: inherited, source: "main-worktree" });
17213
17237
  }
17214
17238
  return out2;
17215
17239
  }
17216
17240
  function formalRefusal(path) {
17217
- const worktree = (0, import_node_path7.dirname)((0, import_node_path7.dirname)(path));
17218
- try {
17219
- if ((0, import_node_fs5.lstatSync)((0, import_node_path7.join)(worktree, VERITY_DIR)).isSymbolicLink()) return "symlink";
17220
- if (!(0, import_node_fs5.lstatSync)(path).isFile()) return "symlink";
17221
- } catch {
17222
- return "unverified";
17223
- }
17224
- const r = runGitSync(worktree, ["ls-files", "-z", "--", PROJECT_CONFIG_FILE], { timeoutMs: 5e3 });
17225
- if (!r.ok) return "unverified";
17226
- return r.stdout.length > 0 ? "tracked" : null;
17241
+ return repoControlled((0, import_node_path8.dirname)((0, import_node_path8.dirname)(path)), PROJECT_CONFIG_FILE);
17227
17242
  }
17228
17243
  function readProjectConfigRaw() {
17229
17244
  for (const { path, source: source2 } of candidates()) {
@@ -17235,10 +17250,10 @@ function readProjectConfigRaw() {
17235
17250
  function readProjectConfig() {
17236
17251
  const cfg = readProjectConfigRaw();
17237
17252
  if (cfg.formal !== "push" || !cfg.path) return cfg;
17238
- const refused = formalRefusal(cfg.path);
17239
- if (!refused) return cfg;
17253
+ const refused2 = formalRefusal(cfg.path);
17254
+ if (!refused2) return cfg;
17240
17255
  const { formal: _dropped, ...rest } = cfg;
17241
- return { ...rest, formal_refused: refused };
17256
+ return { ...rest, formal_refused: refused2 };
17242
17257
  }
17243
17258
  function formalRefusalMessage(reason) {
17244
17259
  switch (reason) {
@@ -17259,8 +17274,8 @@ function writeProjectConfig(patch) {
17259
17274
  ...patch
17260
17275
  };
17261
17276
  const target = projectPath(PROJECT_CONFIG_FILE);
17262
- (0, import_node_fs5.mkdirSync)((0, import_node_path7.dirname)(target), { recursive: true });
17263
- (0, import_node_fs5.writeFileSync)(target, JSON.stringify(next, null, 2) + "\n");
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");
17264
17279
  return next;
17265
17280
  }
17266
17281
  function resolveGuardMoments(explicit) {
@@ -17269,11 +17284,11 @@ function resolveGuardMoments(explicit) {
17269
17284
  }
17270
17285
 
17271
17286
  // src/lib/plugin-ownership.ts
17272
- var import_node_fs8 = require("node:fs");
17287
+ var import_node_fs9 = require("node:fs");
17273
17288
 
17274
17289
  // src/lib/which.ts
17275
- var import_node_fs6 = require("node:fs");
17276
- var import_node_path8 = require("node:path");
17290
+ var import_node_fs7 = require("node:fs");
17291
+ var import_node_path9 = require("node:path");
17277
17292
  function executableExtensions(platform4, pathext) {
17278
17293
  if (platform4 !== "win32") return [""];
17279
17294
  const raw = (pathext ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
@@ -17291,14 +17306,14 @@ function whichSync(bin, opts = {}) {
17291
17306
  if (!rawPath) return null;
17292
17307
  const exts = executableExtensions(platform4, opts.pathext ?? process.env.PATHEXT);
17293
17308
  const real = opts.real ?? true;
17294
- for (const dir of rawPath.split(import_node_path8.delimiter)) {
17309
+ for (const dir of rawPath.split(import_node_path9.delimiter)) {
17295
17310
  if (!dir) continue;
17296
17311
  for (const ext of exts) {
17297
- const candidate = (0, import_node_path8.join)(dir, bin + ext);
17312
+ const candidate = (0, import_node_path9.join)(dir, bin + ext);
17298
17313
  try {
17299
- if (!(0, import_node_fs6.statSync)(candidate).isFile()) continue;
17300
- if (platform4 !== "win32") (0, import_node_fs6.accessSync)(candidate, import_node_fs6.constants.X_OK);
17301
- return real ? (0, import_node_fs6.realpathSync)(candidate) : candidate;
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;
17302
17317
  } catch {
17303
17318
  continue;
17304
17319
  }
@@ -17309,10 +17324,10 @@ function whichSync(bin, opts = {}) {
17309
17324
 
17310
17325
  // src/lib/plugin-ownership.ts
17311
17326
  var import_node_os2 = require("node:os");
17312
- var import_node_path9 = require("node:path");
17327
+ var import_node_path10 = require("node:path");
17313
17328
 
17314
17329
  // src/lib/stderr-log.ts
17315
- var import_node_fs7 = require("node:fs");
17330
+ var import_node_fs8 = require("node:fs");
17316
17331
  var TOKEN_RE2 = /verity_[0-9a-f]{16,}/g;
17317
17332
  var ANSI_RE = /\u001b\[[0-?]*[ -/]*[@-~]/g;
17318
17333
  function scrub(s) {
@@ -17325,9 +17340,9 @@ function append(text) {
17325
17340
  try {
17326
17341
  const dir = projectPath(DEBUG_LOG_DIR);
17327
17342
  const file = projectPath(STDERR_LOG_FILE);
17328
- (0, import_node_fs7.mkdirSync)(dir, { recursive: true });
17343
+ (0, import_node_fs8.mkdirSync)(dir, { recursive: true });
17329
17344
  rotateIfNeeded(file);
17330
- (0, import_node_fs7.appendFileSync)(file, text);
17345
+ (0, import_node_fs8.appendFileSync)(file, text);
17331
17346
  } catch {
17332
17347
  }
17333
17348
  }
@@ -17375,8 +17390,8 @@ function markerPath() {
17375
17390
  }
17376
17391
  function readMarker() {
17377
17392
  try {
17378
- if (!(0, import_node_fs8.existsSync)(markerPath())) return null;
17379
- const raw = JSON.parse((0, import_node_fs8.readFileSync)(markerPath(), "utf-8"));
17393
+ if (!(0, import_node_fs9.existsSync)(markerPath())) return null;
17394
+ const raw = JSON.parse((0, import_node_fs9.readFileSync)(markerPath(), "utf-8"));
17380
17395
  const pluginRoot = typeof raw.plugin_root === "string" ? raw.plugin_root : "";
17381
17396
  if (!pluginRoot || CONTROL_CHARS2.test(pluginRoot)) return null;
17382
17397
  const version = typeof raw.version === "string" && !CONTROL_CHARS2.test(raw.version) ? raw.version : null;
@@ -17394,23 +17409,23 @@ function recordPluginOwnership(sessionId) {
17394
17409
  const pluginRoot = process.env.VERITY_PLUGIN_ROOT;
17395
17410
  if (!pluginRoot) return;
17396
17411
  try {
17397
- (0, import_node_fs8.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
17412
+ (0, import_node_fs9.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
17398
17413
  const marker = {
17399
17414
  session_id: sessionId,
17400
17415
  plugin_root: pluginRoot,
17401
17416
  version: process.env.VERITY_PLUGIN_VERSION || null,
17402
17417
  ts: Math.floor(Date.now() / 1e3)
17403
17418
  };
17404
- (0, import_node_fs8.writeFileSync)(markerPath(), JSON.stringify(marker));
17419
+ (0, import_node_fs9.writeFileSync)(markerPath(), JSON.stringify(marker));
17405
17420
  } catch {
17406
17421
  }
17407
17422
  }
17408
17423
  function claudeConfigDir() {
17409
- return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path9.join)((0, import_node_os2.homedir)(), ".claude");
17424
+ return process.env.CLAUDE_CONFIG_DIR || (0, import_node_path10.join)((0, import_node_os2.homedir)(), ".claude");
17410
17425
  }
17411
17426
  function readJsonFile(path) {
17412
17427
  try {
17413
- const parsed = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf-8"));
17428
+ const parsed = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf-8"));
17414
17429
  return parsed && typeof parsed === "object" ? parsed : null;
17415
17430
  } catch {
17416
17431
  return null;
@@ -17418,9 +17433,9 @@ function readJsonFile(path) {
17418
17433
  }
17419
17434
  function enabledPluginSetting(key) {
17420
17435
  const files = [
17421
- projectPath((0, import_node_path9.join)(".claude", "settings.local.json")),
17422
- projectPath((0, import_node_path9.join)(".claude", "settings.json")),
17423
- (0, import_node_path9.join)(claudeConfigDir(), "settings.json")
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")
17424
17439
  ];
17425
17440
  for (const file of files) {
17426
17441
  const map = readJsonFile(file)?.enabledPlugins;
@@ -17432,11 +17447,11 @@ function enabledPluginSetting(key) {
17432
17447
  }
17433
17448
  function marketplaceLocations() {
17434
17449
  const out2 = /* @__PURE__ */ new Map();
17435
- const known = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17450
+ const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17436
17451
  if (!known) return out2;
17437
17452
  for (const [name2, entry] of Object.entries(known)) {
17438
17453
  const loc2 = entry?.installLocation;
17439
- if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path9.resolve)(loc2));
17454
+ if (typeof loc2 === "string" && loc2) out2.set(name2, (0, import_node_path10.resolve)(loc2));
17440
17455
  }
17441
17456
  return out2;
17442
17457
  }
@@ -17450,7 +17465,7 @@ function globalVerityVersion() {
17450
17465
  const entry = verityPathEntry();
17451
17466
  if (!entry) return null;
17452
17467
  try {
17453
- const pkg = readJsonFile((0, import_node_path9.join)((0, import_node_path9.dirname)((0, import_node_fs8.realpathSync)(entry)), "..", "package.json"));
17468
+ const pkg = readJsonFile((0, import_node_path10.join)((0, import_node_path10.dirname)((0, import_node_fs9.realpathSync)(entry)), "..", "package.json"));
17454
17469
  if (pkg?.name !== "@codacy/verity-cli" || typeof pkg.version !== "string") return null;
17455
17470
  return pkg.version;
17456
17471
  } catch {
@@ -17467,7 +17482,7 @@ var VERITY_MARKETPLACE_REPO = "codacy/verity";
17467
17482
  function marketplaceConflict() {
17468
17483
  const wanted = VERITY_MARKETPLACE;
17469
17484
  for (const file of ["settings.json", "settings.local.json"]) {
17470
- const path = (0, import_node_path9.join)(claudeConfigDir(), file);
17485
+ const path = (0, import_node_path10.join)(claudeConfigDir(), file);
17471
17486
  const declared = readJsonFile(path)?.extraKnownMarketplaces ?? null;
17472
17487
  const entry2 = declared && typeof declared === "object" ? declared[wanted] : void 0;
17473
17488
  if (entry2 && typeof entry2 === "object") {
@@ -17477,7 +17492,7 @@ function marketplaceConflict() {
17477
17492
  }
17478
17493
  }
17479
17494
  }
17480
- const known = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17495
+ const known = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "known_marketplaces.json"));
17481
17496
  const entry = known?.[wanted];
17482
17497
  if (entry && typeof entry === "object" && !pointsAtVerity(entry.source)) {
17483
17498
  return { name: wanted, declaredAs: describeSource(entry.source) };
@@ -17498,7 +17513,7 @@ function describeSource(src) {
17498
17513
  return target ? `${kind} \u2192 ${target}` : kind;
17499
17514
  }
17500
17515
  function legacyMarketplaceInstall() {
17501
- const plugins = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17516
+ const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17502
17517
  if (!plugins || typeof plugins !== "object") return null;
17503
17518
  for (const key of Object.keys(plugins)) {
17504
17519
  const at = key.lastIndexOf("@");
@@ -17510,13 +17525,13 @@ function legacyMarketplaceInstall() {
17510
17525
  }
17511
17526
  function realpathOr(p) {
17512
17527
  try {
17513
- return import_node_fs8.realpathSync.native(p);
17528
+ return import_node_fs9.realpathSync.native(p);
17514
17529
  } catch {
17515
- return (0, import_node_path9.resolve)(p);
17530
+ return (0, import_node_path10.resolve)(p);
17516
17531
  }
17517
17532
  }
17518
17533
  function isWithin(want, dir) {
17519
- return want === dir || want.startsWith(dir + import_node_path9.sep);
17534
+ return want === dir || want.startsWith(dir + import_node_path10.sep);
17520
17535
  }
17521
17536
  function entryAppliesHere(entry, here) {
17522
17537
  const e = entry;
@@ -17526,9 +17541,9 @@ function entryAppliesHere(entry, here) {
17526
17541
  return forProject === here;
17527
17542
  }
17528
17543
  function registrySays(pluginRoot) {
17529
- const plugins = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17544
+ const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17530
17545
  if (!plugins || typeof plugins !== "object") return "unverified";
17531
- const want = (0, import_node_path9.resolve)(pluginRoot);
17546
+ const want = (0, import_node_path10.resolve)(pluginRoot);
17532
17547
  const here = realpathOr(repoRoot());
17533
17548
  const markets = marketplaceLocations();
17534
17549
  for (const [key, value] of Object.entries(plugins)) {
@@ -17537,15 +17552,15 @@ function registrySays(pluginRoot) {
17537
17552
  const applicable = (Array.isArray(value) ? value : []).filter((entry) => entryAppliesHere(entry, here));
17538
17553
  const claims = applicable.some((entry) => {
17539
17554
  const installPath = entry?.installPath;
17540
- return typeof installPath === "string" && (0, import_node_path9.resolve)(installPath) === want;
17555
+ return typeof installPath === "string" && (0, import_node_path10.resolve)(installPath) === want;
17541
17556
  }) || source2 !== void 0 && applicable.length > 0 && isWithin(want, source2);
17542
17557
  if (claims) {
17543
17558
  if (enabledPluginSetting(key) === false) return "gone";
17544
- return (0, import_node_fs8.existsSync)(pluginRoot) ? "live" : "gone";
17559
+ return (0, import_node_fs9.existsSync)(pluginRoot) ? "live" : "gone";
17545
17560
  }
17546
17561
  }
17547
- const managed = (0, import_node_path9.resolve)((0, import_node_path9.join)(claudeConfigDir(), "plugins", "cache"));
17548
- return want === managed || want.startsWith(managed + import_node_path9.sep) ? "gone" : "unverified";
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";
17549
17564
  }
17550
17565
  var _live = /* @__PURE__ */ new Map();
17551
17566
  function pluginLiveness(pluginRoot) {
@@ -17559,7 +17574,7 @@ function clearStalePluginMarker() {
17559
17574
  const marker = readMarker();
17560
17575
  if (!marker || pluginLiveness(marker.plugin_root) !== "gone") return null;
17561
17576
  try {
17562
- (0, import_node_fs8.rmSync)(markerPath(), { force: true });
17577
+ (0, import_node_fs9.rmSync)(markerPath(), { force: true });
17563
17578
  } catch {
17564
17579
  return null;
17565
17580
  }
@@ -17587,7 +17602,7 @@ function pluginActiveHere() {
17587
17602
  return activePluginInstall() !== null;
17588
17603
  }
17589
17604
  function registeredVerityPlugin() {
17590
- const plugins = readJsonFile((0, import_node_path9.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17605
+ const plugins = readJsonFile((0, import_node_path10.join)(claudeConfigDir(), "plugins", "installed_plugins.json"))?.plugins;
17591
17606
  if (!plugins || typeof plugins !== "object") return null;
17592
17607
  const here = realpathOr(repoRoot());
17593
17608
  for (const [key, value] of Object.entries(plugins)) {
@@ -17597,7 +17612,7 @@ function registeredVerityPlugin() {
17597
17612
  for (const entry of Array.isArray(value) ? value : []) {
17598
17613
  const e = entry;
17599
17614
  const installPath = typeof e.installPath === "string" ? e.installPath : "";
17600
- if (!installPath || !(0, import_node_fs8.existsSync)(installPath)) continue;
17615
+ if (!installPath || !(0, import_node_fs9.existsSync)(installPath)) continue;
17601
17616
  if (!entryAppliesHere(entry, here)) continue;
17602
17617
  return { pluginRoot: installPath, version: typeof e.version === "string" ? e.version : null };
17603
17618
  }
@@ -17649,28 +17664,28 @@ async function resolveHookWiring() {
17649
17664
  }
17650
17665
 
17651
17666
  // src/lib/cli-provenance.ts
17652
- var import_node_fs9 = require("node:fs");
17667
+ var import_node_fs10 = require("node:fs");
17653
17668
  var import_node_os3 = require("node:os");
17654
- var import_node_path10 = require("node:path");
17669
+ var import_node_path11 = require("node:path");
17655
17670
  var CLI_PACKAGE = "@codacy/verity-cli";
17656
- var CLI_ENTRY = (0, import_node_path10.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
17671
+ var CLI_ENTRY = (0, import_node_path11.join)("node_modules", CLI_PACKAGE, "bin", "verity.js");
17657
17672
  function readJson(path) {
17658
17673
  try {
17659
- const parsed = JSON.parse((0, import_node_fs9.readFileSync)(path, "utf-8"));
17674
+ const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
17660
17675
  return parsed && typeof parsed === "object" ? parsed : null;
17661
17676
  } catch {
17662
17677
  return null;
17663
17678
  }
17664
17679
  }
17665
17680
  function versionUnder(base) {
17666
- const entry = (0, import_node_path10.join)(base, CLI_ENTRY);
17667
- if (!(0, import_node_fs9.existsSync)(entry)) return null;
17668
- const pkg = readJson((0, import_node_path10.join)(base, "node_modules", CLI_PACKAGE, "package.json"));
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"));
17669
17684
  return typeof pkg?.version === "string" ? pkg.version : null;
17670
17685
  }
17671
17686
  function versionForEntry(entry) {
17672
17687
  try {
17673
- const pkg = readJson((0, import_node_path10.join)((0, import_node_path10.dirname)((0, import_node_fs9.realpathSync)(entry)), "..", "package.json"));
17688
+ const pkg = readJson((0, import_node_path11.join)((0, import_node_path11.dirname)((0, import_node_fs10.realpathSync)(entry)), "..", "package.json"));
17674
17689
  return typeof pkg?.version === "string" ? pkg.version : null;
17675
17690
  } catch {
17676
17691
  return null;
@@ -17678,16 +17693,16 @@ function versionForEntry(entry) {
17678
17693
  }
17679
17694
  function resolveHooksCli(pluginRoot) {
17680
17695
  const override = process.env.VERITY_CLI_PATH;
17681
- if (override && (0, import_node_fs9.existsSync)(override)) {
17696
+ if (override && (0, import_node_fs10.existsSync)(override)) {
17682
17697
  return { version: versionForEntry(override), rung: "override" };
17683
17698
  }
17684
17699
  const fromPlugin = versionUnder(pluginRoot);
17685
17700
  if (fromPlugin !== null) return { version: fromPlugin, rung: "plugin" };
17686
- if ((0, import_node_fs9.existsSync)((0, import_node_path10.join)(pluginRoot, CLI_ENTRY))) return { version: null, rung: "plugin" };
17687
- const dataDir = process.env.CLAUDE_PLUGIN_DATA || (0, import_node_path10.join)((0, import_node_os3.homedir)(), ".verity", "plugin-cli");
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");
17688
17703
  const fromData = versionUnder(dataDir);
17689
17704
  if (fromData !== null) return { version: fromData, rung: "plugin-data" };
17690
- if ((0, import_node_fs9.existsSync)((0, import_node_path10.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
17705
+ if ((0, import_node_fs10.existsSync)((0, import_node_path11.join)(dataDir, CLI_ENTRY))) return { version: null, rung: "plugin-data" };
17691
17706
  const global = globalVerityVersion();
17692
17707
  if (global !== null) return { version: global, rung: "global" };
17693
17708
  return null;
@@ -17789,7 +17804,7 @@ function pluginCliInvocation() {
17789
17804
  return resolverCommand(root);
17790
17805
  }
17791
17806
  function resolverCommand(root) {
17792
- return `node ${JSON.stringify((0, import_node_path10.join)(root, "scripts", "verity.mjs"))}`;
17807
+ return `node ${JSON.stringify((0, import_node_path11.join)(root, "scripts", "verity.mjs"))}`;
17793
17808
  }
17794
17809
 
17795
17810
  // src/commands/hooks.ts
@@ -17929,7 +17944,7 @@ var import_node_crypto9 = require("node:crypto");
17929
17944
 
17930
17945
  // src/lib/conversation-buffer.ts
17931
17946
  var import_promises5 = require("node:fs/promises");
17932
- var import_node_fs10 = require("node:fs");
17947
+ var import_node_fs11 = require("node:fs");
17933
17948
  var import_node_child_process6 = require("node:child_process");
17934
17949
  var import_node_crypto = require("node:crypto");
17935
17950
  function stripImageReferences(text) {
@@ -17965,7 +17980,7 @@ async function appendToConversationBuffer(prompt, sessionId) {
17965
17980
  }
17966
17981
  async function readAndClearConversationBuffer(currentSessionId) {
17967
17982
  try {
17968
- if ((0, import_node_fs10.existsSync)(CONVERSATION_BUFFER_FILE)) {
17983
+ if ((0, import_node_fs11.existsSync)(CONVERSATION_BUFFER_FILE)) {
17969
17984
  const entries = await readBufferEntries();
17970
17985
  let mine = entries;
17971
17986
  let others = [];
@@ -17989,7 +18004,7 @@ async function readAndClearConversationBuffer(currentSessionId) {
17989
18004
  };
17990
18005
  }
17991
18006
  }
17992
- if ((0, import_node_fs10.existsSync)(INTENT_FILE)) {
18007
+ if ((0, import_node_fs11.existsSync)(INTENT_FILE)) {
17993
18008
  try {
17994
18009
  const content = await (0, import_promises5.readFile)(INTENT_FILE, "utf-8");
17995
18010
  await (0, import_promises5.unlink)(INTENT_FILE).catch(() => {
@@ -18282,9 +18297,9 @@ function isCommandOnlyTurn(input) {
18282
18297
 
18283
18298
  // src/lib/context-identity.ts
18284
18299
  var import_node_crypto2 = require("node:crypto");
18285
- var import_node_fs11 = require("node:fs");
18300
+ var import_node_fs12 = require("node:fs");
18286
18301
  var import_node_os4 = require("node:os");
18287
- var import_node_path11 = require("node:path");
18302
+ var import_node_path12 = require("node:path");
18288
18303
  var SHARED_SENTINELS = /* @__PURE__ */ new Set([
18289
18304
  "",
18290
18305
  "-",
@@ -18322,7 +18337,7 @@ function contextIdentity(input) {
18322
18337
  if (rawTree && !isSharedSentinel(rawTree)) {
18323
18338
  let resolved = rawTree;
18324
18339
  try {
18325
- resolved = import_node_fs11.realpathSync.native(rawTree);
18340
+ resolved = import_node_fs12.realpathSync.native(rawTree);
18326
18341
  } catch {
18327
18342
  }
18328
18343
  treeKey = (0, import_node_crypto2.createHash)("sha256").update(resolved).digest("hex").slice(0, 12);
@@ -18338,13 +18353,13 @@ function contextIdentity(input) {
18338
18353
  }
18339
18354
  function verityHome() {
18340
18355
  const override = process.env.VERITY_HOME;
18341
- return override && override.trim() ? (0, import_node_path11.resolve)(override) : (0, import_node_path11.join)((0, import_node_os4.homedir)(), ".verity");
18356
+ return override && override.trim() ? (0, import_node_path12.resolve)(override) : (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".verity");
18342
18357
  }
18343
18358
  function dossierDir(identity) {
18344
- return (0, import_node_path11.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
18359
+ return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey, identity.sessionKey);
18345
18360
  }
18346
18361
  function treeDir(identity) {
18347
- return (0, import_node_path11.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
18362
+ return (0, import_node_path12.join)(verityHome(), "sessions", identity.userKey, identity.treeKey);
18348
18363
  }
18349
18364
  function scopeIdentity(token, sessionId) {
18350
18365
  const t = (token ?? "").trim();
@@ -18359,8 +18374,8 @@ function sessionScopeKey(token, sessionId) {
18359
18374
 
18360
18375
  // src/lib/task-context-buffer.ts
18361
18376
  var import_promises6 = require("node:fs/promises");
18362
- var import_node_fs12 = require("node:fs");
18363
- var import_node_path12 = require("node:path");
18377
+ var import_node_fs13 = require("node:fs");
18378
+ var import_node_path13 = require("node:path");
18364
18379
  var TASK_CONTEXT_DIR = `${VERITY_DIR}/.task-context`;
18365
18380
  var MAX_BUFFER_BYTES = 500 * 1024;
18366
18381
  var MAX_PROMPT_CHARS = 2e3;
@@ -18399,7 +18414,7 @@ async function appendResponseToTaskBuffer(taskId, assistantResponse, actionSumma
18399
18414
  }
18400
18415
  async function readTaskContextBuffer(taskId) {
18401
18416
  const filePath = bufferPath(taskId);
18402
- if (!(0, import_node_fs12.existsSync)(filePath)) return null;
18417
+ if (!(0, import_node_fs13.existsSync)(filePath)) return null;
18403
18418
  try {
18404
18419
  const content = await (0, import_promises6.readFile)(filePath, "utf-8");
18405
18420
  if (!content.trim()) return null;
@@ -18433,12 +18448,12 @@ async function readTaskContextBuffer(taskId) {
18433
18448
  }
18434
18449
  async function cleanupTaskContextBuffers() {
18435
18450
  try {
18436
- if (!(0, import_node_fs12.existsSync)(TASK_CONTEXT_DIR)) return;
18451
+ if (!(0, import_node_fs13.existsSync)(TASK_CONTEXT_DIR)) return;
18437
18452
  const files = await (0, import_promises6.readdir)(TASK_CONTEXT_DIR);
18438
18453
  const cutoffMs = Date.now() - RETENTION_DAYS * 24 * 60 * 60 * 1e3;
18439
18454
  for (const file of files) {
18440
18455
  if (!file.endsWith(".jsonl")) continue;
18441
- const filePath = (0, import_node_path12.join)(TASK_CONTEXT_DIR, file);
18456
+ const filePath = (0, import_node_path13.join)(TASK_CONTEXT_DIR, file);
18442
18457
  try {
18443
18458
  const stats = await (0, import_promises6.stat)(filePath);
18444
18459
  if (stats.mtimeMs < cutoffMs) {
@@ -18452,13 +18467,13 @@ async function cleanupTaskContextBuffers() {
18452
18467
  }
18453
18468
  function bufferPath(taskId) {
18454
18469
  const safe = taskId.replace(/[^a-zA-Z0-9_-]/g, "");
18455
- return (0, import_node_path12.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
18470
+ return (0, import_node_path13.join)(TASK_CONTEXT_DIR, `${safe}.jsonl`);
18456
18471
  }
18457
18472
  async function appendEntry(taskId, entry) {
18458
18473
  try {
18459
18474
  await (0, import_promises6.mkdir)(TASK_CONTEXT_DIR, { recursive: true });
18460
18475
  const filePath = bufferPath(taskId);
18461
- if ((0, import_node_fs12.existsSync)(filePath)) {
18476
+ if ((0, import_node_fs13.existsSync)(filePath)) {
18462
18477
  const stats = await (0, import_promises6.stat)(filePath);
18463
18478
  if (stats.size >= MAX_BUFFER_BYTES) {
18464
18479
  const content = await (0, import_promises6.readFile)(filePath, "utf-8");
@@ -18469,7 +18484,7 @@ async function appendEntry(taskId, entry) {
18469
18484
  }
18470
18485
  }
18471
18486
  const line2 = JSON.stringify(entry) + "\n";
18472
- const existing = (0, import_node_fs12.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
18487
+ const existing = (0, import_node_fs13.existsSync)(filePath) ? await (0, import_promises6.readFile)(filePath, "utf-8") : "";
18473
18488
  await (0, import_promises6.writeFile)(filePath, existing + line2);
18474
18489
  } catch {
18475
18490
  }
@@ -18477,20 +18492,20 @@ async function appendEntry(taskId, entry) {
18477
18492
 
18478
18493
  // src/lib/memory-retrieval.ts
18479
18494
  var import_promises8 = require("node:fs/promises");
18480
- var import_node_fs15 = require("node:fs");
18481
- var import_node_path15 = require("node:path");
18495
+ var import_node_fs16 = require("node:fs");
18496
+ var import_node_path16 = require("node:path");
18482
18497
 
18483
18498
  // src/lib/org-mirror.ts
18484
- var import_node_fs13 = require("node:fs");
18499
+ var import_node_fs14 = require("node:fs");
18485
18500
  var import_promises7 = require("node:fs/promises");
18486
- var import_node_path13 = require("node:path");
18501
+ var import_node_path14 = require("node:path");
18487
18502
  var ORG_KINDS = ["decision", "security", "gotcha", "pattern", "domain", "integration"];
18488
18503
  var STATE_FILE = ".org-pull-state.json";
18489
18504
  var BODY_MAX = 8192;
18490
18505
  function orgMirrorDir(remote = requestRemote()) {
18491
18506
  const parsed = parseRemote(remote);
18492
18507
  if (!parsed) return null;
18493
- return (0, import_node_path13.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
18508
+ return (0, import_node_path14.join)(verityHome(), "orgs", parsed.host, parsed.owner.toLowerCase(), "memory");
18494
18509
  }
18495
18510
  function slugify(s) {
18496
18511
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 60);
@@ -18556,7 +18571,7 @@ function parseOrgNode(content) {
18556
18571
  }
18557
18572
  async function readState(dir) {
18558
18573
  try {
18559
- const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path13.join)(dir, STATE_FILE), "utf-8"));
18574
+ const parsed = JSON.parse(await (0, import_promises7.readFile)((0, import_node_path14.join)(dir, STATE_FILE), "utf-8"));
18560
18575
  return {
18561
18576
  version: typeof parsed?.version === "string" ? parsed.version : null,
18562
18577
  organization: parsed?.organization && typeof parsed.organization.id === "string" ? parsed.organization : null,
@@ -18568,7 +18583,7 @@ async function readState(dir) {
18568
18583
  }
18569
18584
  async function writeState(dir, state) {
18570
18585
  await (0, import_promises7.mkdir)(dir, { recursive: true });
18571
- await (0, import_promises7.writeFile)((0, import_node_path13.join)(dir, STATE_FILE), JSON.stringify({
18586
+ await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, STATE_FILE), JSON.stringify({
18572
18587
  ...state.version ? { version: state.version } : {},
18573
18588
  organization: state.organization,
18574
18589
  pulled_at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -18633,24 +18648,24 @@ async function pullOrgKnowledge(opts) {
18633
18648
  for (const n of nodes) {
18634
18649
  const rel = orgNodePath(n);
18635
18650
  if (written.has(rel)) continue;
18636
- await (0, import_promises7.mkdir)((0, import_node_path13.join)(dir, rel.split("/")[0]), { recursive: true });
18637
- await (0, import_promises7.writeFile)((0, import_node_path13.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
18651
+ await (0, import_promises7.mkdir)((0, import_node_path14.join)(dir, rel.split("/")[0]), { recursive: true });
18652
+ await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, rel), renderOrgNode(n, org?.name ?? ""));
18638
18653
  written.add(rel);
18639
18654
  }
18640
18655
  for (const rel of state.files) {
18641
- if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path13.join)(dir, rel), { force: true });
18656
+ if (!written.has(rel)) await (0, import_promises7.rm)((0, import_node_path14.join)(dir, rel), { force: true });
18642
18657
  }
18643
- await (0, import_promises7.writeFile)((0, import_node_path13.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
18658
+ await (0, import_promises7.writeFile)((0, import_node_path14.join)(dir, "index.md"), renderIndex(org?.name ?? "no organization", nodes));
18644
18659
  await writeState(dir, { version: org ? page.version : null, organization: org, files: [...written].sort() });
18645
18660
  return { ok: true, status: org ? "pulled" : "none", received: nodes.length, dir };
18646
18661
  }
18647
18662
  async function readOrgMirror(remote = requestRemote()) {
18648
18663
  const dir = orgMirrorDir(remote);
18649
- if (!dir || !(0, import_node_fs13.existsSync)(dir)) return [];
18664
+ if (!dir || !(0, import_node_fs14.existsSync)(dir)) return [];
18650
18665
  const out2 = [];
18651
18666
  for (const kind of ORG_KINDS) {
18652
- const kindDir = (0, import_node_path13.join)(dir, kind);
18653
- if (!(0, import_node_fs13.existsSync)(kindDir)) continue;
18667
+ const kindDir = (0, import_node_path14.join)(dir, kind);
18668
+ if (!(0, import_node_fs14.existsSync)(kindDir)) continue;
18654
18669
  let files;
18655
18670
  try {
18656
18671
  files = await (0, import_promises7.readdir)(kindDir);
@@ -18660,7 +18675,7 @@ async function readOrgMirror(remote = requestRemote()) {
18660
18675
  for (const file of files) {
18661
18676
  if (!file.endsWith(".md")) continue;
18662
18677
  try {
18663
- const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path13.join)(kindDir, file), "utf-8"));
18678
+ const node = parseOrgNode(await (0, import_promises7.readFile)((0, import_node_path14.join)(kindDir, file), "utf-8"));
18664
18679
  if (node) out2.push(node);
18665
18680
  } catch {
18666
18681
  }
@@ -18670,29 +18685,29 @@ async function readOrgMirror(remote = requestRemote()) {
18670
18685
  }
18671
18686
 
18672
18687
  // src/lib/safe-read.ts
18673
- var import_node_fs14 = require("node:fs");
18674
- var import_node_path14 = require("node:path");
18675
- var FLAGS = import_node_fs14.constants;
18688
+ var import_node_fs15 = require("node:fs");
18689
+ var import_node_path15 = require("node:path");
18690
+ var FLAGS = import_node_fs15.constants;
18676
18691
  var NOFOLLOW = FLAGS.O_NOFOLLOW;
18677
18692
  var NONBLOCK = FLAGS.O_NONBLOCK;
18678
18693
  function closeOpened(fd) {
18679
18694
  try {
18680
- (0, import_node_fs14.closeSync)(fd);
18695
+ (0, import_node_fs15.closeSync)(fd);
18681
18696
  } catch {
18682
18697
  }
18683
18698
  }
18684
18699
  function isInsideRoot(realRoot, realPath) {
18685
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path14.sep) ? realRoot : realRoot + import_node_path14.sep);
18700
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path15.sep) ? realRoot : realRoot + import_node_path15.sep);
18686
18701
  }
18687
18702
  function sameOpenedFile(opened, current, nofollowAvailable) {
18688
18703
  if (!nofollowAvailable && (opened.ino === 0n || current.ino === 0n)) return false;
18689
18704
  return opened.ino === current.ino && opened.dev === current.dev;
18690
18705
  }
18691
18706
  function openRegularInRoot(root, path) {
18692
- const full = (0, import_node_path14.isAbsolute)(path) ? path : (0, import_node_path14.join)(root, path);
18707
+ const full = (0, import_node_path15.isAbsolute)(path) ? path : (0, import_node_path15.join)(root, path);
18693
18708
  let fd;
18694
18709
  try {
18695
- fd = (0, import_node_fs14.openSync)(full, import_node_fs14.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
18710
+ fd = (0, import_node_fs15.openSync)(full, import_node_fs15.constants.O_RDONLY | (NOFOLLOW ?? 0) | (NONBLOCK ?? 0));
18696
18711
  } catch (err2) {
18697
18712
  const code = err2.code;
18698
18713
  if (code === "ELOOP" || code === "EMLINK" || code === "EFTYPE") return { ok: false, reason: "symlink" };
@@ -18700,18 +18715,18 @@ function openRegularInRoot(root, path) {
18700
18715
  return { ok: false, reason: "unreadable" };
18701
18716
  }
18702
18717
  try {
18703
- const opened = (0, import_node_fs14.fstatSync)(fd, { bigint: true });
18718
+ const opened = (0, import_node_fs15.fstatSync)(fd, { bigint: true });
18704
18719
  if (!opened.isFile()) {
18705
18720
  closeOpened(fd);
18706
18721
  return { ok: false, reason: "not-regular" };
18707
18722
  }
18708
- const realRoot = import_node_fs14.realpathSync.native(root);
18709
- const realPath = import_node_fs14.realpathSync.native(full);
18723
+ const realRoot = import_node_fs15.realpathSync.native(root);
18724
+ const realPath = import_node_fs15.realpathSync.native(full);
18710
18725
  if (!isInsideRoot(realRoot, realPath)) {
18711
18726
  closeOpened(fd);
18712
18727
  return { ok: false, reason: "outside-root" };
18713
18728
  }
18714
- const current = (0, import_node_fs14.statSync)(realPath, { bigint: true });
18729
+ const current = (0, import_node_fs15.statSync)(realPath, { bigint: true });
18715
18730
  if (!sameOpenedFile(opened, current, NOFOLLOW !== void 0)) {
18716
18731
  closeOpened(fd);
18717
18732
  return { ok: false, reason: NOFOLLOW === void 0 ? "unreadable" : "outside-root" };
@@ -18733,7 +18748,7 @@ function readOpened(fd, size) {
18733
18748
  const buffer = Buffer.alloc(size);
18734
18749
  let offset = 0;
18735
18750
  while (offset < size) {
18736
- const n = (0, import_node_fs14.readSync)(fd, buffer, offset, size - offset, offset);
18751
+ const n = (0, import_node_fs15.readSync)(fd, buffer, offset, size - offset, offset);
18737
18752
  if (n === 0) break;
18738
18753
  offset += n;
18739
18754
  }
@@ -19048,14 +19063,14 @@ function parseFrontmatter(content) {
19048
19063
  return { fm, body: match[2].trim() };
19049
19064
  }
19050
19065
  async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = DEFAULT_BUDGET_TOKENS) {
19051
- const hasRepoGraph = (0, import_node_fs15.existsSync)(memoryDir());
19066
+ const hasRepoGraph = (0, import_node_fs16.existsSync)(memoryDir());
19052
19067
  const budget = Math.min(budgetTokens, MAX_BUDGET_TOKENS);
19053
19068
  const promptTokens = tokenize(promptText);
19054
19069
  const orgPromptTerms = orgTerms(promptText);
19055
19070
  const nodes = [];
19056
19071
  for (const domain of hasRepoGraph ? DOMAINS : []) {
19057
- const domainDir = (0, import_node_path15.join)(memoryDir(), domain);
19058
- if (!(0, import_node_fs15.existsSync)(domainDir)) continue;
19072
+ const domainDir = (0, import_node_path16.join)(memoryDir(), domain);
19073
+ if (!(0, import_node_fs16.existsSync)(domainDir)) continue;
19059
19074
  try {
19060
19075
  const files = await (0, import_promises8.readdir)(domainDir);
19061
19076
  for (const file of files) {
@@ -19129,27 +19144,27 @@ async function retrieveForInjection(promptText, taskFiles = [], budgetTokens = D
19129
19144
  }
19130
19145
 
19131
19146
  // src/lib/injection-record.ts
19132
- var import_node_fs17 = require("node:fs");
19147
+ var import_node_fs18 = require("node:fs");
19133
19148
  var import_node_crypto3 = require("node:crypto");
19134
19149
 
19135
19150
  // src/lib/safe-write.ts
19136
- var import_node_fs16 = require("node:fs");
19137
- var import_node_path16 = require("node:path");
19138
- var FLAGS2 = import_node_fs16.constants;
19151
+ var import_node_fs17 = require("node:fs");
19152
+ var import_node_path17 = require("node:path");
19153
+ var FLAGS2 = import_node_fs17.constants;
19139
19154
  var O_NOFOLLOW = FLAGS2.O_NOFOLLOW ?? 0;
19140
19155
  var NOFOLLOW_AVAILABLE = O_NOFOLLOW !== 0;
19141
19156
  function validateRoot(root) {
19142
19157
  try {
19143
- const parentReal = (0, import_node_fs16.realpathSync)((0, import_node_path16.dirname)(root));
19144
- const expected = (0, import_node_path16.join)(parentReal, (0, import_node_path16.basename)(root));
19158
+ const parentReal = (0, import_node_fs17.realpathSync)((0, import_node_path17.dirname)(root));
19159
+ const expected = (0, import_node_path17.join)(parentReal, (0, import_node_path17.basename)(root));
19145
19160
  try {
19146
- (0, import_node_fs16.mkdirSync)(expected);
19161
+ (0, import_node_fs17.mkdirSync)(expected);
19147
19162
  } catch (e) {
19148
19163
  if (e.code !== "EEXIST") return null;
19149
19164
  }
19150
- const st = (0, import_node_fs16.lstatSync)(expected, { bigint: true });
19165
+ const st = (0, import_node_fs17.lstatSync)(expected, { bigint: true });
19151
19166
  if (st.isSymbolicLink() || !st.isDirectory()) return null;
19152
- if ((0, import_node_fs16.realpathSync)(expected) !== expected) return null;
19167
+ if ((0, import_node_fs17.realpathSync)(expected) !== expected) return null;
19153
19168
  return { real: expected, dev: st.dev, ino: st.ino };
19154
19169
  } catch {
19155
19170
  return null;
@@ -19157,18 +19172,18 @@ function validateRoot(root) {
19157
19172
  }
19158
19173
  function rootUnchanged(root) {
19159
19174
  try {
19160
- const st = (0, import_node_fs16.lstatSync)(root.real, { bigint: true });
19175
+ const st = (0, import_node_fs17.lstatSync)(root.real, { bigint: true });
19161
19176
  return !st.isSymbolicLink() && st.isDirectory() && st.dev === root.dev && st.ino === root.ino;
19162
19177
  } catch {
19163
19178
  return false;
19164
19179
  }
19165
19180
  }
19166
19181
  function bareName(name2) {
19167
- return !!name2 && name2 === (0, import_node_path16.basename)(name2) && name2 !== "." && name2 !== ".." && !name2.includes("\0");
19182
+ return !!name2 && name2 === (0, import_node_path17.basename)(name2) && name2 !== "." && name2 !== ".." && !name2.includes("\0");
19168
19183
  }
19169
19184
  function absentOrRegular(path) {
19170
19185
  try {
19171
- const st = (0, import_node_fs16.lstatSync)(path);
19186
+ const st = (0, import_node_fs17.lstatSync)(path);
19172
19187
  return st.isFile() && !st.isSymbolicLink();
19173
19188
  } catch (e) {
19174
19189
  return e.code === "ENOENT";
@@ -19176,11 +19191,11 @@ function absentOrRegular(path) {
19176
19191
  }
19177
19192
  function verifyOpened(fd, path, root) {
19178
19193
  try {
19179
- const opened = (0, import_node_fs16.fstatSync)(fd, { bigint: true });
19194
+ const opened = (0, import_node_fs17.fstatSync)(fd, { bigint: true });
19180
19195
  if (!opened.isFile() || opened.nlink !== 1n) return false;
19181
- const real = (0, import_node_fs16.realpathSync)(path);
19196
+ const real = (0, import_node_fs17.realpathSync)(path);
19182
19197
  if (!isInsideRoot(root.real, real)) return false;
19183
- const current = (0, import_node_fs16.statSync)(real, { bigint: true });
19198
+ const current = (0, import_node_fs17.statSync)(real, { bigint: true });
19184
19199
  if (!sameOpenedFile(opened, current, NOFOLLOW_AVAILABLE)) return false;
19185
19200
  return rootUnchanged(root);
19186
19201
  } catch {
@@ -19189,21 +19204,21 @@ function verifyOpened(fd, path, root) {
19189
19204
  }
19190
19205
  function removeIfOurs(fd, path) {
19191
19206
  try {
19192
- const opened = (0, import_node_fs16.fstatSync)(fd, { bigint: true });
19193
- const at = (0, import_node_fs16.lstatSync)(path, { bigint: true });
19194
- if (!at.isSymbolicLink() && at.dev === opened.dev && at.ino === opened.ino) (0, import_node_fs16.unlinkSync)(path);
19207
+ const opened = (0, import_node_fs17.fstatSync)(fd, { bigint: true });
19208
+ const at = (0, import_node_fs17.lstatSync)(path, { bigint: true });
19209
+ if (!at.isSymbolicLink() && at.dev === opened.dev && at.ino === opened.ino) (0, import_node_fs17.unlinkSync)(path);
19195
19210
  } catch {
19196
19211
  }
19197
19212
  }
19198
19213
  function openTarget(path, append2) {
19199
- const base = import_node_fs16.constants.O_WRONLY | (append2 ? import_node_fs16.constants.O_APPEND : 0) | O_NOFOLLOW;
19214
+ const base = import_node_fs17.constants.O_WRONLY | (append2 ? import_node_fs17.constants.O_APPEND : 0) | O_NOFOLLOW;
19200
19215
  try {
19201
- return { fd: (0, import_node_fs16.openSync)(path, base), created: false };
19216
+ return { fd: (0, import_node_fs17.openSync)(path, base), created: false };
19202
19217
  } catch (e) {
19203
19218
  if (e.code !== "ENOENT") return null;
19204
19219
  }
19205
19220
  try {
19206
- return { fd: (0, import_node_fs16.openSync)(path, base | import_node_fs16.constants.O_CREAT | import_node_fs16.constants.O_EXCL, 384), created: true };
19221
+ return { fd: (0, import_node_fs17.openSync)(path, base | import_node_fs17.constants.O_CREAT | import_node_fs17.constants.O_EXCL, 384), created: true };
19207
19222
  } catch {
19208
19223
  return null;
19209
19224
  }
@@ -19211,7 +19226,7 @@ function openTarget(path, append2) {
19211
19226
  function writeVerified(root, name2, hooks, append2, write) {
19212
19227
  const r = validateRoot(root);
19213
19228
  if (!r || !bareName(name2)) return false;
19214
- const path = (0, import_node_path16.join)(r.real, name2);
19229
+ const path = (0, import_node_path17.join)(r.real, name2);
19215
19230
  if (!absentOrRegular(path)) return false;
19216
19231
  if (!runHook(hooks)) return false;
19217
19232
  const opened = openTarget(path, append2);
@@ -19227,7 +19242,7 @@ function writeVerified(root, name2, hooks, append2, write) {
19227
19242
  return false;
19228
19243
  } finally {
19229
19244
  try {
19230
- (0, import_node_fs16.closeSync)(opened.fd);
19245
+ (0, import_node_fs17.closeSync)(opened.fd);
19231
19246
  } catch {
19232
19247
  }
19233
19248
  }
@@ -19242,13 +19257,13 @@ function runHook(hooks) {
19242
19257
  }
19243
19258
  function appendInRoot(root, name2, text, hooks = {}) {
19244
19259
  return writeVerified(root, name2, hooks, true, (fd) => {
19245
- (0, import_node_fs16.writeSync)(fd, text);
19260
+ (0, import_node_fs17.writeSync)(fd, text);
19246
19261
  });
19247
19262
  }
19248
19263
  function replaceInRoot(root, name2, text, hooks = {}) {
19249
19264
  return writeVerified(root, name2, hooks, false, (fd) => {
19250
- (0, import_node_fs16.ftruncateSync)(fd, 0);
19251
- (0, import_node_fs16.writeSync)(fd, text, 0);
19265
+ (0, import_node_fs17.ftruncateSync)(fd, 0);
19266
+ (0, import_node_fs17.writeSync)(fd, text, 0);
19252
19267
  });
19253
19268
  }
19254
19269
 
@@ -19296,7 +19311,7 @@ function hashPrompt(prompt) {
19296
19311
  function recordInjection(event) {
19297
19312
  if (!appendInRoot(projectPath(VERITY_DIR), "injections.jsonl", JSON.stringify(event) + "\n")) return;
19298
19313
  try {
19299
- if ((0, import_node_fs17.lstatSync)(recordPath()).size > COMPACT_AT_BYTES) writeEvents(readPendingInjections());
19314
+ if ((0, import_node_fs18.lstatSync)(recordPath()).size > COMPACT_AT_BYTES) writeEvents(readPendingInjections());
19300
19315
  } catch {
19301
19316
  }
19302
19317
  }
@@ -19306,7 +19321,7 @@ function writeEvents(events) {
19306
19321
  function readPendingInjections() {
19307
19322
  try {
19308
19323
  const p = recordPath();
19309
- if (!(0, import_node_fs17.existsSync)(p)) return [];
19324
+ if (!(0, import_node_fs18.existsSync)(p)) return [];
19310
19325
  const read2 = readRegularFileInRoot(projectPath(VERITY_DIR), "injections.jsonl", MAX_RECORD_BYTES);
19311
19326
  if (!read2.ok) return [];
19312
19327
  const out2 = [];
@@ -19326,13 +19341,13 @@ function readPendingInjections() {
19326
19341
 
19327
19342
  // src/lib/memory-sync.ts
19328
19343
  var import_promises9 = require("node:fs/promises");
19329
- var import_node_fs20 = require("node:fs");
19330
- var import_node_path18 = require("node:path");
19344
+ var import_node_fs21 = require("node:fs");
19345
+ var import_node_path19 = require("node:path");
19331
19346
  var import_node_crypto4 = require("node:crypto");
19332
19347
 
19333
19348
  // src/lib/gitignore.ts
19334
19349
  var import_node_child_process7 = require("node:child_process");
19335
- var import_node_fs18 = require("node:fs");
19350
+ var import_node_fs19 = require("node:fs");
19336
19351
  var VERITY_GITIGNORE_MARKER = "# Verity \u2014 machine-local state.";
19337
19352
  var SETTINGS_LOCAL_IGNORE_ENTRY = ".claude/settings.local.json";
19338
19353
  var VERITY_GITIGNORE_BLOCK = [
@@ -19416,7 +19431,7 @@ function fenceMemoryLines(lines) {
19416
19431
  function ensureVerityGitignore() {
19417
19432
  let content = "";
19418
19433
  try {
19419
- content = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
19434
+ content = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
19420
19435
  } catch {
19421
19436
  }
19422
19437
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -19443,7 +19458,7 @@ function ensureVerityGitignore() {
19443
19458
  const sep5 = text === "" ? "" : text.endsWith("\n") ? "\n" : "\n\n";
19444
19459
  text = text + sep5 + VERITY_GITIGNORE_BLOCK;
19445
19460
  }
19446
- if (text !== content) (0, import_node_fs18.writeFileSync)(".gitignore", text);
19461
+ if (text !== content) (0, import_node_fs19.writeFileSync)(".gitignore", text);
19447
19462
  return verified(
19448
19463
  memoryIsCommitted ? "memory-tracked" : hasSupersededMemory ? "memory-fenced" : needsRepair ? "repaired" : "added"
19449
19464
  );
@@ -19463,7 +19478,7 @@ function untrackMemory() {
19463
19478
  function writeFencedBlock() {
19464
19479
  let content = "";
19465
19480
  try {
19466
- content = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
19481
+ content = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
19467
19482
  } catch {
19468
19483
  }
19469
19484
  const hasMarker = content.includes(VERITY_GITIGNORE_MARKER);
@@ -19475,7 +19490,7 @@ function writeFencedBlock() {
19475
19490
  text = text + sep5 + VERITY_GITIGNORE_BLOCK;
19476
19491
  }
19477
19492
  try {
19478
- (0, import_node_fs18.writeFileSync)(".gitignore", text);
19493
+ (0, import_node_fs19.writeFileSync)(".gitignore", text);
19479
19494
  return true;
19480
19495
  } catch {
19481
19496
  return false;
@@ -19484,14 +19499,14 @@ function writeFencedBlock() {
19484
19499
  function fenceMemory() {
19485
19500
  let original = null;
19486
19501
  try {
19487
- original = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
19502
+ original = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
19488
19503
  } catch {
19489
19504
  original = null;
19490
19505
  }
19491
19506
  const restore = () => {
19492
19507
  try {
19493
- if (original === null) (0, import_node_fs18.rmSync)(".gitignore", { force: true });
19494
- else (0, import_node_fs18.writeFileSync)(".gitignore", original);
19508
+ if (original === null) (0, import_node_fs19.rmSync)(".gitignore", { force: true });
19509
+ else (0, import_node_fs19.writeFileSync)(".gitignore", original);
19495
19510
  } catch {
19496
19511
  }
19497
19512
  };
@@ -19509,7 +19524,7 @@ function fenceMemory() {
19509
19524
  }
19510
19525
  function memoryOptOut() {
19511
19526
  try {
19512
- return (0, import_node_fs18.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
19527
+ return (0, import_node_fs19.readFileSync)(".gitignore", "utf-8").includes(MEMORY_OPT_OUT_MARKER);
19513
19528
  } catch {
19514
19529
  return false;
19515
19530
  }
@@ -19517,13 +19532,13 @@ function memoryOptOut() {
19517
19532
  function keepMemoryTracked() {
19518
19533
  let content = "";
19519
19534
  try {
19520
- content = (0, import_node_fs18.readFileSync)(".gitignore", "utf-8");
19535
+ content = (0, import_node_fs19.readFileSync)(".gitignore", "utf-8");
19521
19536
  } catch {
19522
19537
  }
19523
19538
  if (content.includes(MEMORY_OPT_OUT_MARKER)) return "already";
19524
19539
  try {
19525
19540
  const sep5 = content === "" ? "" : content.endsWith("\n") ? "\n" : "\n\n";
19526
- (0, import_node_fs18.writeFileSync)(".gitignore", content + sep5 + MEMORY_OPT_OUT_STANZA);
19541
+ (0, import_node_fs19.writeFileSync)(".gitignore", content + sep5 + MEMORY_OPT_OUT_STANZA);
19527
19542
  } catch {
19528
19543
  return "failed";
19529
19544
  }
@@ -19558,26 +19573,26 @@ function untrackVerityState() {
19558
19573
  }
19559
19574
 
19560
19575
  // src/lib/safe-path.ts
19561
- var import_node_fs19 = require("node:fs");
19562
- var import_node_path17 = require("node:path");
19576
+ var import_node_fs20 = require("node:fs");
19577
+ var import_node_path18 = require("node:path");
19563
19578
  function resolveInside(baseDir, candidate) {
19564
19579
  if (typeof candidate !== "string" || candidate.length === 0) return null;
19565
- if ((0, import_node_path17.isAbsolute)(candidate)) return null;
19566
- const baseAbs = (0, import_node_path17.resolve)(baseDir);
19567
- const full = (0, import_node_path17.resolve)(baseAbs, candidate);
19568
- const baseSep = baseAbs.endsWith(import_node_path17.sep) ? baseAbs : baseAbs + import_node_path17.sep;
19580
+ if ((0, import_node_path18.isAbsolute)(candidate)) return null;
19581
+ const baseAbs = (0, import_node_path18.resolve)(baseDir);
19582
+ const full = (0, import_node_path18.resolve)(baseAbs, candidate);
19583
+ const baseSep = baseAbs.endsWith(import_node_path18.sep) ? baseAbs : baseAbs + import_node_path18.sep;
19569
19584
  if (full !== baseAbs && !full.startsWith(baseSep)) return null;
19570
19585
  try {
19571
- if ((0, import_node_fs19.existsSync)(baseAbs)) {
19572
- const realBase = (0, import_node_fs19.realpathSync)(baseAbs);
19573
- const realBaseSep = realBase.endsWith(import_node_path17.sep) ? realBase : realBase + import_node_path17.sep;
19586
+ if ((0, import_node_fs20.existsSync)(baseAbs)) {
19587
+ const realBase = (0, import_node_fs20.realpathSync)(baseAbs);
19588
+ const realBaseSep = realBase.endsWith(import_node_path18.sep) ? realBase : realBase + import_node_path18.sep;
19574
19589
  let probe = full;
19575
- while (!(0, import_node_fs19.existsSync)(probe)) {
19576
- const parent = (0, import_node_path17.dirname)(probe);
19590
+ while (!(0, import_node_fs20.existsSync)(probe)) {
19591
+ const parent = (0, import_node_path18.dirname)(probe);
19577
19592
  if (parent === probe) break;
19578
19593
  probe = parent;
19579
19594
  }
19580
- const realProbe = (0, import_node_fs19.realpathSync)(probe);
19595
+ const realProbe = (0, import_node_fs20.realpathSync)(probe);
19581
19596
  if (realProbe !== realBase && !realProbe.startsWith(realBaseSep)) return null;
19582
19597
  }
19583
19598
  } catch {
@@ -19585,37 +19600,37 @@ function resolveInside(baseDir, candidate) {
19585
19600
  }
19586
19601
  return full;
19587
19602
  }
19588
- var O_NOFOLLOW2 = typeof import_node_fs19.constants.O_NOFOLLOW === "number" ? import_node_fs19.constants.O_NOFOLLOW : 0;
19603
+ var O_NOFOLLOW2 = typeof import_node_fs20.constants.O_NOFOLLOW === "number" ? import_node_fs20.constants.O_NOFOLLOW : 0;
19589
19604
  function readFileInside(baseDir, candidate, maxBytes) {
19590
19605
  const full = resolveInside(baseDir, candidate);
19591
19606
  if (!full) return null;
19592
19607
  let realParent;
19593
19608
  let realBase;
19594
19609
  try {
19595
- realParent = (0, import_node_fs19.realpathSync)((0, import_node_path17.dirname)(full));
19596
- realBase = (0, import_node_fs19.realpathSync)((0, import_node_path17.resolve)(baseDir));
19610
+ realParent = (0, import_node_fs20.realpathSync)((0, import_node_path18.dirname)(full));
19611
+ realBase = (0, import_node_fs20.realpathSync)((0, import_node_path18.resolve)(baseDir));
19597
19612
  } catch {
19598
19613
  return null;
19599
19614
  }
19600
- const realBaseSep = realBase.endsWith(import_node_path17.sep) ? realBase : realBase + import_node_path17.sep;
19615
+ const realBaseSep = realBase.endsWith(import_node_path18.sep) ? realBase : realBase + import_node_path18.sep;
19601
19616
  if (realParent !== realBase && !realParent.startsWith(realBaseSep)) return null;
19602
- const target = (0, import_node_path17.join)(realParent, (0, import_node_path17.basename)(full));
19617
+ const target = (0, import_node_path18.join)(realParent, (0, import_node_path18.basename)(full));
19603
19618
  let fd = null;
19604
19619
  try {
19605
- fd = (0, import_node_fs19.openSync)(target, import_node_fs19.constants.O_RDONLY | O_NOFOLLOW2);
19606
- const st = (0, import_node_fs19.fstatSync)(fd);
19620
+ fd = (0, import_node_fs20.openSync)(target, import_node_fs20.constants.O_RDONLY | O_NOFOLLOW2);
19621
+ const st = (0, import_node_fs20.fstatSync)(fd);
19607
19622
  if (!st.isFile()) return null;
19608
19623
  const cap2 = Math.min(maxBytes, st.size);
19609
19624
  if (cap2 <= 0) return "";
19610
19625
  const buf = Buffer.alloc(cap2);
19611
- const bytesRead = (0, import_node_fs19.readSync)(fd, buf, 0, cap2, 0);
19626
+ const bytesRead = (0, import_node_fs20.readSync)(fd, buf, 0, cap2, 0);
19612
19627
  return buf.subarray(0, bytesRead).toString("utf-8");
19613
19628
  } catch {
19614
19629
  return null;
19615
19630
  } finally {
19616
19631
  if (fd !== null) {
19617
19632
  try {
19618
- (0, import_node_fs19.closeSync)(fd);
19633
+ (0, import_node_fs20.closeSync)(fd);
19619
19634
  } catch {
19620
19635
  }
19621
19636
  }
@@ -19698,32 +19713,32 @@ var syncStateFile = () => projectPath(`${VERITY_DIR}/.memory-sync-state.json`);
19698
19713
  async function ensureMemoryDir() {
19699
19714
  await (0, import_promises9.mkdir)(memoryDir2(), { recursive: true });
19700
19715
  for (const domain of DOMAINS2) {
19701
- await (0, import_promises9.mkdir)((0, import_node_path18.join)(memoryDir2(), domain), { recursive: true });
19716
+ await (0, import_promises9.mkdir)((0, import_node_path19.join)(memoryDir2(), domain), { recursive: true });
19702
19717
  }
19703
- if (!(0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "SCHEMA.md"))) {
19704
- await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
19718
+ if (!(0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "SCHEMA.md"))) {
19719
+ await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "SCHEMA.md"), SCHEMA_TEMPLATE);
19705
19720
  }
19706
- if (!(0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "index.md"))) {
19707
- await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
19721
+ if (!(0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "index.md"))) {
19722
+ await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "index.md"), "# Project Memory Index\n\nNo nodes yet. Run an analysis to start building the knowledge graph.\n");
19708
19723
  }
19709
- if (!(0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "log.md"))) {
19710
- await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
19724
+ if (!(0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "log.md"))) {
19725
+ await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), "# Memory Log\n\n");
19711
19726
  }
19712
19727
  }
19713
19728
  async function buildManifest() {
19714
- if (!(0, import_node_fs20.existsSync)(memoryDir2())) {
19729
+ if (!(0, import_node_fs21.existsSync)(memoryDir2())) {
19715
19730
  return { schema_version: 1, nodes: [], index_hash: null, log_length: 0 };
19716
19731
  }
19717
19732
  const nodes = [];
19718
19733
  for (const domain of DOMAINS2) {
19719
- const domainDir = (0, import_node_path18.join)(memoryDir2(), domain);
19720
- if (!(0, import_node_fs20.existsSync)(domainDir)) continue;
19734
+ const domainDir = (0, import_node_path19.join)(memoryDir2(), domain);
19735
+ if (!(0, import_node_fs21.existsSync)(domainDir)) continue;
19721
19736
  try {
19722
19737
  const files = await (0, import_promises9.readdir)(domainDir);
19723
19738
  for (const file of files) {
19724
19739
  if (!file.endsWith(".md")) continue;
19725
19740
  const filePath = `${domain}/${file}`;
19726
- const fullPath = (0, import_node_path18.join)(memoryDir2(), filePath);
19741
+ const fullPath = (0, import_node_path19.join)(memoryDir2(), filePath);
19727
19742
  try {
19728
19743
  const content = await (0, import_promises9.readFile)(fullPath, "utf-8");
19729
19744
  const hash = (0, import_node_crypto4.createHash)("sha256").update(content).digest("hex").slice(0, 16);
@@ -19736,13 +19751,13 @@ async function buildManifest() {
19736
19751
  }
19737
19752
  let indexHash = null;
19738
19753
  try {
19739
- const indexContent = await (0, import_promises9.readFile)((0, import_node_path18.join)(memoryDir2(), "index.md"), "utf-8");
19754
+ const indexContent = await (0, import_promises9.readFile)((0, import_node_path19.join)(memoryDir2(), "index.md"), "utf-8");
19740
19755
  indexHash = `sha256:${(0, import_node_crypto4.createHash)("sha256").update(indexContent).digest("hex").slice(0, 16)}`;
19741
19756
  } catch {
19742
19757
  }
19743
19758
  let logLength = 0;
19744
19759
  try {
19745
- const logContent = await (0, import_promises9.readFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), "utf-8");
19760
+ const logContent = await (0, import_promises9.readFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), "utf-8");
19746
19761
  logLength = logContent.split("\n").length;
19747
19762
  } catch {
19748
19763
  }
@@ -19753,15 +19768,15 @@ function hashContent(content) {
19753
19768
  }
19754
19769
  async function readOnDiskNodes() {
19755
19770
  const out2 = /* @__PURE__ */ new Map();
19756
- if (!(0, import_node_fs20.existsSync)(memoryDir2())) return out2;
19771
+ if (!(0, import_node_fs21.existsSync)(memoryDir2())) return out2;
19757
19772
  for (const domain of DOMAINS2) {
19758
- const domainDir = (0, import_node_path18.join)(memoryDir2(), domain);
19759
- if (!(0, import_node_fs20.existsSync)(domainDir)) continue;
19773
+ const domainDir = (0, import_node_path19.join)(memoryDir2(), domain);
19774
+ if (!(0, import_node_fs21.existsSync)(domainDir)) continue;
19760
19775
  try {
19761
19776
  for (const file of await (0, import_promises9.readdir)(domainDir)) {
19762
19777
  if (!file.endsWith(".md")) continue;
19763
19778
  try {
19764
- out2.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path18.join)(domainDir, file), "utf-8")));
19779
+ out2.set(`${domain}/${file}`, hashContent(await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8")));
19765
19780
  } catch {
19766
19781
  }
19767
19782
  }
@@ -19798,7 +19813,7 @@ async function recordSyncedNodePaths() {
19798
19813
  }
19799
19814
  }
19800
19815
  async function writeFileAtomic(path, content) {
19801
- await (0, import_promises9.mkdir)((0, import_node_path18.dirname)(path), { recursive: true });
19816
+ await (0, import_promises9.mkdir)((0, import_node_path19.dirname)(path), { recursive: true });
19802
19817
  const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
19803
19818
  await (0, import_promises9.writeFile)(tmp, content);
19804
19819
  await (0, import_promises9.rename)(tmp, path);
@@ -19812,8 +19827,8 @@ async function computeEditedNodeUploads() {
19812
19827
  const uploads = [];
19813
19828
  for (const [path, prevHash] of prev) {
19814
19829
  if (prevHash == null) continue;
19815
- const full = (0, import_node_path18.join)(memoryDir2(), path);
19816
- if (!(0, import_node_fs20.existsSync)(full)) continue;
19830
+ const full = (0, import_node_path19.join)(memoryDir2(), path);
19831
+ if (!(0, import_node_fs21.existsSync)(full)) continue;
19817
19832
  let content;
19818
19833
  try {
19819
19834
  content = await (0, import_promises9.readFile)(full, "utf-8");
@@ -19857,8 +19872,8 @@ async function applyMemoryWrites(writes, opts = {}) {
19857
19872
  const logLines = [`- ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)} \u2014 Applied ${count} write(s) from server`];
19858
19873
  for (const n of notes) logLines.push(` - ${n}`);
19859
19874
  try {
19860
- const existing = (0, import_node_fs20.existsSync)((0, import_node_path18.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
19861
- await (0, import_promises9.writeFile)((0, import_node_path18.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
19875
+ const existing = (0, import_node_fs21.existsSync)((0, import_node_path19.join)(memoryDir2(), "log.md")) ? await (0, import_promises9.readFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), "utf-8") : "# Memory Log\n\n";
19876
+ await (0, import_promises9.writeFile)((0, import_node_path19.join)(memoryDir2(), "log.md"), existing + logLines.join("\n") + "\n");
19862
19877
  } catch {
19863
19878
  }
19864
19879
  if (opts.baseline === "written") await mergeSyncBaseline(synced);
@@ -19868,7 +19883,7 @@ async function applyMemoryWrites(writes, opts = {}) {
19868
19883
  async function mergeSyncBaseline(entries) {
19869
19884
  if (entries.size === 0) return;
19870
19885
  try {
19871
- if ((0, import_node_fs20.existsSync)(syncStateFile())) {
19886
+ if ((0, import_node_fs21.existsSync)(syncStateFile())) {
19872
19887
  try {
19873
19888
  JSON.parse(await (0, import_promises9.readFile)(syncStateFile(), "utf-8"));
19874
19889
  } catch {
@@ -19896,7 +19911,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
19896
19911
  notes.push(`${write.path}: dropped unmatched file_globs [${grounded.dropped.join(", ")}]`);
19897
19912
  }
19898
19913
  }
19899
- if ((0, import_node_fs20.existsSync)(fullPath)) {
19914
+ if ((0, import_node_fs21.existsSync)(fullPath)) {
19900
19915
  let existing = "";
19901
19916
  try {
19902
19917
  existing = await (0, import_promises9.readFile)(fullPath, "utf-8");
@@ -19912,7 +19927,7 @@ async function applyOneWrite(write, treePaths, lastServed) {
19912
19927
  notes.push(`${write.path}: updated from server (untouched here since the server delivered it)`);
19913
19928
  }
19914
19929
  }
19915
- await (0, import_promises9.mkdir)((0, import_node_path18.dirname)(fullPath), { recursive: true });
19930
+ await (0, import_promises9.mkdir)((0, import_node_path19.dirname)(fullPath), { recursive: true });
19916
19931
  await (0, import_promises9.writeFile)(fullPath, content);
19917
19932
  return { written: true, syncedHash: hashContent(content), notes };
19918
19933
  }
@@ -19953,8 +19968,8 @@ async function regenerateIndex() {
19953
19968
  ];
19954
19969
  let totalNodes = 0;
19955
19970
  for (const domain of DOMAINS2.filter((d) => d !== "_archive")) {
19956
- const domainDir = (0, import_node_path18.join)(memoryDir2(), domain);
19957
- if (!(0, import_node_fs20.existsSync)(domainDir)) continue;
19971
+ const domainDir = (0, import_node_path19.join)(memoryDir2(), domain);
19972
+ if (!(0, import_node_fs21.existsSync)(domainDir)) continue;
19958
19973
  try {
19959
19974
  const files = await (0, import_promises9.readdir)(domainDir);
19960
19975
  const mdFiles = files.filter((f) => f.endsWith(".md"));
@@ -19964,7 +19979,7 @@ async function regenerateIndex() {
19964
19979
  for (const file of mdFiles.sort()) {
19965
19980
  const slug = file.replace(/\.md$/, "");
19966
19981
  try {
19967
- const content = await (0, import_promises9.readFile)((0, import_node_path18.join)(domainDir, file), "utf-8");
19982
+ const content = await (0, import_promises9.readFile)((0, import_node_path19.join)(domainDir, file), "utf-8");
19968
19983
  const title = pickFrontmatter(content, "title") ?? slug;
19969
19984
  const kind = pickFrontmatter(content, "kind") ?? "-";
19970
19985
  const confidence = pickFrontmatter(content, "confidence");
@@ -19988,7 +20003,7 @@ async function regenerateIndex() {
19988
20003
  lines.push("No nodes yet. Run an analysis to start building the knowledge graph.");
19989
20004
  }
19990
20005
  const next = lines.join("\n") + "\n";
19991
- const indexPath = (0, import_node_path18.join)(memoryDir2(), "index.md");
20006
+ const indexPath = (0, import_node_path19.join)(memoryDir2(), "index.md");
19992
20007
  let existing = null;
19993
20008
  try {
19994
20009
  existing = await (0, import_promises9.readFile)(indexPath, "utf-8");
@@ -20385,9 +20400,9 @@ function hasLegacyMemoryBlock(text) {
20385
20400
  return findMarker(text, LEGACY_MD_START) !== -1;
20386
20401
  }
20387
20402
  async function ensureClaudeMdPointer(cwd = repoRoot()) {
20388
- const claudeMdPath = (0, import_node_path18.join)(cwd, "CLAUDE.md");
20403
+ const claudeMdPath = (0, import_node_path19.join)(cwd, "CLAUDE.md");
20389
20404
  let existing = "";
20390
- if ((0, import_node_fs20.existsSync)(claudeMdPath)) {
20405
+ if ((0, import_node_fs21.existsSync)(claudeMdPath)) {
20391
20406
  existing = await (0, import_promises9.readFile)(claudeMdPath, "utf-8");
20392
20407
  }
20393
20408
  let startTag = CLAUDE_MD_START;
@@ -20528,9 +20543,9 @@ Body content (\u22648KB). Use [[node-id]] wikilinks for cross-references.
20528
20543
  `;
20529
20544
 
20530
20545
  // src/lib/dossier-session.ts
20531
- var import_node_fs25 = require("node:fs");
20546
+ var import_node_fs26 = require("node:fs");
20532
20547
  var import_node_crypto8 = require("node:crypto");
20533
- var import_node_path21 = require("node:path");
20548
+ var import_node_path22 = require("node:path");
20534
20549
 
20535
20550
  // src/lib/pending-repeat.ts
20536
20551
  var STOP = /* @__PURE__ */ new Set([
@@ -20635,8 +20650,8 @@ function statementAnchorKey(file, patternId) {
20635
20650
 
20636
20651
  // src/lib/dossier/log.ts
20637
20652
  var import_node_crypto5 = require("node:crypto");
20638
- var import_node_fs21 = require("node:fs");
20639
- var import_node_path19 = require("node:path");
20653
+ var import_node_fs22 = require("node:fs");
20654
+ var import_node_path20 = require("node:path");
20640
20655
  var CRC_TABLE = (() => {
20641
20656
  const t = new Int32Array(256);
20642
20657
  for (let i2 = 0; i2 < 256; i2++) {
@@ -20655,13 +20670,13 @@ function crc32(s) {
20655
20670
  function openDossier(identity) {
20656
20671
  try {
20657
20672
  const dir = dossierDir(identity);
20658
- (0, import_node_fs21.mkdirSync)(dir, { recursive: true, mode: 448 });
20673
+ (0, import_node_fs22.mkdirSync)(dir, { recursive: true, mode: 448 });
20659
20674
  return {
20660
20675
  dir,
20661
20676
  identity,
20662
- eventsPath: (0, import_node_path19.join)(dir, "events.jsonl"),
20663
- foldPath: (0, import_node_path19.join)(dir, "fold.json"),
20664
- rotatedDir: (0, import_node_path19.join)(dir, "rotated")
20677
+ eventsPath: (0, import_node_path20.join)(dir, "events.jsonl"),
20678
+ foldPath: (0, import_node_path20.join)(dir, "fold.json"),
20679
+ rotatedDir: (0, import_node_path20.join)(dir, "rotated")
20665
20680
  };
20666
20681
  } catch {
20667
20682
  return null;
@@ -20723,7 +20738,7 @@ function appendEvent(d, ev) {
20723
20738
  at: ev.at ?? (/* @__PURE__ */ new Date()).toISOString(),
20724
20739
  ...ev
20725
20740
  });
20726
- (0, import_node_fs21.appendFileSync)(d.eventsPath, line2, { mode: 384 });
20741
+ (0, import_node_fs22.appendFileSync)(d.eventsPath, line2, { mode: 384 });
20727
20742
  return true;
20728
20743
  } catch {
20729
20744
  return false;
@@ -20731,14 +20746,14 @@ function appendEvent(d, ev) {
20731
20746
  }
20732
20747
  function rotateIfNeeded2(d) {
20733
20748
  try {
20734
- if (!(0, import_node_fs21.existsSync)(d.eventsPath)) return;
20735
- if ((0, import_node_fs21.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
20736
- (0, import_node_fs21.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
20737
- (0, import_node_fs21.renameSync)(d.eventsPath, (0, import_node_path19.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
20738
- const kept = (0, import_node_fs21.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
20749
+ if (!(0, import_node_fs22.existsSync)(d.eventsPath)) return;
20750
+ if ((0, import_node_fs22.statSync)(d.eventsPath).size < ROTATE_BYTES) return;
20751
+ (0, import_node_fs22.mkdirSync)(d.rotatedDir, { recursive: true, mode: 448 });
20752
+ (0, import_node_fs22.renameSync)(d.eventsPath, (0, import_node_path20.join)(d.rotatedDir, `events.${Date.now()}.jsonl`));
20753
+ const kept = (0, import_node_fs22.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
20739
20754
  for (const stale of kept.slice(0, Math.max(0, kept.length - ROTATE_KEEP))) {
20740
20755
  try {
20741
- (0, import_node_fs21.renameSync)((0, import_node_path19.join)(d.rotatedDir, stale), (0, import_node_path19.join)(d.rotatedDir, `${stale}.pruned`));
20756
+ (0, import_node_fs22.renameSync)((0, import_node_path20.join)(d.rotatedDir, stale), (0, import_node_path20.join)(d.rotatedDir, `${stale}.pruned`));
20742
20757
  } catch {
20743
20758
  }
20744
20759
  }
@@ -20748,8 +20763,8 @@ function rotateIfNeeded2(d) {
20748
20763
 
20749
20764
  // src/lib/dossier/fold-dossier.ts
20750
20765
  var import_node_crypto6 = require("node:crypto");
20751
- var import_node_fs22 = require("node:fs");
20752
- var import_node_path20 = require("node:path");
20766
+ var import_node_fs23 = require("node:fs");
20767
+ var import_node_path21 = require("node:path");
20753
20768
  var EMPTY_CAPABILITIES = () => ({
20754
20769
  human_reachable: { value: "unknown", tier: "unknown" },
20755
20770
  authorship_observability: { value: "unknown", tier: "unknown" },
@@ -20800,12 +20815,12 @@ function foldDossier(d, opts = {}) {
20800
20815
  }
20801
20816
  };
20802
20817
  try {
20803
- if ((0, import_node_fs22.existsSync)(d.rotatedDir)) {
20804
- const files = (0, import_node_fs22.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
20818
+ if ((0, import_node_fs23.existsSync)(d.rotatedDir)) {
20819
+ const files = (0, import_node_fs23.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).sort();
20805
20820
  state.meta.rotations = files.length;
20806
20821
  for (const f of files) {
20807
20822
  try {
20808
- ingest((0, import_node_fs22.readFileSync)((0, import_node_path20.join)(d.rotatedDir, f), "utf8"));
20823
+ ingest((0, import_node_fs23.readFileSync)((0, import_node_path21.join)(d.rotatedDir, f), "utf8"));
20809
20824
  } catch {
20810
20825
  state.meta.dropped_lines++;
20811
20826
  }
@@ -20814,9 +20829,9 @@ function foldDossier(d, opts = {}) {
20814
20829
  } catch {
20815
20830
  }
20816
20831
  try {
20817
- if ((0, import_node_fs22.existsSync)(d.eventsPath)) {
20818
- state.meta.upto_offset = (0, import_node_fs22.statSync)(d.eventsPath).size;
20819
- ingest((0, import_node_fs22.readFileSync)(d.eventsPath, "utf8"));
20832
+ if ((0, import_node_fs23.existsSync)(d.eventsPath)) {
20833
+ state.meta.upto_offset = (0, import_node_fs23.statSync)(d.eventsPath).size;
20834
+ ingest((0, import_node_fs23.readFileSync)(d.eventsPath, "utf8"));
20820
20835
  }
20821
20836
  } catch {
20822
20837
  }
@@ -21087,7 +21102,7 @@ function applyBounds(state, input) {
21087
21102
  }
21088
21103
 
21089
21104
  // src/lib/dossier/cache.ts
21090
- var import_node_fs23 = require("node:fs");
21105
+ var import_node_fs24 = require("node:fs");
21091
21106
  function compactState(s) {
21092
21107
  const ms = (iso) => Date.parse(iso) || 0;
21093
21108
  return {
@@ -21216,20 +21231,20 @@ function encodeState(s) {
21216
21231
  function writeFoldCache(d, state) {
21217
21232
  try {
21218
21233
  const tmp = `${d.foldPath}.${process.pid}.tmp`;
21219
- (0, import_node_fs23.writeFileSync)(tmp, encodeState(state), { mode: 384 });
21220
- (0, import_node_fs23.renameSync)(tmp, d.foldPath);
21234
+ (0, import_node_fs24.writeFileSync)(tmp, encodeState(state), { mode: 384 });
21235
+ (0, import_node_fs24.renameSync)(tmp, d.foldPath);
21221
21236
  } catch {
21222
21237
  }
21223
21238
  }
21224
21239
  function readFoldCache(d) {
21225
21240
  try {
21226
- if (!(0, import_node_fs23.existsSync)(d.foldPath)) return null;
21227
- const raw = JSON.parse((0, import_node_fs23.readFileSync)(d.foldPath, "utf8"));
21241
+ if (!(0, import_node_fs24.existsSync)(d.foldPath)) return null;
21242
+ const raw = JSON.parse((0, import_node_fs24.readFileSync)(d.foldPath, "utf8"));
21228
21243
  if (raw?.v !== 1) return null;
21229
21244
  const cached2 = expandState(raw);
21230
21245
  if (!cached2?.meta) return null;
21231
- const size = (0, import_node_fs23.existsSync)(d.eventsPath) ? (0, import_node_fs23.statSync)(d.eventsPath).size : 0;
21232
- const rotations = (0, import_node_fs23.existsSync)(d.rotatedDir) ? (0, import_node_fs23.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
21246
+ const size = (0, import_node_fs24.existsSync)(d.eventsPath) ? (0, import_node_fs24.statSync)(d.eventsPath).size : 0;
21247
+ const rotations = (0, import_node_fs24.existsSync)(d.rotatedDir) ? (0, import_node_fs24.readdirSync)(d.rotatedDir).filter((f) => f.endsWith(".jsonl")).length : 0;
21233
21248
  if (cached2.meta.upto_offset !== size || cached2.meta.rotations !== rotations) return null;
21234
21249
  return cached2;
21235
21250
  } catch {
@@ -21280,13 +21295,13 @@ function assessContinuity(i2) {
21280
21295
 
21281
21296
  // src/lib/dossier/reanchor.ts
21282
21297
  var import_node_crypto7 = require("node:crypto");
21283
- var import_node_fs24 = require("node:fs");
21298
+ var import_node_fs25 = require("node:fs");
21284
21299
  function lineSha(text) {
21285
21300
  return (0, import_node_crypto7.createHash)("sha256").update(text.trim()).digest("hex").slice(0, HASH_WIDTH);
21286
21301
  }
21287
21302
  function fileHash(path) {
21288
21303
  try {
21289
- return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs24.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21304
+ return (0, import_node_crypto7.createHash)("sha256").update((0, import_node_fs25.readFileSync)(path)).digest("hex").slice(0, HASH_WIDTH);
21290
21305
  } catch {
21291
21306
  return null;
21292
21307
  }
@@ -21658,20 +21673,20 @@ function foreignAuthoredPaths(identity, opts = {}) {
21658
21673
  let sessions = 0;
21659
21674
  try {
21660
21675
  const dir = treeDir(identity);
21661
- if (!(0, import_node_fs25.existsSync)(dir)) return { paths: [], sessions: 0 };
21662
- for (const entry of (0, import_node_fs25.readdirSync)(dir, { withFileTypes: true })) {
21676
+ if (!(0, import_node_fs26.existsSync)(dir)) return { paths: [], sessions: 0 };
21677
+ for (const entry of (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true })) {
21663
21678
  if (!entry.isDirectory()) continue;
21664
21679
  if (entry.name === identity.sessionKey) continue;
21665
- const log = (0, import_node_path21.join)(dir, entry.name, "events.jsonl");
21680
+ const log = (0, import_node_path22.join)(dir, entry.name, "events.jsonl");
21666
21681
  try {
21667
- if (!(0, import_node_fs25.existsSync)(log)) continue;
21668
- if (now - (0, import_node_fs25.statSync)(log).mtimeMs > windowMs) continue;
21682
+ if (!(0, import_node_fs26.existsSync)(log)) continue;
21683
+ if (now - (0, import_node_fs26.statSync)(log).mtimeMs > windowMs) continue;
21669
21684
  const sib = {
21670
- dir: (0, import_node_path21.join)(dir, entry.name),
21685
+ dir: (0, import_node_path22.join)(dir, entry.name),
21671
21686
  identity,
21672
21687
  eventsPath: log,
21673
- foldPath: (0, import_node_path21.join)(dir, entry.name, "fold.json"),
21674
- rotatedDir: (0, import_node_path21.join)(dir, entry.name, "rotated")
21688
+ foldPath: (0, import_node_path22.join)(dir, entry.name, "fold.json"),
21689
+ rotatedDir: (0, import_node_path22.join)(dir, entry.name, "rotated")
21675
21690
  };
21676
21691
  const state = readFoldCache(sib) ?? foldDossier(sib);
21677
21692
  sessions++;
@@ -21699,25 +21714,25 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
21699
21714
  let removed = 0;
21700
21715
  try {
21701
21716
  const mine = dossierDir(identity);
21702
- const userDir = (0, import_node_path21.dirname)((0, import_node_path21.dirname)(mine));
21703
- if (!(0, import_node_fs25.existsSync)(userDir)) return 0;
21717
+ const userDir = (0, import_node_path22.dirname)((0, import_node_path22.dirname)(mine));
21718
+ if (!(0, import_node_fs26.existsSync)(userDir)) return 0;
21704
21719
  const cutoff = Date.now() - maxAgeMs;
21705
- for (const tree of (0, import_node_fs25.readdirSync)(userDir, { withFileTypes: true })) {
21720
+ for (const tree of (0, import_node_fs26.readdirSync)(userDir, { withFileTypes: true })) {
21706
21721
  if (!tree.isDirectory()) continue;
21707
- const treePath = (0, import_node_path21.join)(userDir, tree.name);
21722
+ const treePath = (0, import_node_path22.join)(userDir, tree.name);
21708
21723
  let live = 0;
21709
- for (const entry of (0, import_node_fs25.readdirSync)(treePath, { withFileTypes: true })) {
21724
+ for (const entry of (0, import_node_fs26.readdirSync)(treePath, { withFileTypes: true })) {
21710
21725
  if (!entry.isDirectory()) continue;
21711
- const dir = (0, import_node_path21.join)(treePath, entry.name);
21726
+ const dir = (0, import_node_path22.join)(treePath, entry.name);
21712
21727
  if (dir === mine) {
21713
21728
  live++;
21714
21729
  continue;
21715
21730
  }
21716
21731
  try {
21717
- const log = (0, import_node_path21.join)(dir, "events.jsonl");
21718
- const at = (0, import_node_fs25.existsSync)(log) ? (0, import_node_fs25.statSync)(log).mtimeMs : (0, import_node_fs25.statSync)(dir).mtimeMs;
21732
+ const log = (0, import_node_path22.join)(dir, "events.jsonl");
21733
+ const at = (0, import_node_fs26.existsSync)(log) ? (0, import_node_fs26.statSync)(log).mtimeMs : (0, import_node_fs26.statSync)(dir).mtimeMs;
21719
21734
  if (at < cutoff) {
21720
- (0, import_node_fs25.rmSync)(dir, { recursive: true, force: true });
21735
+ (0, import_node_fs26.rmSync)(dir, { recursive: true, force: true });
21721
21736
  removed++;
21722
21737
  } else {
21723
21738
  live++;
@@ -21727,7 +21742,7 @@ function pruneOldDossiers(identity, maxAgeMs = 7 * 24 * 60 * 60 * 1e3) {
21727
21742
  }
21728
21743
  if (live === 0) {
21729
21744
  try {
21730
- (0, import_node_fs25.rmSync)(treePath, { recursive: false, force: false });
21745
+ (0, import_node_fs26.rmSync)(treePath, { recursive: false, force: false });
21731
21746
  } catch {
21732
21747
  }
21733
21748
  }
@@ -21744,8 +21759,8 @@ function sessionDossier(token, sessionId) {
21744
21759
  }
21745
21760
  function hasActiveGoal(d) {
21746
21761
  try {
21747
- if (!(0, import_node_fs25.existsSync)(d.eventsPath)) return false;
21748
- return (0, import_node_fs25.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
21762
+ if (!(0, import_node_fs26.existsSync)(d.eventsPath)) return false;
21763
+ return (0, import_node_fs26.readFileSync)(d.eventsPath, "utf8").includes('"k":"goal"');
21749
21764
  } catch {
21750
21765
  return false;
21751
21766
  }
@@ -21769,7 +21784,7 @@ function recordTurn(d, t) {
21769
21784
  for (const a of t.authored) {
21770
21785
  const origin = a.owner === "subagent" ? "subagent" : "edit_tool";
21771
21786
  const prior = t.known?.authored?.get(a.p);
21772
- const hash = fileHash((0, import_node_path21.join)(root, a.p));
21787
+ const hash = fileHash((0, import_node_path22.join)(root, a.p));
21773
21788
  const hunks = Math.max(0, a.h - (prior?.hunks ?? 0));
21774
21789
  const adds = Math.max(0, a.a - (prior?.adds ?? 0));
21775
21790
  const dels = Math.max(0, a.d - (prior?.dels ?? 0));
@@ -21802,7 +21817,7 @@ function recordTurn(d, t) {
21802
21817
  }
21803
21818
  const seenDivergence = t.known?.divergence ?? /* @__PURE__ */ new Set();
21804
21819
  for (const u of t.unobserved) {
21805
- const hash = fileHash((0, import_node_path21.join)(root, u.p));
21820
+ const hash = fileHash((0, import_node_path22.join)(root, u.p));
21806
21821
  if (seenDivergence.has(divergenceKey(u.p, hash))) continue;
21807
21822
  appendEvent(d, { k: "divergence", kind: "external_mutation", path: u.p, hash });
21808
21823
  }
@@ -21837,8 +21852,8 @@ function recordVerdict(d, v) {
21837
21852
  if (!sent.has(f.file)) continue;
21838
21853
  if (!lines.has(f.file)) {
21839
21854
  try {
21840
- const abs = (0, import_node_path21.join)(root, f.file);
21841
- lines.set(f.file, (0, import_node_fs25.existsSync)(abs) ? (0, import_node_fs25.readFileSync)(abs, "utf8").split("\n") : null);
21855
+ const abs = (0, import_node_path22.join)(root, f.file);
21856
+ lines.set(f.file, (0, import_node_fs26.existsSync)(abs) ? (0, import_node_fs26.readFileSync)(abs, "utf8").split("\n") : null);
21842
21857
  } catch {
21843
21858
  lines.set(f.file, null);
21844
21859
  }
@@ -21938,8 +21953,8 @@ function recallMemory(d, identity, opts) {
21938
21953
  budgetBytes: opts.budgetBytes,
21939
21954
  readFileLines: (file) => {
21940
21955
  try {
21941
- const abs = (0, import_node_path21.join)(root, file);
21942
- return (0, import_node_fs25.existsSync)(abs) ? (0, import_node_fs25.readFileSync)(abs, "utf8").split("\n") : null;
21956
+ const abs = (0, import_node_path22.join)(root, file);
21957
+ return (0, import_node_fs26.existsSync)(abs) ? (0, import_node_fs26.readFileSync)(abs, "utf8").split("\n") : null;
21943
21958
  } catch {
21944
21959
  return null;
21945
21960
  }
@@ -22107,21 +22122,21 @@ async function fireClassify(prompt, sessionId, globals) {
22107
22122
  }
22108
22123
 
22109
22124
  // src/commands/lifecycle.ts
22110
- var import_node_fs28 = require("node:fs");
22111
- var import_node_path25 = require("node:path");
22125
+ var import_node_fs29 = require("node:fs");
22126
+ var import_node_path26 = require("node:path");
22112
22127
 
22113
22128
  // src/lib/baseline.ts
22114
- var import_node_fs27 = require("node:fs");
22115
- var import_node_path24 = require("node:path");
22129
+ var import_node_fs28 = require("node:fs");
22130
+ var import_node_path25 = require("node:path");
22116
22131
  var import_node_crypto10 = require("node:crypto");
22117
22132
 
22118
22133
  // src/lib/snapshot.ts
22119
- var import_node_fs26 = require("node:fs");
22120
- var import_node_path23 = require("node:path");
22134
+ var import_node_fs27 = require("node:fs");
22135
+ var import_node_path24 = require("node:path");
22121
22136
  var import_node_child_process8 = require("node:child_process");
22122
22137
 
22123
22138
  // src/lib/files.ts
22124
- var import_node_path22 = require("node:path");
22139
+ var import_node_path23 = require("node:path");
22125
22140
  var LANG_MAP = {
22126
22141
  // Analyzable (static analysis + Gemini)
22127
22142
  ts: "typescript",
@@ -22189,7 +22204,7 @@ var LANG_MAP = {
22189
22204
  mk: "make"
22190
22205
  };
22191
22206
  function detectLanguage(filepath) {
22192
- const ext = (0, import_node_path22.extname)(filepath).slice(1);
22207
+ const ext = (0, import_node_path23.extname)(filepath).slice(1);
22193
22208
  return LANG_MAP[ext] ?? ext;
22194
22209
  }
22195
22210
  function sortByMtime(files) {
@@ -22280,16 +22295,16 @@ function collectCodeDelta(files, opts) {
22280
22295
 
22281
22296
  // src/lib/snapshot.ts
22282
22297
  function generateSnapshotDiffs(files) {
22283
- if (!(0, import_node_fs26.existsSync)(SNAPSHOT_DIR)) {
22298
+ if (!(0, import_node_fs27.existsSync)(SNAPSHOT_DIR)) {
22284
22299
  return { diffs: [], has_snapshots: false };
22285
22300
  }
22286
22301
  const diffs = [];
22287
22302
  for (const file of files) {
22288
22303
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
22289
- const snapshotPath = (0, import_node_path23.join)(SNAPSHOT_DIR, file.path);
22304
+ const snapshotPath = (0, import_node_path24.join)(SNAPSHOT_DIR, file.path);
22290
22305
  const language = file.language ?? detectLanguage(file.path);
22291
- if ((0, import_node_fs26.existsSync)(snapshotPath)) {
22292
- const oldContent = (0, import_node_fs26.readFileSync)(snapshotPath, "utf-8");
22306
+ if ((0, import_node_fs27.existsSync)(snapshotPath)) {
22307
+ const oldContent = (0, import_node_fs27.readFileSync)(snapshotPath, "utf-8");
22293
22308
  if (oldContent === file.content) continue;
22294
22309
  const diff = computeDiff(oldContent, file.content, file.path);
22295
22310
  if (diff) {
@@ -22314,20 +22329,20 @@ function saveSnapshots(files) {
22314
22329
  const snapshotPaths = /* @__PURE__ */ new Set();
22315
22330
  for (const file of files) {
22316
22331
  if (!resolveInside(SNAPSHOT_DIR, file.path)) continue;
22317
- const snapshotPath = (0, import_node_path23.join)(SNAPSHOT_DIR, file.path);
22332
+ const snapshotPath = (0, import_node_path24.join)(SNAPSHOT_DIR, file.path);
22318
22333
  snapshotPaths.add(snapshotPath);
22319
- (0, import_node_fs26.mkdirSync)((0, import_node_path23.dirname)(snapshotPath), { recursive: true });
22320
- (0, import_node_fs26.writeFileSync)(snapshotPath, file.content);
22334
+ (0, import_node_fs27.mkdirSync)((0, import_node_path24.dirname)(snapshotPath), { recursive: true });
22335
+ (0, import_node_fs27.writeFileSync)(snapshotPath, file.content);
22321
22336
  }
22322
22337
  cleanStaleSnapshots(SNAPSHOT_DIR, snapshotPaths);
22323
22338
  }
22324
22339
  function computeDiff(oldContent, newContent, filePath) {
22325
- const tmpOld = (0, import_node_path23.join)(SNAPSHOT_DIR, ".diff-old.tmp");
22326
- const tmpNew = (0, import_node_path23.join)(SNAPSHOT_DIR, ".diff-new.tmp");
22340
+ const tmpOld = (0, import_node_path24.join)(SNAPSHOT_DIR, ".diff-old.tmp");
22341
+ const tmpNew = (0, import_node_path24.join)(SNAPSHOT_DIR, ".diff-new.tmp");
22327
22342
  try {
22328
- (0, import_node_fs26.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
22329
- (0, import_node_fs26.writeFileSync)(tmpOld, oldContent);
22330
- (0, import_node_fs26.writeFileSync)(tmpNew, newContent);
22343
+ (0, import_node_fs27.mkdirSync)(SNAPSHOT_DIR, { recursive: true });
22344
+ (0, import_node_fs27.writeFileSync)(tmpOld, oldContent);
22345
+ (0, import_node_fs27.writeFileSync)(tmpNew, newContent);
22331
22346
  const result = (0, import_node_child_process8.execSync)(
22332
22347
  `git diff --no-index --unified=10 -- "${tmpOld}" "${tmpNew}"`,
22333
22348
  { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
@@ -22341,32 +22356,32 @@ function computeDiff(oldContent, newContent, filePath) {
22341
22356
  return null;
22342
22357
  } finally {
22343
22358
  try {
22344
- (0, import_node_fs26.unlinkSync)(tmpOld);
22359
+ (0, import_node_fs27.unlinkSync)(tmpOld);
22345
22360
  } catch {
22346
22361
  }
22347
22362
  try {
22348
- (0, import_node_fs26.unlinkSync)(tmpNew);
22363
+ (0, import_node_fs27.unlinkSync)(tmpNew);
22349
22364
  } catch {
22350
22365
  }
22351
22366
  }
22352
22367
  }
22353
22368
  function cleanStaleSnapshots(dir, keepSet) {
22354
- if (!(0, import_node_fs26.existsSync)(dir)) return;
22369
+ if (!(0, import_node_fs27.existsSync)(dir)) return;
22355
22370
  try {
22356
- const entries = (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true });
22371
+ const entries = (0, import_node_fs27.readdirSync)(dir, { withFileTypes: true });
22357
22372
  for (const entry of entries) {
22358
22373
  if (dir === SNAPSHOT_DIR && (entry.name === ".diff-old.tmp" || entry.name === ".diff-new.tmp")) continue;
22359
- const fullPath = (0, import_node_path23.join)(dir, entry.name);
22374
+ const fullPath = (0, import_node_path24.join)(dir, entry.name);
22360
22375
  if (entry.isDirectory()) {
22361
22376
  cleanStaleSnapshots(fullPath, keepSet);
22362
22377
  try {
22363
- const remaining = (0, import_node_fs26.readdirSync)(fullPath);
22364
- if (remaining.length === 0) (0, import_node_fs26.rmdirSync)(fullPath);
22378
+ const remaining = (0, import_node_fs27.readdirSync)(fullPath);
22379
+ if (remaining.length === 0) (0, import_node_fs27.rmdirSync)(fullPath);
22365
22380
  } catch {
22366
22381
  }
22367
22382
  } else if (!keepSet.has(fullPath)) {
22368
22383
  try {
22369
- (0, import_node_fs26.unlinkSync)(fullPath);
22384
+ (0, import_node_fs27.unlinkSync)(fullPath);
22370
22385
  } catch {
22371
22386
  }
22372
22387
  }
@@ -22385,20 +22400,20 @@ function sessionKey(sessionId) {
22385
22400
  return (0, import_node_crypto10.createHash)("sha256").update(sessionId).digest("hex").slice(0, 16);
22386
22401
  }
22387
22402
  function sessionDir(key) {
22388
- return (0, import_node_path24.join)(projectPath(BASELINE_DIR), key);
22403
+ return (0, import_node_path25.join)(projectPath(BASELINE_DIR), key);
22389
22404
  }
22390
22405
  function manifestPath(dir) {
22391
- return (0, import_node_path24.join)(dir, "manifest.json");
22406
+ return (0, import_node_path25.join)(dir, "manifest.json");
22392
22407
  }
22393
22408
  function mirrorPath(dir, repoRelPath) {
22394
- return (0, import_node_path24.join)(dir, "files", repoRelPath);
22409
+ return (0, import_node_path25.join)(dir, "files", repoRelPath);
22395
22410
  }
22396
22411
  var CARRY_FILE = `${BASELINE_DIR}/.carry`;
22397
22412
  var CARRY_WINDOW_MS = 12e4;
22398
22413
  function writeCarry(sessionId, headSha) {
22399
22414
  try {
22400
- (0, import_node_fs27.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
22401
- (0, import_node_fs27.writeFileSync)(
22415
+ (0, import_node_fs28.mkdirSync)(projectPath(BASELINE_DIR), { recursive: true });
22416
+ (0, import_node_fs28.writeFileSync)(
22402
22417
  projectPath(CARRY_FILE),
22403
22418
  JSON.stringify({ from_key: sessionKey(sessionId), head_sha: headSha, ts: Date.now() })
22404
22419
  );
@@ -22408,10 +22423,10 @@ function writeCarry(sessionId, headSha) {
22408
22423
  function claimCarry(newKey) {
22409
22424
  const carryPath = projectPath(CARRY_FILE);
22410
22425
  try {
22411
- if (!(0, import_node_fs27.existsSync)(carryPath)) return null;
22412
- const carry = JSON.parse((0, import_node_fs27.readFileSync)(carryPath, "utf-8"));
22426
+ if (!(0, import_node_fs28.existsSync)(carryPath)) return null;
22427
+ const carry = JSON.parse((0, import_node_fs28.readFileSync)(carryPath, "utf-8"));
22413
22428
  try {
22414
- (0, import_node_fs27.rmSync)(carryPath, { force: true });
22429
+ (0, import_node_fs28.rmSync)(carryPath, { force: true });
22415
22430
  } catch {
22416
22431
  }
22417
22432
  if (!carry?.from_key || typeof carry.ts !== "number") return null;
@@ -22422,11 +22437,11 @@ function claimCarry(newKey) {
22422
22437
  if (!prior) return null;
22423
22438
  const toDir = sessionDir(newKey);
22424
22439
  try {
22425
- (0, import_node_fs27.rmSync)(toDir, { recursive: true, force: true });
22440
+ (0, import_node_fs28.rmSync)(toDir, { recursive: true, force: true });
22426
22441
  } catch {
22427
22442
  }
22428
- (0, import_node_fs27.renameSync)(fromDir, toDir);
22429
- (0, import_node_fs27.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
22443
+ (0, import_node_fs28.renameSync)(fromDir, toDir);
22444
+ (0, import_node_fs28.writeFileSync)(manifestPath(toDir), JSON.stringify({ ...prior, session_id: newKey }) + "\n");
22430
22445
  return readManifest(toDir);
22431
22446
  } catch {
22432
22447
  return null;
@@ -22450,21 +22465,21 @@ function captureBaseline(opts = {}) {
22450
22465
  const head_sha = getCurrentCommit();
22451
22466
  const dirty = getDirtyFiles();
22452
22467
  try {
22453
- (0, import_node_fs27.rmSync)(dir, { recursive: true, force: true });
22468
+ (0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
22454
22469
  } catch {
22455
22470
  }
22456
- const filesDir = (0, import_node_path24.join)(dir, "files");
22471
+ const filesDir = (0, import_node_path25.join)(dir, "files");
22457
22472
  const mirrored = [];
22458
22473
  try {
22459
- (0, import_node_fs27.mkdirSync)(filesDir, { recursive: true });
22474
+ (0, import_node_fs28.mkdirSync)(filesDir, { recursive: true });
22460
22475
  for (const p of dirty) {
22461
22476
  if (p.includes("..")) continue;
22462
22477
  const content = safeReadForMirror(projectPath(p));
22463
22478
  if (content === null) continue;
22464
22479
  const dest = mirrorPath(dir, p);
22465
22480
  try {
22466
- (0, import_node_fs27.mkdirSync)((0, import_node_path24.dirname)(dest), { recursive: true });
22467
- (0, import_node_fs27.writeFileSync)(dest, content);
22481
+ (0, import_node_fs28.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
22482
+ (0, import_node_fs28.writeFileSync)(dest, content);
22468
22483
  mirrored.push(p);
22469
22484
  } catch {
22470
22485
  }
@@ -22479,8 +22494,8 @@ function captureBaseline(opts = {}) {
22479
22494
  version: BASELINE_VERSION
22480
22495
  };
22481
22496
  try {
22482
- (0, import_node_fs27.mkdirSync)(dir, { recursive: true });
22483
- (0, import_node_fs27.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
22497
+ (0, import_node_fs28.mkdirSync)(dir, { recursive: true });
22498
+ (0, import_node_fs28.writeFileSync)(manifestPath(dir), JSON.stringify(baseline));
22484
22499
  } catch {
22485
22500
  }
22486
22501
  pruneOldBaselines();
@@ -22491,9 +22506,9 @@ function readBaseline(sessionId) {
22491
22506
  }
22492
22507
  function readManifest(dir) {
22493
22508
  const mp = manifestPath(dir);
22494
- if (!(0, import_node_fs27.existsSync)(mp)) return null;
22509
+ if (!(0, import_node_fs28.existsSync)(mp)) return null;
22495
22510
  try {
22496
- const parsed = JSON.parse((0, import_node_fs27.readFileSync)(mp, "utf-8"));
22511
+ const parsed = JSON.parse((0, import_node_fs28.readFileSync)(mp, "utf-8"));
22497
22512
  if (typeof parsed.head_sha !== "string" || typeof parsed.captured_at !== "number" || !Array.isArray(parsed.dirty_paths) || parsed.version !== BASELINE_VERSION) {
22498
22513
  return null;
22499
22514
  }
@@ -22524,9 +22539,9 @@ function preImage(repoRelPath, baseline) {
22524
22539
  function resolvePreImage(repoRelPath, baseline) {
22525
22540
  if (baseline.dirty_paths.includes(repoRelPath)) {
22526
22541
  const mp = mirrorPath(sessionDir(sessionKey(baseline.session_id)), repoRelPath);
22527
- if ((0, import_node_fs27.existsSync)(mp)) {
22542
+ if ((0, import_node_fs28.existsSync)(mp)) {
22528
22543
  try {
22529
- return { content: (0, import_node_fs27.readFileSync)(mp, "utf-8"), existed: true };
22544
+ return { content: (0, import_node_fs28.readFileSync)(mp, "utf-8"), existed: true };
22530
22545
  } catch {
22531
22546
  }
22532
22547
  }
@@ -22571,8 +22586,8 @@ function absorbIntoBaseline(paths, sessionId) {
22571
22586
  const content = safeReadForMirror(projectPath(p));
22572
22587
  if (content === null) continue;
22573
22588
  const dest = mirrorPath(dir, p);
22574
- (0, import_node_fs27.mkdirSync)((0, import_node_path24.dirname)(dest), { recursive: true });
22575
- (0, import_node_fs27.writeFileSync)(dest, content);
22589
+ (0, import_node_fs28.mkdirSync)((0, import_node_path25.dirname)(dest), { recursive: true });
22590
+ (0, import_node_fs28.writeFileSync)(dest, content);
22576
22591
  dirty.add(p);
22577
22592
  adopted++;
22578
22593
  } catch {
@@ -22581,7 +22596,7 @@ function absorbIntoBaseline(paths, sessionId) {
22581
22596
  if (adopted === 0) return 0;
22582
22597
  try {
22583
22598
  const updated = { ...baseline, dirty_paths: [...dirty] };
22584
- (0, import_node_fs27.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
22599
+ (0, import_node_fs28.writeFileSync)(manifestPath(dir), JSON.stringify(updated));
22585
22600
  preImageCache.delete(baseline);
22586
22601
  } catch {
22587
22602
  return 0;
@@ -22592,7 +22607,7 @@ function changedSinceBaseline(repoRelPath, baseline) {
22592
22607
  const pre = preImage(repoRelPath, baseline);
22593
22608
  let current;
22594
22609
  try {
22595
- current = (0, import_node_fs27.readFileSync)(projectPath(repoRelPath), "utf-8");
22610
+ current = (0, import_node_fs28.readFileSync)(projectPath(repoRelPath), "utf-8");
22596
22611
  } catch {
22597
22612
  return pre.existed;
22598
22613
  }
@@ -22601,8 +22616,8 @@ function changedSinceBaseline(repoRelPath, baseline) {
22601
22616
  }
22602
22617
  function safeReadForMirror(absPath) {
22603
22618
  try {
22604
- if ((0, import_node_fs27.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
22605
- const buf = (0, import_node_fs27.readFileSync)(absPath);
22619
+ if ((0, import_node_fs28.statSync)(absPath).size > MIRROR_MAX_BYTES) return null;
22620
+ const buf = (0, import_node_fs28.readFileSync)(absPath);
22606
22621
  if (buf.includes(0)) return null;
22607
22622
  return buf.toString("utf-8");
22608
22623
  } catch {
@@ -22613,18 +22628,18 @@ function pruneOldBaselines() {
22613
22628
  const root = projectPath(BASELINE_DIR);
22614
22629
  let entries;
22615
22630
  try {
22616
- entries = (0, import_node_fs27.readdirSync)(root);
22631
+ entries = (0, import_node_fs28.readdirSync)(root);
22617
22632
  } catch {
22618
22633
  return;
22619
22634
  }
22620
22635
  const now = Date.now();
22621
22636
  for (const name2 of entries) {
22622
- const dir = (0, import_node_path24.join)(root, name2);
22637
+ const dir = (0, import_node_path25.join)(root, name2);
22623
22638
  const manifest = readManifest(dir);
22624
22639
  if (!manifest) {
22625
22640
  try {
22626
- if (now - (0, import_node_fs27.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
22627
- (0, import_node_fs27.rmSync)(dir, { recursive: true, force: true });
22641
+ if (now - (0, import_node_fs28.statSync)(dir).mtimeMs > BASELINE_TTL_MS) {
22642
+ (0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
22628
22643
  }
22629
22644
  } catch {
22630
22645
  }
@@ -22632,7 +22647,7 @@ function pruneOldBaselines() {
22632
22647
  }
22633
22648
  if (now - manifest.captured_at <= BASELINE_TTL_MS) continue;
22634
22649
  try {
22635
- (0, import_node_fs27.rmSync)(dir, { recursive: true, force: true });
22650
+ (0, import_node_fs28.rmSync)(dir, { recursive: true, force: true });
22636
22651
  } catch {
22637
22652
  }
22638
22653
  }
@@ -22807,8 +22822,8 @@ function buildCompactionContext(session) {
22807
22822
  commitsSince: commitsSincePaths(watermark, (state.authored ?? []).map((a) => a.path)),
22808
22823
  readFileLines: (file) => {
22809
22824
  try {
22810
- const abs = (0, import_node_path25.join)(root, file);
22811
- return (0, import_node_fs28.existsSync)(abs) ? (0, import_node_fs28.readFileSync)(abs, "utf8").split("\n") : null;
22825
+ const abs = (0, import_node_path26.join)(root, file);
22826
+ return (0, import_node_fs29.existsSync)(abs) ? (0, import_node_fs29.readFileSync)(abs, "utf8").split("\n") : null;
22812
22827
  } catch {
22813
22828
  return null;
22814
22829
  }
@@ -22865,24 +22880,24 @@ async function readHookStdin() {
22865
22880
 
22866
22881
  // src/commands/standard.ts
22867
22882
  var import_promises13 = require("node:fs/promises");
22868
- var import_node_fs35 = require("node:fs");
22883
+ var import_node_fs36 = require("node:fs");
22869
22884
  var import_yaml3 = __toESM2(require_dist());
22870
22885
 
22871
22886
  // src/lib/synthesize.ts
22872
22887
  var import_node_child_process10 = require("node:child_process");
22873
- var import_node_fs31 = require("node:fs");
22888
+ var import_node_fs32 = require("node:fs");
22874
22889
  var import_promises10 = require("node:fs/promises");
22875
- var import_node_path28 = require("node:path");
22890
+ var import_node_path29 = require("node:path");
22876
22891
  var import_yaml = __toESM2(require_dist());
22877
22892
 
22878
22893
  // src/lib/data-dir.ts
22879
- var import_node_fs29 = require("node:fs");
22880
- var import_node_path26 = require("node:path");
22894
+ var import_node_fs30 = require("node:fs");
22895
+ var import_node_path27 = require("node:path");
22881
22896
  function resolveDataDir() {
22882
22897
  const candidates2 = [
22883
- (0, import_node_path26.join)(__dirname, "..", "data"),
22898
+ (0, import_node_path27.join)(__dirname, "..", "data"),
22884
22899
  // installed: node_modules/@codacy/verity-cli/data
22885
- (0, import_node_path26.join)(__dirname, "..", "..", "data"),
22900
+ (0, import_node_path27.join)(__dirname, "..", "..", "data"),
22886
22901
  // edge case: nested resolution
22887
22902
  // THE COMMITTED SOURCE, for a source checkout that has not been built.
22888
22903
  // cli/data/skills/ is a BUILD ARTIFACT (scripts/build.js copies client/skills
@@ -22891,14 +22906,14 @@ function resolveDataDir() {
22891
22906
  // without this the synthesizer throws "Could not find Verity skill data"
22892
22907
  // for every test and every `verity` run from source. Resolved from this
22893
22908
  // module's own location, never the cwd: see the warning below.
22894
- (0, import_node_path26.join)(__dirname, "..", "..", "client"),
22909
+ (0, import_node_path27.join)(__dirname, "..", "..", "client"),
22895
22910
  // bundled: cli/bin/ → ../../client
22896
- (0, import_node_path26.join)(__dirname, "..", "..", "..", "client"),
22911
+ (0, import_node_path27.join)(__dirname, "..", "..", "..", "client"),
22897
22912
  // tsx: cli/src/lib/ → ../../../client
22898
22913
  ...process.env.VERITY_DEV_DATA_DIR ? [process.env.VERITY_DEV_DATA_DIR] : []
22899
22914
  ];
22900
22915
  for (const candidate of candidates2) {
22901
- if ((0, import_node_fs29.existsSync)((0, import_node_path26.join)(candidate, "skills"))) {
22916
+ if ((0, import_node_fs30.existsSync)((0, import_node_path27.join)(candidate, "skills"))) {
22902
22917
  return candidate;
22903
22918
  }
22904
22919
  }
@@ -22907,13 +22922,13 @@ function resolveDataDir() {
22907
22922
  );
22908
22923
  }
22909
22924
  function setupDataPath(file) {
22910
- return (0, import_node_path26.join)(resolveDataDir(), "skills", "verity-setup", file);
22925
+ return (0, import_node_path27.join)(resolveDataDir(), "skills", "verity-setup", file);
22911
22926
  }
22912
22927
 
22913
22928
  // src/lib/detect.ts
22914
22929
  var import_node_child_process9 = require("node:child_process");
22915
- var import_node_fs30 = require("node:fs");
22916
- var import_node_path27 = require("node:path");
22930
+ var import_node_fs31 = require("node:fs");
22931
+ var import_node_path28 = require("node:path");
22917
22932
  var TOOLED_LANGUAGES = /* @__PURE__ */ new Set([
22918
22933
  "typescript",
22919
22934
  "javascript",
@@ -22970,25 +22985,25 @@ function walk(root) {
22970
22985
  if (depth > WALK_MAX_DEPTH || found.length >= WALK_MAX_FILES) return;
22971
22986
  let entries;
22972
22987
  try {
22973
- entries = (0, import_node_fs30.readdirSync)(dir, { withFileTypes: true });
22988
+ entries = (0, import_node_fs31.readdirSync)(dir, { withFileTypes: true });
22974
22989
  } catch {
22975
22990
  return;
22976
22991
  }
22977
22992
  for (const entry of entries) {
22978
22993
  if (found.length >= WALK_MAX_FILES) return;
22979
22994
  if (IGNORED_SEGMENTS.includes(entry.name)) continue;
22980
- const full = (0, import_node_path27.join)(dir, entry.name);
22995
+ const full = (0, import_node_path28.join)(dir, entry.name);
22981
22996
  if (entry.isDirectory()) visit(full, depth + 1);
22982
- else if (entry.isFile()) found.push((0, import_node_path27.relative)(root, full));
22997
+ else if (entry.isFile()) found.push((0, import_node_path28.relative)(root, full));
22983
22998
  }
22984
22999
  };
22985
23000
  visit(root, 0);
22986
23001
  return found;
22987
23002
  }
22988
23003
  function languageOf(path) {
22989
- const name2 = (0, import_node_path27.basename)(path);
23004
+ const name2 = (0, import_node_path28.basename)(path);
22990
23005
  if (/^Dockerfile(\..+)?$/i.test(name2)) return "dockerfile";
22991
- if (!(0, import_node_path27.extname)(name2)) return null;
23006
+ if (!(0, import_node_path28.extname)(name2)) return null;
22992
23007
  const lang = detectLanguage(path);
22993
23008
  return lang || null;
22994
23009
  }
@@ -23045,7 +23060,7 @@ var TOOL_CONFIG_MARKERS = [
23045
23060
  ];
23046
23061
  function readJson2(path) {
23047
23062
  try {
23048
- return JSON.parse((0, import_node_fs30.readFileSync)(path, "utf-8"));
23063
+ return JSON.parse((0, import_node_fs31.readFileSync)(path, "utf-8"));
23049
23064
  } catch {
23050
23065
  return null;
23051
23066
  }
@@ -23070,17 +23085,17 @@ function declaredDependencies(root, files) {
23070
23085
  if (deps && typeof deps === "object") names2.push(...Object.keys(deps));
23071
23086
  }
23072
23087
  };
23073
- readPackageJson((0, import_node_path27.join)(root, "package.json"));
23074
- const nested = files.filter((f) => f.includes("/") && (0, import_node_path27.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
23075
- for (const rel of nested) readPackageJson((0, import_node_path27.join)(root, rel));
23088
+ readPackageJson((0, import_node_path28.join)(root, "package.json"));
23089
+ const nested = files.filter((f) => f.includes("/") && (0, import_node_path28.basename)(f) === "package.json").slice(0, NESTED_MANIFEST_LIMIT);
23090
+ for (const rel of nested) readPackageJson((0, import_node_path28.join)(root, rel));
23076
23091
  const pythonManifests = [
23077
- ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path27.join)(root, f)),
23078
- ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path27.join)(root, f))
23092
+ ...["pyproject.toml", "requirements.txt", "Pipfile", "setup.py"].map((f) => (0, import_node_path28.join)(root, f)),
23093
+ ...files.filter((f) => f.includes("/") && /(^|\/)(pyproject\.toml|requirements\.txt)$/.test(f)).slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path28.join)(root, f))
23079
23094
  ];
23080
23095
  for (const path of pythonManifests) {
23081
- if (!(0, import_node_fs30.existsSync)(path)) continue;
23096
+ if (!(0, import_node_fs31.existsSync)(path)) continue;
23082
23097
  try {
23083
- const text = (0, import_node_fs30.readFileSync)(path, "utf-8");
23098
+ const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23084
23099
  for (const m of text.matchAll(/^\s*["']?([A-Za-z][A-Za-z0-9._-]+)/gm)) names2.push(m[1]);
23085
23100
  for (const line2 of text.split("\n")) {
23086
23101
  if (!/dependencies\s*=/.test(line2)) continue;
@@ -23090,13 +23105,13 @@ function declaredDependencies(root, files) {
23090
23105
  }
23091
23106
  }
23092
23107
  const goMods = [
23093
- (0, import_node_path27.join)(root, "go.mod"),
23094
- ...files.filter((f) => f.includes("/") && (0, import_node_path27.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path27.join)(root, f))
23108
+ (0, import_node_path28.join)(root, "go.mod"),
23109
+ ...files.filter((f) => f.includes("/") && (0, import_node_path28.basename)(f) === "go.mod").slice(0, NESTED_MANIFEST_LIMIT).map((f) => (0, import_node_path28.join)(root, f))
23095
23110
  ];
23096
23111
  for (const path of goMods) {
23097
- if (!(0, import_node_fs30.existsSync)(path)) continue;
23112
+ if (!(0, import_node_fs31.existsSync)(path)) continue;
23098
23113
  try {
23099
- const text = (0, import_node_fs30.readFileSync)(path, "utf-8");
23114
+ const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23100
23115
  for (const m of text.matchAll(/^\s+([\w.-]+\/[\w./-]+)\s+v/gm)) {
23101
23116
  names2.push(m[1].replace(/^github\.com\//, ""));
23102
23117
  }
@@ -23104,10 +23119,10 @@ function declaredDependencies(root, files) {
23104
23119
  }
23105
23120
  }
23106
23121
  for (const file of ["pom.xml", "build.gradle", "build.gradle.kts", "Gemfile", "Cargo.toml"]) {
23107
- const path = (0, import_node_path27.join)(root, file);
23108
- if (!(0, import_node_fs30.existsSync)(path)) continue;
23122
+ const path = (0, import_node_path28.join)(root, file);
23123
+ if (!(0, import_node_fs31.existsSync)(path)) continue;
23109
23124
  try {
23110
- const text = (0, import_node_fs30.readFileSync)(path, "utf-8");
23125
+ const text = (0, import_node_fs31.readFileSync)(path, "utf-8");
23111
23126
  for (const m of text.matchAll(/["'<]([A-Za-z][A-Za-z0-9._-]{2,})["'>]/g)) names2.push(m[1]);
23112
23127
  } catch {
23113
23128
  }
@@ -23115,7 +23130,7 @@ function declaredDependencies(root, files) {
23115
23130
  return names2;
23116
23131
  }
23117
23132
  function detectBuildSystem(root, files) {
23118
- const has = (f) => (0, import_node_fs30.existsSync)((0, import_node_path27.join)(root, f)) || files.some((p) => (0, import_node_path27.basename)(p) === f);
23133
+ const has = (f) => (0, import_node_fs31.existsSync)((0, import_node_path28.join)(root, f)) || files.some((p) => (0, import_node_path28.basename)(p) === f);
23119
23134
  if (has("pnpm-lock.yaml")) return "pnpm";
23120
23135
  if (has("yarn.lock")) return "yarn";
23121
23136
  if (has("bun.lock") || has("bun.lockb")) return "bun";
@@ -23132,8 +23147,8 @@ function detectBuildSystem(root, files) {
23132
23147
  }
23133
23148
  function detectArchitecture(root, files) {
23134
23149
  const workspaceMarkers = ["lerna.json", "pnpm-workspace.yaml", "nx.json", "turbo.json", "rush.json"];
23135
- if (workspaceMarkers.some((m) => (0, import_node_fs30.existsSync)((0, import_node_path27.join)(root, m)))) return "monorepo";
23136
- const pkg = readJson2((0, import_node_path27.join)(root, "package.json"));
23150
+ if (workspaceMarkers.some((m) => (0, import_node_fs31.existsSync)((0, import_node_path28.join)(root, m)))) return "monorepo";
23151
+ const pkg = readJson2((0, import_node_path28.join)(root, "package.json"));
23137
23152
  if (pkg && "workspaces" in pkg) return "monorepo";
23138
23153
  const manifests = files.filter((f) => /(^|\/)(package\.json|go\.mod|pyproject\.toml|Cargo\.toml|pom\.xml)$/.test(f));
23139
23154
  const nested = manifests.filter((f) => f.includes("/"));
@@ -23155,10 +23170,10 @@ function measureAvgFileLength(root, files, languages) {
23155
23170
  let total = 0;
23156
23171
  let counted = 0;
23157
23172
  for (let i2 = 0; i2 < candidates2.length; i2 += stride) {
23158
- const path = (0, import_node_path27.join)(root, candidates2[i2]);
23173
+ const path = (0, import_node_path28.join)(root, candidates2[i2]);
23159
23174
  try {
23160
- if ((0, import_node_fs30.statSync)(path).size > 2 * 1024 * 1024) continue;
23161
- total += (0, import_node_fs30.readFileSync)(path, "utf-8").split("\n").length;
23175
+ if ((0, import_node_fs31.statSync)(path).size > 2 * 1024 * 1024) continue;
23176
+ total += (0, import_node_fs31.readFileSync)(path, "utf-8").split("\n").length;
23162
23177
  counted++;
23163
23178
  } catch {
23164
23179
  }
@@ -23188,14 +23203,14 @@ function detectProject(root = repoRoot()) {
23188
23203
  const existingToolConfigs = [];
23189
23204
  for (const [tool, markers] of TOOL_CONFIG_MARKERS) {
23190
23205
  for (const marker of markers) {
23191
- if ((0, import_node_fs30.existsSync)((0, import_node_path27.join)(root, marker))) {
23206
+ if ((0, import_node_fs31.existsSync)((0, import_node_path28.join)(root, marker))) {
23192
23207
  existingToolConfigs.push({ tool, path: `./${marker}` });
23193
23208
  break;
23194
23209
  }
23195
23210
  }
23196
23211
  }
23197
23212
  return {
23198
- projectName: (0, import_node_path27.basename)(root),
23213
+ projectName: (0, import_node_path28.basename)(root),
23199
23214
  languages,
23200
23215
  languageCounts,
23201
23216
  frameworks: matchAll(dependencies, FRAMEWORK_BY_DEPENDENCY),
@@ -23293,8 +23308,8 @@ ${closingNote(input.origin)}
23293
23308
 
23294
23309
  // src/lib/synthesize.ts
23295
23310
  function loadCatalog() {
23296
- const catalog = (0, import_yaml.parse)((0, import_node_fs31.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
23297
- const template = (0, import_yaml.parse)((0, import_node_fs31.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
23311
+ const catalog = (0, import_yaml.parse)((0, import_node_fs32.readFileSync)(setupDataPath("patterns-reference.yaml"), "utf-8"));
23312
+ const template = (0, import_yaml.parse)((0, import_node_fs32.readFileSync)(setupDataPath("standard-template.yaml"), "utf-8"));
23298
23313
  return { catalog, template };
23299
23314
  }
23300
23315
  function selectTools(languages, intensity, catalog) {
@@ -23572,7 +23587,7 @@ function validatePatternIds() {
23572
23587
  }
23573
23588
  async function runSynthesis(opts) {
23574
23589
  const standardPath = projectPath(STANDARD_FILE);
23575
- if ((0, import_node_fs31.existsSync)(standardPath) && !opts.force) {
23590
+ if ((0, import_node_fs32.existsSync)(standardPath) && !opts.force) {
23576
23591
  return { refused: `${STANDARD_FILE} already exists \u2014 pass --force to replace it.` };
23577
23592
  }
23578
23593
  const detected = opts.detected ?? detectProject();
@@ -23641,7 +23656,7 @@ async function correctVerityMdVersion(opts) {
23641
23656
  }
23642
23657
  async function writeFileTo(relative6, body2) {
23643
23658
  const target = projectPath(relative6);
23644
- await (0, import_promises10.mkdir)((0, import_node_path28.dirname)(target), { recursive: true });
23659
+ await (0, import_promises10.mkdir)((0, import_node_path29.dirname)(target), { recursive: true });
23645
23660
  await (0, import_promises10.writeFile)(target, body2);
23646
23661
  }
23647
23662
  async function deriveConfigForStandard(standard) {
@@ -23700,11 +23715,11 @@ ${validation.detail}`);
23700
23715
 
23701
23716
  // src/lib/setup-state.ts
23702
23717
  var import_promises11 = require("node:fs/promises");
23703
- var import_node_fs32 = require("node:fs");
23718
+ var import_node_fs33 = require("node:fs");
23704
23719
  var SETUP_STATE_FILE = `${VERITY_DIR}/setup.json`;
23705
23720
  async function readSetupState() {
23706
23721
  const path = projectPath(SETUP_STATE_FILE);
23707
- if (!(0, import_node_fs32.existsSync)(path)) return null;
23722
+ if (!(0, import_node_fs33.existsSync)(path)) return null;
23708
23723
  try {
23709
23724
  const parsed = JSON.parse(await (0, import_promises11.readFile)(path, "utf-8"));
23710
23725
  return parsed && typeof parsed === "object" ? parsed : null;
@@ -23720,12 +23735,12 @@ async function writeSetupState(patch) {
23720
23735
  }
23721
23736
 
23722
23737
  // src/lib/push-setup.ts
23723
- var import_node_fs34 = require("node:fs");
23738
+ var import_node_fs35 = require("node:fs");
23724
23739
  var import_promises12 = require("node:fs/promises");
23725
23740
  var import_yaml2 = __toESM2(require_dist());
23726
23741
 
23727
23742
  // src/lib/verityignore.ts
23728
- var import_node_fs33 = require("node:fs");
23743
+ var import_node_fs34 = require("node:fs");
23729
23744
  var EMPTY = { rules: [], securityOverlap: [], problems: [] };
23730
23745
  var SECURITY_PROBES = [
23731
23746
  ".env",
@@ -23818,9 +23833,9 @@ function isIgnored3(ig, path) {
23818
23833
  }
23819
23834
  function loadVerityIgnore() {
23820
23835
  const file = projectPath(VERITYIGNORE_FILE);
23821
- if (!(0, import_node_fs33.existsSync)(file)) return EMPTY;
23836
+ if (!(0, import_node_fs34.existsSync)(file)) return EMPTY;
23822
23837
  try {
23823
- return parseVerityIgnore((0, import_node_fs33.readFileSync)(file, "utf-8"));
23838
+ return parseVerityIgnore((0, import_node_fs34.readFileSync)(file, "utf-8"));
23824
23839
  } catch {
23825
23840
  return EMPTY;
23826
23841
  }
@@ -23858,9 +23873,9 @@ function buildStandardUpload(standard, ignoreRaw) {
23858
23873
  }
23859
23874
  function readVerityIgnoreRaw() {
23860
23875
  const file = projectPath(VERITYIGNORE_FILE);
23861
- if (!(0, import_node_fs33.existsSync)(file)) return null;
23876
+ if (!(0, import_node_fs34.existsSync)(file)) return null;
23862
23877
  try {
23863
- return (0, import_node_fs33.readFileSync)(file, "utf-8");
23878
+ return (0, import_node_fs34.readFileSync)(file, "utf-8");
23864
23879
  } catch {
23865
23880
  return null;
23866
23881
  }
@@ -23888,7 +23903,7 @@ async function pushStandardAndConfig(globals, what = {}) {
23888
23903
  }
23889
23904
  let standardVersion = null;
23890
23905
  const standardPath = projectPath(STANDARD_FILE);
23891
- if (pushStandard && (0, import_node_fs34.existsSync)(standardPath)) {
23906
+ if (pushStandard && (0, import_node_fs35.existsSync)(standardPath)) {
23892
23907
  try {
23893
23908
  const content = (0, import_yaml2.parse)(await (0, import_promises12.readFile)(standardPath, "utf-8"));
23894
23909
  const upload = buildStandardUpload(content, readVerityIgnoreRaw());
@@ -23913,7 +23928,7 @@ async function pushStandardAndConfig(globals, what = {}) {
23913
23928
  }
23914
23929
  let configPushed = false;
23915
23930
  const configPath = projectPath(CODACY_CONFIG_FILE);
23916
- if (pushConfig && (0, import_node_fs34.existsSync)(configPath)) {
23931
+ if (pushConfig && (0, import_node_fs35.existsSync)(configPath)) {
23917
23932
  try {
23918
23933
  const content = JSON.parse(await (0, import_promises12.readFile)(configPath, "utf-8"));
23919
23934
  const result = await apiRequest({
@@ -23945,7 +23960,7 @@ function registerStandardCommands(program2) {
23945
23960
  const state = await readSetupState();
23946
23961
  if (opts.configOnly) {
23947
23962
  const standardPath = projectPath(STANDARD_FILE);
23948
- if (!(0, import_node_fs35.existsSync)(standardPath)) {
23963
+ if (!(0, import_node_fs36.existsSync)(standardPath)) {
23949
23964
  printError(`No ${STANDARD_FILE} here \u2014 run "verity standard synthesize" to create one.`);
23950
23965
  process.exit(1);
23951
23966
  }
@@ -24137,7 +24152,7 @@ function registerConfigCommands(program2) {
24137
24152
  config.command("formal [state]").description('Get or set formal verification at push: "push" or "off" (needs Lean \u2014 verity lean status)').action((state) => {
24138
24153
  if (state === void 0) {
24139
24154
  const cfg = readProjectConfig();
24140
- process.stdout.write((cfg.formal ?? "off") + "\n");
24155
+ process.stdout.write((cfg.formal === "push" ? "push" : "off") + "\n");
24141
24156
  if (cfg.formal_refused) printWarn(formalRefusalMessage(cfg.formal_refused));
24142
24157
  return;
24143
24158
  }
@@ -24145,10 +24160,10 @@ function registerConfigCommands(program2) {
24145
24160
  printError(`Unrecognised state: ${state}. Use "push" or "off".`);
24146
24161
  process.exit(1);
24147
24162
  }
24148
- writeProjectConfig({ formal: state === "push" ? "push" : void 0 });
24149
- const refused = state === "push" ? readProjectConfig().formal_refused : void 0;
24150
- if (refused) {
24151
- printWarn(`Formal verification at push: still off \u2014 ${formalRefusalMessage(refused)}`);
24163
+ writeProjectConfig({ formal: state === "push" ? "push" : "off" });
24164
+ const refused2 = state === "push" ? readProjectConfig().formal_refused : void 0;
24165
+ if (refused2) {
24166
+ printWarn(`Formal verification at push: still off \u2014 ${formalRefusalMessage(refused2)}`);
24152
24167
  return;
24153
24168
  }
24154
24169
  printInfo(state === "push" ? "Formal verification at push: on for this checkout (Lean must be installed \u2014 verity lean status)" : "Formal verification at push: off");
@@ -24298,10 +24313,10 @@ function formatRunDetail(run4) {
24298
24313
  }
24299
24314
 
24300
24315
  // src/lib/ignore-declaration.ts
24301
- var import_node_fs37 = require("node:fs");
24316
+ var import_node_fs38 = require("node:fs");
24302
24317
 
24303
24318
  // src/lib/debounce.ts
24304
- var import_node_fs36 = require("node:fs");
24319
+ var import_node_fs37 = require("node:fs");
24305
24320
  var import_node_crypto11 = require("node:crypto");
24306
24321
  function scopedFile(base, sessionId) {
24307
24322
  if (!sessionId) return base;
@@ -24309,9 +24324,9 @@ function scopedFile(base, sessionId) {
24309
24324
  }
24310
24325
  function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
24311
24326
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
24312
- if (!(0, import_node_fs36.existsSync)(file)) return null;
24327
+ if (!(0, import_node_fs37.existsSync)(file)) return null;
24313
24328
  try {
24314
- const lastTs = parseInt((0, import_node_fs36.readFileSync)(file, "utf-8").trim(), 10);
24329
+ const lastTs = parseInt((0, import_node_fs37.readFileSync)(file, "utf-8").trim(), 10);
24315
24330
  const nowTs = Math.floor(Date.now() / 1e3);
24316
24331
  const elapsed = nowTs - lastTs;
24317
24332
  if (elapsed < debounceSeconds) {
@@ -24324,10 +24339,10 @@ function checkDebounce(debounceSeconds = DEBOUNCE_SECONDS, sessionId) {
24324
24339
  function checkMtime(files, bypassForRecentCommits, sessionId) {
24325
24340
  if (bypassForRecentCommits) return null;
24326
24341
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
24327
- if (!(0, import_node_fs36.existsSync)(file)) return null;
24342
+ if (!(0, import_node_fs37.existsSync)(file)) return null;
24328
24343
  let debounceTime;
24329
24344
  try {
24330
- debounceTime = (0, import_node_fs36.statSync)(file).mtimeMs;
24345
+ debounceTime = (0, import_node_fs37.statSync)(file).mtimeMs;
24331
24346
  } catch {
24332
24347
  return null;
24333
24348
  }
@@ -24335,7 +24350,7 @@ function checkMtime(files, bypassForRecentCommits, sessionId) {
24335
24350
  const resolved = resolveFile(f);
24336
24351
  if (!resolved) continue;
24337
24352
  try {
24338
- const stat3 = (0, import_node_fs36.statSync)(resolved);
24353
+ const stat3 = (0, import_node_fs37.statSync)(resolved);
24339
24354
  if (stat3.mtimeMs > debounceTime) {
24340
24355
  return null;
24341
24356
  }
@@ -24351,8 +24366,8 @@ function computeContentHash(files) {
24351
24366
  for (const f of sorted) {
24352
24367
  const resolved = resolveFile(f) ?? f;
24353
24368
  try {
24354
- if ((0, import_node_fs36.existsSync)(resolved)) {
24355
- hash.update((0, import_node_fs36.readFileSync)(resolved));
24369
+ if ((0, import_node_fs37.existsSync)(resolved)) {
24370
+ hash.update((0, import_node_fs37.readFileSync)(resolved));
24356
24371
  }
24357
24372
  } catch {
24358
24373
  }
@@ -24362,9 +24377,9 @@ function computeContentHash(files) {
24362
24377
  function checkContentHash(files, sessionId) {
24363
24378
  const hash = computeContentHash(files);
24364
24379
  const file = scopedFile(HASH_FILE, sessionId);
24365
- if ((0, import_node_fs36.existsSync)(file)) {
24380
+ if ((0, import_node_fs37.existsSync)(file)) {
24366
24381
  try {
24367
- const storedHash = (0, import_node_fs36.readFileSync)(file, "utf-8").trim();
24382
+ const storedHash = (0, import_node_fs37.readFileSync)(file, "utf-8").trim();
24368
24383
  if (hash === storedHash) {
24369
24384
  return { skip: "No source changes since last analysis", hash };
24370
24385
  }
@@ -24374,24 +24389,24 @@ function checkContentHash(files, sessionId) {
24374
24389
  return { skip: null, hash };
24375
24390
  }
24376
24391
  function recordAnalysisStart(sessionId) {
24377
- (0, import_node_fs36.mkdirSync)(VERITY_DIR, { recursive: true });
24378
- (0, import_node_fs36.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
24392
+ (0, import_node_fs37.mkdirSync)(VERITY_DIR, { recursive: true });
24393
+ (0, import_node_fs37.writeFileSync)(scopedFile(DEBOUNCE_FILE, sessionId), String(Math.floor(Date.now() / 1e3)));
24379
24394
  }
24380
24395
  function recordPassHash(hash, sessionId) {
24381
- (0, import_node_fs36.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
24396
+ (0, import_node_fs37.writeFileSync)(scopedFile(HASH_FILE, sessionId), hash);
24382
24397
  }
24383
24398
  function narrowToRecent(files, sessionId) {
24384
24399
  const file = scopedFile(DEBOUNCE_FILE, sessionId);
24385
- if (!(0, import_node_fs36.existsSync)(file)) return files;
24400
+ if (!(0, import_node_fs37.existsSync)(file)) return files;
24386
24401
  let debounceTime;
24387
24402
  try {
24388
- debounceTime = (0, import_node_fs36.statSync)(file).mtimeMs;
24403
+ debounceTime = (0, import_node_fs37.statSync)(file).mtimeMs;
24389
24404
  } catch {
24390
24405
  return files;
24391
24406
  }
24392
24407
  const recent = files.filter((f) => {
24393
24408
  try {
24394
- return (0, import_node_fs36.existsSync)(f) && (0, import_node_fs36.statSync)(f).mtimeMs > debounceTime;
24409
+ return (0, import_node_fs37.existsSync)(f) && (0, import_node_fs37.statSync)(f).mtimeMs > debounceTime;
24395
24410
  } catch {
24396
24411
  return false;
24397
24412
  }
@@ -24404,9 +24419,9 @@ function readIteration(currentCommit, _contentHash) {
24404
24419
  var NO_BLOCKS = { attempts: 0, blocks: 0, fingerprint: null };
24405
24420
  function readBlockState(currentCommit, opts) {
24406
24421
  if (opts?.newUserPrompt) return NO_BLOCKS;
24407
- if (!(0, import_node_fs36.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
24422
+ if (!(0, import_node_fs37.existsSync)(ITERATION_FILE)) return NO_BLOCKS;
24408
24423
  try {
24409
- const stored = (0, import_node_fs36.readFileSync)(ITERATION_FILE, "utf-8").trim();
24424
+ const stored = (0, import_node_fs37.readFileSync)(ITERATION_FILE, "utf-8").trim();
24410
24425
  const parsed = stored.startsWith("{") ? parseJsonState(stored) : parseLegacyState(stored);
24411
24426
  if (!parsed) return NO_BLOCKS;
24412
24427
  if (parsed.commit !== currentCommit) return NO_BLOCKS;
@@ -24452,8 +24467,8 @@ function isSameProblem(previous, current) {
24452
24467
  return current.split(",").some((k) => prev.has(k));
24453
24468
  }
24454
24469
  function writeBlockState(commit, state) {
24455
- (0, import_node_fs36.mkdirSync)(VERITY_DIR, { recursive: true });
24456
- (0, import_node_fs36.writeFileSync)(
24470
+ (0, import_node_fs37.mkdirSync)(VERITY_DIR, { recursive: true });
24471
+ (0, import_node_fs37.writeFileSync)(
24457
24472
  ITERATION_FILE,
24458
24473
  JSON.stringify({
24459
24474
  v: 2,
@@ -24558,9 +24573,9 @@ function resolveIgnoreState(keys) {
24558
24573
  }
24559
24574
  function readIgnoreState(sessionId) {
24560
24575
  const file = stateFile(sessionId);
24561
- if (!(0, import_node_fs37.existsSync)(file)) return null;
24576
+ if (!(0, import_node_fs38.existsSync)(file)) return null;
24562
24577
  try {
24563
- const o = JSON.parse((0, import_node_fs37.readFileSync)(file, "utf-8")) ?? {};
24578
+ const o = JSON.parse((0, import_node_fs38.readFileSync)(file, "utf-8")) ?? {};
24564
24579
  const spent = typeof o.spent === "number" ? o.spent : 0;
24565
24580
  const raw = o.active;
24566
24581
  let active = null;
@@ -24584,8 +24599,8 @@ function readIgnoreState(sessionId) {
24584
24599
  }
24585
24600
  function writeIgnoreState(state, sessionId) {
24586
24601
  try {
24587
- (0, import_node_fs37.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
24588
- (0, import_node_fs37.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
24602
+ (0, import_node_fs38.mkdirSync)(projectPath(VERITY_DIR), { recursive: true });
24603
+ (0, import_node_fs38.writeFileSync)(stateFile(sessionId), JSON.stringify({ v: 1, active: state.active, spent: state.spent }));
24589
24604
  } catch {
24590
24605
  }
24591
24606
  }
@@ -24968,7 +24983,7 @@ function createRun(opts, globals) {
24968
24983
  }
24969
24984
 
24970
24985
  // src/commands/analyze/index.ts
24971
- var import_node_fs51 = require("node:fs");
24986
+ var import_node_fs52 = require("node:fs");
24972
24987
 
24973
24988
  // src/lib/repo-context.ts
24974
24989
  var import_node_child_process11 = require("node:child_process");
@@ -25932,10 +25947,10 @@ function installRunEvidence(run4) {
25932
25947
  }
25933
25948
 
25934
25949
  // src/lib/git-frame.ts
25935
- var import_node_fs38 = require("node:fs");
25950
+ var import_node_fs39 = require("node:fs");
25936
25951
  var import_node_os6 = require("node:os");
25937
- var import_node_path29 = require("node:path");
25938
25952
  var import_node_path30 = require("node:path");
25953
+ var import_node_path31 = require("node:path");
25939
25954
  var VALUE_TOKEN = `(?:'[^']*'|"[^"]*"|\\S+)`;
25940
25955
  var GIT_GLOBAL_OPTS = `(?:\\s+(?:-[Cc]\\s+${VALUE_TOKEN}|--?[\\w-]+(?:=\\S+)?))*`;
25941
25956
  var COMMIT_HEAD = `git${GIT_GLOBAL_OPTS}\\s+commit(?![\\w-])`;
@@ -26022,8 +26037,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
26022
26037
  if (SHELL_DYNAMIC.test(raw) || raw === "-") {
26023
26038
  return { dir: null, named: true, unresolvable: `cd target not statically resolvable: ${raw}` };
26024
26039
  }
26025
- const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path30.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
26026
- dir = (0, import_node_path29.isAbsolute)(expanded) ? expanded : (0, import_node_path29.resolve)(dir, expanded);
26040
+ const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path31.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
26041
+ dir = (0, import_node_path30.isAbsolute)(expanded) ? expanded : (0, import_node_path30.resolve)(dir, expanded);
26027
26042
  }
26028
26043
  const seg = segments[segmentIndex];
26029
26044
  const overrideMatch = /--(?:git-dir|work-tree)(?:=|\s)|\bGIT_(?:DIR|WORK_TREE|INDEX_FILE)=/.exec(seg);
@@ -26041,8 +26056,8 @@ function extractCommandTarget(command, segmentIndex, baseDir) {
26041
26056
  if (SHELL_DYNAMIC.test(raw)) {
26042
26057
  return { dir: null, named: true, unresolvable: `-C target not statically resolvable: ${raw}` };
26043
26058
  }
26044
- const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path30.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
26045
- dir = (0, import_node_path29.isAbsolute)(expanded) ? expanded : (0, import_node_path29.resolve)(dir, expanded);
26059
+ const expanded = raw === "~" ? (0, import_node_os6.homedir)() : raw.startsWith("~/") ? (0, import_node_path31.join)((0, import_node_os6.homedir)(), raw.slice(2)) : raw;
26060
+ dir = (0, import_node_path30.isAbsolute)(expanded) ? expanded : (0, import_node_path30.resolve)(dir, expanded);
26046
26061
  }
26047
26062
  }
26048
26063
  return { dir, named, unresolvable: null };
@@ -26102,14 +26117,14 @@ function gitAt(dir, args2) {
26102
26117
  }
26103
26118
  function realpathOr2(p) {
26104
26119
  try {
26105
- return import_node_fs38.realpathSync.native(p);
26120
+ return import_node_fs39.realpathSync.native(p);
26106
26121
  } catch {
26107
- return (0, import_node_path29.resolve)(p);
26122
+ return (0, import_node_path30.resolve)(p);
26108
26123
  }
26109
26124
  }
26110
26125
  function resolveFrame(input) {
26111
26126
  const found = findMomentSegment(input.command, input.on);
26112
- const hookDirUsable = !!input.hookCwd && (0, import_node_fs38.existsSync)(input.hookCwd);
26127
+ const hookDirUsable = !!input.hookCwd && (0, import_node_fs39.existsSync)(input.hookCwd);
26113
26128
  const baseDir = hookDirUsable ? input.hookCwd : process.cwd();
26114
26129
  let anchor = hookDirUsable ? "hook-cwd" : "process-cwd";
26115
26130
  const refuse = (refusal) => ({
@@ -26132,7 +26147,7 @@ function resolveFrame(input) {
26132
26147
  if (dirs.size > 1) return refuse(`target:multiple ${found.moment} targets in one command`);
26133
26148
  const targetDir = dirs.size === 1 ? [...dirs][0] : baseDir;
26134
26149
  if (targetDir !== baseDir) {
26135
- if (!(0, import_node_fs38.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26150
+ if (!(0, import_node_fs39.existsSync)(targetDir)) return refuse(`target:directory does not exist: ${targetDir}`);
26136
26151
  dir = targetDir;
26137
26152
  }
26138
26153
  }
@@ -26143,7 +26158,7 @@ function resolveFrame(input) {
26143
26158
  const gitDirRaw = gitAt(dir, ["rev-parse", "--absolute-git-dir"]);
26144
26159
  const commonRaw = gitAt(dir, ["rev-parse", "--git-common-dir"]);
26145
26160
  const gitDir = gitDirRaw ? realpathOr2(gitDirRaw) : null;
26146
- const commonDir = commonRaw ? realpathOr2((0, import_node_path29.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path29.resolve)(dir, commonRaw)) : null;
26161
+ const commonDir = commonRaw ? realpathOr2((0, import_node_path30.isAbsolute)(commonRaw) ? commonRaw : (0, import_node_path30.resolve)(dir, commonRaw)) : null;
26147
26162
  const branchRaw = gitAt(dir, ["rev-parse", "--abbrev-ref", "HEAD"]);
26148
26163
  return {
26149
26164
  moment: found?.moment ?? null,
@@ -26318,8 +26333,8 @@ function stagedRange(frame, command) {
26318
26333
  if (plan.kind === "unpredictable") {
26319
26334
  return { kind: "staged", base: "HEAD", head: "INDEX", via: "staged-in-command", refusal: plan.reason };
26320
26335
  }
26321
- const mergeHead = frame.gitDir ? (0, import_node_path30.join)(frame.gitDir, "MERGE_HEAD") : null;
26322
- if (mergeHead && (0, import_node_fs38.existsSync)(mergeHead)) {
26336
+ const mergeHead = frame.gitDir ? (0, import_node_path31.join)(frame.gitDir, "MERGE_HEAD") : null;
26337
+ if (mergeHead && (0, import_node_fs39.existsSync)(mergeHead)) {
26323
26338
  const vsHead = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "HEAD"]).split("\n").filter(Boolean));
26324
26339
  const vsMerge = new Set(frameGit(frame, ["diff", "--cached", "--name-only", "MERGE_HEAD"]).split("\n").filter(Boolean));
26325
26340
  const resolutions = new Set([...vsHead].filter((f) => vsMerge.has(f) && !isVerityOwnedPath(f)));
@@ -26453,7 +26468,7 @@ function truthy(v) {
26453
26468
  }
26454
26469
 
26455
26470
  // src/lib/transcript.ts
26456
- var import_node_fs39 = require("node:fs");
26471
+ var import_node_fs40 = require("node:fs");
26457
26472
  var MAX_READ_BYTES = 256 * 1024;
26458
26473
  var SMALL_FILE_BYTES = 64 * 1024;
26459
26474
  var MAX_FILES_LIST = 20;
@@ -26480,7 +26495,7 @@ async function extractActionSummary(transcriptPath) {
26480
26495
  function readTurnLines(transcriptPath) {
26481
26496
  let size;
26482
26497
  try {
26483
- size = (0, import_node_fs39.statSync)(transcriptPath).size;
26498
+ size = (0, import_node_fs40.statSync)(transcriptPath).size;
26484
26499
  } catch {
26485
26500
  return null;
26486
26501
  }
@@ -26488,7 +26503,7 @@ function readTurnLines(transcriptPath) {
26488
26503
  let raw;
26489
26504
  let windowed = false;
26490
26505
  if (size <= SMALL_FILE_BYTES) {
26491
- raw = (0, import_node_fs39.readFileSync)(transcriptPath, "utf-8");
26506
+ raw = (0, import_node_fs40.readFileSync)(transcriptPath, "utf-8");
26492
26507
  } else {
26493
26508
  windowed = true;
26494
26509
  const buf = Buffer.alloc(Math.min(MAX_READ_BYTES, size));
@@ -27058,7 +27073,7 @@ function channelSilence(input) {
27058
27073
  // src/lib/cli-version.ts
27059
27074
  function cliVersion() {
27060
27075
  try {
27061
- return true ? "0.34.0-experimental.b9e8508" : "dev";
27076
+ return true ? "0.34.0-experimental.cc5f6ec" : "dev";
27062
27077
  } catch {
27063
27078
  return "dev";
27064
27079
  }
@@ -27099,7 +27114,7 @@ async function sendSkipBeacon(ctx, reason) {
27099
27114
 
27100
27115
  // src/lib/static-analysis.ts
27101
27116
  var import_node_child_process12 = require("node:child_process");
27102
- var import_node_fs40 = require("node:fs");
27117
+ var import_node_fs41 = require("node:fs");
27103
27118
  var SEVERITY_ORDER = {
27104
27119
  Error: 0,
27105
27120
  Critical: 0,
@@ -27155,7 +27170,7 @@ function runCodacyAnalysis(files) {
27155
27170
  if (files.length === 0) return empty;
27156
27171
  const existingFiles = files.filter((f) => {
27157
27172
  try {
27158
- return (0, import_node_fs40.existsSync)(f);
27173
+ return (0, import_node_fs41.existsSync)(f);
27159
27174
  } catch {
27160
27175
  return false;
27161
27176
  }
@@ -27424,8 +27439,8 @@ async function scope(run4) {
27424
27439
  }
27425
27440
 
27426
27441
  // src/lib/specs.ts
27427
- var import_node_fs41 = require("node:fs");
27428
- var import_node_path31 = require("node:path");
27442
+ var import_node_fs42 = require("node:fs");
27443
+ var import_node_path32 = require("node:path");
27429
27444
  var SPEC_CANDIDATES = [
27430
27445
  "CLAUDE.md",
27431
27446
  "AGENTS.md",
@@ -27447,7 +27462,7 @@ var UNCONSULTED_TOTAL_BYTES = 30720;
27447
27462
  function readSpecFiles(specsOpt, root) {
27448
27463
  const out2 = [];
27449
27464
  for (const raw of specsOpt.split(",").map((f) => f.trim()).filter(Boolean)) {
27450
- const candidate = (0, import_node_path31.isAbsolute)(raw) ? (0, import_node_path31.relative)(root, raw) : raw;
27465
+ const candidate = (0, import_node_path32.isAbsolute)(raw) ? (0, import_node_path32.relative)(root, raw) : raw;
27451
27466
  const content = readFileInside(root, candidate, MAX_EXPLICIT_SPEC_FILE_BYTES);
27452
27467
  if (content === null) continue;
27453
27468
  out2.push({ path: raw, content });
@@ -27466,7 +27481,7 @@ function discoverSpecs(consulted = []) {
27466
27481
  const totalCap = relevant ? MAX_TOTAL_SPEC_BYTES : UNCONSULTED_TOTAL_BYTES;
27467
27482
  if (totalBytes >= totalCap) return false;
27468
27483
  if (seen.has(specPath)) return true;
27469
- if (!(0, import_node_fs41.existsSync)(specPath)) return true;
27484
+ if (!(0, import_node_fs42.existsSync)(specPath)) return true;
27470
27485
  seen.add(specPath);
27471
27486
  const remaining = totalCap - totalBytes;
27472
27487
  const fileCap = relevant ? MAX_SPEC_FILE_BYTES : UNCONSULTED_FILE_BYTES;
@@ -27489,7 +27504,7 @@ function discoverSpecs(consulted = []) {
27489
27504
  if (!addSpec(candidate)) break;
27490
27505
  }
27491
27506
  for (const dir of ["spec", "docs"]) {
27492
- if (!(0, import_node_fs41.existsSync)(dir)) continue;
27507
+ if (!(0, import_node_fs42.existsSync)(dir)) continue;
27493
27508
  try {
27494
27509
  const mdFiles = findMdFiles(dir, 2).sort();
27495
27510
  for (const mdFile of mdFiles) {
@@ -27504,9 +27519,9 @@ function findMdFiles(dir, maxDepth, depth = 0) {
27504
27519
  if (depth >= maxDepth) return [];
27505
27520
  const result = [];
27506
27521
  try {
27507
- const entries = (0, import_node_fs41.readdirSync)(dir, { withFileTypes: true });
27522
+ const entries = (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true });
27508
27523
  for (const entry of entries) {
27509
- const fullPath = (0, import_node_path31.join)(dir, entry.name);
27524
+ const fullPath = (0, import_node_path32.join)(dir, entry.name);
27510
27525
  if (entry.isFile() && entry.name.endsWith(".md")) {
27511
27526
  result.push(fullPath);
27512
27527
  } else if (entry.isDirectory() && depth < maxDepth - 1) {
@@ -27519,25 +27534,25 @@ function findMdFiles(dir, maxDepth, depth = 0) {
27519
27534
  }
27520
27535
  function discoverPlans() {
27521
27536
  const home = process.env.HOME ?? "";
27522
- const homePlansDir = (0, import_node_path31.join)(home, ".claude", "plans");
27537
+ const homePlansDir = (0, import_node_path32.join)(home, ".claude", "plans");
27523
27538
  const sources = [];
27524
27539
  if (isRealDirectoryChain(process.cwd(), [".claude", "plans"])) {
27525
- sources.push({ root: process.cwd(), prefix: (0, import_node_path31.join)(".claude", "plans") });
27540
+ sources.push({ root: process.cwd(), prefix: (0, import_node_path32.join)(".claude", "plans") });
27526
27541
  }
27527
- if (home && (0, import_node_fs41.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
27542
+ if (home && (0, import_node_fs42.existsSync)(homePlansDir)) sources.push({ root: homePlansDir, prefix: "" });
27528
27543
  const candidates2 = [];
27529
27544
  const seen = /* @__PURE__ */ new Set();
27530
27545
  for (const source2 of sources) {
27531
27546
  let names2;
27532
27547
  try {
27533
- names2 = (0, import_node_fs41.readdirSync)(source2.prefix ? (0, import_node_path31.join)(source2.root, source2.prefix) : source2.root);
27548
+ names2 = (0, import_node_fs42.readdirSync)(source2.prefix ? (0, import_node_path32.join)(source2.root, source2.prefix) : source2.root);
27534
27549
  } catch {
27535
27550
  continue;
27536
27551
  }
27537
27552
  for (const f of names2) {
27538
27553
  if (!f.endsWith(".md") || seen.has(f)) continue;
27539
27554
  seen.add(f);
27540
- const relPath = source2.prefix ? (0, import_node_path31.join)(source2.prefix, f) : f;
27555
+ const relPath = source2.prefix ? (0, import_node_path32.join)(source2.prefix, f) : f;
27541
27556
  const stat3 = statRegularInRoot(source2.root, relPath);
27542
27557
  if (!stat3.ok) continue;
27543
27558
  candidates2.push({ name: f, root: source2.root, relPath, mtime: stat3.mtimeMs, size: stat3.size });
@@ -27555,9 +27570,9 @@ function discoverPlans() {
27555
27570
  function isRealDirectoryChain(root, parts2) {
27556
27571
  let current = root;
27557
27572
  for (const part of parts2) {
27558
- current = (0, import_node_path31.join)(current, part);
27573
+ current = (0, import_node_path32.join)(current, part);
27559
27574
  try {
27560
- if (!(0, import_node_fs41.lstatSync)(current).isDirectory()) return false;
27575
+ if (!(0, import_node_fs42.lstatSync)(current).isDirectory()) return false;
27561
27576
  } catch {
27562
27577
  return false;
27563
27578
  }
@@ -27572,7 +27587,7 @@ function discoverGuardDocs(rangeFiles2) {
27572
27587
  if (result.length >= MAX_SPEC_FILES) break;
27573
27588
  if (!GUARD_DOC_EXT.test(path)) continue;
27574
27589
  if (path.startsWith("/") || path.includes("..")) continue;
27575
- if (!(0, import_node_fs41.existsSync)(path)) continue;
27590
+ if (!(0, import_node_fs42.existsSync)(path)) continue;
27576
27591
  const opened = openRegularInRoot(process.cwd(), path);
27577
27592
  if (!opened.ok) continue;
27578
27593
  if (opened.size > MAX_PLAN_FILE_BYTES || totalBytes + opened.size > MAX_TOTAL_SPEC_BYTES) {
@@ -27758,8 +27773,8 @@ async function mode(run4) {
27758
27773
  }
27759
27774
 
27760
27775
  // src/lib/fold.ts
27761
- var import_node_fs42 = require("node:fs");
27762
- var import_node_path32 = require("node:path");
27776
+ var import_node_fs43 = require("node:fs");
27777
+ var import_node_path33 = require("node:path");
27763
27778
  var KNOWN_RECORD_TYPES = /* @__PURE__ */ new Set([
27764
27779
  "user",
27765
27780
  "assistant",
@@ -27896,7 +27911,7 @@ function candidateRoots(repoRoot2) {
27896
27911
  const norm2 = repoRoot2.replace(/\\/g, "/").replace(/\/+$/, "");
27897
27912
  const out2 = [norm2];
27898
27913
  try {
27899
- const real = import_node_fs42.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
27914
+ const real = import_node_fs43.realpathSync.native(norm2).replace(/\\/g, "/").replace(/\/+$/, "");
27900
27915
  if (real !== norm2) out2.push(real);
27901
27916
  } catch {
27902
27917
  }
@@ -27984,31 +27999,31 @@ function fold(transcriptPath, opts = {}) {
27984
27999
  }
27985
28000
  };
27986
28001
  try {
27987
- if (!(0, import_node_fs42.existsSync)(transcriptPath)) return result;
27988
- ingest((0, import_node_fs42.readFileSync)(transcriptPath, "utf8"), "agent");
28002
+ if (!(0, import_node_fs43.existsSync)(transcriptPath)) return result;
28003
+ ingest((0, import_node_fs43.readFileSync)(transcriptPath, "utf8"), "agent");
27989
28004
  result.coverage.complete = true;
27990
28005
  } catch {
27991
28006
  return result;
27992
28007
  }
27993
28008
  try {
27994
- const sidecarDir = (0, import_node_path32.join)(
27995
- (0, import_node_path32.dirname)(transcriptPath),
27996
- (0, import_node_path32.basename)(transcriptPath).replace(/\.jsonl$/, ""),
28009
+ const sidecarDir = (0, import_node_path33.join)(
28010
+ (0, import_node_path33.dirname)(transcriptPath),
28011
+ (0, import_node_path33.basename)(transcriptPath).replace(/\.jsonl$/, ""),
27997
28012
  "subagents"
27998
28013
  );
27999
- if ((0, import_node_fs42.existsSync)(sidecarDir)) {
28014
+ if ((0, import_node_fs43.existsSync)(sidecarDir)) {
28000
28015
  const maxFiles = opts.maxSidecars ?? 200;
28001
28016
  const maxBytes = opts.maxSidecarBytes ?? 16 * 1024 * 1024;
28002
28017
  const found = [];
28003
28018
  const walk2 = (d, depth) => {
28004
28019
  if (depth > 4) return;
28005
- for (const e of (0, import_node_fs42.readdirSync)(d, { withFileTypes: true })) {
28006
- const p = (0, import_node_path32.join)(d, e.name);
28020
+ for (const e of (0, import_node_fs43.readdirSync)(d, { withFileTypes: true })) {
28021
+ const p = (0, import_node_path33.join)(d, e.name);
28007
28022
  if (e.isDirectory()) {
28008
28023
  walk2(p, depth + 1);
28009
28024
  } else if (e.name.startsWith("agent-") && e.name.endsWith(".jsonl")) {
28010
28025
  try {
28011
- const st = (0, import_node_fs42.statSync)(p);
28026
+ const st = (0, import_node_fs43.statSync)(p);
28012
28027
  found.push({ path: p, size: st.size, mtimeMs: st.mtimeMs });
28013
28028
  } catch {
28014
28029
  result.coverage.malformed++;
@@ -28025,7 +28040,7 @@ function fold(transcriptPath, opts = {}) {
28025
28040
  continue;
28026
28041
  }
28027
28042
  try {
28028
- ingest((0, import_node_fs42.readFileSync)(f.path, "utf8"), "subagent");
28043
+ ingest((0, import_node_fs43.readFileSync)(f.path, "utf8"), "subagent");
28029
28044
  bytes += f.size;
28030
28045
  result.coverage.subagentFiles++;
28031
28046
  } catch {
@@ -28060,7 +28075,7 @@ function fold(transcriptPath, opts = {}) {
28060
28075
  }
28061
28076
  function classifyUnobserved(path) {
28062
28077
  try {
28063
- const st = (0, import_node_fs42.statSync)(path);
28078
+ const st = (0, import_node_fs43.statSync)(path);
28064
28079
  if (!st.isFile()) return "unreadable";
28065
28080
  } catch {
28066
28081
  return "unreadable";
@@ -28375,20 +28390,20 @@ async function evidence(run4) {
28375
28390
  }
28376
28391
 
28377
28392
  // src/lib/cache-cleanup.ts
28378
- var import_node_fs43 = require("node:fs");
28379
- var import_node_path33 = require("node:path");
28393
+ var import_node_fs44 = require("node:fs");
28394
+ var import_node_path34 = require("node:path");
28380
28395
  var CACHE_TTL_DAYS = 7;
28381
28396
  function pruneStaleCache() {
28382
28397
  try {
28383
28398
  const dir = projectPath(CACHE_DIR);
28384
28399
  const cutoff = Date.now() - CACHE_TTL_DAYS * 24 * 3600 * 1e3;
28385
- for (const entry of (0, import_node_fs43.readdirSync)(dir)) {
28400
+ for (const entry of (0, import_node_fs44.readdirSync)(dir)) {
28386
28401
  if (!entry.startsWith("pending-")) continue;
28387
- const path = (0, import_node_path33.join)(dir, entry);
28402
+ const path = (0, import_node_path34.join)(dir, entry);
28388
28403
  try {
28389
- const stat3 = (0, import_node_fs43.statSync)(path);
28404
+ const stat3 = (0, import_node_fs44.statSync)(path);
28390
28405
  if (stat3.mtimeMs < cutoff) {
28391
- (0, import_node_fs43.unlinkSync)(path);
28406
+ (0, import_node_fs44.unlinkSync)(path);
28392
28407
  logEvent("cache_entry_pruned", {
28393
28408
  path: entry,
28394
28409
  age_days: Math.round((Date.now() - stat3.mtimeMs) / 864e5)
@@ -28402,7 +28417,7 @@ function pruneStaleCache() {
28402
28417
  }
28403
28418
 
28404
28419
  // src/lib/context-files.ts
28405
- var import_node_fs44 = require("node:fs");
28420
+ var import_node_fs45 = require("node:fs");
28406
28421
  var import_node_os7 = require("node:os");
28407
28422
  var MAX_CONTEXT_FILES = 10;
28408
28423
  var MAX_CONTEXT_FILE_BYTES = 10240;
@@ -28460,7 +28475,7 @@ function gatherContextFiles(contextPaths, deltaFiles, opts) {
28460
28475
  continue;
28461
28476
  }
28462
28477
  try {
28463
- const content = (0, import_node_fs44.readFileSync)(safePath, "utf8");
28478
+ const content = (0, import_node_fs45.readFileSync)(safePath, "utf8");
28464
28479
  const bytes = Buffer.byteLength(content);
28465
28480
  if (bytes > MAX_CONTEXT_FILE_BYTES) {
28466
28481
  logEvent("context_file_skipped", { path: filePath, reason: "too_large", bytes });
@@ -28618,8 +28633,8 @@ function languageOf2(path) {
28618
28633
  }
28619
28634
 
28620
28635
  // src/lib/code/runtime.ts
28621
- var import_node_fs45 = require("node:fs");
28622
- var import_node_path34 = require("node:path");
28636
+ var import_node_fs46 = require("node:fs");
28637
+ var import_node_path35 = require("node:path");
28623
28638
  var import_web_tree_sitter2 = __toESM2(require_web_tree_sitter2());
28624
28639
 
28625
28640
  // src/lib/code/grammars.json
@@ -28679,18 +28694,18 @@ var grammars_default = {
28679
28694
  var MAX_PARSE_BYTES = 512 * 1024;
28680
28695
  function grammarCandidates(file, pkg, env = process.env) {
28681
28696
  return [
28682
- ...env.VERITY_GRAMMAR_DIR ? [(0, import_node_path34.join)(env.VERITY_GRAMMAR_DIR, file)] : [],
28683
- (0, import_node_path34.join)(__dirname, "..", "data", "grammars", file),
28697
+ ...env.VERITY_GRAMMAR_DIR ? [(0, import_node_path35.join)(env.VERITY_GRAMMAR_DIR, file)] : [],
28698
+ (0, import_node_path35.join)(__dirname, "..", "data", "grammars", file),
28684
28699
  // bundled: cli/bin/ → cli/data/grammars/
28685
- (0, import_node_path34.join)(__dirname, "..", "..", "..", "data", "grammars", file),
28700
+ (0, import_node_path35.join)(__dirname, "..", "..", "..", "data", "grammars", file),
28686
28701
  // tsx: cli/src/lib/code/ → cli/data/grammars/
28687
- (0, import_node_path34.join)(__dirname, "..", "..", "..", "node_modules", pkg, file)
28702
+ (0, import_node_path35.join)(__dirname, "..", "..", "..", "node_modules", pkg, file)
28688
28703
  // tsx, before a build: the pinned devDependency
28689
28704
  ];
28690
28705
  }
28691
28706
  function locateGrammar(id, env = process.env) {
28692
28707
  const g = grammars_default[id];
28693
- return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs45.existsSync)(p)) ?? null;
28708
+ return grammarCandidates(g.file, g.package, env).find((p) => (0, import_node_fs46.existsSync)(p)) ?? null;
28694
28709
  }
28695
28710
  var loading = null;
28696
28711
  function loadRuntime(env = process.env) {
@@ -31019,8 +31034,8 @@ async function repoContext(run4) {
31019
31034
 
31020
31035
  // src/lib/seed-runner.ts
31021
31036
  var import_promises15 = require("node:fs/promises");
31022
- var import_node_fs46 = require("node:fs");
31023
- var import_node_path35 = require("node:path");
31037
+ var import_node_fs47 = require("node:fs");
31038
+ var import_node_path36 = require("node:path");
31024
31039
  var import_yaml4 = __toESM2(require_dist());
31025
31040
 
31026
31041
  // src/lib/seed.ts
@@ -31243,8 +31258,8 @@ function normalizeTitle(title) {
31243
31258
  async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
31244
31259
  const titles = /* @__PURE__ */ new Set();
31245
31260
  for (const dir of NODE_DIRS) {
31246
- const full = (0, import_node_path35.join)(memoryDir3, dir);
31247
- if (!(0, import_node_fs46.existsSync)(full)) continue;
31261
+ const full = (0, import_node_path36.join)(memoryDir3, dir);
31262
+ if (!(0, import_node_fs47.existsSync)(full)) continue;
31248
31263
  let files;
31249
31264
  try {
31250
31265
  files = await (0, import_promises15.readdir)(full);
@@ -31255,7 +31270,7 @@ async function localSeedTitles(memoryDir3 = MEMORY_DIR) {
31255
31270
  if (!file.endsWith(".md")) continue;
31256
31271
  let content;
31257
31272
  try {
31258
- content = await (0, import_promises15.readFile)((0, import_node_path35.join)(full, file), "utf-8");
31273
+ content = await (0, import_promises15.readFile)((0, import_node_path36.join)(full, file), "utf-8");
31259
31274
  } catch {
31260
31275
  continue;
31261
31276
  }
@@ -31326,7 +31341,7 @@ function renderNodeMarkdown(candidate, nodeId, createdAt) {
31326
31341
  return fm;
31327
31342
  }
31328
31343
  async function runSeed(opts) {
31329
- if (!(0, import_node_fs46.existsSync)(STANDARD_FILE)) {
31344
+ if (!(0, import_node_fs47.existsSync)(STANDARD_FILE)) {
31330
31345
  return { created: 0, existing: 0, failed: 0, skipped: "no_standard", candidates: [] };
31331
31346
  }
31332
31347
  let standardDoc;
@@ -31338,7 +31353,7 @@ async function runSeed(opts) {
31338
31353
  }
31339
31354
  const knowledgeSpec = standardDoc.knowledge_spec ?? {};
31340
31355
  let readmeContent;
31341
- if ((0, import_node_fs46.existsSync)("README.md")) {
31356
+ if ((0, import_node_fs47.existsSync)("README.md")) {
31342
31357
  try {
31343
31358
  readmeContent = await (0, import_promises15.readFile)("README.md", "utf-8");
31344
31359
  } catch {
@@ -31346,7 +31361,7 @@ async function runSeed(opts) {
31346
31361
  }
31347
31362
  let claudeMdContent;
31348
31363
  for (const p of ["CLAUDE.md", ".claude/CLAUDE.md"]) {
31349
- if ((0, import_node_fs46.existsSync)(p)) {
31364
+ if ((0, import_node_fs47.existsSync)(p)) {
31350
31365
  try {
31351
31366
  claudeMdContent = await (0, import_promises15.readFile)(p, "utf-8");
31352
31367
  break;
@@ -31426,13 +31441,13 @@ async function runSeed(opts) {
31426
31441
  continue;
31427
31442
  }
31428
31443
  const deduplicated = res.data.deduplicated === true;
31429
- if (deduplicated && (0, import_node_fs46.existsSync)(targetPath)) {
31444
+ if (deduplicated && (0, import_node_fs47.existsSync)(targetPath)) {
31430
31445
  existing++;
31431
31446
  continue;
31432
31447
  }
31433
31448
  const content = typeof res.data.content === "string" && res.data.content.length > 0 ? res.data.content : renderNodeMarkdown(c, nodeId, createdAt);
31434
31449
  try {
31435
- await (0, import_promises15.mkdir)((0, import_node_path35.dirname)(targetPath), { recursive: true });
31450
+ await (0, import_promises15.mkdir)((0, import_node_path36.dirname)(targetPath), { recursive: true });
31436
31451
  await (0, import_promises15.writeFile)(targetPath, content);
31437
31452
  if (deduplicated) existing++;
31438
31453
  else {
@@ -31448,8 +31463,8 @@ async function runSeed(opts) {
31448
31463
  }
31449
31464
 
31450
31465
  // src/commands/analyze/phases/08-memory-manifest.ts
31451
- var import_node_fs47 = require("node:fs");
31452
- var import_node_path36 = require("node:path");
31466
+ var import_node_fs48 = require("node:fs");
31467
+ var import_node_path37 = require("node:path");
31453
31468
  async function memoryManifest(run4) {
31454
31469
  const { globals } = run4;
31455
31470
  const { serviceUrl, token } = run4;
@@ -31459,9 +31474,9 @@ async function memoryManifest(run4) {
31459
31474
  let autoSeedNotice = null;
31460
31475
  try {
31461
31476
  await ensureMemoryDir();
31462
- const seedMarker = (0, import_node_path36.join)(VERITY_DIR, ".seeded");
31463
- const hasStandard = (0, import_node_fs47.existsSync)(STANDARD_FILE);
31464
- const alreadyTried = (0, import_node_fs47.existsSync)(seedMarker);
31477
+ 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);
31465
31480
  if (hasStandard && !alreadyTried) {
31466
31481
  const preManifest = await buildManifest();
31467
31482
  if (preManifest.nodes.length === 0) {
@@ -31474,7 +31489,7 @@ async function memoryManifest(run4) {
31474
31489
  dryRun: false
31475
31490
  });
31476
31491
  if (seedResult.created > 0 || seedResult.existing > 0) {
31477
- (0, import_node_fs47.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
31492
+ (0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} created=${seedResult.created} existing=${seedResult.existing}
31478
31493
  `);
31479
31494
  if (seedResult.created > 0) {
31480
31495
  autoSeedNotice = `Seeded ${seedResult.created} knowledge node(s) from your existing Standard (one-time).`;
@@ -31485,7 +31500,7 @@ async function memoryManifest(run4) {
31485
31500
  failed: seedResult.failed
31486
31501
  });
31487
31502
  } else if (seedResult.skipped === "already_seeded") {
31488
- (0, import_node_fs47.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
31503
+ (0, import_node_fs48.writeFileSync)(seedMarker, `${(/* @__PURE__ */ new Date()).toISOString()} skipped=already_seeded
31489
31504
  `);
31490
31505
  } else {
31491
31506
  logEvent("auto_seed_noop", {
@@ -31580,7 +31595,7 @@ function computeIncrement(reviewedPaths, hashOf, priorAuthored) {
31580
31595
  }
31581
31596
 
31582
31597
  // src/commands/analyze/phases/10-working-memory.ts
31583
- var import_node_path37 = require("node:path");
31598
+ var import_node_path38 = require("node:path");
31584
31599
  async function workingMemory(run4) {
31585
31600
  const { opts } = run4;
31586
31601
  const { allForReview, baseline, conversation, foldResult, sessionId, token, transcriptPath } = run4;
@@ -31592,7 +31607,7 @@ async function workingMemory(run4) {
31592
31607
  const priorState = foldForMarks(memorySession.d);
31593
31608
  incrementReport = computeIncrement(
31594
31609
  allForReview,
31595
- (p) => fileHash((0, import_node_path37.join)(repoRoot(), p)),
31610
+ (p) => fileHash((0, import_node_path38.join)(repoRoot(), p)),
31596
31611
  priorState.authored_all.map((a) => ({
31597
31612
  path: a.path,
31598
31613
  hash_at_last_verdict: a.hash_at_last_verdict
@@ -31674,7 +31689,7 @@ async function workingMemory(run4) {
31674
31689
  }
31675
31690
 
31676
31691
  // src/lib/note-budget.ts
31677
- var import_node_fs48 = require("node:fs");
31692
+ var import_node_fs49 = require("node:fs");
31678
31693
  var ADVISORY_BUDGET = { PASS: 1, WARN: 2 };
31679
31694
  var EPISODE_STALE_SECONDS = 30 * 60;
31680
31695
  var FRESH = { delivered: 0, tasksCompleted: 0, ts: 0 };
@@ -31696,9 +31711,9 @@ function advisoryBudgetSpent(episode, rawDecision) {
31696
31711
  }
31697
31712
  function readAdvisoryEpisode(sessionId) {
31698
31713
  const file = scopedFile(ADVISORY_EPISODE_FILE, sessionId);
31699
- if (!(0, import_node_fs48.existsSync)(file)) return null;
31714
+ if (!(0, import_node_fs49.existsSync)(file)) return null;
31700
31715
  try {
31701
- const o = JSON.parse((0, import_node_fs48.readFileSync)(file, "utf-8")) ?? {};
31716
+ const o = JSON.parse((0, import_node_fs49.readFileSync)(file, "utf-8")) ?? {};
31702
31717
  const delivered = typeof o.delivered === "number" ? o.delivered : NaN;
31703
31718
  if (isNaN(delivered)) return null;
31704
31719
  return {
@@ -31712,8 +31727,8 @@ function readAdvisoryEpisode(sessionId) {
31712
31727
  }
31713
31728
  function writeAdvisoryEpisode(episode, sessionId) {
31714
31729
  try {
31715
- (0, import_node_fs48.mkdirSync)(VERITY_DIR, { recursive: true });
31716
- (0, import_node_fs48.writeFileSync)(
31730
+ (0, import_node_fs49.mkdirSync)(VERITY_DIR, { recursive: true });
31731
+ (0, import_node_fs49.writeFileSync)(
31717
31732
  scopedFile(ADVISORY_EPISODE_FILE, sessionId),
31718
31733
  JSON.stringify({ v: 1, ...episode })
31719
31734
  );
@@ -32045,14 +32060,14 @@ async function buildRequest(run4) {
32045
32060
  }
32046
32061
 
32047
32062
  // src/lib/offline.ts
32048
- var import_node_fs49 = require("node:fs");
32063
+ var import_node_fs50 = require("node:fs");
32049
32064
  var import_node_crypto13 = require("node:crypto");
32050
32065
  function cacheRequest(body2) {
32051
32066
  try {
32052
- (0, import_node_fs49.mkdirSync)(CACHE_DIR, { recursive: true });
32067
+ (0, import_node_fs50.mkdirSync)(CACHE_DIR, { recursive: true });
32053
32068
  const suffix = (0, import_node_crypto13.randomBytes)(4).toString("hex");
32054
32069
  const filename = `pending-${Math.floor(Date.now() / 1e3)}-${suffix}.json`;
32055
- (0, import_node_fs49.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
32070
+ (0, import_node_fs50.writeFileSync)(`${CACHE_DIR}/${filename}`, JSON.stringify(redactRequest(body2)));
32056
32071
  } catch {
32057
32072
  }
32058
32073
  }
@@ -32171,8 +32186,8 @@ async function transmit(run4) {
32171
32186
  }
32172
32187
 
32173
32188
  // src/commands/analyze/phases/13-reconcile.ts
32174
- var import_node_fs50 = require("node:fs");
32175
- var import_node_path38 = require("node:path");
32189
+ var import_node_fs51 = require("node:fs");
32190
+ var import_node_path39 = require("node:path");
32176
32191
  async function reconcile(run4) {
32177
32192
  const { actionSummary, allChanged, analyzable, baseline, baselineSessionId, codeDelta, contentHash, conversation, decision, foldResult, memory: memory2, memorySession, response, reviewable, securityFiles, turnId } = run4;
32178
32193
  const sentPaths = codeDelta.files.map((f) => f.path);
@@ -32201,7 +32216,7 @@ async function reconcile(run4) {
32201
32216
  const st = foldDossier(memorySession.d);
32202
32217
  openElsewhere = openBlockingElsewhere(st.statements, sentPaths, (file, line2) => {
32203
32218
  try {
32204
- const src = (0, import_node_fs50.readFileSync)((0, import_node_path38.join)(repoRoot(), file), "utf8").split("\n");
32219
+ const src = (0, import_node_fs51.readFileSync)((0, import_node_path39.join)(repoRoot(), file), "utf8").split("\n");
32205
32220
  const at = src[line2 - 1];
32206
32221
  return at === void 0 ? null : lineSha(at);
32207
32222
  } catch {
@@ -33023,7 +33038,7 @@ function registerAnalyzeCommand(program2) {
33023
33038
  var tracing = () => process.env.VERITY_TRACE_PHASES === "1";
33024
33039
  async function runAnalyze(opts, globals) {
33025
33040
  if (!verityConfigured()) {
33026
- (0, import_node_fs51.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
33041
+ (0, import_node_fs52.writeSync)(2, '[verity] not set up in this project \u2014 run "verity init" first.\n');
33027
33042
  process.exit(0);
33028
33043
  }
33029
33044
  const run4 = createRun(opts, globals);
@@ -33044,11 +33059,11 @@ async function runAnalyze(opts, globals) {
33044
33059
  }
33045
33060
 
33046
33061
  // src/commands/baseline.ts
33047
- var import_node_fs53 = require("node:fs");
33062
+ var import_node_fs54 = require("node:fs");
33048
33063
 
33049
33064
  // src/lib/project-skills.ts
33050
- var import_node_fs52 = require("node:fs");
33051
- var import_node_path39 = require("node:path");
33065
+ var import_node_fs53 = require("node:fs");
33066
+ var import_node_path40 = require("node:path");
33052
33067
  var PROJECT_SKILL_NAMES = [
33053
33068
  "verity-setup",
33054
33069
  "verity-analyze",
@@ -33074,14 +33089,14 @@ var LEGACY_SKILL_NAMES = [
33074
33089
  var ALL = [...PROJECT_SKILL_NAMES, ...LEGACY_SKILL_NAMES];
33075
33090
  function staleProjectSkills() {
33076
33091
  const root = projectPath(".claude/skills");
33077
- if (!(0, import_node_fs52.existsSync)(root)) return [];
33078
- return ALL.filter((name2) => (0, import_node_fs52.existsSync)((0, import_node_path39.join)(root, name2)));
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)));
33079
33094
  }
33080
33095
  function removeProjectSkills() {
33081
33096
  const root = projectPath(".claude/skills");
33082
33097
  const removed = [];
33083
33098
  for (const name2 of staleProjectSkills()) {
33084
- (0, import_node_fs52.rmSync)((0, import_node_path39.join)(root, name2), { recursive: true, force: true });
33099
+ (0, import_node_fs53.rmSync)((0, import_node_path40.join)(root, name2), { recursive: true, force: true });
33085
33100
  removed.push(name2);
33086
33101
  }
33087
33102
  return removed;
@@ -33146,13 +33161,13 @@ function registerBaselineCommands(program2) {
33146
33161
  let memoryMsg = null;
33147
33162
  let memoryAgentLine = null;
33148
33163
  const memoryNotice = projectPath(`${VERITY_DIR}/.memory-fence-notice`);
33149
- if (realStart && !(0, import_node_fs53.existsSync)(memoryNotice)) {
33164
+ if (realStart && !(0, import_node_fs54.existsSync)(memoryNotice)) {
33150
33165
  const trackedGraph = memoryOptOut() ? 0 : committedMemoryFiles().length;
33151
33166
  if (trackedGraph > 0) {
33152
33167
  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.`;
33153
33168
  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.`;
33154
33169
  try {
33155
- (0, import_node_fs53.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33170
+ (0, import_node_fs54.writeFileSync)(memoryNotice, (/* @__PURE__ */ new Date()).toISOString() + "\n");
33156
33171
  } catch {
33157
33172
  }
33158
33173
  }
@@ -33253,7 +33268,7 @@ function hookSource(value) {
33253
33268
  }
33254
33269
 
33255
33270
  // src/commands/review.ts
33256
- var import_node_fs54 = require("node:fs");
33271
+ var import_node_fs55 = require("node:fs");
33257
33272
  function registerReviewCommand(program2) {
33258
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) => {
33259
33274
  const globals = program2.opts();
@@ -33270,7 +33285,7 @@ async function runReview(opts, globals) {
33270
33285
  const changedFiles = opts.changed ? opts.changed.split(",").map((f) => f.trim()).filter(Boolean) : allFiles;
33271
33286
  const analyzable = filterAnalyzable(allFiles);
33272
33287
  const securityFiles = filterSecurity(allFiles);
33273
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs54.existsSync)(f) || resolveFile(f) !== null);
33288
+ const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).filter((f) => (0, import_node_fs55.existsSync)(f) || resolveFile(f) !== null);
33274
33289
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
33275
33290
  const codeDelta = collectCodeDelta(allFiles);
33276
33291
  const tokenResult = await resolveToken(globals.token);
@@ -33336,8 +33351,8 @@ async function runReview(opts, globals) {
33336
33351
  }
33337
33352
 
33338
33353
  // src/commands/guard.ts
33339
- var import_node_fs58 = require("node:fs");
33340
- var import_node_path44 = require("node:path");
33354
+ var import_node_fs59 = require("node:fs");
33355
+ var import_node_path45 = require("node:path");
33341
33356
 
33342
33357
  // src/lib/terminal-text.ts
33343
33358
  var CONTROL = /[\x00-\x08\x0b-\x1f\x7f-\x9f\u061c\u200e\u200f\u2028-\u202e\u2066-\u2069]/g;
@@ -33445,7 +33460,7 @@ async function runAgentReview(options) {
33445
33460
  }
33446
33461
 
33447
33462
  // src/lib/prove/auto.ts
33448
- var import_node_path43 = require("node:path");
33463
+ var import_node_path44 = require("node:path");
33449
33464
  var import_node_crypto18 = require("node:crypto");
33450
33465
 
33451
33466
  // src/lib/prove/signals.ts
@@ -33854,6 +33869,11 @@ async function rankViaServer(candidates2, ctx, auth2) {
33854
33869
  cmd: "prove-rank"
33855
33870
  });
33856
33871
  if (!res.ok) return { ok: false, ranker: "luna", error: res.error, ranked: fallback };
33872
+ const off = res.data;
33873
+ if (off?.enabled === false) {
33874
+ const why = typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled";
33875
+ return { ok: false, ranker: "luna", error: `formal is off for this project (${why})`, ranked: fallback, disabled: why };
33876
+ }
33857
33877
  const items = Array.isArray(res.data?.items) ? res.data.items : [];
33858
33878
  return { ok: true, ranker: "luna", ranked: applyAnnotations(candidates2, items), costUsd: typeof res.data?.cost_usd === "number" ? res.data.cost_usd : null };
33859
33879
  }
@@ -34578,6 +34598,8 @@ async function generateModel(target, opts) {
34578
34598
  });
34579
34599
  if (!res.ok) return { ok: false, error: res.error };
34580
34600
  const d = res.data ?? {};
34601
+ const off = d;
34602
+ if (off.enabled === false) return { ok: false, error: `formal is off for this project (${typeof off.reason === "string" ? off.reason.slice(0, 40) : "disabled"})` };
34581
34603
  if (d.error && typeof d.error === "object") return { ok: false, error: `${d.error.code ?? "SERVICE_ERROR"}: ${d.error.message ?? "the service failed"}` };
34582
34604
  const usage2 = d.usage && typeof d.usage === "object" ? { inputTokens: Number(d.usage.inputTokens ?? 0), outputTokens: Number(d.usage.outputTokens ?? 0) } : null;
34583
34605
  return acceptAnswer(d, usage2, typeof d.cost_usd === "number" ? d.cost_usd : null);
@@ -34757,8 +34779,7 @@ Rules:
34757
34779
  5. Write the harness as ONE file and run it in the SAME shell call that writes it (a heredoc followed by the run). TypeScript: node --experimental-strip-types harness.ts (detect runtimes only if that fails: node --version, python3 --version); if strip-types is unavailable, remove type annotations ONLY on lines that are not part of the function under test's logic, and say so. Python: python3 harness.py.
34758
34780
  6. Nothing you run can reach the network. Do not try.
34759
34781
  7. Keep it under about eight shell calls. Output tokens are time.
34760
- 8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters), impact (one word, below).
34761
- 9. impact \u2014 AFTER the verdict, and never a reason to change it: what the violation you ran costs a user of this code, the most serious one the run showed. money: a balance, charge, refund, price or stock is wrong. access: someone gets access they should not have, or an auth check is bypassed. data: a user's records are lost, corrupted or wrongly duplicated. external: an effect outside the system happens twice or never (a charge, an email, a shipment, a webhook). count: a counter, metric or statistic is off. cache: a cached or derived value is stale until it refreshes. internal: the program's own bookkeeping is off, with no effect a user would see. none: the verdict is not reproduced.
34782
+ 8. Answer with the JSON object only: verdict (reproduced | diverged | unreplayable), reason (2-4 sentences: what you ran, what the real code did, and how that compares to the trace's final state), harness_files (every file you wrote: path and its line count \u2014 do NOT paste contents, your shell calls already carry them), executed_output (the last relevant stdout, at most 2000 characters).
34762
34783
 
34763
34784
  "reproduced" means the real code, driven by the trace, reached the property violation the model describes. "diverged" means it did not \u2014 the model is wrong about the code, which is a useful answer. "unreplayable" means you could not run the real function faithfully; say why.`;
34764
34785
  var REPLAY_SCHEMA = {
@@ -34776,10 +34797,9 @@ var REPLAY_SCHEMA = {
34776
34797
  required: ["path", "lines"]
34777
34798
  }
34778
34799
  },
34779
- executed_output: { type: "string" },
34780
- impact: { type: "string", enum: ["money", "access", "data", "external", "count", "cache", "internal", "none"] }
34800
+ executed_output: { type: "string" }
34781
34801
  },
34782
- required: ["verdict", "reason", "harness_files", "executed_output", "impact"]
34802
+ required: ["verdict", "reason", "harness_files", "executed_output"]
34783
34803
  };
34784
34804
  function renderBriefInput(brief) {
34785
34805
  const p = brief.property;
@@ -34806,8 +34826,6 @@ function renderBriefInput(brief) {
34806
34826
  }
34807
34827
  return parts2.join("\n");
34808
34828
  }
34809
- var IMPACTS = ["money", "access", "data", "external", "count", "cache", "internal", "none"];
34810
- var isImpact = (v) => typeof v === "string" && IMPACTS.includes(v);
34811
34829
  function stringsIn(value, out2 = [], depth = 0) {
34812
34830
  if (depth > 8) return out2;
34813
34831
  if (typeof value === "string") out2.push(value);
@@ -34849,8 +34867,7 @@ function parseReplayOutput(output) {
34849
34867
  verdict,
34850
34868
  reason: typeof o.reason === "string" ? o.reason.slice(0, 2e3) : "",
34851
34869
  harness_files: Array.isArray(o.harness_files) ? o.harness_files.filter((f) => typeof f.path === "string").map((f) => ({ path: String(f.path).slice(0, 200), lines: Number.isInteger(f.lines) ? f.lines : 0 })) : [],
34852
- executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : "",
34853
- impact: isImpact(o.impact) ? o.impact : "none"
34870
+ executed_output: typeof o.executed_output === "string" ? o.executed_output.slice(0, 2e3) : ""
34854
34871
  };
34855
34872
  }
34856
34873
  } catch {
@@ -34858,10 +34875,10 @@ function parseReplayOutput(output) {
34858
34875
  }
34859
34876
  return { claim, shellCalls, executedCalls, shellTexts, outputTexts };
34860
34877
  }
34861
- var RESULT_LINE = /REPLAY_RESULT=(reproduced|diverged)\b/;
34878
+ var RESULT_LINE = /REPLAY_RESULT=(reproduced|diverged)\b/g;
34862
34879
  function printedResult(outputTexts) {
34863
34880
  let last = null;
34864
- for (const t of outputTexts) for (const m of t.matchAll(new RegExp(RESULT_LINE.source, "g"))) last = m[1];
34881
+ for (const t of outputTexts) for (const m of t.matchAll(RESULT_LINE)) last = m[1];
34865
34882
  return last;
34866
34883
  }
34867
34884
  var RESULT_MISSING = "the harness never printed REPLAY_RESULT=reproduced on its own stdout \u2014 the verdict was the model's word, not the run's";
@@ -35051,7 +35068,6 @@ async function runReplayInContainer(brief, opts) {
35051
35068
  ...judged,
35052
35069
  executedCalls,
35053
35070
  shellCalls,
35054
- ...judged.verdict === "reproduced" && parsed.claim ? { impact: parsed.claim.impact } : {},
35055
35071
  executedOutput: parsed.claim?.executed_output ?? "",
35056
35072
  harnessFiles: parsed.claim?.harness_files ?? [],
35057
35073
  usage,
@@ -35098,6 +35114,11 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
35098
35114
  return { claimed: null, verdict: "unverified", reason: "", downgrade: res.error, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: res.error };
35099
35115
  }
35100
35116
  const d = res.data ?? {};
35117
+ if (d.enabled === false) {
35118
+ const why = d.reason;
35119
+ const msg = `formal is off for this project (${typeof why === "string" ? why.slice(0, 40) : "disabled"})`;
35120
+ return { claimed: null, verdict: "unverified", reason: "", downgrade: msg, executedCalls: 0, shellCalls: 0, verbatim: none, executedOutput: "", harnessFiles: [], usage: null, durationMs: Date.now() - started, containerId: null, error: msg };
35121
+ }
35101
35122
  if (d.error && typeof d.error === "object") {
35102
35123
  const e = d.error;
35103
35124
  const msg = `${e.code ?? "SERVICE_ERROR"}: ${e.message ?? "the service failed"}`;
@@ -35110,7 +35131,6 @@ async function runReplayViaServer(brief, auth2, budgetMs = 24e4) {
35110
35131
  verdict: verdict === "reproduced" || verdict === "diverged" || verdict === "unreplayable" ? verdict : "unverified",
35111
35132
  reason: typeof d.reason === "string" ? d.reason : "",
35112
35133
  downgrade: typeof d.downgrade === "string" ? d.downgrade : null,
35113
- ...isImpact(d.impact) ? { impact: d.impact } : {},
35114
35134
  executedCalls: Number(d.executed_calls ?? 0),
35115
35135
  shellCalls: Number(d.shell_calls ?? 0),
35116
35136
  verbatim: { covered: Number(v.covered ?? 0), total: Number(v.total ?? 0), ratio: Number(v.ratio ?? 0), basis: v.basis === "symbol" || v.basis === "file" ? v.basis : "none" },
@@ -35167,18 +35187,18 @@ function renderReplay(model, property, r) {
35167
35187
  // src/lib/prove/runner.ts
35168
35188
  var import_node_child_process15 = require("node:child_process");
35169
35189
  var import_node_os8 = require("node:os");
35170
- var import_node_fs57 = require("node:fs");
35190
+ var import_node_fs58 = require("node:fs");
35171
35191
  var import_node_os9 = require("node:os");
35172
- var import_node_path42 = require("node:path");
35192
+ var import_node_path43 = require("node:path");
35173
35193
 
35174
35194
  // src/lib/prove/scaffold.ts
35175
- var import_node_fs56 = require("node:fs");
35176
- var import_node_path41 = require("node:path");
35195
+ var import_node_fs57 = require("node:fs");
35196
+ var import_node_path42 = require("node:path");
35177
35197
 
35178
35198
  // src/lib/prove/safe-write.ts
35179
- var import_node_fs55 = require("node:fs");
35199
+ var import_node_fs56 = require("node:fs");
35180
35200
  var import_node_crypto14 = require("node:crypto");
35181
- var import_node_path40 = require("node:path");
35201
+ var import_node_path41 = require("node:path");
35182
35202
  var SafeWriteError = class extends Error {
35183
35203
  constructor(reason, path) {
35184
35204
  super(`refusing to write ${path}: ${reason}`);
@@ -35187,10 +35207,10 @@ var SafeWriteError = class extends Error {
35187
35207
  this.name = "SafeWriteError";
35188
35208
  }
35189
35209
  };
35190
- var FLAGS3 = import_node_fs55.constants;
35210
+ var FLAGS3 = import_node_fs56.constants;
35191
35211
  var NOFOLLOW2 = FLAGS3.O_NOFOLLOW ?? 0;
35192
35212
  function assertPlainRelative(rel) {
35193
- if (!rel || (0, import_node_path40.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35213
+ if (!rel || (0, import_node_path41.isAbsolute)(rel)) throw new SafeWriteError("bad-path", rel);
35194
35214
  for (const part of rel.split(/[\\/]/)) {
35195
35215
  if (part === ".." || part === "" || part === ".") throw new SafeWriteError("bad-path", rel);
35196
35216
  }
@@ -35199,34 +35219,34 @@ function ensureDirsNoFollow(root, rel) {
35199
35219
  const parts2 = rel.split(/[\\/]/);
35200
35220
  let cur = root;
35201
35221
  for (const part of parts2.slice(0, -1)) {
35202
- cur = (0, import_node_path40.join)(cur, part);
35222
+ cur = (0, import_node_path41.join)(cur, part);
35203
35223
  let st;
35204
35224
  try {
35205
- st = (0, import_node_fs55.lstatSync)(cur);
35225
+ st = (0, import_node_fs56.lstatSync)(cur);
35206
35226
  } catch {
35207
- (0, import_node_fs55.mkdirSync)(cur);
35227
+ (0, import_node_fs56.mkdirSync)(cur);
35208
35228
  continue;
35209
35229
  }
35210
35230
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", cur);
35211
35231
  if (!st.isDirectory()) throw new SafeWriteError("not-regular", cur);
35212
35232
  }
35213
- return (0, import_node_path40.join)(root, rel);
35233
+ return (0, import_node_path41.join)(root, rel);
35214
35234
  }
35215
35235
  function insideRoot(realRoot, realPath) {
35216
- return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path40.sep) ? realRoot : realRoot + import_node_path40.sep);
35236
+ return realPath === realRoot || realPath.startsWith(realRoot.endsWith(import_node_path41.sep) ? realRoot : realRoot + import_node_path41.sep);
35217
35237
  }
35218
35238
  function removeQuietly(path) {
35219
35239
  try {
35220
- (0, import_node_fs55.unlinkSync)(path);
35240
+ (0, import_node_fs56.unlinkSync)(path);
35221
35241
  } catch {
35222
35242
  }
35223
35243
  }
35224
35244
  function writeFileInRootNoFollow(root, rel, content) {
35225
35245
  assertPlainRelative(rel);
35226
35246
  const dest = ensureDirsNoFollow(root, rel);
35227
- const dir = (0, import_node_path40.dirname)(dest);
35247
+ const dir = (0, import_node_path41.dirname)(dest);
35228
35248
  try {
35229
- const st = (0, import_node_fs55.lstatSync)(dest);
35249
+ const st = (0, import_node_fs56.lstatSync)(dest);
35230
35250
  if (st.isSymbolicLink()) throw new SafeWriteError("symlink", dest);
35231
35251
  if (!st.isFile()) throw new SafeWriteError("not-regular", dest);
35232
35252
  } catch (err2) {
@@ -35234,41 +35254,41 @@ function writeFileInRootNoFollow(root, rel, content) {
35234
35254
  }
35235
35255
  let realRoot;
35236
35256
  try {
35237
- realRoot = (0, import_node_fs55.realpathSync)(root);
35257
+ realRoot = (0, import_node_fs56.realpathSync)(root);
35238
35258
  } catch {
35239
35259
  throw new SafeWriteError("unwritable", root);
35240
35260
  }
35241
- const tmp = (0, import_node_path40.join)(dir, `.${(0, import_node_path40.basename)(dest)}.${(0, import_node_crypto14.randomBytes)(6).toString("hex")}.tmp`);
35261
+ const tmp = (0, import_node_path41.join)(dir, `.${(0, import_node_path41.basename)(dest)}.${(0, import_node_crypto14.randomBytes)(6).toString("hex")}.tmp`);
35242
35262
  let fd;
35243
35263
  try {
35244
- fd = (0, import_node_fs55.openSync)(tmp, import_node_fs55.constants.O_WRONLY | import_node_fs55.constants.O_CREAT | import_node_fs55.constants.O_EXCL | NOFOLLOW2, 420);
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);
35245
35265
  } catch {
35246
35266
  throw new SafeWriteError("unwritable", tmp);
35247
35267
  }
35248
35268
  try {
35249
- const opened = (0, import_node_fs55.fstatSync)(fd, { bigint: true });
35269
+ const opened = (0, import_node_fs56.fstatSync)(fd, { bigint: true });
35250
35270
  let realTmp;
35251
35271
  try {
35252
- realTmp = (0, import_node_fs55.realpathSync)(tmp);
35272
+ realTmp = (0, import_node_fs56.realpathSync)(tmp);
35253
35273
  } catch {
35254
35274
  throw new SafeWriteError("escaped", tmp);
35255
35275
  }
35256
- const there = (0, import_node_fs55.lstatSync)(realTmp, { bigint: true });
35276
+ const there = (0, import_node_fs56.lstatSync)(realTmp, { bigint: true });
35257
35277
  if (!opened.isFile() || there.ino !== opened.ino || there.dev !== opened.dev || !insideRoot(realRoot, realTmp)) {
35258
35278
  throw new SafeWriteError("escaped", tmp);
35259
35279
  }
35260
35280
  const buf = Buffer.from(content, "utf-8");
35261
35281
  let off = 0;
35262
- while (off < buf.length) off += (0, import_node_fs55.writeSync)(fd, buf, off, buf.length - off);
35282
+ while (off < buf.length) off += (0, import_node_fs56.writeSync)(fd, buf, off, buf.length - off);
35263
35283
  } catch (err2) {
35264
- (0, import_node_fs55.closeSync)(fd);
35284
+ (0, import_node_fs56.closeSync)(fd);
35265
35285
  removeQuietly(tmp);
35266
35286
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", tmp);
35267
35287
  }
35268
- (0, import_node_fs55.closeSync)(fd);
35288
+ (0, import_node_fs56.closeSync)(fd);
35269
35289
  try {
35270
- if (!insideRoot(realRoot, (0, import_node_fs55.realpathSync)(dir)) || (0, import_node_fs55.lstatSync)(dir).isSymbolicLink()) throw new SafeWriteError("escaped", dir);
35271
- (0, import_node_fs55.renameSync)(tmp, dest);
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);
35272
35292
  } catch (err2) {
35273
35293
  removeQuietly(tmp);
35274
35294
  throw err2 instanceof SafeWriteError ? err2 : new SafeWriteError("unwritable", dest);
@@ -35282,9 +35302,9 @@ function pathHasNoLink(root, rel) {
35282
35302
  }
35283
35303
  let cur = root;
35284
35304
  for (const part of rel.split(/[\\/]/)) {
35285
- cur = cur + import_node_path40.sep + part;
35305
+ cur = cur + import_node_path41.sep + part;
35286
35306
  try {
35287
- if ((0, import_node_fs55.lstatSync)(cur).isSymbolicLink()) return false;
35307
+ if ((0, import_node_fs56.lstatSync)(cur).isSymbolicLink()) return false;
35288
35308
  } catch {
35289
35309
  return true;
35290
35310
  }
@@ -35594,20 +35614,20 @@ This directory is machine-local and gitignored (see ../.gitignore). Models are
35594
35614
  never committed; what reaches the team is the bug report and the fix.
35595
35615
  `;
35596
35616
  function scaffoldProofs(root) {
35597
- const proofsDir = (0, import_node_path41.join)(root, PROOFS_DIR);
35617
+ const proofsDir = (0, import_node_path42.join)(root, PROOFS_DIR);
35598
35618
  const written = [];
35599
35619
  const kept = [];
35600
35620
  for (const stray of ["lakefile.lean"]) {
35601
35621
  const rel = `${PROOFS_DIR}/${stray}`;
35602
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path41.join)(root, rel));
35622
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
35603
35623
  try {
35604
- (0, import_node_fs56.rmSync)((0, import_node_path41.join)(root, rel), { force: true });
35624
+ (0, import_node_fs57.rmSync)((0, import_node_path42.join)(root, rel), { force: true });
35605
35625
  } catch {
35606
35626
  }
35607
35627
  }
35608
35628
  for (const f of PROOFS_TEMPLATE_FILES) {
35609
35629
  const rel = `${PROOFS_DIR}/${f.path}`;
35610
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path41.join)(root, rel));
35630
+ if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path42.join)(root, rel));
35611
35631
  const current = readRegularFileInRoot(root, rel, 4 * 1024 * 1024);
35612
35632
  if (current.ok && current.content === f.content) {
35613
35633
  kept.push(rel);
@@ -35620,8 +35640,8 @@ function scaffoldProofs(root) {
35620
35640
  [`${PROOFS_DIR}/.gitignore`, LOCAL_GITIGNORE],
35621
35641
  [`${MODELS_DIR}/README.md`, MODELS_README]
35622
35642
  ]) {
35623
- if (!pathHasNoLink(root, rel)) throw new SafeWriteError("symlink", (0, import_node_path41.join)(root, rel));
35624
- if (existsNoFollow((0, import_node_path41.join)(root, rel))) {
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))) {
35625
35645
  kept.push(rel);
35626
35646
  continue;
35627
35647
  }
@@ -35632,7 +35652,7 @@ function scaffoldProofs(root) {
35632
35652
  }
35633
35653
  function existsNoFollow(abs) {
35634
35654
  try {
35635
- (0, import_node_fs56.lstatSync)(abs);
35655
+ (0, import_node_fs57.lstatSync)(abs);
35636
35656
  return true;
35637
35657
  } catch {
35638
35658
  return false;
@@ -35890,16 +35910,17 @@ function renderReport(r) {
35890
35910
 
35891
35911
  // src/lib/prove/runner.ts
35892
35912
  function verityLeanHome(env = process.env) {
35893
- return env.VERITY_LEAN_HOME ?? (0, import_node_path42.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
35913
+ return env.VERITY_LEAN_HOME ?? (0, import_node_path43.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".verity", "lean");
35894
35914
  }
35895
35915
  function findToolchain(env = process.env) {
35896
- const managedBin = (0, import_node_path42.join)(verityLeanHome(env), LEAN_TOOLCHAIN.replace(/^leanprover\/lean4:/, ""), "bin");
35897
- const elanBin = (0, import_node_path42.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "bin");
35898
- const path = [managedBin, elanBin, env.PATH ?? ""].filter(Boolean).join(import_node_path42.delimiter);
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);
35899
35921
  const merged = { ...env, PATH: path, ELAN_TOOLCHAIN: env.ELAN_TOOLCHAIN ?? LEAN_TOOLCHAIN };
35900
- const elanHas = (0, import_node_fs57.existsSync)((0, import_node_path42.join)(env.HOME ?? (0, import_node_os9.homedir)(), ".elan", "toolchains", LEAN_TOOLCHAIN.replace("/", "--").replace(":", "---")));
35901
35922
  const exe = process.platform === "win32" ? "lake.exe" : "lake";
35902
- const candidates2 = [(0, import_node_path42.join)(managedBin, exe), ...elanHas ? [(0, import_node_path42.join)(elanBin, exe)] : [], exe];
35923
+ const candidates2 = [(0, import_node_path43.join)(managedBin, exe), ...elanHas ? [(0, import_node_path43.join)(elanBin, exe)] : [], exe];
35903
35924
  for (const candidate of candidates2) {
35904
35925
  try {
35905
35926
  (0, import_node_child_process15.execFileSync)(candidate, ["--version"], { env: merged, stdio: ["ignore", "pipe", "pipe"], timeout: 1e4 });
@@ -35974,53 +35995,80 @@ function runAsync(tc, cwd, args2, timeoutMs) {
35974
35995
  }
35975
35996
  var DEFAULT_BUILD_TIMEOUT_MS = 10 * 6e4;
35976
35997
  var DEFAULT_CHECK_TIMEOUT_MS = 12e4;
35998
+ function proofsWorkspaceProblem(root) {
35999
+ for (const rel of [".verity", PROOFS_DIR, `${PROOFS_DIR}/.lake`]) {
36000
+ let st;
36001
+ try {
36002
+ st = (0, import_node_fs58.lstatSync)((0, import_node_path43.join)(root, rel));
36003
+ } catch {
36004
+ break;
36005
+ }
36006
+ if (st.isSymbolicLink()) return `${rel} is a symlink; Lean is not run through it`;
36007
+ }
36008
+ const r = runGitSync(root, ["ls-files", "-z", "--", PROOFS_DIR], { timeoutMs: 5e3 });
36009
+ if (!r.ok) return `could not confirm with git that ${PROOFS_DIR} holds no committed files; Lean is not run`;
36010
+ const tracked = r.stdout.split("\0").filter(Boolean);
36011
+ if (tracked.length > 0) {
36012
+ return `${tracked.length} file(s) under ${PROOFS_DIR} are tracked in git (e.g. ${tracked[0]}); Lean is not run on a workspace the repository supplies \u2014 untrack them with: git rm -r --cached ${PROOFS_DIR}`;
36013
+ }
36014
+ return null;
36015
+ }
36016
+ function refused(problem) {
36017
+ return { ok: false, stdout: "", stderr: problem, durationMs: 0, timedOut: false };
36018
+ }
35977
36019
  function buildLibrary(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
35978
- return run2(tc, (0, import_node_path42.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36020
+ const problem = proofsWorkspaceProblem(root);
36021
+ if (problem) return refused(problem);
36022
+ return run2(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
35979
36023
  }
35980
- function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
35981
- return runAsync(tc, (0, import_node_path42.join)(root, PROOFS_DIR), ["build"], timeoutMs);
36024
+ async function buildLibraryAsync(tc, root, timeoutMs = DEFAULT_BUILD_TIMEOUT_MS) {
36025
+ const problem = proofsWorkspaceProblem(root);
36026
+ if (problem) return refused(problem);
36027
+ return runAsync(tc, (0, import_node_path43.join)(root, PROOFS_DIR), ["build"], timeoutMs);
35982
36028
  }
35983
36029
  function isModelInRoot(modelsAbs, rel) {
35984
- if (!rel.endsWith(".lean") || (0, import_node_path42.isAbsolute)(rel) || rel.startsWith("..")) return false;
36030
+ if (!rel.endsWith(".lean") || (0, import_node_path43.isAbsolute)(rel) || rel.startsWith("..")) return false;
35985
36031
  return statRegularInRoot(modelsAbs, rel).ok;
35986
36032
  }
35987
36033
  function resolveModelFile(root, arg) {
35988
- const modelsAbs = (0, import_node_path42.join)(root, MODELS_DIR);
35989
- const asPath = (0, import_node_path42.relative)(modelsAbs, (0, import_node_path42.isAbsolute)(arg) ? arg : (0, import_node_path42.resolve)(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));
35990
36036
  const candidates2 = arg.includes("/") || arg.includes("\\") ? [asPath] : [arg, `${arg}.lean`];
35991
36037
  for (const rel of candidates2) {
35992
- if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path42.join)(modelsAbs, rel);
36038
+ if (isModelInRoot(modelsAbs, rel)) return (0, import_node_path43.join)(modelsAbs, rel);
35993
36039
  }
35994
36040
  return null;
35995
36041
  }
35996
36042
  function listModelFiles(root) {
35997
- const modelsAbs = (0, import_node_path42.join)(root, MODELS_DIR);
35998
- if (!(0, import_node_fs57.existsSync)(modelsAbs)) return [];
35999
- return (0, import_node_fs57.readdirSync)(modelsAbs).filter((f) => isModelInRoot(modelsAbs, f)).sort().map((f) => (0, import_node_path42.join)(modelsAbs, f));
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));
36000
36046
  }
36001
36047
  function trimDiagnostics(text) {
36002
36048
  return text.split("\n").filter((l) => !l.startsWith("trace:")).join("\n").trim().slice(0, 4e3);
36003
36049
  }
36004
36050
  function checkModel(tc, root, modelFile, opts = {}) {
36005
- const proofsAbs = (0, import_node_path42.join)(root, PROOFS_DIR);
36006
- const rel = (0, import_node_path42.relative)(proofsAbs, modelFile);
36007
- const res = run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36051
+ const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
36052
+ const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
36053
+ const problem = proofsWorkspaceProblem(root);
36054
+ const res = problem ? refused(problem) : run2(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36008
36055
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36009
36056
  }
36010
36057
  async function checkModelAsync(tc, root, modelFile, opts = {}) {
36011
- const proofsAbs = (0, import_node_path42.join)(root, PROOFS_DIR);
36012
- const rel = (0, import_node_path42.relative)(proofsAbs, modelFile);
36013
- const res = await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36058
+ const proofsAbs = (0, import_node_path43.join)(root, PROOFS_DIR);
36059
+ const rel = (0, import_node_path43.relative)(proofsAbs, modelFile);
36060
+ const problem = proofsWorkspaceProblem(root);
36061
+ const res = problem ? refused(problem) : await runAsync(tc, proofsAbs, ["env", "lean", rel], opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36014
36062
  return toReport(res, root, modelFile, opts.timeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS);
36015
36063
  }
36016
36064
  function toReport(res, root, modelFile, timeoutMs) {
36017
36065
  const parsed = parseVerityLines(res.stdout);
36018
36066
  const combined = `${res.stdout}
36019
36067
  ${res.stderr}`;
36020
- const name2 = parsed.header?.model ?? (0, import_node_path42.basename)(modelFile, ".lean");
36068
+ const name2 = parsed.header?.model ?? (0, import_node_path43.basename)(modelFile, ".lean");
36021
36069
  const report = {
36022
36070
  model: name2,
36023
- file: (0, import_node_path42.relative)(root, modelFile),
36071
+ file: (0, import_node_path43.relative)(root, modelFile),
36024
36072
  ok: res.ok,
36025
36073
  header: parsed.header,
36026
36074
  properties: parsed.properties,
@@ -36065,33 +36113,18 @@ function writeResult(root, report) {
36065
36113
  function isCrashTrace(trace) {
36066
36114
  return trace.some((s) => /\b(crash\w*|kill\w*|restart\w*|interrupt\w*|power|abort\w*|process (dies|exit\w*)|lost (reply|response))\b/i.test(s));
36067
36115
  }
36068
- var SEVERITY_BY_IMPACT = {
36069
- money: "high",
36070
- access: "high",
36071
- data: "high",
36072
- external: "high",
36073
- count: "medium",
36074
- cache: "medium",
36075
- internal: "medium",
36076
- // A reproduced finding always has a real code; 'none' here is a malformed answer, so it blocks.
36077
- none: "high"
36078
- };
36079
- function formalSeverity(f) {
36080
- return f.impact && SEVERITY_BY_IMPACT[f.impact] || "high";
36081
- }
36082
36116
  function mergeFormalFindings(response, outcome, pushedFiles) {
36083
- if (!outcome) return { blocking: 0, warning: 0 };
36117
+ if (!outcome) return { blocking: 0 };
36084
36118
  const norm2 = (p) => p.replace(/\\/g, "/");
36085
36119
  const pushed = new Set(pushedFiles.map(norm2));
36086
- const reproduced = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
36087
- if (reproduced.length === 0) return { blocking: 0, warning: 0 };
36088
- const blocking = reproduced.filter((f) => formalSeverity(f) === "high");
36120
+ const blocking = outcome.findings.filter((f) => f.verdict === "reproduced" && !f.waived && pushed.has(norm2(f.file)));
36121
+ if (blocking.length === 0) return { blocking: 0 };
36089
36122
  const existing = Array.isArray(response.findings) ? response.findings : [];
36090
36123
  response.findings = [
36091
36124
  ...existing,
36092
- ...reproduced.map((f) => ({
36125
+ ...blocking.map((f) => ({
36093
36126
  pattern_id: "formal-counterexample",
36094
- severity: formalSeverity(f),
36127
+ severity: "high",
36095
36128
  scope: "change",
36096
36129
  file: f.file,
36097
36130
  line: outcome.target?.lines?.from ?? null,
@@ -36099,15 +36132,14 @@ function mergeFormalFindings(response, outcome, pushedFiles) {
36099
36132
  // as a title it read backwards (e2e, 2026-09-26). A trace that needs a
36100
36133
  // crash between two writes is labelled: reproducing it means injecting
36101
36134
  // the crash, so it is a crash-consistency finding, not a race.
36102
- title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code${f.impact && f.impact !== "none" ? ` (impact: ${f.impact})` : ""}`,
36135
+ title: `Formal: ${terminalText(f.symbol, 128)} breaks "${terminalText(f.desc, 280)}"${isCrashTrace(f.trace) ? " after a crash (crash consistency)" : ""} \u2014 reproduced on the real code`,
36103
36136
  description: terminalText(f.reason ?? "", 2e3),
36104
36137
  fix: { description: `Trace: ${terminalText(f.trace.join(" \u2192 ") || "(initial state)", 2e3)}. Replay: ${terminalText(f.reason ?? "reproduced in the container", 2e3)}` },
36105
36138
  source: "formal"
36106
36139
  }))
36107
36140
  ];
36108
- if (blocking.length > 0) response.gate_decision = "FAIL";
36109
- else if (response.gate_decision === "PASS" || response.gate_decision == null) response.gate_decision = "WARN";
36110
- return { blocking: blocking.length, warning: reproduced.length - blocking.length };
36141
+ if (response.gate_decision !== "FAIL") response.gate_decision = "FAIL";
36142
+ return { blocking: blocking.length };
36111
36143
  }
36112
36144
 
36113
36145
  // src/lib/prove/scalpel.ts
@@ -36274,20 +36306,28 @@ function isEligible(s, largePush) {
36274
36306
  function intersects(a, ranges) {
36275
36307
  return ranges.some((b) => a.from <= b.to && b.from <= a.to);
36276
36308
  }
36309
+ function isLocalState(root, rel) {
36310
+ return repoControlled(root, rel) === null;
36311
+ }
36312
+ function nonNegative(v) {
36313
+ return typeof v === "number" && Number.isFinite(v) && v > 0 ? v : 0;
36314
+ }
36277
36315
  function readLedger(root) {
36278
36316
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
36279
36317
  const empty = { day: today, models: 0, costUsd: 0 };
36318
+ if (!isLocalState(root, AUTO_LEDGER)) return empty;
36280
36319
  const read2 = readRegularFileInRoot(root, AUTO_LEDGER, 4096);
36281
36320
  if (!read2.ok) return empty;
36282
36321
  try {
36283
36322
  const o = JSON.parse(read2.content);
36284
36323
  if (o.day !== today || typeof o.models !== "number") return empty;
36285
- return { day: today, models: o.models, costUsd: typeof o.costUsd === "number" && Number.isFinite(o.costUsd) ? o.costUsd : 0 };
36324
+ return { day: today, models: nonNegative(o.models), costUsd: nonNegative(o.costUsd) };
36286
36325
  } catch {
36287
36326
  return empty;
36288
36327
  }
36289
36328
  }
36290
36329
  function writeLedger(root, l) {
36330
+ if (!isLocalState(root, AUTO_LEDGER)) return;
36291
36331
  try {
36292
36332
  writeFileInRootNoFollow(root, AUTO_LEDGER, JSON.stringify(l) + "\n");
36293
36333
  } catch {
@@ -36300,6 +36340,7 @@ function addLedgerCost(root, usd) {
36300
36340
  }
36301
36341
  var FINDINGS_FILE = `${PROOFS_DIR}/.results/.findings.json`;
36302
36342
  function readPersistedFindings(root) {
36343
+ if (!isLocalState(root, FINDINGS_FILE)) return [];
36303
36344
  const read2 = readRegularFileInRoot(root, FINDINGS_FILE, 256 * 1024);
36304
36345
  if (!read2.ok) return [];
36305
36346
  try {
@@ -36323,6 +36364,7 @@ function waiveFormalFindings(root, file, reason) {
36323
36364
  return n;
36324
36365
  }
36325
36366
  function writePersistedFindings(root, findings) {
36367
+ if (!isLocalState(root, FINDINGS_FILE)) return;
36326
36368
  try {
36327
36369
  writeFileInRootNoFollow(root, FINDINGS_FILE, JSON.stringify({ findings: findings.slice(0, 50) }, null, 2) + "\n");
36328
36370
  } catch {
@@ -36416,9 +36458,7 @@ async function runFormalPhase(input) {
36416
36458
  symbol: f.symbol,
36417
36459
  verdict: "reproduced",
36418
36460
  reason: f.waived ? `waived ${f.waived.at.slice(0, 10)}: ${f.waived.reason} (standing since ${f.at.slice(0, 10)}; the file has not changed)` : `${f.reason ?? "reproduced on the real code"} (standing since ${f.at.slice(0, 10)}; the file has not changed)`,
36419
- ...f.waived ? { waived: true } : {},
36420
- // A hand-edited file cannot invent a code: unknown values read as absent (HIGH).
36421
- ...isImpact(f.impact) ? { impact: f.impact } : {}
36461
+ ...f.waived ? { waived: true } : {}
36422
36462
  });
36423
36463
  }
36424
36464
  }
@@ -36457,6 +36497,7 @@ async function runFormalPhase(input) {
36457
36497
  return done({ status: "skipped", skip: "not-eligible", detail: `${best.file}: ${isEligible(best, largePush).why}` });
36458
36498
  }
36459
36499
  const ranked = await deps.rank(eligible, root, input.changedLines);
36500
+ if (!ranked.ok && ranked.disabled) return done({ status: "skipped", skip: "disabled-by-server", detail: ranked.error });
36460
36501
  if (ranked.ok) spend(ranked);
36461
36502
  candidates2 = ranked.ranked.slice(0, 5).map((c) => ({ file: c.file, symbol: c.ai?.symbol ?? null, score: c.ai?.score ?? null, criteria: c.ai?.criteria ?? null, reasked: !!c.ai?.reasked, reasons: (c.ai?.reasons ?? []).map((r) => r.slice(0, 200)) }));
36462
36503
  if (cancelled()) return done({ status: "skipped", skip: "deadline", detail: "cut off after ranking" });
@@ -36597,7 +36638,7 @@ async function runFormalPhase(input) {
36597
36638
  modelName = gen.name;
36598
36639
  const rel = `${AUTO_MODELS_DIR}/${gen.name}.lean`;
36599
36640
  writeFileInRootNoFollow(root, rel, gen.source);
36600
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path43.join)(root, rel);
36641
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
36601
36642
  progress.model = { name: gen.name, file: rel, rounds: round };
36602
36643
  progress.step = "check";
36603
36644
  report = await deps.check(root, abs);
@@ -36691,7 +36732,7 @@ async function runFormalPhase(input) {
36691
36732
  continue;
36692
36733
  }
36693
36734
  const verdict = r.verdict === "reproduced" ? "reproduced" : r.verdict === "diverged" ? "diverged" : r.verdict === "unreplayable" ? "model-only" : "unverified";
36694
- findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0, ...verdict === "reproduced" && r.impact ? { impact: r.impact } : {} });
36735
+ findings.push({ ...baseOf(p), verdict, reason: r.reason || r.downgrade || void 0 });
36695
36736
  }
36696
36737
  const reproduced = findings.filter((f) => f.verdict === "reproduced");
36697
36738
  if (reproduced.length > 0 && !cancelled()) {
@@ -36699,7 +36740,7 @@ async function runFormalPhase(input) {
36699
36740
  const others = readPersistedFindings(root).filter((f) => f.file !== top.file);
36700
36741
  writePersistedFindings(root, [
36701
36742
  ...others,
36702
- ...reproduced.map((f) => ({ file: f.file, symbol: f.symbol, sha256: sha2562, property: f.property, desc: f.desc, kind: f.kind, trace: f.trace, model: modelName, reason: f.reason, ...f.impact ? { impact: f.impact } : {}, ...lines ? { lines } : {}, at: now }))
36743
+ ...reproduced.map((f) => ({ file: f.file, symbol: f.symbol, sha256: sha2562, property: f.property, desc: f.desc, kind: f.kind, trace: f.trace, model: modelName, reason: f.reason, ...lines ? { lines } : {}, at: now }))
36703
36744
  ]);
36704
36745
  }
36705
36746
  const clean2 = findings.every((f) => f.verdict === "diverged");
@@ -36719,7 +36760,7 @@ async function runFormalPhase(input) {
36719
36760
  return done({
36720
36761
  status: "checked",
36721
36762
  target,
36722
- model: { name: modelName, file: (0, import_node_path43.relative)(root, (0, import_node_path43.join)(root, modelFile)), rounds },
36763
+ model: { name: modelName, file: (0, import_node_path44.relative)(root, (0, import_node_path44.join)(root, modelFile)), rounds },
36723
36764
  properties: report.properties,
36724
36765
  findings
36725
36766
  });
@@ -36782,7 +36823,7 @@ async function generateAndCheck(root, req, opts) {
36782
36823
  }
36783
36824
  const rel = `${dir}/${gen.name}.lean`;
36784
36825
  writeFileInRootNoFollow(root, rel, gen.source);
36785
- const abs = resolveModelFile(root, rel) ?? (0, import_node_path43.join)(root, rel);
36826
+ const abs = resolveModelFile(root, rel) ?? (0, import_node_path44.join)(root, rel);
36786
36827
  const report = await opts.deps.check(root, abs);
36787
36828
  const abstracts = report.header?.abstracts ?? [];
36788
36829
  const stray = abstracts.find((a) => !headerFiles.has(a.file)) ?? (abstracts[0] && abstracts[0].file !== req.file ? abstracts[0] : void 0);
@@ -36820,6 +36861,8 @@ async function prepareFormalPhase(root, env = process.env, auth2, readSource, co
36820
36861
  const apiKey = direct ? env.OPENAI_API_KEY : void 0;
36821
36862
  const toolchain = findToolchain(env);
36822
36863
  if (!toolchain) return { ok: false, skip: "no-toolchain" };
36864
+ const untrusted = proofsWorkspaceProblem(root);
36865
+ if (untrusted) return { ok: false, skip: "workspace-untrusted", detail: untrusted.slice(0, 200) };
36823
36866
  try {
36824
36867
  scaffoldProofs(root);
36825
36868
  } catch (err2) {
@@ -36909,7 +36952,7 @@ var EXCERPT_SOURCE_MAX_BYTES = 2 * 1024 * 1024;
36909
36952
  var WRITERS_BUDGET_MS = 1500;
36910
36953
  var EXCERPT_MAX_LINES2 = 30;
36911
36954
  var GUARD_BLOCK_CAP = 2;
36912
- var GUARD_ITER_FILE = (0, import_node_path44.join)(VERITY_DIR, ".guard-iteration");
36955
+ var GUARD_ITER_FILE = (0, import_node_path45.join)(VERITY_DIR, ".guard-iteration");
36913
36956
  function readPreToolUseStdin() {
36914
36957
  const empty = { command: "", cwd: null, sessionId: null };
36915
36958
  return new Promise((resolve8) => {
@@ -36954,7 +36997,7 @@ function readPreToolUseStdin() {
36954
36997
  }
36955
36998
  function readIterMap() {
36956
36999
  try {
36957
- const raw = JSON.parse((0, import_node_fs58.readFileSync)(GUARD_ITER_FILE, "utf-8"));
37000
+ const raw = JSON.parse((0, import_node_fs59.readFileSync)(GUARD_ITER_FILE, "utf-8"));
36958
37001
  if (raw && typeof raw === "object") {
36959
37002
  if (typeof raw.moment === "string" && typeof raw.count === "number") {
36960
37003
  return { [raw.moment]: raw.count };
@@ -36974,10 +37017,10 @@ function readIter(moment) {
36974
37017
  }
36975
37018
  function writeIter(moment, count) {
36976
37019
  try {
36977
- (0, import_node_fs58.mkdirSync)(VERITY_DIR, { recursive: true });
37020
+ (0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
36978
37021
  const map = readIterMap();
36979
37022
  map[moment] = count;
36980
- (0, import_node_fs58.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37023
+ (0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
36981
37024
  } catch {
36982
37025
  }
36983
37026
  }
@@ -36987,10 +37030,10 @@ function resetIter(moment) {
36987
37030
  if (!(moment in map)) return;
36988
37031
  delete map[moment];
36989
37032
  if (Object.keys(map).length === 0) {
36990
- if ((0, import_node_fs58.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs58.unlinkSync)(GUARD_ITER_FILE);
37033
+ if ((0, import_node_fs59.existsSync)(GUARD_ITER_FILE)) (0, import_node_fs59.unlinkSync)(GUARD_ITER_FILE);
36991
37034
  } else {
36992
- (0, import_node_fs58.mkdirSync)(VERITY_DIR, { recursive: true });
36993
- (0, import_node_fs58.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
37035
+ (0, import_node_fs59.mkdirSync)(VERITY_DIR, { recursive: true });
37036
+ (0, import_node_fs59.writeFileSync)(GUARD_ITER_FILE, JSON.stringify(map));
36994
37037
  }
36995
37038
  } catch {
36996
37039
  }
@@ -37060,7 +37103,7 @@ function hasBlockingFinding(response, sentFiles) {
37060
37103
  function buildGuardRequest(moment, files, codeDelta, iter, sessionId, statedIntent, coverageTelemetry) {
37061
37104
  const analyzable = filterAnalyzable(files);
37062
37105
  const securityFiles = filterSecurity(files);
37063
- const scannable = Array.from(/* @__PURE__ */ new Set([...analyzable, ...securityFiles])).map((f) => (0, import_node_fs58.existsSync)(f) ? f : resolveFile(f)).filter((f) => f !== null);
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);
37064
37107
  const staticResults = runCodacyAnalysisIfAvailable(scannable);
37065
37108
  const trigger = moment === "pre-commit" ? "hook:pre-commit" : "hook:pre-push";
37066
37109
  const requestBody = {
@@ -37437,8 +37480,6 @@ async function runGuard(opts, globals) {
37437
37480
  rounds: formalOutcome.model?.rounds ?? null,
37438
37481
  properties: formalOutcome.properties?.map((p) => `${p.id}:${p.result}`) ?? [],
37439
37482
  findings: formalOutcome.findings.map((f) => `${f.property}:${f.verdict}`),
37440
- // Decision 82: the replay's impact code per reproduced finding; count/cache/internal warn, the rest block.
37441
- impacts: formalOutcome.findings.filter((f) => f.impact).map((f) => `${f.property}:${f.impact}`),
37442
37483
  // Decision 81: what each property rests on (a rule, or "line"), what was
37443
37484
  // sent back or dropped as ungrounded, and which counterexamples lack their
37444
37485
  // property's trigger (shadow). Ids and rule names only, never code.
@@ -37680,7 +37721,7 @@ function registerIgnoreCommand(program2) {
37680
37721
 
37681
37722
  // src/commands/waive.ts
37682
37723
  var import_node_crypto19 = require("node:crypto");
37683
- var import_node_fs59 = require("node:fs");
37724
+ var import_node_fs60 = require("node:fs");
37684
37725
  function registerWaiveCommand(program2) {
37685
37726
  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) => {
37686
37727
  const globals = program2.opts();
@@ -37709,7 +37750,7 @@ function registerWaiveCommand(program2) {
37709
37750
  if (opts.file) {
37710
37751
  body2.file = opts.file;
37711
37752
  try {
37712
- body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0, import_node_fs59.readFileSync)(opts.file)).digest("hex");
37753
+ body2.file_sha256 = (0, import_node_crypto19.createHash)("sha256").update((0, import_node_fs60.readFileSync)(opts.file)).digest("hex");
37713
37754
  } catch {
37714
37755
  printError(`Cannot read ${opts.file} \u2014 run from the repo root, or omit --file to waive by pattern.`);
37715
37756
  process.exit(1);
@@ -37734,10 +37775,10 @@ function registerWaiveCommand(program2) {
37734
37775
  }
37735
37776
 
37736
37777
  // src/commands/init.ts
37737
- var import_node_fs64 = require("node:fs");
37778
+ var import_node_fs65 = require("node:fs");
37738
37779
  var import_promises20 = require("node:fs/promises");
37739
37780
  var import_yaml6 = __toESM2(require_dist());
37740
- var import_node_path48 = require("node:path");
37781
+ var import_node_path49 = require("node:path");
37741
37782
  var import_node_child_process19 = require("node:child_process");
37742
37783
 
37743
37784
  // src/lib/banner.ts
@@ -37816,7 +37857,7 @@ function printPhase(n, of, title, subtitle) {
37816
37857
  }
37817
37858
 
37818
37859
  // src/commands/doctor.ts
37819
- var import_node_fs60 = require("node:fs");
37860
+ var import_node_fs61 = require("node:fs");
37820
37861
 
37821
37862
  // src/lib/prereqs.ts
37822
37863
  var import_node_child_process16 = require("node:child_process");
@@ -38024,11 +38065,11 @@ async function buildReport() {
38024
38065
  const hooks = wiring.status;
38025
38066
  const provenance = cliProvenance();
38026
38067
  const telemetry = await checkTelemetry();
38027
- const hasConfig = (0, import_node_fs60.existsSync)(projectPath(CODACY_CONFIG_FILE));
38068
+ const hasConfig = (0, import_node_fs61.existsSync)(projectPath(CODACY_CONFIG_FILE));
38028
38069
  const artifacts = {
38029
- standard: (0, import_node_fs60.existsSync)(projectPath(STANDARD_FILE)),
38070
+ standard: (0, import_node_fs61.existsSync)(projectPath(STANDARD_FILE)),
38030
38071
  analysisConfig: hasConfig,
38031
- verityMd: (0, import_node_fs60.existsSync)(projectPath(VERITY_MD_FILE)),
38072
+ verityMd: (0, import_node_fs61.existsSync)(projectPath(VERITY_MD_FILE)),
38032
38073
  analysisConfigIds: hasConfig ? validatePatternIds().status : "absent"
38033
38074
  };
38034
38075
  const next = [];
@@ -38187,8 +38228,8 @@ function registerDoctorCommand(program2) {
38187
38228
  }
38188
38229
 
38189
38230
  // src/commands/migrate.ts
38190
- var import_node_fs61 = require("node:fs");
38191
- var import_node_path45 = require("node:path");
38231
+ var import_node_fs62 = require("node:fs");
38232
+ var import_node_path46 = require("node:path");
38192
38233
  var import_node_child_process17 = require("node:child_process");
38193
38234
  var LEGACY_NPM_PACKAGE = "@codacy/gate-cli";
38194
38235
  function defaultNpmRemover(pkg) {
@@ -38225,12 +38266,12 @@ async function runMigration(opts = {}) {
38225
38266
  return { actions, migrated: actions.length > 0 };
38226
38267
  }
38227
38268
  function migrateProjectDir(root, actions) {
38228
- const gateDir = (0, import_node_path45.join)(root, ".gate");
38229
- const verityDir = (0, import_node_path45.join)(root, ".verity");
38230
- if ((0, import_node_fs61.existsSync)(gateDir) && !(0, import_node_fs61.existsSync)(verityDir)) {
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)) {
38231
38272
  return migrateProjectDirRename(root, gateDir, verityDir, actions);
38232
38273
  }
38233
- if ((0, import_node_fs61.existsSync)(gateDir) && (0, import_node_fs61.existsSync)(verityDir)) {
38274
+ if ((0, import_node_fs62.existsSync)(gateDir) && (0, import_node_fs62.existsSync)(verityDir)) {
38234
38275
  return migrateProjectDirCarry(gateDir, verityDir, actions);
38235
38276
  }
38236
38277
  return false;
@@ -38251,13 +38292,13 @@ function migrateProjectDirRename(root, gateDir, verityDir, actions) {
38251
38292
  }
38252
38293
  }
38253
38294
  if (moved) {
38254
- if ((0, import_node_fs61.existsSync)(gateDir)) {
38295
+ if ((0, import_node_fs62.existsSync)(gateDir)) {
38255
38296
  const carried = carryLegacyContents(gateDir, verityDir);
38256
38297
  if (carried > 0) {
38257
38298
  actions.push(`Carried ${carried} untracked legacy file(s) from .gate/ into .verity/`);
38258
38299
  }
38259
38300
  try {
38260
- (0, import_node_fs61.rmSync)(gateDir, { recursive: true, force: true });
38301
+ (0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
38261
38302
  } catch {
38262
38303
  }
38263
38304
  }
@@ -38273,18 +38314,18 @@ function migrateProjectDirCarry(gateDir, verityDir, actions) {
38273
38314
  actions.push(`Carried ${carried} legacy file(s) from .gate/ into .verity/`);
38274
38315
  }
38275
38316
  try {
38276
- (0, import_node_fs61.rmSync)(gateDir, { recursive: true, force: true });
38317
+ (0, import_node_fs62.rmSync)(gateDir, { recursive: true, force: true });
38277
38318
  } catch {
38278
38319
  }
38279
38320
  return carried > 0;
38280
38321
  }
38281
38322
  function migrateGlobalCredentials(home, actions) {
38282
38323
  if (!home) return;
38283
- const gateCreds = (0, import_node_path45.join)(home, ".gate", "credentials");
38284
- const verityCreds = (0, import_node_path45.join)(home, ".verity", "credentials");
38285
- if (!(0, import_node_fs61.existsSync)(gateCreds)) return;
38286
- if (!(0, import_node_fs61.existsSync)(verityCreds)) {
38287
- (0, import_node_fs61.mkdirSync)((0, import_node_path45.join)(home, ".verity"), { recursive: true });
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 });
38288
38329
  moveFile(gateCreds, verityCreds);
38289
38330
  actions.push("Moved ~/.gate/credentials \u2192 ~/.verity/credentials");
38290
38331
  return;
@@ -38306,8 +38347,8 @@ async function migrateLegacyHooks(root, actions) {
38306
38347
  }
38307
38348
  }
38308
38349
  async function migrateClaudeMd(root, actions) {
38309
- const claudeMd = (0, import_node_path45.join)(root, "CLAUDE.md");
38310
- const hadLegacyBlock = (0, import_node_fs61.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38350
+ const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
38351
+ const hadLegacyBlock = (0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd));
38311
38352
  if (!hadLegacyBlock) return;
38312
38353
  try {
38313
38354
  await ensureClaudeMdPointer(root);
@@ -38317,9 +38358,9 @@ async function migrateClaudeMd(root, actions) {
38317
38358
  }
38318
38359
  }
38319
38360
  function migrateStandardFile(root, actions) {
38320
- const gateMd = (0, import_node_path45.join)(root, "GATE.md");
38321
- const verityMd = (0, import_node_path45.join)(root, "VERITY.md");
38322
- if (!(0, import_node_fs61.existsSync)(gateMd) || (0, import_node_fs61.existsSync)(verityMd)) return;
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;
38323
38364
  let moved = false;
38324
38365
  if (isGitRepo(root) && isGitTracked(root, "GATE.md")) {
38325
38366
  try {
@@ -38331,12 +38372,12 @@ function migrateStandardFile(root, actions) {
38331
38372
  if (!moved) moveFile(gateMd, verityMd);
38332
38373
  const content = readFileSyncSafe(verityMd);
38333
38374
  const refreshed = content.split("GATE.md").join("VERITY.md");
38334
- if (refreshed !== content) (0, import_node_fs61.writeFileSync)(verityMd, refreshed);
38375
+ if (refreshed !== content) (0, import_node_fs62.writeFileSync)(verityMd, refreshed);
38335
38376
  actions.push("Renamed GATE.md \u2192 VERITY.md");
38336
38377
  }
38337
38378
  async function migrateTelemetryHeaders(root, actions) {
38338
- const file = (0, import_node_path45.join)(root, ".claude", "settings.local.json");
38339
- if (!(0, import_node_fs61.existsSync)(file)) return;
38379
+ const file = (0, import_node_path46.join)(root, ".claude", "settings.local.json");
38380
+ if (!(0, import_node_fs62.existsSync)(file)) return;
38340
38381
  let settings;
38341
38382
  try {
38342
38383
  settings = JSON.parse(readFileSyncSafe(file) || "{}");
@@ -38384,14 +38425,14 @@ function mergeGlobalCredentials(gateCreds, verityCreds) {
38384
38425
  }
38385
38426
  if (toAppend.length > 0) {
38386
38427
  const sep5 = verityContent.endsWith("\n") || verityContent === "" ? "" : "\n";
38387
- (0, import_node_fs61.writeFileSync)(verityCreds, verityContent + sep5 + toAppend.join("\n") + "\n");
38428
+ (0, import_node_fs62.writeFileSync)(verityCreds, verityContent + sep5 + toAppend.join("\n") + "\n");
38388
38429
  }
38389
- (0, import_node_fs61.rmSync)(gateCreds, { force: true });
38430
+ (0, import_node_fs62.rmSync)(gateCreds, { force: true });
38390
38431
  return toAppend.length;
38391
38432
  }
38392
38433
  function readFileSyncSafe(path) {
38393
38434
  try {
38394
- return (0, import_node_fs61.readFileSync)(path, "utf-8");
38435
+ return (0, import_node_fs62.readFileSync)(path, "utf-8");
38395
38436
  } catch {
38396
38437
  return "";
38397
38438
  }
@@ -38406,35 +38447,35 @@ function hasStagedChanges(root) {
38406
38447
  }
38407
38448
  function moveDir(from, to) {
38408
38449
  try {
38409
- (0, import_node_fs61.renameSync)(from, to);
38450
+ (0, import_node_fs62.renameSync)(from, to);
38410
38451
  } catch (err2) {
38411
38452
  if (err2.code !== "EXDEV") throw err2;
38412
- (0, import_node_fs61.cpSync)(from, to, { recursive: true });
38413
- (0, import_node_fs61.rmSync)(from, { recursive: true, force: true });
38453
+ (0, import_node_fs62.cpSync)(from, to, { recursive: true });
38454
+ (0, import_node_fs62.rmSync)(from, { recursive: true, force: true });
38414
38455
  }
38415
38456
  }
38416
38457
  function moveFile(from, to) {
38417
38458
  try {
38418
- (0, import_node_fs61.renameSync)(from, to);
38459
+ (0, import_node_fs62.renameSync)(from, to);
38419
38460
  } catch (err2) {
38420
38461
  if (err2.code !== "EXDEV") throw err2;
38421
- (0, import_node_fs61.cpSync)(from, to);
38422
- (0, import_node_fs61.rmSync)(from, { force: true });
38462
+ (0, import_node_fs62.cpSync)(from, to);
38463
+ (0, import_node_fs62.rmSync)(from, { force: true });
38423
38464
  }
38424
38465
  }
38425
38466
  function carryLegacyContents(gateDir, verityDir) {
38426
38467
  let copied = 0;
38427
38468
  const walk2 = (relDir) => {
38428
- const srcDir = (0, import_node_path45.join)(gateDir, relDir);
38429
- for (const entry of (0, import_node_fs61.readdirSync)(srcDir)) {
38430
- const rel = relDir ? (0, import_node_path45.join)(relDir, entry) : entry;
38431
- const src = (0, import_node_path45.join)(gateDir, rel);
38432
- const dest = (0, import_node_path45.join)(verityDir, rel);
38433
- if ((0, import_node_fs61.statSync)(src).isDirectory()) {
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()) {
38434
38475
  walk2(rel);
38435
- } else if (!(0, import_node_fs61.existsSync)(dest)) {
38436
- (0, import_node_fs61.mkdirSync)((0, import_node_path45.dirname)(dest), { recursive: true });
38437
- (0, import_node_fs61.cpSync)(src, dest);
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);
38438
38479
  copied++;
38439
38480
  }
38440
38481
  }
@@ -38443,22 +38484,22 @@ function carryLegacyContents(gateDir, verityDir) {
38443
38484
  return copied;
38444
38485
  }
38445
38486
  async function needsMigration(root = repoRoot()) {
38446
- const gateDir = (0, import_node_path45.join)(root, ".gate");
38447
- const verityDir = (0, import_node_path45.join)(root, ".verity");
38448
- if ((0, import_node_fs61.existsSync)(gateDir) && !(0, import_node_fs61.existsSync)(verityDir)) return true;
38449
- if ((0, import_node_fs61.existsSync)(gateDir) && (0, import_node_fs61.existsSync)(verityDir)) {
38450
- if ((0, import_node_fs61.existsSync)((0, import_node_path45.join)(gateDir, "credentials")) && !(0, import_node_fs61.existsSync)((0, import_node_path45.join)(verityDir, "credentials"))) {
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"))) {
38451
38492
  return true;
38452
38493
  }
38453
- if ((0, import_node_fs61.existsSync)((0, import_node_path45.join)(gateDir, "memory")) && !(0, import_node_fs61.existsSync)((0, import_node_path45.join)(verityDir, "memory"))) {
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"))) {
38454
38495
  return true;
38455
38496
  }
38456
38497
  }
38457
- const claudeMd = (0, import_node_path45.join)(root, "CLAUDE.md");
38458
- if ((0, import_node_fs61.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38498
+ const claudeMd = (0, import_node_path46.join)(root, "CLAUDE.md");
38499
+ if ((0, import_node_fs62.existsSync)(claudeMd) && hasLegacyMemoryBlock(readFileSyncSafe(claudeMd))) {
38459
38500
  return true;
38460
38501
  }
38461
- if ((0, import_node_fs61.existsSync)((0, import_node_path45.join)(root, "GATE.md")) && !(0, import_node_fs61.existsSync)((0, import_node_path45.join)(root, "VERITY.md"))) {
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"))) {
38462
38503
  return true;
38463
38504
  }
38464
38505
  if (await hasLegacyHooksAt(root)) return true;
@@ -38739,15 +38780,31 @@ async function promptMultiSelect(question, choices, fallback) {
38739
38780
  }
38740
38781
 
38741
38782
  // src/lib/prove/lean-install.ts
38742
- var import_node_fs62 = require("node:fs");
38783
+ var import_node_fs63 = require("node:fs");
38743
38784
  var import_node_crypto20 = require("node:crypto");
38744
38785
  var import_node_child_process18 = require("node:child_process");
38745
38786
  var import_node_os10 = require("node:os");
38746
- var import_node_path46 = require("node:path");
38787
+ var import_node_path47 = require("node:path");
38747
38788
  var import_promises18 = require("node:stream/promises");
38748
38789
  var import_node_stream = require("node:stream");
38749
38790
  var RELEASES = "https://releases.lean-lang.org/lean4";
38750
38791
  var LEAN_DOWNLOAD_SIZE = "\u2248800 MB download, 2.7 GB on disk";
38792
+ var DOWNLOAD_STALL_MS = 6e4;
38793
+ var LEAN_DISK_NEEDED_BYTES = 3.75 * 1024 ** 3;
38794
+ function freeBytes(dir) {
38795
+ let d = dir;
38796
+ for (let i2 = 0; i2 < 64; i2++) {
38797
+ try {
38798
+ const st = (0, import_node_fs63.statfsSync)(d);
38799
+ return Number(st.bavail) * Number(st.bsize);
38800
+ } catch {
38801
+ const up = (0, import_node_path47.join)(d, "..");
38802
+ if (up === d) return null;
38803
+ d = up;
38804
+ }
38805
+ }
38806
+ return null;
38807
+ }
38751
38808
  var LEAN_ASSET_SHA256 = {
38752
38809
  "v4.34.0": {
38753
38810
  "lean-4.34.0-darwin.zip": "75a2a4b8e3d35680e8f51fae5a42c79702f463dd73ee1520fb61e5a9143e336c",
@@ -38763,7 +38820,7 @@ function expectedSha256(asset, version = pinnedVersion()) {
38763
38820
  function sha256File(path) {
38764
38821
  return new Promise((resolve8, reject) => {
38765
38822
  const hash = (0, import_node_crypto20.createHash)("sha256");
38766
- (0, import_node_fs62.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve8(hash.digest("hex"))).on("error", reject);
38823
+ (0, import_node_fs63.createReadStream)(path).on("data", (chunk) => hash.update(chunk)).on("end", () => resolve8(hash.digest("hex"))).on("error", reject);
38767
38824
  });
38768
38825
  }
38769
38826
  async function verifyDownload(zip, asset, version = pinnedVersion()) {
@@ -38783,7 +38840,7 @@ function leanAssetName(version = pinnedVersion()) {
38783
38840
  return suffix ? `lean-${v}-${suffix}.zip` : null;
38784
38841
  }
38785
38842
  function pinnedVersionDir(env = process.env) {
38786
- return (0, import_node_path46.join)(verityLeanHome(env), pinnedVersion());
38843
+ return (0, import_node_path47.join)(verityLeanHome(env), pinnedVersion());
38787
38844
  }
38788
38845
  function lakeBinary() {
38789
38846
  return (0, import_node_os10.platform)() === "win32" ? "lake.exe" : "lake";
@@ -38794,29 +38851,44 @@ function unzip(zip, dest) {
38794
38851
  for (const [cmd, args2] of attempts) {
38795
38852
  try {
38796
38853
  (0, import_node_child_process18.execFileSync)(cmd, args2, { stdio: ["ignore", "ignore", "pipe"], timeout: 15 * 6e4 });
38797
- if ((0, import_node_fs62.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
38854
+ if ((0, import_node_fs63.readdirSync)(dest).length > 0) return { ok: true, via: cmd };
38798
38855
  errors.push(`${cmd}: produced nothing`);
38799
38856
  } catch (err2) {
38800
38857
  errors.push(`${cmd}: ${String(err2.message).split("\n")[0].slice(0, 120)}`);
38801
38858
  try {
38802
- for (const e of (0, import_node_fs62.readdirSync)(dest)) (0, import_node_fs62.rmSync)((0, import_node_path46.join)(dest, e), { recursive: true, force: true });
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 });
38803
38860
  } catch {
38804
38861
  }
38805
38862
  }
38806
38863
  }
38807
38864
  return { ok: false, error: errors.join("; ") };
38808
38865
  }
38809
- async function download(url, dest, onProgress) {
38810
- const res = await fetch(url, { redirect: "follow" });
38811
- if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status}`);
38812
- const total = Number(res.headers.get("content-length")) || null;
38813
- let seen = 0;
38814
- const stream = import_node_stream.Readable.fromWeb(res.body);
38815
- stream.on("data", (chunk) => {
38816
- seen += chunk.length;
38817
- onProgress(seen, total);
38818
- });
38819
- await (0, import_promises18.pipeline)(stream, (0, import_node_fs62.createWriteStream)(dest));
38866
+ async function download(url, dest, onProgress, stallMs = DOWNLOAD_STALL_MS) {
38867
+ const ctrl = new AbortController();
38868
+ let timer;
38869
+ const arm = () => {
38870
+ clearTimeout(timer);
38871
+ timer = setTimeout(() => ctrl.abort(), stallMs);
38872
+ };
38873
+ arm();
38874
+ try {
38875
+ const res = await fetch(url, { redirect: "follow", signal: ctrl.signal });
38876
+ if (!res.ok || !res.body) throw new Error(`download failed: HTTP ${res.status}`);
38877
+ const total = Number(res.headers.get("content-length")) || null;
38878
+ let seen = 0;
38879
+ const stream = import_node_stream.Readable.fromWeb(res.body);
38880
+ stream.on("data", (chunk) => {
38881
+ arm();
38882
+ seen += chunk.length;
38883
+ onProgress(seen, total);
38884
+ });
38885
+ await (0, import_promises18.pipeline)(stream, (0, import_node_fs63.createWriteStream)(dest), { signal: ctrl.signal });
38886
+ } catch (err2) {
38887
+ if (ctrl.signal.aborted) throw new Error(`download stalled: nothing received for ${Math.round(stallMs / 1e3)} s`);
38888
+ throw err2;
38889
+ } finally {
38890
+ clearTimeout(timer);
38891
+ }
38820
38892
  }
38821
38893
  function inPlaceProgress(label2, write = (s) => process.stderr.write(s)) {
38822
38894
  let active = false;
@@ -38854,10 +38926,16 @@ async function installLean(opts = {}) {
38854
38926
  const dir = pinnedVersionDir(env);
38855
38927
  const url = `${RELEASES}/${pinnedVersion()}/${asset}`;
38856
38928
  const home = verityLeanHome(env);
38857
- const tmp = (0, import_node_path46.join)(home, ".tmp");
38858
- (0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
38859
- (0, import_node_fs62.mkdirSync)(tmp, { recursive: true });
38860
- const zip = (0, import_node_path46.join)(tmp, asset);
38929
+ const free = freeBytes(home);
38930
+ const needed = opts.minFreeBytes ?? LEAN_DISK_NEEDED_BYTES;
38931
+ if (free !== null && free < needed) {
38932
+ const gb = (n) => (n / 1024 ** 3).toFixed(1);
38933
+ return { ok: false, error: `not enough disk space for Lean: ${gb(free)} GB free where ${home} lives, needs about ${gb(needed)} GB` };
38934
+ }
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);
38861
38939
  say(`downloading ${url}`);
38862
38940
  let lastPct = -1;
38863
38941
  try {
@@ -38870,40 +38948,40 @@ async function installLean(opts = {}) {
38870
38948
  }
38871
38949
  });
38872
38950
  } catch (err2) {
38873
- (0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
38951
+ (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
38874
38952
  return { ok: false, error: err2.message };
38875
38953
  }
38876
38954
  say("verifying checksum");
38877
38955
  const verified = await verifyDownload(zip, asset);
38878
38956
  if (!verified.ok) {
38879
- (0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
38957
+ (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
38880
38958
  return { ok: false, error: verified.error };
38881
38959
  }
38882
38960
  say("unpacking (this takes a minute)");
38883
- const unpack = (0, import_node_path46.join)(tmp, "unpack");
38884
- (0, import_node_fs62.mkdirSync)(unpack);
38961
+ const unpack = (0, import_node_path47.join)(tmp, "unpack");
38962
+ (0, import_node_fs63.mkdirSync)(unpack);
38885
38963
  const unpacked = unzip(zip, unpack);
38886
38964
  if (!unpacked.ok) {
38887
- (0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
38965
+ (0, import_node_fs63.rmSync)(tmp, { recursive: true, force: true });
38888
38966
  return { ok: false, error: `unpack failed: ${unpacked.error}` };
38889
38967
  }
38890
- const entries = (0, import_node_fs62.readdirSync)(unpack);
38891
- const top = entries.length === 1 && (0, import_node_fs62.statSync)((0, import_node_path46.join)(unpack, entries[0])).isDirectory() ? (0, import_node_path46.join)(unpack, entries[0]) : unpack;
38892
- if (!(0, import_node_fs62.existsSync)((0, import_node_path46.join)(top, "bin", lakeBinary()))) {
38893
- (0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
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 });
38894
38972
  return { ok: false, error: "the archive did not contain bin/lake" };
38895
38973
  }
38896
- (0, import_node_fs62.rmSync)(dir, { recursive: true, force: true });
38897
- (0, import_node_fs62.mkdirSync)(home, { recursive: true });
38898
- (0, import_node_fs62.renameSync)(top, dir);
38899
- (0, import_node_fs62.rmSync)(tmp, { recursive: true, force: true });
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 });
38900
38978
  return { ok: true, dir };
38901
38979
  }
38902
38980
 
38903
38981
  // src/lib/remote-config.ts
38904
- var import_node_fs63 = require("node:fs");
38982
+ var import_node_fs64 = require("node:fs");
38905
38983
  var import_promises19 = require("node:fs/promises");
38906
- var import_node_path47 = require("node:path");
38984
+ var import_node_path48 = require("node:path");
38907
38985
  var import_yaml5 = __toESM2(require_dist());
38908
38986
  var IGNORE_RIDER = "verityignore";
38909
38987
  async function fetchRemoteSetup(opts) {
@@ -38948,7 +39026,7 @@ async function adoptRemoteSetup(found, opts) {
38948
39026
  written.push(STANDARD_FILE);
38949
39027
  if (rider !== null) {
38950
39028
  const localIgnore = projectPath(VERITYIGNORE_FILE);
38951
- if (!(0, import_node_fs63.existsSync)(localIgnore)) {
39029
+ if (!(0, import_node_fs64.existsSync)(localIgnore)) {
38952
39030
  await writeOut(VERITYIGNORE_FILE, rider);
38953
39031
  written.push(VERITYIGNORE_FILE);
38954
39032
  } else {
@@ -38981,7 +39059,7 @@ async function adoptRemoteSetup(found, opts) {
38981
39059
  }
38982
39060
  async function writeOut(relative6, body2) {
38983
39061
  const target = projectPath(relative6);
38984
- await (0, import_promises19.mkdir)((0, import_node_path47.dirname)(target), { recursive: true });
39062
+ await (0, import_promises19.mkdir)((0, import_node_path48.dirname)(target), { recursive: true });
38985
39063
  await (0, import_promises19.writeFile)(target, body2);
38986
39064
  }
38987
39065
  function describeRemote(found) {
@@ -39098,15 +39176,15 @@ async function runOptionalAuth(resolution, opts = {}) {
39098
39176
  }
39099
39177
  function resolveDataDir2() {
39100
39178
  const candidates2 = [
39101
- (0, import_node_path48.join)(__dirname, "..", "data"),
39179
+ (0, import_node_path49.join)(__dirname, "..", "data"),
39102
39180
  // installed: node_modules/@codacy/verity-cli/data
39103
- (0, import_node_path48.join)(__dirname, "..", "..", "data"),
39181
+ (0, import_node_path49.join)(__dirname, "..", "..", "data"),
39104
39182
  // edge case: nested resolution
39105
- (0, import_node_path48.join)(process.cwd(), "cli", "data")
39183
+ (0, import_node_path49.join)(process.cwd(), "cli", "data")
39106
39184
  // local dev: running from repo root
39107
39185
  ];
39108
39186
  for (const candidate of candidates2) {
39109
- if ((0, import_node_fs64.existsSync)((0, import_node_path48.join)(candidate, "skills"))) {
39187
+ if ((0, import_node_fs65.existsSync)((0, import_node_path49.join)(candidate, "skills"))) {
39110
39188
  return candidate;
39111
39189
  }
39112
39190
  }
@@ -39122,9 +39200,9 @@ async function skillIsCurrent(src, dest) {
39122
39200
  const list2 = (dir) => {
39123
39201
  const out2 = [];
39124
39202
  const walk2 = (d, prefix) => {
39125
- for (const e of (0, import_node_fs64.readdirSync)(d, { withFileTypes: true })) {
39203
+ for (const e of (0, import_node_fs65.readdirSync)(d, { withFileTypes: true })) {
39126
39204
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
39127
- if (e.isDirectory()) walk2((0, import_node_path48.join)(d, e.name), rel);
39205
+ if (e.isDirectory()) walk2((0, import_node_path49.join)(d, e.name), rel);
39128
39206
  else if (e.isFile()) out2.push(rel);
39129
39207
  }
39130
39208
  };
@@ -39135,8 +39213,8 @@ async function skillIsCurrent(src, dest) {
39135
39213
  const shipped = list2(src);
39136
39214
  if (JSON.stringify(shipped) !== JSON.stringify(list2(dest))) return false;
39137
39215
  for (const rel of shipped) {
39138
- const a = await (0, import_promises20.readFile)((0, import_node_path48.join)(src, rel), "utf-8");
39139
- const b = await (0, import_promises20.readFile)((0, import_node_path48.join)(dest, rel), "utf-8");
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");
39140
39218
  if (a !== b) return false;
39141
39219
  }
39142
39220
  return true;
@@ -39162,8 +39240,10 @@ var INTENSITY_CHOICES = [
39162
39240
  { id: "thorough", label: "thorough", hint: "all tools, all rules (~15s)" }
39163
39241
  ];
39164
39242
  var FORMAL_CHOICES = [
39165
- { id: "yes", label: "yes", hint: "a Lean model of the riskiest changed function; blocks only on a REPRODUCED counterexample", recommended: true },
39166
- { id: "no", label: "no", hint: "enable later with: verity config formal push" }
39243
+ { id: "yes", label: "yes", hint: "a Lean model of the riskiest changed function; blocks only on a REPRODUCED counterexample" },
39244
+ // No is the default (review of #255): "yes" downloads ≈800 MB and unpacks
39245
+ // 2.7 GB, and a bare Enter must never do that.
39246
+ { id: "no", label: "no", hint: "enable later with: verity config formal push", recommended: true }
39167
39247
  ];
39168
39248
  var MOMENT_CHOICES = [
39169
39249
  { id: "stop", label: "On stop", hint: "after every agent turn \u2014 fast feedback while you work", recommended: true },
@@ -39337,7 +39417,7 @@ async function synthesizeLocally(opts) {
39337
39417
  async function healStaleAnalysisConfig(globals) {
39338
39418
  const configPath = projectPath(CODACY_CONFIG_FILE);
39339
39419
  const standardPath = projectPath(STANDARD_FILE);
39340
- if (!(0, import_node_fs64.existsSync)(configPath) || !(0, import_node_fs64.existsSync)(standardPath)) return;
39420
+ if (!(0, import_node_fs65.existsSync)(configPath) || !(0, import_node_fs65.existsSync)(standardPath)) return;
39341
39421
  const validation = validatePatternIds();
39342
39422
  if (validation.status !== "invalid") return;
39343
39423
  printWarn(" Your analysis config names pattern ids that no longer resolve \u2014 those tools were");
@@ -39434,17 +39514,17 @@ async function handoffToSetup(enabled, claudeInstalled) {
39434
39514
  async function installSkills(force, step) {
39435
39515
  step("Installing skills");
39436
39516
  const dataDir = resolveDataDir2();
39437
- const skillsSource = (0, import_node_path48.join)(dataDir, "skills");
39517
+ const skillsSource = (0, import_node_path49.join)(dataDir, "skills");
39438
39518
  const skillsDest = ".claude/skills";
39439
39519
  let skillsInstalled = 0;
39440
39520
  for (const skill of SKILLS) {
39441
- const src = (0, import_node_path48.join)(skillsSource, skill);
39442
- const dest = (0, import_node_path48.join)(skillsDest, skill);
39443
- if (!(0, import_node_fs64.existsSync)(src)) {
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)) {
39444
39524
  printWarn(` Skill data not found: ${skill}`);
39445
39525
  continue;
39446
39526
  }
39447
- if ((0, import_node_fs64.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39527
+ if ((0, import_node_fs65.existsSync)(dest) && !force && await skillIsCurrent(src, dest)) {
39448
39528
  skillsInstalled++;
39449
39529
  continue;
39450
39530
  }
@@ -39569,16 +39649,20 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
39569
39649
  printWarn(` Formal verification: off \u2014 ${formalRefusalMessage(cfg.formal_refused)}`);
39570
39650
  return;
39571
39651
  }
39572
- const toolchain = findToolchain();
39573
39652
  if (cfg.formal === "push") {
39574
- if (toolchain) printInfo(" Formal verification at push \u2713");
39653
+ if (findToolchain()) printInfo(" Formal verification at push \u2713");
39575
39654
  else printWarn(" Formal verification is on but Lean is missing \u2014 run: verity lean install");
39576
39655
  return;
39577
39656
  }
39657
+ if (cfg.formal === "off") {
39658
+ printInfo(" Formal verification: off (enable with: verity config formal push)");
39659
+ return;
39660
+ }
39578
39661
  if (defaultsOnly || !interactive()) {
39579
39662
  printInfo(" Formal verification (a model-based bug finder at push): off \u2014 enable with: verity config formal push");
39580
39663
  return;
39581
39664
  }
39665
+ const toolchain = findToolchain();
39582
39666
  console.log("");
39583
39667
  console.log(" Formal verification review \u2014 a model-based bug finder for your riskiest code.");
39584
39668
  console.log(" At push, Verity picks the riskiest changed function, checks a small model of");
@@ -39586,9 +39670,10 @@ async function offerFormalVerification(defaultsOnly, pluginMode) {
39586
39670
  console.log(" Verity for that). Only a reproduced bug can block; most pushes get no model.");
39587
39671
  console.log(` Adds /verity-prove <worry> to check any code on demand.${toolchain ? "" : ` Needs to install Lean 4 (${LEAN_DOWNLOAD_SIZE}) on "yes".`}`);
39588
39672
  console.log("");
39589
- const wants = await promptChoice("Formal verification at push?", FORMAL_CHOICES, "yes");
39673
+ const wants = await promptChoice("Formal verification at push?", FORMAL_CHOICES, "no");
39590
39674
  if (wants === "yes" && pluginMode) printInfo(" Plugin: the push check works now; /verity:verity-prove arrives with the plugin's next release.");
39591
39675
  if (wants !== "yes") {
39676
+ writeProjectConfig({ formal: "off" });
39592
39677
  printInfo(" Formal verification: off (enable later with: verity config formal push)");
39593
39678
  return;
39594
39679
  }
@@ -39639,7 +39724,7 @@ function registerInitCommand(program2) {
39639
39724
  const staleMarker = clearStalePluginMarker();
39640
39725
  const pluginMode = opts.plugin === false ? false : opts.pluginMode ?? pluginActiveHere();
39641
39726
  const projectMarkers = [".git", "package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile", "pom.xml", "build.gradle"];
39642
- const isProject = projectMarkers.some((m) => (0, import_node_fs64.existsSync)(m));
39727
+ const isProject = projectMarkers.some((m) => (0, import_node_fs65.existsSync)(m));
39643
39728
  if (!isProject) {
39644
39729
  printError("No project detected in the current directory.");
39645
39730
  printInfo('Run "verity init" from your project root.');
@@ -39742,7 +39827,7 @@ function registerInitCommand(program2) {
39742
39827
  untrackMemory: opts.untrackMemory === true,
39743
39828
  untrackState: opts.untrackState === true
39744
39829
  });
39745
- const globalVerityDir = (0, import_node_path48.join)(process.env.HOME ?? "", ".verity");
39830
+ const globalVerityDir = (0, import_node_path49.join)(process.env.HOME ?? "", ".verity");
39746
39831
  await (0, import_promises20.mkdir)(globalVerityDir, { recursive: true });
39747
39832
  console.log("");
39748
39833
  step("Wiring Claude Code hooks");
@@ -39817,7 +39902,7 @@ function registerInitCommand(program2) {
39817
39902
  }
39818
39903
  step("Your project's Standard");
39819
39904
  let haveStandard = false;
39820
- if ((0, import_node_fs64.existsSync)(projectPath(STANDARD_FILE))) {
39905
+ if ((0, import_node_fs65.existsSync)(projectPath(STANDARD_FILE))) {
39821
39906
  printInfo(" This project already has .verity/standard.yaml \u2014 keeping it.");
39822
39907
  haveStandard = true;
39823
39908
  } else {
@@ -39847,7 +39932,7 @@ function registerInitCommand(program2) {
39847
39932
  ...telemetryChoice ? { telemetry: telemetryChoice } : {},
39848
39933
  init: {
39849
39934
  completed_at: (/* @__PURE__ */ new Date()).toISOString(),
39850
- cli_version: true ? "0.34.0-experimental.b9e8508" : "dev"
39935
+ cli_version: true ? "0.34.0-experimental.cc5f6ec" : "dev"
39851
39936
  }
39852
39937
  });
39853
39938
  } catch (err2) {
@@ -39897,8 +39982,8 @@ function registerInitCommand(program2) {
39897
39982
  }
39898
39983
 
39899
39984
  // src/commands/uninstall.ts
39900
- var import_node_fs65 = require("node:fs");
39901
- var import_node_path49 = require("node:path");
39985
+ var import_node_fs66 = require("node:fs");
39986
+ var import_node_path50 = require("node:path");
39902
39987
  function registerUninstallCommand(program2) {
39903
39988
  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) => {
39904
39989
  const dryRun = opts.dryRun ?? false;
@@ -39907,11 +39992,11 @@ function registerUninstallCommand(program2) {
39907
39992
  const actions = [];
39908
39993
  const skillsRoot = projectPath(".claude/skills");
39909
39994
  for (const name2 of PROJECT_SKILL_NAMES) {
39910
- const dir = (0, import_node_path49.join)(skillsRoot, name2);
39911
- if ((0, import_node_fs65.existsSync)(dir)) {
39995
+ const dir = (0, import_node_path50.join)(skillsRoot, name2);
39996
+ if ((0, import_node_fs66.existsSync)(dir)) {
39912
39997
  actions.push({
39913
39998
  label: `Remove .claude/skills/${name2}/`,
39914
- apply: () => (0, import_node_fs65.rmSync)(dir, { recursive: true, force: true })
39999
+ apply: () => (0, import_node_fs66.rmSync)(dir, { recursive: true, force: true })
39915
40000
  });
39916
40001
  }
39917
40002
  }
@@ -39925,24 +40010,24 @@ function registerUninstallCommand(program2) {
39925
40010
  });
39926
40011
  }
39927
40012
  const verityDir = projectPath(VERITY_DIR);
39928
- if ((0, import_node_fs65.existsSync)(verityDir)) {
40013
+ if ((0, import_node_fs66.existsSync)(verityDir)) {
39929
40014
  actions.push({
39930
40015
  label: `Remove ${VERITY_DIR}/`,
39931
- apply: () => (0, import_node_fs65.rmSync)(verityDir, { recursive: true, force: true })
40016
+ apply: () => (0, import_node_fs66.rmSync)(verityDir, { recursive: true, force: true })
39932
40017
  });
39933
40018
  }
39934
40019
  if (!keepVerityMd) {
39935
40020
  const verityMd = projectPath(VERITY_MD_FILE);
39936
- if ((0, import_node_fs65.existsSync)(verityMd)) {
40021
+ if ((0, import_node_fs66.existsSync)(verityMd)) {
39937
40022
  actions.push({
39938
40023
  label: `Remove ${VERITY_MD_FILE}`,
39939
- apply: () => (0, import_node_fs65.rmSync)(verityMd, { force: true })
40024
+ apply: () => (0, import_node_fs66.rmSync)(verityMd, { force: true })
39940
40025
  });
39941
40026
  }
39942
40027
  }
39943
40028
  const cleanupEmptyDir = (path) => {
39944
- if ((0, import_node_fs65.existsSync)(path) && (0, import_node_fs65.statSync)(path).isDirectory() && (0, import_node_fs65.readdirSync)(path).length === 0) {
39945
- (0, import_node_fs65.rmdirSync)(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);
39946
40031
  }
39947
40032
  };
39948
40033
  actions.push({
@@ -39953,11 +40038,11 @@ function registerUninstallCommand(program2) {
39953
40038
  }
39954
40039
  });
39955
40040
  const home = process.env.HOME ?? "";
39956
- const globalVerityDir = (0, import_node_path49.join)(home, ".verity");
39957
- if (purgeGlobal && (0, import_node_fs65.existsSync)(globalVerityDir)) {
40041
+ const globalVerityDir = (0, import_node_path50.join)(home, ".verity");
40042
+ if (purgeGlobal && (0, import_node_fs66.existsSync)(globalVerityDir)) {
39958
40043
  actions.push({
39959
40044
  label: `Remove ~/.verity/ (global credentials \u2014 reconnect requires re-registration)`,
39960
- apply: () => (0, import_node_fs65.rmSync)(globalVerityDir, { recursive: true, force: true })
40045
+ apply: () => (0, import_node_fs66.rmSync)(globalVerityDir, { recursive: true, force: true })
39961
40046
  });
39962
40047
  }
39963
40048
  if (actions.length === 0) {
@@ -40151,8 +40236,8 @@ function registerTaskCommands(program2) {
40151
40236
  }
40152
40237
 
40153
40238
  // src/commands/reset.ts
40154
- var import_node_fs66 = require("node:fs");
40155
- var import_node_path50 = require("node:path");
40239
+ var import_node_fs67 = require("node:fs");
40240
+ var import_node_path51 = require("node:path");
40156
40241
  function registerResetCommand(program2) {
40157
40242
  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) => {
40158
40243
  const globals = program2.opts();
@@ -40189,11 +40274,11 @@ function registerResetCommand(program2) {
40189
40274
  }
40190
40275
  const cacheDir = projectPath(CACHE_DIR);
40191
40276
  let purged = 0;
40192
- if ((0, import_node_fs66.existsSync)(cacheDir)) {
40193
- for (const entry of (0, import_node_fs66.readdirSync)(cacheDir)) {
40277
+ if ((0, import_node_fs67.existsSync)(cacheDir)) {
40278
+ for (const entry of (0, import_node_fs67.readdirSync)(cacheDir)) {
40194
40279
  if (entry.startsWith("pending-")) {
40195
40280
  try {
40196
- (0, import_node_fs66.unlinkSync)((0, import_node_path50.join)(cacheDir, entry));
40281
+ (0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(cacheDir, entry));
40197
40282
  purged++;
40198
40283
  } catch {
40199
40284
  }
@@ -40208,19 +40293,19 @@ function registerResetCommand(program2) {
40208
40293
  projectPath(`${VERITY_DIR}/.last-analysis`)
40209
40294
  ];
40210
40295
  for (const file of filesToClear) {
40211
- if ((0, import_node_fs66.existsSync)(file)) {
40296
+ if ((0, import_node_fs67.existsSync)(file)) {
40212
40297
  try {
40213
- (0, import_node_fs66.writeFileSync)(file, "");
40298
+ (0, import_node_fs67.writeFileSync)(file, "");
40214
40299
  } catch {
40215
40300
  }
40216
40301
  }
40217
40302
  }
40218
40303
  if (opts.all) {
40219
40304
  const logsDir = projectPath(`${VERITY_DIR}/.logs`);
40220
- if ((0, import_node_fs66.existsSync)(logsDir)) {
40221
- for (const entry of (0, import_node_fs66.readdirSync)(logsDir)) {
40305
+ if ((0, import_node_fs67.existsSync)(logsDir)) {
40306
+ for (const entry of (0, import_node_fs67.readdirSync)(logsDir)) {
40222
40307
  try {
40223
- (0, import_node_fs66.unlinkSync)((0, import_node_path50.join)(logsDir, entry));
40308
+ (0, import_node_fs67.unlinkSync)((0, import_node_path51.join)(logsDir, entry));
40224
40309
  } catch {
40225
40310
  }
40226
40311
  }
@@ -40232,7 +40317,7 @@ function registerResetCommand(program2) {
40232
40317
  }
40233
40318
 
40234
40319
  // src/commands/reflect.ts
40235
- var import_node_fs67 = require("node:fs");
40320
+ var import_node_fs68 = require("node:fs");
40236
40321
 
40237
40322
  // src/lib/reflection-globs.ts
40238
40323
  var MAX_GLOBS = 6;
@@ -40270,7 +40355,7 @@ async function writeNodeToDisk(args2) {
40270
40355
  { treePaths: listTrackedFiles(), recordBaseline: false }
40271
40356
  );
40272
40357
  if (written === 0) return false;
40273
- return (0, import_node_fs67.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40358
+ return (0, import_node_fs68.existsSync)(projectPath(`${VERITY_DIR}/memory/${args2.filePath}`));
40274
40359
  } catch {
40275
40360
  return false;
40276
40361
  }
@@ -40702,9 +40787,9 @@ function registerRunCommand(program2) {
40702
40787
  }
40703
40788
 
40704
40789
  // src/commands/telemetry.ts
40705
- var import_node_fs68 = require("node:fs");
40790
+ var import_node_fs69 = require("node:fs");
40706
40791
  async function recordTelemetryChoice(choice) {
40707
- if (!(0, import_node_fs68.existsSync)(projectPath(SETUP_STATE_FILE))) return;
40792
+ if (!(0, import_node_fs69.existsSync)(projectPath(SETUP_STATE_FILE))) return;
40708
40793
  try {
40709
40794
  if ((await readSetupState())?.telemetry === choice) return;
40710
40795
  await writeSetupState({ telemetry: choice });
@@ -40781,8 +40866,8 @@ function registerTelemetryCommands(program2) {
40781
40866
  }
40782
40867
 
40783
40868
  // src/commands/prove.ts
40784
- var import_node_fs69 = require("node:fs");
40785
- var import_node_path51 = require("node:path");
40869
+ var import_node_fs70 = require("node:fs");
40870
+ var import_node_path52 = require("node:path");
40786
40871
 
40787
40872
  // src/lib/prove/hint-pool.ts
40788
40873
  var STOP2 = /* @__PURE__ */ new Set([
@@ -40918,7 +41003,7 @@ function registerProveCommand(program2) {
40918
41003
  process.exit(2);
40919
41004
  }
40920
41005
  const limit = Math.max(1, Math.min(50, Number(opts.limit) || 10));
40921
- let signals = collectRiskSignals(root, { since: opts.since, limit, paths: paths.map((p) => (0, import_node_path51.relative)(root, (0, import_node_path51.resolve)(p)) || ".") });
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)) || ".") });
40922
41007
  if (opts.hint && paths.length === 0) {
40923
41008
  const hit = hintMatches(root, opts.hint);
40924
41009
  if (hit.files.length > 0) {
@@ -40972,7 +41057,7 @@ function registerProveCommand(program2) {
40972
41057
  });
40973
41058
  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) => {
40974
41059
  const root = repoRoot();
40975
- if (!(0, import_node_fs69.existsSync)((0, import_node_path51.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41060
+ if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
40976
41061
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
40977
41062
  process.exit(2);
40978
41063
  }
@@ -40996,7 +41081,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
40996
41081
  const reports = [];
40997
41082
  for (const f of files) {
40998
41083
  const report = checkModel(tc, root, f, { timeoutMs: Math.max(1e3, Number(opts.timeout) || 12e4) });
40999
- report.file = (0, import_node_path51.relative)(root, f);
41084
+ report.file = (0, import_node_path52.relative)(root, f);
41000
41085
  reports.push(report);
41001
41086
  try {
41002
41087
  writeResult(root, report);
@@ -41034,7 +41119,7 @@ ${build.stderr.split("\n").filter((l) => !l.startsWith("trace:")).slice(0, 20).j
41034
41119
  printError("Not logged in \u2014 replays run on the Verity service. Run `verity login` first.");
41035
41120
  process.exit(2);
41036
41121
  }
41037
- if (!(0, import_node_fs69.existsSync)((0, import_node_path51.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41122
+ if (!(0, import_node_fs70.existsSync)((0, import_node_path52.join)(root, PROOFS_DIR, "lakefile.toml"))) {
41038
41123
  printError(`No ${PROOFS_DIR}/ project here. Run \`verity prove init\` first.`);
41039
41124
  process.exit(2);
41040
41125
  }
@@ -41065,7 +41150,7 @@ ${report.error ?? ""}`);
41065
41150
  printInfo(opts.property ? `${model} ${opts.property} has no counterexample to replay` : `${model} has no counterexample to replay`);
41066
41151
  return;
41067
41152
  }
41068
- const modelSource = readRegularFileInRoot(root, (0, import_node_path51.relative)(root, file), 512 * 1024);
41153
+ const modelSource = readRegularFileInRoot(root, (0, import_node_path52.relative)(root, file), 512 * 1024);
41069
41154
  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`);
41070
41155
  const outcomes = await mapPool(targets, REPLAY_CONCURRENCY, async (p) => {
41071
41156
  const brief = buildReplayBrief(root, report, p, modelSource.ok ? modelSource.content : "");
@@ -41085,7 +41170,7 @@ ${report.error ?? ""}`);
41085
41170
  });
41086
41171
  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) => {
41087
41172
  const root = repoRoot();
41088
- let files = paths.map((p) => (0, import_node_path51.relative)(root, (0, import_node_path51.resolve)(p)));
41173
+ let files = paths.map((p) => (0, import_node_path52.relative)(root, (0, import_node_path52.resolve)(p)));
41089
41174
  if (files.length === 0) {
41090
41175
  const ahead = runGitSync(root, ["diff", "--name-only", "@{upstream}...HEAD"]);
41091
41176
  const fallback = ahead.ok ? ahead : runGitSync(root, ["diff", "--name-only", "HEAD~1..HEAD"]);
@@ -41145,7 +41230,7 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41145
41230
  let revise;
41146
41231
  if (opts.revise) {
41147
41232
  const existing = resolveModelFile(root, opts.revise);
41148
- const src = existing ? readRegularFileInRoot(root, (0, import_node_path51.relative)(root, existing), 64 * 1024) : null;
41233
+ const src = existing ? readRegularFileInRoot(root, (0, import_node_path52.relative)(root, existing), 64 * 1024) : null;
41149
41234
  if (!src || !src.ok || !opts.note) {
41150
41235
  printError('--revise needs an existing model under Models/ and --note "<what the replay showed>"');
41151
41236
  process.exit(2);
@@ -41184,8 +41269,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41184
41269
  });
41185
41270
  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) => {
41186
41271
  const root = repoRoot();
41187
- const rel0 = (0, import_node_path51.relative)(root, (0, import_node_path51.isAbsolute)(file) ? file : (0, import_node_path51.join)(root, file)).replace(/\\/g, "/");
41188
- const rel = rel0.startsWith("..") || (0, import_node_path51.isAbsolute)(rel0) ? null : rel0;
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;
41189
41274
  if (!rel) {
41190
41275
  printError(`${file} is not inside this repository`);
41191
41276
  process.exit(2);
@@ -41201,8 +41286,8 @@ ${f.reason ? ` ${terminalText(f.reason, 2e3)}
41201
41286
  });
41202
41287
  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) => {
41203
41288
  const root = repoRoot();
41204
- const rel = (0, import_node_path51.relative)(root, (0, import_node_path51.isAbsolute)(file) ? file : (0, import_node_path51.join)(root, file));
41205
- const digest = rel.startsWith("..") || (0, import_node_path51.isAbsolute)(rel) ? null : sha256InRoot(root, rel);
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);
41206
41291
  if (!digest) {
41207
41292
  printError(`Cannot hash ${file}: it must be a regular file inside this repository (not a symlink)`);
41208
41293
  process.exit(2);
@@ -41236,10 +41321,10 @@ function refreshScaffold(root) {
41236
41321
  }
41237
41322
 
41238
41323
  // src/commands/lean.ts
41239
- var import_node_fs70 = require("node:fs");
41324
+ var import_node_fs71 = require("node:fs");
41240
41325
  var import_node_child_process20 = require("node:child_process");
41241
41326
  var import_node_os11 = require("node:os");
41242
- var import_node_path52 = require("node:path");
41327
+ var import_node_path53 = require("node:path");
41243
41328
  function registerLeanCommand(program2) {
41244
41329
  const lean = program2.command("lean").description("The Lean 4 toolchain formal verification needs (managed download, pinned by this CLI)");
41245
41330
  lean.command("status").option("--json", "Machine-readable output").description("Which toolchain would run, and whether it matches the pinned version").action((opts) => {
@@ -41256,7 +41341,7 @@ function registerLeanCommand(program2) {
41256
41341
  const managed = pinnedVersionDir();
41257
41342
  const matches = version ? version.includes(pin) : false;
41258
41343
  if (opts.json) {
41259
- printJson({ pinned: LEAN_TOOLCHAIN, found: tc?.lake ?? null, version, matches_pin: matches, managed_dir: managed, managed_installed: (0, import_node_fs70.existsSync)((0, import_node_path52.join)(managed, "bin")), asset: leanAssetName() });
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() });
41260
41345
  return;
41261
41346
  }
41262
41347
  printInfo(`pinned: ${LEAN_TOOLCHAIN}`);
@@ -41274,7 +41359,7 @@ function registerLeanCommand(program2) {
41274
41359
  process.exit(2);
41275
41360
  }
41276
41361
  const dir = pinnedVersionDir();
41277
- if ((0, import_node_fs70.existsSync)((0, import_node_path52.join)(dir, "bin", "lake")) && !opts.force) {
41362
+ if ((0, import_node_fs71.existsSync)((0, import_node_path53.join)(dir, "bin", "lake")) && !opts.force) {
41278
41363
  printInfo(`already installed at ${dir}`);
41279
41364
  return;
41280
41365
  }
@@ -41310,18 +41395,18 @@ function registerLeanCommand(program2) {
41310
41395
  });
41311
41396
  lean.command("remove").description("Delete the Verity-managed toolchain for the pinned version").action(() => {
41312
41397
  const dir = pinnedVersionDir();
41313
- if (!(0, import_node_fs70.existsSync)(dir)) {
41398
+ if (!(0, import_node_fs71.existsSync)(dir)) {
41314
41399
  printInfo("nothing to remove");
41315
41400
  return;
41316
41401
  }
41317
- (0, import_node_fs70.rmSync)(dir, { recursive: true, force: true });
41402
+ (0, import_node_fs71.rmSync)(dir, { recursive: true, force: true });
41318
41403
  printInfo(`removed ${dir}`);
41319
41404
  });
41320
41405
  }
41321
41406
 
41322
41407
  // src/cli.ts
41323
- program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.b9e8508").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) => {
41324
- installStderrLog(actionCommand.name(), process.argv.slice(2), "0.34.0-experimental.b9e8508");
41408
+ program.name("verity").description("CLI for Verity quality gate service").version("0.34.0-experimental.cc5f6ec").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.cc5f6ec");
41325
41410
  setUserNamedServiceUrl(program.opts().serviceUrl);
41326
41411
  try {
41327
41412
  await foldLegacyLocalCredential();